pg has asked for the wisdom of the Perl Monks concerning the following question:

I got a problem here. See comment in the code for detail. Is it with my program? Is it with in memory file handler? Is it with Net::FTP? Anyone noticed this before?

I thought in memory file handlers can be used almost without you know.

Thanks in advance.
use Net::FTP; use strict; #This works. It opens a in memory file first, passing it to a sub, and + do something. { my $in_mem; print "First try something else\n"; open(AFILE, ">", \$in_mem); write_okay_okay(*AFILE); close(AFILE); print $in_mem, "\n"; } #This does not work. It opens a in memory file, passing it to Net::FTP +->get(). #However got error msg complained bad file descriptor { print "Now try FTP with in mem\n"; my $ftp = new Net::FTP("Kyanite", Debug => 1); $ftp->login("user name", "password"); my $in_mem; open(BFILE, ">", \$in_mem) || die "failed"; print BFILE "okayokay"; $ftp->get("MComSubChng.txt", \*BFILE); $ftp->quit(); close(BFILE); print $in_mem, "\n"; } #This works fine. It opens a normal file, and pass the handler to Net: +:FTP->get(). #I checked, and the local file was created { print "Now try FTP norm\n"; my $ftp = new Net::FTP("Kyanite", Debug => 1); $ftp->login("user name", "password"); open(BFILE, ">", "bfile") || die "failed"; $ftp->get("MComSubChng.txt", \*BFILE); $ftp->quit(); close(BFILE); } sub write_okay_okay { my $file = shift; print $file "okay okay"; }

Replies are listed 'Best First'.
Re: question about Net::FTP + in memory file handler
by crenz (Priest) on Apr 14, 2003 at 20:34 UTC

    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?

      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; }
Re: question about Net::FTP + in memory file handler
by runrig (Abbot) on Apr 14, 2003 at 20:39 UTC
    This used to happen using IO::Scalar file handles with older versions of Net::FTP. You probably need to get the latest Net::FTP.