1 /* AWSTAPE.C (c) Copyright Roger Bowler, 1999-2009 */
2 /* Hercules Tape Device Handler for AWSTAPE */
3
4 /* Original Author: Roger Bowler */
5 /* Prime Maintainer: Ivan Warren */
6 /* Secondary Maintainer: "Fish" (David B. Trout) */
7
8 /*-------------------------------------------------------------------*/
9 /* This module contains the AWSTAPE emulated tape format support. */
10 /* */
11 /* The subroutines in this module are called by the general tape */
12 /* device handler (tapedev.c) when the tape format is AWSTAPE. */
13 /* */
14 /* Messages issued by this module are prefixed HHCTA1nn */
15 /*-------------------------------------------------------------------*/
16
17 #include "hstdinc.h"
18 #include "hercules.h" /* need Hercules control blocks */
19 #include "tapedev.h" /* Main tape handler header file */
20
21 //#define ENABLE_TRACING_STMTS // (Fish: DEBUGGING)
22
23 #ifdef ENABLE_TRACING_STMTS
24 #if !defined(DEBUG)
25 #warning DEBUG required for ENABLE_TRACING_STMTS
26 #endif
27 // (TRACE, ASSERT, and VERIFY macros are #defined in hmacros.h)
28 #else
29 #undef TRACE
30 #undef ASSERT
31 #undef VERIFY
32 #define TRACE 1 ? ((void)0) : logmsg
33 #define ASSERT(a)
34 #define VERIFY(a) ((void)(a))
35 #endif
36
37 /*********************************************************************/
38 /* START OF ORIGINAL AWS FUNCTIONS (ISW Additions) */
39 /*********************************************************************/
40
41 /*-------------------------------------------------------------------*/
42 /* Close an AWSTAPE format file */
43 /* New Function added by ISW for consistency with other medias */
44 /*-------------------------------------------------------------------*/
close_awstape(DEVBLK * dev)45 void close_awstape (DEVBLK *dev)
46 {
47 if(dev->fd>=0)
48 {
49 logmsg (_("HHCTA101I %4.4X: AWS Tape %s closed\n"),
50 dev->devnum, dev->filename);
51 close(dev->fd);
52 }
53 strcpy(dev->filename, TAPE_UNLOADED);
54 dev->fd=-1;
55 dev->blockid = 0;
56 dev->fenced = 0;
57 return;
58 }
59
60 /*-------------------------------------------------------------------*/
61 /* Rewinds an AWS Tape format file */
62 /* New Function added by ISW for consistency with other medias */
63 /*-------------------------------------------------------------------*/
rewind_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)64 int rewind_awstape (DEVBLK *dev,BYTE *unitstat,BYTE code)
65 {
66 off_t rcoff;
67 rcoff=lseek(dev->fd,0,SEEK_SET);
68 if(rcoff<0)
69 {
70 build_senseX(TAPE_BSENSE_REWINDFAILED,dev,unitstat,code);
71 return -1;
72 }
73 dev->nxtblkpos=0;
74 dev->prvblkpos=-1;
75 dev->curfilen=1;
76 dev->blockid=0;
77 dev->fenced = 0;
78 return 0;
79 }
80
81 /*-------------------------------------------------------------------*/
82 /* Determines if a tape has passed a virtual EOT marker */
83 /* New Function added by ISW for consistency with other medias */
84 /*-------------------------------------------------------------------*/
passedeot_awstape(DEVBLK * dev)85 int passedeot_awstape (DEVBLK *dev)
86 {
87 if(dev->nxtblkpos==0)
88 {
89 dev->eotwarning = 0;
90 return 0;
91 }
92 if(dev->tdparms.maxsize==0)
93 {
94 dev->eotwarning = 0;
95 return 0;
96 }
97 if(dev->nxtblkpos+dev->eotmargin > dev->tdparms.maxsize)
98 {
99 dev->eotwarning = 1;
100 return 1;
101 }
102 dev->eotwarning = 0;
103 return 0;
104 }
105
106 /*********************************************************************/
107 /* START OF ORIGINAL RB AWS FUNCTIONS */
108 /*********************************************************************/
109
110 /*-------------------------------------------------------------------*/
111 /* Open an AWSTAPE format file */
112 /* */
113 /* If successful, the file descriptor is stored in the device block */
114 /* and the return value is zero. Otherwise the return value is -1. */
115 /*-------------------------------------------------------------------*/
open_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)116 int open_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
117 {
118 int rc = -1; /* Return code */
119 char pathname[MAX_PATH]; /* file path in host format */
120
121 /* Check for no tape in drive */
122 if (!strcmp (dev->filename, TAPE_UNLOADED))
123 {
124 build_senseX(TAPE_BSENSE_TAPEUNLOADED,dev,unitstat,code);
125 return -1;
126 }
127
128 /* Open the AWSTAPE file */
129 hostpath(pathname, dev->filename, sizeof(pathname));
130 if(!dev->tdparms.logical_readonly)
131 {
132 rc = hopen(pathname, O_RDWR | O_BINARY);
133 }
134
135 /* If file is read-only, attempt to open again */
136 if (dev->tdparms.logical_readonly || (rc < 0 && (EROFS == errno || EACCES == errno)))
137 {
138 dev->readonly = 1;
139 rc = hopen(pathname, O_RDONLY | O_BINARY);
140 }
141
142 /* Check for successful open */
143 if (rc < 0)
144 {
145 logmsg (_("HHCTA102E %4.4X: Error opening %s: %s\n"),
146 dev->devnum, dev->filename, strerror(errno));
147
148 strcpy(dev->filename, TAPE_UNLOADED);
149 build_senseX(TAPE_BSENSE_TAPELOADFAIL,dev,unitstat,code);
150 return -1;
151 }
152
153 /* Store the file descriptor in the device block */
154 dev->fd = rc;
155 rc=rewind_awstape(dev,unitstat,code);
156 return rc;
157
158 } /* end function open_awstape */
159
160 /*-------------------------------------------------------------------*/
161 /* Read an AWSTAPE block header */
162 /* */
163 /* If successful, return value is zero, and buffer contains header. */
164 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
165 /*-------------------------------------------------------------------*/
readhdr_awstape(DEVBLK * dev,off_t blkpos,AWSTAPE_BLKHDR * buf,BYTE * unitstat,BYTE code)166 int readhdr_awstape (DEVBLK *dev, off_t blkpos,
167 AWSTAPE_BLKHDR *buf, BYTE *unitstat,BYTE code)
168 {
169 int rc; /* Return code */
170 off_t rcoff; /* Return code from lseek() */
171
172 /* Reposition file to the requested block header */
173 rcoff = lseek (dev->fd, blkpos, SEEK_SET);
174 if (rcoff < 0)
175 {
176 /* Handle seek error condition */
177 logmsg (_("HHCTA103E %4.4X: Error seeking to offset "I64_FMTX" "
178 "in file %s: %s\n"),
179 dev->devnum, blkpos, dev->filename, strerror(errno));
180
181 /* Set unit check with equipment check */
182 build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
183 return -1;
184 }
185
186 /* Read the 6-byte block header */
187 rc = read (dev->fd, buf, sizeof(AWSTAPE_BLKHDR));
188
189 /* Handle read error condition */
190 if (rc < 0)
191 {
192 logmsg (_("HHCTA104E %4.4X: Error reading block header "
193 "at offset "I64_FMTX" in file %s: %s\n"),
194 dev->devnum, blkpos, dev->filename, strerror(errno));
195
196 /* Set unit check with equipment check */
197 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
198 return -1;
199 }
200
201 /* Handle end of file (uninitialized tape) condition */
202 if (rc == 0)
203 {
204 logmsg (_("HHCTA105E %4.4X: End of file (end of tape) "
205 "at offset "I64_FMTX" in file %s\n"),
206 dev->devnum, blkpos, dev->filename);
207
208 /* Set unit exception with tape indicate (end of tape) */
209 build_senseX(TAPE_BSENSE_EMPTYTAPE,dev,unitstat,code);
210 return -1;
211 }
212
213 /* Handle end of file within block header */
214 if (rc < (int)sizeof(AWSTAPE_BLKHDR))
215 {
216 logmsg (_("HHCTA106E %4.4X: Unexpected end of file in block header "
217 "at offset "I64_FMTX" in file %s\n"),
218 dev->devnum, blkpos, dev->filename);
219
220 build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code);
221 return -1;
222 }
223
224 /* Successful return */
225 return 0;
226
227 } /* end function readhdr_awstape */
228
229 /*-------------------------------------------------------------------*/
230 /* Read a block from an AWSTAPE format file */
231 /* */
232 /* The block may be formed of one or more block segments each */
233 /* preceded by an AWSTAPE block header. The ENDREC flag in the */
234 /* block header indicates the final segment of the block. */
235 /* */
236 /* If successful, return value is block length read. */
237 /* If a tapemark was read, the return value is zero, and the */
238 /* current file number in the device block is incremented. */
239 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
240 /*-------------------------------------------------------------------*/
read_awstape(DEVBLK * dev,BYTE * buf,BYTE * unitstat,BYTE code)241 int read_awstape (DEVBLK *dev, BYTE *buf, BYTE *unitstat,BYTE code)
242 {
243 int rc; /* Return code */
244 AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */
245 off_t blkpos; /* Offset of block header */
246 int blklen = 0; /* Total length of block */
247 U16 seglen; /* Data length of segment */
248
249 /* Initialize current block position */
250 blkpos = dev->nxtblkpos;
251
252 /* Read block segments until end of block */
253 do
254 {
255 /* Read the 6-byte block header */
256 rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code);
257 if (rc < 0) return -1;
258
259 /* Extract the segment length from the block header */
260 seglen = ((U16)(awshdr.curblkl[1]) << 8)
261 | awshdr.curblkl[0];
262
263 /* Calculate the offset of the next block segment */
264 blkpos += sizeof(awshdr) + seglen;
265
266 /* Check that block length will not exceed buffer size */
267 if (blklen + seglen > MAX_BLKLEN)
268 {
269 logmsg (_("HHCTA107E %4.4X: Block length exceeds %d "
270 "at offset "I64_FMTX" in file %s\n"),
271 dev->devnum,
272 (int)MAX_BLKLEN, blkpos, dev->filename);
273
274 /* Set unit check with data check */
275 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
276 return -1;
277 }
278
279 /* Check that tapemark blocksize is zero */
280 if ((awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK)
281 && blklen + seglen > 0)
282 {
283 logmsg (_("HHCTA108E %4.4X: Invalid tapemark "
284 "at offset "I64_FMTX" in file %s\n"),
285 dev->devnum, blkpos, dev->filename);
286
287 /* Set unit check with data check */
288 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
289 return -1;
290 }
291
292 /* Exit loop if this is a tapemark */
293 if (awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK)
294 break;
295
296 /* Read data block segment from tape file */
297 rc = read (dev->fd, buf+blklen, seglen);
298
299 /* Handle read error condition */
300 if (rc < 0)
301 {
302 logmsg (_("HHCTA109E %4.4X: Error reading data block "
303 "at offset "I64_FMTX" in file %s: %s\n"),
304 dev->devnum, blkpos, dev->filename, strerror(errno));
305
306 /* Set unit check with equipment check */
307 build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code);
308 return -1;
309 }
310
311 /* Handle end of file within data block */
312 if (rc < seglen)
313 {
314 logmsg (_("HHCTA110E %4.4X: Unexpected end of file in data block "
315 "at offset "I64_FMTX" in file %s\n"),
316 dev->devnum, blkpos, dev->filename);
317
318 /* Set unit check with data check and partial record */
319 build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code);
320 return -1;
321 }
322
323 /* Accumulate the total block length */
324 blklen += seglen;
325
326 } while ((awshdr.flags1 & AWSTAPE_FLAG1_ENDREC) == 0);
327
328 /* Calculate the offsets of the next and previous blocks */
329 dev->prvblkpos = dev->nxtblkpos;
330 dev->nxtblkpos = blkpos;
331
332 /* Increment the block number */
333 dev->blockid++;
334
335 /* Increment file number and return zero if tapemark was read */
336 if (blklen == 0)
337 {
338 dev->curfilen++;
339 return 0; /* UX will be set by caller */
340 }
341
342 /* Return block length */
343 return blklen;
344
345 } /* end function read_awstape */
346
347 /*-------------------------------------------------------------------*/
348 /* Write a block to an AWSTAPE format file */
349 /* */
350 /* If successful, return value is zero. */
351 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
352 /*-------------------------------------------------------------------*/
write_awstape(DEVBLK * dev,BYTE * buf,U16 blklen,BYTE * unitstat,BYTE code)353 int write_awstape (DEVBLK *dev, BYTE *buf, U16 blklen,
354 BYTE *unitstat,BYTE code)
355 {
356 int rc; /* Return code */
357 off_t rcoff; /* Return code from lseek() */
358 AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */
359 off_t blkpos; /* Offset of block header */
360 U16 prvblkl; /* Length of previous block */
361
362 /* Initialize current block position and previous block length */
363 blkpos = dev->nxtblkpos;
364 prvblkl = 0;
365
366 /* Determine previous block length if not at start of tape */
367 if (dev->nxtblkpos > 0)
368 {
369 /* Reread the previous block header */
370 rc = readhdr_awstape (dev, dev->prvblkpos, &awshdr, unitstat,code);
371 if (rc < 0) return -1;
372
373 /* Extract the block length from the block header */
374 prvblkl = ((U16)(awshdr.curblkl[1]) << 8)
375 | awshdr.curblkl[0];
376
377 /* Recalculate the offset of the next block */
378 blkpos = dev->prvblkpos + sizeof(awshdr) + prvblkl;
379 }
380
381 /* Reposition file to the new block header */
382 rcoff = lseek (dev->fd, blkpos, SEEK_SET);
383 if (rcoff < 0)
384 {
385 /* Handle seek error condition */
386 logmsg (_("HHCTA111E %4.4X: Error seeking to offset "I64_FMTX" "
387 "in file %s: %s\n"),
388 dev->devnum, blkpos, dev->filename, strerror(errno));
389
390 /* Set unit check with equipment check */
391 build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
392 return -1;
393 }
394 /* ISW: Determine if we are passed maxsize */
395 if(dev->tdparms.maxsize>0)
396 {
397 if((off_t)(dev->nxtblkpos+blklen+sizeof(awshdr)) > dev->tdparms.maxsize)
398 {
399 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
400 return -1;
401 }
402 }
403 /* ISW: End of virtual physical EOT determination */
404
405 /* Build the 6-byte block header */
406 awshdr.curblkl[0] = blklen & 0xFF;
407 awshdr.curblkl[1] = (blklen >> 8) & 0xFF;
408 awshdr.prvblkl[0] = prvblkl & 0xFF;
409 awshdr.prvblkl[1] = (prvblkl >>8) & 0xFF;
410 awshdr.flags1 = AWSTAPE_FLAG1_NEWREC | AWSTAPE_FLAG1_ENDREC;
411 awshdr.flags2 = 0;
412
413 /* Write the block header */
414 rc = write (dev->fd, &awshdr, sizeof(awshdr));
415 if (rc < (int)sizeof(awshdr))
416 {
417 if(errno==ENOSPC)
418 {
419 /* Disk FULL */
420 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
421 logmsg (_("HHCTA112E %4.4X: Media full condition reached "
422 "at offset "I64_FMTX" in file %s\n"),
423 dev->devnum, blkpos, dev->filename);
424 return -1;
425 }
426
427 /* Handle write error condition */
428 logmsg (_("HHCTA113E %4.4X: Error writing block header "
429 "at offset "I64_FMTX" in file %s: %s\n"),
430 dev->devnum, blkpos, dev->filename, strerror(errno));
431
432 /* Set unit check with equipment check */
433 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
434 return -1;
435 }
436
437 /* Calculate the offsets of the next and previous blocks */
438 dev->nxtblkpos = blkpos + sizeof(awshdr) + blklen;
439 dev->prvblkpos = blkpos;
440
441 /* Write the data block */
442 rc = write (dev->fd, buf, blklen);
443 if (rc < blklen)
444 {
445 if(errno==ENOSPC)
446 {
447 /* Disk FULL */
448 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
449 logmsg (_("HHCTA114E %4.4X: Media full condition reached "
450 "at offset "I64_FMTX" in file %s\n"),
451 dev->devnum, blkpos, dev->filename);
452 return -1;
453 }
454
455 /* Handle write error condition */
456 logmsg (_("HHCTA115E %4.4X: Error writing data block "
457 "at offset "I64_FMTX" in file %s: %s\n"),
458 dev->devnum, blkpos, dev->filename, strerror(errno));
459
460 /* Set unit check with equipment check */
461 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
462 return -1;
463 }
464
465 dev->blockid++;
466
467 /* Set new physical EOF */
468 do rc = ftruncate( dev->fd, dev->nxtblkpos );
469 while (EINTR == rc);
470
471 if (rc != 0)
472 {
473 /* Handle write error condition */
474 logmsg (_("HHCTA116E %4.4X: Error writing data block "
475 "at offset "I64_FMTX" in file %s: %s\n"),
476 dev->devnum, blkpos, dev->filename, strerror(errno));
477
478 /* Set unit check with equipment check */
479 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
480 return -1;
481 }
482
483 /* Return normal status */
484 return 0;
485
486 } /* end function write_awstape */
487
488 /*-------------------------------------------------------------------*/
489 /* Write a tapemark to an AWSTAPE format file */
490 /* */
491 /* If successful, return value is zero. */
492 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
493 /*-------------------------------------------------------------------*/
write_awsmark(DEVBLK * dev,BYTE * unitstat,BYTE code)494 int write_awsmark (DEVBLK *dev, BYTE *unitstat,BYTE code)
495 {
496 int rc; /* Return code */
497 off_t rcoff; /* Return code from lseek() */
498 AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */
499 off_t blkpos; /* Offset of block header */
500 U16 prvblkl; /* Length of previous block */
501
502 /* Initialize current block position and previous block length */
503 blkpos = dev->nxtblkpos;
504 prvblkl = 0;
505
506 /* Determine previous block length if not at start of tape */
507 if (dev->nxtblkpos > 0)
508 {
509 /* Reread the previous block header */
510 rc = readhdr_awstape (dev, dev->prvblkpos, &awshdr, unitstat,code);
511 if (rc < 0) return -1;
512
513 /* Extract the block length from the block header */
514 prvblkl = ((U16)(awshdr.curblkl[1]) << 8)
515 | awshdr.curblkl[0];
516
517 /* Recalculate the offset of the next block */
518 blkpos = dev->prvblkpos + sizeof(awshdr) + prvblkl;
519 }
520
521 /* Reposition file to the new block header */
522 rcoff = lseek (dev->fd, blkpos, SEEK_SET);
523 if (rcoff < 0)
524 {
525 /* Handle seek error condition */
526 logmsg (_("HHCTA117E %4.4X: Error seeking to offset "I64_FMTX" "
527 "in file %s: %s\n"),
528 dev->devnum, blkpos, dev->filename, strerror(errno));
529
530 build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code);
531 return -1;
532 }
533 /* ISW: Determine if we are passed maxsize */
534 if(dev->tdparms.maxsize>0)
535 {
536 if((off_t)(dev->nxtblkpos+sizeof(awshdr)) > dev->tdparms.maxsize)
537 {
538 build_senseX(TAPE_BSENSE_ENDOFTAPE,dev,unitstat,code);
539 return -1;
540 }
541 }
542 /* ISW: End of virtual physical EOT determination */
543
544 /* Build the 6-byte block header */
545 awshdr.curblkl[0] = 0;
546 awshdr.curblkl[1] = 0;
547 awshdr.prvblkl[0] = prvblkl & 0xFF;
548 awshdr.prvblkl[1] = (prvblkl >>8) & 0xFF;
549 awshdr.flags1 = AWSTAPE_FLAG1_TAPEMARK;
550 awshdr.flags2 = 0;
551
552 /* Write the block header */
553 rc = write (dev->fd, &awshdr, sizeof(awshdr));
554 if (rc < (int)sizeof(awshdr))
555 {
556 /* Handle write error condition */
557 logmsg (_("HHCTA118E %4.4X: Error writing block header "
558 "at offset "I64_FMTX" in file %s: %s\n"),
559 dev->devnum, blkpos, dev->filename, strerror(errno));
560
561 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
562 return -1;
563 }
564
565 dev->blockid++;
566
567 /* Calculate the offsets of the next and previous blocks */
568 dev->nxtblkpos = blkpos + sizeof(awshdr);
569 dev->prvblkpos = blkpos;
570
571 /* Set new physical EOF */
572 do rc = ftruncate( dev->fd, dev->nxtblkpos );
573 while (EINTR == rc);
574
575 if (rc != 0)
576 {
577 /* Handle write error condition */
578 logmsg (_("HHCTA119E Error writing tape mark "
579 "at offset "I64_FMTX" in file %s: %s\n"),
580 blkpos, dev->filename, strerror(errno));
581
582 /* Set unit check with equipment check */
583 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
584 return -1;
585 }
586
587 /* Return normal status */
588 return 0;
589
590 } /* end function write_awsmark */
591
592 /*-------------------------------------------------------------------*/
593 /* Synchronize an AWSTAPE format file (i.e. flush buffers to disk) */
594 /* */
595 /* If successful, return value is zero. */
596 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
597 /*-------------------------------------------------------------------*/
sync_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)598 int sync_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
599 {
600 /* Unit check if tape is write-protected */
601 if (dev->readonly)
602 {
603 build_senseX(TAPE_BSENSE_WRITEPROTECT,dev,unitstat,code);
604 return -1;
605 }
606
607 /* Perform sync. Return error on failure. */
608 if (fdatasync( dev->fd ) < 0)
609 {
610 /* Log the error */
611 logmsg (_("HHCTA120E %4.4X: Sync error on file %s: %s\n"),
612 dev->devnum, dev->filename, strerror(errno));
613 /* Set unit check with equipment check */
614 build_senseX(TAPE_BSENSE_WRITEFAIL,dev,unitstat,code);
615 return -1;
616 }
617
618 /* Return normal status */
619 return 0;
620
621 } /* end function sync_awstape */
622
623 /*-------------------------------------------------------------------*/
624 /* Forward space over next block of AWSTAPE format file */
625 /* */
626 /* If successful, return value is the length of the block skipped. */
627 /* If the block skipped was a tapemark, the return value is zero, */
628 /* and the current file number in the device block is incremented. */
629 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
630 /*-------------------------------------------------------------------*/
fsb_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)631 int fsb_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
632 {
633 int rc; /* Return code */
634 AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */
635 off_t blkpos; /* Offset of block header */
636 int blklen = 0; /* Total length of block */
637 U16 seglen; /* Data length of segment */
638
639 /* Initialize current block position */
640 blkpos = dev->nxtblkpos;
641
642 /* Read block segments until end of block */
643 do
644 {
645 /* Read the 6-byte block header */
646 rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code);
647 if (rc < 0) return -1;
648
649 /* Extract the block length from the block header */
650 seglen = ((U16)(awshdr.curblkl[1]) << 8)
651 | awshdr.curblkl[0];
652
653 /* Calculate the offset of the next block segment */
654 blkpos += sizeof(awshdr) + seglen;
655
656 /* Accumulate the total block length */
657 blklen += seglen;
658
659 /* Exit loop if this is a tapemark */
660 if (awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK)
661 break;
662
663 } while ((awshdr.flags1 & AWSTAPE_FLAG1_ENDREC) == 0);
664
665 /* Calculate the offsets of the next and previous blocks */
666 dev->prvblkpos = dev->nxtblkpos;
667 dev->nxtblkpos = blkpos;
668
669 /* Increment current file number if tapemark was skipped */
670 if (blklen == 0)
671 dev->curfilen++;
672
673 dev->blockid++;
674
675 /* Return block length or zero if tapemark */
676 return blklen;
677
678 } /* end function fsb_awstape */
679
680 /*-------------------------------------------------------------------*/
681 /* Backspace to previous block of AWSTAPE format file */
682 /* */
683 /* If successful, return value is the length of the block. */
684 /* If the block is a tapemark, the return value is zero, */
685 /* and the current file number in the device block is decremented. */
686 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
687 /*-------------------------------------------------------------------*/
bsb_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)688 int bsb_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
689 {
690 int rc; /* Return code */
691 AWSTAPE_BLKHDR awshdr; /* AWSTAPE block header */
692 U16 curblkl; /* Length of current block */
693 U16 prvblkl; /* Length of previous block */
694 off_t blkpos; /* Offset of block header */
695
696 /* Unit check if already at start of tape */
697 if (dev->nxtblkpos == 0)
698 {
699 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
700 return -1;
701 }
702
703 /* Backspace to previous block position */
704 blkpos = dev->prvblkpos;
705
706 /* Read the 6-byte block header */
707 rc = readhdr_awstape (dev, blkpos, &awshdr, unitstat,code);
708 if (rc < 0) return -1;
709
710 /* Extract the block lengths from the block header */
711 curblkl = ((U16)(awshdr.curblkl[1]) << 8)
712 | awshdr.curblkl[0];
713 prvblkl = ((U16)(awshdr.prvblkl[1]) << 8)
714 | awshdr.prvblkl[0];
715
716 /* Calculate the offset of the previous block */
717 dev->prvblkpos = blkpos - sizeof(awshdr) - prvblkl;
718 dev->nxtblkpos = blkpos;
719
720 /* Decrement current file number if backspaced over tapemark */
721 if (curblkl == 0)
722 dev->curfilen--;
723
724 dev->blockid--;
725
726 /* Return block length or zero if tapemark */
727 return curblkl;
728
729 } /* end function bsb_awstape */
730
731 /*-------------------------------------------------------------------*/
732 /* Forward space to next logical file of AWSTAPE format file */
733 /* */
734 /* For AWSTAPE files, the forward space file operation is achieved */
735 /* by forward spacing blocks until positioned just after a tapemark. */
736 /* */
737 /* If successful, return value is zero, and the current file number */
738 /* in the device block is incremented by fsb_awstape. */
739 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
740 /*-------------------------------------------------------------------*/
fsf_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)741 int fsf_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
742 {
743 int rc; /* Return code */
744
745 while (1)
746 {
747 /* Forward space over next block */
748 rc = fsb_awstape (dev, unitstat,code);
749 if (rc < 0) return -1;
750
751 /* Exit loop if spaced over a tapemark */
752 if (rc == 0) break;
753
754 } /* end while */
755
756 /* Return normal status */
757 return 0;
758
759 } /* end function fsf_awstape */
760
761 /*-------------------------------------------------------------------*/
762 /* Backspace to previous logical file of AWSTAPE format file */
763 /* */
764 /* For AWSTAPE files, the backspace file operation is achieved */
765 /* by backspacing blocks until positioned just before a tapemark */
766 /* or until positioned at start of tape. */
767 /* */
768 /* If successful, return value is zero, and the current file number */
769 /* in the device block is decremented by bsb_awstape. */
770 /* If error, return value is -1 and unitstat is set to CE+DE+UC */
771 /*-------------------------------------------------------------------*/
bsf_awstape(DEVBLK * dev,BYTE * unitstat,BYTE code)772 int bsf_awstape (DEVBLK *dev, BYTE *unitstat,BYTE code)
773 {
774 int rc; /* Return code */
775
776 while (1)
777 {
778 /* Exit if now at start of tape */
779 if (dev->nxtblkpos == 0)
780 {
781 build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code);
782 return -1;
783 }
784
785 /* Backspace to previous block position */
786 rc = bsb_awstape (dev, unitstat,code);
787 if (rc < 0) return -1;
788
789 /* Exit loop if backspaced over a tapemark */
790 if (rc == 0) break;
791
792 } /* end while */
793
794 /* Return normal status */
795 return 0;
796
797 } /* end function bsf_awstape */
798
799 /*********************************************************************/
800 /* END OF ORIGINAL RB AWS FUNCTIONS */
801 /*********************************************************************/
802