net-sftp 1.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +23 -0
- data/Manifest +55 -0
- data/README.rdoc +96 -0
- data/Rakefile +30 -0
- data/lib/net/sftp.rb +53 -38
- data/lib/net/sftp/constants.rb +187 -0
- data/lib/net/sftp/errors.rb +34 -20
- data/lib/net/sftp/operations/dir.rb +93 -0
- data/lib/net/sftp/operations/download.rb +364 -0
- data/lib/net/sftp/operations/file.rb +176 -0
- data/lib/net/sftp/operations/file_factory.rb +60 -0
- data/lib/net/sftp/operations/upload.rb +387 -0
- data/lib/net/sftp/packet.rb +21 -0
- data/lib/net/sftp/protocol.rb +32 -0
- data/lib/net/sftp/protocol/01/attributes.rb +265 -96
- data/lib/net/sftp/protocol/01/base.rb +268 -0
- data/lib/net/sftp/protocol/01/name.rb +43 -0
- data/lib/net/sftp/protocol/02/base.rb +31 -0
- data/lib/net/sftp/protocol/03/base.rb +35 -0
- data/lib/net/sftp/protocol/04/attributes.rb +120 -195
- data/lib/net/sftp/protocol/04/base.rb +94 -0
- data/lib/net/sftp/protocol/04/name.rb +67 -0
- data/lib/net/sftp/protocol/05/base.rb +66 -0
- data/lib/net/sftp/protocol/06/attributes.rb +107 -0
- data/lib/net/sftp/protocol/06/base.rb +63 -0
- data/lib/net/sftp/protocol/base.rb +50 -0
- data/lib/net/sftp/request.rb +91 -0
- data/lib/net/sftp/response.rb +76 -0
- data/lib/net/sftp/session.rb +914 -238
- data/lib/net/sftp/version.rb +14 -21
- data/net-sftp.gemspec +60 -0
- data/setup.rb +1331 -0
- data/test/common.rb +173 -0
- data/test/protocol/01/test_attributes.rb +97 -0
- data/test/protocol/01/test_base.rb +210 -0
- data/test/protocol/01/test_name.rb +27 -0
- data/test/protocol/02/test_base.rb +26 -0
- data/test/protocol/03/test_base.rb +27 -0
- data/test/protocol/04/test_attributes.rb +148 -0
- data/test/protocol/04/test_base.rb +74 -0
- data/test/protocol/04/test_name.rb +49 -0
- data/test/protocol/05/test_base.rb +62 -0
- data/test/protocol/06/test_attributes.rb +124 -0
- data/test/protocol/06/test_base.rb +51 -0
- data/test/protocol/test_base.rb +42 -0
- data/test/test_all.rb +3 -0
- data/test/test_dir.rb +47 -0
- data/test/test_download.rb +252 -0
- data/test/test_file.rb +159 -0
- data/test/test_file_factory.rb +48 -0
- data/test/test_packet.rb +9 -0
- data/test/test_protocol.rb +17 -0
- data/test/test_request.rb +71 -0
- data/test/test_response.rb +53 -0
- data/test/test_session.rb +741 -0
- data/test/test_upload.rb +219 -0
- metadata +59 -111
- data/doc/LICENSE-BSD +0 -27
- data/doc/LICENSE-GPL +0 -280
- data/doc/LICENSE-RUBY +0 -56
- data/doc/faq/faq.html +0 -298
- data/doc/faq/faq.rb +0 -154
- data/doc/faq/faq.yml +0 -183
- data/examples/asynchronous.rb +0 -57
- data/examples/get-put.rb +0 -45
- data/examples/sftp-open-uri.rb +0 -30
- data/examples/ssh-service.rb +0 -30
- data/examples/synchronous.rb +0 -131
- data/lib/net/sftp/operations/abstract.rb +0 -108
- data/lib/net/sftp/operations/close.rb +0 -31
- data/lib/net/sftp/operations/errors.rb +0 -76
- data/lib/net/sftp/operations/fsetstat.rb +0 -36
- data/lib/net/sftp/operations/fstat.rb +0 -32
- data/lib/net/sftp/operations/lstat.rb +0 -31
- data/lib/net/sftp/operations/mkdir.rb +0 -33
- data/lib/net/sftp/operations/open.rb +0 -32
- data/lib/net/sftp/operations/opendir.rb +0 -32
- data/lib/net/sftp/operations/read.rb +0 -88
- data/lib/net/sftp/operations/readdir.rb +0 -55
- data/lib/net/sftp/operations/realpath.rb +0 -37
- data/lib/net/sftp/operations/remove.rb +0 -31
- data/lib/net/sftp/operations/rename.rb +0 -32
- data/lib/net/sftp/operations/rmdir.rb +0 -31
- data/lib/net/sftp/operations/services.rb +0 -42
- data/lib/net/sftp/operations/setstat.rb +0 -33
- data/lib/net/sftp/operations/stat.rb +0 -31
- data/lib/net/sftp/operations/write.rb +0 -63
- data/lib/net/sftp/protocol/01/impl.rb +0 -251
- data/lib/net/sftp/protocol/01/packet-assistant.rb +0 -82
- data/lib/net/sftp/protocol/01/services.rb +0 -47
- data/lib/net/sftp/protocol/02/impl.rb +0 -39
- data/lib/net/sftp/protocol/02/packet-assistant.rb +0 -32
- data/lib/net/sftp/protocol/02/services.rb +0 -44
- data/lib/net/sftp/protocol/03/impl.rb +0 -42
- data/lib/net/sftp/protocol/03/packet-assistant.rb +0 -35
- data/lib/net/sftp/protocol/03/services.rb +0 -44
- data/lib/net/sftp/protocol/04/impl.rb +0 -86
- data/lib/net/sftp/protocol/04/packet-assistant.rb +0 -45
- data/lib/net/sftp/protocol/04/services.rb +0 -44
- data/lib/net/sftp/protocol/05/impl.rb +0 -90
- data/lib/net/sftp/protocol/05/packet-assistant.rb +0 -34
- data/lib/net/sftp/protocol/05/services.rb +0 -44
- data/lib/net/sftp/protocol/constants.rb +0 -60
- data/lib/net/sftp/protocol/driver.rb +0 -235
- data/lib/net/sftp/protocol/packet-assistant.rb +0 -84
- data/lib/net/sftp/protocol/services.rb +0 -55
- data/lib/uri/open-sftp.rb +0 -54
- data/lib/uri/sftp.rb +0 -42
- data/test/ALL-TESTS.rb +0 -23
- data/test/operations/tc_abstract.rb +0 -124
- data/test/operations/tc_close.rb +0 -40
- data/test/operations/tc_fsetstat.rb +0 -48
- data/test/operations/tc_fstat.rb +0 -40
- data/test/operations/tc_lstat.rb +0 -40
- data/test/operations/tc_mkdir.rb +0 -48
- data/test/operations/tc_open.rb +0 -42
- data/test/operations/tc_opendir.rb +0 -40
- data/test/operations/tc_read.rb +0 -103
- data/test/operations/tc_readdir.rb +0 -88
- data/test/operations/tc_realpath.rb +0 -54
- data/test/operations/tc_remove.rb +0 -40
- data/test/operations/tc_rmdir.rb +0 -40
- data/test/operations/tc_setstat.rb +0 -48
- data/test/operations/tc_stat.rb +0 -40
- data/test/operations/tc_write.rb +0 -91
- data/test/protocol/01/tc_attributes.rb +0 -138
- data/test/protocol/01/tc_impl.rb +0 -294
- data/test/protocol/01/tc_packet_assistant.rb +0 -81
- data/test/protocol/02/tc_impl.rb +0 -41
- data/test/protocol/02/tc_packet_assistant.rb +0 -31
- data/test/protocol/03/tc_impl.rb +0 -48
- data/test/protocol/03/tc_packet_assistant.rb +0 -34
- data/test/protocol/04/tc_attributes.rb +0 -174
- data/test/protocol/04/tc_impl.rb +0 -91
- data/test/protocol/04/tc_packet_assistant.rb +0 -38
- data/test/protocol/05/tc_impl.rb +0 -61
- data/test/protocol/05/tc_packet_assistant.rb +0 -32
- data/test/protocol/tc_driver.rb +0 -219
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'net/sftp/protocol/03/base'
|
2
|
+
require 'net/sftp/protocol/04/attributes'
|
3
|
+
require 'net/sftp/protocol/04/name'
|
4
|
+
|
5
|
+
module Net; module SFTP; module Protocol; module V04
|
6
|
+
|
7
|
+
# Wraps the low-level SFTP calls for version 4 of the SFTP protocol. Also
|
8
|
+
# implements the updated FXP_NAME packet parsing as mandated by v4 of the
|
9
|
+
# protocol.
|
10
|
+
#
|
11
|
+
# None of these protocol methods block--all of them return immediately,
|
12
|
+
# requiring the SSH event loop to be run while the server response is
|
13
|
+
# pending.
|
14
|
+
#
|
15
|
+
# You will almost certainly never need to use this driver directly. Please
|
16
|
+
# see Net::SFTP::Session for the recommended interface.
|
17
|
+
class Base < V03::Base
|
18
|
+
|
19
|
+
# Returns the protocol version implemented by this driver. (4, in this
|
20
|
+
# case)
|
21
|
+
def version
|
22
|
+
4
|
23
|
+
end
|
24
|
+
|
25
|
+
# As of v4 of the SFTP protocol, the "longname" member was removed from the
|
26
|
+
# FXP_NAME structure. This method is essentially the same as the previous
|
27
|
+
# implementation, but omits longname.
|
28
|
+
def parse_name_packet(packet)
|
29
|
+
names = []
|
30
|
+
|
31
|
+
packet.read_long.times do
|
32
|
+
filename = packet.read_string
|
33
|
+
attrs = attribute_factory.from_buffer(packet)
|
34
|
+
names << name_factory.new(filename, attrs)
|
35
|
+
end
|
36
|
+
|
37
|
+
{ :names => names }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Sends a FXP_STAT packet to the server for the given +path+, and with the
|
41
|
+
# given +flags+. If +flags+ is nil, it defaults to F_SIZE | F_PERMISSIONS |
|
42
|
+
# F_ACCESSTIME | F_CREATETIME | F_MODIFYTIME | F_ACL | F_OWNERGROUP |
|
43
|
+
# F_SUBSECOND_TIMES | F_EXTENDED (see Net::SFTP::Protocol::V04::Attributes
|
44
|
+
# for those constants).
|
45
|
+
def stat(path, flags=nil)
|
46
|
+
send_request(FXP_STAT, :string, path, :long, flags || DEFAULT_FLAGS)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sends a FXP_LSTAT packet to the server for the given +path+, and with the
|
50
|
+
# given +flags+. If +flags+ is nil, it defaults to F_SIZE | F_PERMISSIONS |
|
51
|
+
# F_ACCESSTIME | F_CREATETIME | F_MODIFYTIME | F_ACL | F_OWNERGROUP |
|
52
|
+
# F_SUBSECOND_TIMES | F_EXTENDED (see Net::SFTP::Protocol::V04::Attributes
|
53
|
+
# for those constants).
|
54
|
+
def lstat(path, flags=nil)
|
55
|
+
send_request(FXP_LSTAT, :string, path, :long, flags || DEFAULT_FLAGS)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sends a FXP_FSTAT packet to the server for the given +path+, and with the
|
59
|
+
# given +flags+. If +flags+ is nil, it defaults to F_SIZE | F_PERMISSIONS |
|
60
|
+
# F_ACCESSTIME | F_CREATETIME | F_MODIFYTIME | F_ACL | F_OWNERGROUP |
|
61
|
+
# F_SUBSECOND_TIMES | F_EXTENDED (see Net::SFTP::Protocol::V04::Attributes
|
62
|
+
# for those constants).
|
63
|
+
def fstat(handle, flags=nil)
|
64
|
+
send_request(FXP_FSTAT, :string, handle, :long, flags || DEFAULT_FLAGS)
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
# The default flags used if the +flags+ parameter is nil for any of the
|
70
|
+
# #stat, #lstat, or #fstat operations.
|
71
|
+
DEFAULT_FLAGS = Attributes::F_SIZE |
|
72
|
+
Attributes::F_PERMISSIONS |
|
73
|
+
Attributes::F_ACCESSTIME |
|
74
|
+
Attributes::F_CREATETIME |
|
75
|
+
Attributes::F_MODIFYTIME |
|
76
|
+
Attributes::F_ACL |
|
77
|
+
Attributes::F_OWNERGROUP |
|
78
|
+
Attributes::F_SUBSECOND_TIMES |
|
79
|
+
Attributes::F_EXTENDED
|
80
|
+
|
81
|
+
# Returns the Attributes class used by this version of the protocol
|
82
|
+
# (Net::SFTP::Protocol::V04::Attributes, in this case)
|
83
|
+
def attribute_factory
|
84
|
+
V04::Attributes
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the Name class used by this version of the protocol
|
88
|
+
# (Net::SFTP::Protocol::V04::Name, in this case)
|
89
|
+
def name_factory
|
90
|
+
V04::Name
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end; end; end; end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Net; module SFTP; module Protocol; module V04
|
2
|
+
|
3
|
+
# Represents a single named item on the remote server. This includes the
|
4
|
+
# name, and attributes about the item, and the "longname".
|
5
|
+
#
|
6
|
+
# For backwards compatibility with the format and interface of the Name
|
7
|
+
# structure from previous protocol versions, this also exposes a #longname
|
8
|
+
# method, which returns a string that can be used to display this item in
|
9
|
+
# a directory listing.
|
10
|
+
class Name
|
11
|
+
# The name of the item on the remote server.
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# Attributes instance describing this item.
|
15
|
+
attr_reader :attributes
|
16
|
+
|
17
|
+
# Create a new Name object with the given name and attributes.
|
18
|
+
def initialize(name, attributes)
|
19
|
+
@name, @attributes = name, attributes
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns +true+ if the item is a directory.
|
23
|
+
def directory?
|
24
|
+
attributes.directory?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns +true+ if the item is a symlink.
|
28
|
+
def symlink?
|
29
|
+
attributes.symlink?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns +true+ if the item is a regular file.
|
33
|
+
def file?
|
34
|
+
attributes.file?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a string representing this file, in a format similar to that
|
38
|
+
# used by the unix "ls" utility.
|
39
|
+
def longname
|
40
|
+
@longname ||= begin
|
41
|
+
longname = if directory?
|
42
|
+
"d"
|
43
|
+
elsif symlink?
|
44
|
+
"l"
|
45
|
+
else
|
46
|
+
"-"
|
47
|
+
end
|
48
|
+
|
49
|
+
longname << (attributes.permissions & 0400 != 0 ? "r" : "-")
|
50
|
+
longname << (attributes.permissions & 0200 != 0 ? "w" : "-")
|
51
|
+
longname << (attributes.permissions & 0100 != 0 ? "x" : "-")
|
52
|
+
longname << (attributes.permissions & 0040 != 0 ? "r" : "-")
|
53
|
+
longname << (attributes.permissions & 0020 != 0 ? "w" : "-")
|
54
|
+
longname << (attributes.permissions & 0010 != 0 ? "x" : "-")
|
55
|
+
longname << (attributes.permissions & 0004 != 0 ? "r" : "-")
|
56
|
+
longname << (attributes.permissions & 0002 != 0 ? "w" : "-")
|
57
|
+
longname << (attributes.permissions & 0001 != 0 ? "x" : "-")
|
58
|
+
|
59
|
+
longname << (" %-8s %-8s %8d " % [attributes.owner, attributes.group, attributes.size])
|
60
|
+
|
61
|
+
longname << Time.at(attributes.mtime).strftime("%b %e %H:%M ")
|
62
|
+
longname << name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end; end; end; end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'net/sftp/protocol/04/base'
|
2
|
+
|
3
|
+
module Net; module SFTP; module Protocol; module V05
|
4
|
+
|
5
|
+
# Wraps the low-level SFTP calls for version 5 of the SFTP protocol.
|
6
|
+
#
|
7
|
+
# None of these protocol methods block--all of them return immediately,
|
8
|
+
# requiring the SSH event loop to be run while the server response is
|
9
|
+
# pending.
|
10
|
+
#
|
11
|
+
# You will almost certainly never need to use this driver directly. Please
|
12
|
+
# see Net::SFTP::Session for the recommended interface.
|
13
|
+
class Base < V04::Base
|
14
|
+
# Returns the protocol version implemented by this driver. (5, in this
|
15
|
+
# case)
|
16
|
+
def version
|
17
|
+
5
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sends a FXP_RENAME packet to the server to request that the file or
|
21
|
+
# directory with the given +name+ (must be a full path) be changed to
|
22
|
+
# +new_name+ (which must also be a path). The +flags+ parameter must be
|
23
|
+
# either +nil+ or 0 (the default), or some combination of the
|
24
|
+
# Net::SFTP::Constants::RenameFlags constants.
|
25
|
+
def rename(name, new_name, flags=nil)
|
26
|
+
send_request(FXP_RENAME, :string, name, :string, new_name, :long, flags || 0)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Sends a FXP_OPEN packet to the server and returns the packet identifier.
|
30
|
+
# The +flags+ parameter is either an integer (in which case it must be
|
31
|
+
# a combination of the IO constants) or a string (in which case it must
|
32
|
+
# be one of the mode strings that IO::open accepts). The +options+
|
33
|
+
# parameter is a hash that is used to construct a new Attribute object,
|
34
|
+
# to pass as part of the FXP_OPEN request.
|
35
|
+
def open(path, flags, options)
|
36
|
+
flags = normalize_open_flags(flags)
|
37
|
+
|
38
|
+
sftp_flags, desired_access = if flags & (IO::WRONLY | IO::RDWR) != 0
|
39
|
+
open = if flags & (IO::CREAT | IO::EXCL) == (IO::CREAT | IO::EXCL)
|
40
|
+
FV5::CREATE_NEW
|
41
|
+
elsif flags & (IO::CREAT | IO::TRUNC) == (IO::CREAT | IO::TRUNC)
|
42
|
+
FV5::CREATE_TRUNCATE
|
43
|
+
elsif flags & IO::CREAT == IO::CREAT
|
44
|
+
FV5::OPEN_OR_CREATE
|
45
|
+
else
|
46
|
+
FV5::OPEN_EXISTING
|
47
|
+
end
|
48
|
+
access = ACE::Mask::WRITE_DATA | ACE::Mask::WRITE_ATTRIBUTES
|
49
|
+
access |= ACE::Mask::READ_DATA | ACE::Mask::READ_ATTRIBUTES if (flags & IO::RDWR) == IO::RDWR
|
50
|
+
if flags & IO::APPEND == IO::APPEND
|
51
|
+
open |= FV5::APPEND_DATA
|
52
|
+
access |= ACE::Mask::APPEND_DATA
|
53
|
+
end
|
54
|
+
[open, access]
|
55
|
+
else
|
56
|
+
[FV5::OPEN_EXISTING, ACE::Mask::READ_DATA | ACE::Mask::READ_ATTRIBUTES]
|
57
|
+
end
|
58
|
+
|
59
|
+
attributes = attribute_factory.new(options)
|
60
|
+
|
61
|
+
send_request(FXP_OPEN, :string, path, :long, desired_access, :long, sftp_flags, :raw, attributes.to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end; end; end; end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'net/sftp/protocol/04/attributes'
|
2
|
+
|
3
|
+
module Net; module SFTP; module Protocol; module V06
|
4
|
+
|
5
|
+
# A class representing the attributes of a file or directory on the server.
|
6
|
+
# It may be used to specify new attributes, or to query existing attributes.
|
7
|
+
# This particular class is specific to versions 6 and higher of the SFTP
|
8
|
+
# protocol.
|
9
|
+
#
|
10
|
+
# To specify new attributes, just pass a hash as the argument to the
|
11
|
+
# constructor. The following keys are supported:
|
12
|
+
#
|
13
|
+
# * :type:: the type of the item (integer, one of the T_ constants)
|
14
|
+
# * :size:: the size of the item (integer)
|
15
|
+
# * :allocation_size:: the actual number of bytes that the item uses on disk (integer)
|
16
|
+
# * :uid:: the user-id that owns the file (integer)
|
17
|
+
# * :gid:: the group-id that owns the file (integer)
|
18
|
+
# * :owner:: the name of the user that owns the file (string)
|
19
|
+
# * :group:: the name of the group that owns the file (string)
|
20
|
+
# * :permissions:: the permissions on the file (integer, e.g. 0755)
|
21
|
+
# * :atime:: the access time of the file (integer, seconds since epoch)
|
22
|
+
# * :atime_nseconds:: the nanosecond component of atime (integer)
|
23
|
+
# * :createtime:: the time at which the file was created (integer, seconds since epoch)
|
24
|
+
# * :createtime_nseconds:: the nanosecond component of createtime (integer)
|
25
|
+
# * :mtime:: the modification time of the file (integer, seconds since epoch)
|
26
|
+
# * :mtime_nseconds:: the nanosecond component of mtime (integer)
|
27
|
+
# * :ctime:: the time that the file's attributes were last changed (integer)
|
28
|
+
# * :ctime_nseconds:: the nanosecond component of ctime (integer)
|
29
|
+
# * :acl:: an array of ACL entries for the item
|
30
|
+
# * :attrib_bits:: other attributes of the file or directory (as a bit field) (integer)
|
31
|
+
# * :attrib_bits_valid:: a mask describing which bits in attrib_bits are valid (integer)
|
32
|
+
# * :text_hint:: whether the file may or may not contain textual data (integer)
|
33
|
+
# * :mime_type:: the mime type of the file (string)
|
34
|
+
# * :link_count:: the hard link count of the file (integer)
|
35
|
+
# * :untranslated_name:: the value of the filename before filename translation was attempted (string)
|
36
|
+
# * :extended:: a hash of name/value pairs identifying extended info
|
37
|
+
#
|
38
|
+
# Likewise, when the server sends an Attributes object, all of the
|
39
|
+
# above attributes are exposed as methods (though not all will be set with
|
40
|
+
# non-nil values from the server).
|
41
|
+
class Attributes < V04::Attributes
|
42
|
+
F_BITS = 0x00000200
|
43
|
+
F_ALLOCATION_SIZE = 0x00000400
|
44
|
+
F_TEXT_HINT = 0x00000800
|
45
|
+
F_MIME_TYPE = 0x00001000
|
46
|
+
F_LINK_COUNT = 0x00002000
|
47
|
+
F_UNTRANSLATED_NAME = 0x00004000
|
48
|
+
F_CTIME = 0x00008000
|
49
|
+
|
50
|
+
# The array of elements that describe this structure, in order. Used when
|
51
|
+
# parsing and serializing attribute objects.
|
52
|
+
def self.elements #:nodoc:
|
53
|
+
@elements ||= [
|
54
|
+
[:type, :byte, 0],
|
55
|
+
[:size, :int64, F_SIZE],
|
56
|
+
[:allocation_size, :int64, F_ALLOCATION_SIZE],
|
57
|
+
[:owner, :string, F_OWNERGROUP],
|
58
|
+
[:group, :string, F_OWNERGROUP],
|
59
|
+
[:permissions, :long, F_PERMISSIONS],
|
60
|
+
[:atime, :int64, F_ACCESSTIME],
|
61
|
+
[:atime_nseconds, :long, F_ACCESSTIME | F_SUBSECOND_TIMES],
|
62
|
+
[:createtime, :int64, F_CREATETIME],
|
63
|
+
[:createtime_nseconds, :long, F_CREATETIME | F_SUBSECOND_TIMES],
|
64
|
+
[:mtime, :int64, F_MODIFYTIME],
|
65
|
+
[:mtime_nseconds, :long, F_MODIFYTIME | F_SUBSECOND_TIMES],
|
66
|
+
[:ctime, :int64, F_CTIME],
|
67
|
+
[:ctime_nseconds, :long, F_CTIME | F_SUBSECOND_TIMES],
|
68
|
+
[:acl, :special, F_ACL],
|
69
|
+
[:attrib_bits, :long, F_BITS],
|
70
|
+
[:attrib_bits_valid, :long, F_BITS],
|
71
|
+
[:text_hint, :byte, F_TEXT_HINT],
|
72
|
+
[:mime_type, :string, F_MIME_TYPE],
|
73
|
+
[:link_count, :long, F_LINK_COUNT],
|
74
|
+
[:untranslated_name, :string, F_UNTRANSLATED_NAME],
|
75
|
+
[:extended, :special, F_EXTENDED]
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
# The size on-disk of the file
|
80
|
+
attr_accessor :allocation_size
|
81
|
+
|
82
|
+
# The time at which the file's attributes were last changed
|
83
|
+
attr_accessor :ctime
|
84
|
+
|
85
|
+
# The nanosecond component of #ctime
|
86
|
+
attr_accessor :ctime_nseconds
|
87
|
+
|
88
|
+
# Other attributes of this file or directory (as a bit field)
|
89
|
+
attr_accessor :attrib_bits
|
90
|
+
|
91
|
+
# A bit mask describing which bits in #attrib_bits are valid
|
92
|
+
attr_accessor :attrib_bits_valid
|
93
|
+
|
94
|
+
# Describes whether the file may or may not contain textual data
|
95
|
+
attr_accessor :text_hint
|
96
|
+
|
97
|
+
# The mime-type of the file
|
98
|
+
attr_accessor :mime_type
|
99
|
+
|
100
|
+
# The hard link count for the file
|
101
|
+
attr_accessor :link_count
|
102
|
+
|
103
|
+
# The value of the file name before filename translation was attempted
|
104
|
+
attr_accessor :untranslated_name
|
105
|
+
end
|
106
|
+
|
107
|
+
end; end; end; end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'net/sftp/protocol/05/base'
|
2
|
+
require 'net/sftp/protocol/06/attributes'
|
3
|
+
|
4
|
+
module Net; module SFTP; module Protocol; module V06
|
5
|
+
|
6
|
+
# Wraps the low-level SFTP calls for version 6 of the SFTP protocol.
|
7
|
+
#
|
8
|
+
# None of these protocol methods block--all of them return immediately,
|
9
|
+
# requiring the SSH event loop to be run while the server response is
|
10
|
+
# pending.
|
11
|
+
#
|
12
|
+
# You will almost certainly never need to use this driver directly. Please
|
13
|
+
# see Net::SFTP::Session for the recommended interface.
|
14
|
+
class Base < V05::Base
|
15
|
+
|
16
|
+
# Returns the protocol version implemented by this driver. (6, in this
|
17
|
+
# case)
|
18
|
+
def version
|
19
|
+
6
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sends a FXP_LINK packet to the server to request that a link be created
|
23
|
+
# at +new_link_path+, pointing to +existing_path+. If +symlink+ is true, a
|
24
|
+
# symbolic link will be created; otherwise a hard link will be created.
|
25
|
+
def link(new_link_path, existing_path, symlink)
|
26
|
+
send_request(FXP_LINK, :string, new_link_path, :string, existing_path, :bool, symlink)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Provided for backwards compatibility; v6 of the SFTP protocol removes the
|
30
|
+
# older FXP_SYMLINK packet type, so this method simply calls the #link
|
31
|
+
# method.
|
32
|
+
def symlink(path, target)
|
33
|
+
link(path, target, true)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sends a FXP_BLOCK packet to the server to request that a byte-range lock
|
37
|
+
# be obtained on the given +handle+, for the given byte +offset+ and
|
38
|
+
# +length+. The +mask+ parameter is a bitfield indicating what kind of
|
39
|
+
# lock to acquire, and must be a combination of one or more of the
|
40
|
+
# Net::SFTP::Constants::LockTypes constants.
|
41
|
+
def block(handle, offset, length, mask)
|
42
|
+
send_request(FXP_BLOCK, :string, handle, :int64, offset, :int64, length, :long, mask)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Sends a FXP_UNBLOCK packet to the server to request that a previously
|
46
|
+
# acquired byte-range lock be released on the given +handle+, for the
|
47
|
+
# given byte +offset+ and +length+. The +handle+, +offset+, and +length+
|
48
|
+
# must all exactly match the parameters that were given when the lock was
|
49
|
+
# originally acquired (see #block).
|
50
|
+
def unblock(handle, offset, length)
|
51
|
+
send_request(FXP_UNBLOCK, :string, handle, :int64, offset, :int64, length)
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
# Returns the Attributes class used by this version of the protocol
|
57
|
+
# (Net::SFTP::Protocol::V06::Attributes, in this case)
|
58
|
+
def attribute_factory
|
59
|
+
V06::Attributes
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end; end; end; end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'net/ssh/loggable'
|
2
|
+
require 'net/sftp/constants'
|
3
|
+
|
4
|
+
module Net; module SFTP; module Protocol
|
5
|
+
|
6
|
+
# The abstract superclass of the specific implementations for each supported
|
7
|
+
# SFTP protocol version. It implements general packet parsing logic, and
|
8
|
+
# provides a way for subclasses to send requests.
|
9
|
+
class Base
|
10
|
+
include Net::SSH::Loggable
|
11
|
+
include Net::SFTP::Constants
|
12
|
+
include Net::SFTP::Constants::PacketTypes
|
13
|
+
|
14
|
+
# The SFTP session object that acts as client to this protocol instance
|
15
|
+
attr_reader :session
|
16
|
+
|
17
|
+
# Create a new instance of a protocol driver, servicing the given session.
|
18
|
+
def initialize(session)
|
19
|
+
@session = session
|
20
|
+
self.logger = session.logger
|
21
|
+
@request_id_counter = -1
|
22
|
+
end
|
23
|
+
|
24
|
+
# Attept to parse the given packet. If the packet is of an unsupported
|
25
|
+
# type, an exception will be raised. Returns the parsed data as a hash
|
26
|
+
# (the keys in the hash are packet-type specific).
|
27
|
+
def parse(packet)
|
28
|
+
case packet.type
|
29
|
+
when FXP_STATUS then parse_status_packet(packet)
|
30
|
+
when FXP_HANDLE then parse_handle_packet(packet)
|
31
|
+
when FXP_DATA then parse_data_packet(packet)
|
32
|
+
when FXP_NAME then parse_name_packet(packet)
|
33
|
+
when FXP_ATTRS then parse_attrs_packet(packet)
|
34
|
+
else raise NotImplementedError, "unknown packet type: #{packet.type}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Send a new packet of the given type, and with the given data arguments.
|
41
|
+
# A new request identifier will be allocated to this request, and will
|
42
|
+
# be returned.
|
43
|
+
def send_request(type, *args)
|
44
|
+
@request_id_counter += 1
|
45
|
+
session.send_packet(type, :long, @request_id_counter, *args)
|
46
|
+
return @request_id_counter
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end; end; end
|