📄 filecopy.c
字号:
/***************************************************************************/
/* FILECOPY.C */
/* */
/* Copyright (c) 1991 - Microsoft Corp. */
/* All rights reserved. */
/* Microsoft Confidential */
/* */
/* */
/* File copy functions for copying multiple files across disks. */
/* */
/* */
/* Created 11-01-89 johnhe */
/* TABS = 3 */
/***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <share.h>
#include <sys\\types.h>
#include <sys\\stat.h>
#include <string.h>
#include <ctype.h>
#include <alias.h>
#include <disk_io.h>
#include <window.h>
#include <strlib.h>
#include <copy.h>
#include <decomp.h>
extern unsigned gfCompressedDiskIsFull;
extern unsigned gfCompressedDiskCritSection;
extern unsigned gfCompressedDiskInstall;
/***************************************************************************/
#define _A_FINDALL (_A_HIDDEN | _A_SYSTEM)
/* m116 #define MIN_BUF_SIZE 10000L */
/* m116 #define MALLOC_RESERVE 40000L */
#define MIN_BUF_SIZE 10000L /* m116 */
#define MALLOC_RESERVE 40000L /* m116 */
#define MAX_BLOCK 0xff00
extern void DispInsertDisk(int DiskNum);
extern void DispInsertUserDisk(int UserDisk,char chDrive);
#ifndef SYSTEMS_COMPRESSION
extern int IsHardDisk(int chDrive);
#endif
/***************************************************************************/
/* */
/* WR_BUF_INFO */
/* */
/* Status structure which contains the currents status of the disk */
/* write buffer. */
/* */
/***************************************************************************/
struct BUF_INFO
{
char far *Start; /* Far ptr to start of buffer */
char far *Next;
long BufLen; /* Total length of the buffer */
long BytesFree; /* Number free bytes left in the buffer */
};
/***************************************************************************/
/* Static globals for this module. */
/***************************************************************************/
static struct MULT_FILES *File; /* Ptr to current file information */
static struct BUF_INFO Buf; /* Copy buffer information struct */
#ifdef SYSTEMS_COMPRESSION
static char far *UnpackArea; /* Ptr to unpack area */
extern char far *UnpackSeg; /* Ptr segment allocated for unpack() */
#endif
/***************************************************************************/
/* Prototypes for local functions within this module. */
/***************************************************************************/
static UINT ShareAccess; /* File access mode */
static void BufCopyFile ( struct MULT_FILES *File );
static int BufFlush ( void );
static int InitCpyBuffer ( void );
static int InitFile ( struct MULT_FILES *File, char *szFile );
static long WriteFile ( int iFile, struct MULT_FILES *ThisFile,
long lToWrite );
long far Unpack ( int iFile, char far *InBuffer,
long lPackedBytes );
void far ClearRingBuffer( int CompressType );
void far CompressedDiskIsFull (void);
#ifndef SYSTEMS_COMPRESSION
static long ExpandFile ( int iFile, struct MULT_FILES *File );
#endif
/***************************************************************************/
/* Functions to copy multiple files between different drives. Will prompt */
/* for the disks before each file is read or written if the disk is not */
/* already inserted. Will allow the user to decide whether to continue or */
/* or not if there is an error reading any of the files. */
/* */
/* int Xcopy( struct MULT_FILES *FileList ) */
/* */
/* ARGUMENTS: FileList - Array of structures which describe everything */
/* necessary about the files. */
/* RETURNS: void */
/* */
/***************************************************************************/
void Xcopy( struct MULT_FILES *FileList )
{
register i;
if ( _osmajor < 3 || (_osmajor == 3 && _osminor < 10) )
ShareAccess = O_RDONLY;
else
ShareAccess = SH_DENYWR;
File = FileList; /* Set ptr to file structures */
if ( InitCpyBuffer() == OK ) /* Initialize the copy buffer */
{
/* Loop for each file */
for ( i = 0; gfCompressedDiskIsFull == FALSE &&
File[i].Name.Source != NULL; i++ )
BufCopyFile( File+i );
if (gfCompressedDiskIsFull == FALSE)
BufFlush(); /* Flush any files in memory */
hfree( Buf.Start ); /* Free the copy buffer */
#ifdef SYSTEMS_COMPRESSION
hfree( UnpackArea ); /* Free the unpacked segment */
/* FreeMemory( UnpackArea );*/ /* Free the unpacked segment */
#endif
if (gfCompressedDiskIsFull == TRUE)
{
/* The compressed disk filled up */
CompressedDiskIsFull(); /* This routine reboots */
}
}
else
FatalError( FATAL_MEMORY_ERROR );
}
/***************************************************************************/
/* Reads a specified file and appends it to the copy buffer. The copy */
/* buffer is flushed to disk as often as necessary. If an error occurs */
/* while reading a file the file is marked with a zero length and the */
/* user is given a chance to continue if no making recovery disk. */
/* */
/* void BufCopyFile( int Index ) */
/* */
/* ARGUMENTS: File - File structure for file to be copied. */
/* Source and Destination path and file members */
/* must be complete */
/* RETURNS: void */
/* */
/***************************************************************************/
static void BufCopyFile( struct MULT_FILES *File )
{
int iStatus; /* Return status */
int iFile; /* Open file handle */
char *szFile; /* Full path name for file */
long lToRead;
#ifndef SYSTEMS_COMPRESSION
int fFlush;
long lDecompRead;
File->pchStart = NULL;
#endif
szFile = GetMemory( MAX_PATH_LEN );
BuildPath( szFile, File->Drive.Source, File->Path.Source,
File->Name.Source );
do
{
#ifndef SYSTEMS_COMPRESSION
fFlush = FALSE;
#endif
iStatus = ERROR;
DispInsertDisk( File->DiskNumber );
DisplayFileStatus( File->Name.Source, READ );
/* Set up file's structure */
if ( File->lSourceSize == 0L && InitFile( File, szFile ) != OK )
{
File->lSourceSize = 0L;
break;
}
/* Determine how much of the file will fit in */
/* the buffer and where it will be written to */
#ifdef SYSTEMS_COMPRESSION
File->pchStart = Buf.Next;
#else
if ( File->pchStart == NULL )
File->pchStart = Buf.Next;
#endif
lToRead = File->lSourceSize - File->lRead;
if ( lToRead > Buf.BytesFree )
lToRead = Buf.BytesFree;
/* Open the file and seek to the location for */
/* the start of the next read. Then read in the */
/* portition of the file and update structures */
if ( _dos_open( szFile, ShareAccess, &iFile ) == OK )
{
#ifdef SYSTEMS_COMPRESSION
if ( _dos_seek( iFile, File->lRead, SEEK_SET ) == File->lRead )
{
if ( BigReadWrite( iFile, Buf.Next, lToRead, READ ) == OK )
{
/* Update buffer information */
Buf.Next = HugeAdd( Buf.Next, lToRead );
Buf.BytesFree -= lToRead;
/* Update the file's structure */
File->lRead += lToRead;
iStatus = OK; /* Can only get here if no error */
}
}
#else
if ( File->IsPacked )
{
/* The file is compressed, it gets uncompressed as it's read
into the buffer. There is a big time hit for every pass
through the same file because the decompression code has to
(re)decompress and through away everything it's already done
for a file on subsequent passes. So, if a packed file will
not fit into the remaining buffer space, but it will fit
into an empty buffer, force a BufFlush() call and loop back
here again. */
if ( lToRead == Buf.BytesFree ) /* reading to fill buffer? */
{
/* reading less when remaining, but remaining would fit in
empty buffer? */
lDecompRead = File->lSourceSize - File->lRead; /* remaining*/
if ( lToRead < lDecompRead )
if ( lDecompRead <= Buf.BufLen ) /* remaining fit? */
{
lToRead = 0; /* don't read anything this */
iStatus = OK; /* pass, just force a flush */
fFlush = TRUE; /* and read on next pass */
} else
/* The packed file is too big for even an empty buffer,
but if installing to a hard disk (non swappable)
it can be expanded directly from file to file.
Otherwise just go ahead and buffer it. */
if ( IsHardDisk(File->Drive.Destin) )
{
lToRead = 0; /* don't try to buffer below */
lDecompRead = ExpandFile( iFile, File );
UpdateByteCount (lDecompRead * 2); /* Update gauge */
if ( lDecompRead == File->lDestinSize )/* got all? */
iStatus = OK;
}
}
if ( lToRead > 0 ) /* may have been zeroed above */
{
/* read and decompress a chunk (maybe all) of the file */
lDecompRead = LcbDecompressToBuffer( iFile, Buf.Next, lToRead,
File->lRead, FALSE );
UpdateByteCount (lDecompRead); /* Update gauge */
if ( lDecompRead == lToRead ) /* got all that was requested? */
iStatus = OK;
}
} else {
/* The file is not packed, so just seek to the read offset
and read the next chunk */
if ( _dos_seek( iFile, File->lRead, SEEK_SET ) == File->lRead )
iStatus = BigReadWrite( iFile, Buf.Next, lToRead, READ );
}
if ( iStatus == OK )
{
/* Update buffer information */
Buf.Next = HugeAdd( Buf.Next, lToRead );
Buf.BytesFree -= lToRead;
/* Update the file's structure */
File->lRead += lToRead;
}
#endif
if ( _dos_close( iFile ) != OK ) /* Close the file checking */
iStatus = ERROR; /* for errors */
}
/* Check for an error reading the file and */
/* if error mark this file as 0 length if */
/* user decides to continue */
if ( iStatus != OK )
File->lSourceSize = 0L;
#ifdef SYSTEMS_COMPRESSION
else if ( Buf.BytesFree == 0 ) /* See if the buffer needs flushing */
#else
else if ( fFlush || Buf.BytesFree == 0 ) /* Buffer need flushing? */
#endif
{
#ifdef SYSTEMS_COMPRESSION
if ( BufFlush() != OK )
File->lSourceSize = 0L; /* Signal this file not written */
#else
if ( BufFlush() == OK )
File->pchStart = NULL;
else
File->lSourceSize = 0L; /* Signal this file not written */
#endif
}
}
while ( iStatus == OK && File->lRead < File->lSourceSize &&
gfCompressedDiskIsFull == FALSE);
if ( iStatus != OK )
ProcessCopyError( File->Name.Destin, ERR_READING );
FreeMemory( szFile );
}
/***************************************************************************/
/* Initializes a file structure for use by the BufCopyFile() function. */
/* Also reads first 12 bytes of the files to see if it is a packed file. */
/* */
/* int InitFile( struct MULT_FILES *File, char *szFile ) */
/* */
/* ARGUMENTS: File - Ptr to file structure to be initialized */
/* szFile - Complete file and path for a source file */
/* RETURNS: int - OK if no file errors else ERROR */
/* */
/***************************************************************************/
static int InitFile( struct MULT_FILES *File, char *szFile )
{
char *szEndChar;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -