hrr_rb_sftp 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/.travis.yml +25 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +135 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/demo/hrr_rb_sftp_server.rb +23 -0
- data/demo/instantiate_hrr_rb_sftp_server.rb +67 -0
- data/demo/spawn_hrr_rb_sftp_server.rb +66 -0
- data/hrr_rb_sftp.gemspec +26 -0
- data/lib/hrr_rb_sftp.rb +13 -0
- data/lib/hrr_rb_sftp/loggable.rb +41 -0
- data/lib/hrr_rb_sftp/protocol.rb +62 -0
- data/lib/hrr_rb_sftp/protocol/common.rb +10 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type.rb +15 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/byte.rb +22 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pair.rb +23 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pairs.rb +24 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/string.rb +24 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/uint32.rb +22 -0
- data/lib/hrr_rb_sftp/protocol/common/data_type/uint64.rb +22 -0
- data/lib/hrr_rb_sftp/protocol/common/packet.rb +11 -0
- data/lib/hrr_rb_sftp/protocol/common/packet/001_ssh_fxp_init.rb +18 -0
- data/lib/hrr_rb_sftp/protocol/common/packet/002_ssh_fxp_version.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/common/packetable.rb +72 -0
- data/lib/hrr_rb_sftp/protocol/version1.rb +10 -0
- data/lib/hrr_rb_sftp/protocol/version1/data_type.rb +11 -0
- data/lib/hrr_rb_sftp/protocol/version1/data_type/attrs.rb +54 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet.rb +29 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/003_ssh_fxp_open.rb +109 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/004_ssh_fxp_close.rb +44 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/005_ssh_fxp_read.rb +53 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/006_ssh_fxp_write.rb +46 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/007_ssh_fxp_lstat.rb +62 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/008_ssh_fxp_fstat.rb +48 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/009_ssh_fxp_setstat.rb +63 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/010_ssh_fxp_fsetstat.rb +48 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/011_ssh_fxp_opendir.rb +65 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/012_ssh_fxp_readdir.rb +134 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/013_ssh_fxp_remove.rb +57 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/014_ssh_fxp_mkdir.rb +57 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/015_ssh_fxp_rmdir.rb +73 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/016_ssh_fxp_realpath.rb +30 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/017_ssh_fxp_stat.rb +62 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/101_ssh_fxp_status.rb +29 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/102_ssh_fxp_handle.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/103_ssh_fxp_data.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/104_ssh_fxp_name.rb +33 -0
- data/lib/hrr_rb_sftp/protocol/version1/packet/105_ssh_fxp_attrs.rb +19 -0
- data/lib/hrr_rb_sftp/protocol/version2.rb +10 -0
- data/lib/hrr_rb_sftp/protocol/version2/data_type.rb +9 -0
- data/lib/hrr_rb_sftp/protocol/version2/packet.rb +11 -0
- data/lib/hrr_rb_sftp/protocol/version2/packet/018_ssh_fxp_rename.rb +70 -0
- data/lib/hrr_rb_sftp/protocol/version3.rb +10 -0
- data/lib/hrr_rb_sftp/protocol/version3/data_type.rb +9 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet.rb +16 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/014_ssh_fxp_mkdir.rb +58 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/019_ssh_fxp_readlink.rb +57 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/020_ssh_fxp_symlink.rb +58 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/101_ssh_fxp_status.rb +31 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/200_ssh_fxp_extended.rb +34 -0
- data/lib/hrr_rb_sftp/protocol/version3/packet/201_ssh_fxp_extended_reply.rb +23 -0
- data/lib/hrr_rb_sftp/receiver.rb +22 -0
- data/lib/hrr_rb_sftp/sender.rb +13 -0
- data/lib/hrr_rb_sftp/server.rb +96 -0
- data/lib/hrr_rb_sftp/version.rb +3 -0
- metadata +114 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module DataType
|
5
|
+
class Attrs
|
6
|
+
SSH_FILEXFER_ATTR_SIZE = 0x00000001
|
7
|
+
SSH_FILEXFER_ATTR_UIDGID = 0x00000002
|
8
|
+
SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004
|
9
|
+
SSH_FILEXFER_ATTR_ACMODTIME = 0x00000008
|
10
|
+
SSH_FILEXFER_ATTR_EXTENDED = 0x80000000
|
11
|
+
|
12
|
+
def self.encode arg
|
13
|
+
unless arg.kind_of? ::Hash
|
14
|
+
raise ArgumentError, "must be a kind of Hash, but got #{arg.inspect}"
|
15
|
+
end
|
16
|
+
|
17
|
+
flags = 0
|
18
|
+
flags |= SSH_FILEXFER_ATTR_SIZE if arg.has_key?(:"size")
|
19
|
+
flags |= SSH_FILEXFER_ATTR_UIDGID if arg.has_key?(:"uid") && arg.has_key?(:"gid")
|
20
|
+
flags |= SSH_FILEXFER_ATTR_PERMISSIONS if arg.has_key?(:"permissions")
|
21
|
+
flags |= SSH_FILEXFER_ATTR_ACMODTIME if arg.has_key?(:"atime") && arg.has_key?(:"mtime")
|
22
|
+
flags |= SSH_FILEXFER_ATTR_EXTENDED if arg.has_key?(:"extensions")
|
23
|
+
|
24
|
+
payload = DataType::Uint32.encode flags
|
25
|
+
payload += DataType::Uint64.encode arg[:"size"] unless (flags & SSH_FILEXFER_ATTR_SIZE).zero?
|
26
|
+
payload += DataType::Uint32.encode arg[:"uid"] unless (flags & SSH_FILEXFER_ATTR_UIDGID).zero?
|
27
|
+
payload += DataType::Uint32.encode arg[:"gid"] unless (flags & SSH_FILEXFER_ATTR_UIDGID).zero?
|
28
|
+
payload += DataType::Uint32.encode arg[:"permissions"] unless (flags & SSH_FILEXFER_ATTR_PERMISSIONS).zero?
|
29
|
+
payload += DataType::Uint32.encode arg[:"atime"] unless (flags & SSH_FILEXFER_ATTR_ACMODTIME).zero?
|
30
|
+
payload += DataType::Uint32.encode arg[:"mtime"] unless (flags & SSH_FILEXFER_ATTR_ACMODTIME).zero?
|
31
|
+
payload += DataType::Uint32.encode arg[:"extensions"].size unless (flags & SSH_FILEXFER_ATTR_EXTENDED).zero?
|
32
|
+
payload += DataType::ExtensionPairs.encode arg[:"extensions"] unless (flags & SSH_FILEXFER_ATTR_EXTENDED).zero?
|
33
|
+
payload
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.decode io
|
37
|
+
attrs = Hash.new
|
38
|
+
flags = DataType::Uint32.decode(io)
|
39
|
+
attrs[:"size"] = DataType::Uint64.decode(io) unless (flags & SSH_FILEXFER_ATTR_SIZE).zero?
|
40
|
+
attrs[:"uid"] = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_UIDGID).zero?
|
41
|
+
attrs[:"gid"] = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_UIDGID).zero?
|
42
|
+
attrs[:"permissions"] = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_PERMISSIONS).zero?
|
43
|
+
attrs[:"atime"] = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_ACMODTIME).zero?
|
44
|
+
attrs[:"mtime"] = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_ACMODTIME).zero?
|
45
|
+
extended_count = DataType::Uint32.decode(io) unless (flags & SSH_FILEXFER_ATTR_EXTENDED).zero?
|
46
|
+
attrs[:"extensions"] = Array.new(extended_count){DataType::ExtensionPair.decode(io)} unless (flags & SSH_FILEXFER_ATTR_EXTENDED).zero?
|
47
|
+
attrs
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require "hrr_rb_sftp/protocol/version1/packet/003_ssh_fxp_open"
|
11
|
+
require "hrr_rb_sftp/protocol/version1/packet/004_ssh_fxp_close"
|
12
|
+
require "hrr_rb_sftp/protocol/version1/packet/005_ssh_fxp_read"
|
13
|
+
require "hrr_rb_sftp/protocol/version1/packet/006_ssh_fxp_write"
|
14
|
+
require "hrr_rb_sftp/protocol/version1/packet/007_ssh_fxp_lstat"
|
15
|
+
require "hrr_rb_sftp/protocol/version1/packet/008_ssh_fxp_fstat"
|
16
|
+
require "hrr_rb_sftp/protocol/version1/packet/009_ssh_fxp_setstat"
|
17
|
+
require "hrr_rb_sftp/protocol/version1/packet/010_ssh_fxp_fsetstat"
|
18
|
+
require "hrr_rb_sftp/protocol/version1/packet/011_ssh_fxp_opendir"
|
19
|
+
require "hrr_rb_sftp/protocol/version1/packet/012_ssh_fxp_readdir"
|
20
|
+
require "hrr_rb_sftp/protocol/version1/packet/013_ssh_fxp_remove"
|
21
|
+
require "hrr_rb_sftp/protocol/version1/packet/014_ssh_fxp_mkdir"
|
22
|
+
require "hrr_rb_sftp/protocol/version1/packet/015_ssh_fxp_rmdir"
|
23
|
+
require "hrr_rb_sftp/protocol/version1/packet/016_ssh_fxp_realpath"
|
24
|
+
require "hrr_rb_sftp/protocol/version1/packet/017_ssh_fxp_stat"
|
25
|
+
require "hrr_rb_sftp/protocol/version1/packet/101_ssh_fxp_status"
|
26
|
+
require "hrr_rb_sftp/protocol/version1/packet/102_ssh_fxp_handle"
|
27
|
+
require "hrr_rb_sftp/protocol/version1/packet/103_ssh_fxp_data"
|
28
|
+
require "hrr_rb_sftp/protocol/version1/packet/104_ssh_fxp_name"
|
29
|
+
require "hrr_rb_sftp/protocol/version1/packet/105_ssh_fxp_attrs"
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_OPEN
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 3
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"filename" ],
|
14
|
+
[DataType::Uint32, :"pflags" ],
|
15
|
+
[DataType::Attrs, :"attrs" ],
|
16
|
+
]
|
17
|
+
|
18
|
+
SSH_FXF_READ = 0x00000001
|
19
|
+
SSH_FXF_WRITE = 0x00000002
|
20
|
+
SSH_FXF_APPEND = 0x00000004
|
21
|
+
SSH_FXF_CREAT = 0x00000008
|
22
|
+
SSH_FXF_TRUNC = 0x00000010
|
23
|
+
SSH_FXF_EXCL = 0x00000020
|
24
|
+
|
25
|
+
class Error < StandardError
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_pflags_to_flags pflags
|
29
|
+
flags = 0
|
30
|
+
if ((pflags & SSH_FXF_READ) == SSH_FXF_READ) && ((pflags & SSH_FXF_WRITE) == SSH_FXF_WRITE)
|
31
|
+
flags |= ::File::RDWR
|
32
|
+
elsif (pflags & SSH_FXF_READ) == SSH_FXF_READ
|
33
|
+
flags |= ::File::RDONLY
|
34
|
+
elsif (pflags & SSH_FXF_WRITE) == SSH_FXF_WRITE
|
35
|
+
flags |= ::File::WRONLY
|
36
|
+
else
|
37
|
+
raise Error, "At least SSH_FXF_READ or SSH_FXF_READ must be specified"
|
38
|
+
end
|
39
|
+
if (pflags & SSH_FXF_APPEND) == SSH_FXF_APPEND
|
40
|
+
flags |= ::File::APPEND
|
41
|
+
end
|
42
|
+
if (pflags & SSH_FXF_CREAT) == SSH_FXF_CREAT
|
43
|
+
flags |= ::File::CREAT
|
44
|
+
flags |= ::File::TRUNC if (pflags & SSH_FXF_TRUNC) == SSH_FXF_TRUNC
|
45
|
+
flags |= ::File::EXCL if (pflags & SSH_FXF_EXCL ) == SSH_FXF_EXCL
|
46
|
+
elsif (pflags & SSH_FXF_TRUNC) == SSH_FXF_TRUNC
|
47
|
+
raise Error, "SSH_FXF_CREAT MUST also be specified when SSH_FXF_TRUNC is specified"
|
48
|
+
elsif (pflags & SSH_FXF_EXCL) == SSH_FXF_EXCL
|
49
|
+
raise Error, "SSH_FXF_CREAT MUST also be specified when SSH_FXF_EXCL is specified"
|
50
|
+
end
|
51
|
+
flags |= ::File::BINARY
|
52
|
+
flags
|
53
|
+
end
|
54
|
+
|
55
|
+
def respond_to request
|
56
|
+
begin
|
57
|
+
flags = convert_pflags_to_flags request[:"pflags"]
|
58
|
+
args = [request[:"filename"], flags]
|
59
|
+
if request[:"attrs"].has_key?(:"permissions")
|
60
|
+
args.push request[:"attrs"][:"permissions"]
|
61
|
+
end
|
62
|
+
file = ::File.open(*args)
|
63
|
+
handle = file.object_id.to_s(16)
|
64
|
+
@handles[handle] = file
|
65
|
+
{
|
66
|
+
:"type" => SSH_FXP_HANDLE::TYPE,
|
67
|
+
:"request-id" => request[:"request-id"],
|
68
|
+
:"handle" => handle,
|
69
|
+
}
|
70
|
+
rescue Error => e
|
71
|
+
{
|
72
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
73
|
+
:"request-id" => request[:"request-id"],
|
74
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
75
|
+
:"error message" => e.message,
|
76
|
+
:"language tag" => "",
|
77
|
+
}
|
78
|
+
rescue Errno::ENOENT
|
79
|
+
{
|
80
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
81
|
+
:"request-id" => request[:"request-id"],
|
82
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
|
83
|
+
:"error message" => "No such file or directory",
|
84
|
+
:"language tag" => "",
|
85
|
+
}
|
86
|
+
rescue Errno::EACCES
|
87
|
+
{
|
88
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
89
|
+
:"request-id" => request[:"request-id"],
|
90
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
|
91
|
+
:"error message" => "Permission denied",
|
92
|
+
:"language tag" => "",
|
93
|
+
}
|
94
|
+
rescue => e
|
95
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
96
|
+
{
|
97
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
98
|
+
:"request-id" => request[:"request-id"],
|
99
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
100
|
+
:"error message" => e.message,
|
101
|
+
:"language tag" => "",
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_CLOSE
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 4
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"handle" ],
|
14
|
+
]
|
15
|
+
|
16
|
+
def respond_to request
|
17
|
+
begin
|
18
|
+
raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
|
19
|
+
handle = request[:"handle"]
|
20
|
+
@handles[handle].close rescue nil
|
21
|
+
@handles.delete(handle)
|
22
|
+
{
|
23
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
24
|
+
:"request-id" => request[:"request-id"],
|
25
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_OK,
|
26
|
+
:"error message" => "Success",
|
27
|
+
:"language tag" => "",
|
28
|
+
}
|
29
|
+
rescue => e
|
30
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
31
|
+
{
|
32
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
33
|
+
:"request-id" => request[:"request-id"],
|
34
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
35
|
+
:"error message" => e.message,
|
36
|
+
:"language tag" => "",
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_READ
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 5
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"handle" ],
|
14
|
+
[DataType::Uint64, :"offset" ],
|
15
|
+
[DataType::Uint32, :"len" ],
|
16
|
+
]
|
17
|
+
|
18
|
+
def respond_to request
|
19
|
+
begin
|
20
|
+
raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
|
21
|
+
file = @handles[request[:"handle"]]
|
22
|
+
file.pos = request[:"offset"]
|
23
|
+
unless file.eof?
|
24
|
+
{
|
25
|
+
:"type" => SSH_FXP_DATA::TYPE,
|
26
|
+
:"request-id" => request[:"request-id"],
|
27
|
+
:"data" => file.read(request[:"len"]),
|
28
|
+
}
|
29
|
+
else
|
30
|
+
{
|
31
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
32
|
+
:"request-id" => request[:"request-id"],
|
33
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_EOF,
|
34
|
+
:"error message" => "End of file",
|
35
|
+
:"language tag" => "",
|
36
|
+
}
|
37
|
+
end
|
38
|
+
rescue => e
|
39
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
40
|
+
{
|
41
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
42
|
+
:"request-id" => request[:"request-id"],
|
43
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
44
|
+
:"error message" => e.message,
|
45
|
+
:"language tag" => "",
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_WRITE
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 6
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"handle" ],
|
14
|
+
[DataType::Uint64, :"offset" ],
|
15
|
+
[DataType::String, :"data" ],
|
16
|
+
]
|
17
|
+
|
18
|
+
def respond_to request
|
19
|
+
begin
|
20
|
+
raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
|
21
|
+
file = @handles[request[:"handle"]]
|
22
|
+
file.pos = request[:"offset"]
|
23
|
+
file.write request[:"data"]
|
24
|
+
{
|
25
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
26
|
+
:"request-id" => request[:"request-id"],
|
27
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_OK,
|
28
|
+
:"error message" => "Success",
|
29
|
+
:"language tag" => "",
|
30
|
+
}
|
31
|
+
rescue => e
|
32
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
33
|
+
{
|
34
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
35
|
+
:"request-id" => request[:"request-id"],
|
36
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
37
|
+
:"error message" => e.message,
|
38
|
+
:"language tag" => "",
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_LSTAT
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 7
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"path" ],
|
14
|
+
]
|
15
|
+
|
16
|
+
def respond_to request
|
17
|
+
begin
|
18
|
+
stat = File.lstat(request[:"path"])
|
19
|
+
attrs = Hash.new
|
20
|
+
attrs[:"size"] = stat.size if stat.size
|
21
|
+
attrs[:"uid"] = stat.uid if stat.uid
|
22
|
+
attrs[:"gid"] = stat.gid if stat.gid
|
23
|
+
attrs[:"permissions"] = stat.mode if stat.mode
|
24
|
+
attrs[:"atime"] = stat.atime.to_i if stat.atime
|
25
|
+
attrs[:"mtime"] = stat.mtime.to_i if stat.mtime
|
26
|
+
{
|
27
|
+
:"type" => SSH_FXP_ATTRS::TYPE,
|
28
|
+
:"request-id" => request[:"request-id"],
|
29
|
+
:"attrs" => attrs,
|
30
|
+
}
|
31
|
+
rescue Errno::ENOENT
|
32
|
+
{
|
33
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
34
|
+
:"request-id" => request[:"request-id"],
|
35
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
|
36
|
+
:"error message" => "No such file or directory",
|
37
|
+
:"language tag" => "",
|
38
|
+
}
|
39
|
+
rescue Errno::EACCES
|
40
|
+
{
|
41
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
42
|
+
:"request-id" => request[:"request-id"],
|
43
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
|
44
|
+
:"error message" => "Permission denied",
|
45
|
+
:"language tag" => "",
|
46
|
+
}
|
47
|
+
rescue => e
|
48
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
49
|
+
{
|
50
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
51
|
+
:"request-id" => request[:"request-id"],
|
52
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
53
|
+
:"error message" => e.message,
|
54
|
+
:"language tag" => "",
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module HrrRbSftp
|
2
|
+
class Protocol
|
3
|
+
class Version1
|
4
|
+
module Packet
|
5
|
+
class SSH_FXP_FSTAT
|
6
|
+
include Common::Packetable
|
7
|
+
|
8
|
+
TYPE = 8
|
9
|
+
|
10
|
+
FORMAT = [
|
11
|
+
[DataType::Byte, :"type" ],
|
12
|
+
[DataType::Uint32, :"request-id"],
|
13
|
+
[DataType::String, :"handle" ],
|
14
|
+
]
|
15
|
+
|
16
|
+
def respond_to request
|
17
|
+
begin
|
18
|
+
raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
|
19
|
+
file = @handles[request[:"handle"]]
|
20
|
+
stat = file.stat
|
21
|
+
attrs = Hash.new
|
22
|
+
attrs[:"size"] = stat.size if stat.size
|
23
|
+
attrs[:"uid"] = stat.uid if stat.uid
|
24
|
+
attrs[:"gid"] = stat.gid if stat.gid
|
25
|
+
attrs[:"permissions"] = stat.mode if stat.mode
|
26
|
+
attrs[:"atime"] = stat.atime.to_i if stat.atime
|
27
|
+
attrs[:"mtime"] = stat.mtime.to_i if stat.mtime
|
28
|
+
{
|
29
|
+
:"type" => SSH_FXP_ATTRS::TYPE,
|
30
|
+
:"request-id" => request[:"request-id"],
|
31
|
+
:"attrs" => attrs,
|
32
|
+
}
|
33
|
+
rescue => e
|
34
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
35
|
+
{
|
36
|
+
:"type" => SSH_FXP_STATUS::TYPE,
|
37
|
+
:"request-id" => request[:"request-id"],
|
38
|
+
:"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
|
39
|
+
:"error message" => e.message,
|
40
|
+
:"language tag" => "",
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|