110232Sdlw /* 2*23050Skre * Copyright (c) 1980 Regents of the University of California. 3*23050Skre * All rights reserved. The Berkeley software License Agreement 4*23050Skre * specifies the terms and conditions for redistribution. 510232Sdlw * 6*23050Skre * @(#)tapeio.c 5.1 06/07/85 7*23050Skre */ 8*23050Skre 9*23050Skre /* 1010232Sdlw * tapeio - tape device specific I/O routines 1110232Sdlw * 1210232Sdlw * ierr = topen (tlu, name, labelled) 1310232Sdlw * ierr = tclose (tlu) 1410232Sdlw * nbytes = tread (tlu, buffer) 1510232Sdlw * nbytes = twrite (tlu, buffer) 1610232Sdlw * ierr = trewin (tlu) 1710232Sdlw * ierr = tskipf (tlu, nfiles, nrecs) 1810232Sdlw * ierr = tstate (tlu, fileno, recno, err, eof, eot, tcsr) 1910232Sdlw */ 2010232Sdlw 2110232Sdlw #include <ctype.h> 2210232Sdlw #include <sys/ioctl.h> 2310414Sdlw #ifndef MTIOCGET /* 4.1+ defines this in ... */ 2410414Sdlw #include <sys/types.h> 2510414Sdlw #include <sys/mtio.h> 2610414Sdlw #endif 2710232Sdlw #include "../libI77/f_errno.h" 2810232Sdlw 2910232Sdlw #define TU_NAMESIZE 22 3010232Sdlw #define TU_MAXTAPES 4 3110232Sdlw 3210232Sdlw struct tunits { 3310232Sdlw char tu_name[TU_NAMESIZE]; /* device name */ 3410232Sdlw int tu_fd; /* file descriptor */ 3510232Sdlw int tu_flags; /* state flags */ 3610232Sdlw int tu_file; /* current tape file number */ 3710232Sdlw int tu_rec; /* current record number in file */ 3810232Sdlw } tunits[TU_MAXTAPES]; 3910232Sdlw 4010232Sdlw #define TU_OPEN 0x1 4110232Sdlw #define TU_EOF 0x2 4210232Sdlw #define TU_ERR 0x4 4310232Sdlw #define TU_READONLY 0x8 4410232Sdlw #define TU_LABELLED 0x10 4510232Sdlw #define TU_WRITING 0x20 4610232Sdlw #define TU_EOT 0x40 4710232Sdlw #define TU_RDATA 0x80 4810232Sdlw 4910414Sdlw #ifdef MTWEOF /* this implies 4.1+ ... */ 5010414Sdlw struct mtget mtget; /* controller status */ 5110414Sdlw #endif 5210414Sdlw 5310232Sdlw /* 5410232Sdlw * Open a tape unit for I/O 5510232Sdlw * 5610232Sdlw * calling format: 5710232Sdlw * integer topen, tlu 5810232Sdlw * character*(*) devnam 5910232Sdlw * logical labled 6010232Sdlw * ierror = topen(tlu, devnam, labled) 6110232Sdlw * where: 6210232Sdlw * ierror will be 0 for successful open; an error number otherwise. 6310232Sdlw * devnam is a character string 6410232Sdlw * labled should be .true. if the tape is labelled. 6510232Sdlw */ 6610232Sdlw 6710232Sdlw long 6810232Sdlw topen_(tlu, name, labelled, len) 6910232Sdlw long *tlu; 7010232Sdlw char *name; 7110232Sdlw long *labelled; 7210232Sdlw long len; 7310232Sdlw { 7410232Sdlw struct tunits *tu; 7510232Sdlw 7610232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 7710232Sdlw errno = F_ERUNIT; 7810232Sdlw return(-1L); 7910232Sdlw } 8010232Sdlw 8110232Sdlw tu = &tunits[*tlu]; 8210232Sdlw if (tu->tu_flags & TU_OPEN) 8310232Sdlw tclose_(tlu); 8410232Sdlw 8510232Sdlw if (len >= TU_NAMESIZE) { 8610232Sdlw errno = F_ERARG; 8710232Sdlw return(-1L); 8810232Sdlw } 8910232Sdlw 9010232Sdlw g_char(name, len, tu->tu_name); 9110232Sdlw 9210232Sdlw if ((tu->tu_fd = open(tu->tu_name, 2)) < 0) { 9310232Sdlw if ((tu->tu_fd = open(tu->tu_name, 0)) < 0) 9410232Sdlw return(-1L); 9510232Sdlw tu->tu_flags |= TU_READONLY; 9610232Sdlw } 9710232Sdlw tu->tu_flags |= TU_OPEN; 9810232Sdlw tu->tu_file = tu->tu_rec = 0; 9910232Sdlw if (*labelled) 10010232Sdlw tu->tu_flags |= TU_LABELLED; 10110232Sdlw return(0L); 10210232Sdlw } 10310232Sdlw 10410232Sdlw /* 10510232Sdlw * Close a tape unit previously opened by topen_() 10610232Sdlw * 10710232Sdlw * calling sequence: 10810232Sdlw * integer tlu, tclose 10910232Sdlw * ierrno = tclose(tlu) 11010232Sdlw * where: 11110232Sdlw * tlu is a previously topened tape logical unit. 11210232Sdlw */ 11310232Sdlw 11410232Sdlw long 11510232Sdlw tclose_(tlu) 11610232Sdlw long *tlu; 11710232Sdlw { 11810232Sdlw struct tunits *tu; 11910232Sdlw 12010232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 12110232Sdlw errno = F_ERUNIT; 12210232Sdlw return(-1L); 12310232Sdlw } 12410232Sdlw 12510232Sdlw tu = &tunits[*tlu]; 12610232Sdlw if (!(tu->tu_flags & TU_OPEN)) 12710232Sdlw return(0L); 12810232Sdlw 12910232Sdlw tu->tu_flags = 0; 13010232Sdlw if (close(tu->tu_fd) < 0) 13110232Sdlw return(-1L); 13210232Sdlw return(0L); 13310232Sdlw } 13410232Sdlw 13510232Sdlw /* 13610232Sdlw * Read from a tape logical unit 13710232Sdlw * 13810232Sdlw * calling sequence: 13910232Sdlw * integer tread, tlu 14010232Sdlw * character*(*) buffer 14110232Sdlw * ierr = tread(tlu, buffer) 14210232Sdlw */ 14310232Sdlw 14410232Sdlw long 14510232Sdlw tread_(tlu, buffer, len) 14610232Sdlw long *tlu; 14710232Sdlw char *buffer; 14810232Sdlw long len; 14910232Sdlw { 15010232Sdlw struct tunits *tu; 15110232Sdlw int nbytes; 15210232Sdlw 15310232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 15410232Sdlw errno = F_ERUNIT; 15510232Sdlw return(-1L); 15610232Sdlw } 15710232Sdlw 15810232Sdlw tu = &tunits[*tlu]; 15910232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 16010232Sdlw errno = F_ERNOPEN; 16110232Sdlw return(-1L); 16210232Sdlw } 16310232Sdlw if (tu->tu_flags & TU_WRITING) { 16410232Sdlw errno = F_ERILLOP; 16510232Sdlw return(-1L); 16610232Sdlw } 16710232Sdlw if (tu->tu_flags & (TU_EOF|TU_EOT)) 16810232Sdlw return(0L); 16910232Sdlw 17010232Sdlw if ((nbytes = read(tu->tu_fd, buffer, (int)len)) > 0) 17110232Sdlw tu->tu_flags |= TU_RDATA; 17210232Sdlw 17310232Sdlw if (nbytes == 0 && len != 0) { 17410232Sdlw tu->tu_flags |= TU_EOF; 17510232Sdlw if (tu->tu_rec == 0) 17610232Sdlw tu->tu_flags |= TU_EOT; 17710232Sdlw } 17810232Sdlw if (nbytes < 0) 17910232Sdlw tu->tu_flags |= TU_ERR; 18010232Sdlw else 18110232Sdlw tu->tu_rec++; 18210232Sdlw 18310232Sdlw return((long)nbytes); 18410232Sdlw } 18510232Sdlw 18610232Sdlw /* 18710232Sdlw * Write to a tape logical unit 18810232Sdlw * 18910232Sdlw * calling sequence: 19010232Sdlw * integer twrite, tlu 19110232Sdlw * character*(*) buffer 19210232Sdlw * ierr = twrite(tlu, buffer) 19310232Sdlw */ 19410232Sdlw 19510232Sdlw long 19610232Sdlw twrite_(tlu, buffer, len) 19710232Sdlw long *tlu; 19810232Sdlw char *buffer; 19910232Sdlw long len; 20010232Sdlw { 20110232Sdlw struct tunits *tu; 20210232Sdlw int nbytes; 20310232Sdlw long nf; 20410232Sdlw long zero = 0L; 20510232Sdlw 20610232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 20710232Sdlw errno = F_ERUNIT; 20810232Sdlw return(-1L); 20910232Sdlw } 21010232Sdlw 21110232Sdlw tu = &tunits[*tlu]; 21210232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 21310232Sdlw errno = F_ERNOPEN; 21410232Sdlw return(-1L); 21510232Sdlw } 21610232Sdlw if (tu->tu_flags & TU_READONLY) { 21710232Sdlw errno = F_ERILLOP; 21810232Sdlw return(-1L); 21910232Sdlw } 22010232Sdlw 22110232Sdlw if (tu->tu_flags & TU_EOT) { /* must backspace over last EOF */ 22210232Sdlw nf = (long)tu->tu_file; /* should be number to skip */ 22310232Sdlw trewin_(tlu); /* KLUDGE!! */ 22410232Sdlw tskipf_(tlu, &nf, &zero); 22510232Sdlw } 22610232Sdlw 22710232Sdlw nbytes = write(tu->tu_fd, buffer, (int)len); 22810232Sdlw if (nbytes <= 0) 22910232Sdlw tu->tu_flags |= TU_ERR; 23010232Sdlw tu->tu_rec++; 23110232Sdlw tu->tu_flags |= TU_WRITING; 23210232Sdlw tu->tu_flags &= ~(TU_EOF|TU_EOT|TU_RDATA); 23310232Sdlw return((long)nbytes); 23410232Sdlw } 23510232Sdlw 23610232Sdlw /* 23710232Sdlw * rewind a tape device 23810232Sdlw */ 23910232Sdlw 24010232Sdlw long 24110232Sdlw trewin_(tlu) 24210232Sdlw long *tlu; 24310232Sdlw { 24410232Sdlw struct tunits *tu; 24510232Sdlw char namebuf[TU_NAMESIZE]; 24610232Sdlw register char *p, *q; 24710232Sdlw int munit; 24810232Sdlw int rfd; 24910232Sdlw long labelled; 25010232Sdlw long one = 1L; 25110232Sdlw long zero = 0L; 25210232Sdlw int save_errno; 25310232Sdlw 25410232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 25510232Sdlw errno = F_ERUNIT; 25610232Sdlw return(-1L); 25710232Sdlw } 25810232Sdlw 25910232Sdlw tu = &tunits[*tlu]; 26010232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 26110232Sdlw errno = F_ERNOPEN; 26210232Sdlw return(-1L); 26310232Sdlw } 26410232Sdlw labelled = (tu->tu_flags & TU_LABELLED); 26510232Sdlw tclose_(tlu); 26610232Sdlw 26710232Sdlw for (p = tu->tu_name, q = namebuf; *p; p++) { 26810232Sdlw if (*p == 'n') /* norewind name */ 26910232Sdlw continue; 27010232Sdlw if (isdigit(*p)) { /* might be norewind minor dev */ 27110232Sdlw munit = 0; 27210232Sdlw while (isdigit(*p)) 27310232Sdlw munit = (10 * munit) + (*p++ - '0'); 27410232Sdlw *q++ = (munit & 03) + '0'; 27510232Sdlw while (*p) 27610232Sdlw *q++ = *p++; 27710232Sdlw break; 27810232Sdlw } 27910232Sdlw *q++ = *p; 28010232Sdlw } 28110232Sdlw *q = '\0'; 28210232Sdlw /* debug printf("rewinding [%s]\n", namebuf); /* */ 28310232Sdlw 28410232Sdlw if ((rfd = open(namebuf, 0)) < 0) 28510232Sdlw save_errno = errno; 28610232Sdlw else { 28710232Sdlw save_errno = 0; 28810232Sdlw close(rfd); 28910232Sdlw } 29010232Sdlw 29110232Sdlw topen_(tlu, tu->tu_name, &labelled, (long)strlen(tu->tu_name)); 29210232Sdlw if (labelled) { 29310232Sdlw tskipf_(tlu, &one, &zero); 29410232Sdlw tu->tu_file = 0; 29510232Sdlw } 29610232Sdlw if (save_errno) { 29710232Sdlw errno = save_errno; 29810232Sdlw return(-1L); 29910232Sdlw } 30010232Sdlw return(0L); 30110232Sdlw } 30210232Sdlw 30310232Sdlw /* 30410232Sdlw * Skip forward files 30510232Sdlw * 30610232Sdlw * NOTE: This is a kludge, to be fixed after 4.1a 30710232Sdlw */ 30810232Sdlw 30910232Sdlw long 31010232Sdlw tskipf_(tlu, nfiles, nrecs) 31110232Sdlw long *tlu; 31210232Sdlw long *nfiles; 31310232Sdlw long *nrecs; 31410232Sdlw { 31510232Sdlw struct tunits *tu; 31610232Sdlw char dummybuf[20]; 31710232Sdlw int nf; 31810232Sdlw int nr; 31910232Sdlw int nb; 32010232Sdlw int empty; 32110232Sdlw 32210232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 32310232Sdlw errno = F_ERUNIT; 32410232Sdlw return(-1L); 32510232Sdlw } 32610232Sdlw 32710232Sdlw tu = &tunits[*tlu]; 32810232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 32910232Sdlw errno = F_ERNOPEN; 33010232Sdlw return(-1L); 33110232Sdlw } 33210232Sdlw if (tu->tu_flags & TU_WRITING) { 33310232Sdlw errno = F_ERILLOP; 33410232Sdlw return(-1L); 33510232Sdlw } 33610232Sdlw 33710232Sdlw nf = (int)*nfiles; 33810232Sdlw while (nf > 0) { 33910232Sdlw if (tu->tu_flags & TU_EOT) { 34010232Sdlw errno = F_ERILLOP; 34110232Sdlw return(-1L); 34210232Sdlw } 34310232Sdlw if (tu->tu_flags & TU_EOF) 34410232Sdlw tu->tu_flags &= ~TU_EOF; 34510232Sdlw else { 34610232Sdlw empty = ((tu->tu_flags & TU_RDATA) == 0); 34710232Sdlw while ((nb = read(tu->tu_fd, dummybuf, sizeof dummybuf)) > 0) 34810232Sdlw empty = 0; 34910232Sdlw 35010232Sdlw if (nb < 0) { 35110232Sdlw tu->tu_flags |= TU_ERR; 35210232Sdlw return(-1L); 35310232Sdlw } 35410232Sdlw if (empty) 35510232Sdlw tu->tu_flags |= TU_EOT; 35610232Sdlw } 35710232Sdlw nf--; 35810232Sdlw tu->tu_rec = 0; 35910232Sdlw tu->tu_flags &= ~TU_RDATA; 36010232Sdlw if (tu->tu_flags & TU_EOT) 36110232Sdlw return(-1L); 36210232Sdlw else 36310232Sdlw tu->tu_file++; 36410232Sdlw } 36510232Sdlw 36610232Sdlw nr = (int)*nrecs; 36710232Sdlw while (nr > 0) { 36810232Sdlw if (tu->tu_flags & (TU_EOT|TU_EOF)) { 36910232Sdlw errno = F_ERILLOP; 37010232Sdlw return(-1L); 37110232Sdlw } 37210232Sdlw 37310232Sdlw empty = ((nb = read(tu->tu_fd, dummybuf, sizeof dummybuf)) <= 0); 37410232Sdlw if (nb < 0) { 37510232Sdlw tu->tu_flags |= TU_ERR; 37610232Sdlw return(-1L); 37710232Sdlw } 37810232Sdlw if (empty) { 37910232Sdlw tu->tu_flags |= TU_EOF; 38010232Sdlw if (!(tu->tu_flags & TU_RDATA)) 38110232Sdlw tu->tu_flags |= TU_EOT; 38210232Sdlw } else 38310232Sdlw tu->tu_flags |= TU_RDATA; 38410232Sdlw nr--; 38510232Sdlw tu->tu_rec++; 38610232Sdlw } 38710232Sdlw return(0L); 38810232Sdlw } 38910232Sdlw 39010232Sdlw /* 39110232Sdlw * Return status of tape channel 39210232Sdlw */ 39310232Sdlw 39410232Sdlw long 39510232Sdlw tstate_(tlu, fileno, recno, err, eof, eot, tcsr) 39610232Sdlw long *tlu, *fileno, *recno, *err, *eof, *eot, *tcsr; 39710232Sdlw { 39810232Sdlw struct tunits *tu; 39910232Sdlw int csr; 40010232Sdlw 40110232Sdlw if (*tlu < 0 || *tlu >= TU_MAXTAPES) { 40210232Sdlw errno = F_ERUNIT; 40310232Sdlw return(-1L); 40410232Sdlw } 40510232Sdlw 40610232Sdlw tu = &tunits[*tlu]; 40710232Sdlw if (!(tu->tu_flags & TU_OPEN)) { 40810232Sdlw errno = F_ERNOPEN; 40910232Sdlw return(-1L); 41010232Sdlw } 41110232Sdlw 41210232Sdlw *fileno = (long)tu->tu_file; 41310232Sdlw *recno = (long)tu->tu_rec; 41410232Sdlw *err = (long)((tu->tu_flags & TU_ERR) != 0); 41510232Sdlw *eof = (long)((tu->tu_flags & TU_EOF) != 0); 41610232Sdlw *eot = (long)((tu->tu_flags & TU_EOT) != 0); 41710414Sdlw #ifdef MTWEOF /* implies 4.1+ system */ 41810414Sdlw ioctl(tu->tu_fd, MTIOCGET, &mtget); 41910414Sdlw *tcsr = (long)mtget.mt_dsreg & 0xffff; 42010414Sdlw #else 42110232Sdlw ioctl(tu->tu_fd, MTIOCGET, &csr); 42210232Sdlw *tcsr = (long)csr; 42310414Sdlw #endif 42410232Sdlw return(0L); 42510232Sdlw } 426