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