Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

'Anonymous' copy via file handle fails

by Monk::Thomas (Friar)
on Jan 16, 2013 at 20:34 UTC ( #1013642=perlquestion: print w/replies, xml ) Need Help??
Monk::Thomas has asked for the wisdom of the Perl Monks concerning the following question:

(This is part of a larger program. I stripped the code example down.)

I'd like to get a file from somewhere (HTTP, SCP, FTP, local file) and make a local copy via fetch(), pass the file descriptor around, modify the content and later on write the file content to one or more other files.

Alternative a) It would be easy to do this via actual file names but I would like to use open filehandles without an actual filename. This way I wouldn't have to worry about someone tampering with my data while I'm working on it.

Alternative b) I don't want to slurp the file content into main memory.

Script output:

FETCH The file '/etc/services' has inode 2105201 and size 19398
FETCH The file 'GLOB(0x10c7c78)' has inode 142159 and size 19398
STORE The file 'GLOB(0x10c7c78)' has inode 142159 and size 19398
STORE The file '/tmp/services.d1JH' has inode 142160 and size 0
STORE Copying filehandle tmp1 (GLOB(0x10c7c78)) to tmp2 (/tmp/services.d1JH) file.
STORE The file 'GLOB(0x10c7c78)' has inode 142159 and size 19398
STORE The file '/tmp/services.d1JH' has inode 142160 and size 0
-rw------- 1 thomas thomas 0 Jan 16 21:15 /tmp/services_copy

As you can see, the store() function seems to receive the correct data to the file object, but copy does not actually copy the file. I seriously scratched my head on this, but so far no enlightenment has occured. Buffering issue? Copy not happy with the GLOBs? Something totally different?

Time to confess my non-knowledge and ask a senior monk. Hopefully I get something more then just a koan. ;)

#!/usr/bin/env perl use strict; use warnings; use 5.010_001; use English qw( -no_match_vars ); # avoid regex performance penalty use File::Copy; use File::Temp qw(tempfile); use Readonly; Readonly my $STAT_INODE => '1'; Readonly my $STAT_SIZE => '7'; my $tmp_fh = fetch(); store($tmp_fh); exit 0; sub fetch { my $src_file = '/etc/services'; show_filestats('FETCH', $src_file); my ( $tmp1_fh, $tmp1_filename ) = tempfile(); unlink $tmp1_filename; # copy $src_file, $tmp1_fh or die "$ERRNO\n"; show_filestats('FETCH', $tmp1_fh); return $tmp1_fh; } sub store { my $tmp1_fh = shift; my $tmp2_file = File::Temp->new( TEMPLATE => '/tmp/services.XXXX', + UNLINK => 0 ); my $dst_file = '/tmp/services_copy'; show_filestats('STORE', $tmp1_fh); show_filestats('STORE', $tmp2_file); print "[STORE] Copying filehandle tmp1 ($tmp1_fh) to tmp2 ($tmp2_f +ile) file.\n" or croak(); copy $tmp1_fh, $tmp2_file or die "E: $ERRNO\n"; show_filestats('STORE', $tmp1_fh); show_filestats('STORE', $tmp2_file); # apply permissions and ACLs rename $tmp2_file, $dst_file or die "E: $ERRNO\n"; } sub show_filestats { my $id = shift; my $fh = shift; my ( $inode, $size ) = ( stat $fh )[ $STAT_INODE, $STAT_SIZE ]; print "[$id] The file '$fh' has inode $inode and size $size\n" or croak(); return; }

Replies are listed 'Best First'.
Re: 'Anonymous' copy via file handle fails
by Anonymous Monk on Jan 17, 2013 at 00:02 UTC
    Filehandles are iterators. Once you reach the end, you're at the end, subsequent read/readline reads from the end, there is nothing at the end, so you have to use seek to rewind the FA filehandle before you read it again.

    $ echo > 1 $ perl -MFile::Copy -wE " open $O, 1 or die $!; sub F{copy $O, \*STDOU +T } F;F; seek $O,0,0; F; " ECHO is on. ECHO is on. $ rm 1 $
      Hmmm. The strange thing is I actually had a 'rewind' in there at some point but removed it again because it didn't have any impact. However if I change the first copy operation to
      copy $src_file, $tmp1_fh or die "$ERRNO\n"; seek $tmp1_fh,0,0;
      then it magically works now. Thanks for the tip! Maybe there is some other bug lurking in the original program, but now that the basic copy works I'm sure to figure it out.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1013642]
Front-paged by Lotus1
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2018-04-24 03:49 GMT
Find Nodes?
    Voting Booth?