home *** CD-ROM | disk | FTP | other *** search
- /* FCOPY.C -- contains fcopy() function */
- /* Version 3.1 */
- /* */
- /* This function copies one file to another, much as the DOS COPY */
- /* command does. This version adds the capability to detect if */
- /* the source and target filespecs, in fact, refer to the same file. */
- /* It will not copy a file onto itself, and will return an error */
- /* if that is attempted. */
- /* */
- /* fcopy now has three assembler functions to support it. As in */
- /* earlier versions, _copyfile performs the actual file reads and */
- /* writes. Two new functions have also been added: truename() uses */
- /* DOS function 60h to determine the canonical (fully qualified) */
- /* name of a file given a path name. It needs the function strtrim() */
- /* to remove leading and trailing white space from the name string */
- /* before processing. */
- /* */
- /* fcopy() uses a farmalloc() call to allocate a large file buffer */
- /* from the far heap, regardless of the memory model being used. */
- /* BUFF_SIZE, indicating the buffer size, can be any int sized */
- /* value up to (but not including) 65,535. It is recommended that */
- /* the buffer be a multiple of the sector size (512 bytes in the */
- /* current version of DOS), since reads and writes are more efficient */
- /* if they involve whole sectors. A good value to use is 65024 (in */
- /* decimal), since this is 1 sector (512 bytes) short of a complete */
- /* segment (64k bytes). */
- /* */
- /* Function prototypes are contained in fcopy.h */
- /* */
- /* Usage: */
- /* */
- /* #include "fcopy.h" */
- /* int fcopy (char *sourcename, char *targetname) */
- /* */
- /* Returns: If successful, returns 0. */
- /* */
- /* If copy fails, returns -1 and sets errno */
- /* and _doserrno to one of the following: */
- /* */
- /* 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) */
- /* DISKFUL Target disk full (-2) */
- /* NOCOPY Cannot copy file onto itself (-3) */
- /* ------------------------------------------------------------------- */
- /* Revision history: */
- /* */
- /* 1.0 5 JAN 92 Original. Written for Turbo C++. */
- /* */
- /* 1.1 19 JAN 92 Updated comments to reflect _farread() */
- /* and _farwrite() being split into */
- /* separate modules. No code changes to */
- /* this module. */
- /* */
- /* 2.0 16 MAR 92 Replaced _farread() and _farwrite() */
- /* functions with a single _copyfile() */
- /* function. fcopy() modified to match. */
- /* */
- /* 3.0 19 APR 92 Now checks to see if source and target */
- /* filespecs refer to the same file, to */
- /* avoid attempting to copy a file onto */
- /* itself. */
- /* */
- /* Also dropped the leading underscore */
- /* from the function name; it is now */
- /* fcopy (rather than _fcopy). */
- /* */
- /* 3.1 12 MAY 92 Returns -1 for all error conditions, */
- /* instead of returning _doserrno. */
- /* ------------------------------------------------------------------- */
- /* Copyright (c) 1992 Ray Waters */
- /* All Rights Reserved */
- /* ------------------------------------------------------------------- */
-
- #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 */
- #include <string.h> /* stricmp, strcmp */
- #include <errno.h> /* errno, _doserrno */
- #include "fcopy.h" /* fcopy, strtrim, truename, _copyfile */
-
- void __cleanup(void); /* function to close files, free memory */
-
- char far *buffer; /* far pointer to the file buffer */
- int SrcHandle, TgtHandle; /* file handles for source and target */
-
- int fcopy(char *sourcename, char *targetname)
- {
- struct ftime ft; /* structure for file date/time stamp */
- char qSrcName[128]; /* buffer for qualified source name */
- char qTgtName[128]; /* buffer for qualified target name */
-
- /* First, just perform a simple string compare to see if the source
- and target names are identical. This will provide some protection
- for users running a version of DOS earlier than 3.0, which is
- necessary to support the truename function below. */
-
- if (!stricmp(sourcename, targetname)) { /* if the names are the same */
- errno = NOCOPY; /* set errno */
- _doserrno = NOCOPY; /* set _doserrno */
- return -1; /* return error */
- }
-
- /* Next, check to see if the source and target filespecs actually
- refer to the same file. If they do, return an error without
- doing any further work. If either truename call returns an error
- see if truename is supported. If not, proceed (and hope for the
- best). If the error is an invalid pathname, return the error
- condition. */
-
- if (!truename(sourcename, qSrcName) && !truename(targetname, qTgtName)) {
- if (!strcmp(qSrcName, qTgtName)) { /* if the names are the same */
- errno = NOCOPY; /* set errno */
- _doserrno = NOCOPY; /* set _doserrno */
- return -1; /* return error */
- }
- }
- else if (errno != EINVFNC) /* if filespecs were invalid */
- return -1; /* return error */
-
- 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 */
- }
-
- TgtHandle = _creat(targetname, 0); /* create/truncate target */
- if (TgtHandle == -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(TgtHandle); /* close target file */
- return -1; /* return error */
- }
-
- /* perform the copy */
- if (_copyfile(SrcHandle, TgtHandle, buffer, BUFF_SIZE)) {
- __cleanup(); /* if copy failed, close files, free mem */
- return -1; /* return error */
- }
-
- setftime(TgtHandle, &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(TgtHandle); /* close target file */
- farfree(buffer); /* free memory */
- }
-