removed local copy of isbad, fixed (?) skip sector handling, need more testing !!
[unix-history] / usr / src / usr.bin / f77 / libU77 / tapeio.c
CommitLineData
58ad378e
DW
1/*
2char 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
22struct 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
53long
54topen_(tlu, name, labelled, len)
55long *tlu;
56char *name;
57long *labelled;
58long 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
100long
101tclose_(tlu)
102long *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
130long
131tread_(tlu, buffer, len)
132long *tlu;
133char *buffer;
134long 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
181long
182twrite_(tlu, buffer, len)
183long *tlu;
184char *buffer;
185long 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
226long
227trewin_(tlu)
228long *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
295long
296tskipf_(tlu, nfiles, nrecs)
297long *tlu;
298long *nfiles;
299long *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
380long
381tstate_(tlu, fileno, recno, err, eof, eot, tcsr)
382long *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}