net-sftp-backports 4.0.0.backports
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.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +35 -0
- data/.gitignore +6 -0
- data/CHANGES.txt +67 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +19 -0
- data/Manifest +55 -0
- data/README.rdoc +118 -0
- data/Rakefile +53 -0
- data/lib/net/sftp/constants.rb +187 -0
- data/lib/net/sftp/errors.rb +39 -0
- data/lib/net/sftp/operations/dir.rb +93 -0
- data/lib/net/sftp/operations/download.rb +365 -0
- data/lib/net/sftp/operations/file.rb +198 -0
- data/lib/net/sftp/operations/file_factory.rb +60 -0
- data/lib/net/sftp/operations/upload.rb +395 -0
- data/lib/net/sftp/packet.rb +21 -0
- data/lib/net/sftp/protocol/01/attributes.rb +315 -0
- 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 +152 -0
- 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/protocol.rb +32 -0
- data/lib/net/sftp/request.rb +91 -0
- data/lib/net/sftp/response.rb +76 -0
- data/lib/net/sftp/session.rb +954 -0
- data/lib/net/sftp/version.rb +68 -0
- data/lib/net/sftp.rb +78 -0
- data/net-sftp-public_cert.pem +20 -0
- data/net-sftp.gemspec +48 -0
- data/setup.rb +1331 -0
- metadata +132 -0
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'net/sftp/protocol/01/attributes'
|
2
|
+
|
3
|
+
module Net; module SFTP; module Protocol; module V04
|
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 4 and 5 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
|
+
# * :uid:: the user-id that owns the file (integer)
|
16
|
+
# * :gid:: the group-id that owns the file (integer)
|
17
|
+
# * :owner:: the name of the user that owns the file (string)
|
18
|
+
# * :group:: the name of the group that owns the file (string)
|
19
|
+
# * :permissions:: the permissions on the file (integer, e.g. 0755)
|
20
|
+
# * :atime:: the access time of the file (integer, seconds since epoch)
|
21
|
+
# * :atime_nseconds:: the nanosecond component of atime (integer)
|
22
|
+
# * :createtime:: the time at which the file was created (integer, seconds since epoch)
|
23
|
+
# * :createtime_nseconds:: the nanosecond component of createtime (integer)
|
24
|
+
# * :mtime:: the modification time of the file (integer, seconds since epoch)
|
25
|
+
# * :mtime_nseconds:: the nanosecond component of mtime (integer)
|
26
|
+
# * :acl:: an array of ACL entries for the item
|
27
|
+
# * :extended:: a hash of name/value pairs identifying extended info
|
28
|
+
#
|
29
|
+
# Likewise, when the server sends an Attributes object, all of the
|
30
|
+
# above attributes are exposed as methods (though not all will be set with
|
31
|
+
# non-nil values from the server).
|
32
|
+
class Attributes < V01::Attributes
|
33
|
+
|
34
|
+
F_ACCESSTIME = 0x00000008
|
35
|
+
F_CREATETIME = 0x00000010
|
36
|
+
F_MODIFYTIME = 0x00000020
|
37
|
+
F_ACL = 0x00000040
|
38
|
+
F_OWNERGROUP = 0x00000080
|
39
|
+
F_SUBSECOND_TIMES = 0x00000100
|
40
|
+
|
41
|
+
# A simple struct for representing a single entry in an Access Control
|
42
|
+
# List. (See Net::SFTP::Constants::ACE)
|
43
|
+
ACL = Struct.new(:type, :flag, :mask, :who)
|
44
|
+
|
45
|
+
class <<self
|
46
|
+
# The list of supported elements in the attributes structure as defined
|
47
|
+
# by v4 of the sftp protocol.
|
48
|
+
def elements #:nodoc:
|
49
|
+
@elements ||= [
|
50
|
+
[:type, :byte, 0],
|
51
|
+
[:size, :int64, V01::Attributes::F_SIZE],
|
52
|
+
[:owner, :string, F_OWNERGROUP],
|
53
|
+
[:group, :string, F_OWNERGROUP],
|
54
|
+
[:permissions, :long, V01::Attributes::F_PERMISSIONS],
|
55
|
+
[:atime, :int64, F_ACCESSTIME],
|
56
|
+
[:atime_nseconds, :long, F_ACCESSTIME | F_SUBSECOND_TIMES],
|
57
|
+
[:createtime, :int64, F_CREATETIME],
|
58
|
+
[:createtime_nseconds, :long, F_CREATETIME | F_SUBSECOND_TIMES],
|
59
|
+
[:mtime, :int64, F_MODIFYTIME],
|
60
|
+
[:mtime_nseconds, :long, F_MODIFYTIME | F_SUBSECOND_TIMES],
|
61
|
+
[:acl, :special, F_ACL],
|
62
|
+
[:extended, :special, V01::Attributes::F_EXTENDED]
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# A helper method for parsing the ACL entry in an Attributes struct.
|
69
|
+
def parse_acl(buffer)
|
70
|
+
acl_buf = Net::SSH::Buffer.new(buffer.read_string)
|
71
|
+
acl = []
|
72
|
+
acl_buf.read_long.times do
|
73
|
+
acl << ACL.new(acl_buf.read_long, acl_buf.read_long, acl_buf.read_long, acl_buf.read_string)
|
74
|
+
end
|
75
|
+
acl
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# The type of the item on the remote server. Must be one of the T_* constants.
|
80
|
+
attr_accessor :type
|
81
|
+
|
82
|
+
# The owner of the item on the remote server, as a string.
|
83
|
+
attr_writer :owner
|
84
|
+
|
85
|
+
# The group of the item on the remote server, as a string.
|
86
|
+
attr_writer :group
|
87
|
+
|
88
|
+
# The nanosecond component of the access time.
|
89
|
+
attr_accessor :atime_nseconds
|
90
|
+
|
91
|
+
# The creation time of the remote item, in seconds since the epoch.
|
92
|
+
attr_accessor :createtime
|
93
|
+
|
94
|
+
# The nanosecond component of the creation time.
|
95
|
+
attr_accessor :createtime_nseconds
|
96
|
+
|
97
|
+
# The nanosecond component of the modification time.
|
98
|
+
attr_accessor :mtime_nseconds
|
99
|
+
|
100
|
+
# The array of access control entries for this item.
|
101
|
+
attr_accessor :acl
|
102
|
+
|
103
|
+
# Create a new Attributes instance with the given attributes. The
|
104
|
+
# following keys are supported:
|
105
|
+
#
|
106
|
+
# * :type:: the type of the item (integer, one of the T_ constants)
|
107
|
+
# * :size:: the size of the item (integer)
|
108
|
+
# * :uid:: the user-id that owns the file (integer)
|
109
|
+
# * :gid:: the group-id that owns the file (integer)
|
110
|
+
# * :owner:: the name of the user that owns the file (string)
|
111
|
+
# * :group:: the name of the group that owns the file (string)
|
112
|
+
# * :permissions:: the permissions on the file (integer, e.g. 0755)
|
113
|
+
# * :atime:: the access time of the file (integer, seconds since epoch)
|
114
|
+
# * :atime_nseconds:: the nanosecond component of atime (integer)
|
115
|
+
# * :createtime:: the time at which the file was created (integer, seconds since epoch)
|
116
|
+
# * :createtime_nseconds:: the nanosecond component of createtime (integer)
|
117
|
+
# * :mtime:: the modification time of the file (integer, seconds since epoch)
|
118
|
+
# * :mtime_nseconds:: the nanosecond component of mtime (integer)
|
119
|
+
# * :acl:: an array of ACL entries for the item
|
120
|
+
# * :extended:: a hash of name/value pairs identifying extended info
|
121
|
+
#
|
122
|
+
# All of them default to +nil+ if omitted, except for +type+, which defaults
|
123
|
+
# to T_REGULAR.
|
124
|
+
def initialize(attributes={})
|
125
|
+
super
|
126
|
+
attributes[:type] ||= T_REGULAR
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# Perform protocol-version-specific preparations for serialization.
|
132
|
+
def prepare_serialization!
|
133
|
+
# force the group/owner to be translated from uid/gid, if those keys
|
134
|
+
# were given on instantiation
|
135
|
+
owner
|
136
|
+
group
|
137
|
+
end
|
138
|
+
|
139
|
+
# Performs protocol-version-specific encoding of the access control
|
140
|
+
# list, if one exists.
|
141
|
+
def encode_acl(buffer)
|
142
|
+
acl_buf = Net::SSH::Buffer.from(:long, acl.length)
|
143
|
+
acl.each do |item|
|
144
|
+
acl_buf.write_long item.type, item.flag, item.mask
|
145
|
+
acl_buf.write_string item.who
|
146
|
+
end
|
147
|
+
buffer.write_string(acl_buf.to_s)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end ; end ; end ; end
|
@@ -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
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'net/sftp/protocol/01/base'
|
2
|
+
require 'net/sftp/protocol/02/base'
|
3
|
+
require 'net/sftp/protocol/03/base'
|
4
|
+
require 'net/sftp/protocol/04/base'
|
5
|
+
require 'net/sftp/protocol/05/base'
|
6
|
+
require 'net/sftp/protocol/06/base'
|
7
|
+
|
8
|
+
module Net; module SFTP
|
9
|
+
|
10
|
+
# The Protocol module contains the definitions for all supported SFTP
|
11
|
+
# protocol versions.
|
12
|
+
module Protocol
|
13
|
+
|
14
|
+
# Instantiates and returns a new protocol driver instance for the given
|
15
|
+
# protocol version. +session+ must be a valid SFTP session object, and
|
16
|
+
# +version+ must be an integer. If an unsupported version is given,
|
17
|
+
# an exception will be raised.
|
18
|
+
def self.load(session, version)
|
19
|
+
case version
|
20
|
+
when 1 then V01::Base.new(session)
|
21
|
+
when 2 then V02::Base.new(session)
|
22
|
+
when 3 then V03::Base.new(session)
|
23
|
+
when 4 then V04::Base.new(session)
|
24
|
+
when 5 then V05::Base.new(session)
|
25
|
+
when 6 then V06::Base.new(session)
|
26
|
+
else raise NotImplementedError, "unsupported SFTP version #{version.inspect}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end; end
|