Restore errno after VMS hack in S_sv_gets_read_record.
authorCraig A. Berry <craigberry@mac.com>
Sat, 23 Mar 2013 01:39:37 +0000 (20:39 -0500)
committerCraig A. Berry <craigberry@mac.com>
Sat, 23 Mar 2013 01:39:37 +0000 (20:39 -0500)
In 596a6cbd6bcaa8e6a4 I added a somewhat desperate hack to detect
if a file is record-oriented so that we preserve record semantics
when PL_rs has beeen set.  I did it by calling fstat(), which is
already a pretty icky thing to be doing on every record read, but
it turns out things are even worse becaseu fstat() sets errno in
some conditions where it's successful, specifically when the file
is a Process-Permanent File (PPF), i.e., standard input or output.

So save errno before the fstat and restore it before doing the
read so if the read fails we get a proper errno.  This gets
t/io/errno.t passing.

Side note: instead of fstat() here, we probably need to store a
pointer to the FAB (File Access Block) in the PerlIO struct so all
the metadata about the file is always accessible.  This would
require setting up completion routines in PerlIOUnix_open and
PerlIOStdio_open.

sv.c

index 3f68d9c..4ed4349 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -7674,6 +7674,7 @@ S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
 #include <rms.h>
     int fd;
     Stat_t st;
+    dSAVE_ERRNO;
 
     /* With a true, record-oriented file on VMS, we need to use read directly
      * to ensure that we respect RMS record boundaries.  The user is responsible
@@ -7688,6 +7689,8 @@ S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append)
            || st.st_fab_rfm == FAB$C_VFC
            || st.st_fab_rfm == FAB$C_FIX)) {
 
+       /* fstat does the equivalent of SETERRNO(EVMSERR, RMS$_IOP) on PPFs. */
+       RESTORE_ERRNO;
        bytesread = PerlLIO_read(fd, buffer, recsize);
     }
     else /* in-memory file from PerlIO::Scalar