Class: Net::SFTP::Protocol::V01::Attributes

Inherits:
Object
  • Object
show all
Defined in:
lib/net/sftp/protocol/01/attributes.rb

Overview

A class representing the attributes of a file or directory on the server. It may be used to specify new attributes, or to query existing attributes.

To specify new attributes, just pass a hash as the argument to the constructor. The following keys are supported:

  • :size

    the size of the file

  • :uid

    the user-id that owns the file (integer)

  • :gid

    the group-id that owns the file (integer)

  • :owner

    the name of the user that owns the file (string)

  • :group

    the name of the group that owns the file (string)

  • :permissions

    the permissions on the file (integer, e.g. 0755)

  • :atime

    the access time of the file (integer, seconds since epoch)

  • :mtime

    the modification time of the file (integer, seconds since epoch)

  • :extended

    a hash of name/value pairs identifying extended info

Likewise, when the server sends an Attributes object, all of the above attributes are exposed as methods (though not all will be set with non-nil values from the server).

Direct Known Subclasses

Net::SFTP::Protocol::V04::Attributes

Constant Summary collapse

F_SIZE =
0x00000001
F_UIDGID =
0x00000002
F_PERMISSIONS =
0x00000004
F_ACMODTIME =
0x00000008
F_EXTENDED =
0x80000000
T_REGULAR =
1
T_DIRECTORY =
2
3
T_SPECIAL =
4
T_UNKNOWN =
5
T_SOCKET =
6
T_CHAR_DEVICE =
7
T_BLOCK_DEVICE =
8
T_FIFO =
9

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}) ⇒ Attributes

Create a new Attributes instance with the given attributes. The following keys are supported:

  • :size

    the size of the file

  • :uid

    the user-id that owns the file (integer)

  • :gid

    the group-id that owns the file (integer)

  • :owner

    the name of the user that owns the file (string)

  • :group

    the name of the group that owns the file (string)

  • :permissions

    the permissions on the file (integer, e.g. 0755)

  • :atime

    the access time of the file (integer, seconds since epoch)

  • :mtime

    the modification time of the file (integer, seconds since epoch)

  • :extended

    a hash of name/value pairs identifying extended info



152
153
154
# File 'lib/net/sftp/protocol/01/attributes.rb', line 152

def initialize(attributes={})
  @attributes = attributes
end

Instance Attribute Details

#atimeObject

The last access time of the file



132
133
134
# File 'lib/net/sftp/protocol/01/attributes.rb', line 132

def atime
  @atime
end

#attributesObject (readonly)

The hash of name/value pairs that backs this Attributes instance



117
118
119
# File 'lib/net/sftp/protocol/01/attributes.rb', line 117

def attributes
  @attributes
end

#extendedObject

The hash of name/value pairs identifying extended information about the file



138
139
140
# File 'lib/net/sftp/protocol/01/attributes.rb', line 138

def extended
  @extended
end

#gidObject

Returns the group-id of the group that owns the file, or nil if that information is not available. If a :group key exists, but not a :gid key, the Etc module will be used to reverse lookup the id from the name. This might fail on some systems (e.g., Windows).



172
173
174
175
176
177
178
# File 'lib/net/sftp/protocol/01/attributes.rb', line 172

def gid
  if attributes[:group] && !attributes.key?(:gid)
    require 'etc'
    attributes[:gid] = Etc.getgrnam(attributes[:group]).gid
  end
  attributes[:gid]
end

#mtimeObject

The modification time of the file



135
136
137
# File 'lib/net/sftp/protocol/01/attributes.rb', line 135

def mtime
  @mtime
end

#permissionsObject

The permissions on the file



129
130
131
# File 'lib/net/sftp/protocol/01/attributes.rb', line 129

def permissions
  @permissions
end

#sizeObject

The size of the file.



120
121
122
# File 'lib/net/sftp/protocol/01/attributes.rb', line 120

def size
  @size
end

#uidObject

Returns the user-id of the user that owns the file, or nil if that information is not available. If an :owner key exists, but not a :uid key, the Etc module will be used to reverse lookup the id from the name. This might fail on some systems (e.g., Windows).



160
161
162
163
164
165
166
# File 'lib/net/sftp/protocol/01/attributes.rb', line 160

def uid
  if attributes[:owner] && !attributes.key?(:uid)
    require 'etc'
    attributes[:uid] = Etc.getpwnam(attributes[:owner]).uid
  end
  attributes[:uid]
end

Class Method Details

.attr_accessor(name) ⇒ Object

A convenience method for defining methods that expose specific attributes. This redefines the standard attr_accessor (an admittedly bad practice) because (1) I don’t need any “regular” accessors, and (2) because rdoc will automatically pick up and note methods defined via attr_accessor.



81
82
83
84
85
86
87
88
89
# File 'lib/net/sftp/protocol/01/attributes.rb', line 81

def attr_accessor(name) #:nodoc:
  class_eval <<-CODE
    def #{name}
      attributes[:#{name}]
    end
  CODE

  attr_writer(name)
end

.attr_writer(name) ⇒ Object

A convenience method for defining methods that expose specific attributes. This redefines the standard attr_writer (an admittedly bad practice) because (1) I don’t need any “regular” accessors, and (2) because rdoc will automatically pick up and note methods defined via attr_writer.



96
97
98
99
100
101
102
# File 'lib/net/sftp/protocol/01/attributes.rb', line 96

def attr_writer(name) #:nodoc:
  class_eval <<-CODE
    def #{name}=(value)
      attributes[:#{name}] = value
    end
  CODE
end

.elementsObject

Returns the array of attribute meta-data that defines the structure of the attributes packet as described by this version of the protocol.



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/net/sftp/protocol/01/attributes.rb', line 45

def elements #:nodoc:
  @elements ||= [
    [:size,                :int64,   F_SIZE],
    [:uid,                 :long,    F_UIDGID],
    [:gid,                 :long,    F_UIDGID],
    [:permissions,         :long,    F_PERMISSIONS],
    [:atime,               :long,    F_ACMODTIME],
    [:mtime,               :long,    F_ACMODTIME],
    [:extended,            :special, F_EXTENDED]
  ]
end

.from_buffer(buffer) ⇒ Object

Parses the given buffer and returns an Attributes object compsed from the data extracted from it.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/net/sftp/protocol/01/attributes.rb', line 59

def from_buffer(buffer)
  flags = buffer.read_long
  data = {}

  elements.each do |name, type, condition|
    if flags & condition == condition
      if type == :special
        data[name] = send("parse_#{name}", buffer)
      else
        data[name] = buffer.send("read_#{type}")
      end
    end
  end

  new(data)
end

Instance Method Details

#directory?Boolean

Returns true if these attributes appear to describe a directory.

Returns:

  • (Boolean)


244
245
246
247
248
249
250
# File 'lib/net/sftp/protocol/01/attributes.rb', line 244

def directory?
  case type
  when T_DIRECTORY then true
  when T_UNKNOWN   then nil
  else false
  end
end

#file?Boolean

Returns true if these attributes appear to describe a regular file.

Returns:

  • (Boolean)


262
263
264
265
266
267
268
# File 'lib/net/sftp/protocol/01/attributes.rb', line 262

def file?
  case type
  when T_REGULAR then true
  when T_UNKNOWN then nil
  else false
  end
end

#groupObject

Returns the group name of the group that owns the file, or nil if that information is not available. If the :gid is given, but not the :group, the Etc module will be used to lookup the name from the id. This might fail on some systems (e.g. Windows).



196
197
198
199
200
201
202
# File 'lib/net/sftp/protocol/01/attributes.rb', line 196

def group
  if attributes[:gid] && !attributes[:group]
    require 'etc'
    attributes[:group] = Etc.getgrgid(attributes[:gid].to_i).name
  end
  attributes[:group]
end

#ownerObject

Returns the username of the user that owns the file, or nil if that information is not available. If the :uid is given, but not the :owner, the Etc module will be used to lookup the name from the id. This might fail on some systems (e.g. Windows).



184
185
186
187
188
189
190
# File 'lib/net/sftp/protocol/01/attributes.rb', line 184

def owner
  if attributes[:uid] && !attributes[:owner]
    require 'etc'
    attributes[:owner] = Etc.getpwuid(attributes[:uid].to_i).name
  end
  attributes[:owner]
end

#symbolic_typeObject

Returns the type as a symbol, rather than an integer, for easier use in Ruby programs.



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/net/sftp/protocol/01/attributes.rb', line 228

def symbolic_type
  case type
  when T_SOCKET       then :socket
  when T_SYMLINK      then :symlink
  when T_REGULAR      then :regular
  when T_BLOCK_DEVICE then :block_device
  when T_DIRECTORY    then :directory
  when T_CHAR_DEVICE  then :char_device
  when T_FIFO         then :fifo
  when T_SPECIAL      then :special
  when T_UNKNOWN      then :unknown
  else raise NotImplementedError, "unknown file type #{type} (bug?)"
  end
end

#symlink?Boolean

Returns true if these attributes appear to describe a symlink.

Returns:

  • (Boolean)


253
254
255
256
257
258
259
# File 'lib/net/sftp/protocol/01/attributes.rb', line 253

def symlink?
  case type
  when T_SYMLINK then true
  when T_UNKNOWN then nil
  else false
  end
end

#to_sObject

Convert the object to a string suitable for passing in an SFTP packet. This is the raw representation of the attribute packet payload, and is not intended to be human readable.



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/net/sftp/protocol/01/attributes.rb', line 273

def to_s
  prepare_serialization!

  flags = 0

  self.class.elements.each do |name, type, condition|
    flags |= condition if attributes[name]
  end

  buffer = Net::SSH::Buffer.from(:long, flags)
  self.class.elements.each do |name, type, condition|
    if flags & condition == condition
      if type == :special
        send("encode_#{name}", buffer)
      else
        buffer.send("write_#{type}", attributes[name])
      end
    end
  end

  buffer.to_s
end

#typeObject

Inspects the permissions bits to determine what type of entity this attributes object represents. If will return one of the T_ constants.



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/net/sftp/protocol/01/attributes.rb', line 206

def type
  if    permissions & 0140000 == 0140000 then 
    T_SOCKET
  elsif permissions & 0120000 == 0120000 then 
    T_SYMLINK
  elsif permissions & 0100000 == 0100000 then
    T_REGULAR
  elsif permissions &  060000 ==  060000 then
    T_BLOCK_DEVICE
  elsif permissions &  040000 ==  040000 then
    T_DIRECTORY
  elsif permissions &  020000 ==  020000 then
    T_CHAR_DEVICE
  elsif permissions &  010000 ==  010000 then
    T_FIFO
  else
    T_UNKNOWN
  end
end