diff --git a/CHANGES b/CHANGES
index 6f0d1df4..1775435c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+06 Jul 2010 Add FTLIB.C FakeTape library; add support in hetmap and hetinit for
+ FAKETAPE.
22 Jun 2010 CAPPING feature. Capping can be set in hercules.cnf with the keyword
CAPPING and a number, representing the maximum MIPS for CPs. Capping
does not apply to specialty engines.
diff --git a/Hercules.vcproj b/Hercules.vcproj
index 8b96c0d4..9f22cdb7 100644
--- a/Hercules.vcproj
+++ b/Hercules.vcproj
@@ -729,6 +729,10 @@
RelativePath=".\hetlib.h"
>
+
+
@@ -765,6 +769,10 @@
RelativePath=".\hetlib.c"
>
+
+
diff --git a/Makefile.am b/Makefile.am
index 3a444db6..07799087 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -143,6 +143,7 @@ dyndev_SRC = commadpt.c \
tapeccws.c \
sllib.c \
hetlib.c \
+ ftlib.c \
awstape.c \
faketape.c \
hettape.c \
@@ -335,6 +336,7 @@ endif
#
libherct_la_SOURCES = sllib.c \
+ ftlib.c \
hetlib.c
libherct_la_LDFLAGS = $(LIB_LD_FLAGS)
@@ -719,6 +721,7 @@ noinst_HEADERS = fishhang.h \
hbyteswp.h \
dasdblks.h \
hetlib.h \
+ ftlib.h \
version.h \
parser.h \
dasdtab.h \
diff --git a/ftlib.c b/ftlib.c
new file mode 100644
index 00000000..3899b8b5
--- /dev/null
+++ b/ftlib.c
@@ -0,0 +1,792 @@
+/* FTLIB.C (c) Copyright TurboHercules, SAS 2010 */
+/* 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. */
+
+// $Id: ftlib.c 6000 2010-05-18 14:30:48Z pgorlinsky $
+
+
+/*-------------------------------------------------------------------*/
+/* 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 */
+int fd = -1;
+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 );
+ }
+
+ /*
+ || 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 ) )
+ {
+ fd = open( 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 ) || (fd < 0 && (EROFS == errno || EACCES == errno)))
+ {
+ omode = "rb";
+ tfetb->writeprotect = TRUE;
+ fd = open( pathname, O_RDONLY | O_BINARY, S_IRUSR | S_IRGRP );
+ }
+
+ /*
+ || Error out if both opens failed
+ */
+ if( fd == -1 )
+ {
+ free( tfetb );
+ return( FETE_ERROR );
+ }
+
+ /*
+ || Associate stream with file descriptor
+ */
+ tfetb->fd = fdopen( fd, omode );
+
+ if( tfetb->fd == NULL )
+ {
+ rc = errno;
+ close( 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 );
+ }
+ }
+
+ /*
+ || 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)->fd != NULL )
+ {
+ fclose( (*fetb)->fd );
+ }
+ 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 */
+off_t rcoff; /* Return code from lseek() */
+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->fd, blkpos, SEEK_SET );
+ if (rc < 0)
+ {
+ return FETE_ERROR;
+ }
+ else
+ rcoff = ftell( fetb->fd );
+
+ /* Read the 12-ASCII-hex-character block header */
+ rc = (int)fread( &fakehdr, 1, sizeof(FAKETAPE_BLKHDR), fetb->fd );
+
+ /* 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, BYTE *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) */
+ ASSERT( curblkl >= 0 );
+
+ /* 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->fd );
+
+ /* 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 */
+off_t rcoff; /* Return code from lseek() */
+FAKETAPE_BLKHDR fakehdr; /* FAKETAPE block header */
+char sblklen[5]; /* work buffer */
+
+ /* Position file to where block header is to go */
+ rc = fseek( fetb->fd, blkpos, SEEK_SET );
+ if (rc < 0)
+ {
+ return FETE_BADLOC;
+ }
+ else
+ rcoff = ftell( fetb->fd );
+
+ /* Build the 12-ASCII-hex-character block header */
+ snprintf( sblklen, sizeof(sblklen), "%4.4X", prvblkl );
+ strncpy( fakehdr.sprvblkl, sblklen, sizeof(fakehdr.sprvblkl) );
+ snprintf( sblklen, sizeof(sblklen), "%4.4X", curblkl );
+ strncpy( fakehdr.scurblkl, sblklen, sizeof(fakehdr.scurblkl) );
+ snprintf( sblklen, sizeof(sblklen), "%4.4X", prvblkl ^ curblkl );
+ strncpy( fakehdr.sxorblkl, sblklen, sizeof(fakehdr.sxorblkl) );
+
+ /* Write the block header */
+ rc = (int)fwrite( &fakehdr, 1, sizeof(FAKETAPE_BLKHDR), fetb->fd );
+ 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, BYTE *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->fd, blkpos, SEEK_SET );
+ if (rc < 0)
+ {
+ return FETE_BADLOC;
+ }
+ else
+ rcoff = ftell( fetb->fd );
+
+ 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->fd);
+ 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( fileno( 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->fd, blkpos, SEEK_SET );
+ if (rc < 0)
+ {
+ return FETE_BADLOC;
+ }
+ else
+ rcoff = ftell( fetb->fd );
+
+ 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->fd );
+
+ do rc = ftruncate( fileno( 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( fileno( 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;
+off_t rcoff;
+
+ rc = fseek( fetb->fd, 0L, SEEK_SET );
+ if ( rc < 0 )
+ {
+ return FETE_ERROR;
+ }
+ else
+ rcoff = ftell( fetb->fd );
+
+ 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 ] );
+}
diff --git a/ftlib.h b/ftlib.h
new file mode 100644
index 00000000..cbd94d66
--- /dev/null
+++ b/ftlib.h
@@ -0,0 +1,134 @@
+/* FTLIB.H (c) Copyright TurboHercules, SAS 2010 */
+/* Header files for FAKETAPE. */
+/* */
+/* Released under "The Q Public License Version 1" */
+/* (http://www.hercules-390.org/herclic.html) as modifications to */
+/* Hercules. */
+
+// $Id: ftlib.h 6033 2010-05-25 03:55:37Z pgorlinsky $
+
+#if !defined( _FTLIB_H_ )
+#define _FTLIB_H_
+
+#include "hercules.h"
+
+#ifndef _FTLIB_C_
+#ifndef _HTAPE_DLL_
+#define FET_DLL_IMPORT DLL_IMPORT
+#else /* _HTAPE_DLL_ */
+#define FET_DLL_IMPORT extern
+#endif /* _HTAPE_DLL_ */
+#else
+#define FET_DLL_IMPORT DLL_EXPORT
+#endif
+
+/*-------------------------------------------------------------------*/
+/* Structure definition for Flex FakeTape block headers */
+/*-------------------------------------------------------------------*/
+/*
+ * The character length fields in a Flex FakeTape header are in BIG
+ * endian ASCII hex. That is to say, when the length field is ASCII
+ * "0123" (i.e. 0x30, 0x31, 0x32, 0x33), the length of the block is
+ * decimal 291 bytes (0x0123 == 291).
+ *
+ * The two block length fields are followed by an XOR "check" field
+ * calculated as the XOR of the two preceding length fields and is
+ * used to verify the integrity of the header.
+ *
+ * The Flex FakeTape tape format does not support any flag fields
+ * in its header and thus does not support any type of compression.
+ */
+typedef struct _FAKETAPE_BLKHDR
+{ /*
+ * PROGRAMMING NOTE: note that for Flex FakeTapes, the "previous
+ * chunk size" comes FIRST, followed by the "current chunk size"
+ * second. This is the complete opposite from the way it is for
+ * AWS tape files. Also note that for Flex FakeTape the size fields
+ * are in BIG endian ASCII hex-string whereas for AWS tapes
+ * they're LITTLE endian binary.
+ */
+ char sprvblkl[4]; /* length of previous block */
+ char scurblkl[4]; /* length of this block */
+ char sxorblkl[4]; /* XOR both lengths together */
+}
+FAKETAPE_BLKHDR;
+
+/*
+|| Control block for FakeTape Emulated Tape files
+*/
+typedef struct _fetb
+{
+ FILE *fd; /* Tape file descriptor */
+ char filename[MAX_PATH]; /* filename */
+
+ off_t nxtblkpos; /* Offset from start of file
+ to next block */
+ off_t prvblkpos; /* Offset from start of file
+ to previous block */
+ off_t eotmargin; /* Amount of space left before
+ reporting EOT (in bytes) */
+ off_t maxsize; /* Maximum allowed TAPE file
+ size */
+ U16 curfilen; /* Current file number */
+ U32 blockid; /* Current device block ID */
+ FAKETAPE_BLKHDR chdr; /* Current block header */
+ u_int writeprotect:1; /* TRUE=write protected */
+ u_int readlast:1; /* TRUE=last i/o was read */
+ u_int truncated:1; /* TRUE=file truncated */
+ u_int eotwarning:1; /* TRUE=EOT warning area reached */
+
+} FETB;
+
+/*
+|| Flags for fet_open()
+*/
+#define FETOPEN_CREATE 0x01 /* Create NL tape, if file missing */
+#define FETOPEN_READONLY 0x02 /* Force the open read-only */
+
+/*
+|| Error definitions NOTE: Keep these in sync with hetlib.h
+*/
+#define FETE_OK 0 /* No error */
+#define FETE_ERROR -1 /* File error (check errno) */
+#define FETE_TAPEMARK -2 /* Tapemark read */
+#define FETE_BOT -3 /* Beginning of tape */
+#define FETE_EOT -4 /* End of tape */
+#define FETE_BADBOR -5 /* BOR not found */
+#define FETE_BADEOR -6 /* EOR not found */
+#define FETE_BADMARK -7 /* Unexpected tapemark */
+#define FETE_OVERFLOW -8 /* Buffer not big enough */
+#define FETE_PREMEOF -9 /* Premature EOF */
+#define FETE_DECERR -10 // unused
+#define FETE_UNKMETH -11 // unused
+#define FETE_COMPERR -12 // unused
+#define FETE_BADLEN -13 /* Specified length to big */
+#define FETE_PROTECTED -14 /* Write protected */
+#define FETE_BADFUNC -15 /* Bad function code passed */
+#define FETE_BADMETHOD -16 // unused
+#define FETE_BADLEVEL -17 // unused
+#define FETE_BADMSIZE -18 // unused
+#define FETE_BADDIR -19 /* Invalid direction specified */
+#define FETE_NOMEM -20 /* Insufficient memory */
+#define FETE_BADHDR -21 /* Couldn't read block header */
+#define FETE_BADCOMPRESS -22 // unused
+#define FETE_BADBLOCK -23 /* Block is short */
+#define FETE_BADLOC -24 /* Location error */
+
+// Function Prototypes
+
+FET_DLL_IMPORT int fet_open( FETB **fetb, char *filename, int flags );
+FET_DLL_IMPORT int fet_close( FETB **fetb );
+FET_DLL_IMPORT int fet_read_header( FETB *fetb, off_t blkpos, U16* pprvblkl, U16* pcurblkl );
+FET_DLL_IMPORT int fet_read( FETB *fetb, void *sbuf );
+FET_DLL_IMPORT int fet_write_header( FETB *fetb, off_t blkpos, U16 prvblkl, U16 curblkl );
+FET_DLL_IMPORT int fet_write( FETB *fetb, void *sbuf, U16 slen );
+FET_DLL_IMPORT int fet_tapemark( FETB *fetb );
+FET_DLL_IMPORT int fet_sync( FETB *fetb );
+FET_DLL_IMPORT int fet_bsb( FETB *fetb );
+FET_DLL_IMPORT int fet_fsb( FETB *fetb );
+FET_DLL_IMPORT int fet_bsf( FETB *fetb );
+FET_DLL_IMPORT int fet_fsf( FETB *fetb );
+FET_DLL_IMPORT int fet_rewind( FETB *fetb );
+FET_DLL_IMPORT int fet_passedeot( FETB *fetb );
+FET_DLL_IMPORT const char *fet_error( int rc );
+#endif /* defined( _FTLIB_H_ ) */
diff --git a/hetinit.c b/hetinit.c
index 76758421..c5505e92 100644
--- a/hetinit.c
+++ b/hetinit.c
@@ -1,4 +1,5 @@
/* HETINIT.C (c) Copyright Leland Lucius, 2000-2009 */
+/* (c) Copyright TurboHercules, SAS 2010 */
/* Creates IEHINITT or NL format Hercules Emulated Tapes */
/* */
/* Released under "The Q Public License Version 1" */
@@ -22,6 +23,7 @@
#include "hercules.h"
#include "hetlib.h"
+#include "ftlib.h"
#include "sllib.h"
#include "herc_getopt.h"
@@ -59,10 +61,12 @@ main( int argc, char *argv[] )
char msgbuf[512]; /* message build work area */
int rc;
SLLABEL lab;
- HETB *hetb;
+ HETB *hetb; /* used for aws and het tapes*/
+ FETB *fetb; /* used for faketapes */
int o_iehinitt;
int o_nl;
int o_compress;
+ int o_faketape;
char *o_filename;
char *o_owner;
char *o_volser;
@@ -105,7 +109,9 @@ main( int argc, char *argv[] )
display_version (stderr, msgbuf+10, FALSE);
hetb = NULL;
+ fetb = NULL;
o_filename = NULL;
+ o_faketape = FALSE;
o_iehinitt = TRUE;
o_nl = FALSE;
o_compress = TRUE;
@@ -158,6 +164,11 @@ main( int argc, char *argv[] )
o_filename = argv[ optind ];
+ if ( ( rc = (int)strlen( o_filename ) ) > 4 && ( rc = strcasecmp( &o_filename[rc-4], ".fkt" ) ) == 0 )
+ {
+ o_faketape = TRUE;
+ }
+
if( o_iehinitt )
{
if( argc == 2 )
@@ -191,18 +202,31 @@ main( int argc, char *argv[] )
if( o_owner )
het_string_to_upper( o_owner );
- rc = het_open( &hetb, o_filename, HETOPEN_CREATE );
- if( rc < 0 )
+ if ( o_faketape )
{
- printf( MSG( HHC00075, "E", "het_open()", het_error( rc ) ) );
- goto exit;
- }
+ rc = fet_open( &fetb, o_filename, FETOPEN_CREATE );
+ if ( rc < 0 )
+ {
+ printf( MSG( HHC00075, "E", "fet_open()", fet_error( rc ) ) );
+ goto exit;
+ }
- rc = het_cntl( hetb, HETCNTL_SET | HETCNTL_COMPRESS, o_compress );
- if( rc < 0 )
+ }
+ else
{
- printf( MSG( HHC00075, "E", "het_cntl()", het_error( rc ) ) );
- goto exit;
+ rc = het_open( &hetb, o_filename, HETOPEN_CREATE );
+ if( rc < 0 )
+ {
+ printf( MSG( HHC00075, "E", "het_open()", het_error( rc ) ) );
+ goto exit;
+ }
+
+ rc = het_cntl( hetb, HETCNTL_SET | HETCNTL_COMPRESS, o_compress );
+ if( rc < 0 )
+ {
+ printf( MSG( HHC00075, "E", "het_cntl()", het_error( rc ) ) );
+ goto exit;
+ }
}
if( o_iehinitt )
@@ -214,10 +238,16 @@ main( int argc, char *argv[] )
goto exit;
}
- rc = het_write( hetb, &lab, sizeof( lab ) );
+ if ( o_faketape )
+ rc = fet_write( fetb, &lab, (U16)sizeof( lab ) );
+ else
+ rc = het_write( hetb, &lab, sizeof( lab ) );
if( rc < 0 )
{
- printf( MSG( HHC00075, "E", "het_write() for VOL1", het_error( rc ) ) );
+ if ( o_faketape )
+ printf( MSG( HHC00075, "E", "fet_write() for VOL1", fet_error( rc ) ) );
+ else
+ printf( MSG( HHC00075, "E", "het_write() for VOL1", het_error( rc ) ) );
goto exit;
}
@@ -227,34 +257,55 @@ main( int argc, char *argv[] )
printf( MSG( HHC00075, "E", "sl_hdr1()", sl_error( rc ) ) );
goto exit;
}
-
- rc = het_write( hetb, &lab, sizeof( lab ) );
+
+ if ( o_faketape )
+ rc = fet_write( fetb, &lab, (U16)sizeof(lab) );
+ else
+ rc = het_write( hetb, &lab, sizeof( lab ) );
if( rc < 0 )
{
- printf( MSG( HHC00075, "E", "het_write() for HDR1", het_error( rc ) ) );
+ if ( o_faketape )
+ printf( MSG( HHC00075, "E", "fet_write() for HDR1", fet_error( rc ) ) );
+ else
+ printf( MSG( HHC00075, "E", "het_write() for HDR1", het_error( rc ) ) );
goto exit;
}
}
else if( o_nl )
{
- rc = het_tapemark( hetb );
+ if ( o_faketape )
+ rc = fet_tapemark( fetb );
+ else
+ rc = het_tapemark( hetb );
if( rc < 0 )
{
- printf( MSG( HHC00075, "E", "het_tapemark()", het_error( rc ) ) );
+ if ( o_faketape )
+ printf( MSG( HHC00075, "E", "fet_tapemark()", fet_error( rc ) ) );
+ else
+ printf( MSG( HHC00075, "E", "het_tapemark()", het_error( rc ) ) );
goto exit;
}
}
- rc = het_tapemark( hetb );
+ if ( o_faketape )
+ rc = fet_tapemark( fetb );
+ else
+ rc = het_tapemark( hetb );
if( rc < 0 )
{
- printf( MSG( HHC00075, "E", "het_tapemark()", het_error( rc ) ) );
+ if ( o_faketape )
+ printf( MSG( HHC00075, "E", "fet_tapemark()", fet_error( rc ) ) );
+ else
+ printf( MSG( HHC00075, "E", "het_tapemark()", het_error( rc ) ) );
goto exit;
}
exit:
- het_close( &hetb );
+ if ( o_faketape)
+ fet_close( &fetb );
+ else
+ het_close( &hetb );
return( rc < 0 );
}
diff --git a/hetlib.c b/hetlib.c
index 26e5438d..12bf543c 100644
--- a/hetlib.c
+++ b/hetlib.c
@@ -30,7 +30,7 @@
#undef HETDEBUGW
/*
-|| Local constant data
+|| Local constant data NOTE: Keep in sync with ftlib.c
*/
static const char *het_errstr[] =
{
@@ -57,6 +57,8 @@ static const char *het_errstr[] =
"Insufficient memory",
"Couldn't read block header",
"Inconsistent compression flags",
+ "Block is short",
+ "Location error",
"Invalid error code",
};
#define HET_ERRSTR_MAX ( sizeof( het_errstr) / sizeof( het_errstr[ 0 ] ) )
diff --git a/hetlib.h b/hetlib.h
index 1b04ca16..752703f7 100644
--- a/hetlib.h
+++ b/hetlib.h
@@ -173,6 +173,8 @@ typedef struct _hetb
#define HETE_NOMEM -20 /* Insufficient memory */
#define HETE_BADHDR -21 /* Couldn't read block header */
#define HETE_BADCOMPRESS -22 /* Inconsistent compression flags */
+#define HETE_BADBLOCK -23 // unused
+#define HETE_BADLOC -24 // unused
/*
|| Public functions
diff --git a/hetmap.c b/hetmap.c
index c815ba6c..77c6f11c 100644
--- a/hetmap.c
+++ b/hetmap.c
@@ -24,6 +24,7 @@
#include "hercules.h"
#include "hetlib.h"
+#include "ftlib.h"
#include "sllib.h"
#include "herc_getopt.h"
@@ -189,7 +190,7 @@ static SInt32 Print_Block_Data ( SInt32 );
*/
static const char sep[] = "---------------------\n";
static const char help_hetmap[] =
- "%s - Print a map of an HET or AWS tape file\n\n"
+ "%s - Print a map of an AWS, HET or FakeTape tape file\n\n"
"Usage: %s [options] filename\n\n"
"Options:\n"
" -a print all label and file information (default: on)\n"
@@ -200,7 +201,7 @@ static const char help_hetmap[] =
" -s print dump of each data file (SLANAL format) (default: off)\n"
" -t print TAPEMAP-compatible format output (default: off)\n";
static const char help_tapemap[] =
- "%s - Print a map of an HET or AWS tape file\n\n"
+ "%s - Print a map of an AWS, HET or FakeTape tape file\n\n"
"Usage: %s filename\n\n";
#ifdef EXTERNALGUI
@@ -228,6 +229,9 @@ main( int argc, char *argv[] )
{
Boolean lProcStdLbl = FALSE;
HETB *hetb;
+ FETB *fetb;
+ char *i_filename;
+ int i_faketape = FALSE;
SInt32 rc;
SInt32 fileno;
SInt32 i;
@@ -240,7 +244,7 @@ main( int argc, char *argv[] )
U32 totblocks;
U32 totubytes;
U32 totcbytes;
- U32 opts;
+ U32 opts = 0;
SInt32 lResidue = max_bytes_dsply; /* amount of space left to print */
char pgmpath[MAX_PATH];
char *pgm;
@@ -284,7 +288,7 @@ main( int argc, char *argv[] )
INITIALIZE_UTILITY(pgm);
/* Display the program identification message */
- display_version (stderr, "Hercules HET and AWS tape map program", FALSE);
+ display_version (stderr, "Hercules AWS, HET and FakeTape tape map program", FALSE);
if (! (opts & O_TAPEMAP_INVOKED) )
{
@@ -295,45 +299,36 @@ main( int argc, char *argv[] )
{
rc = getopt( argc, argv, "adfhlst" );
if( rc == -1 )
- {
break;
- }
switch( rc )
{
case 'a':
opts = O_ALL;
- break;
-
+ break;
case 'd':
opts = O_DATASETS;
- break;
-
+ break;
case 'f':
opts = O_FILES;
- break;
-
+ break;
case 'h':
Print_Usage( pgm );
exit( 1 );
- break;
-
+ break;
case 'l':
opts = O_LABELS;
- break;
-
+ break;
case 's':
opts = O_SLANAL_OUT;
break;
-
case 't':
opts = O_TAPEMAP_OUTPUT;
- break;
-
+ break;
default:
Print_Usage( pgm );
exit( 1 );
- break;
+ break;
}
}
@@ -352,11 +347,29 @@ main( int argc, char *argv[] )
printf( "%-20.20s: %s\n", "Filename", argv[ optind ] );
}
- rc = het_open( &hetb, argv[ optind ], 0 );
+ i_filename = argv[ optind ];
+
+ if ( ( rc = (int)strlen( i_filename ) ) > 4 && ( rc = strcasecmp( &i_filename[rc-4], ".fkt" ) ) == 0 )
+ {
+ i_faketape = TRUE;
+ }
+
+ if ( i_faketape )
+ rc = fet_open( &fetb, i_filename, FETOPEN_READONLY );
+ else
+ rc = het_open( &hetb, i_filename, HETOPEN_READONLY );
if( rc < 0 )
{
- printf( "het_open() returned %d\n", rc );
- het_close( &hetb );
+ if ( i_faketape )
+ {
+ printf( "fet_open() returned %d\n", rc );
+ fet_close( &fetb );
+ }
+ else
+ {
+ printf( "het_open() returned %d\n", rc );
+ het_close( &hetb );
+ }
exit( 1 );
}
@@ -381,8 +394,12 @@ main( int argc, char *argv[] )
#ifdef EXTERNALGUI
if( extgui )
{
+ off_t curpos;
/* Report progress every nnnK */
- off_t curpos = ftell( hetb->fd );
+ if ( i_faketape )
+ curpos = ftell( fetb->fd );
+ else
+ curpos = ftell( hetb->fd );
if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) )
{
prevpos = curpos;
@@ -391,8 +408,13 @@ main( int argc, char *argv[] )
}
#endif /*EXTERNALGUI*/
- rc = het_read( hetb, gBuffer );
- if( rc == HETE_EOT )
+ if ( i_faketape)
+ {
+ rc = fet_read( fetb, gBuffer );
+ }
+ else
+ rc = het_read( hetb, gBuffer );
+ if( rc == HETE_EOT ) // FETE and HETE enums are the same
{
if( opts & O_TAPEMAP_OUTPUT )
{
@@ -400,7 +422,7 @@ main( int argc, char *argv[] )
}
break;
}
-
+
if( rc == HETE_TAPEMARK )
{
fileno += 1;
@@ -420,10 +442,13 @@ main( int argc, char *argv[] )
printf( "%-20.20s: %d\n", "Blocks", gBlkCount );
printf( "%-20.20s: %d\n", "Min Blocksize", uminsz );
printf( "%-20.20s: %d\n", "Max Blocksize", umaxsz );
- printf( "%-20.20s: %d\n", "Uncompressed bytes", ubytes );
- printf( "%-20.20s: %d\n", "Min Blocksize-Comp", cminsz );
- printf( "%-20.20s: %d\n", "Max Blocksize-Comp", cmaxsz );
- printf( "%-20.20s: %d\n", "Compressed bytes", cbytes );
+ if ( !i_faketape )
+ {
+ printf( "%-20.20s: %d\n", "Uncompressed bytes", ubytes );
+ printf( "%-20.20s: %d\n", "Min Blocksize-Comp", cminsz );
+ printf( "%-20.20s: %d\n", "Max Blocksize-Comp", cmaxsz );
+ printf( "%-20.20s: %d\n", "Compressed bytes", cbytes );
+ }
}
totblocks += gBlkCount;
@@ -445,18 +470,24 @@ main( int argc, char *argv[] )
if( rc < 0 )
{
- printf( "het_read() returned %d\n", rc );
+ if ( i_faketape )
+ printf( "fet_read() returned %d\n", rc );
+ else
+ printf( "het_read() returned %d\n", rc );
break;
}
gBlkCount += 1;
- ubytes += hetb->ublksize;
- cbytes += hetb->cblksize;
+ if ( !i_faketape )
+ {
+ ubytes += hetb->ublksize;
+ cbytes += hetb->cblksize;
- if( uminsz == 0 || hetb->ublksize < uminsz ) uminsz = hetb->ublksize;
- if( hetb->ublksize > umaxsz ) umaxsz = hetb->ublksize;
- if( cminsz == 0 || hetb->cblksize < cminsz ) cminsz = hetb->cblksize;
- if( hetb->cblksize > cmaxsz ) cmaxsz = hetb->cblksize;
+ if( uminsz == 0 || hetb->ublksize < uminsz ) uminsz = hetb->ublksize;
+ if( hetb->ublksize > umaxsz ) umaxsz = hetb->ublksize;
+ if( cminsz == 0 || hetb->cblksize < cminsz ) cminsz = hetb->cblksize;
+ if( hetb->cblksize > cmaxsz ) cmaxsz = hetb->cblksize;
+ }
if ( rc >= 80 )
{
@@ -541,12 +572,18 @@ main( int argc, char *argv[] )
printf( "%-20.20s:\n", "Summary" );
printf( "%-20.20s: %d\n", "Files", fileno );
printf( "%-20.20s: %d\n", "Blocks", totblocks );
- printf( "%-20.20s: %d\n", "Uncompressed bytes", totubytes );
- printf( "%-20.20s: %d\n", "Compressed bytes", totcbytes );
- printf( "%-20.20s: %d\n", "Reduction", totubytes - totcbytes );
+ if ( !i_faketape )
+ {
+ printf( "%-20.20s: %d\n", "Uncompressed bytes", totubytes );
+ printf( "%-20.20s: %d\n", "Compressed bytes", totcbytes );
+ printf( "%-20.20s: %d\n", "Reduction", totubytes - totcbytes );
+ }
}
- het_close( &hetb );
+ if ( i_faketape )
+ fet_close( &fetb );
+ else
+ fet_close( &fetb );
return 0;
}
diff --git a/makefile.generic b/makefile.generic
index d1d52358..bec3b028 100644
--- a/makefile.generic
+++ b/makefile.generic
@@ -183,10 +183,10 @@ dasdcopy_OBJ = dasdcopy.o dasdutil.o codepage.o hostinfo.o version.o \
hetget_OBJ = hetget.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o pttrace.o hsys.o
-hetinit_OBJ = hetinit.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
+hetinit_OBJ = hetinit.o hetlib.o ftlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o pttrace.o hsys.o
-hetmap_OBJ = hetmap.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
+hetmap_OBJ = hetmap.o hetlib.o ftlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o pttrace.o hsys.o
hetupd_OBJ = hetupd.o hetlib.o sllib.o codepage.o hostinfo.o version.o logmsg.o pttrace.o hsys.o
@@ -199,7 +199,7 @@ HEADERS = codepage.h commadpt.h cpuint.h ctcadpt.h dasdblks.h \
dasdtab.h dat.h devtype.h esa390.h feat370.h feat390.h \
feat900.h featall.h featchk.h feature.h fishhang.h \
fthreads.h wthreads.h hbyteswp.h hercifc.h hercnls.h hercules.h \
- hetlib.h hostinfo.h httpmisc.h htypes.h ieee-w32.h \
+ hetlib.h ftlib.h hostinfo.h httpmisc.h htypes.h ieee-w32.h \
inline.h linklist.h logger.h machdep.h opcode.h chsc.h \
parser.h sllib.h tapedev.h tt32api.h tuntap.h version.h \
vstore.h w32chan.h w32ctca.h shared.h hdl.h crypto.h \
diff --git a/makefile.w32 b/makefile.w32
index 164867e3..1075c785 100644
--- a/makefile.w32
+++ b/makefile.w32
@@ -194,10 +194,10 @@ dasdcopy_OBJ = dasdcopy.o dasdutil.o codepage.o hostinfo.o version.o \
hetget_OBJ = hetget.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o hsys.o pttrace.o
-hetinit_OBJ = hetinit.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
+hetinit_OBJ = hetinit.o hetlib.o ftlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o hsys.o pttrace.o
-hetmap_OBJ = hetmap.o hetlib.o sllib.o hostinfo.o version.o logmsg.o \
+hetmap_OBJ = hetmap.o hetlib.o ftlib.o sllib.o hostinfo.o version.o logmsg.o \
codepage.o hsys.o pttrace.o
hetupd_OBJ = hetupd.o hetlib.o sllib.o codepage.o hostinfo.o version.o \
@@ -211,7 +211,7 @@ dyngui_OBJ = dyngui.o
HEADERS = codepage.h commadpt.h cpuint.h ctcadpt.h dasdblks.h \
dasdtab.h dat.h devtype.h esa390.h feat370.h feat390.h \
- feat900.h featall.h featchk.h feature.h fishhang.h \
+ feat900.h featall.h featchk.h feature.h fishhang.h ftlib.h \
fthreads.h wthreads.h hbyteswp.h hercifc.h hercnls.h hercules.h \
hetlib.h hostinfo.h httpmisc.h htypes.h ieee-w32.h \
inline.h linklist.h logger.h machdep.h opcode.h chsc.h \
diff --git a/msvc.makefile.includes/OBJ_CODE.msvc b/msvc.makefile.includes/OBJ_CODE.msvc
index e3778345..9878fa38 100644
--- a/msvc.makefile.includes/OBJ_CODE.msvc
+++ b/msvc.makefile.includes/OBJ_CODE.msvc
@@ -52,6 +52,7 @@ hdasd_OBJ = \
htape_OBJ = \
$(O)hetlib.obj \
+ $(O)ftlib.obj \
$(O)sllib.obj \
$(O)w32stape.obj