Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Inconsistancy within Net::FTP?

by vaevictus (Pilgrim)
on Aug 23, 2000 at 23:21 UTC ( #29295=perlquestion: print w/ replies, xml ) Need Help??
vaevictus has asked for the wisdom of the Perl Monks concerning the following question:

I was searching through the categorize Q&A, and mccormi asked a question that was a problem i had given up on a while back.
I'm not sure whether the problem is related to my ignorance or the module, but here's what i've discovered:

Net::FTP doesn't support any sort of variable uploads, just named files, and filehandles.
With the objective being to upload without using a file on the network, (useful for me, for example, when i want to upload a zipped (tgz'd) backup of a filesystem, too large to write to disk first), my first line of thought was "hmm... it takes filehandles, see if STDIN works"... and it does:

$ftp = Net::FTP->new($destserv) || die "error connecting\n"; $ftp->login($destuser,$destpass); $ftp->binary(); $ftp->put(*STDIN,$remotefile) or die "error uploading\n"; $ftp->quit();

This will solve the issue at hand, by allowing a first script to pipe data into the STDIN of this script, to upload data without a file. However, I don't see why this has to be written with two processes. So, my second line of thought was "hmmm... it takes filehandles, use tie"... So, using IO::Scalar I wrote this:

my $data="FOOBAR"; tie *FOO, 'IO::Scalar',\$data; $ftp = Net::FTP->new($destserv) || die "error connecting\n"; $ftp->login($destuser,$destpass); $ftp->binary(); $ftp->put(*FOO,"remotelogfile") or die "error uploading\n"; $ftp->quit();

and while this scalar works for me as a FILE with normal filehandle usage,

while (<FOO>){print $_;} print FOO "hi";

in this particular module, i get the following error:

Cannot open Local file *main::FOO: No such file or directory at ./netftpcgi.pl line 18
error uploading

This leads me to believe that for some reason, *main::FOO is different than *main::STDIN and that Net::FTP can tell. If anyone would help me with my logic, I'd appreciate it.

Comment on Inconsistancy within Net::FTP?
Select or Download Code
Re (tilly) 1: Inconsistancy within Net::FTP?
by tilly (Archbishop) on Aug 23, 2000 at 23:30 UTC
    I believe you are right, and I believe that what is happening is that an xsub somewhere is assuming that it has (at the C level) a filehandle, but none is really there.

    Perl's tied filehandles can only trap output coming through Perl. Not C extensions, the system call, etc.

    But file a bug report anyways...

Re: Inconsistancy within Net::FTP?
by btrott (Parson) on Aug 23, 2000 at 23:34 UTC
    Looking through the Net::FTP code, I think this is because your tied handle doesn't have a valid file descriptor. Which, I think, would make sense, since it's not actually associated with a real file.

    See, Net::FTP calls fileno on the filehandle you pass in; if the result is undef (as it is in your case), it treats the handle as a file path. Which doesn't exist, obviously.

    Unfortunately I don't know how to solve your problem. :( It may be just a limitation that can't be fixed.

    Update: it turns out that in 5.6 you can define a FILENO method for your tied filehandle class. So you could possibly use that to make Net::FTP work properly with your tied filehandle. The 5.6 perltie is at http://search.cpan.org/doc/GSAR/perl-5.6.0/pod/perltie.pod if you don't have it locally.

      IMNSHO calling fileno on a tied filehandle should case some screaming and shouting. Or at least a warning?
        I definitely agree. And, while it makes conceptual sense, I think it should also be mentioned in the docs for tying filehandles. Of course, it could be; I didn't look very hard. :)

        But I agree, a warning/fatal error would definitely be welcome in such a scenario.

Re: Inconsistancy within Net::FTP?
by rdw (Curate) on Aug 24, 2000 at 12:50 UTC
    As others have pointed out, this is because Net::FTP is calling fileno. I just tried this and it worked for me - I don't think it will solve all your problems, but it might be a good starting point.
    my $data="FOOBAR"; pipe PIPEREAD, PIPEWRITE; print PIPEWRITE $data; close PIPEWRITE; my($ftp) = Net::FTP->new($destserv) || die "error connecting\n"; $ftp->login($destuser, $destpass); $ftp->binary(); $ftp->put(*PIPEREAD,"remotelogfile") or die "error uploading\n"; $ftp->quit();
    Basically, I used pipe to create a real pipe between Perl and whatever Net::FTP is doing.

    Have fun,

    Rich
      That works as long as you don't have more than 8K of data (doh!), because a pipe can buffer up to that before blocking. More than that, you'll block on the write at your print PIPEWRITE, and there won't be anyone around to be reading it, so you'll wait forever. Bzzzzz.

      -- Randal L. Schwartz, Perl hacker

        Like I said, it won't solve all the problems :-)

        Since Net::FTP is blocking, you can't really do this without two processes.

        Rich

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://29295]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2014-09-30 22:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (385 votes), past polls