hrr_rb_sftp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +25 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +135 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/demo/hrr_rb_sftp_server.rb +23 -0
  13. data/demo/instantiate_hrr_rb_sftp_server.rb +67 -0
  14. data/demo/spawn_hrr_rb_sftp_server.rb +66 -0
  15. data/hrr_rb_sftp.gemspec +26 -0
  16. data/lib/hrr_rb_sftp.rb +13 -0
  17. data/lib/hrr_rb_sftp/loggable.rb +41 -0
  18. data/lib/hrr_rb_sftp/protocol.rb +62 -0
  19. data/lib/hrr_rb_sftp/protocol/common.rb +10 -0
  20. data/lib/hrr_rb_sftp/protocol/common/data_type.rb +15 -0
  21. data/lib/hrr_rb_sftp/protocol/common/data_type/byte.rb +22 -0
  22. data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pair.rb +23 -0
  23. data/lib/hrr_rb_sftp/protocol/common/data_type/extension_pairs.rb +24 -0
  24. data/lib/hrr_rb_sftp/protocol/common/data_type/string.rb +24 -0
  25. data/lib/hrr_rb_sftp/protocol/common/data_type/uint32.rb +22 -0
  26. data/lib/hrr_rb_sftp/protocol/common/data_type/uint64.rb +22 -0
  27. data/lib/hrr_rb_sftp/protocol/common/packet.rb +11 -0
  28. data/lib/hrr_rb_sftp/protocol/common/packet/001_ssh_fxp_init.rb +18 -0
  29. data/lib/hrr_rb_sftp/protocol/common/packet/002_ssh_fxp_version.rb +19 -0
  30. data/lib/hrr_rb_sftp/protocol/common/packetable.rb +72 -0
  31. data/lib/hrr_rb_sftp/protocol/version1.rb +10 -0
  32. data/lib/hrr_rb_sftp/protocol/version1/data_type.rb +11 -0
  33. data/lib/hrr_rb_sftp/protocol/version1/data_type/attrs.rb +54 -0
  34. data/lib/hrr_rb_sftp/protocol/version1/packet.rb +29 -0
  35. data/lib/hrr_rb_sftp/protocol/version1/packet/003_ssh_fxp_open.rb +109 -0
  36. data/lib/hrr_rb_sftp/protocol/version1/packet/004_ssh_fxp_close.rb +44 -0
  37. data/lib/hrr_rb_sftp/protocol/version1/packet/005_ssh_fxp_read.rb +53 -0
  38. data/lib/hrr_rb_sftp/protocol/version1/packet/006_ssh_fxp_write.rb +46 -0
  39. data/lib/hrr_rb_sftp/protocol/version1/packet/007_ssh_fxp_lstat.rb +62 -0
  40. data/lib/hrr_rb_sftp/protocol/version1/packet/008_ssh_fxp_fstat.rb +48 -0
  41. data/lib/hrr_rb_sftp/protocol/version1/packet/009_ssh_fxp_setstat.rb +63 -0
  42. data/lib/hrr_rb_sftp/protocol/version1/packet/010_ssh_fxp_fsetstat.rb +48 -0
  43. data/lib/hrr_rb_sftp/protocol/version1/packet/011_ssh_fxp_opendir.rb +65 -0
  44. data/lib/hrr_rb_sftp/protocol/version1/packet/012_ssh_fxp_readdir.rb +134 -0
  45. data/lib/hrr_rb_sftp/protocol/version1/packet/013_ssh_fxp_remove.rb +57 -0
  46. data/lib/hrr_rb_sftp/protocol/version1/packet/014_ssh_fxp_mkdir.rb +57 -0
  47. data/lib/hrr_rb_sftp/protocol/version1/packet/015_ssh_fxp_rmdir.rb +73 -0
  48. data/lib/hrr_rb_sftp/protocol/version1/packet/016_ssh_fxp_realpath.rb +30 -0
  49. data/lib/hrr_rb_sftp/protocol/version1/packet/017_ssh_fxp_stat.rb +62 -0
  50. data/lib/hrr_rb_sftp/protocol/version1/packet/101_ssh_fxp_status.rb +29 -0
  51. data/lib/hrr_rb_sftp/protocol/version1/packet/102_ssh_fxp_handle.rb +19 -0
  52. data/lib/hrr_rb_sftp/protocol/version1/packet/103_ssh_fxp_data.rb +19 -0
  53. data/lib/hrr_rb_sftp/protocol/version1/packet/104_ssh_fxp_name.rb +33 -0
  54. data/lib/hrr_rb_sftp/protocol/version1/packet/105_ssh_fxp_attrs.rb +19 -0
  55. data/lib/hrr_rb_sftp/protocol/version2.rb +10 -0
  56. data/lib/hrr_rb_sftp/protocol/version2/data_type.rb +9 -0
  57. data/lib/hrr_rb_sftp/protocol/version2/packet.rb +11 -0
  58. data/lib/hrr_rb_sftp/protocol/version2/packet/018_ssh_fxp_rename.rb +70 -0
  59. data/lib/hrr_rb_sftp/protocol/version3.rb +10 -0
  60. data/lib/hrr_rb_sftp/protocol/version3/data_type.rb +9 -0
  61. data/lib/hrr_rb_sftp/protocol/version3/packet.rb +16 -0
  62. data/lib/hrr_rb_sftp/protocol/version3/packet/014_ssh_fxp_mkdir.rb +58 -0
  63. data/lib/hrr_rb_sftp/protocol/version3/packet/019_ssh_fxp_readlink.rb +57 -0
  64. data/lib/hrr_rb_sftp/protocol/version3/packet/020_ssh_fxp_symlink.rb +58 -0
  65. data/lib/hrr_rb_sftp/protocol/version3/packet/101_ssh_fxp_status.rb +31 -0
  66. data/lib/hrr_rb_sftp/protocol/version3/packet/200_ssh_fxp_extended.rb +34 -0
  67. data/lib/hrr_rb_sftp/protocol/version3/packet/201_ssh_fxp_extended_reply.rb +23 -0
  68. data/lib/hrr_rb_sftp/receiver.rb +22 -0
  69. data/lib/hrr_rb_sftp/sender.rb +13 -0
  70. data/lib/hrr_rb_sftp/server.rb +96 -0
  71. data/lib/hrr_rb_sftp/version.rb +3 -0
  72. metadata +114 -0
@@ -0,0 +1,63 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_SETSTAT
6
+ include Common::Packetable
7
+
8
+ TYPE = 9
9
+
10
+ FORMAT = [
11
+ [DataType::Byte, :"type" ],
12
+ [DataType::Uint32, :"request-id"],
13
+ [DataType::String, :"path" ],
14
+ [DataType::Attrs, :"attrs" ],
15
+ ]
16
+
17
+ def respond_to request
18
+ begin
19
+ path = request[:"path"]
20
+ attrs = request[:"attrs"]
21
+ FileUtils.chmod(attrs[:"permissions"], path) if attrs.has_key?(:"permissions")
22
+ File.utime(attrs[:"atime"], attrs[:"mtime"], path) if attrs.has_key?(:"atime") && attrs.has_key?(:"mtime")
23
+ FileUtils.chown(attrs[:"uid"], attrs[:"gid"], path) if attrs.has_key?(:"uid") && attrs.has_key?(:"gid")
24
+ File.truncate(path, attrs[:"size"]) if attrs.has_key?(:"size")
25
+ {
26
+ :"type" => SSH_FXP_STATUS::TYPE,
27
+ :"request-id" => request[:"request-id"],
28
+ :"code" => SSH_FXP_STATUS::SSH_FX_OK,
29
+ :"error message" => "Success",
30
+ :"language tag" => "",
31
+ }
32
+ rescue Errno::ENOENT
33
+ {
34
+ :"type" => SSH_FXP_STATUS::TYPE,
35
+ :"request-id" => request[:"request-id"],
36
+ :"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
37
+ :"error message" => "No such file or directory",
38
+ :"language tag" => "",
39
+ }
40
+ rescue Errno::EACCES
41
+ {
42
+ :"type" => SSH_FXP_STATUS::TYPE,
43
+ :"request-id" => request[:"request-id"],
44
+ :"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
45
+ :"error message" => "Permission denied",
46
+ :"language tag" => "",
47
+ }
48
+ rescue => e
49
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
50
+ {
51
+ :"type" => SSH_FXP_STATUS::TYPE,
52
+ :"request-id" => request[:"request-id"],
53
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
54
+ :"error message" => e.message,
55
+ :"language tag" => "",
56
+ }
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,48 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_FSETSTAT
6
+ include Common::Packetable
7
+
8
+ TYPE = 10
9
+
10
+ FORMAT = [
11
+ [DataType::Byte, :"type" ],
12
+ [DataType::Uint32, :"request-id"],
13
+ [DataType::String, :"handle" ],
14
+ [DataType::Attrs, :"attrs" ],
15
+ ]
16
+
17
+ def respond_to request
18
+ begin
19
+ raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
20
+ file = @handles[request[:"handle"]]
21
+ attrs = request[:"attrs"]
22
+ file.chmod(attrs[:"permissions"]) if attrs.has_key?(:"permissions")
23
+ File.utime(attrs[:"atime"], attrs[:"mtime"], file.path) if attrs.has_key?(:"atime") && attrs.has_key?(:"mtime")
24
+ file.chown(attrs[:"uid"], attrs[:"gid"]) if attrs.has_key?(:"uid") && attrs.has_key?(:"gid")
25
+ file.truncate(attrs[:"size"]) if attrs.has_key?(:"size")
26
+ {
27
+ :"type" => SSH_FXP_STATUS::TYPE,
28
+ :"request-id" => request[:"request-id"],
29
+ :"code" => SSH_FXP_STATUS::SSH_FX_OK,
30
+ :"error message" => "Success",
31
+ :"language tag" => "",
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
@@ -0,0 +1,65 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_OPENDIR
6
+ include Common::Packetable
7
+
8
+ TYPE = 11
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
+ dir = ::Dir.open(request[:"path"])
19
+ handle = dir.object_id.to_s(16)
20
+ @handles[handle] = dir
21
+ {
22
+ :"type" => SSH_FXP_HANDLE::TYPE,
23
+ :"request-id" => request[:"request-id"],
24
+ :"handle" => handle,
25
+ }
26
+ rescue Errno::ENOENT
27
+ {
28
+ :"type" => SSH_FXP_STATUS::TYPE,
29
+ :"request-id" => request[:"request-id"],
30
+ :"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
31
+ :"error message" => "No such file or directory",
32
+ :"language tag" => "",
33
+ }
34
+ rescue Errno::EACCES
35
+ {
36
+ :"type" => SSH_FXP_STATUS::TYPE,
37
+ :"request-id" => request[:"request-id"],
38
+ :"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
39
+ :"error message" => "Permission denied",
40
+ :"language tag" => "",
41
+ }
42
+ rescue Errno::ENOTDIR
43
+ {
44
+ :"type" => SSH_FXP_STATUS::TYPE,
45
+ :"request-id" => request[:"request-id"],
46
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
47
+ :"error message" => "Not a directory",
48
+ :"language tag" => "",
49
+ }
50
+ rescue => e
51
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
52
+ {
53
+ :"type" => SSH_FXP_STATUS::TYPE,
54
+ :"request-id" => request[:"request-id"],
55
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
56
+ :"error message" => e.message,
57
+ :"language tag" => "",
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,134 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_READDIR
6
+ include Common::Packetable
7
+
8
+ TYPE = 12
9
+
10
+ FORMAT = [
11
+ [DataType::Byte, :"type" ],
12
+ [DataType::Uint32, :"request-id"],
13
+ [DataType::String, :"handle" ],
14
+ ]
15
+
16
+ def longname_permissions stat
17
+ s = ::String.new
18
+ s += case stat.mode & 0170000
19
+ when 0140000 then "s"
20
+ when 0120000 then "l"
21
+ when 0100000 then "-"
22
+ when 0060000 then "b"
23
+ when 0040000 then "d"
24
+ when 0020000 then "c"
25
+ when 0010000 then "p"
26
+ else "?"
27
+ end
28
+ s += (stat.mode & 0400) == 0400 ? "r" : "-"
29
+ s += (stat.mode & 0200) == 0200 ? "w" : "-"
30
+ s += (stat.mode & 0100) == 0100 ? "x" : "-"
31
+ s += (stat.mode & 0040) == 0040 ? "r" : "-"
32
+ s += (stat.mode & 0020) == 0020 ? "w" : "-"
33
+ s += (stat.mode & 0010) == 0010 ? "x" : "-"
34
+ s += (stat.mode & 0004) == 0004 ? "r" : "-"
35
+ s += (stat.mode & 0002) == 0002 ? "w" : "-"
36
+ s += (stat.mode & 0001) == 0001 ? "x" : "-"
37
+ s
38
+ end
39
+
40
+ def longname_nlink stat
41
+ stat.nlink.to_s.rjust(3, " ")
42
+ end
43
+
44
+ def longname_user stat
45
+ (::Etc.getpwuid(stat.uid).name rescue stat.uid).to_s.ljust(8, " ")
46
+ end
47
+
48
+ def longname_group stat
49
+ (::Etc.getgrgid(stat.gid).name rescue stat.gid).to_s.ljust(8, " ")
50
+ end
51
+
52
+ def longname_size stat
53
+ stat.size.to_s.rjust(8, " ")
54
+ end
55
+
56
+ def longname_mtime stat
57
+ if stat.mtime.year == ::Time.now.year
58
+ stat.mtime.strftime "%b %e %H:%M"
59
+ else
60
+ stat.mtime.strftime "%b %e %Y"
61
+ end
62
+ end
63
+
64
+ def longname dir, entry
65
+ stat = ::File.lstat(::File.join(dir.path, entry))
66
+ [
67
+ longname_permissions(stat),
68
+ longname_nlink(stat),
69
+ longname_user(stat),
70
+ longname_group(stat),
71
+ longname_size(stat),
72
+ longname_mtime(stat),
73
+ entry,
74
+ ].join(" ")
75
+ end
76
+
77
+ def attrs dir, entry
78
+ stat = ::File.lstat(::File.join(dir.path, entry))
79
+ attrs = ::Hash.new
80
+ attrs[:"size"] = stat.size if stat.size
81
+ attrs[:"uid"] = stat.uid if stat.uid
82
+ attrs[:"gid"] = stat.gid if stat.gid
83
+ attrs[:"permissions"] = stat.mode if stat.mode
84
+ attrs[:"atime"] = stat.atime.to_i if stat.atime
85
+ attrs[:"mtime"] = stat.mtime.to_i if stat.mtime
86
+ attrs
87
+ end
88
+
89
+ def respond_to request
90
+ begin
91
+ raise "Specified handle does not exist" unless @handles.has_key?(request[:"handle"])
92
+ dir = @handles[request[:"handle"]]
93
+ raise "Specified handle is not directory" unless dir.instance_of?(::Dir)
94
+ entries = ::Array.new
95
+ while entry = dir.read
96
+ entries.push entry
97
+ end
98
+ unless entries.empty?
99
+ response = {
100
+ :"type" => SSH_FXP_NAME::TYPE,
101
+ :"request-id" => request[:"request-id"],
102
+ :"count" => entries.size,
103
+ }
104
+ entries.each.with_index do |entry, idx|
105
+ response[:"filename[#{idx}]"] = entry
106
+ response[:"longname[#{idx}]"] = longname(dir, entry)
107
+ response[:"attrs[#{idx}]"] = attrs(dir, entry)
108
+ end
109
+ response
110
+ else
111
+ {
112
+ :"type" => SSH_FXP_STATUS::TYPE,
113
+ :"request-id" => request[:"request-id"],
114
+ :"code" => SSH_FXP_STATUS::SSH_FX_EOF,
115
+ :"error message" => "End of file",
116
+ :"language tag" => "",
117
+ }
118
+ end
119
+ rescue => e
120
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
121
+ {
122
+ :"type" => SSH_FXP_STATUS::TYPE,
123
+ :"request-id" => request[:"request-id"],
124
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
125
+ :"error message" => e.message,
126
+ :"language tag" => "",
127
+ }
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,57 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_REMOVE
6
+ include Common::Packetable
7
+
8
+ TYPE = 13
9
+
10
+ FORMAT = [
11
+ [DataType::Byte, :"type" ],
12
+ [DataType::Uint32, :"request-id"],
13
+ [DataType::String, :"filename" ],
14
+ ]
15
+
16
+ def respond_to request
17
+ begin
18
+ File.delete(request[:"filename"])
19
+ {
20
+ :"type" => SSH_FXP_STATUS::TYPE,
21
+ :"request-id" => request[:"request-id"],
22
+ :"code" => SSH_FXP_STATUS::SSH_FX_OK,
23
+ :"error message" => "Success",
24
+ :"language tag" => "",
25
+ }
26
+ rescue Errno::ENOENT
27
+ {
28
+ :"type" => SSH_FXP_STATUS::TYPE,
29
+ :"request-id" => request[:"request-id"],
30
+ :"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
31
+ :"error message" => "No such file or directory",
32
+ :"language tag" => "",
33
+ }
34
+ rescue Errno::EACCES
35
+ {
36
+ :"type" => SSH_FXP_STATUS::TYPE,
37
+ :"request-id" => request[:"request-id"],
38
+ :"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
39
+ :"error message" => "Permission denied",
40
+ :"language tag" => "",
41
+ }
42
+ rescue => e
43
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
44
+ {
45
+ :"type" => SSH_FXP_STATUS::TYPE,
46
+ :"request-id" => request[:"request-id"],
47
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
48
+ :"error message" => e.message,
49
+ :"language tag" => "",
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_MKDIR
6
+ include Common::Packetable
7
+
8
+ TYPE = 14
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
+ Dir.mkdir request[:"path"]
19
+ {
20
+ :"type" => SSH_FXP_STATUS::TYPE,
21
+ :"request-id" => request[:"request-id"],
22
+ :"code" => SSH_FXP_STATUS::SSH_FX_OK,
23
+ :"error message" => "Success",
24
+ :"language tag" => "",
25
+ }
26
+ rescue Errno::EACCES
27
+ {
28
+ :"type" => SSH_FXP_STATUS::TYPE,
29
+ :"request-id" => request[:"request-id"],
30
+ :"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
31
+ :"error message" => "Permission denied",
32
+ :"language tag" => "",
33
+ }
34
+ rescue Errno::EEXIST
35
+ {
36
+ :"type" => SSH_FXP_STATUS::TYPE,
37
+ :"request-id" => request[:"request-id"],
38
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
39
+ :"error message" => "File exists",
40
+ :"language tag" => "",
41
+ }
42
+ rescue => e
43
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
44
+ {
45
+ :"type" => SSH_FXP_STATUS::TYPE,
46
+ :"request-id" => request[:"request-id"],
47
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
48
+ :"error message" => e.message,
49
+ :"language tag" => "",
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,73 @@
1
+ module HrrRbSftp
2
+ class Protocol
3
+ class Version1
4
+ module Packet
5
+ class SSH_FXP_RMDIR
6
+ include Common::Packetable
7
+
8
+ TYPE = 15
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
+ Dir.rmdir request[:"path"]
19
+ {
20
+ :"type" => SSH_FXP_STATUS::TYPE,
21
+ :"request-id" => request[:"request-id"],
22
+ :"code" => SSH_FXP_STATUS::SSH_FX_OK,
23
+ :"error message" => "Success",
24
+ :"language tag" => "",
25
+ }
26
+ rescue Errno::ENOENT
27
+ {
28
+ :"type" => SSH_FXP_STATUS::TYPE,
29
+ :"request-id" => request[:"request-id"],
30
+ :"code" => SSH_FXP_STATUS::SSH_FX_NO_SUCH_FILE,
31
+ :"error message" => "No such file or directory",
32
+ :"language tag" => "",
33
+ }
34
+ rescue Errno::EACCES
35
+ {
36
+ :"type" => SSH_FXP_STATUS::TYPE,
37
+ :"request-id" => request[:"request-id"],
38
+ :"code" => SSH_FXP_STATUS::SSH_FX_PERMISSION_DENIED,
39
+ :"error message" => "Permission denied",
40
+ :"language tag" => "",
41
+ }
42
+ rescue Errno::ENOTDIR
43
+ {
44
+ :"type" => SSH_FXP_STATUS::TYPE,
45
+ :"request-id" => request[:"request-id"],
46
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
47
+ :"error message" => "Not a directory",
48
+ :"language tag" => "",
49
+ }
50
+ rescue Errno::ENOTEMPTY
51
+ {
52
+ :"type" => SSH_FXP_STATUS::TYPE,
53
+ :"request-id" => request[:"request-id"],
54
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
55
+ :"error message" => "Directory not empty",
56
+ :"language tag" => "",
57
+ }
58
+ rescue => e
59
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
60
+ {
61
+ :"type" => SSH_FXP_STATUS::TYPE,
62
+ :"request-id" => request[:"request-id"],
63
+ :"code" => SSH_FXP_STATUS::SSH_FX_FAILURE,
64
+ :"error message" => e.message,
65
+ :"language tag" => "",
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end