TAPE: Fix - Tape read reports "end of medium" even if a gap precedes it from Dave Bryan

OBSERVATION:  Calling "sim_tape_rdrecf" to read a tape record sometimes
     returns MTSE_EOM and sets the "position not updated" (PNU) flag, even when
     an erase gap precedes the EOM.  The correct response should be to return
     MTSE_RUNAWAY to indicate that spacing over a gap did not end with a data
     record or tape mark.  Moreover, PNU should not be set, as the position has
     been updated.

     CAUSE:  The routine attempts to handle this case by returning MTSE_RUNAWAY
     if the EOF was detected while reading a buffer of gap markers.  However, if
     a buffer read ends immediately before an EOM marker or the physical EOF,
     the next read attempt will return a zero buffer length.  The routine
     misinterprets this to mean that no gap was present and returns MTSE_EOM and
     sets the PNU flag.

     RESOLUTION:  Modify "sim_tape_rdlntf" (sim_tape.c) to determine whether the
     EOM marker or physical EOF was seen on the first or a subsequent buffer
     read, and to return MTSE_EOM with PNU or MTSE_RUNAWAY without PNU,
     respectively.
This commit is contained in:
Mark Pizzolato 2015-11-25 05:16:13 -08:00
parent 62e36241a4
commit 391c823e79

View file

@ -604,10 +604,10 @@ if (sim_deb && (ctx->dptr->dctrl & reason))
status = operation status status = operation status
exit condition tape position exit condition tape position
------------------ ------------------------------------------- ------------------ -----------------------------------------------------
unit unattached unchanged unit unattached unchanged
read error unchanged, PNU set read error unchanged, PNU set
end of file/medium unchanged, PNU set end of file/medium updated if a gap precedes, else unchanged and PNU set
tape mark updated tape mark updated
tape runaway updated tape runaway updated
data record updated, sim_fread will read record forward data record updated, sim_fread will read record forward
@ -628,7 +628,8 @@ if (sim_deb && (ctx->dptr->dctrl & reason))
then the length is monitored when skipping over erase gaps. If the length then the length is monitored when skipping over erase gaps. If the length
reaches 25 feet, motion is terminated, and MTSE_RUNAWAY status is returned. reaches 25 feet, motion is terminated, and MTSE_RUNAWAY status is returned.
Runaway status is also returned if an end-of-medium marker or the physical Runaway status is also returned if an end-of-medium marker or the physical
end of file is encountered while spacing over a gap. end of file is encountered while spacing over a gap; however, MTSE_EOM is
returned if the tape is positioned at the EOM on entry.
If the density has not been set, then a gap of any length is skipped, and If the density has not been set, then a gap of any length is skipped, and
MTSE_RUNAWAY status is never returned. In effect, erase gaps present in the MTSE_RUNAWAY status is never returned. In effect, erase gaps present in the
@ -670,6 +671,13 @@ if (sim_deb && (ctx->dptr->dctrl & reason))
256 203 256 203
512 186 512 186
1024 171 1024 171
4. Because an erase gap may precede the logical end-of-medium, represented
either by the physical end-of-file or by an EOM marker, the "position not
updated" flag is set only if the tape is positioned at the EOM when the
routine is entered. If at least one gap marker precedes the EOM, then
the PNU flag is not set. This ensures that a backspace-and-retry
sequence will work correctly in both cases.
*/ */
static t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc) static t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc)
@ -708,9 +716,9 @@ switch (f) { /* the read method depen
bufcntr = 0; /* force an initial read */ bufcntr = 0; /* force an initial read */
bufcap = 0; /* but of just one metadata marker */ bufcap = 0; /* but of just one metadata marker */
do { /* loop until a record, gap, or error seen */ do { /* loop until a record, gap, or error is seen */
if (bufcntr == bufcap) { /* if the buffer is empty then refill it */ if (bufcntr == bufcap) { /* if the buffer is empty then refill it */
if (feof (uptr->fileref)) { /* if we hit the EOF while reading gaps */ if (feof (uptr->fileref)) { /* if we hit the EOF while reading a gap */
if (sizeof_gap > 0) /* then if detection is enabled */ if (sizeof_gap > 0) /* then if detection is enabled */
r = MTSE_RUNAWAY; /* then report a tape runaway */ r = MTSE_RUNAWAY; /* then report a tape runaway */
else /* otherwise report the physical EOF */ else /* otherwise report the physical EOF */
@ -731,14 +739,26 @@ switch (f) { /* the read method depen
uptr->fileref); uptr->fileref);
if (ferror (uptr->fileref)) { /* if a file I/O error occurred */ if (ferror (uptr->fileref)) { /* if a file I/O error occurred */
if (bufcntr == 0) /* then if this is the initial read */
MT_SET_PNU (uptr); /* then set position not updated */ MT_SET_PNU (uptr); /* then set position not updated */
r = sim_tape_ioerr (uptr); /* report the error and quit */ r = sim_tape_ioerr (uptr); /* report the error and quit */
break; break;
} }
else if (bufcap == 0) { /* otherwise if nothing was read */ else if (bufcap == 0 /* otherwise if positioned at the physical EOF */
|| buffer [0] == MTR_EOM) /* or at the logical EOM */
if (bufcntr == 0) { /* then if this is the initial read */
MT_SET_PNU (uptr); /* then set position not updated */ MT_SET_PNU (uptr); /* then set position not updated */
r = MTSE_EOM; /* report the end of medium and quit */ r = MTSE_EOM; /* and report the end-of-medium and quit */
break;
}
else { /* otherwise some gap has already been skipped */
if (sizeof_gap > 0) /* so if detection is enabled */
r = MTSE_RUNAWAY; /* then report a tape runaway */
else /* otherwise report the physical EOF */
r = MTSE_EOM; /* as the end-of-medium */
break; break;
} }
@ -749,8 +769,10 @@ switch (f) { /* the read method depen
*bc = buffer [bufcntr++]; /* store the metadata marker value */ *bc = buffer [bufcntr++]; /* store the metadata marker value */
if (*bc == MTR_EOM) { /* if an end-of-medium marker is seen */ if (*bc == MTR_EOM) { /* if an end-of-medium marker is seen */
MT_SET_PNU (uptr); /* then set position not updated */ if (sizeof_gap > 0) /* then if detection is enabled */
r = MTSE_EOM; /* report the end of medium and quit */ r = MTSE_RUNAWAY; /* then report a tape runaway */
else /* otherwise report the physical EOF */
r = MTSE_EOM; /* as the end-of-medium */
break; break;
} }