/*  The function returns 0 if sucessful, -1 otherwise.  Error codes     */
/*  are returned in the global variables errno and _doserrno.           */
/*  Possible error codes are:                                           */
/*                                                                      */
/*      EINVFNC     Invalid function number  (1)                        */
/*      ENOFILE     File not found  (2)                                 */
/*      ENOPATH     Path not found  (3)                                 */
/*      EMFILE      Too many open files  (4)                            */
/*      EACCESS     Permission denied  (5)                              */
/*      EBADF       Bad file number  (6)                                */
/*      ECONTR      Memory blocks destroyed  (7)                        */
/*      ENOMEM      Not enough core  (8)                                */
/*      EINVMEM     Invalid memory block address  (9)                   */
/*      EINVACC     Invalid access code  (12)                           */
/*           -1     Target disk full  (-1)                              */
/*  ------------------------------------------------------------------- */

#define BUFF_SIZE   65024U          /* size of file buffer */

#include <io.h>             /* _open, _creat, _close */
#include <fcntl.h>          /* definition for O_RDONLY */
#include <alloc.h>          /* farmalloc, farfree, NULL pointer */
#include "copy.h"           /* FileCopy, _farread, _farwrite */

void __cleanup(void);       /* function to close files, free memory */

char far *buffer;
int 		SrcHandle, DestHandle;

int 		FileCopy(const char *sourcename, const char *destname)
{
	register int BytesRead;
	struct ftime ft;

	SrcHandle = _open(sourcename, O_RDONLY);		/* open source (read only) */
	if (SrcHandle == -1)												/* if open failed, */
		return -1;																/* return error */
	if (getftime(SrcHandle, &ft)) 							/* get date/time stamp */
	{
		_close(SrcHandle);												/* if error, close file */
		return -1;																/* return error */
	}

	DestHandle = _creat(destname, 0); 					/* create/truncate target */
	if (DestHandle == -1) 											/* if open failed, */
	{ 										
		_close(SrcHandle);												/* close source file */
		return -1;																/* return error */
	}

	if	(!(buffer = farmalloc(BUFF_SIZE)))			/* allocate a far buffer */
	{ 																					/* if allocation failed, */
		_close(SrcHandle);												/* close source file */
		_close(DestHandle); 											/* close target file */
		return -1;																/* return error */
	}

	do
	{ 																					/* read from source */
		BytesRead = _farread(SrcHandle, buffer, BUFF_SIZE);
		if (BytesRead == -1) {										/* if read failed, */
			__cleanup();														/* close files, free mem */
			return -1;															/* return error */
		}
																							/* write to target */
		if (_farwrite(DestHandle, buffer, BytesRead) == -1)
		{ 																				/* if write failed, */
			__cleanup();														/* close files, free mem */
			return -1;															/* return error */
		}
	}
	while (BytesRead);													/* loop until finished */

	setftime(DestHandle, &ft);									/* set target date/time stamp */
	__cleanup();																/* close files, free mem */
	return 0; 																	/* return success */
}

void __cleanup(void)                    /* close files and release memory */
{
	_close(SrcHandle);													/* close source file */
	_close(DestHandle); 												/* close target file */
	farfree(buffer);														/* free memory */
}
