⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filecopy.c

📁 [随书类]Dos6.0源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************/
/* 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 + -