Net-SFTP-Server

 view release on metacpan or  search on metacpan

lib/Net/SFTP/Server/FS.pm  view on Meta::CPAN

	return $self->push_status_response($id, SSH_FX_FAILURE,
					   "Bad handler");
    $len = 65536 if $len > 65536;

    sysseek($fh, $off, 0) // return $self->push_status_errno_response($id);
    my $bytes = sysread($fh, my($data), $len) //
	return $self->push_status_errno_response($id);
    $bytes == 0 and
	return $self->push_status_response($id, SSH_FX_EOF);
    # TODO: build packet on buffer_out to reduce data copying
    $self->push_packet(uint8 => SSH_FXP_DATA,
		       uint32 => $id,
		       str => $data);
}

sub handle_command_write_v3 {
    my ($self, $id, $hid, $off) = @_;
    my $fh = $self->get_file_handler($hid) //
	return $self->push_status_response($id, SSH_FX_FAILURE,
					   "Bad handler");
    sysseek($fh, $off, 0) // return $self->push_status_errno_response($id);
    my $len = length $_[4];
    while ($len) {
	my $bytes = syswrite($fh, $_[4], $len, -$len)
	    or return $self->push_status_errno_response($id);
	$len -= $bytes;
    }
    $self->push_status_ok_response($id);
}

sub handle_command_close_v3 {
    my ($self, $id, $hid) = @_;
    my ($type, $fh) = $self->remove_handler($hid)
	or return $self->push_status_response($id, SSH_FX_FAILURE, "Bad file handler");
    if ($type eq 'dir') {
	$debug and $debug & 2 and _debug "closing dir handle $hid (id: $id)";
	closedir($fh) or return $self->push_status_errno_response($id);
    }
    elsif ($type eq 'file') {
	$debug and $debug & 2 and _debug "closing file handle $hid (id: $id)";
	close($fh) or return $self->push_status_errno_response($id);
    }
    else {
	die "Internal error: unknown handler type $type";
    }
    $self->push_status_ok_response($id);
}

sub handle_command_opendir_v3 {
    my ($self, $id, $path) = @_;
    opendir my $dh, $path or return $self->push_status_errno_response($id);
    my $hid = $self->save_dir_handler($dh, $path);
    $debug and $debug & 2 and _debug "dir $path open as $hid (pkt id: $id)";
    $self->push_handle_response($id, $hid);
}

our @month2name = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);

sub resolve_uid {
    my ($self, $uid) = @_;
    my $name = getpwuid $uid;
    defined $name ? $name : $uid;
}

sub resolve_gid {
    my ($self, $gid) = @_;
    my $name = getgrgid $gid;
    defined $name ? $name : $gid;
}

sub readdir_name {
    my ($self, $dir, $entry, $lstat) = @_;
    my $fn = File::Spec->catfile($dir, $entry);
    my (undef, undef, $mode, $nlink, $uid, $gid, undef, $size, $atime, $mtime) =
	($lstat ? lstat $fn : stat $fn) or return { filename => $entry };
    my (undef, $min, $hour, $mday, $mon, $year) = localtime $mtime;
    my $current_year = (localtime)[5];
    my $longname = sprintf("%10s %3d %-9s %-9s % 8d %-3s %2d % 5s %s",
			   strmode($mode),
			   $nlink,
			   $self->resolve_uid($uid),
			   $self->resolve_gid($gid),
			   $size,
			   $month2name[$mon],
			   $mday,
			   ($year == $current_year
			    ? sprintf("%02d:%02d", $hour, $min)
			    : $year + 1900),
			   $entry);

    $debug and $debug & 2 and _debug "longname: $longname (entry: $entry)";

    return {
	filename => $entry,
	longname => $longname,
	attrs => {
	    size => $size,
	    uid => $uid,
	    gid => $gid,
	    permissions => $mode,
	    atime => $atime,
	    mtime => $mtime
	}
    }
}

sub handle_command_readdir_v3 {
    my ($self, $id, $hid) = @_;
    my ($dh, $path) = $self->get_dir_handler($hid)
	or $self->push_status_response($id, SSH_FX_FAILURE, "Bad directory handler");
    my @entry;
    while (defined (my $entry = readdir $dh)) {
	push @entry, $entry;
	last if @entry > 200;
    }
    @entry or return $self->push_status_eof_response($id);
    $self->push_name_response($id, map $self->readdir_name($path, $_), @entry);
}

sub stat_to_attrs {
    my ($self, undef, undef, $mode, undef, $uid, $gid, undef, $size, $atime, $mtime) = @_;



( run in 1.446 second using v1.01-cache-2.11-cpan-5b529ec07f3 )