home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / FCOPY / FCOPY.C < prev    next >
C/C++ Source or Header  |  1993-12-01  |  11KB  |  170 lines

  1. /*  FCOPY.C  --  contains fcopy() function                              */
  2. /*  Version 3.1                                                         */
  3. /*                                                                      */
  4. /*  This function copies one file to another, much as the DOS COPY      */
  5. /*  command does.  This version adds the capability to detect if        */
  6. /*  the source and target filespecs, in fact, refer to the same file.   */
  7. /*  It will not copy a file onto itself, and will return an error       */
  8. /*  if that is attempted.                                               */
  9. /*                                                                      */
  10. /*  fcopy now has three assembler functions to support it.  As in       */
  11. /*  earlier versions, _copyfile performs the actual file reads and      */
  12. /*  writes.  Two new functions have also been added: truename() uses    */
  13. /*  DOS function 60h to determine the canonical (fully qualified)       */
  14. /*  name of a file given a path name.  It needs the function strtrim()  */
  15. /*  to remove leading and trailing white space from the name string     */
  16. /*  before processing.                                                  */
  17. /*                                                                      */
  18. /*  fcopy() uses a farmalloc() call to allocate a large file buffer     */
  19. /*  from the far heap, regardless of the memory model being used.       */
  20. /*  BUFF_SIZE, indicating the buffer size, can be any int sized         */
  21. /*  value up to (but not including) 65,535.  It is recommended that     */
  22. /*  the buffer be a multiple of the sector size (512 bytes in the       */
  23. /*  current version of DOS), since reads and writes are more efficient  */
  24. /*  if they involve whole sectors.  A good value to use is 65024 (in    */
  25. /*  decimal), since this is 1 sector (512 bytes) short of a complete    */
  26. /*  segment (64k bytes).                                                */
  27. /*                                                                      */
  28. /*  Function prototypes are contained in fcopy.h                        */
  29. /*                                                                      */
  30. /*  Usage:                                                              */
  31. /*                                                                      */
  32. /*      #include "fcopy.h"                                              */
  33. /*      int fcopy (char *sourcename, char *targetname)                  */
  34. /*                                                                      */
  35. /*  Returns:  If successful, returns 0.                                 */
  36. /*                                                                      */
  37. /*            If copy fails, returns -1 and sets errno                  */
  38. /*            and _doserrno to one of the following:                    */
  39. /*                                                                      */
  40. /*              EINVFNC     Invalid function number  (1)                */
  41. /*              ENOFILE     File not found  (2)                         */
  42. /*              ENOPATH     Path not found  (3)                         */
  43. /*              EMFILE      Too many open files  (4)                    */
  44. /*              EACCESS     Permission denied  (5)                      */
  45. /*              EBADF       Bad file number  (6)                        */
  46. /*              ECONTR      Memory blocks destroyed  (7)                */
  47. /*              ENOMEM      Not enough core  (8)                        */
  48. /*              EINVMEM     Invalid memory block address  (9)           */
  49. /*              EINVACC     Invalid access code  (12)                   */
  50. /*              DISKFUL     Target disk full  (-2)                      */
  51. /*              NOCOPY      Cannot copy file onto itself (-3)           */
  52. /*  ------------------------------------------------------------------- */
  53. /*  Revision history:                                                   */
  54. /*                                                                      */
  55. /*      1.0      5 JAN 92       Original.  Written for Turbo C++.       */
  56. /*                                                                      */
  57. /*      1.1     19 JAN 92       Updated comments to reflect _farread()  */
  58. /*                              and _farwrite() being split into        */
  59. /*                              separate modules.  No code changes to   */
  60. /*                              this module.                            */
  61. /*                                                                      */
  62. /*      2.0     16 MAR 92       Replaced _farread() and _farwrite()     */
  63. /*                              functions with a single _copyfile()     */
  64. /*                              function.  fcopy() modified to match.   */
  65. /*                                                                      */
  66. /*      3.0     19 APR 92       Now checks to see if source and target  */
  67. /*                              filespecs refer to the same file, to    */
  68. /*                              avoid attempting to copy a file onto    */
  69. /*                              itself.                                 */
  70. /*                                                                      */
  71. /*                              Also dropped the leading underscore     */
  72. /*                              from the function name; it is now       */
  73. /*                              fcopy (rather than _fcopy).             */
  74. /*                                                                      */
  75. /*      3.1     12 MAY 92       Returns -1 for all error conditions,    */
  76. /*                              instead of returning _doserrno.         */
  77. /*  ------------------------------------------------------------------- */
  78. /*      Copyright (c) 1992 Ray Waters                                   */
  79. /*      All Rights Reserved                                             */
  80. /*  ------------------------------------------------------------------- */
  81.  
  82. #define BUFF_SIZE   65024U          /* size of file buffer */
  83.  
  84. #include <io.h>             /* _open, _creat, _close */
  85. #include <fcntl.h>          /* definition for O_RDONLY */
  86. #include <alloc.h>          /* farmalloc, farfree */
  87. #include <string.h>         /* stricmp, strcmp */
  88. #include <errno.h>          /* errno, _doserrno */
  89. #include "fcopy.h"          /* fcopy, strtrim, truename, _copyfile */
  90.  
  91. void __cleanup(void);       /* function to close files, free memory */
  92.  
  93. char far *buffer;               /* far pointer to the file buffer */
  94. int  SrcHandle, TgtHandle;      /* file handles for source and target */
  95.  
  96. int fcopy(char *sourcename, char *targetname)
  97. {
  98.     struct ftime ft;                /* structure for file date/time stamp */
  99.     char qSrcName[128];             /* buffer for qualified source name */
  100.     char qTgtName[128];             /* buffer for qualified target name */
  101.  
  102.     /* First, just perform a simple string compare to see if the source
  103.        and target names are identical.  This will provide some protection
  104.        for users running a version of DOS earlier than 3.0, which is
  105.        necessary to support the truename function below. */
  106.  
  107.     if (!stricmp(sourcename, targetname)) {     /* if the names are the same */
  108.         errno = NOCOPY;                         /* set errno */
  109.         _doserrno = NOCOPY;                     /* set _doserrno */
  110.         return -1;                              /* return error */
  111.     }
  112.  
  113.     /* Next, check to see if the source and target filespecs actually
  114.        refer to the same file.  If they do, return an error without
  115.        doing any further work.  If either truename call returns an error
  116.        see if truename is supported.  If not, proceed (and hope for the
  117.        best).  If the error is an invalid pathname, return the error
  118.        condition. */
  119.  
  120.     if (!truename(sourcename, qSrcName) && !truename(targetname, qTgtName)) {
  121.         if (!strcmp(qSrcName, qTgtName)) {      /* if the names are the same */
  122.             errno = NOCOPY;                     /* set errno */
  123.             _doserrno = NOCOPY;                 /* set _doserrno */
  124.             return -1;                          /* return error */
  125.         }
  126.     }
  127.     else if (errno != EINVFNC)                  /* if filespecs were invalid */
  128.         return -1;                              /* return error */
  129.  
  130.     SrcHandle = _open(sourcename, O_RDONLY);    /* open source (read only) */
  131.     if (SrcHandle == -1)                        /* if open failed, */
  132.         return -1;                              /* return error */
  133.     if (getftime(SrcHandle, &ft)) {             /* get date/time stamp */
  134.         _close(SrcHandle);                      /* if error, close file */
  135.         return -1;                              /* return error */
  136.     }
  137.  
  138.     TgtHandle = _creat(targetname, 0);          /* create/truncate target */
  139.     if (TgtHandle == -1) {                      /* if open failed, */
  140.         _close(SrcHandle);                      /* close source file */
  141.         return -1;                              /* return error */
  142.     }
  143.  
  144.     if  (!(buffer = farmalloc(BUFF_SIZE))) {    /* allocate a far buffer */
  145.                                                 /* if allocation failed, */
  146.         _close(SrcHandle);                      /* close source file */
  147.         _close(TgtHandle);                      /* close target file */
  148.         return -1;                              /* return error */
  149.     }
  150.  
  151.                                                 /* perform the copy */
  152.     if (_copyfile(SrcHandle, TgtHandle, buffer, BUFF_SIZE)) {
  153.         __cleanup();                /* if copy failed, close files, free mem */
  154.         return -1;                              /* return error */
  155.     }
  156.  
  157.     setftime(TgtHandle, &ft);               /* set target date/time stamp */
  158.     __cleanup();                                /* close files, free mem */
  159.     return 0;                                   /* return success */
  160. }
  161.  
  162. /*------------------------------------------------------------------------*/
  163.  
  164. void __cleanup(void)                    /* close files and release memory */
  165. {
  166.     _close(SrcHandle);                          /* close source file */
  167.     _close(TgtHandle);                          /* close target file */
  168.     farfree(buffer);                            /* free memory */
  169. }
  170.