Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

There be dragons (or, perl5.8's open stringref breaks...)

by Tanktalus (Canon)
on Apr 23, 2005 at 00:05 UTC ( [id://450615]=perlquestion: print w/replies, xml ) Need Help??

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

Here I thought I was being clever. Allowing any type of input - filenames, handles, whatever. And then copying that data to some arbitrary file (via gzip or whatever). Too clever, I suppose.

#!/usr/bin/perl use strict; use warnings; use File::Copy; my $buffer = <<EOS; Here there be dragons! EOS open my $fh, '<', \$buffer; copy($fh, "foo.txt");
The output?
stat() on unopened filehandle $fh at /share/perl5/lib/5.8.6/File/Copy. +pm line 82.
I think that's pretty nifty. So much for File::Copy! I'm not entirely sure where to report the problem, either. Nor am I really aware enough of the internals to know the difference between a GLOB that points to a file and one that points to a string reference (although I'm sure there is a way) so that I could submit a patch.

That'll learn me for trying to abuse all the new features at once... ;-)

Replies are listed 'Best First'.
Re: There be dragons (or, perl5.8's open stringref breaks...)
by toma (Vicar) on Apr 23, 2005 at 03:30 UTC
    To change everything you do with IO all at once, check out IO::All. It handles the 'or whatever' anything->anything part of what you're doing.
    use IO::All; my $buffer = <<EOS; Here there be dragons! EOS io("foo.txt") < $buffer;
    I keep my IO bag-o-tricks offsite.

    It should work perfectly the first time! - toma
Re: There be dragons (or, perl5.8's open stringref breaks...)
by dragonchild (Archbishop) on Apr 23, 2005 at 02:17 UTC
    There's two problems here. The first is stat() and the second is sysread() (and, I would presume, syswrite() as well). stat() treats scalar filehandles as unopened. If you comment out that section in File::Copy::copy(), sysread() treats it as a "Bad file descriptor". I would argue that both are bugs, but that's because they violate the Principle of Least Surprise.
      So it is arguably doing the right thing and they are not bugs, at least not bugs in the binary but in the dox somewhere. As mentioned there, they don't actually exist. At least, such an argument could be made for sys*. Stat ought to be able to fake most things for a scalar easily enough, although one could argue sys* aren't that hard either. It's either a gross oversight on somebody's part, or a big can of worms they decided to consider Somebody Else's Problem.

      --
      I'm not belgian but I play one on TV. On dit que je parle comme un belge aussi.

        They aren't bugs in implementation, but in specification. This is why you need requirements and design reviews along with code reviews.

        The Perfect is the Enemy of the Good.

Re: There be dragons (or, perl5.8's open stringref breaks...)
by ikegami (Patriarch) on Apr 23, 2005 at 00:37 UTC

    Not really an answer to your question -- I don't have one -- but some alternative code:

    #!/usr/bin/perl use strict; use warnings; use File::Copy; my $buffer = <<EOS; Here there be dragons! EOS open my $fh, '>', 'foo.txt'; print $fh $buffer;

      This code is a simplified example. The real code is much bigger and more complex. And is used for everything from getting data from pipelines (open my $fh, "tar cf - * | gzip -c |";) carrying hundreds of MB of data, to a couple KB of strings. The latter isn't a big deal, the former is. I'm figuring that I'm going to have to perform the copy myself. Not hard to do, but just has to be done. Note that I can't assume anything about the data, so if I want to be efficient (time/memory), I'm going to either have to use sysread or something, or I'm going to have to set $/ to \1024 or something (fixed length read/write, not line-by-line since, as potentially binary data, I don't have any idea what lines are). Not a big deal, but this is what I was using File::Copy for. :-)

      I'm just going to rip some of it from File::Copy, and assume the filehandle is good. I do know, however, that the from-handle and the to-filename should not be the same (it would actually be difficult to do), so this should be ok for all but the pathological cases (where someone is simply trying to break something on purpose).

      Thanks!

Re: There be dragons (or, perl5.8's open stringref breaks...)
by tlm (Prior) on Apr 23, 2005 at 01:04 UTC

    FWIW, fileno returns -1 for handles pointing to scalar refs, though this behavior appears to be undocumented; at least the docs for fileno are noncommittal on the subject.

    the lowliest monk

Re: There be dragons (or, perl5.8's open stringref breaks...)
by starbolin (Hermit) on Apr 23, 2005 at 14:19 UTC

    Interesting, this code compiles and runs, but the data isn't copied.

    #!/usr/bin/perl use strict; use warnings; use File::Copy; my $buffer = <<EOS; Here there be dragons! EOS copy(\$buffer, "foo.txt");


    Update:

    My bad. The Copy chokes on a non-filehandle.


    s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}
Re: There be dragons (or, perl5.8's open stringref breaks...)
by salva (Canon) on Apr 24, 2005 at 13:04 UTC
    the problem with scalars refs used as streams is that they lack an OS file descriptor. They live exclusively at the PerlIO layer, which is fine most of the time for perl scripts, but it isn't for external C libraries or even perl functions that wrap OS calls expecting a file descriptor as an argument.

    Send a bug report to File::Copy author!.

      Yeah ... I was hoping the PerlIO abstracted this, too ;-)

      What would be really cool is to be able to do this:

      { local *STDOUT; my $buf; open STDOUT, '>', \$buf; system("some_command","with","args"); $logger->write($buf); }
      But that's probably expecting a bit much. ;-)

      Anyway, as I said in the original post of the thread, I can't quite figure out who the author is - probably owned by p5p anyway. So I submitted the bug report - we'll see if there's any answer. I do still think, however, that this is a much larger problem than I would be able to give a reasonable patch for, since getting it to work properly may involve many, many changes, or just one: disallow string-handles in File::Copy.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://450615]
Approved by ikegami
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (9)
As of 2024-04-16 08:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found