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