App-SimpleBackuper
view release on metacpan or search on metacpan
local/lib/perl5/Net/SFTP/Foreign/Common.pm view on Meta::CPAN
sub _call_on_error {
my ($sftp, $on_error, $entry) = @_;
$on_error and $sftp->error
and $on_error->($sftp, $entry);
$sftp->_clear_error_and_status;
}
# this method code is a little convoluted because we are trying to
# keep in memory as few entries as possible!!!
sub find {
@_ >= 1 or croak 'Usage: $sftp->find($remote_dirs, %opts)';
my $self = shift;
my %opts = @_ & 1 ? ('dirs', @_) : @_;
$self->_clear_error_and_status;
my $dirs = delete $opts{dirs};
my $follow_links = delete $opts{follow_links};
my $on_error = delete $opts{on_error};
local $self->{_autodie} if $on_error;
my $realpath = delete $opts{realpath};
my $ordered = delete $opts{ordered};
my $names_only = delete $opts{names_only};
my $atomic_readdir = delete $opts{atomic_readdir};
my $wanted = _gen_wanted( delete $opts{wanted},
delete $opts{no_wanted} );
my $descend = _gen_wanted( delete $opts{descend},
delete $opts{no_descend} );
%opts and croak "invalid option(s) '".CORE::join("', '", keys %opts)."'";
$dirs = '.' unless defined $dirs;
my $wantarray = wantarray;
my (@res, $res);
my %done;
my %rpdone; # used to detect cycles
my @dirs = _ensure_list $dirs;
my @queue = map { { filename => $_ } } ($ordered ? sort @dirs : @dirs);
# we use a clousure instead of an auxiliary method to have access
# to the state:
my $task = sub {
my $entry = shift;
my $fn = $entry->{filename};
for (1) {
my $follow = ($follow_links and _is_lnk($entry->{a}->perm));
if ($follow or $realpath) {
unless (defined $entry->{realpath}) {
my $rp = $entry->{realpath} = $self->realpath($fn);
next unless (defined $rp and not $rpdone{$rp}++);
}
}
if ($follow) {
my $a = $self->stat($fn);
if (defined $a) {
$entry->{a} = $a;
# we queue it for reprocessing as it could be a directory
unshift @queue, $entry;
}
next;
}
if (!$wanted or $wanted->($self, $entry)) {
if ($wantarray) {
push @res, ( $names_only
? ( exists $entry->{realpath}
? $entry->{realpath}
: $entry->{filename} )
: $entry )
}
else {
$res++;
}
}
}
continue {
$self->_call_on_error($on_error, $entry)
}
};
my $try;
while (@queue) {
no warnings 'uninitialized';
$try = shift @queue;
my $fn = $try->{filename};
my $a = $try->{a} ||= $self->lstat($fn)
or next;
next if (_is_dir($a->perm) and $done{$fn}++);
$task->($try);
if (_is_dir($a->perm)) {
if (!$descend or $descend->($self, $try)) {
if ($ordered or $atomic_readdir) {
my $ls = $self->ls( $fn,
ordered => $ordered,
_wanted => sub {
my $child = $_[1]->{filename};
if ($child !~ /^\.\.?$/) {
$_[1]->{filename} = $self->join($fn, $child);
return 1;
}
undef;
})
or next;
unshift @queue, @$ls;
}
else {
$self->ls( $fn,
_wanted => sub {
my $entry = $_[1];
my $child = $entry->{filename};
if ($child !~ /^\.\.?$/) {
$entry->{filename} = $self->join($fn, $child);
if (_is_dir($entry->{a}->perm)) {
push @queue, $entry;
}
else {
$task->($entry);
}
}
undef } )
or next;
}
}
}
}
continue {
$self->_call_on_error($on_error, $try)
}
return wantarray ? @res : $res;
}
sub glob {
@_ >= 2 or croak 'Usage: $sftp->glob($pattern, %opts)';
${^TAINT} and &_catch_tainted_args;
my ($sftp, $glob, %opts) = @_;
return () if $glob eq '';
my $on_error = delete $opts{on_error};
local $sftp->{_autodie} if $on_error;
my $follow_links = delete $opts{follow_links};
my $ignore_case = delete $opts{ignore_case};
my $names_only = delete $opts{names_only};
my $realpath = delete $opts{realpath};
my $ordered = delete $opts{ordered};
my $wanted = _gen_wanted( delete $opts{wanted},
delete $opts{no_wanted});
my $strict_leading_dot = delete $opts{strict_leading_dot};
$strict_leading_dot = 1 unless defined $strict_leading_dot;
%opts and _croak_bad_options(keys %opts);
my $wantarray = wantarray;
my (@parts, $top);
if (ref $glob eq 'Regexp') {
@parts = ($glob);
$top = '.';
}
else {
@parts = ($glob =~ m{\G/*([^/]+)}g);
push @parts, '.' unless @parts;
$top = ( $glob =~ m|^/| ? '/' : '.');
}
my @res = ( {filename => $top} );
my $res = 0;
while (@parts and @res) {
my @parents = @res;
@res = ();
my $part = shift @parts;
my ($re, $has_wildcards);
if (ref $part eq 'Regexp') {
$re = $part;
$has_wildcards = 1;
}
else {
($re, $has_wildcards) = _glob_to_regex($part, $strict_leading_dot, $ignore_case);
}
for my $parent (@parents) {
my $pfn = $parent->{filename};
if ($has_wildcards) {
$sftp->ls( $pfn,
ordered => $ordered,
_wanted => sub {
my $e = $_[1];
if ($e->{filename} =~ $re) {
my $fn = $e->{filename} = $sftp->join($pfn, $e->{filename});
if ( (@parts or $follow_links)
and _is_lnk($e->{a}->perm) ) {
if (my $a = $sftp->stat($fn)) {
$e->{a} = $a;
}
else {
$on_error and $sftp->_call_on_error($on_error, $e);
return undef;
}
}
if (@parts) {
push @res, $e if _is_dir($e->{a}->perm)
}
elsif (!$wanted or $wanted->($sftp, $e)) {
if ($wantarray) {
if ($realpath) {
my $rp = $e->{realpath} = $sftp->realpath($e->{filename});
unless (defined $rp) {
$on_error and $sftp->_call_on_error($on_error, $e);
return undef;
}
}
push @res, ($names_only
? ($realpath ? $e->{realpath} : $e->{filename} )
: $e);
}
$res++;
}
}
return undef
} )
or ($on_error and $sftp->_call_on_error($on_error, $parent));
}
else {
my $fn = $sftp->join($pfn, $part);
my $method = ((@parts or $follow_links) ? 'stat' : 'lstat');
if (my $a = $sftp->$method($fn)) {
my $e = { filename => $fn, a => $a };
if (@parts) {
push @res, $e if _is_dir($a->{perm})
}
elsif (!$wanted or $wanted->($sftp, $e)) {
if ($wantarray) {
if ($realpath) {
my $rp = $fn = $e->{realpath} = $sftp->realpath($fn);
unless (defined $rp) {
$on_error and $sftp->_call_on_error($on_error, $e);
next;
}
}
push @res, ($names_only ? $fn : $e)
}
$res++;
}
}
}
}
}
return wantarray ? @res : $res;
}
sub test_d {
my ($sftp, $name) = @_;
{
local $sftp->{_autodie};
my $a = $sftp->stat($name);
return _is_dir($a->perm) if $a;
}
if ($sftp->{_status} == SSH2_FX_NO_SUCH_FILE) {
$sftp->_clear_error_and_status;
return undef;
}
$sftp->_ok_or_autodie;
}
sub test_e {
my ($sftp, $name) = @_;
{
local $sftp->{_autodie};
$sftp->stat($name) and return 1;
}
if ($sftp->{_status} == SSH2_FX_NO_SUCH_FILE) {
$sftp->_clear_error_and_status;
return undef;
}
$sftp->_ok_or_autodie;
}
1;
( run in 0.601 second using v1.01-cache-2.11-cpan-39bf76dae61 )