From: Slaven Rezic Date: Thu, 24 Oct 2002 00:44:35 +0000 (+0200) Subject: Re: [perl #18048] read \*FH, ... returns undef but doesn' t set $! if \*FH not open X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b5fe5ca2134a9ef76f895fb7bc7abec4e8196b08;p=p5sagit%2Fp5-mst-13.2.git Re: [perl #18048] read \*FH, ... returns undef but doesn' t set $! if \*FH not open Message-ID: <87vg3sixm4.fsf@vran.herceg.de> p4raw-id: //depot/perl@18115 --- diff --git a/pod/perldiag.pod b/pod/perldiag.pod index 20d9d91..e59eee3 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -3093,6 +3093,14 @@ are outside the range which can be represented by integers internally. One possible workaround is to force Perl to use magical string increment by prepending "0" to your numbers. +=item read() on closed filehandle %s + +(W closed) You tried to read from a closed filehandle. + +=item read() on unopened filehandle %s + +(W unopened) You tried to read from a filehandle that was never opened. + =item readline() on closed filehandle %s (W closed) The filehandle you're reading from got itself closed sometime @@ -3567,6 +3575,14 @@ or "my $var" or "our $var". (F) The final summary message when a C succeeds. +=item sysread() on closed filehandle %s + +(W closed) You tried to read from a closed filehandle. + +=item sysread() on unopened filehandle %s + +(W unopened) You tried to read from a filehandle that was never opened. + =item System V %s is not implemented on this machine (F) You tried to do something with a function beginning with "sem", diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod index d1d6469..8a745ef 100644 --- a/pod/perlfunc.pod +++ b/pod/perlfunc.pod @@ -453,7 +453,7 @@ Arranges for FILEHANDLE to be read or written in "binary" or "text" mode on systems where the run-time libraries distinguish between binary and text files. If FILEHANDLE is an expression, the value is taken as the name of the filehandle. Returns true on success, -C on failure. +otherwise it returns C and sets C<$!> (errno). If LAYER is omitted or specified as C<:raw> the filehandle is made suitable for passing binary data. This includes turning off possible CRLF @@ -1805,11 +1805,11 @@ C always returns true. See L for other examples. =item getc Returns the next character from the input file attached to FILEHANDLE, -or the undefined value at end of file, or if there was an error. -If FILEHANDLE is omitted, reads from STDIN. This is not particularly -efficient. However, it cannot be used by itself to fetch single -characters without waiting for the user to hit enter. For that, try -something more like: +or the undefined value at end of file, or if there was an error (in +the latter case C<$!> is set). If FILEHANDLE is omitted, reads from +STDIN. This is not particularly efficient. However, it cannot be +used by itself to fetch single characters without waiting for the user +to hit enter. For that, try something more like: if ($BSD_STYLE) { system "stty cbreak /dev/tty 2>&1"; @@ -3767,13 +3767,13 @@ with the wrong number of RANDBITS.) Attempts to read LENGTH I of data into variable SCALAR from the specified FILEHANDLE. Returns the number of characters -actually read, C<0> at end of file, or undef if there was an error. -SCALAR will be grown or shrunk to the length actually read. If SCALAR -needs growing, the new bytes will be zero bytes. An OFFSET may be -specified to place the read data into some other place in SCALAR than -the beginning. The call is actually implemented in terms of either -Perl's or system's fread() call. To get a true read(2) system call, -see C. +actually read, C<0> at end of file, or undef if there was an error (in +the latter case C<$!> is also set). SCALAR will be grown or shrunk to +the length actually read. If SCALAR needs growing, the new bytes will +be zero bytes. An OFFSET may be specified to place the read data into +some other place in SCALAR than the beginning. The call is actually +implemented in terms of either Perl's or system's fread() call. To +get a true read(2) system call, see C. Note the I: depending on the status of the filehandle, either (8-bit) bytes or characters are read. By default all @@ -5519,14 +5519,15 @@ See L for a kinder, gentler explanation of opening files. =item sysread FILEHANDLE,SCALAR,LENGTH -Attempts to read LENGTH I of data into variable SCALAR from -the specified FILEHANDLE, using the system call read(2). It bypasses -buffered IO, so mixing this with other kinds of reads, C, -C, C, C, or C can cause confusion because -stdio usually buffers data. Returns the number of characters actually -read, C<0> at end of file, or undef if there was an error. SCALAR -will be grown or shrunk so that the last byte actually read is the -last byte of the scalar after the read. +Attempts to read LENGTH I of data into variable SCALAR +from the specified FILEHANDLE, using the system call read(2). It +bypasses buffered IO, so mixing this with other kinds of reads, +C, C, C, C, or C can cause confusion +because stdio usually buffers data. Returns the number of characters +actually read, C<0> at end of file, or undef if there was an error (in +the latter case C<$!> is also set). SCALAR will be grown or shrunk so +that the last byte actually read is the last byte of the scalar after +the read. Note the I: depending on the status of the filehandle, either (8-bit) bytes or characters are read. By default all @@ -5644,9 +5645,10 @@ is not specified, writes whole SCALAR. It bypasses buffered IO, so mixing this with reads (other than C, C, C, C, C, or C may cause confusion because stdio usually buffers data. Returns the number of characters actually written, or -C if there was an error. If the LENGTH is greater than the -available data in the SCALAR after the OFFSET, only as much data as is -available will be written. +C if there was an error (in this case the errno variable C<$!> +is also set). If the LENGTH is greater than the available data in the +SCALAR after the OFFSET, only as much data as is available will be +written. An OFFSET may be specified to write the data from some part of the string other than the beginning. A negative OFFSET specifies writing diff --git a/pp_sys.c b/pp_sys.c index 2d27d86..2939e90 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -734,6 +734,7 @@ PP(pp_binmode) if (!(io = GvIO(gv)) || !(fp = IoIFP(io))) { if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) report_evil_fh(gv, io, PL_op->op_type); + SETERRNO(EBADF,RMS_IFI); RETPUSHUNDEF; } @@ -1177,6 +1178,7 @@ PP(pp_getc) if (ckWARN2(WARN_UNOPENED,WARN_CLOSED) && (!io || (!IoIFP(io) && IoTYPE(io) != IoTYPE_WRONLY))) report_evil_fh(gv, io, PL_op->op_type); + SETERRNO(EBADF,RMS_IFI); RETPUSHUNDEF; } TAINT; @@ -1571,8 +1573,12 @@ PP(pp_sysread) else offset = 0; io = GvIO(gv); - if (!io || !IoIFP(io)) + if (!io || !IoIFP(io)) { + if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) + report_evil_fh(gv, io, PL_op->op_type); + SETERRNO(EBADF,RMS_IFI); goto say_undef; + } if ((fp_utf8 = PerlIO_isutf8(IoIFP(io))) && !IN_BYTES) { buffer = SvPVutf8_force(bufsv, blen); /* UTF8 may not have been set if they are all low bytes */ @@ -1813,6 +1819,7 @@ PP(pp_send) retval = -1; if (ckWARN(WARN_CLOSED)) report_evil_fh(gv, io, PL_op->op_type); + SETERRNO(EBADF,RMS_IFI); goto say_undef; } diff --git a/t/io/binmode.t b/t/io/binmode.t index 3775290..f50d0f7 100644 --- a/t/io/binmode.t +++ b/t/io/binmode.t @@ -3,12 +3,13 @@ BEGIN { chdir 't' if -d 't'; @INC = qw(. ../lib); + require './test.pl'; } use Config; +use Errno; -require "test.pl"; -plan(tests => 8); +plan(tests => 9); ok( binmode(STDERR), 'STDERR made binary' ); if (find PerlIO::Layer 'perlio') { @@ -28,3 +29,12 @@ if (find PerlIO::Layer 'perlio') { } ok( binmode(STDOUT, ":raw"), ' raw' ); ok( binmode(STDOUT, ":crlf"), ' and crlf' ); + +SKIP: { + skip "no EBADF", 1 if (!exists &Errno::EBADF); + + no warnings 'io'; + $! = 0; + binmode(B); + ok($! == &Errno::EBADF); +} diff --git a/t/io/print.t b/t/io/print.t index 0578ee6..f33aa66 100755 --- a/t/io/print.t +++ b/t/io/print.t @@ -1,8 +1,16 @@ #!./perl -print "1..18\n"; +BEGIN { + chdir 't' if -d 't'; + @INC = '../lib'; +} + +use strict 'vars'; +use Errno; + +print "1..19\n"; -$foo = 'STDOUT'; +my $foo = 'STDOUT'; print $foo "ok 1\n"; print "ok 2\n","ok 3\n","ok 4\n"; @@ -14,7 +22,7 @@ print foo "ok 6\n"; printf "ok %d\n",7; printf("ok %d\n",8); -@a = ("ok %d%c",9,ord("\n")); +my @a = ("ok %d%c",9,ord("\n")); printf @a; $a[1] = 10; @@ -25,10 +33,19 @@ $\ = "\n"; print "ok","11"; -@x = ("ok","12\nok","13\nok"); -@y = ("15\nok","16"); +my @x = ("ok","12\nok","13\nok"); +my @y = ("15\nok","16"); print @x,"14\nok",@y; { local $\ = "ok 17\n# null =>[\000]\nok 18\n"; print ""; } + +if (!exists &Errno::EBADF) { + print "ok 19 # skipped: no EBADF\n"; +} else { + $! = 0; + print NONEXISTENT "foo"; + print "not " if ($! != &Errno::EBADF); + print "ok 19\n"; +} diff --git a/t/io/read.t b/t/io/read.t index b27fde1..ea2672d 100755 --- a/t/io/read.t +++ b/t/io/read.t @@ -2,13 +2,22 @@ # $RCSfile$ -print "1..1\n"; +BEGIN { + chdir 't' if -d 't'; + @INC = '../lib'; + require './test.pl'; +} + +use strict; +use Errno; + +plan tests => 2; open(A,"+>a"); print A "_"; seek(A,0,0); -$b = "abcd"; +my $b = "abcd"; $b = ""; read(A,$b,1,4); @@ -17,10 +26,14 @@ close(A); unlink("a"); -if ($b eq "\000\000\000\000_") { - print "ok 1\n"; -} else { # Probably "\000bcd_" - print "not ok 1\n"; -} +is($b,"\000\000\000\000_"); # otherwise probably "\000bcd_" unlink 'a'; + +SKIP: { + skip "no EBADF", 1 if (!exists &Errno::EBADF); + + $! = 0; + read(B,$b,1); + ok($! == &Errno::EBADF); +} diff --git a/t/lib/warnings/pp_sys b/t/lib/warnings/pp_sys index be8bb62..881e81e 100644 --- a/t/lib/warnings/pp_sys +++ b/t/lib/warnings/pp_sys @@ -389,9 +389,18 @@ my $a = sysread(F, $a,10) ; no warnings 'io' ; my $a = sysread(F, $a,10) ; close F ; +use warnings 'io' ; +sysread(F, $a, 10); +read(F, $a, 10); +sysread(NONEXISTENT, $a, 10); +read(NONEXISTENT, $a, 10); unlink $file ; EXPECT Filehandle F opened only for output at - line 12. +sysread() on closed filehandle F at - line 17. +read() on closed filehandle F at - line 18. +sysread() on unopened filehandle NONEXISTENT at - line 19. +read() on unopened filehandle NONEXISTENT at - line 20. ######## # pp_sys.c [pp_binmode] use warnings 'unopened' ;