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