net-sftp 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/doc/LICENSE-BSD +27 -0
- data/doc/LICENSE-GPL +280 -0
- data/doc/LICENSE-RUBY +56 -0
- data/examples/asynchronous.rb +57 -0
- data/examples/ssh-service.rb +31 -0
- data/examples/synchronous.rb +120 -0
- data/lib/net/sftp.rb +39 -0
- data/lib/net/sftp/errors.rb +25 -0
- data/lib/net/sftp/operations/abstract.rb +103 -0
- data/lib/net/sftp/operations/close.rb +31 -0
- data/lib/net/sftp/operations/errors.rb +76 -0
- data/lib/net/sftp/operations/fsetstat.rb +36 -0
- data/lib/net/sftp/operations/fstat.rb +32 -0
- data/lib/net/sftp/operations/lstat.rb +31 -0
- data/lib/net/sftp/operations/mkdir.rb +33 -0
- data/lib/net/sftp/operations/open.rb +32 -0
- data/lib/net/sftp/operations/opendir.rb +32 -0
- data/lib/net/sftp/operations/read.rb +84 -0
- data/lib/net/sftp/operations/readdir.rb +55 -0
- data/lib/net/sftp/operations/realpath.rb +37 -0
- data/lib/net/sftp/operations/remove.rb +31 -0
- data/lib/net/sftp/operations/rename.rb +32 -0
- data/lib/net/sftp/operations/rmdir.rb +31 -0
- data/lib/net/sftp/operations/services.rb +42 -0
- data/lib/net/sftp/operations/setstat.rb +33 -0
- data/lib/net/sftp/operations/stat.rb +31 -0
- data/lib/net/sftp/operations/write.rb +63 -0
- data/lib/net/sftp/protocol/01/attributes.rb +146 -0
- data/lib/net/sftp/protocol/01/impl.rb +251 -0
- data/lib/net/sftp/protocol/01/packet-assistant.rb +82 -0
- data/lib/net/sftp/protocol/01/services.rb +47 -0
- data/lib/net/sftp/protocol/02/impl.rb +39 -0
- data/lib/net/sftp/protocol/02/packet-assistant.rb +32 -0
- data/lib/net/sftp/protocol/02/services.rb +44 -0
- data/lib/net/sftp/protocol/03/impl.rb +42 -0
- data/lib/net/sftp/protocol/03/packet-assistant.rb +35 -0
- data/lib/net/sftp/protocol/03/services.rb +44 -0
- data/lib/net/sftp/protocol/04/attributes.rb +227 -0
- data/lib/net/sftp/protocol/04/impl.rb +134 -0
- data/lib/net/sftp/protocol/04/packet-assistant.rb +51 -0
- data/lib/net/sftp/protocol/04/services.rb +44 -0
- data/lib/net/sftp/protocol/05/services.rb +44 -0
- data/lib/net/sftp/protocol/constants.rb +60 -0
- data/lib/net/sftp/protocol/driver.rb +232 -0
- data/lib/net/sftp/protocol/packet-assistant.rb +84 -0
- data/lib/net/sftp/protocol/services.rb +55 -0
- data/lib/net/sftp/session.rb +215 -0
- data/lib/net/sftp/version.rb +25 -0
- data/test/ALL-TESTS.rb +21 -0
- data/test/operations/tc_abstract.rb +124 -0
- data/test/operations/tc_close.rb +40 -0
- data/test/operations/tc_fsetstat.rb +48 -0
- data/test/operations/tc_fstat.rb +40 -0
- data/test/operations/tc_lstat.rb +40 -0
- data/test/operations/tc_mkdir.rb +48 -0
- data/test/operations/tc_open.rb +42 -0
- data/test/operations/tc_opendir.rb +40 -0
- data/test/operations/tc_read.rb +103 -0
- data/test/operations/tc_readdir.rb +88 -0
- data/test/operations/tc_realpath.rb +54 -0
- data/test/operations/tc_remove.rb +40 -0
- data/test/operations/tc_rmdir.rb +40 -0
- data/test/operations/tc_setstat.rb +48 -0
- data/test/operations/tc_stat.rb +40 -0
- data/test/operations/tc_write.rb +91 -0
- data/test/protocol/01/tc_attributes.rb +138 -0
- data/test/protocol/01/tc_impl.rb +294 -0
- data/test/protocol/01/tc_packet_assistant.rb +81 -0
- data/test/protocol/02/tc_impl.rb +41 -0
- data/test/protocol/02/tc_packet_assistant.rb +31 -0
- data/test/protocol/03/tc_impl.rb +48 -0
- data/test/protocol/03/tc_packet_assistant.rb +34 -0
- data/test/protocol/04/tc_attributes.rb +174 -0
- data/test/protocol/04/tc_impl.rb +102 -0
- data/test/protocol/04/tc_packet_assistant.rb +41 -0
- data/test/protocol/tc_driver.rb +219 -0
- metadata +137 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
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
|
+
require 'net/sftp/operations/abstract'
|
18
|
+
|
19
|
+
module Net ; module SFTP ; module Operations
|
20
|
+
|
21
|
+
# Implements the +setstat+ operation.
|
22
|
+
class Setstat < Abstract
|
23
|
+
|
24
|
+
# Perform the operation. The +hash+ parameter is a hash of attributes that
|
25
|
+
# should be set on the file or directory indicated by the +path+.
|
26
|
+
def perform( path, hash )
|
27
|
+
attrs = @driver.attr_factory.from_hash( hash )
|
28
|
+
@driver.setstat( nil, path, attrs )
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end ; end ; end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
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
|
+
require 'net/sftp/operations/abstract'
|
18
|
+
|
19
|
+
module Net ; module SFTP ; module Operations
|
20
|
+
|
21
|
+
# Implements the +stat+ operation.
|
22
|
+
class Stat < Abstract
|
23
|
+
|
24
|
+
# Perform the operation.
|
25
|
+
def perform( path )
|
26
|
+
@driver.stat( nil, path )
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end ; end ; end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
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
|
+
require 'net/sftp/operations/abstract'
|
18
|
+
|
19
|
+
module Net ; module SFTP ; module Operations
|
20
|
+
|
21
|
+
# Implements the +write+ operation. Handles, automatically, the looping
|
22
|
+
# necessary to write a large data set.
|
23
|
+
class Write < Abstract
|
24
|
+
|
25
|
+
# The maximum size of data that will be written at one time.
|
26
|
+
CHUNK_SIZE = 64 * 1024
|
27
|
+
|
28
|
+
# Perform the operation. Only CHUNK_SIZE portions of the +data+ parameter
|
29
|
+
# will be written at a time, with subsequent chunks being writteni
|
30
|
+
# automatically when prior chunks complete.
|
31
|
+
def perform( handle, data, offset=0 )
|
32
|
+
@handle = handle
|
33
|
+
@offset = offset
|
34
|
+
@data = data
|
35
|
+
@pos = 0
|
36
|
+
|
37
|
+
@driver.write( nil, handle, offset, data[0,CHUNK_SIZE] )
|
38
|
+
end
|
39
|
+
|
40
|
+
# Invoked when the server sends a status packet. If the status is FX_OK,
|
41
|
+
# then the callback is invoked (if all data has been written), or the
|
42
|
+
# next chunk is written to the server (if more data remains). Other
|
43
|
+
# status codes are handled by the superclass.
|
44
|
+
def do_status( code, message, language )
|
45
|
+
if code == FX_OK
|
46
|
+
@log.debug "[#{@id}] chunk written" if @log.debug?
|
47
|
+
@pos += CHUNK_SIZE
|
48
|
+
|
49
|
+
if @pos > @data.length
|
50
|
+
@callback[ OK ]
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
@driver.write @id, @handle, @offset + @pos, @data[@pos,CHUNK_SIZE]
|
55
|
+
@session.register @id, self
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end ; end ; end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
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
|
18
|
+
|
19
|
+
# A class representing the attributes of a file or directory on the server.
|
20
|
+
# It may be used to specify new attributes, or to query existing attributes.
|
21
|
+
class Attributes
|
22
|
+
|
23
|
+
F_SIZE = 0x00000001
|
24
|
+
F_UIDGID = 0x00000002
|
25
|
+
F_PERMISSIONS = 0x00000004
|
26
|
+
F_ACMODTIME = 0x00000008
|
27
|
+
F_EXTENDED = 0x80000000
|
28
|
+
|
29
|
+
attr_accessor :size
|
30
|
+
attr_accessor :uid
|
31
|
+
attr_accessor :gid
|
32
|
+
attr_accessor :permissions
|
33
|
+
attr_accessor :atime
|
34
|
+
attr_accessor :mtime
|
35
|
+
attr_accessor :extended
|
36
|
+
|
37
|
+
# An initialization routine, to grant the class (factory) access to a
|
38
|
+
# buffer factory. The buffer factory is used by the class' #to_s
|
39
|
+
# method to encode the object's attributes.
|
40
|
+
#
|
41
|
+
# This returns +self+, making it suitable for chaining.
|
42
|
+
def self.init( buffers )
|
43
|
+
@buffers = buffers
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the buffer factory for this class.
|
48
|
+
def self.buffers
|
49
|
+
@buffers
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the buffer factory for the object's class.
|
53
|
+
def buffers
|
54
|
+
self.class.buffers
|
55
|
+
end
|
56
|
+
|
57
|
+
# Create a new, empty Attributes object.
|
58
|
+
def self.empty
|
59
|
+
new
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create a new Attributes object, initialized from the given buffer.
|
63
|
+
def self.from_buffer( buffer )
|
64
|
+
flags = buffer.read_long
|
65
|
+
|
66
|
+
size = buffer.read_int64 if ( flags & F_SIZE ) != 0
|
67
|
+
uid = buffer.read_long if ( flags & F_UIDGID ) != 0
|
68
|
+
gid = buffer.read_long if ( flags & F_UIDGID ) != 0
|
69
|
+
permissions = buffer.read_long if ( flags & F_PERMISSIONS ) != 0
|
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
|
78
|
+
end
|
79
|
+
|
80
|
+
new( size, uid, gid, permissions, atime, mtime, extended )
|
81
|
+
end
|
82
|
+
|
83
|
+
# Create a new attributes object, initialized from the given hash. The
|
84
|
+
# :owner and :group attributes are treated specially; they are not actually
|
85
|
+
# supported by this version of the protocol, but are instead converted
|
86
|
+
# by this method to their corresponding id numbers, and assigned
|
87
|
+
# (respectively) to :uid and :gid.
|
88
|
+
def self.from_hash( hash )
|
89
|
+
if hash[:owner]
|
90
|
+
require 'etc'
|
91
|
+
hash[:uid] = Etc.getpwnam( hash[:owner] ).uid
|
92
|
+
end
|
93
|
+
|
94
|
+
if hash[:group]
|
95
|
+
require 'etc'
|
96
|
+
hash[:gid] = Etc.getgrnam( hash[:group] ).gid
|
97
|
+
end
|
98
|
+
|
99
|
+
new hash[:size], hash[:uid], hash[:gid], hash[:permissions],
|
100
|
+
hash[:atime], hash[:mtime], hash[:extended]
|
101
|
+
end
|
102
|
+
|
103
|
+
private_class_method :new
|
104
|
+
|
105
|
+
# Create a new Attributes with the given attributes.
|
106
|
+
def initialize( size=nil, uid=nil, gid=nil, permissions=nil,
|
107
|
+
atime=nil, mtime=nil, extended=nil )
|
108
|
+
# begin
|
109
|
+
@size = size
|
110
|
+
@uid = uid
|
111
|
+
@gid = gid
|
112
|
+
@permissions = permissions
|
113
|
+
@atime = atime
|
114
|
+
@mtime = mtime
|
115
|
+
@extended = extended
|
116
|
+
end
|
117
|
+
|
118
|
+
# Convert the object to a string suitable for passing in an SFTP
|
119
|
+
# packet.
|
120
|
+
def to_s
|
121
|
+
flags = 0
|
122
|
+
|
123
|
+
flags |= F_SIZE if @size
|
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
|
128
|
+
|
129
|
+
buffer = buffers.writer
|
130
|
+
buffer.write_long flags
|
131
|
+
buffer.write_int64 @size if @size
|
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
|
135
|
+
|
136
|
+
if @extended
|
137
|
+
buffer.write_long @extended.size
|
138
|
+
@extended.each { |k,v| buffer.write_string k, v }
|
139
|
+
end
|
140
|
+
|
141
|
+
buffer.to_s
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end ; end ; end ; end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
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
|
+
require 'net/sftp/errors'
|
18
|
+
require 'net/sftp/protocol/constants'
|
19
|
+
|
20
|
+
module Net ; module SFTP ; module Protocol ; module V_01
|
21
|
+
|
22
|
+
# The implementing class for version 1 of the SFTP protocol. It
|
23
|
+
# implements the various operations and callbacks available to this
|
24
|
+
# level of the protocol. Other protocol versions will typically
|
25
|
+
# extend this class, adding (or modifying) methods as needed to bring
|
26
|
+
# the implementation into sync with the needed version.
|
27
|
+
class Impl
|
28
|
+
include Constants
|
29
|
+
|
30
|
+
Name = Struct.new( :filename, :longname, :attributes )
|
31
|
+
|
32
|
+
# The protocol driver that drives this dispatcher.
|
33
|
+
attr_reader :driver
|
34
|
+
|
35
|
+
# The attribute-factory used by this dispatcher.
|
36
|
+
attr_reader :attr_factory
|
37
|
+
|
38
|
+
# The protocol extensions specified when the protocol version was
|
39
|
+
# negotiated.
|
40
|
+
attr_accessor :extensions
|
41
|
+
|
42
|
+
# Create a new instance using the given protocol driver, packet
|
43
|
+
# assistant, and attributes factory.
|
44
|
+
def initialize( buffers, driver, assistant, attr_factory )
|
45
|
+
@buffers = buffers
|
46
|
+
@driver = driver
|
47
|
+
@assistant = assistant
|
48
|
+
@attr_factory = attr_factory
|
49
|
+
@on_status = nil
|
50
|
+
@on_handle = nil
|
51
|
+
@on_data = nil
|
52
|
+
@on_name = nil
|
53
|
+
@on_attrs = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
# A helper method for defining new operations supported by this
|
57
|
+
# implementation. This will create one method for each named operation.
|
58
|
+
# By default, the method simply formats the packet (using the packet
|
59
|
+
# assistant), and then sends the data via the driver. It will then
|
60
|
+
# return the request id used for this operation.
|
61
|
+
def self.operation( *names )
|
62
|
+
names.each do |name|
|
63
|
+
const = "FXP_#{name.to_s.upcase}"
|
64
|
+
class_eval <<-EOF, __FILE__, __LINE__+1
|
65
|
+
def #{name}( id, *args )
|
66
|
+
id, packet = @assistant.#{name}( id, *args )
|
67
|
+
@driver.send_data #{const}, packet
|
68
|
+
id
|
69
|
+
end
|
70
|
+
EOF
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# A helper method for registering new callbacks. Each callback will
|
75
|
+
# cause three new methods to be created, <tt>on_<em>name</em></tt>,
|
76
|
+
# <tt>has_on_<em>name</em>?</tt>, and <tt>call_on_<em>name</em></tt>.
|
77
|
+
# The <tt>on_<em>name</em></tt> method may be used to register a block
|
78
|
+
# for the corresponding callback.
|
79
|
+
def self.callback( *names )
|
80
|
+
names.each do |name|
|
81
|
+
class_eval <<-EOF, __FILE__, __LINE__+1
|
82
|
+
def on_#{name}( &block )
|
83
|
+
@on_#{name} = block
|
84
|
+
end
|
85
|
+
|
86
|
+
def has_on_#{name}?
|
87
|
+
not @on_#{name}.nil?
|
88
|
+
end
|
89
|
+
|
90
|
+
def call_on_#{name}( *args )
|
91
|
+
return unless @on_#{name}
|
92
|
+
@on_#{name}.call( *args )
|
93
|
+
end
|
94
|
+
|
95
|
+
public :on_#{name}
|
96
|
+
protected :has_on_#{name}?, :call_on_#{name}
|
97
|
+
EOF
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
operation :open,
|
102
|
+
:close,
|
103
|
+
:read,
|
104
|
+
:write,
|
105
|
+
:opendir,
|
106
|
+
:readdir,
|
107
|
+
:remove,
|
108
|
+
:stat,
|
109
|
+
:lstat,
|
110
|
+
:fstat,
|
111
|
+
:setstat,
|
112
|
+
:fsetstat,
|
113
|
+
:mkdir,
|
114
|
+
:rmdir,
|
115
|
+
:realpath
|
116
|
+
|
117
|
+
callback :status,
|
118
|
+
:handle,
|
119
|
+
:data,
|
120
|
+
:name,
|
121
|
+
:attrs
|
122
|
+
|
123
|
+
alias :open_raw :open
|
124
|
+
alias :stat_raw :stat
|
125
|
+
alias :lstat_raw :lstat
|
126
|
+
alias :fstat_raw :fstat
|
127
|
+
|
128
|
+
alias :close_handle :close
|
129
|
+
|
130
|
+
F_READ = 0x00000001
|
131
|
+
F_WRITE = 0x00000002
|
132
|
+
F_APPEND = 0x00000004
|
133
|
+
F_CREAT = 0x00000008
|
134
|
+
F_TRUNC = 0x00000010
|
135
|
+
F_EXCL = 0x00000020
|
136
|
+
|
137
|
+
# The open operation is special, since it protects the caller from the
|
138
|
+
# specific flags and options required by SFTP. Instead, the caller simply
|
139
|
+
# specifies a combination of IO flags, and an appropriate posix mode, and
|
140
|
+
# they are translated into the correct SFTP flags.
|
141
|
+
def open( id, path, flags, mode=0660 )
|
142
|
+
sftp_flags = case
|
143
|
+
when ( flags & IO::WRONLY ) != 0 then F_WRITE
|
144
|
+
when ( flags & IO::RDWR ) != 0 then F_READ | F_WRITE
|
145
|
+
when ( flags & IO::APPEND ) != 0 then F_APPEND
|
146
|
+
else F_READ
|
147
|
+
end
|
148
|
+
|
149
|
+
sftp_flags |= F_CREAT if ( flags & IO::CREAT ) != 0
|
150
|
+
sftp_flags |= F_TRUNC if ( flags & IO::TRUNC ) != 0
|
151
|
+
sftp_flags |= F_EXCL if ( flags & IO::EXCL ) != 0
|
152
|
+
|
153
|
+
attributes = @attr_factory.empty
|
154
|
+
attributes.permissions = mode
|
155
|
+
|
156
|
+
open_raw id, path, sftp_flags, attributes
|
157
|
+
end
|
158
|
+
|
159
|
+
# The stat operation is special, since later versions of the protocol add
|
160
|
+
# support for 'flags'. These flags are ignored in this version, but the
|
161
|
+
# parameter exists to allow a program written for one version of the
|
162
|
+
# protocol to work with later versions.
|
163
|
+
def stat( id, filename, flags=nil )
|
164
|
+
stat_raw id, filename
|
165
|
+
end
|
166
|
+
|
167
|
+
# The lstat operation is special, since later versions of the protocol add
|
168
|
+
# support for 'flags'. These flags are ignored in this version, but the
|
169
|
+
# parameter exists to allow a program written for one version of the
|
170
|
+
# protocol to work with later versions.
|
171
|
+
def lstat( id, filename, flags=nil )
|
172
|
+
lstat_raw id, filename
|
173
|
+
end
|
174
|
+
|
175
|
+
# The fstat operation is special, since later versions of the protocol add
|
176
|
+
# support for 'flags'. These flags are ignored in this version, but the
|
177
|
+
# parameter exists to allow a program written for one version of the
|
178
|
+
# protocol to work with later versions.
|
179
|
+
def fstat( id, handle, flags=nil )
|
180
|
+
fstat_raw id, handle
|
181
|
+
end
|
182
|
+
|
183
|
+
# Dispatches the given packet type to the appropriate handler method.
|
184
|
+
# If a new protocol version adds a new packet type, it should override
|
185
|
+
# this method, performing its own checking first, followed by calling
|
186
|
+
# +super+.
|
187
|
+
def dispatch( channel, type, content )
|
188
|
+
case type
|
189
|
+
when FXP_STATUS then do_status( channel, content )
|
190
|
+
when FXP_HANDLE then do_handle( channel, content )
|
191
|
+
when FXP_DATA then do_data( channel, content )
|
192
|
+
when FXP_NAME then do_name( channel, content )
|
193
|
+
when FXP_ATTRS then do_attrs( channel, content )
|
194
|
+
else
|
195
|
+
raise Net::SFTP::Exception,
|
196
|
+
"unsupported SFTP packet type #{type} (#{content.to_s.inspect})"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Used internally to handle +status+ packets. The +on_status+ callback is
|
201
|
+
# invoked, if registered, with the driver, id, and code.
|
202
|
+
def do_status( channel, content )
|
203
|
+
return unless has_on_status?
|
204
|
+
id = content.read_long
|
205
|
+
code = content.read_long
|
206
|
+
call_on_status( driver, id, code, nil, nil )
|
207
|
+
end
|
208
|
+
|
209
|
+
# Used internally to handle +handle+ packets. The +on_handle+ callback is
|
210
|
+
# invoked, if registered, with the driver, id, and handle.
|
211
|
+
def do_handle( channel, content )
|
212
|
+
return unless has_on_handle?
|
213
|
+
id = content.read_long
|
214
|
+
handle = content.read_string
|
215
|
+
call_on_handle( driver, id, handle )
|
216
|
+
end
|
217
|
+
|
218
|
+
# Used internally to handle +data+ packets. The +on_data+ callback is
|
219
|
+
# invoked, if registered, with the driver, id, and data (as a buffer).
|
220
|
+
def do_data( channel, content )
|
221
|
+
return unless has_on_data?
|
222
|
+
id = content.read_long
|
223
|
+
data = content.read_string
|
224
|
+
call_on_data( driver, id, data )
|
225
|
+
end
|
226
|
+
|
227
|
+
# Used internally to handle +name+ packets. The +on_name+ callback is
|
228
|
+
# invoked, if registered, with the driver, id, and array of items.
|
229
|
+
def do_name( channel, content )
|
230
|
+
return unless has_on_name?
|
231
|
+
id = content.read_long
|
232
|
+
items = []
|
233
|
+
content.read_long.times do
|
234
|
+
items.push( Name.new( content.read_string, content.read_string,
|
235
|
+
@attr_factory.from_buffer( content ) ) )
|
236
|
+
end
|
237
|
+
call_on_name( driver, id, items )
|
238
|
+
end
|
239
|
+
|
240
|
+
# Used internally to handle +attrs+ packets. The +on_attrs+ callback is
|
241
|
+
# invoked, if registered, with the driver, id, and attribute object.
|
242
|
+
def do_attrs( channel, content )
|
243
|
+
return unless has_on_attrs?
|
244
|
+
id = content.read_long
|
245
|
+
attrs = @attr_factory.from_buffer( content )
|
246
|
+
call_on_attrs( driver, id, attrs )
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
end ; end ; end ; end
|