diff options
author | Craig A. Berry <craigberry@mac.com> | 2012-03-16 14:20:29 -0500 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2012-12-09 09:32:47 +1100 |
commit | 596a6cbd6bcaa8e6a414f466dc748513439de5da (patch) | |
tree | 70ac616bfc70db709e19dd58c7ab2ca1f5e80986 /sv.c | |
parent | 265c4172cf0ecfa267652bbdb8e7fb7919f14656 (diff) | |
download | perl-596a6cbd6bcaa8e6a414f466dc748513439de5da.tar.gz |
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.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 29 |
1 files changed, 19 insertions, 10 deletions
@@ -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 <rms.h> 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); |