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