summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorCraig A. Berry <craigberry@mac.com>2012-03-16 14:20:29 -0500
committerTony Cook <tony@develop-help.com>2012-12-09 09:32:47 +1100
commit596a6cbd6bcaa8e6a414f466dc748513439de5da (patch)
tree70ac616bfc70db709e19dd58c7ab2ca1f5e80986 /sv.c
parent265c4172cf0ecfa267652bbdb8e7fb7919f14656 (diff)
downloadperl-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.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/sv.c b/sv.c
index da10129802..c611e97274 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 <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);