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