Read from filehandle opened for appending

S

Sisyphus

Hi,
If I try to read from a filehandle opened for appending, I get no warning
about the fact that the filehandle is not readable. Why is that ?

Here's the demo script:

use warnings;

# Create a test file:

open(WR, '>', 'temp.txt') or die "Can't open for writing: $!";
print WR "line 1\nline2\n\nline4\nline5\n";
close(WR) or die "Can't close after writing: $!";

# Open for appending, then try to read:

open($fh, '>>', 'temp.txt') or die "Can't open: $!";
seek($fh, 0, 0);
@lines = <$fh>;
close($fh) or die "Can't close: $!";
print for @lines;
__END__

@lines is empty as it should be, but no warning gets issued.
If I replace the '>>' with a '+>>', then @lines is filled with the contents
of the file.

Even at the XS level, we are unable to tell if a filehandle opened for
appending is readable or not:

use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

void my_fmode(SV * handle) {
int x;
IO *io;
io = sv_2io(handle);
x = IoTYPE(io);
if (x == IoTYPE_RDONLY) printf ("read only\n");
if (x == IoTYPE_WRONLY) printf ("write only\n");
if (x == IoTYPE_RDWR) printf ("read_write\n");
if (x == IoTYPE_APPEND) printf ("append\n");
}

EOC

open($fh1, '+>>', 'temp.txt')
or die "Can't open fh1 for reading and appending: $!";

open($fh2, '>>', 'temp.txt')
or die "Can't open fh2 for appending: $!";

my_fmode($fh1);
my_fmode($fh2);

close($fh1) or die "Can't close fh1: $!";
close($fh2) or die "Can't close fh2: $!";
__END__

For both filehandles, x is set to the same value (ie to IoTYPE_APPEND) so we
have no chance of determining whether it's a '>>' filehandle or a '+>>'
filehandle.

Are these oversights, or are there sound reasons for these behaviours ?

I don't really know why anyone would open a file for appending only and then
try to read from it .... but I would have thought that such an action should
be detectable/reportable in some way.

Cheers,
Rob
 
M

Martin Kißner

Sisyphus wrote :
Hi,
If I try to read from a filehandle opened for appending, I get no warning
about the fact that the filehandle is not readable. Why is that ?

Because you don't ask for it

perldoc -f seek
seek FILEHANDLE,POSITION,WHENCE
...
Returns 1 upon success, 0 otherwise.

HTH

Best regards
Martin
 
A

attn.steven.kuo

Sisyphus said:
Hi,
If I try to read from a filehandle opened for appending, I get no warning
about the fact that the filehandle is not readable. Why is that ?

[ snipped ... ]
Even at the XS level, we are unable to tell if a filehandle opened for
appending is readable or not:

use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

void my_fmode(SV * handle) {
int x;
IO *io;
io = sv_2io(handle);
x = IoTYPE(io);
if (x == IoTYPE_RDONLY) printf ("read only\n");
if (x == IoTYPE_WRONLY) printf ("write only\n");
if (x == IoTYPE_RDWR) printf ("read_write\n");
if (x == IoTYPE_APPEND) printf ("append\n");
}

EOC

open($fh1, '+>>', 'temp.txt')
or die "Can't open fh1 for reading and appending: $!";

open($fh2, '>>', 'temp.txt')
or die "Can't open fh2 for appending: $!";

my_fmode($fh1);
my_fmode($fh2);

close($fh1) or die "Can't close fh1: $!";
close($fh2) or die "Can't close fh2: $!";
__END__

For both filehandles, x is set to the same value (ie to IoTYPE_APPEND) so we
have no chance of determining whether it's a '>>' filehandle or a '+>>'
filehandle.

Are these oversights, or are there sound reasons for these behaviours ?

I don't really know why anyone would open a file for appending only and then
try to read from it .... but I would have thought that such an action should
be detectable/reportable in some way.



It seems IoTYPE returns only a single character (see sv.h)
and so it can't indicate that a handle is open for
both read and append in the case of your $fh1, above.

I seem to have more luck with using the macros and
functions from perliol.h. I'm running perl 5.8.8 --
I can't guarantee that this won't break on earlier
versions:

# with slight modifications to your code:

use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

#include <perliol.h>

void my_fmode(SV * handle) {
IO *io;
PerlIO *f;
io = sv_2io(handle);
f = IoIFP(io);
if (PerlIOValid(f))
{
const IV flags = PerlIOBase(f)->flags;
if (flags & PERLIO_F_CANWRITE) printf ("can write\n");
if (flags & PERLIO_F_CANREAD) printf ("can read\n");
if (flags & PERLIO_F_APPEND) printf ("append\n");
}
}

EOC

open($fh1, '+>>', 'temp.txt')
or die "Can't open fh1 for reading and appending: $!";

open($fh2, '>>', 'temp.txt')
or die "Can't open fh2 for appending: $!";

my_fmode($fh1);
print "=" x 72, "\n";
my_fmode($fh2);

close($fh1) or die "Can't close fh1: $!";
close($fh2) or die "Can't close fh2: $!";
__END__

can write
can read
append
========================================================================
can write
append
 
S

Sisyphus

Martin Kißner said:
Sisyphus wrote :

Because you don't ask for it

perldoc -f seek
seek FILEHANDLE,POSITION,WHENCE
...
Returns 1 upon success, 0 otherwise.

Yes - but if I'm wondering why I don't get a warning from having tried to
*read* the file.

I get a warning if I:

open(WR, '>', 'temp.txt') or die "$!";
@lines = <WR>;

I would expect a similar warning if I:

open(WR, '>>', 'temp.txt') or die "$!";
@lines = <WR>;

but no warning eventuates. And when I look at what's happening at the XS
level, I'm not surprised that no warning eventuates - because IoTYPE()
doesn't know that the filehandle is not readable (because it can't
distinguish between '>>' and '+>>') ..... but I'm not so sure my reasoning
there is correct :)

Cheers,
Rob
 
S

Sisyphus

..
..
I seem to have more luck with using the macros and
functions from perliol.h. I'm running perl 5.8.8 --
I can't guarantee that this won't break on earlier
versions:

# with slight modifications to your code:

use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

#include <perliol.h>

void my_fmode(SV * handle) {
IO *io;
PerlIO *f;
io = sv_2io(handle);
f = IoIFP(io);
if (PerlIOValid(f))
{
const IV flags = PerlIOBase(f)->flags;
if (flags & PERLIO_F_CANWRITE) printf ("can write\n");
if (flags & PERLIO_F_CANREAD) printf ("can read\n");
if (flags & PERLIO_F_APPEND) printf ("append\n");
}
}

EOC

open($fh1, '+>>', 'temp.txt')
or die "Can't open fh1 for reading and appending: $!";

open($fh2, '>>', 'temp.txt')
or die "Can't open fh2 for appending: $!";

my_fmode($fh1);
print "=" x 72, "\n";
my_fmode($fh2);

close($fh1) or die "Can't close fh1: $!";
close($fh2) or die "Can't close fh2: $!";
__END__

Thanks for that. I can probably use it if it's reliable over perl 5.8.x
(for all 'x').
In any event, it's most interesting ..... and using a perl header file that
has to be explicitly called ... how scary is that :)

I'm a little bit intrigued by the fact that you can assign to 'f' using
IoIFP(), even if the handle is write only and my_fmode() produces correct
results. Otoh, if I instead assign to 'f' using IoOFP(), my_fmode() produces
incorrect results if its fed a read only handle. Can you explain that ?

Cheers,
Rob
 
S

Sisyphus

..
..
I'm a little bit intrigued by the fact that you can assign to 'f' using
IoIFP(), even if the handle is write only and my_fmode() produces correct
results. Otoh, if I instead assign to 'f' using IoOFP(), my_fmode() produces
incorrect results if its fed a read only handle. Can you explain that ?

Perhaps I should have explained a bit better.

If we do:

f = IoIFP(io);

then PerlIOValid(f) returns true, even if the handle is write only.

But if we do:

f = IoOFP(io);

then PerlIOValid(f) returns false if the handle is read only.

I'm puzzled as to how we can get away with the former, but not the latter.

Cheers,
Rob
 
A

attn.steven.kuo

Sisyphus said:
.
.

Perhaps I should have explained a bit better.

If we do:

f = IoIFP(io);

then PerlIOValid(f) returns true, even if the handle is write only.

But if we do:

f = IoOFP(io);

then PerlIOValid(f) returns false if the handle is read only.

I'm puzzled as to how we can get away with the former, but not the latter.



On my system PerlIOValid(f) returns true
when given a read-only file handle.

Tested with:

open ($fh3, '<', $0)
or die "Can't open fh3 for read: $!";

my_fmode($fh3);

# with the aforementioned XS code:

void my_fmode(SV * handle) {
IO *io;
PerlIO *f;
io = sv_2io(handle);
f = IoIFP(io);
if (PerlIOValid(f))
{
const IV flags = PerlIOBase(f)->flags;
if (flags & PERLIO_F_CANWRITE) printf ("can write\n");
if (flags & PERLIO_F_CANREAD) printf ("can read\n");
if (flags & PERLIO_F_APPEND) printf ("append\n");
}
}



In any case, the code is largely cribbed from the perl source:

http://search.cpan.org/src/NWCLARK/perl-5.8.8/perlio.c

Brief details of my system:

$ perl -v

This is perl, v5.8.8 built for darwin-2level

Copyright 1987-2006, Larry Wall
....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top