[svn-upgrade] new version libnet-sftp-foreign-perl (1.65+dfsg)
Nicholas Bamber
12 years ago
0 | 0 | Revision history for Net::SFTP::Foreign |
1 | 1 | |
2 | 1.65 May 17, 2011 | |
3 | - die_on_error was broken | |
4 | ||
5 | 1.64 May 09, 2011 | |
6 | - release as stable | |
7 | - document the write_delay and read_ahead options | |
8 | - minor doc corrections | |
9 | ||
10 | 1.63_10 Apr 13, 2011 | |
11 | - workaround bug in perl 5.6 calling STORE in a tied | |
12 | filehandle | |
13 | - solve "not enough arguments for grep" when using an old | |
14 | version of Scalar::Util | |
15 | ||
16 | 1.63_09 Apr 12, 2011 | |
17 | - an error in the handler accessors was adding and useless | |
18 | wrapping layer | |
19 | ||
20 | 1.63_08 Jan 22, 2011 | |
21 | - bad method call inside mkpath corrected (bug report and | |
22 | solution by Adam Pingel) | |
23 | ||
24 | 1.63_07 Jan 20, 2011 | |
25 | - do not override PreferredAuthentication when explicitly set | |
26 | by the user (bug report and solution by Ave Wrigley) | |
27 | ||
28 | 1.63_06 Dec 10, 2010 | |
29 | - redirect_stderr_to_tty was redirecting to the wrong side of | |
30 | the tty (bug report by Russ Brewer) | |
31 | ||
32 | 1.63_05 Dec 6, 2010 | |
33 | - add support for hardlink@openssh.com extension | |
34 | - add die_on_error method | |
35 | - create a new process group for slave ssh process so that | |
36 | signals sent from the terminal are not propagated | |
37 | - better error messages | |
38 | ||
39 | 1.63_04 Nov 11, 2010 | |
40 | - workaround for IPC::Open3::open3 not working with tied file | |
41 | handles on Windows (bug report by Barnabas Bona) | |
42 | - several spelling corrections (contributed by Philippe Bruhat) | |
43 | ||
44 | 1.63_03 Nov 10, 2010 | |
45 | - On some OSs (i.e. AIX) reading/writing from non-blocking fds | |
46 | can result in EAGAIN even when select has indicated that | |
47 | data was available (bug report and patch by Bill Godfrey) | |
48 | ||
49 | 1.63_02 Nov 2, 2010 | |
50 | - Windows backend was not pipelining requests when called from | |
51 | put method | |
52 | ||
53 | 1.63_01 | |
54 | - support for Tectia client added (bug report by Russ Brewer) | |
2 | 55 | |
3 | 56 | 1.62 Oct 5, 2010 |
4 | 57 | - _catch_tainted_args was not being imported from helpers (bug |
0 | 0 | --- #YAML:1.0 |
1 | 1 | name: Net-SFTP-Foreign |
2 | version: 1.62 | |
2 | version: 1.65 | |
3 | 3 | abstract: Secure File Transfer Protocol client |
4 | 4 | author: |
5 | 5 | - Salvador Fandino <sfandino@yahoo.com> |
32 | 32 | |
33 | 33 | COPYRIGHT AND LICENCE |
34 | 34 | |
35 | Copyright (c) 2005-2010 by Salvador Fandino | |
35 | Copyright (c) 2005-2011 by Salvador Fandino | |
36 | 36 | |
37 | 37 | Copyright (c) 2001 Benjamin Trott, Copyright (c) 2003 David Rolsky. |
38 | 38 |
0 | 0 | package Net::SFTP::Foreign::Backend::Unix; |
1 | 1 | |
2 | our $VERSION = '1.58_07'; | |
2 | our $VERSION = '1.63_07'; | |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
21 | 21 | } |
22 | 22 | |
23 | 23 | sub _init_transport_streams { |
24 | my ($self, $sftp) = @_; | |
24 | my (undef, $sftp) = @_; | |
25 | 25 | for my $dir (qw(ssh_in ssh_out)) { |
26 | 26 | binmode $sftp->{$dir}; |
27 | 27 | my $flags = fcntl($sftp->{$dir}, F_GETFL, 0); |
49 | 49 | } |
50 | 50 | |
51 | 51 | sub _open3 { |
52 | my $backend = shift; | |
52 | 53 | my $sftp = shift; |
53 | 54 | if (defined $_[2]) { |
54 | 55 | my $sftp_err = $_[2]; |
69 | 70 | } |
70 | 71 | |
71 | 72 | sub _init_transport { |
72 | my ($class, $sftp, $opts) = @_; | |
73 | my ($backend, $sftp, $opts) = @_; | |
73 | 74 | |
74 | 75 | my $transport = delete $opts->{transport}; |
75 | 76 | |
97 | 98 | my $stderr_discard = delete $opts->{stderr_discard}; |
98 | 99 | my $stderr_fh = ($stderr_discard ? undef : delete $opts->{stderr_fh}); |
99 | 100 | my $open2_cmd = delete $opts->{open2_cmd}; |
101 | my $ssh_cmd_interface = delete $opts->{ssh_cmd_interface}; | |
100 | 102 | |
101 | 103 | my @open2_cmd; |
102 | 104 | if (defined $open2_cmd) { |
110 | 112 | $ssh_cmd = 'ssh' unless defined $ssh_cmd; |
111 | 113 | @open2_cmd = ($ssh_cmd); |
112 | 114 | |
113 | my $ssh_cmd_interface = delete $opts->{ssh_cmd_interface}; | |
114 | 115 | unless (defined $ssh_cmd_interface) { |
115 | $ssh_cmd_interface = ( $ssh_cmd =~ /\bplink(?:\.exe)?$/i | |
116 | ? 'plink' | |
117 | : 'ssh'); | |
116 | $ssh_cmd_interface = ( $ssh_cmd =~ /\bplink(?:\.exe)?$/i ? 'plink' : | |
117 | $ssh_cmd =~ /\bsshg3$/i ? 'tectia' : | |
118 | 'ssh' ); | |
118 | 119 | } |
119 | 120 | |
120 | 121 | my $port = delete $opts->{port}; |
124 | 125 | my $more = delete $opts->{more}; |
125 | 126 | carp "'more' argument looks like if it should be splited first" |
126 | 127 | if (defined $more and !ref($more) and $more =~ /^-\w\s+\S/); |
128 | my @more = _ensure_list $more; | |
127 | 129 | |
128 | 130 | if ($ssh_cmd_interface eq 'plink') { |
129 | 131 | $pass and !$passphrase |
133 | 135 | elsif ($ssh_cmd_interface eq 'ssh') { |
134 | 136 | push @open2_cmd, -p => $port if defined $port; |
135 | 137 | if ($pass and !$passphrase) { |
136 | push @open2_cmd, (-o => 'NumberOfPasswordPrompts=1', | |
137 | -o => 'PreferredAuthentications=keyboard-interactive,password'); | |
138 | push @open2_cmd, -o => 'NumberOfPasswordPrompts=1'; | |
139 | push @open2_cmd, -o => 'PreferredAuthentications=keyboard-interactive,password' | |
140 | unless grep { $more[$_] eq '-o' and | |
141 | $more[$_ + 1] =~ /^PreferredAuthentications\W/ } 0..$#more-1; | |
138 | 142 | } |
143 | } | |
144 | elsif ($ssh_cmd_interface eq 'tectia') { | |
139 | 145 | } |
140 | 146 | else { |
141 | 147 | die "Unsupported ssh_cmd_interface '$ssh_cmd_interface'"; |
142 | 148 | } |
143 | 149 | push @open2_cmd, -l => $user if defined $user; |
144 | push @open2_cmd, _ensure_list($more) if defined $more; | |
150 | push @open2_cmd, @more; | |
145 | 151 | push @open2_cmd, $host; |
146 | 152 | push @open2_cmd, ($ssh1 ? "/usr/lib/sftp-server" : -s => 'sftp'); |
147 | 153 | } |
148 | _debug "ssh cmd: @open2_cmd\n" if ($debug and $debug & 1); | |
154 | ||
155 | my $redirect_stderr_to_tty = ( (defined $pass or defined $passphrase) and | |
156 | (delete $opts->{redirect_stderr_to_tty} or | |
157 | $ssh_cmd_interface eq 'tectia' ) ); | |
158 | ||
159 | $redirect_stderr_to_tty and ($stderr_discard or $stderr_fh) | |
160 | and croak "stderr_discard or stderr_fh can not be used together with password/passphrase " | |
161 | . "authentication when Tectia client is used"; | |
162 | ||
163 | $debug and $debug & 1 and _debug "ssh cmd: @open2_cmd\n"; | |
149 | 164 | |
150 | 165 | %$opts and return; # Net::SFTP::Foreign will find the |
151 | 166 | # unhandled options and croak |
155 | 170 | } |
156 | 171 | |
157 | 172 | if ($stderr_discard) { |
158 | $stderr_fh = $class->_open_dev_null($sftp) or return; | |
173 | $stderr_fh = $backend->_open_dev_null($sftp) or return; | |
159 | 174 | } |
160 | 175 | |
161 | 176 | my $this_pid = $$; |
184 | 199 | $expect->raw_pty(1); |
185 | 200 | $expect->log_user($expect_log_user); |
186 | 201 | |
187 | $child = _open3($sftp, $sftp->{ssh_in}, $sftp->{ssh_out}, $stderr_fh, '-'); | |
202 | $redirect_stderr_to_tty and $stderr_fh = $pty->slave; | |
203 | ||
204 | $child = $backend->_open3($sftp, $sftp->{ssh_in}, $sftp->{ssh_out}, $stderr_fh, '-'); | |
188 | 205 | |
189 | 206 | if (defined $child and !$child) { |
190 | 207 | $pty->make_slave_controlling_terminal; |
195 | 212 | # $pty->close_slave(); |
196 | 213 | } |
197 | 214 | else { |
215 | $redirect_stderr_to_tty and | |
216 | croak "In order to support password/passphrase authentication with the Tectia client, " . | |
217 | "IPC::Open3 version 1.0105 is required (current version is $IPC::Open3::VERSION)"; | |
198 | 218 | $expect = Expect->new; |
199 | 219 | $expect->raw_pty(1); |
200 | 220 | $expect->log_user($expect_log_user); |
230 | 250 | $expect->close_slave(); |
231 | 251 | } |
232 | 252 | else { |
233 | $sftp->{pid} = _open3($sftp, $sftp->{ssh_in}, $sftp->{ssh_out}, $stderr_fh, @open2_cmd); | |
253 | $sftp->{pid} = $backend->_open3($sftp, $sftp->{ssh_in}, $sftp->{ssh_out}, $stderr_fh, @open2_cmd); | |
234 | 254 | _ipc_open2_bug_workaround $this_pid; |
235 | 255 | |
236 | 256 | unless (defined $sftp->{pid}) { |
237 | 257 | $sftp->_conn_failed("Bad ssh command", $!); |
238 | 258 | return; |
239 | 259 | } |
240 | } | |
241 | } | |
242 | $class->_init_transport_streams($sftp); | |
260 | # do not propagate signals sent from the terminal to the | |
261 | # slave SSH: | |
262 | eval { | |
263 | setpgrp($sftp->{pid}, 0); | |
264 | }; | |
265 | } | |
266 | } | |
267 | $backend->_init_transport_streams($sftp); | |
243 | 268 | } |
244 | 269 | |
245 | 270 | |
246 | 271 | sub _do_io { |
247 | my ($self, $sftp, $timeout) = @_; | |
272 | my (undef, $sftp, $timeout) = @_; | |
248 | 273 | |
249 | 274 | $debug and $debug & 32 and _debug(sprintf "_do_io connected: %s", $sftp->{_connected} || 0); |
250 | 275 | |
294 | 319 | 64 * 1024, $!); |
295 | 320 | $debug & 2048 and $written and _hexdump(substr($$bout, 0, $written)); |
296 | 321 | } |
297 | unless ($written) { | |
322 | if ($written) { | |
323 | substr($$bout, 0, $written, ''); | |
324 | } | |
325 | elsif ($! != Errno::EAGAIN() and $! != Errno::EINTR()) { | |
298 | 326 | $sftp->_conn_lost; |
299 | 327 | return undef; |
300 | 328 | } |
301 | substr($$bout, 0, $written, ''); | |
302 | 329 | } |
303 | 330 | if (vec($rv1, $fnoin, 1)) { |
304 | 331 | my $read = sysread($sftp->{ssh_in}, $$bin, 64 * 1024, length($$bin)); |
309 | 336 | $!); |
310 | 337 | $debug & 1024 and $read and _hexdump(substr($$bin, -$read)); |
311 | 338 | } |
312 | unless ($read) { | |
339 | if (!$read and $! != Errno::EAGAIN() and $! != Errno::EINTR()) { | |
313 | 340 | $sftp->_conn_lost; |
314 | 341 | return undef; |
315 | 342 | } |
317 | 344 | } |
318 | 345 | else { |
319 | 346 | $debug and $debug & 32 and _debug "_do_io select failed: $!"; |
320 | next if ($n < 0 and $! == Errno::EINTR()); | |
347 | next if ($n < 0 and ($! == Errno::EINTR() or $! == Errno::EAGAIN())); | |
321 | 348 | return undef; |
322 | 349 | } |
323 | 350 | } |
0 | 0 | package Net::SFTP::Foreign::Backend::Windows; |
1 | 1 | |
2 | our $VERSION = '1.58_05'; | |
2 | our $VERSION = '1.63_05'; | |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
19 | 19 | } |
20 | 20 | |
21 | 21 | sub _init_transport_streams { |
22 | my ($self, $sftp) = @_; | |
22 | my ($backend, $sftp) = @_; | |
23 | 23 | binmode $sftp->{ssh_in}; |
24 | 24 | binmode $sftp->{ssh_out}; |
25 | 25 | } |
27 | 27 | sub _open_dev_null { |
28 | 28 | my $sftp = shift; |
29 | 29 | my $dev_null; |
30 | unless (open $dev_null, '>', "NUL:") { | |
31 | $sftp->_conn_failed("Unable to redirect stderr to NUL:"); | |
30 | unless (open $dev_null, '>', 'NUL:') { | |
31 | $sftp->_conn_failed("Unable to redirect stderr for slave SSH process to NUL: $!"); | |
32 | 32 | return; |
33 | 33 | } |
34 | 34 | $dev_null |
35 | } | |
36 | ||
37 | # workaround for IPC::Open3 not working with tied filehandles even | |
38 | # when they implement FILENO | |
39 | sub _open3 { | |
40 | my $backend = shift; | |
41 | my $sftp = shift; | |
42 | if (tied(*STDERR)) { | |
43 | my $fn = eval { defined $_[2] ? fileno $_[2] : fileno *STDERR }; | |
44 | unless (defined $fn and $fn >= 0) { | |
45 | $sftp->_conn_failed("STDERR or stderr_fh is not a real file handle: " . (length $@ ? $@ : $!)); | |
46 | return; | |
47 | } | |
48 | local *STDERR; | |
49 | unless (open STDERR, ">&=$fn") { | |
50 | $sftp->_conn_failed("Unable to reattach STDERR to fd $fn: $!"); | |
51 | return; | |
52 | } | |
53 | $backend->SUPER::_open3($sftp, @_); | |
54 | } | |
55 | else { | |
56 | $backend->SUPER::_open3($sftp, @_); | |
57 | } | |
35 | 58 | } |
36 | 59 | |
37 | 60 | sub _sysreadn { |
50 | 73 | } |
51 | 74 | |
52 | 75 | sub _do_io { |
53 | my ($self, $sftp, $timeout) = @_; | |
76 | my ($backend, $sftp, $timeout) = @_; | |
54 | 77 | |
55 | 78 | return undef unless $sftp->{_connected}; |
56 | 79 | |
66 | 89 | substr($$bout, 0, $written, ""); |
67 | 90 | } |
68 | 91 | |
92 | defined $timeout and $timeout <= 0 and return; | |
93 | ||
69 | 94 | _sysreadn($sftp, 4) or return undef; |
70 | 95 | |
71 | 96 | my $len = 4 + unpack N => $$bin; |
72 | 97 | if ($len > 256 * 1024) { |
73 | $sftp->_set_status(SSH2_FX_BAD_MESSAGE); | |
74 | $sftp->_set_error(SFTP_ERR_REMOTE_BAD_MESSAGE, | |
75 | "bad remote message received"); | |
76 | return undef; | |
98 | $sftp->_set_status(SSH2_FX_BAD_MESSAGE); | |
99 | $sftp->_set_error(SFTP_ERR_REMOTE_BAD_MESSAGE, | |
100 | "bad remote message received"); | |
101 | return undef; | |
77 | 102 | } |
78 | 103 | _sysreadn($sftp, $len); |
79 | 104 | } |
0 | 0 | package Net::SFTP::Foreign::Common; |
1 | 1 | |
2 | our $VERSION = '1.57'; | |
2 | our $VERSION = '1.65'; | |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
76 | 76 | } |
77 | 77 | |
78 | 78 | sub error { shift->{_error} } |
79 | ||
80 | sub die_on_error { | |
81 | my $sftp = shift; | |
82 | $sftp->{_error} and croak(@_ ? "@_: $sftp->{_error}" : $sftp->{_error}); | |
83 | } | |
79 | 84 | |
80 | 85 | sub _set_errno { |
81 | 86 | my $sftp = shift; |
0 | 0 | package Net::SFTP::Foreign::Constants; |
1 | 1 | |
2 | our $VERSION = '1.52'; | |
2 | our $VERSION = '1.63_05'; | |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
116 | 116 | SFTP_ERR_REMOTE_STATVFS_FAILED => 48, |
117 | 117 | SFTP_ERR_REMOTE_FSTATVFS_FAILED => 49, |
118 | 118 | SFTP_ERR_PASSWORD_AUTHENTICATION_FAILED => 50, |
119 | SFTP_ERR_REMOTE_HARDLINK_FAILED => 51, | |
119 | 120 | ); |
120 | 121 | |
121 | 122 | for my $key (keys %constants) { |
214 | 215 | C<SFTP_ERR_REMOTE_REALPATH_FAILED>, C<SFTP_ERR_REMOTE_REMOVE_FAILED>, |
215 | 216 | C<SFTP_ERR_REMOTE_RENAME_FAILED>, C<SFTP_ERR_REMOTE_RMDIR_FAILED>, |
216 | 217 | C<SFTP_ERR_REMOTE_READLINK_FAILED>, C<SFTP_ERR_REMOTE_SYMLINK_FAILED>, |
217 | C<SFTP_ERR_REMOTE_SETSTAT_FAILED>, C<SFTP_ERR_REMOTE_STAT_FAILED> and | |
218 | C<SFTP_ERR_REMOTE_WRITE_FAILED>. | |
218 | C<SFTP_ERR_REMOTE_SETSTAT_FAILED>, C<SFTP_ERR_REMOTE_STAT_FAILED>, | |
219 | C<SFTP_ERR_REMOTE_WRITE_FAILED> and | |
220 | C<SFTP_ERR_REMOTE_HARDLINK_FAILED>. | |
219 | 221 | |
220 | 222 | Note: these constants are not defined on the SFTP draft. |
221 | 223 |
206 | 206 | my $i; |
207 | 207 | for (@_) { |
208 | 208 | next unless $i++; |
209 | if (tainted $_) { | |
209 | if (tainted($_)) { | |
210 | 210 | my (undef, undef, undef, $subn) = caller 1; |
211 | 211 | my $msg = ( $subn =~ /::([a-z]\w*)$/ |
212 | 212 | ? "Insecure argument '$_' on '$1' method call" |
214 | 214 | _tcroak($msg); |
215 | 215 | } |
216 | 216 | elsif (ref($_)) { |
217 | for (grep tainted $_, | |
217 | for (grep tainted($_), | |
218 | 218 | do { local ($@, $SIG{__DIE__}); eval { values %$_ }}) { |
219 | 219 | my (undef, undef, undef, $subn) = caller 1; |
220 | 220 | my $msg = ( $subn =~ /::([a-z]\w*)$/ |
0 | 0 | package Net::SFTP::Foreign; |
1 | 1 | |
2 | our $VERSION = '1.62'; | |
2 | our $VERSION = '1.65'; | |
3 | 3 | |
4 | 4 | use strict; |
5 | 5 | use warnings; |
187 | 187 | $sftp->{_queue_size} = delete $opts{queue_size} || $defs{queue_size} || 32; |
188 | 188 | $sftp->{_read_ahead} = $defs{read_ahead} || $sftp->{_block_size} * 4; |
189 | 189 | $sftp->{_write_delay} = $defs{write_delay} || $sftp->{_block_size} * 8; |
190 | $sftp->{_timeout} = delete $opts{timeout}; | |
191 | 190 | $sftp->{_autoflush} = delete $opts{autoflush}; |
192 | 191 | $sftp->{_late_set_perm} = delete $opts{late_set_perm}; |
193 | 192 | $sftp->{_dirty_cleanup} = delete $opts{dirty_cleanup}; |
193 | ||
194 | $sftp->{_timeout} = delete $opts{timeout}; | |
195 | defined $sftp->{_timeout} and $sftp->{_timeout} <= 0 and croak "invalid timeout"; | |
196 | ||
194 | 197 | $sftp->{_fs_encoding} = delete $opts{fs_encoding}; |
195 | ||
196 | 198 | if (defined $sftp->{_fs_encoding}) { |
197 | 199 | $] < 5.008 |
198 | 200 | and carp "fs_encoding feature is not supported in this perl version $]"; |
1023 | 1025 | last; |
1024 | 1026 | } |
1025 | 1027 | unless (length $path) { |
1026 | $sftp->set_error(SFTP_ERR_REMOTE_MKDIR_FAILED, | |
1027 | "Unable to make path, bad root"); | |
1028 | $sftp->_set_error(SFTP_ERR_REMOTE_MKDIR_FAILED, | |
1029 | "Unable to make path, bad root"); | |
1028 | 1030 | return undef; |
1029 | 1031 | } |
1030 | 1032 | unshift @path, $p; |
1299 | 1301 | |
1300 | 1302 | $sftp->_check_status_ok($id, SFTP_ERR_REMOTE_SYMLINK_FAILED, |
1301 | 1303 | "Couldn't create symlink '$sl' pointing to '$target'"); |
1304 | } | |
1305 | ||
1306 | sub hardlink { | |
1307 | @_ == 3 or croak 'Usage: $sftp->hardlink($hl, $target)'; | |
1308 | ${^TAINT} and &_catch_tainted_args; | |
1309 | ||
1310 | my ($sftp, $hl, $target) = @_; | |
1311 | ||
1312 | $sftp->_check_extension('hardlink@openssh.com' => 1, | |
1313 | SFTP_ERR_REMOTE_HARDLINK_FAILED, | |
1314 | "hardlink failed") | |
1315 | or return undef; | |
1316 | $hl = $sftp->_rel2abs($hl); | |
1317 | $target = $sftp->_rel2abs($target); | |
1318 | ||
1319 | my $id = $sftp->_queue_new_msg(SSH2_FXP_EXTENDED, | |
1320 | str => 'hardlink@openssh.com', | |
1321 | str => $sftp->_fs_encode($target), | |
1322 | str => $sftp->_fs_encode($hl)); | |
1323 | $sftp->_check_status_ok($id, SFTP_ERR_REMOTE_HARDLINK_FAILED, | |
1324 | "Couldn't create hardlink '$hl' pointing to '$target'"); | |
1302 | 1325 | } |
1303 | 1326 | |
1304 | 1327 | sub _gen_save_status_method { |
2764 | 2787 | my $gen_accessor = sub { |
2765 | 2788 | my $ix = shift; |
2766 | 2789 | sub { |
2767 | my $st = *{shift()}->{ARRAY}; | |
2790 | my $st = *{shift()}{ARRAY}; | |
2768 | 2791 | if (@_) { |
2769 | 2792 | $st->[$ix] = shift; |
2770 | 2793 | } |
2814 | 2837 | |
2815 | 2838 | my $self = Symbol::gensym; |
2816 | 2839 | bless $self, $class; |
2840 | *$self = [ $sftp, $rid, 0, $flags, @_]; | |
2817 | 2841 | tie *$self, $self; |
2818 | *{$self}->{ARRAY} = [ $sftp, $rid, 0, $flags, @_]; | |
2819 | 2842 | |
2820 | 2843 | $self; |
2821 | 2844 | } |
2822 | 2845 | |
2823 | 2846 | sub _close { |
2824 | 2847 | my $self = shift; |
2825 | @{*$self->{ARRAY}} = (); | |
2848 | @{*{$self}{ARRAY}} = (); | |
2826 | 2849 | } |
2827 | 2850 | |
2828 | 2851 | sub _check { |
2829 | return 1 if defined(*{shift()}->{ARRAY}[0]); | |
2852 | return 1 if defined(*{shift()}{ARRAY}[0]); | |
2830 | 2853 | $! = Errno::EBADF; |
2831 | 2854 | undef; |
2832 | 2855 | } |
2840 | 2863 | "-1:sftp(0x$hrid)" |
2841 | 2864 | } |
2842 | 2865 | |
2843 | sub _sftp { *{shift()}->{ARRAY}[0] } | |
2844 | sub _rid { *{shift()}->{ARRAY}[1] } | |
2866 | sub _sftp { *{shift()}{ARRAY}[0] } | |
2867 | sub _rid { *{shift()}{ARRAY}[1] } | |
2845 | 2868 | |
2846 | 2869 | * _pos = $gen_accessor->(2); |
2847 | 2870 | |
2848 | 2871 | sub _inc_pos { |
2849 | 2872 | my ($self, $inc) = @_; |
2850 | *{shift()}->{ARRAY}[2] += $inc; | |
2873 | *{shift()}{ARRAY}[2] += $inc; | |
2851 | 2874 | } |
2852 | 2875 | |
2853 | 2876 | |
2854 | 2877 | my %flag_bit = (append => 0x1); |
2855 | 2878 | |
2856 | 2879 | sub _flag { |
2857 | my $st = *{shift()}->{ARRAY}; | |
2880 | my $st = *{shift()}{ARRAY}; | |
2858 | 2881 | my $fn = shift; |
2859 | 2882 | my $flag = $flag_bit{$fn}; |
2860 | 2883 | Carp::croak("unknown flag $fn") unless defined $flag; |
2907 | 2930 | |
2908 | 2931 | sub _check_is_file {} |
2909 | 2932 | |
2910 | sub _bin { \(*{shift()}->{ARRAY}[4]) } | |
2911 | sub _bout { \(*{shift()}->{ARRAY}[5]) } | |
2933 | sub _bin { \(*{shift()}{ARRAY}[4]) } | |
2934 | sub _bout { \(*{shift()}{ARRAY}[5]) } | |
2912 | 2935 | |
2913 | 2936 | sub WRITE { |
2914 | 2937 | my ($self, undef, $length, $offset) = @_; |
3005 | 3028 | |
3006 | 3029 | sub _check_is_dir {} |
3007 | 3030 | |
3008 | sub _cache { *{shift()}->{ARRAY}[4] } | |
3031 | sub _cache { *{shift()}{ARRAY}[4] } | |
3009 | 3032 | |
3010 | 3033 | *CLOSEDIR = $gen_proxy_method->('closedir'); |
3011 | 3034 | *READDIR = $gen_proxy_method->('_readdir'); |
3041 | 3064 | |
3042 | 3065 | use Net::SFTP::Foreign; |
3043 | 3066 | my $sftp = Net::SFTP::Foreign->new($host); |
3044 | $sftp->error and | |
3045 | die "Unable to stablish SFTP connection: " . $sftp->error; | |
3067 | $sftp->die_on_error("Unable to establish SFTP connection"); | |
3046 | 3068 | |
3047 | 3069 | $sftp->setcwd($path) or die "unable to change cwd: " . $sftp->error; |
3048 | 3070 | |
3078 | 3100 | |
3079 | 3101 | Well, both modules have their pros and cons: |
3080 | 3102 | |
3081 | Net::SFTP::Foreign does not requiere a bunch of additional modules and | |
3103 | Net::SFTP::Foreign does not require a bunch of additional modules and | |
3082 | 3104 | external libraries to work, just the OpenBSD SSH client (or any other |
3083 | 3105 | client compatible enough). |
3084 | 3106 | |
3135 | 3157 | constructor call: |
3136 | 3158 | |
3137 | 3159 | my $sftp = Net::SFTP::Foreign->new(...); |
3138 | $sftp->error and die "SSH connection failed: " . $sftp->error; | |
3160 | $sftp->die_on_error("SSH connection failed"); | |
3139 | 3161 | |
3140 | 3162 | C<%args> can contain: |
3141 | 3163 | |
3172 | 3194 | more => "-i $key" # wrong!!! |
3173 | 3195 | more => [-i => $key] # right |
3174 | 3196 | |
3175 | =item ssh_cmd_interface =E<gt> 'plink' or 'ssh' | |
3197 | =item ssh_cmd_interface =E<gt> 'plink' or 'ssh' or 'tectia' | |
3176 | 3198 | |
3177 | 3199 | declares the command line interface that the SSH client used to |
3178 | connect to the remote host understands. Currently C<plink> and C<ssh> | |
3179 | are supported. | |
3200 | connect to the remote host understands. Currently C<plink>, C<ssh> and | |
3201 | C<tectia> are supported. | |
3180 | 3202 | |
3181 | 3203 | This option would be rarely required as the module infers the |
3182 | 3204 | interface from the SSH command name. |
3183 | ||
3184 | =item autoflush =E<gt> $bool | |
3185 | ||
3186 | by default, and for performance reasons, write operations are cached, | |
3187 | and only when the write buffer becomes big enough is the data written to | |
3188 | the remote file. Setting this flag makes the write operations inmediate. | |
3189 | 3205 | |
3190 | 3206 | =item timeout =E<gt> $seconds |
3191 | 3207 | |
3207 | 3223 | |
3208 | 3224 | For instance: |
3209 | 3225 | |
3210 | $sftp = Net::SFTP::Foreign->new('user@host', fs_encoding => latin1); | |
3226 | $sftp = Net::SFTP::Foreign->new('user@host', fs_encoding => 'latin1'); | |
3211 | 3227 | |
3212 | 3228 | will convert any path name passed to any method in this package to its |
3213 | 3229 | C<latin1> representation before sending it to the remote side. |
3308 | 3324 | default C<block_size> and C<queue_size> used for read and write |
3309 | 3325 | operations (see the C<put> or C<get> documentation). |
3310 | 3326 | |
3327 | =item autoflush =E<gt> $bool | |
3328 | ||
3329 | by default, and for performance reasons, write operations are cached, | |
3330 | and only when the write buffer becomes big enough is the data written to | |
3331 | the remote file. Setting this flag makes the write operations inmediate. | |
3332 | ||
3333 | =item write_delay =E<gt> $bytes | |
3334 | ||
3335 | This option determines how many bytes are buffered before the real | |
3336 | SFTP write operation is performed. | |
3337 | ||
3338 | =item read_ahead =E<gt> $bytes | |
3339 | ||
3340 | On read operations this option determines how many bytes to read in | |
3341 | advance so that later read operations can be fulfilled from the | |
3342 | buffer. | |
3343 | ||
3344 | Using a high value will increase the performance of the module for a | |
3345 | sequential reads access pattern but degrade it for a short random | |
3346 | reads access pattern. It can also cause synchronization problems if | |
3347 | the file is concurrently modified by other parties (L</flush> can be | |
3348 | used to discard all the data inside the read buffer on demand). | |
3349 | ||
3350 | The default value is set dynamically considering some runtime | |
3351 | parameters and given options, though it tends to favor the sequential | |
3352 | read access pattern. | |
3353 | ||
3311 | 3354 | =item autodisconnect =E<gt> $ad |
3312 | 3355 | |
3313 | 3356 | by default, the SSH connection is closed from the DESTROY method when |
3325 | 3368 | |
3326 | 3369 | Never try to disconnect this object when exiting from any process. |
3327 | 3370 | |
3328 | On most operative systems, the SSH process will exit when the last | |
3371 | On most operating systems, the SSH process will exit when the last | |
3329 | 3372 | process connected to it ends, but this is not guaranteed. |
3330 | 3373 | |
3331 | 3374 | =item 1 |
3368 | 3411 | |
3369 | 3412 | See L<Net::SFTP::Foreign::Constants> for a list of possible error |
3370 | 3413 | codes and how to import them on your scripts. |
3414 | ||
3415 | =item $sftp-E<gt>die_on_error($msg) | |
3416 | ||
3417 | Convenience method: | |
3418 | ||
3419 | $sftp->die_on_error("Something bad happened"); | |
3420 | # is a shortcut for... | |
3421 | $sftp->error and die "Something bad happened: " . $sftp->error; | |
3371 | 3422 | |
3372 | 3423 | =item $sftp-E<gt>status |
3373 | 3424 | |
3682 | 3733 | |
3683 | 3734 | =item wanted =E<gt> qr/.../ |
3684 | 3735 | |
3685 | Only elements which filename match the regular expresion are included | |
3736 | Only elements which filename match the regular expression are included | |
3686 | 3737 | on the listing. |
3687 | 3738 | |
3688 | 3739 | =item wanted =E<gt> sub {...} |
3809 | 3860 | |
3810 | 3861 | =item ordered =E<gt> 1 |
3811 | 3862 | |
3812 | By default, the file system is searched in an implementation dependant | |
3863 | By default, the file system is searched in an implementation dependent | |
3813 | 3864 | order (actually optimized for low memory comsumption). If this option |
3814 | 3865 | is included, the file system is searched in a deep-first, sorted by |
3815 | 3866 | filename fashion. |
3893 | 3944 | |
3894 | 3945 | =item strict_leading_dot =E<gt> 0 |
3895 | 3946 | |
3896 | by default, a dot character at the begining of a file or directory | |
3947 | by default, a dot character at the beginning of a file or directory | |
3897 | 3948 | name is not matched by willcards (C<*> or C<?>). Setting this flags to |
3898 | 3949 | a false value changes this behaviour. |
3899 | 3950 | |
4274 | 4325 | =item $sftp-E<gt>opendir($path) |
4275 | 4326 | |
4276 | 4327 | Sends a C<SSH_FXP_OPENDIR> command to open the remote directory |
4277 | C<$path>, and returns an open handle on success (unfortunatelly, | |
4328 | C<$path>, and returns an open handle on success (unfortunately, | |
4278 | 4329 | current versions of perl does not support directory operations via |
4279 | 4330 | tied handles, so it is not possible to use the returned handle as a |
4280 | 4331 | native one). |
4408 | 4459 | it. Use C<realpath> to normalize it: |
4409 | 4460 | |
4410 | 4461 | $sftp->symlink("foo.lnk" => $sftp->realpath("../bar")) |
4462 | ||
4463 | =item $sftp-E<gt>hardlink($hl, $target) | |
4464 | ||
4465 | Creates a hardlink on the server. | |
4466 | ||
4467 | This command requires support for the 'hardlink@openssh.com' extension | |
4468 | on the server (available in OpenSSH from version 5.7). | |
4411 | 4469 | |
4412 | 4470 | =item $sftp-E<gt>statvfs($path) |
4413 | 4471 | |
4560 | 4618 | my $sftp = Net::SFTP::Foreign->new('foo@bar', |
4561 | 4619 | ssh_cmd => 'plink', |
4562 | 4620 | more => [-pw => $password]); |
4563 | $sftp->error and die $sftp->error; | |
4621 | $sftp->die_on_error; | |
4564 | 4622 | |
4565 | 4623 | =item Plink |
4566 | 4624 | |
4576 | 4634 | B<Q>: put fails with the following error: |
4577 | 4635 | |
4578 | 4636 | Couldn't setstat remote file (fsetstat): The requested operation |
4579 | cannot be performed because there is a file transfer in progress. | |
4637 | cannot be performed because there is a file transfer in progress. | |
4580 | 4638 | |
4581 | 4639 | B<A>: Try passing the C<late_set_perm> option to the put method: |
4582 | 4640 | |
4646 | 4704 | B<A>: That probably means that the public key from the remote server |
4647 | 4705 | is not stored in the C<~/.ssh/known_hosts> file. Run an SSH Connection |
4648 | 4706 | from the command line as the same user as the script and answer C<yes> |
4649 | when asked to confirm the key suplied. | |
4707 | when asked to confirm the key supplied. | |
4650 | 4708 | |
4651 | 4709 | Example: |
4652 | 4710 | |
4682 | 4740 | |
4683 | 4741 | =item - Dirty cleanup: |
4684 | 4742 | |
4685 | On some operative systems, closing the pipes used to comunicate with | |
4743 | On some operating systems, closing the pipes used to comunicate with | |
4686 | 4744 | the slave SSH process does not terminate it and a work around has to |
4687 | 4745 | be applied. If you find that your scripts hung when the $sftp object |
4688 | 4746 | gets out of scope, try setting C<$Net::SFTP::Foreign::dirty_cleanup> |
4703 | 4761 | |
4704 | 4762 | Also, the following features should be considered experimental: |
4705 | 4763 | |
4764 | - support for Tectia server | |
4765 | ||
4706 | 4766 | - redirecting SSH stderr stream |
4707 | 4767 | |
4708 | 4768 | - multi-backend support |
4754 | 4814 | |
4755 | 4815 | =head1 COPYRIGHT |
4756 | 4816 | |
4757 | Copyright (c) 2005-2010 Salvador FandiE<ntilde>o (sfandino@yahoo.com). | |
4817 | Copyright (c) 2005-2011 Salvador FandiE<ntilde>o (sfandino@yahoo.com). | |
4758 | 4818 | |
4759 | 4819 | Copyright (c) 2001 Benjamin Trott, Copyright (c) 2003 David Rolsky. |
4760 | 4820 |