summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig A. Berry <craigberry@mac.com>2012-03-16 14:20:29 -0500
committerCraig A. Berry <craigberry@mac.com>2012-03-24 14:29:23 -0500
commitfdd4a33e7c504f4b1b8ea9e9c0317055451d7733 (patch)
treeea99989d3ac83ed8df2177483f4a6cf69dc11318
parentabf116bf8d0b86e2c2d1a33fbbe8acc97b53a932 (diff)
downloadperl-tonyc/readline-fixed.tar.gz
Only handle PL_rs differently on VMS for record-oriented files.tonyc/readline-fixed
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.
-rw-r--r--sv.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/sv.c b/sv.c
index 8d5a4170f1..b7149d2f4e 100644
--- a/sv.c
+++ b/sv.c
@@ -7561,22 +7561,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);