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

Add correct support for SFTP V5 access bits #155

Open
wants to merge 2 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
62 changes: 62 additions & 0 deletions lib/net/sftp/protocol/05/attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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 5 and higher 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)
# * :allocation_size:: the actual number of bytes that the item uses on disk (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 array of elements that describe this structure, in order. Used when
# parsing and serializing attribute objects.
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

# Other attributes of this file or directory (as a bit field)
attr_accessor :attrib_bits
end

end; end; end; end
10 changes: 9 additions & 1 deletion lib/net/sftp/protocol/05/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,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
7 changes: 3 additions & 4 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 Expand Up @@ -104,4 +103,4 @@ def self.elements #:nodoc:
attr_accessor :untranslated_name
end

end; end; end; end
end; end; end; end
102 changes: 102 additions & 0 deletions test/protocol/05/test_attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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_from_buffer_should_correctly_parse_buffer_with_attribute_subset_and_return_attribute_object
buffer = Net::SSH::Buffer.from(:long, 0x4, :byte, 1, :long, 0755)

attributes = attributes_factory.from_buffer(buffer)

assert_equal 1, attributes.type
assert_equal 0755, attributes.permissions

assert_nil attributes.size
assert_nil attributes.owner
assert_nil attributes.group
assert_nil attributes.atime
assert_nil attributes.atime_nseconds
assert_nil attributes.createtime
assert_nil attributes.createtime_nseconds
assert_nil attributes.mtime
assert_nil attributes.mtime_nseconds
assert_nil attributes.acl
assert_nil attributes.attrib_bits
assert_nil attributes.extended
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