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