Commit | Line | Data |
---|---|---|
58ad378e | 1 | /* |
161423a6 RE |
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. | |
58ad378e | 5 | * |
161423a6 RE |
6 | * @(#)tapeio.c 5.1 %G% |
7 | */ | |
8 | ||
9 | /* | |
58ad378e DW |
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> | |
ecbaeb66 DW |
23 | #ifndef MTIOCGET /* 4.1+ defines this in ... */ |
24 | #include <sys/types.h> | |
25 | #include <sys/mtio.h> | |
26 | #endif | |
58ad378e DW |
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 | ||
ecbaeb66 DW |
49 | #ifdef MTWEOF /* this implies 4.1+ ... */ |
50 | struct mtget mtget; /* controller status */ | |
51 | #endif | |
52 | ||
58ad378e DW |
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); | |
ecbaeb66 DW |
417 | #ifdef MTWEOF /* implies 4.1+ system */ |
418 | ioctl(tu->tu_fd, MTIOCGET, &mtget); | |
419 | *tcsr = (long)mtget.mt_dsreg & 0xffff; | |
420 | #else | |
58ad378e DW |
421 | ioctl(tu->tu_fd, MTIOCGET, &csr); |
422 | *tcsr = (long)csr; | |
ecbaeb66 | 423 | #endif |
58ad378e DW |
424 | return(0L); |
425 | } |