Net-SFTP-Foreign-Backend-Net_SSH2
view release on metacpan or search on metacpan
lib/Net/SFTP/Foreign/Backend/Net_SSH2.pm view on Meta::CPAN
sub _make_error_string {
my ($self, $msg) = @_;
my ($err_code, $err_name, $err_str) = $self->{_ssh2}->error;
if ($err_code) {
return sprintf("%s: %s (%d): %s", $msg, $err_name, $err_code, $err_str)
}
else {
return $msg
}
}
sub _conn_failed {
my ($self, $sftp, $msg) = @_;
$sftp->_conn_failed($self->_make_error_string($msg))
}
sub _conn_lost {
my ($self, $sftp, $msg) = @_;
$sftp->_conn_lost(undef, undef, $self->_make_error_string($msg))
}
my %auth_arg_map = qw(host hostname
user username
passphrase password
local_user local_username
key_path privatekey);
sub _init_transport {
my ($self, $sftp, $opts) = @_;
my $ssh2 = delete $opts->{ssh2};
if (defined $ssh2) {
$self->{_ssh2} = $ssh2;
$debug and $debug & 131072 and $ssh2->debug(1);
unless ($ssh2->auth_ok) {
$sftp->_conn_failed("Net::SSH2 object is not authenticated");
return;
}
}
else {
my %auth_args;
for (qw(rank username passphrase password publickey privatekey
hostname key_path local_user local_username interact
cb_keyboard cb_password user host)) {
my $map = $auth_arg_map{$_} || $_;
next if defined $auth_args{$map};
$auth_args{$map} = delete $opts->{$_} if exists $opts->{$_}
}
if (defined $auth_args{privatekey} and not defined $auth_args{publickey}) {
$auth_args{publickey} = "$auth_args{privatekey}.pub";
}
my $host = $auth_args{hostname};
defined $host or croak "sftp target host not defined";
my $port = delete $opts->{port} || 22;
%$opts and return;
unless (defined $auth_args{username}) {
local $SIG{__DIE__};
$auth_args{username} = eval { scalar getpwuid $< };
defined $auth_args{username} or croak "required option 'user' missing";
}
$ssh2 = $self->{_ssh2} = Net::SSH2->new();
$debug and $debug & 131072 and $ssh2->debug(1);
unless ($ssh2->connect($host, $port)) {
$self->_conn_failed($sftp, "Connection to remote host $host failed");
return;
}
unless ($ssh2->auth(%auth_args)) {
$self->_conn_failed($sftp, "Authentication failed");
return;
}
}
my $channel = $self->{_channel} = $ssh2->channel;
unless (defined $channel) {
$self->_conn_failed($sftp, "Unable to create new session channel");
return;
}
$channel->ext_data('ignore');
$channel->subsystem('sftp');
}
sub _sysreadn {
my ($self, $sftp, $n) = @_;
my $channel = $self->{_channel};
my $bin = \$sftp->{_bin};
while (1) {
my $len = length $$bin;
return 1 if $len >= $n;
my $buf = '';
my $read = $channel->read($buf, $n - $len);
unless (defined $read) {
$debug and $debug & 32 and _debug("read failed: " . $self->{_ssh2}->error . ", n: $n, len: $len");
if ($self->{_ssh2}->error == $eagain_error) {
$debug and $debug & 32 and _debug "read error: EAGAIN, delaying before retrying";
sleep 0.01;
redo;
}
$self->_conn_lost($sftp, "Read failed");
return undef;
}
$sftp->{_read_total} += $read;
if ($debug and $debug & 32) {
_debug "$read bytes read from SSH channel, total $sftp->{_read_total}";
$debug & 2048 and $read and _hexdump($buf);
}
$$bin .= $buf;
}
return $n;
}
sub _do_io {
my ($self, $sftp, $timeout) = @_;
my $channel = $self->{_channel};
return undef unless $sftp->{_connected};
( run in 2.437 seconds using v1.01-cache-2.11-cpan-98e64b0badf )