Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site umcp-cs.UUCP Path: utzoo!linus!decvax!harpo!seismo!rlgvax!cvl!umcp-cs!chris From: chris@umcp-cs.UUCP Newsgroups: net.unix-wizards Subject: Re: read() from a tape Message-ID: <3757@umcp-cs.UUCP> Date: Sat, 12-Nov-83 19:47:20 EST Article-I.D.: umcp-cs.3757 Posted: Sat Nov 12 19:47:20 1983 Date-Received: Mon, 14-Nov-83 06:57:47 EST References: <120@hsi.UUCP> Organization: Univ. of Maryland, Computer Science Dept. Lines: 185 Re: read () from a tape gives ridiculous return value. Bug is on 4.1BSD and possibly other versions of Unix]. Welcome to the Wonderful World of Weirdness -- tape drives. The 4.1BSD tm.c has a sign extension bug when filling in b->b_resid. CVL has a fixed version of tm.c; here's a diff listing, with my comments, and some irrelevant stuff (Digi-Data stuff, and some error logging) removed. *** /usr/src/sys/dev/tm.c Fri Oct 9 17:24:17 1981 [4.1 version] --- tm.c Sat Nov 12 19:07:53 1983 [CVL's fixed version] *************** This one looks like someone wasn't thinking... *** 100,106 u_short sc_dens; /* prototype command with density info */ daddr_t sc_timo; /* time until timeout expires */ short sc_tact; /* timeout is active */ ! } te_softc[NTM]; #ifdef unneeded int tmgapsdcnt; /* DEBUG */ #endif --- 100,117 ----- u_short sc_dens; /* prototype command with density info */ daddr_t sc_timo; /* time until timeout expires */ short sc_tact; /* timeout is active */ ! } te_softc[NTE]; /* was NTM - JIP, CVL, 12/30/82 */ #ifdef unneeded int tmgapsdcnt; /* DEBUG */ #endif *************** Not all tape drives are the same speed... *** 422,427 * Set next state; give 5 minutes to complete * rewind, or 10 seconds per iteration (minimum 60 * seconds and max 5 minutes) to complete other ops. */ if (bp->b_command == TM_REW) { um->um_tab.b_active = SREW; --- 433,440 ----- * Set next state; give 5 minutes to complete * rewind, or 10 seconds per iteration (minimum 60 * seconds and max 5 minutes) to complete other ops. + * Changed to allow 30 seconds per iteration, 10 min max, + * with 10 min rewind JIP */ if (bp->b_command == TM_REW) { um->um_tab.b_active = SREW; *************** *** 425,431 */ if (bp->b_command == TM_REW) { um->um_tab.b_active = SREW; ! sc->sc_timo = 5 * 60; } else { um->um_tab.b_active = SCOM; sc->sc_timo = --- 438,444 ----- */ if (bp->b_command == TM_REW) { um->um_tab.b_active = SREW; ! sc->sc_timo = 10 * 60; } else { um->um_tab.b_active = SCOM; sc->sc_timo = *************** *** 429,435 } else { um->um_tab.b_active = SCOM; sc->sc_timo = ! imin(imax(10*(int)-bp->b_repcnt,60),5*60); } if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) addr->tmbc = bp->b_repcnt; --- 442,448 ----- } else { um->um_tab.b_active = SCOM; sc->sc_timo = ! imin(imax(30*(int)-bp->b_repcnt,60),10*60); } if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) addr->tmbc = bp->b_repcnt; *************** I'm not sure why this change... maybe it has something to do with the error logging. [note: I collapsed two diff entries] *** 616,622 * If we were reading raw tape and the only error was that the * record was too long, then we don't consider this an error. */ ! if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE) ! goto ignoreerr; /* --- 635,641 ----- * If we were reading raw tape and the only error was that the * record was too long, then we don't consider this an error. */ ! /* if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE) ! goto ignoreerr; JIP CVL */ /* *************** *** 629,635 ubadone(um); goto opcont; } ! } else /* * Hard or non-i/o errors on non-raw tape * cause it to close. --- 656,662 ----- ubadone(um); goto opcont; } ! } else { /* * Hard or non-i/o errors on non-raw tape * cause it to close. *************** *** 634,639 * Hard or non-i/o errors on non-raw tape * cause it to close. */ if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) sc->sc_openf = -1; /* --- 661,668 ----- * Hard or non-i/o errors on non-raw tape * cause it to close. */ + /* JIP CVL */ if ((addr->tmer&TMER_HARD)==0 && + um->um_tab.b_errcnt) goto ignoreerr; if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) sc->sc_openf = -1; } *************** *** 636,641 */ if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) sc->sc_openf = -1; /* * Couldn't recover error */ --- 665,671 ----- um->um_tab.b_errcnt) goto ignoreerr; if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) sc->sc_openf = -1; + } /* * Couldn't recover error */ *************** [This here is your length error.] *** 688,694 */ um->um_tab.b_errcnt = 0; dp->b_actf = bp->av_forw; ! bp->b_resid = -addr->tmbc; ubadone(um); iodone(bp); /* --- 729,739 ----- } #endif ERRORLOG dp->b_actf = bp->av_forw; ! /* allow for long reads JIP */ ! /* compiler bug!! casting as (short unsigned) before assigning to ! * long doesn't do anything. ! */ ! bp->b_resid = (-addr->tmbc) & 0xffff; ubadone(um); iodone(bp); /* -- In-Real-Life: Chris Torek, Univ of MD Comp Sci UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris.umcp-cs@CSNet-Relay