in reply to question about Net::FTP + in memory file handler

I recently got bitten by this in the thread Portable in-memory files. In-memory files can be used as long as the functions you call just use open, close, <HANDLE>, print HANDLE etc.

They obviously can't be used when a module demands the (OS-internal) file descriptor. I presume Net::FTP is doing just that?

  • Comment on Re: question about Net::FTP + in memory file handler

Replies are listed 'Best First'.
Re: Re: question about Net::FTP + in memory file handler
by pg (Canon) on Apr 15, 2003 at 02:11 UTC
    Thanks to both crenz and runrig.

    I followed up on the leads crenz presented here. He is right. In the get() of Net::FTP, it calls syswrite to write to the local file, and that's the whole problem.

    Now it is clear that syswrite obviously does not work with in-mem.

    I changed the syswrite to a print. As I don't want that impact the normal get(), I added one function called get_in_mem() to Net::FTP on my PC.

    I simply replicated get(), changed that syswrite to print, and striped some code that is obviously not neccessary for opened handlers (as the original get() also deals with filenames).

    Here is the code (obviously I didn't fully test it, but for my case, I tested it and it worked):
    sub get_in_mem { my($ftp,$remote,$local,$where) = @_; my($loc,$len,$buf,$resp,$data); local *FD; my $localfd = 1; croak("Bad remote filename '$remote'\n") if $remote =~ /[\r\n]/s; ${*$ftp}{'net_ftp_rest'} = $where if ($where); delete ${*$ftp}{'net_ftp_port'}; delete ${*$ftp}{'net_ftp_pasv'}; $data = $ftp->retr($remote) or return undef; $loc = $local; if($ftp->type eq 'I' && !binmode($loc)) { carp "Cannot binmode Local file $local: $!\n"; $data->abort; return undef; } $buf = ''; my($count,$hashh,$hashb,$ref) = (0); ($hashh,$hashb) = @$ref if($ref = ${*$ftp}{'net_ftp_hash'}); my $blksize = ${*$ftp}{'net_ftp_blksize'}; while(1) { last unless $len = $data->read($buf,$blksize); if (trEBCDIC && $ftp->type ne 'I') { $buf = $ftp->toebcdic($buf); $len = length($buf); } if($hashh) { $count += $len; print $hashh "#" x (int($count / $hashb)); $count %= $hashb; } print $loc $buf; =document my $written = syswrite($loc,$buf,$len); unless(defined($written) && $written == $len) { carp "Cannot write to Local file $local: $!\n"; $data->abort; close($loc) unless $localfd; return undef; } =cut } print $hashh "\n" if $hashh; unless ($data->close()) # implied $ftp->response { carp "Unable to close datastream"; return undef; } return $local; }