Version 4 of the SFTP protocol made some pretty significant alterations to the File Attributes data type. This encapsulates those changes.

Methods
Constants
F_SIZE = 0x00000001
F_PERMISSIONS = 0x00000004
F_ACCESSTIME = 0x00000008
F_CREATETIME = 0x00000010
F_MODIFYTIME = 0x00000020
F_ACL = 0x00000040
F_OWNERGROUP = 0x00000080
F_SUBSECOND_TIMES = 0x00000100
F_EXTENDED = 0x80000000
ACL = Struct.new( :type, :flag, :mask, :who )
T_REGULAR = 1
T_DIRECTORY = 2
T_SYMLINK = 3
T_SPECIAL = 4
T_UNKNOWN = 5
T_SOCKET = 6
T_CHAR_DEVICE = 7
T_BLOCK_DEVICE = 8
T_FIFO = 9
Attributes
[RW] acl
[RW] atime
[RW] atime_nseconds
[RW] ctime
[RW] ctime_nseconds
[RW] extended
[RW] group
[RW] mtime
[RW] mtime_nseconds
[RW] owner
[RW] permissions
[RW] size
[RW] type
Public Class methods
buffers()

Return a reference to the buffer factory in use by this class.

    # File lib/net/sftp/protocol/04/attributes.rb, line 57
57:     def self.buffers
58:       @buffers
59:     end
empty()

Return an empty Attributes instance.

    # File lib/net/sftp/protocol/04/attributes.rb, line 68
68:     def self.empty
69:       new
70:     end
from_buffer( buffer )

Return an Attributes instance initialized from the given buffer.

     # File lib/net/sftp/protocol/04/attributes.rb, line 73
 73:     def self.from_buffer( buffer )
 74:       flags = buffer.read_long
 75: 
 76:       type = buffer.read_byte
 77:       size = buffer.read_int64 if ( flags & F_SIZE ) != 0
 78:       owner = buffer.read_string if ( flags & F_OWNERGROUP ) != 0
 79:       group = buffer.read_string if ( flags & F_OWNERGROUP ) != 0
 80:       permissions = buffer.read_long if ( flags & F_PERMISSIONS ) != 0
 81:       if ( flags & F_ACCESSTIME ) != 0
 82:         atime = buffer.read_int64
 83:         atime_nseconds = buffer.read_long if ( flags & F_SUBSECOND_TIMES ) != 0
 84:       end
 85:       if ( flags & F_CREATETIME ) != 0
 86:         ctime = buffer.read_int64
 87:         ctime_nseconds = buffer.read_long if ( flags & F_SUBSECOND_TIMES ) != 0
 88:       end
 89:       if ( flags & F_MODIFYTIME ) != 0
 90:         mtime = buffer.read_int64
 91:         mtime_nseconds = buffer.read_long if ( flags & F_SUBSECOND_TIMES ) != 0
 92:       end
 93:       if ( flags & F_ACL ) != 0
 94:         acl_buf = buffers.reader( buffer.read_string )
 95:         acl = []
 96:         acl_buf.read_long.times do
 97:           acl << ACL.new( acl_buf.read_long,
 98:                           acl_buf.read_long,
 99:                           acl_buf.read_long,
100:                           acl_buf.read_string )
101:         end
102:       end
103: 
104:       if ( flags & F_EXTENDED ) != 0
105:         extended = Hash.new
106:         buffer.read_long.times do
107:           extended[ buffer.read_string ] = buffer.read_string
108:         end
109:       end
110: 
111:       new( type, size, owner, group, permissions, atime, atime_nseconds,
112:         ctime, ctime_nseconds, mtime, mtime_nseconds, acl, extended )
113:     end
from_hash( hash )

Create a new attributes object, initialized from the given hash. The :uid and :gid attributes are treated specially; they are not actually supported by this version of the protocol, but are instead converted by this method to their corresponding names, and assigned (respectively) to :owner and :group.

     # File lib/net/sftp/protocol/04/attributes.rb, line 120
120:     def self.from_hash( hash )
121:       if hash.has_key?(:uid)
122:         require 'etc'
123:         hash[:owner] = Etc.getpwuid( hash[:uid] ).name
124:       end
125: 
126:       if hash.has_key?(:gid)
127:         require 'etc'
128:         hash[:group] = Etc.getgrgid( hash[:gid] ).name
129:       end
130: 
131:       new hash[:type] || T_REGULAR, hash[:size], hash[:owner], hash[:group],
132:         hash[:permissions], hash[:atime], hash[:atime_nseconds],
133:         hash[:ctime], hash[:ctime_nseconds], hash[:mtime],
134:         hash[:mtime_nseconds], hash[:acl], hash[:extended]
135:     end
init( buffers )

An initializer for specifying the buffer factory that should be used by instances of this class.

    # File lib/net/sftp/protocol/04/attributes.rb, line 51
51:     def self.init( buffers )
52:       @buffers = buffers
53:       self
54:     end
new( type=T_REGULAR, size=nil, owner=nil, group=nil, permissions=nil, atime=nil, atime_nseconds=nil, ctime=nil, ctime_nseconds=nil, mtime=nil, mtime_nseconds=nil, acl=nil, extended=nil )

Create a new Attributes instance with the given values.

     # File lib/net/sftp/protocol/04/attributes.rb, line 150
150:     def initialize( type=T_REGULAR, size=nil, owner=nil, group=nil,
151:       permissions=nil, atime=nil, atime_nseconds=nil, ctime=nil,
152:       ctime_nseconds=nil, mtime=nil, mtime_nseconds=nil, acl=nil,
153:       extended=nil )
154:     # begin
155:       @type = type
156:       @size = size
157:       @owner = owner
158:       @group = group
159:       @permissions = permissions
160:       @atime = atime
161:       @atime_nseconds = atime_nseconds
162:       @ctime = ctime
163:       @ctime_nseconds = ctime_nseconds
164:       @mtime = mtime
165:       @mtime_nseconds = mtime_nseconds
166:       @acl = acl
167:       @extended = extended
168:     end
Public Instance methods
buffers()

A convenience for obtaining a reference to the buffer factory used by this instance’s class.

    # File lib/net/sftp/protocol/04/attributes.rb, line 63
63:     def buffers
64:       self.class.buffers
65:     end
to_s()

Convert this object to a string, suitable for inclusion in an SFTP packet (protocol version 4+).

     # File lib/net/sftp/protocol/04/attributes.rb, line 172
172:     def to_s
173:       flags = 0
174: 
175:       flags |= F_SIZE if @size
176:       flags |= F_OWNERGROUP if @owner && @group
177:       flags |= F_PERMISSIONS if @permissions
178:       flags |= F_ACCESSTIME if @atime
179:       flags |= F_CREATETIME if @ctime
180:       flags |= F_MODIFYTIME if @mtime
181:       if @atime_nseconds && @ctime_nseconds && @mtime_nseconds
182:         flags |= F_SUBSECOND_TIMES
183:       end
184:       flags |= F_ACL if @acl
185:       flags |= F_EXTENDED if @extended
186: 
187:       buffer = buffers.writer
188:       buffer.write_long flags
189:       buffer.write_byte @type
190:       buffer.write_int64 @size if @size
191:       buffer.write_string @owner, @group if @owner && @group
192:       buffer.write_long @permissions if @permissions
193: 
194:       if @atime
195:         buffer.write_int64 @atime
196:         buffer.write_long @atime_nseconds if ( flags & F_SUBSECOND_TIMES != 0 )
197:       end
198:       if @ctime
199:         buffer.write_int64 @ctime
200:         buffer.write_long @ctime_nseconds if ( flags & F_SUBSECOND_TIMES != 0 )
201:       end
202:       if @mtime
203:         buffer.write_int64 @mtime
204:         buffer.write_long @mtime_nseconds if ( flags & F_SUBSECOND_TIMES != 0 )
205:       end
206: 
207:       if @acl
208:         acl_buf = buffers.writer
209:         acl_buf.write_long @acl.length
210:         @acl.each do |item|
211:           acl_buf.write_long item.type, item.flag, item.mask
212:           acl_buf.write_string item.who
213:         end
214:         buffer.write_string acl_buf.to_s
215:       end
216: 
217:       if @extended
218:         buffer.write_long @extended.length
219:         @extended.each { |k,v| buffer.write_string k, v }
220:       end
221: 
222:       buffer.to_s
223:     end