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