Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse attrib-bits field when its included in file attributes #139

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions lib/net/sftp/protocol/05/attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require 'net/sftp/protocol/04/attributes'

module Net; module SFTP; module Protocol; module V05

# 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.
# This particular class is specific to versions 4 and 5 of the SFTP
# protocol.
#
# To specify new attributes, just pass a hash as the argument to the
# constructor. The following keys are supported:
#
# * :type:: the type of the item (integer, one of the T_ constants)
# * :size:: the size of the item (integer)
# * :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)
# * :atime_nseconds:: the nanosecond component of atime (integer)
# * :createtime:: the time at which the file was created (integer, seconds since epoch)
# * :createtime_nseconds:: the nanosecond component of createtime (integer)
# * :mtime:: the modification time of the file (integer, seconds since epoch)
# * :mtime_nseconds:: the nanosecond component of mtime (integer)
# * :acl:: an array of ACL entries for the item
# * :attrib_bits:: other attributes of the file or directory (as a bit field) (integer)
# * :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).
class Attributes < V04::Attributes
F_BITS = 0x00000200

# The list of supported elements in the attributes structure as defined
# by v5 of the sftp protocol.
def self.elements #:nodoc:
@elements ||= [
[:type, :byte, 0],
[:size, :int64, F_SIZE],
[:owner, :string, F_OWNERGROUP],
[:group, :string, F_OWNERGROUP],
[:permissions, :long, F_PERMISSIONS],
[:atime, :int64, F_ACCESSTIME],
[:atime_nseconds, :long, F_ACCESSTIME | F_SUBSECOND_TIMES],
[:createtime, :int64, F_CREATETIME],
[:createtime_nseconds, :long, F_CREATETIME | F_SUBSECOND_TIMES],
[:mtime, :int64, F_MODIFYTIME],
[:mtime_nseconds, :long, F_MODIFYTIME | F_SUBSECOND_TIMES],
[:acl, :special, F_ACL],
[:attrib_bits, :long, F_BITS],
[:extended, :special, F_EXTENDED]
]
end

# The type of the item on the remote server. Must be one of the T_* constants.
attr_accessor :attrib_bits
end

end ; end ; end ; end
11 changes: 10 additions & 1 deletion lib/net/sftp/protocol/05/base.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'net/sftp/protocol/04/base'
require 'net/sftp/protocol/05/attributes'

module Net; module SFTP; module Protocol; module V05

Expand Down Expand Up @@ -61,6 +62,14 @@ def open(path, flags, options)
send_request(FXP_OPEN, :string, path, :long, desired_access, :long, sftp_flags, :raw, attributes.to_s)
end

protected

# Returns the Attributes class used by this version of the protocol
# (Net::SFTP::Protocol::V05::Attributes, in this case)
def attribute_factory
V05::Attributes
end

end

end; end; end; end
end; end; end; end
5 changes: 2 additions & 3 deletions lib/net/sftp/protocol/06/attributes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'net/sftp/protocol/04/attributes'
require 'net/sftp/protocol/05/attributes'

module Net; module SFTP; module Protocol; module V06

Expand Down Expand Up @@ -38,8 +38,7 @@ module Net; module SFTP; module Protocol; module V06
# 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).
class Attributes < V04::Attributes
F_BITS = 0x00000200
class Attributes < V05::Attributes
F_ALLOCATION_SIZE = 0x00000400
F_TEXT_HINT = 0x00000800
F_MIME_TYPE = 0x00001000
Expand Down
80 changes: 80 additions & 0 deletions test/protocol/05/test_attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
require 'common'

module Etc; end

class Protocol::V05::TestAttributes < Net::SFTP::TestCase
def test_from_buffer_should_correctly_parse_buffer_and_return_attribute_object
attributes = attributes_factory.from_buffer(full_buffer)

assert_equal 9, attributes.type
assert_equal 1234567890, attributes.size
assert_equal "jamis", attributes.owner
assert_equal "users", attributes.group
assert_equal 0755, attributes.permissions
assert_equal 1234567890, attributes.atime
assert_equal 12345, attributes.atime_nseconds
assert_equal 2345678901, attributes.createtime
assert_equal 23456, attributes.createtime_nseconds
assert_equal 3456789012, attributes.mtime
assert_equal 34567, attributes.mtime_nseconds

assert_equal 2, attributes.acl.length

assert_equal 1, attributes.acl.first.type
assert_equal 2, attributes.acl.first.flag
assert_equal 3, attributes.acl.first.mask
assert_equal "foo", attributes.acl.first.who

assert_equal 4, attributes.acl.last.type
assert_equal 5, attributes.acl.last.flag
assert_equal 6, attributes.acl.last.mask
assert_equal "bar", attributes.acl.last.who

assert_equal 0x12341234, attributes.attrib_bits

assert_equal "second", attributes.extended["first"]
end

def test_attributes_to_s_should_build_binary_representation
attributes = attributes_factory.new(
:type => 9,
:size => 1234567890,
:owner => "jamis", :group => "users",
:permissions => 0755,
:atime => 1234567890, :atime_nseconds => 12345,
:createtime => 2345678901, :createtime_nseconds => 23456,
:mtime => 3456789012, :mtime_nseconds => 34567,
:acl => [attributes_factory::ACL.new(1,2,3,"foo"),
attributes_factory::ACL.new(4,5,6,"bar")],
:attrib_bits => 0x12341234,
:extended => { "first" => "second" })

assert_equal full_buffer.to_s, attributes.to_s
end

def test_attributes_to_s_should_build_binary_representation_when_subset_is_present
attributes = attributes_factory.new(:permissions => 0755)
assert_equal Net::SSH::Buffer.from(:long, 0x4, :byte, 1, :long, 0755).to_s, attributes.to_s
end

private

def full_buffer
Net::SSH::Buffer.from(:long, 0x800003fd,
:byte, 9, :int64, 1234567890,
:string, "jamis", :string, "users",
:long, 0755,
:int64, 1234567890, :long, 12345,
:int64, 2345678901, :long, 23456,
:int64, 3456789012, :long, 34567,
:string, raw(:long, 2,
:long, 1, :long, 2, :long, 3, :string, "foo",
:long, 4, :long, 5, :long, 6, :string, "bar"),
:long, 0x12341234,
:long, 1, :string, "first", :string, "second")
end

def attributes_factory
Net::SFTP::Protocol::V05::Attributes
end
end