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,21 @@
|
|
1
|
+
require 'net/ssh/buffer'
|
2
|
+
|
3
|
+
module Net; module SFTP
|
4
|
+
|
5
|
+
# A specialization of the Net::SSH::Buffer class, which simply auto-reads
|
6
|
+
# the type byte from the front of every packet it represents.
|
7
|
+
class Packet < Net::SSH::Buffer
|
8
|
+
# The (intger) type of this packet. See Net::SFTP::Constants for all
|
9
|
+
# possible packet types.
|
10
|
+
attr_reader :type
|
11
|
+
|
12
|
+
# Create a new Packet object that wraps the given +data+ (which should be
|
13
|
+
# a String). The first byte of the data will be consumed automatically and
|
14
|
+
# interpreted as the #type of this packet.
|
15
|
+
def initialize(data)
|
16
|
+
super
|
17
|
+
@type = read_byte
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
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
|
@@ -1,23 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# All rights reserved.
|
5
|
-
#
|
6
|
-
# This source file is distributed as part of the Net::SFTP Secure FTP Client
|
7
|
-
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
-
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
-
# with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SFTP
|
10
|
-
# distribution for the texts of these licenses.
|
11
|
-
# -----------------------------------------------------------------------------
|
12
|
-
# net-sftp website: http://net-ssh.rubyforge.org/sftp
|
13
|
-
# project website : http://rubyforge.org/projects/net-ssh
|
14
|
-
# =============================================================================
|
15
|
-
#++
|
16
|
-
|
17
|
-
module Net ; module SFTP ; module Protocol ; module V_01
|
1
|
+
require 'net/ssh/buffer'
|
2
|
+
|
3
|
+
module Net; module SFTP; module Protocol; module V01
|
18
4
|
|
19
5
|
# A class representing the attributes of a file or directory on the server.
|
20
6
|
# It may be used to specify new attributes, or to query existing attributes.
|
7
|
+
#
|
8
|
+
# To specify new attributes, just pass a hash as the argument to the
|
9
|
+
# constructor. The following keys are supported:
|
10
|
+
#
|
11
|
+
# * :size:: the size of the file
|
12
|
+
# * :uid:: the user-id that owns the file (integer)
|
13
|
+
# * :gid:: the group-id that owns the file (integer)
|
14
|
+
# * :owner:: the name of the user that owns the file (string)
|
15
|
+
# * :group:: the name of the group that owns the file (string)
|
16
|
+
# * :permissions:: the permissions on the file (integer, e.g. 0755)
|
17
|
+
# * :atime:: the access time of the file (integer, seconds since epoch)
|
18
|
+
# * :mtime:: the modification time of the file (integer, seconds since epoch)
|
19
|
+
# * :extended:: a hash of name/value pairs identifying extended info
|
20
|
+
#
|
21
|
+
# Likewise, when the server sends an Attributes object, all of the
|
22
|
+
# above attributes are exposed as methods (though not all will be set with
|
23
|
+
# non-nil values from the server).
|
21
24
|
class Attributes
|
22
25
|
|
23
26
|
F_SIZE = 0x00000001
|
@@ -25,122 +28,288 @@ module Net ; module SFTP ; module Protocol ; module V_01
|
|
25
28
|
F_PERMISSIONS = 0x00000004
|
26
29
|
F_ACMODTIME = 0x00000008
|
27
30
|
F_EXTENDED = 0x80000000
|
28
|
-
|
31
|
+
|
32
|
+
T_REGULAR = 1
|
33
|
+
T_DIRECTORY = 2
|
34
|
+
T_SYMLINK = 3
|
35
|
+
T_SPECIAL = 4
|
36
|
+
T_UNKNOWN = 5
|
37
|
+
T_SOCKET = 6
|
38
|
+
T_CHAR_DEVICE = 7
|
39
|
+
T_BLOCK_DEVICE = 8
|
40
|
+
T_FIFO = 9
|
41
|
+
|
42
|
+
class <<self
|
43
|
+
# Returns the array of attribute meta-data that defines the structure of
|
44
|
+
# the attributes packet as described by this version of the protocol.
|
45
|
+
def elements #:nodoc:
|
46
|
+
@elements ||= [
|
47
|
+
[:size, :int64, F_SIZE],
|
48
|
+
[:uid, :long, F_UIDGID],
|
49
|
+
[:gid, :long, F_UIDGID],
|
50
|
+
[:permissions, :long, F_PERMISSIONS],
|
51
|
+
[:atime, :long, F_ACMODTIME],
|
52
|
+
[:mtime, :long, F_ACMODTIME],
|
53
|
+
[:extended, :special, F_EXTENDED]
|
54
|
+
]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Parses the given buffer and returns an Attributes object compsed from
|
58
|
+
# the data extracted from it.
|
59
|
+
def from_buffer(buffer)
|
60
|
+
flags = buffer.read_long
|
61
|
+
data = {}
|
62
|
+
|
63
|
+
elements.each do |name, type, condition|
|
64
|
+
if flags & condition == condition
|
65
|
+
if type == :special
|
66
|
+
data[name] = send("parse_#{name}", buffer)
|
67
|
+
else
|
68
|
+
data[name] = buffer.send("read_#{type}")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
new(data)
|
74
|
+
end
|
75
|
+
|
76
|
+
# A convenience method for defining methods that expose specific
|
77
|
+
# attributes. This redefines the standard attr_accessor (an admittedly
|
78
|
+
# bad practice) because (1) I don't need any "regular" accessors, and
|
79
|
+
# (2) because rdoc will automatically pick up and note methods defined
|
80
|
+
# via attr_accessor.
|
81
|
+
def attr_accessor(name) #:nodoc:
|
82
|
+
class_eval <<-CODE
|
83
|
+
def #{name}
|
84
|
+
attributes[:#{name}]
|
85
|
+
end
|
86
|
+
CODE
|
87
|
+
|
88
|
+
attr_writer(name)
|
89
|
+
end
|
90
|
+
|
91
|
+
# A convenience method for defining methods that expose specific
|
92
|
+
# attributes. This redefines the standard attr_writer (an admittedly
|
93
|
+
# bad practice) because (1) I don't need any "regular" accessors, and
|
94
|
+
# (2) because rdoc will automatically pick up and note methods defined
|
95
|
+
# via attr_writer.
|
96
|
+
def attr_writer(name) #:nodoc:
|
97
|
+
class_eval <<-CODE
|
98
|
+
def #{name}=(value)
|
99
|
+
attributes[:#{name}] = value
|
100
|
+
end
|
101
|
+
CODE
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
# Parse the hash of extended data from the buffer.
|
107
|
+
def parse_extended(buffer)
|
108
|
+
extended = Hash.new
|
109
|
+
buffer.read_long.times do
|
110
|
+
extended[buffer.read_string] = buffer.read_string
|
111
|
+
end
|
112
|
+
extended
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# The hash of name/value pairs that backs this Attributes instance
|
117
|
+
attr_reader :attributes
|
118
|
+
|
119
|
+
# The size of the file.
|
29
120
|
attr_accessor :size
|
30
|
-
|
31
|
-
|
121
|
+
|
122
|
+
# The user-id of the user that owns the file
|
123
|
+
attr_writer :uid
|
124
|
+
|
125
|
+
# The group-id of the user that owns the file
|
126
|
+
attr_writer :gid
|
127
|
+
|
128
|
+
# The permissions on the file
|
32
129
|
attr_accessor :permissions
|
130
|
+
|
131
|
+
# The last access time of the file
|
33
132
|
attr_accessor :atime
|
133
|
+
|
134
|
+
# The modification time of the file
|
34
135
|
attr_accessor :mtime
|
136
|
+
|
137
|
+
# The hash of name/value pairs identifying extended information about the file
|
35
138
|
attr_accessor :extended
|
36
139
|
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# method to encode the object's attributes.
|
140
|
+
# Create a new Attributes instance with the given attributes. The
|
141
|
+
# following keys are supported:
|
40
142
|
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
143
|
+
# * :size:: the size of the file
|
144
|
+
# * :uid:: the user-id that owns the file (integer)
|
145
|
+
# * :gid:: the group-id that owns the file (integer)
|
146
|
+
# * :owner:: the name of the user that owns the file (string)
|
147
|
+
# * :group:: the name of the group that owns the file (string)
|
148
|
+
# * :permissions:: the permissions on the file (integer, e.g. 0755)
|
149
|
+
# * :atime:: the access time of the file (integer, seconds since epoch)
|
150
|
+
# * :mtime:: the modification time of the file (integer, seconds since epoch)
|
151
|
+
# * :extended:: a hash of name/value pairs identifying extended info
|
152
|
+
def initialize(attributes={})
|
153
|
+
@attributes = attributes
|
45
154
|
end
|
46
155
|
|
47
|
-
# Returns the
|
48
|
-
|
49
|
-
|
156
|
+
# Returns the user-id of the user that owns the file, or +nil+ if that
|
157
|
+
# information is not available. If an :owner key exists, but not a :uid
|
158
|
+
# key, the Etc module will be used to reverse lookup the id from the name.
|
159
|
+
# This might fail on some systems (e.g., Windows).
|
160
|
+
def uid
|
161
|
+
if attributes[:owner] && !attributes.key?(:uid)
|
162
|
+
require 'etc'
|
163
|
+
attributes[:uid] = Etc.getpwnam(attributes[:owner]).uid
|
164
|
+
end
|
165
|
+
attributes[:uid]
|
50
166
|
end
|
51
167
|
|
52
|
-
# Returns the
|
53
|
-
|
54
|
-
|
168
|
+
# Returns the group-id of the group that owns the file, or +nil+ if that
|
169
|
+
# information is not available. If a :group key exists, but not a :gid
|
170
|
+
# key, the Etc module will be used to reverse lookup the id from the name.
|
171
|
+
# This might fail on some systems (e.g., Windows).
|
172
|
+
def gid
|
173
|
+
if attributes[:group] && !attributes.key?(:gid)
|
174
|
+
require 'etc'
|
175
|
+
attributes[:gid] = Etc.getgrnam(attributes[:group]).gid
|
176
|
+
end
|
177
|
+
attributes[:gid]
|
55
178
|
end
|
56
179
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
180
|
+
# Returns the username of the user that owns the file, or +nil+ if that
|
181
|
+
# information is not available. If the :uid is given, but not the :owner,
|
182
|
+
# the Etc module will be used to lookup the name from the id. This might
|
183
|
+
# fail on some systems (e.g. Windows).
|
184
|
+
def owner
|
185
|
+
if attributes[:uid] && !attributes[:owner]
|
186
|
+
require 'etc'
|
187
|
+
attributes[:owner] = Etc.getpwuid(attributes[:uid].to_i).name
|
188
|
+
end
|
189
|
+
attributes[:owner]
|
60
190
|
end
|
61
191
|
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
atime = buffer.read_long if ( flags & F_ACMODTIME ) != 0
|
71
|
-
mtime = buffer.read_long if ( flags & F_ACMODTIME ) != 0
|
72
|
-
|
73
|
-
if ( flags & F_EXTENDED ) != 0
|
74
|
-
extended = Hash.new
|
75
|
-
buffer.read_long.times do
|
76
|
-
extended[ buffer.read_string ] = buffer.read_string
|
77
|
-
end
|
192
|
+
# Returns the group name of the group that owns the file, or +nil+ if that
|
193
|
+
# information is not available. If the :gid is given, but not the :group,
|
194
|
+
# the Etc module will be used to lookup the name from the id. This might
|
195
|
+
# fail on some systems (e.g. Windows).
|
196
|
+
def group
|
197
|
+
if attributes[:gid] && !attributes[:group]
|
198
|
+
require 'etc'
|
199
|
+
attributes[:group] = Etc.getgrgid(attributes[:gid].to_i).name
|
78
200
|
end
|
201
|
+
attributes[:group]
|
202
|
+
end
|
79
203
|
|
80
|
-
|
204
|
+
# Inspects the permissions bits to determine what type of entity this
|
205
|
+
# attributes object represents. If will return one of the T_ constants.
|
206
|
+
def type
|
207
|
+
if permissions & 0140000 == 0140000 then
|
208
|
+
T_SOCKET
|
209
|
+
elsif permissions & 0120000 == 0120000 then
|
210
|
+
T_SYMLINK
|
211
|
+
elsif permissions & 0100000 == 0100000 then
|
212
|
+
T_REGULAR
|
213
|
+
elsif permissions & 060000 == 060000 then
|
214
|
+
T_BLOCK_DEVICE
|
215
|
+
elsif permissions & 040000 == 040000 then
|
216
|
+
T_DIRECTORY
|
217
|
+
elsif permissions & 020000 == 020000 then
|
218
|
+
T_CHAR_DEVICE
|
219
|
+
elsif permissions & 010000 == 010000 then
|
220
|
+
T_FIFO
|
221
|
+
else
|
222
|
+
T_UNKNOWN
|
223
|
+
end
|
81
224
|
end
|
82
225
|
|
83
|
-
#
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
226
|
+
# Returns the type as a symbol, rather than an integer, for easier use in
|
227
|
+
# Ruby programs.
|
228
|
+
def symbolic_type
|
229
|
+
case type
|
230
|
+
when T_SOCKET then :socket
|
231
|
+
when T_SYMLINK then :symlink
|
232
|
+
when T_REGULAR then :regular
|
233
|
+
when T_BLOCK_DEVICE then :block_device
|
234
|
+
when T_DIRECTORY then :directory
|
235
|
+
when T_CHAR_DEVICE then :char_device
|
236
|
+
when T_FIFO then :fifo
|
237
|
+
when T_SPECIAL then :special
|
238
|
+
when T_UNKNOWN then :unknown
|
239
|
+
else raise NotImplementedError, "unknown file type #{type} (bug?)"
|
92
240
|
end
|
241
|
+
end
|
93
242
|
|
94
|
-
|
95
|
-
|
96
|
-
|
243
|
+
# Returns true if these attributes appear to describe a directory.
|
244
|
+
def directory?
|
245
|
+
case type
|
246
|
+
when T_DIRECTORY then true
|
247
|
+
when T_UNKNOWN then nil
|
248
|
+
else false
|
97
249
|
end
|
250
|
+
end
|
98
251
|
|
99
|
-
|
100
|
-
|
252
|
+
# Returns true if these attributes appear to describe a symlink.
|
253
|
+
def symlink?
|
254
|
+
case type
|
255
|
+
when T_SYMLINK then true
|
256
|
+
when T_UNKNOWN then nil
|
257
|
+
else false
|
258
|
+
end
|
101
259
|
end
|
102
260
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
@uid = uid
|
111
|
-
@gid = gid
|
112
|
-
@permissions = permissions
|
113
|
-
@atime = atime
|
114
|
-
@mtime = mtime
|
115
|
-
@extended = extended
|
261
|
+
# Returns true if these attributes appear to describe a regular file.
|
262
|
+
def file?
|
263
|
+
case type
|
264
|
+
when T_REGULAR then true
|
265
|
+
when T_UNKNOWN then nil
|
266
|
+
else false
|
267
|
+
end
|
116
268
|
end
|
117
269
|
|
118
270
|
# Convert the object to a string suitable for passing in an SFTP
|
119
|
-
# packet.
|
271
|
+
# packet. This is the raw representation of the attribute packet payload,
|
272
|
+
# and is not intended to be human readable.
|
120
273
|
def to_s
|
121
|
-
|
274
|
+
prepare_serialization!
|
122
275
|
|
123
|
-
flags
|
124
|
-
flags |= F_UIDGID if @uid && @gid
|
125
|
-
flags |= F_PERMISSIONS if @permissions
|
126
|
-
flags |= F_ACMODTIME if @atime && @mtime
|
127
|
-
flags |= F_EXTENDED if @extended
|
276
|
+
flags = 0
|
128
277
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
buffer.write_long @uid, @gid if @uid && @gid
|
133
|
-
buffer.write_long @permissions if @permissions
|
134
|
-
buffer.write_long @atime, @mtime if @atime && @mtime
|
278
|
+
self.class.elements.each do |name, type, condition|
|
279
|
+
flags |= condition if attributes[name]
|
280
|
+
end
|
135
281
|
|
136
|
-
|
137
|
-
|
138
|
-
|
282
|
+
buffer = Net::SSH::Buffer.from(:long, flags)
|
283
|
+
self.class.elements.each do |name, type, condition|
|
284
|
+
if flags & condition == condition
|
285
|
+
if type == :special
|
286
|
+
send("encode_#{name}", buffer)
|
287
|
+
else
|
288
|
+
buffer.send("write_#{type}", attributes[name])
|
289
|
+
end
|
290
|
+
end
|
139
291
|
end
|
140
292
|
|
141
293
|
buffer.to_s
|
142
294
|
end
|
143
295
|
|
296
|
+
private
|
297
|
+
|
298
|
+
# Perform protocol-version-specific preparations for serialization.
|
299
|
+
def prepare_serialization!
|
300
|
+
# force the uid/gid to be translated from owner/group, if those keys
|
301
|
+
# were given on instantiation
|
302
|
+
uid
|
303
|
+
gid
|
304
|
+
end
|
305
|
+
|
306
|
+
# Encodes information about the extended info onto the end of the given
|
307
|
+
# buffer.
|
308
|
+
def encode_extended(buffer)
|
309
|
+
buffer.write_long extended.size
|
310
|
+
extended.each { |k,v| buffer.write_string k, v }
|
311
|
+
end
|
312
|
+
|
144
313
|
end
|
145
314
|
|
146
315
|
end ; end ; end ; end
|