/*-------------------------------------------------------------------*/ int read_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *buf, BYTE *unitstat,BYTE code) { int rc; /* Return code */ long blkpos; /* Offset to block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Read the 16-byte block header */ blkpos = dev->nxtblkpos; rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = nxthdro; dev->prvblkpos = blkpos; /* Increment file number and return zero if tapemark */ if (curblkl == -1) { close (dev->fd); dev->fd = -1; dev->curfilen++; dev->nxtblkpos = 0; dev->prvblkpos = -1; return 0; } /* Read data block from tape file */ rc = read (dev->fd, buf, curblkl); /* Handle read error condition */ if (rc < 0) { WRMSG (HHC00204, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, omadesc->filename, "oma", "read()", (off_t)blkpos, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_READFAIL,dev,unitstat,code); return -1; } /* Handle end of file within data block */ if (rc < curblkl) { WRMSG(HHC00204, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, omadesc->filename, "oma", "read_omaheaders()", (off_t)blkpos, "unexpected end of file"); /* Set unit check with data check and partial record */ build_senseX(TAPE_BSENSE_BLOCKSHORT,dev,unitstat,code); return -1; } /* Return block length */ return curblkl; } /* end function read_omaheaders */
/*-------------------------------------------------------------------*/ int fsb_omaheaders (DEVBLK *dev, OMATAPE_DESC *omadesc, BYTE *unitstat,BYTE code) { int rc; /* Return code */ long blkpos; /* Offset of block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Initialize current block position */ blkpos = dev->nxtblkpos; /* Read the 16-byte block header */ rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; /* Check if tapemark was skipped */ if (curblkl == -1) { /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Increment the file number */ dev->curfilen++; /* Return zero to indicate tapemark */ return 0; } /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = nxthdro; dev->prvblkpos = blkpos; /* Return block length */ return curblkl; } /* end function fsb_omaheaders */
/*-------------------------------------------------------------------*/ int bsb_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ long blkpos; /* Offset of block header */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); /* Backspace file if current position is at start of file */ if (dev->nxtblkpos == 0) { /* Unit check if already at start of tape */ if (dev->curfilen <= 1) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Perform backspace file operation */ rc = bsf_omatape (dev, unitstat,code); if (rc < 0) return -1; dev->blockid--; /* Return zero to indicate tapemark detected */ return 0; } /* Unit check if previous block position is unknown */ if (dev->prvblkpos < 0) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Backspace to previous block position */ blkpos = dev->prvblkpos; /* Determine new previous block position */ switch (omadesc->format) { case 'H': /* For OMA headers files, read the previous block header to extract the block length and new previous block offset */ rc = readhdr_omaheaders (dev, omadesc, blkpos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; break; case 'F': /* For OMA fixed block files, calculate the new previous block offset by subtracting the fixed block length */ if (blkpos >= omadesc->blklen) prvhdro = blkpos - omadesc->blklen; else prvhdro = -1; break; case 'T': /* For OMA ASCII text files, new previous block is unknown */ prvhdro = -1; break; } /* end switch(omadesc->format) */ /* Update the offsets of the next and previous blocks */ dev->nxtblkpos = blkpos; dev->prvblkpos = prvhdro; dev->blockid--; /* Return +1 to indicate backspace successful */ return +1; } /* end function bsb_omatape */
/*-------------------------------------------------------------------*/ int bsf_omatape (DEVBLK *dev, BYTE *unitstat,BYTE code) { int rc; /* Return code */ off_t pos; /* File position */ OMATAPE_DESC *omadesc; /* -> OMA descriptor entry */ S32 curblkl; /* Length of current block */ S32 prvhdro; /* Offset of previous header */ S32 nxthdro; /* Offset of next header */ /* Close the current OMA file */ if (dev->fd >= 0) close (dev->fd); dev->fd = -1; dev->nxtblkpos = 0; dev->prvblkpos = -1; /* Exit with tape at load point if currently on first file */ if (dev->curfilen <= 1) { build_senseX(TAPE_BSENSE_LOADPTERR,dev,unitstat,code); return -1; } /* Decrement current file number */ dev->curfilen--; /* Point to the current file entry in the OMA descriptor table */ omadesc = (OMATAPE_DESC*)(dev->omadesc); omadesc += (dev->curfilen-1); /* Open the new current file */ rc = open_omatape (dev, unitstat,code); if (rc < 0) return rc; /* Reposition before tapemark header at end of file, or to end of file for fixed block or ASCII text files */ pos = 0; if ( 'H' == omadesc->format ) pos -= sizeof(OMATAPE_BLKHDR); pos = lseek (dev->fd, pos, SEEK_END); if (pos < 0) { /* Handle seek error condition */ logmsg (_("HHCTA265E %4.4X: Error seeking to end of file %s: %s\n"), dev->devnum, omadesc->filename, strerror(errno)); /* Set unit check with equipment check */ build_senseX(TAPE_BSENSE_LOCATEERR,dev,unitstat,code); dev->sense[0] = SENSE_EC; *unitstat = CSW_CE | CSW_DE | CSW_UC; return -1; } dev->nxtblkpos = pos; dev->prvblkpos = -1; /* Determine the offset of the previous block */ switch (omadesc->format) { case 'H': /* For OMA headers files, read the tapemark header and extract the previous block offset */ rc = readhdr_omaheaders (dev, omadesc, pos, &curblkl, &prvhdro, &nxthdro, unitstat,code); if (rc < 0) return -1; dev->prvblkpos = prvhdro; break; case 'F': /* For OMA fixed block files, calculate the previous block offset allowing for a possible short final block */ pos = (pos + omadesc->blklen - 1) / omadesc->blklen; dev->prvblkpos = (pos > 0 ? (pos - 1) * omadesc->blklen : -1); break; case 'T': /* For OMA ASCII text files, the previous block is unknown */ dev->prvblkpos = -1; break; } /* end switch(omadesc->format) */ /* Return normal status */ return 0; } /* end function bsf_omatape */