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