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
topen_(tlu,name,labelled,len)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
tclose_(tlu)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
tread_(tlu,buffer,len)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
twrite_(tlu,buffer,len)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
trewin_(tlu)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
tskipf_(tlu,nfiles,nrecs)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
tstate_(tlu,fileno,recno,err,eof,eot,tcsr)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