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