1*10232Sdlw /* 2*10232Sdlw char id_tapeio[] = "@(#)tapeio.c 1.1"; 3*10232Sdlw * 4*10232Sdlw * tapeio - tape device specific I/O routines 5*10232Sdlw * 6*10232Sdlw * ierr = topen (tlu, name, labelled) 7*10232Sdlw * ierr = tclose (tlu) 8*10232Sdlw * nbytes = tread (tlu, buffer) 9*10232Sdlw * nbytes = twrite (tlu, buffer) 10*10232Sdlw * ierr = trewin (tlu) 11*10232Sdlw * ierr = tskipf (tlu, nfiles, nrecs) 12*10232Sdlw * ierr = tstate (tlu, fileno, recno, err, eof, eot, tcsr) 13*10232Sdlw */ 14*10232Sdlw 15*10232Sdlw #include <ctype.h> 16*10232Sdlw #include <sys/ioctl.h> 17*10232Sdlw #include "../libI77/f_errno.h" 18*10232Sdlw 19*10232Sdlw #define TU_NAMESIZE 22 20*10232Sdlw #define TU_MAXTAPES 4 21*10232Sdlw 22*10232Sdlw struct tunits { 23*10232Sdlw char tu_name[TU_NAMESIZE]; /* device name */ 24*10232Sdlw int tu_fd; /* file descriptor */ 25*10232Sdlw int tu_flags; /* state flags */ 26*10232Sdlw int tu_file; /* current tape file number */ 27*10232Sdlw int tu_rec; /* current record number in file */ 28*10232Sdlw } tunits[TU_MAXTAPES]; 29*10232Sdlw 30*10232Sdlw #define TU_OPEN 0x1 31*10232Sdlw #define TU_EOF 0x2 32*10232Sdlw #define TU_ERR 0x4 33*10232Sdlw #define TU_READONLY 0x8 34*10232Sdlw #define TU_LABELLED 0x10 35*10232Sdlw #define TU_WRITING 0x20 36*10232Sdlw #define TU_EOT 0x40 37*10232Sdlw #define TU_RDATA 0x80 38*10232Sdlw 39*10232Sdlw /* 40*10232Sdlw * Open a tape unit for I/O 41*10232Sdlw * 42*10232Sdlw * calling format: 43*10232Sdlw * integer topen, tlu 44*10232Sdlw * character*(*) devnam 45*10232Sdlw * logical labled 46*10232Sdlw * ierror = topen(tlu, devnam, labled) 47*10232Sdlw * where: 48*10232Sdlw * ierror will be 0 for successful open; an error number otherwise. 49*10232Sdlw * devnam is a character string 50*10232Sdlw * labled should be .true. if the tape is labelled. 51*10232Sdlw */ 52*10232Sdlw 53*10232Sdlw long 54*10232Sdlw topen_(tlu, name, labelled, len) 55*10232Sdlw long *tlu; 56*10232Sdlw char *name; 57*10232Sdlw long *labelled; 58*10232Sdlw long len; 59*10232Sdlw { 60*10232Sdlw struct tunits *tu; 61*10232Sdlw 62*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 63*10232Sdlw errno = F_ERUNIT; 64*10232Sdlw return(-1L); 65*10232Sdlw } 66*10232Sdlw 67*10232Sdlw tu = &tunits[*tlu]; 68*10232Sdlw if (tu->tu_flags & TU_OPEN) 69*10232Sdlw tclose_(tlu); 70*10232Sdlw 71*10232Sdlw if (len >= TU_NAMESIZE) { 72*10232Sdlw errno = F_ERARG; 73*10232Sdlw return(-1L); 74*10232Sdlw } 75*10232Sdlw 76*10232Sdlw g_char(name, len, tu->tu_name); 77*10232Sdlw 78*10232Sdlw if ((tu->tu_fd = open(tu->tu_name, 2)) < 0) { 79*10232Sdlw if ((tu->tu_fd = open(tu->tu_name, 0)) < 0) 80*10232Sdlw return(-1L); 81*10232Sdlw tu->tu_flags |= TU_READONLY; 82*10232Sdlw } 83*10232Sdlw tu->tu_flags |= TU_OPEN; 84*10232Sdlw tu->tu_file = tu->tu_rec = 0; 85*10232Sdlw if (*labelled) 86*10232Sdlw tu->tu_flags |= TU_LABELLED; 87*10232Sdlw return(0L); 88*10232Sdlw } 89*10232Sdlw 90*10232Sdlw /* 91*10232Sdlw * Close a tape unit previously opened by topen_() 92*10232Sdlw * 93*10232Sdlw * calling sequence: 94*10232Sdlw * integer tlu, tclose 95*10232Sdlw * ierrno = tclose(tlu) 96*10232Sdlw * where: 97*10232Sdlw * tlu is a previously topened tape logical unit. 98*10232Sdlw */ 99*10232Sdlw 100*10232Sdlw long 101*10232Sdlw tclose_(tlu) 102*10232Sdlw long *tlu; 103*10232Sdlw { 104*10232Sdlw struct tunits *tu; 105*10232Sdlw 106*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 107*10232Sdlw errno = F_ERUNIT; 108*10232Sdlw return(-1L); 109*10232Sdlw } 110*10232Sdlw 111*10232Sdlw tu = &tunits[*tlu]; 112*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) 113*10232Sdlw return(0L); 114*10232Sdlw 115*10232Sdlw tu->tu_flags = 0; 116*10232Sdlw if (close(tu->tu_fd) < 0) 117*10232Sdlw return(-1L); 118*10232Sdlw return(0L); 119*10232Sdlw } 120*10232Sdlw 121*10232Sdlw /* 122*10232Sdlw * Read from a tape logical unit 123*10232Sdlw * 124*10232Sdlw * calling sequence: 125*10232Sdlw * integer tread, tlu 126*10232Sdlw * character*(*) buffer 127*10232Sdlw * ierr = tread(tlu, buffer) 128*10232Sdlw */ 129*10232Sdlw 130*10232Sdlw long 131*10232Sdlw tread_(tlu, buffer, len) 132*10232Sdlw long *tlu; 133*10232Sdlw char *buffer; 134*10232Sdlw long len; 135*10232Sdlw { 136*10232Sdlw struct tunits *tu; 137*10232Sdlw int nbytes; 138*10232Sdlw 139*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 140*10232Sdlw errno = F_ERUNIT; 141*10232Sdlw return(-1L); 142*10232Sdlw } 143*10232Sdlw 144*10232Sdlw tu = &tunits[*tlu]; 145*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 146*10232Sdlw errno = F_ERNOPEN; 147*10232Sdlw return(-1L); 148*10232Sdlw } 149*10232Sdlw if (tu->tu_flags & TU_WRITING) { 150*10232Sdlw errno = F_ERILLOP; 151*10232Sdlw return(-1L); 152*10232Sdlw } 153*10232Sdlw if (tu->tu_flags & (TU_EOF|TU_EOT)) 154*10232Sdlw return(0L); 155*10232Sdlw 156*10232Sdlw if ((nbytes = read(tu->tu_fd, buffer, (int)len)) > 0) 157*10232Sdlw tu->tu_flags |= TU_RDATA; 158*10232Sdlw 159*10232Sdlw if (nbytes == 0 && len != 0) { 160*10232Sdlw tu->tu_flags |= TU_EOF; 161*10232Sdlw if (tu->tu_rec == 0) 162*10232Sdlw tu->tu_flags |= TU_EOT; 163*10232Sdlw } 164*10232Sdlw if (nbytes < 0) 165*10232Sdlw tu->tu_flags |= TU_ERR; 166*10232Sdlw else 167*10232Sdlw tu->tu_rec++; 168*10232Sdlw 169*10232Sdlw return((long)nbytes); 170*10232Sdlw } 171*10232Sdlw 172*10232Sdlw /* 173*10232Sdlw * Write to a tape logical unit 174*10232Sdlw * 175*10232Sdlw * calling sequence: 176*10232Sdlw * integer twrite, tlu 177*10232Sdlw * character*(*) buffer 178*10232Sdlw * ierr = twrite(tlu, buffer) 179*10232Sdlw */ 180*10232Sdlw 181*10232Sdlw long 182*10232Sdlw twrite_(tlu, buffer, len) 183*10232Sdlw long *tlu; 184*10232Sdlw char *buffer; 185*10232Sdlw long len; 186*10232Sdlw { 187*10232Sdlw struct tunits *tu; 188*10232Sdlw int nbytes; 189*10232Sdlw long nf; 190*10232Sdlw long zero = 0L; 191*10232Sdlw 192*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 193*10232Sdlw errno = F_ERUNIT; 194*10232Sdlw return(-1L); 195*10232Sdlw } 196*10232Sdlw 197*10232Sdlw tu = &tunits[*tlu]; 198*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 199*10232Sdlw errno = F_ERNOPEN; 200*10232Sdlw return(-1L); 201*10232Sdlw } 202*10232Sdlw if (tu->tu_flags & TU_READONLY) { 203*10232Sdlw errno = F_ERILLOP; 204*10232Sdlw return(-1L); 205*10232Sdlw } 206*10232Sdlw 207*10232Sdlw if (tu->tu_flags & TU_EOT) { /* must backspace over last EOF */ 208*10232Sdlw nf = (long)tu->tu_file; /* should be number to skip */ 209*10232Sdlw trewin_(tlu); /* KLUDGE!! */ 210*10232Sdlw tskipf_(tlu, &nf, &zero); 211*10232Sdlw } 212*10232Sdlw 213*10232Sdlw nbytes = write(tu->tu_fd, buffer, (int)len); 214*10232Sdlw if (nbytes <= 0) 215*10232Sdlw tu->tu_flags |= TU_ERR; 216*10232Sdlw tu->tu_rec++; 217*10232Sdlw tu->tu_flags |= TU_WRITING; 218*10232Sdlw tu->tu_flags &= ~(TU_EOF|TU_EOT|TU_RDATA); 219*10232Sdlw return((long)nbytes); 220*10232Sdlw } 221*10232Sdlw 222*10232Sdlw /* 223*10232Sdlw * rewind a tape device 224*10232Sdlw */ 225*10232Sdlw 226*10232Sdlw long 227*10232Sdlw trewin_(tlu) 228*10232Sdlw long *tlu; 229*10232Sdlw { 230*10232Sdlw struct tunits *tu; 231*10232Sdlw char namebuf[TU_NAMESIZE]; 232*10232Sdlw register char *p, *q; 233*10232Sdlw int munit; 234*10232Sdlw int rfd; 235*10232Sdlw long labelled; 236*10232Sdlw long one = 1L; 237*10232Sdlw long zero = 0L; 238*10232Sdlw int save_errno; 239*10232Sdlw 240*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 241*10232Sdlw errno = F_ERUNIT; 242*10232Sdlw return(-1L); 243*10232Sdlw } 244*10232Sdlw 245*10232Sdlw tu = &tunits[*tlu]; 246*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 247*10232Sdlw errno = F_ERNOPEN; 248*10232Sdlw return(-1L); 249*10232Sdlw } 250*10232Sdlw labelled = (tu->tu_flags & TU_LABELLED); 251*10232Sdlw tclose_(tlu); 252*10232Sdlw 253*10232Sdlw for (p = tu->tu_name, q = namebuf; *p; p++) { 254*10232Sdlw if (*p == 'n') /* norewind name */ 255*10232Sdlw continue; 256*10232Sdlw if (isdigit(*p)) { /* might be norewind minor dev */ 257*10232Sdlw munit = 0; 258*10232Sdlw while (isdigit(*p)) 259*10232Sdlw munit = (10 * munit) + (*p++ - '0'); 260*10232Sdlw *q++ = (munit & 03) + '0'; 261*10232Sdlw while (*p) 262*10232Sdlw *q++ = *p++; 263*10232Sdlw break; 264*10232Sdlw } 265*10232Sdlw *q++ = *p; 266*10232Sdlw } 267*10232Sdlw *q = '\0'; 268*10232Sdlw /* debug printf("rewinding [%s]\n", namebuf); /* */ 269*10232Sdlw 270*10232Sdlw if ((rfd = open(namebuf, 0)) < 0) 271*10232Sdlw save_errno = errno; 272*10232Sdlw else { 273*10232Sdlw save_errno = 0; 274*10232Sdlw close(rfd); 275*10232Sdlw } 276*10232Sdlw 277*10232Sdlw topen_(tlu, tu->tu_name, &labelled, (long)strlen(tu->tu_name)); 278*10232Sdlw if (labelled) { 279*10232Sdlw tskipf_(tlu, &one, &zero); 280*10232Sdlw tu->tu_file = 0; 281*10232Sdlw } 282*10232Sdlw if (save_errno) { 283*10232Sdlw errno = save_errno; 284*10232Sdlw return(-1L); 285*10232Sdlw } 286*10232Sdlw return(0L); 287*10232Sdlw } 288*10232Sdlw 289*10232Sdlw /* 290*10232Sdlw * Skip forward files 291*10232Sdlw * 292*10232Sdlw * NOTE: This is a kludge, to be fixed after 4.1a 293*10232Sdlw */ 294*10232Sdlw 295*10232Sdlw long 296*10232Sdlw tskipf_(tlu, nfiles, nrecs) 297*10232Sdlw long *tlu; 298*10232Sdlw long *nfiles; 299*10232Sdlw long *nrecs; 300*10232Sdlw { 301*10232Sdlw struct tunits *tu; 302*10232Sdlw char dummybuf[20]; 303*10232Sdlw int nf; 304*10232Sdlw int nr; 305*10232Sdlw int nb; 306*10232Sdlw int empty; 307*10232Sdlw 308*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 309*10232Sdlw errno = F_ERUNIT; 310*10232Sdlw return(-1L); 311*10232Sdlw } 312*10232Sdlw 313*10232Sdlw tu = &tunits[*tlu]; 314*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 315*10232Sdlw errno = F_ERNOPEN; 316*10232Sdlw return(-1L); 317*10232Sdlw } 318*10232Sdlw if (tu->tu_flags & TU_WRITING) { 319*10232Sdlw errno = F_ERILLOP; 320*10232Sdlw return(-1L); 321*10232Sdlw } 322*10232Sdlw 323*10232Sdlw nf = (int)*nfiles; 324*10232Sdlw while (nf > 0) { 325*10232Sdlw if (tu->tu_flags & TU_EOT) { 326*10232Sdlw errno = F_ERILLOP; 327*10232Sdlw return(-1L); 328*10232Sdlw } 329*10232Sdlw if (tu->tu_flags & TU_EOF) 330*10232Sdlw tu->tu_flags &= ~TU_EOF; 331*10232Sdlw else { 332*10232Sdlw empty = ((tu->tu_flags & TU_RDATA) == 0); 333*10232Sdlw while ((nb = read(tu->tu_fd, dummybuf, sizeof dummybuf)) > 0) 334*10232Sdlw empty = 0; 335*10232Sdlw 336*10232Sdlw if (nb < 0) { 337*10232Sdlw tu->tu_flags |= TU_ERR; 338*10232Sdlw return(-1L); 339*10232Sdlw } 340*10232Sdlw if (empty) 341*10232Sdlw tu->tu_flags |= TU_EOT; 342*10232Sdlw } 343*10232Sdlw nf--; 344*10232Sdlw tu->tu_rec = 0; 345*10232Sdlw tu->tu_flags &= ~TU_RDATA; 346*10232Sdlw if (tu->tu_flags & TU_EOT) 347*10232Sdlw return(-1L); 348*10232Sdlw else 349*10232Sdlw tu->tu_file++; 350*10232Sdlw } 351*10232Sdlw 352*10232Sdlw nr = (int)*nrecs; 353*10232Sdlw while (nr > 0) { 354*10232Sdlw if (tu->tu_flags & (TU_EOT|TU_EOF)) { 355*10232Sdlw errno = F_ERILLOP; 356*10232Sdlw return(-1L); 357*10232Sdlw } 358*10232Sdlw 359*10232Sdlw empty = ((nb = read(tu->tu_fd, dummybuf, sizeof dummybuf)) <= 0); 360*10232Sdlw if (nb < 0) { 361*10232Sdlw tu->tu_flags |= TU_ERR; 362*10232Sdlw return(-1L); 363*10232Sdlw } 364*10232Sdlw if (empty) { 365*10232Sdlw tu->tu_flags |= TU_EOF; 366*10232Sdlw if (!(tu->tu_flags & TU_RDATA)) 367*10232Sdlw tu->tu_flags |= TU_EOT; 368*10232Sdlw } else 369*10232Sdlw tu->tu_flags |= TU_RDATA; 370*10232Sdlw nr--; 371*10232Sdlw tu->tu_rec++; 372*10232Sdlw } 373*10232Sdlw return(0L); 374*10232Sdlw } 375*10232Sdlw 376*10232Sdlw /* 377*10232Sdlw * Return status of tape channel 378*10232Sdlw */ 379*10232Sdlw 380*10232Sdlw long 381*10232Sdlw tstate_(tlu, fileno, recno, err, eof, eot, tcsr) 382*10232Sdlw long *tlu, *fileno, *recno, *err, *eof, *eot, *tcsr; 383*10232Sdlw { 384*10232Sdlw struct tunits *tu; 385*10232Sdlw int csr; 386*10232Sdlw 387*10232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 388*10232Sdlw errno = F_ERUNIT; 389*10232Sdlw return(-1L); 390*10232Sdlw } 391*10232Sdlw 392*10232Sdlw tu = &tunits[*tlu]; 393*10232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 394*10232Sdlw errno = F_ERNOPEN; 395*10232Sdlw return(-1L); 396*10232Sdlw } 397*10232Sdlw 398*10232Sdlw *fileno = (long)tu->tu_file; 399*10232Sdlw *recno = (long)tu->tu_rec; 400*10232Sdlw *err = (long)((tu->tu_flags & TU_ERR) != 0); 401*10232Sdlw *eof = (long)((tu->tu_flags & TU_EOF) != 0); 402*10232Sdlw *eot = (long)((tu->tu_flags & TU_EOT) != 0); 403*10232Sdlw ioctl(tu->tu_fd, MTIOCGET, &csr); 404*10232Sdlw *tcsr = (long)csr; 405*10232Sdlw return(0L); 406*10232Sdlw } 407