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