xref: /csrg-svn/usr.bin/f77/libU77/tapeio.c (revision 47944)
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