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