📄 filecopy.c
字号:
register i; /* Loop Indice */
int iFile; /* DOS file handle */
unsigned uStatus; /* Error status */
struct find_t Info;
uStatus = (UINT) ERROR; /* Assume may not be successful */
#ifdef SYSTEMS_COMPRESSION
unsigned uRead; /* Count of byte read from file */
struct PACKED_HEADER Fh; /* Struct to hold file header */
struct WIN_HEADER Wh; /* Alternate windows file header */
static char MagicValue[8] = { 'S', 'Z', ' ', '\x88',
'\xf0', '\x27', '\x33', '\xd1' };
#endif
/* Try to open the file normally and if it fails */
/* try opening the file as a compressed file by */
/* switching last char of name extension to a '$' */
for ( i = 0; i < 2; i++ )
{
if ( (_dos_findfirst( szFile, _A_FINDALL, &Info ) == OK &&
_dos_open( szFile, ShareAccess, &iFile ) == OK) )
break;
szEndChar = strchr( szFile, EOL ); /* Find end of string */
if ( szEndChar != NULL )
*(szEndChar - 1) = '_';
}
if ( i < 2 ) /* See if open was OK */
{
File->lDestinSize = File->lSourceSize = filelength( iFile );
#ifdef SYSTEMS_COMPRESSION
/* Read in the file header */
if ( _dos_read( iFile, &Wh, sizeof( Wh ), &uRead ) == OK &&
uRead > 0 )
{
/* Need the header in both structures */
memcpy( &Fh, &Wh, sizeof( Wh ) );
/* Check for a languages group's header */
if ( memcmp( MagicValue, Fh.MagicStr, sizeof(MagicValue)) == OK )
{
File->lDestinSize = Fh.lDestinSize;
File->lRead = File->lUnpacked = (long)sizeof( Fh );
File->IsPacked = LANGUAGE_COMPRESS;
}
/* Now check for a Windows group's header */
else if ( memcmp( WIN_STR, Fh.MagicStr, sizeof(MagicValue)) == OK )
{
File->lDestinSize = Wh.lDestinSize;
File->lRead = File->lUnpacked = (long)sizeof( Wh );
File->IsPacked = WINDOWS_COMPRESS;
}
uStatus = OK;
}
#else
if ((int) (uStatus = WReadHeaderInfo (iFile)) > 0)
{
/* This is a compressed file, using APPS compression. */
/* Unfortunately, the file must be decompressed into */
/* RAM, as the APPS compression APIs do not have a */
/* method to decompress from a buffer to a file (but */
/* it can decompress from a file to a buffer). */
File->lDestinSize = LcbCalculateDecompressedLength (iFile, TRUE);
File->lSourceSize = File->lDestinSize;
File->IsPacked = TRUE;
uStatus = OK;
}
else
uStatus = (uStatus == rcNoHeader) ? OK : ERROR;
#endif
uStatus |= _dos_getftime( iFile, &File->Date, &File->Time );
uStatus |= _dos_close( iFile );
}
return( (uStatus == OK && File->lSourceSize > 0L) ? OK : ERROR );
}
/***************************************************************************/
/* Initializes the copy buffer to max available memory less 20K bytes. If */
/* there is less than 5K of memory available for use the program is */
/* with a call to FatalError(). The static global pchCpyBuffer is set to */
/* point to the successfully allocated buffer a buffer must also be */
/* allocate for the unpack functions. This buffer will have to be */
/* normalized so the functions can use it with an offset of 0 so 16 must */
/* be added to the offset before normalization to allow for this. */
/* */
/* void InitCpyBuffer( void ) */
/* */
/* ARGUMENTS: NONE */
/* RETURNS: void */
/* */
/* GLOBALS: lBufSize - Set to size of allocated buffer */
/* pchCpyBuffer - Pointed to allocated buffer */
/* UnPackSeg - Normalized ptr to an unpack segment area */
/* */
/***************************************************************************/
static int InitCpyBuffer( void )
{
register iStatus;
iStatus = ERROR; /* Error if fails any test */
/* Allocate an unpack segment */
#ifdef SYSTEMS_COMPRESSION
/* UnpackArea = GetMemory(UNPACK_BUF_LEN+RING_BUF_LEN+MAX_STR_LEN+100); */
UnpackArea = halloc( (long)(UNPACK_BUF_LEN + RING_BUF_LEN +MAX_STR_LEN + 100), 1 );
if ( UnpackArea == (char far *)(NULL) )
return( iStatus );
UnpackSeg = NormalizePtr( (char far *)UnpackArea + 16 );
#endif
/* Find out how much memory we can get */
Buf.BufLen = GetMaxHugeSize() - MALLOC_RESERVE;
if ( Buf.BufLen >= MIN_BUF_SIZE ) /* Is there enough memory ? */
{
Buf.Start = halloc( Buf.BufLen, 1); /* Do we allocate it OK */
if ( Buf.Start != NULL )
{
Buf.Next = Buf.Start; /* Set next free byte */
Buf.BytesFree = Buf.BufLen; /* Set number of bytes free */
iStatus = OK; /* Passed all tests */
}
}
return( iStatus );
}
/***************************************************************************/
/* Walks throught the array of file structures and writes out each file */
/* or a portition of each file that resides in the copy buffer. */
/* */
/* int BufFlush( void ) */
/* */
/* ARGUMENTS: void */
/* RETURN: int - OK if no error */
/* */
/* Return status will reflect the status of the last file written. This */
/* will be a signal to the BufCopyFile() to abort the current file being */
/* copied and go to the next file. */
/***************************************************************************/
static int BufFlush( void )
{
char *szFile;
int iFile;
int iStatus;
long lToWrite;
long lWritten;
struct MULT_FILES *ThisFile;
struct find_t Info;
DisplayFileStatus( "", CLEAR );
szFile = GetMemory( MAX_PATH_LEN ); /* Allocate a path buffer */
Buf.Next = Buf.Start; /* Reset ptr to begining of buf */
/* Loop until all files are checked */
for ( iStatus = OK, ThisFile = File;
ThisFile->Name.Source != NULL;
ThisFile++ )
{
BuildPath( szFile, ThisFile->Drive.Destin, ThisFile->Path.Destin,
ThisFile->Name.Destin );
if ( ThisFile->lUnpacked < ThisFile->lSourceSize )
{
iStatus = ERROR;
lToWrite = ThisFile->lRead - ThisFile->lUnpacked;
DispInsertUserDisk( ThisFile->UserDisk, ThisFile->Drive.Destin );
DisplayFileStatus( ThisFile->Name.Destin, WRITE );
_dos_setfileattr( szFile, _A_NORMAL );
if ( (_dos_findfirst( szFile, _A_FINDALL, &Info ) == OK &&
_dos_open( szFile, O_RDWR, &iFile ) == OK)||
_dos_creat( szFile, 0, &iFile ) == OK )
{
if ( (lWritten = WriteFile( iFile, ThisFile, lToWrite )) != -1L )
{
iStatus = OK;
ThisFile->lUnpacked += lToWrite;
ThisFile->lWritten += lWritten;
if ( ThisFile->lWritten == ThisFile->lDestinSize )
{
chsize( iFile, ThisFile->lDestinSize );
_dos_setftime( iFile, ThisFile->Date, ThisFile->Time );
}
}
iStatus |= (int)_dos_close( iFile );
}
}
if ( iStatus != OK ||
(ThisFile->lRead == ThisFile->lSourceSize &&
ThisFile->lWritten != ThisFile->lDestinSize) )
{
if (gfCompressedDiskInstall)
{
gfCompressedDiskIsFull = TRUE;
FreeMemory (szFile); /* Free the path buffer */
return (ERROR);
}
else
{
ProcessCopyError( ParseFileName( szFile ), ERR_WRITING );
ThisFile->lSourceSize = 0L; /* If error set file size to 0 */
ThisFile->lDestinSize = 0L;
}
}
if ( ThisFile->lSourceSize == 0L ) /* If source size == 0 we had an */
remove( szFile ); /* error so delete destin file */
}
Buf.BytesFree = Buf.BufLen; /* Reset number of bytes free */
Buf.Next = Buf.Start; /* Reset ptr to begining of buf */
FreeMemory( szFile ); /* Free the path buffer */
DisplayFileStatus( "", CLEAR );
return( iStatus );
}
/***************************************************************************/
/* Writes out the part of a file in the copy buffer with checking for */
/* using UnPack() or BigReadWrite() depending on whether the file is a */
/* packed file or not. */
/* */
/* static long WriteFile( int iFile, struct MULT_FILES *ThisFile, */
/* long lToWrite ) */
/* */
/* ARGUMENTS: iFile - Open DOS file handle, file pointer must be set */
/* to position for start of read or write */
/* ThisFile - Structure describing the file being written */
/* lToWrite - Number of bytes in the copy buffer to write out */
/* RETURN: long - Number of bytes written to output file or -1L if */
/* and error was detected. */
/* */
/***************************************************************************/
static long WriteFile( int iFile, struct MULT_FILES *ThisFile, long lToWrite )
{
long lWritten;
#ifdef SYSTEMS_COMPRESSION
int HeaderLen;
#endif
lWritten = -1L; /* Assume there may be an error */
/* Be sure file is the length it is supposed to be */
/* and then seek to the offset for the next write */
if ( filelength( iFile ) >= ThisFile->lWritten &&
_dos_seek( iFile, ThisFile->lWritten, SEEK_SET ) == ThisFile->lWritten )
{
#ifdef SYSTEMS_COMPRESSION
if ( ThisFile->IsPacked ) /* Check for compress file */
{
/* If first time for file, initialize ring buffer */
HeaderLen = ThisFile->IsPacked == WINDOWS_COMPRESS ?
sizeof( struct WIN_HEADER ) :
sizeof( struct PACKED_HEADER );
if ( ThisFile->lUnpacked <= HeaderLen )
ClearRingBuffer( ThisFile->IsPacked );
lWritten = Unpack( iFile, ThisFile->pchStart, lToWrite );
}
else
#endif
if ( BigReadWrite( iFile, ThisFile->pchStart, lToWrite,
WRITE ) == OK )
lWritten = lToWrite; /* written == lToWrite */
}
return( lWritten );
}
#ifndef SYSTEMS_COMPRESSION
/***************************************************************************/
/* Expands a file directly from file to file without buffering in memory. */
/* Used as a performance enhancement when copying large packed files and */
/* installing to a hard disk (no disk swaps necessary). */
/* */
/* static long ExpandFile( int iFile, struct MULT_FILES *ThisFile ) */
/* */
/* ARGUMENTS: fhSrc - Open DOS file handle, file pointer must be set */
/* to start of file (input packed file) */
/* ThisFile - Structure describing the file being written */
/* RETURN: long - Number of bytes written to output file or -1L if */
/* and error was detected. */
/* */
/***************************************************************************/
static long ExpandFile( int fhSrc, struct MULT_FILES *ThisFile )
{
char *szFile;
int iFile;
int iStatus;
long lWritten;
struct find_t Info;
DisplayFileStatus( "", CLEAR );
szFile = GetMemory( MAX_PATH_LEN ); /* Allocate a path buffer */
BuildPath( szFile, ThisFile->Drive.Destin, ThisFile->Path.Destin,
ThisFile->Name.Destin );
iStatus = ERROR;
DisplayFileStatus( ThisFile->Name.Destin, WRITE );
_dos_setfileattr( szFile, _A_NORMAL );
if ( (_dos_findfirst( szFile, _A_FINDALL, &Info ) == OK &&
_dos_open( szFile, O_RDWR, &iFile ) == OK)||
_dos_creat( szFile, 0, &iFile ) == OK )
{
lWritten = LcbDecompressToFile( fhSrc, iFile, LCBNIL, 0L, FALSE );
if ( lWritten == ThisFile->lDestinSize )
{
iStatus = OK;
ThisFile->lWritten = lWritten;
ThisFile->lUnpacked = ThisFile->lRead = ThisFile->lSourceSize;
chsize( iFile, ThisFile->lDestinSize );
_dos_setftime( iFile, ThisFile->Date, ThisFile->Time );
} else
lWritten = 0; /* error, return 0 size */
iStatus |= (int)_dos_close( iFile );
}
if ( iStatus != OK )
{
if (gfCompressedDiskInstall)
{
gfCompressedDiskIsFull = TRUE;
FreeMemory (szFile); /* Free the path buffer */
return (ERROR);
}
else
{
ProcessCopyError( ParseFileName( szFile ), ERR_WRITING );
ThisFile->lSourceSize = 0L; /* If error set file size to 0 */
ThisFile->lDestinSize = 0L;
}
}
if ( ThisFile->lSourceSize == 0L ) /* If source size == 0 we had an */
remove( szFile ); /* error so delete destin file */
FreeMemory( szFile ); /* Free the path buffer */
DisplayFileStatus( "", CLEAR );
return ( lWritten );
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -