Net-SFTP-Server
view release on metacpan or search on metacpan
examples/sftp-server-atomic-put.pl view on Meta::CPAN
use 5.010;
use strict;
use warnings;
use parent 'Net::SFTP::Server::FS';
use Net::SFTP::Server::Constants qw(:all);
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->{overlay} = {};
$self;
}
sub handle_command_open_v3 {
my ($self, $id, $path, $flags, $attrs) = @_;
my $writable = $flags & SSH_FXF_WRITE;
my $perms = $attrs->{mode};
my ($old_umask, $fh, $target_path);
if (exists $self->{overlay}{$path}) {
$path = $self->{overlay}{$path}
}
elsif ($writable) {
if ( (-f $path and $flags & SSH_FXF_TRUNC) or
(!-e $path and $flags & SSH_FXF_CREAT) ) {
$target_path = $path;
$path .= '.part';
if (-e $path) {
$self->push_status_response($id, SSH_FX_FAILURE, "A temporal file blocks the transfer");
return;
}
examples/sftp-server-atomic-put.pl view on Meta::CPAN
$self->push_status_errno_response($id);
umask $old_umask if defined $old_umask;
return;
}
umask $old_umask if defined $old_umask;
if ($writable) {
Net::SFTP::Server::FS::_set_attrs($path, $attrs)
or $self->send_status_errno_response($id);
}
my $hid = $self->save_file_handler($fh, $flags, $perms, $target_path // $path);
$self->{overlay}{$target_path} = $path if defined $target_path;
$self->push_handle_response($id, $hid);
}
sub handle_command_close_v3 {
my ($self, $id, $hid) = @_;
my ($type, $fh, undef, undef, $target_path) = $self->remove_handler($hid)
or return $self->push_status_response($id, SSH_FX_FAILURE, "Bad file handler");
if ($type eq 'dir') {
closedir($fh) or return $self->push_status_errno_response($id);
}
elsif ($type eq 'file') {
my $path = delete $self->{overlay}{$target_path};
close($fh) or return $self->push_status_errno_response($id);
if (defined $path) {
rename $path, $target_path or return $self->push_status_errno_response($id);
}
}
else {
die "Internal error: unknown handler type $type";
}
$self->push_status_ok_response($id);
}
for my $action (qw(lstat stat setstat)) {
my $method = "handle_command_${action}_v3";
my $super = Net::SFTP::Server::FS->can($method);
no strict 'refs';
*$method = sub {
my ($self, $id, $target_path) = @_;
my $path = $self->{overlay}{$target_path} // $target_path;
$super->($self, $id, $path);
};
}
DESTROY {
local ($!, $?, $@);
my $self = shift;
unlink $_ for (values %{$self->{overlay}});
}
my $server = main->new();
$server->run;
__END__
=head1 NAME
( run in 0.477 second using v1.01-cache-2.11-cpan-26ccb49234f )