From 596a6cbd6bcaa8e6a414f466dc748513439de5da Mon Sep 17 00:00:00 2001 From: "Craig A. Berry" Date: Fri, 16 Mar 2012 14:20:29 -0500 Subject: [PATCH] Only handle PL_rs differently on VMS for record-oriented files. For stream-oriented files, the effects of buffering and other layers should be exactly as they are on other platforms. For true, record-oriented files, though, setting $/ = \number must provide exactly one low-level read per record. If a read were ever to return less than a full record (due to, for example, filling up the perlio buffer), a subsequent read would get the *next* record, losing whatever data remained in the partially-read record. --- sv.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/sv.c b/sv.c index da10129..c611e97 100644 --- a/sv.c +++ b/sv.c @@ -7671,22 +7671,31 @@ S_sv_gets_read_record(pTHX_ SV *const sv, PerlIO *const fp, I32 append) const STRLEN recsize = SvUV(SvRV(PL_rs)); /* RsRECORD() guarantees > 0. */ /* Grab the size of the record we're getting */ char *buffer = SvGROW(sv, (STRLEN)(recsize + append + 1)) + append; + + /* Go yank in */ #ifdef VMS +#include int fd; -#endif + Stat_t st; - /* Go yank in */ -#ifdef VMS - /* VMS wants read instead of fread, because fread doesn't respect */ - /* RMS record boundaries. This is not necessarily a good thing to be */ - /* doing, but we've got no other real choice - except avoid stdio - as implementation - perhaps write a :vms layer ? - */ + /* 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 + * for providing a PL_rs value that corresponds to the FAB$W_MRS (maximum + * record size) field. N.B. This is likely to produce invalid results on + * varying-width character data when a record ends mid-character. + */ fd = PerlIO_fileno(fp); - if (fd != -1) { + if (fd != -1 + && PerlLIO_fstat(fd, &st) == 0 + && (st.st_fab_rfm == FAB$C_VAR + || st.st_fab_rfm == FAB$C_VFC + || st.st_fab_rfm == FAB$C_FIX)) { + bytesread = PerlLIO_read(fd, buffer, recsize); } - else /* in-memory file from PerlIO::Scalar */ + else /* in-memory file from PerlIO::Scalar + * or not a record-oriented file + */ #endif { bytesread = PerlIO_read(fp, buffer, recsize); -- 2.7.4