mirror of
https://github.com/SDL-Hercules-390/hyperion.git
synced 2026-04-07 12:43:39 +02:00
788 lines
25 KiB
C
788 lines
25 KiB
C
/* FTLIB.C (C) Copyright TurboHercules, SAS 2010-2011 */
|
|
/* Hercules Tape Function Lib for FAKETAPE */
|
|
/* */
|
|
/* Released under "The Q Public License Version 1" */
|
|
/* (http://www.hercules-390.org/herclic.html) as modifications to */
|
|
/* Hercules. */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* This module contains the FAKETAPE emulated tape format library. */
|
|
/* Note: this library was built from the original FAKETAPE.C source. */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Reference information: */
|
|
/* FSIMS100 Faketape manual */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
#include "hstdinc.h"
|
|
|
|
#define _FTLIB_C_
|
|
#define _HTAPE_DLL_
|
|
|
|
#include "hercules.h" /* need Hercules control blocks */
|
|
#include "ftlib.h" /* Main faketape header file */
|
|
|
|
// Local constant data NOTE: Keep in sync with hetlib.c
|
|
|
|
static const char *fet_errstr[] =
|
|
{
|
|
"No error", // FETE_OK
|
|
"File error", // FETE_ERROR
|
|
"Tapemark read", // FETE_TAPEMARK
|
|
"Beginning of tape", // FETE_BOT
|
|
"End of tape", // FETE_EOT
|
|
"BOR not found", // FETE_BADBOR
|
|
"EOR not found", // FETE_BADEOR
|
|
"Unexpected tapemark", // FETE_BADMARK
|
|
"Buffer not big enough", // FETE_OVERFLOW
|
|
"Premature EOF", // FETE_PREMEOF
|
|
"Decompression error",
|
|
"Unknown compression method",
|
|
"Compression error",
|
|
"Specified length to big", // FETE_BADLEN
|
|
"Write protected", // FETE_PROTECTED
|
|
"Bad function code passed", // FETE_BADFUNC
|
|
"Bad compression method",
|
|
"Bad compression level",
|
|
"Bad write chunk size",
|
|
"Invalid direction specified", // FETE_BADDIR
|
|
"Insufficient memory", // FETE_NOMEM
|
|
"Couldn't read block header", // FETE_BADHDR
|
|
"Inconsistent compression flags",
|
|
"Block is short", // FETE_BADBLOCK
|
|
"Location error", // FETE_BADLOC
|
|
"Invalid error code", // unknown error
|
|
};
|
|
#define FET_ERRSTR_MAX ( sizeof( fet_errstr) / sizeof( fet_errstr[ 0 ] ) )
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Open a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, the file descriptor is stored in the device block */
|
|
/* and the return value is zero. Otherwise the return value is < 0. */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_open ( FETB **fetb, char *filename, int flags )
|
|
{
|
|
int rc = -1; /* Return code */
|
|
char pathname[MAX_PATH]; /* file path in host format */
|
|
FETB *tfetb;
|
|
char *omode;
|
|
int oflags;
|
|
|
|
|
|
/* Open the FAKETAPE file */
|
|
*fetb = NULL;
|
|
|
|
hostpath(pathname, filename, sizeof(pathname));
|
|
|
|
/*
|
|
|| Allocate a new FETB
|
|
*/
|
|
tfetb = calloc( 1, sizeof( FETB ) );
|
|
if( tfetb == NULL )
|
|
{
|
|
return( FETE_NOMEM );
|
|
}
|
|
|
|
/* Initialize FETB */
|
|
tfetb->fd = -1;
|
|
|
|
/*
|
|
|| clear FETOPEN_CREATE if FETOPEN_READONLY is specified
|
|
*/
|
|
if(flags & FETOPEN_READONLY)
|
|
{
|
|
flags&=~FETOPEN_CREATE;
|
|
}
|
|
/*
|
|
|| Translate HET create flag to filesystem flag
|
|
*/
|
|
oflags = ( ( flags & FETOPEN_CREATE ) ? O_CREAT : 0 );
|
|
|
|
omode = "r+b";
|
|
if( !( flags & FETOPEN_READONLY ) )
|
|
{
|
|
tfetb->fd = HOPEN( pathname, O_RDWR | O_BINARY | oflags, S_IRUSR | S_IWUSR | S_IRGRP );
|
|
}
|
|
|
|
/* If file is read-only, attempt to open again */
|
|
if ( ( flags & FETOPEN_READONLY ) || (tfetb->fd < 0 && (EROFS == errno || EACCES == errno)))
|
|
{
|
|
omode = "rb";
|
|
tfetb->writeprotect = TRUE;
|
|
tfetb->fd = HOPEN( pathname, O_RDONLY | O_BINARY, S_IRUSR | S_IRGRP );
|
|
}
|
|
|
|
/*
|
|
|| Error out if both opens failed
|
|
*/
|
|
if( tfetb->fd == -1 )
|
|
{
|
|
free( tfetb );
|
|
return( FETE_ERROR );
|
|
}
|
|
|
|
/*
|
|
|| Associate stream with file descriptor
|
|
*/
|
|
tfetb->fh = fdopen( tfetb->fd, omode );
|
|
|
|
if( tfetb->fh == NULL )
|
|
{
|
|
rc = errno;
|
|
close( tfetb->fd );
|
|
errno = rc;
|
|
free( tfetb );
|
|
return( FETE_ERROR );
|
|
}
|
|
|
|
/*
|
|
|| If uninitialized tape, write 2 tapemarks to make it a valid NL tape
|
|
*/
|
|
rc = fet_read_header( tfetb, 0L, NULL, NULL );
|
|
if( rc < 0 && rc != FETE_TAPEMARK )
|
|
{
|
|
if( rc != FETE_EOT )
|
|
{
|
|
return( rc );
|
|
}
|
|
|
|
rc = fet_tapemark( tfetb );
|
|
if( rc < 0 )
|
|
{
|
|
return( rc );
|
|
}
|
|
|
|
rc = fet_tapemark( tfetb );
|
|
if( rc < 0 )
|
|
{
|
|
return( rc );
|
|
}
|
|
|
|
tfetb->created = TRUE;
|
|
}
|
|
else
|
|
tfetb->created = FALSE;
|
|
|
|
/*
|
|
|| Reposition tape to load point
|
|
*/
|
|
rc = fet_rewind( tfetb );
|
|
if( rc < 0 )
|
|
{
|
|
return( rc );
|
|
}
|
|
|
|
/*
|
|
|| Give the caller the new FETB
|
|
*/
|
|
*fetb = tfetb;
|
|
|
|
return( 0 );
|
|
|
|
} /* end function fet_open */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Close a FAKETAPE format file */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_close ( FETB **fetb )
|
|
{
|
|
if( *(fetb) != NULL )
|
|
{
|
|
if( (*fetb)->fh != NULL )
|
|
{
|
|
fclose( (*fetb)->fh );
|
|
}
|
|
free( *(fetb) );
|
|
}
|
|
*fetb = NULL;
|
|
return( 0 );
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Read a FAKETAPE block header */
|
|
/* */
|
|
/* If successful, return value is zero, and prvblkl and curblkl are */
|
|
/* set to the previous and current block lengths respectively. */
|
|
/* If error, return value is -1 and unitstat is set to CE+DE+UC */
|
|
/* and prvblkl and curblkl are undefined. Either or both of prvblkl */
|
|
/* and/or curblkl may be NULL. */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_read_header( FETB *fetb, off_t blkpos,
|
|
U16* pprvblkl, U16* pcurblkl )
|
|
{
|
|
int rc; /* Return code */
|
|
FAKETAPE_BLKHDR fakehdr; /* FakeTape block header */
|
|
char sblklen[5]; /* work for converting hdr */
|
|
int prvblkl; /* Previous block length */
|
|
int curblkl; /* Current block length */
|
|
int xorblkl; /* XOR check of block lens */
|
|
|
|
/* Reposition file to the requested block header */
|
|
rc = fseek( fetb->fh, blkpos, SEEK_SET );
|
|
if (rc < 0)
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
/* Read the 12-ASCII-hex-character block header */
|
|
rc = (int)fread( &fakehdr, 1, sizeof(FAKETAPE_BLKHDR), fetb->fh );
|
|
|
|
/* Handle read error condition */
|
|
if (rc < 0)
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
/* Handle end of file (uninitialized tape) condition */
|
|
if (rc == 0)
|
|
{
|
|
return FETE_EOT;
|
|
}
|
|
|
|
/* Handle end of file within block header */
|
|
if (rc < (int)sizeof(FAKETAPE_BLKHDR))
|
|
{
|
|
return FETE_BADHDR;
|
|
}
|
|
|
|
/* Convert the ASCII-hex-character block lengths to binary */
|
|
strncpy( sblklen, fakehdr.sprvblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &prvblkl );
|
|
strncpy( sblklen, fakehdr.scurblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &curblkl );
|
|
strncpy( sblklen, fakehdr.sxorblkl, 4 ); sblklen[4] = 0; sscanf( sblklen, "%x", &xorblkl );
|
|
|
|
/* Verify header integrity using the XOR header field */
|
|
if ( (prvblkl ^ curblkl) != xorblkl )
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
/* Return the converted value(s) to the caller */
|
|
if (pprvblkl) *pprvblkl = prvblkl;
|
|
if (pcurblkl) *pcurblkl = curblkl;
|
|
|
|
/* Successful return */
|
|
return FETE_OK;
|
|
|
|
} /* end function fet_read_header */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Read a block from a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, return value is block length read. */
|
|
/* If a tapemark was read, the return value is zero, and the */
|
|
/* current file number in the device block is incremented. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_read ( FETB *fetb, void *buf )
|
|
{
|
|
int rc; /* Return code */
|
|
off_t blkpos; /* Offset of block header */
|
|
U16 curblkl; /* Current block length */
|
|
|
|
/* Initialize current block position */
|
|
blkpos = fetb->nxtblkpos;
|
|
|
|
/* Read the block header to obtain the current block length */
|
|
rc = fet_read_header( fetb, blkpos, NULL, &curblkl );
|
|
if ( rc == FETE_EOT ) return FETE_EOT;
|
|
if (rc < 0)
|
|
return FETE_BADHDR; /* (error message already issued) */
|
|
|
|
/* Calculate the offset of the next block header */
|
|
blkpos += sizeof(FAKETAPE_BLKHDR) + curblkl;
|
|
|
|
/* If not a tapemark, read the data block */
|
|
if (curblkl > 0)
|
|
{
|
|
rc = (int)fread( buf, 1, curblkl, fetb->fh );
|
|
|
|
/* Handle read error condition */
|
|
if (rc < 0)
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
/* Handle end of file within data block */
|
|
if (rc < curblkl)
|
|
{
|
|
return FETE_BADBLOCK;
|
|
}
|
|
}
|
|
|
|
/* Calculate the offsets of the next and previous blocks */
|
|
fetb->prvblkpos = fetb->nxtblkpos;
|
|
fetb->nxtblkpos = blkpos;
|
|
|
|
/* Increment the block number */
|
|
fetb->blockid++;
|
|
|
|
/* Increment file number and return zero if tapemark was read */
|
|
if (curblkl == 0)
|
|
{
|
|
fetb->curfilen++;
|
|
return FETE_TAPEMARK; /* UX will be set by caller */
|
|
}
|
|
|
|
/* Return block length */
|
|
return curblkl;
|
|
|
|
} /* end function fet_read */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Write a FAKETAPE block header */
|
|
/* */
|
|
/* If successful, return value is zero. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
DLL_EXPORT int
|
|
fet_write_header ( FETB *fetb, off_t blkpos,
|
|
U16 prvblkl, U16 curblkl )
|
|
{
|
|
int rc; /* Return code */
|
|
FAKETAPE_BLKHDR fakehdr; /* FAKETAPE block header */
|
|
char temp[5];
|
|
|
|
/* Position file to where block header is to go */
|
|
rc = fseek( fetb->fh, blkpos, SEEK_SET );
|
|
if (rc < 0)
|
|
{
|
|
return FETE_BADLOC;
|
|
}
|
|
|
|
/* Build the 12-ASCII-hex-character block header */
|
|
MSGBUF( temp, "%4.4X", prvblkl );
|
|
memcpy( fakehdr.sprvblkl, temp, sizeof(fakehdr.sprvblkl));
|
|
MSGBUF( temp, "%4.4X", curblkl );
|
|
memcpy( fakehdr.scurblkl, temp, sizeof(fakehdr.scurblkl));
|
|
MSGBUF( temp, "%4.4X", prvblkl ^ curblkl );
|
|
memcpy( fakehdr.sxorblkl, temp, sizeof(fakehdr.sxorblkl));
|
|
|
|
/* Write the block header */
|
|
rc = (int)fwrite( &fakehdr, 1, sizeof(FAKETAPE_BLKHDR), fetb->fh );
|
|
if (rc < (int)sizeof(FAKETAPE_BLKHDR))
|
|
{
|
|
if(errno==ENOSPC)
|
|
{
|
|
/* Disk FULL */
|
|
return FETE_EOT;
|
|
}
|
|
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} /* end function fet_write_header */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Write a block to a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, return value is zero. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_write( FETB *fetb, void *buf, U16 blklen )
|
|
{
|
|
int rc; /* Return code */
|
|
off_t rcoff; /* Return code from lseek() */
|
|
off_t blkpos; /* Offset of block header */
|
|
U16 prvblkl; /* Length of previous block */
|
|
|
|
/* Initialize current block position and previous block length */
|
|
blkpos = fetb->nxtblkpos;
|
|
prvblkl = 0;
|
|
|
|
/* Determine previous block length if not at start of tape */
|
|
if (fetb->nxtblkpos > 0)
|
|
{
|
|
/* Retrieve the previous block length */
|
|
rc = fet_read_header( fetb, fetb->prvblkpos, NULL, &prvblkl );
|
|
if (rc < 0) return FETE_ERROR;
|
|
|
|
/* Recalculate the offset of the next block */
|
|
blkpos = fetb->prvblkpos + sizeof(FAKETAPE_BLKHDR) + prvblkl;
|
|
}
|
|
|
|
/* Reposition file to the new block header */
|
|
rc = fseek( fetb->fh, blkpos, SEEK_SET );
|
|
if (rc < 0)
|
|
{
|
|
return FETE_BADLOC;
|
|
}
|
|
else
|
|
rcoff = ftell( fetb->fh );
|
|
|
|
if(fetb->maxsize>0)
|
|
{
|
|
if((off_t)(fetb->nxtblkpos+blklen+sizeof(FAKETAPE_BLKHDR)) > fetb->maxsize )
|
|
{
|
|
return FETE_EOT;
|
|
}
|
|
}
|
|
|
|
/* Write the block header */
|
|
rc = fet_write_header( fetb, rcoff, prvblkl, blklen );
|
|
if (rc < 0)
|
|
return FETE_EOT; /* (error message already issued) */
|
|
|
|
/* Calculate the offsets of the next and previous blocks */
|
|
fetb->nxtblkpos = blkpos + sizeof(FAKETAPE_BLKHDR) + blklen;
|
|
fetb->prvblkpos = blkpos;
|
|
|
|
/* Write the data block */
|
|
rc = (int)fwrite( buf, 1, blklen, fetb->fh);
|
|
if (rc < blklen)
|
|
{
|
|
if(errno==ENOSPC)
|
|
{
|
|
/* Disk FULL */
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
return FETE_EOT;
|
|
}
|
|
|
|
/* Increment the block number */
|
|
fetb->blockid++;
|
|
|
|
/* Set new physical EOF */
|
|
|
|
|
|
do rc = ftruncate( fetb->fd, fetb->nxtblkpos );
|
|
while (EINTR == rc);
|
|
|
|
if (rc != 0)
|
|
{
|
|
return FETE_EOT;
|
|
}
|
|
|
|
/* Return normal status */
|
|
return 0;
|
|
|
|
} /* end function fet_write */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Write a tapemark to a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, return value is zero. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_tapemark( FETB *fetb )
|
|
{
|
|
int rc; /* Return code */
|
|
off_t rcoff; /* Return code from lseek() */
|
|
off_t blkpos; /* Offset of block header */
|
|
U16 prvblkl; /* Length of previous block */
|
|
|
|
/* Initialize current block position and previous block length */
|
|
blkpos = fetb->nxtblkpos;
|
|
prvblkl = 0;
|
|
|
|
/* Determine previous block length if not at start of tape */
|
|
if (fetb->nxtblkpos > 0)
|
|
{
|
|
/* Retrieve the previous block length */
|
|
rc = fet_read_header( fetb, fetb->prvblkpos, NULL, &prvblkl );
|
|
if (rc < 0)
|
|
return rc;
|
|
|
|
/* Recalculate the offset of the next block */
|
|
blkpos = fetb->prvblkpos + sizeof(FAKETAPE_BLKHDR) + prvblkl;
|
|
}
|
|
|
|
/* Reposition file to the new block header */
|
|
rc = fseek( fetb->fh, blkpos, SEEK_SET );
|
|
if (rc < 0)
|
|
{
|
|
return FETE_BADLOC;
|
|
}
|
|
else
|
|
rcoff = ftell( fetb->fh );
|
|
|
|
if(fetb->maxsize>0)
|
|
{
|
|
if((off_t)(fetb->nxtblkpos+sizeof(FAKETAPE_BLKHDR)) > fetb->maxsize)
|
|
{
|
|
return FETE_EOT;
|
|
}
|
|
}
|
|
|
|
/* Write the block header */
|
|
rc = fet_write_header( fetb, rcoff, prvblkl, 0 );
|
|
if (rc < 0)
|
|
return rc; /* (error message already issued) */
|
|
|
|
/* Increment the block number */
|
|
fetb->blockid++;
|
|
|
|
/* Calculate the offsets of the next and previous blocks */
|
|
fetb->nxtblkpos = blkpos + sizeof(FAKETAPE_BLKHDR);
|
|
fetb->prvblkpos = blkpos;
|
|
|
|
/* Set new physical EOF */
|
|
rc = ftell( fetb->fh );
|
|
|
|
do rc = ftruncate( fetb->fd, fetb->nxtblkpos );
|
|
while (EINTR == rc);
|
|
|
|
if (rc != 0)
|
|
{
|
|
return FETE_PROTECTED;
|
|
}
|
|
|
|
/* Return normal status */
|
|
return 0;
|
|
|
|
} /* end function fet_tapemark */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Synchronize a FAKETAPE format file (i.e. flush buffers to disk) */
|
|
/* */
|
|
/* If successful, return value is zero. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_sync( FETB *fetb )
|
|
{
|
|
/* Unit check if tape is write-protected */
|
|
if (fetb->writeprotect)
|
|
{
|
|
return FETE_PROTECTED;
|
|
}
|
|
|
|
/* Perform sync. Return error on failure. */
|
|
if (fdatasync( fetb->fd ) < 0)
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
/* Return normal status */
|
|
return 0;
|
|
|
|
} /* end function fet_sync */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Forward space over next block of a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, return value is the length of the block skipped. */
|
|
/* If the block skipped was a tapemark, the return value is zero, */
|
|
/* and the current file number in the device block is incremented. */
|
|
/* If error, return value is < 0. */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_fsb( FETB *fetb )
|
|
{
|
|
int rc; /* Return code */
|
|
off_t blkpos; /* Offset of block header */
|
|
U16 blklen; /* Block length */
|
|
|
|
/* Initialize current block position */
|
|
blkpos = fetb->nxtblkpos;
|
|
|
|
/* Read the block header to obtain the current block length */
|
|
rc = fet_read_header( fetb, blkpos, NULL, &blklen );
|
|
if (rc < 0)
|
|
return rc; /* (error message already issued) */
|
|
|
|
/* Calculate the offset of the next block */
|
|
blkpos += sizeof(FAKETAPE_BLKHDR) + blklen;
|
|
|
|
/* Calculate the offsets of the next and previous blocks */
|
|
fetb->prvblkpos = fetb->nxtblkpos;
|
|
fetb->nxtblkpos = blkpos;
|
|
|
|
/* Increment current file number if tapemark was skipped */
|
|
if (blklen == 0)
|
|
fetb->curfilen++;
|
|
|
|
/* Increment the block number */
|
|
fetb->blockid++;
|
|
|
|
/* Return block length or zero if tapemark */
|
|
return blklen;
|
|
|
|
} /* end function fet_fsb */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Backspace to previous block of a FAKETAPE format file */
|
|
/* */
|
|
/* If successful, return value is the length of the block. */
|
|
/* If the block is a tapemark, the return value is zero, */
|
|
/* and the current file number in the device block is decremented. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_bsb( FETB *fetb )
|
|
{
|
|
int rc; /* Return code */
|
|
U16 curblkl; /* Length of current block */
|
|
U16 prvblkl; /* Length of previous block */
|
|
off_t blkpos; /* Offset of block header */
|
|
|
|
/* Unit check if already at start of tape */
|
|
if (fetb->nxtblkpos == 0)
|
|
{
|
|
return FETE_BOT;
|
|
}
|
|
|
|
/* Backspace to previous block position */
|
|
blkpos = fetb->prvblkpos;
|
|
|
|
/* Read the block header to obtain the block lengths */
|
|
rc = fet_read_header( fetb, blkpos, &prvblkl, &curblkl );
|
|
if (rc < 0)
|
|
return rc; /* (error message already issued) */
|
|
|
|
/* Calculate the offset of the previous block */
|
|
fetb->prvblkpos = blkpos - sizeof(FAKETAPE_BLKHDR) - prvblkl;
|
|
fetb->nxtblkpos = blkpos;
|
|
|
|
/* Decrement current file number if backspaced over tapemark */
|
|
if (curblkl == 0)
|
|
fetb->curfilen--;
|
|
|
|
/* Decrement the block number */
|
|
fetb->blockid--;
|
|
|
|
/* Return block length or zero if tapemark */
|
|
return curblkl;
|
|
|
|
} /* end function fet_bsb */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Forward space to next logical file of a FAKETAPE format file */
|
|
/* */
|
|
/* For FAKETAPE files, the forward space file operation is achieved */
|
|
/* by forward spacing blocks until positioned just after a tapemark. */
|
|
/* */
|
|
/* If successful, return value is zero, and the current file number */
|
|
/* in the device block is incremented by fet_fsb. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_fsf( FETB *fetb )
|
|
{
|
|
int rc; /* Return code */
|
|
|
|
while (1)
|
|
{
|
|
/* Forward space over next block */
|
|
rc = fet_fsb( fetb );
|
|
if (rc < 0)
|
|
return rc; /* (error message already issued) */
|
|
|
|
/* Exit loop if spaced over a tapemark */
|
|
if (rc == 0)
|
|
break;
|
|
|
|
} /* end while */
|
|
|
|
/* Return normal status */
|
|
return 0;
|
|
|
|
} /* end function fet_fsf */
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Backspace to previous logical file of a FAKETAPE format file */
|
|
/* */
|
|
/* For FAKETAPE files, the backspace file operation is achieved */
|
|
/* by backspacing blocks until positioned just before a tapemark */
|
|
/* or until positioned at start of tape. */
|
|
/* */
|
|
/* If successful, return value is zero, and the current file number */
|
|
/* in the device block is decremented by fet_bsb. */
|
|
/* If error, return value is < 0 */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_bsf( FETB *fetb )
|
|
{
|
|
int rc; /* Return code */
|
|
|
|
while (1)
|
|
{
|
|
/* Exit if now at start of tape */
|
|
if (fetb->nxtblkpos == 0)
|
|
{
|
|
return FETE_BOT;
|
|
}
|
|
|
|
/* Backspace to previous block position */
|
|
rc = fet_bsb( fetb );
|
|
if (rc < 0)
|
|
return rc; /* (error message already issued) */
|
|
|
|
/* Exit loop if backspaced over a tapemark */
|
|
if (rc == 0)
|
|
break;
|
|
|
|
} /* end while */
|
|
|
|
/* Return normal status */
|
|
return 0;
|
|
|
|
} /* end function fet_bsf */
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Rewinds a FAKETAPE format file */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_rewind ( FETB *fetb )
|
|
{
|
|
int rc;
|
|
|
|
rc = fseek( fetb->fh, 0L, SEEK_SET );
|
|
if ( rc < 0 )
|
|
{
|
|
return FETE_ERROR;
|
|
}
|
|
|
|
fetb->nxtblkpos=0;
|
|
fetb->prvblkpos=-1;
|
|
fetb->curfilen=1;
|
|
fetb->blockid=0;
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
/* Determines if a FAKETAPE has passed a virtual EOT marker */
|
|
/*-------------------------------------------------------------------*/
|
|
DLL_EXPORT int
|
|
fet_passedeot ( FETB *fetb )
|
|
{
|
|
if(fetb->nxtblkpos==0)
|
|
fetb->eotwarning = FALSE;
|
|
else
|
|
if(fetb->maxsize==0)
|
|
fetb->eotwarning = TRUE;
|
|
else
|
|
if(fetb->nxtblkpos+fetb->eotmargin > fetb->maxsize)
|
|
fetb->eotwarning = TRUE;
|
|
else
|
|
fetb->eotwarning = FALSE;
|
|
return fetb->eotwarning;
|
|
}
|
|
|
|
DLL_EXPORT const char *
|
|
fet_error( int rc )
|
|
{
|
|
// no error, return OK
|
|
if( rc > -1 )
|
|
rc = 0;
|
|
|
|
rc *= -1; // make positive for indexing
|
|
|
|
if( rc >= (int)FET_ERRSTR_MAX ) // detect mismatch errors vs error strings
|
|
rc = FET_ERRSTR_MAX - 1;
|
|
|
|
return( fet_errstr[ rc ] );
|
|
}
|