home *** CD-ROM | disk | FTP | other *** search
/ Zodiac Super OZ / MEDIADEPOT.ISO / FILES / 16 / FREEDOS.ZIP / FD_A4PRE.ZIP / SOURCE / POWERC.ZIP / move.c < prev    next >
C/C++ Source or Header  |  1995-02-20  |  15KB  |  543 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <dos.h>
  5. #include <direct.h>
  6. #include <malloc.h>
  7.  
  8. #define BOOLEAN char                /* defining BOOLEAN type */
  9. #define TRUE 1
  10. #define FALSE 0
  11.  
  12. #define TESTMODE FALSE              /* whether or not to manipulate files */
  13.  
  14. #define STRSIZ 256                  /* default size for strings */
  15.  
  16. #define BUFMAX 0x0D000              /* buffer size for file copies */
  17.  
  18. #define MOVE_DEFAULT   FA_ARCH
  19. #define EXISTING_FILES FA_ARCH | FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_DIREC | FA_LABEL
  20.  
  21. #define EXPLANATIONS               1    /* errorlevel codes */
  22. #define NO_SUCH_SOURCE             2
  23. #define UNMOVEABLE_SOURCE          3
  24. #define NO_SUCH_DESTINATION        4
  25. #define EXISTING_BAD_DESTINATION   5
  26. #define IDENTICAL_SOURCE_AND_DEST  6
  27. #define SOURCE_TEMP_DEST_FILE      7
  28. #define MALLOC_ERROR               8
  29. #define FILE_OPEN_ERROR            9
  30. #define RENAME_ERROR              10
  31. #define COPY_ERROR                11
  32. #define ERASE_ERROR               12
  33.  
  34. #define T_DIR  1                        /* source / dest types */
  35. #define T_FILE 2
  36. #define T_TEMP 3
  37.  
  38. void *buffy;                            /* buffer for copies and its size */
  39. unsigned int bufsize;
  40.  
  41. int srctype, dsttype, MOVEABLE_FILES = MOVE_DEFAULT;
  42. char fullsrc[STRSIZ], fulldst[STRSIZ], srcpath[STRSIZ], dstpath[STRSIZ],
  43.      source[STRSIZ], dest[STRSIZ], srcfile[13], dstfile[13];
  44. BOOLEAN always_overwrite = FALSE;
  45. /*
  46. -----------------------------------------------------
  47. */
  48. char *fexpand(char *pathout, char *pathin)  /* expand file name to full path */
  49. {
  50.   char *chrptr;
  51.   _AH = 0x60;
  52.   chrptr = pathin;
  53.   _DS = FP_SEG(chrptr);
  54.   _SI = FP_OFF(chrptr);
  55.   chrptr = pathout;
  56.   _ES = FP_SEG(chrptr);
  57.   _DI = FP_OFF(chrptr);
  58.   geninterrupt(0x21);
  59.   return pathout;
  60. }
  61. /*
  62. -----------------------------------------------------
  63. */
  64. void matchfiletime(char *fnin, char *fnout)   /* make timestamps equal */
  65. {
  66.   unsigned int handle, tmpcx, tmpdx;
  67.   
  68.   _AH = 0x3d;                                 /* open input file */
  69.   _AL = 0x40;
  70.   _DS = FP_SEG(fnin);
  71.   _DX = FP_OFF(fnin);
  72.   geninterrupt(0x21);
  73.   handle = _AX;
  74.   
  75.   _AH = 0x57;                                 /* get file time from input */
  76.   _AL = 0x00;
  77.   _BX = handle;
  78.   geninterrupt(0x21);
  79.   tmpcx = _CX;
  80.   tmpdx = _DX;
  81.   
  82.   _AH = 0x3e;                                 /* close input file */
  83.   _BX = handle;
  84.   geninterrupt(0x21);
  85.   
  86.   _AH = 0x3d;                                 /* open output file */
  87.   _AL = 0x40;
  88.   _DS = FP_SEG(fnout);
  89.   _DX = FP_OFF(fnout);
  90.   geninterrupt(0x21);
  91.   handle = _AX;
  92.   
  93.   _AH = 0x57;                                 /* set output file time */
  94.   _AL = 0x01;
  95.   _BX = handle;
  96.   _CX = tmpcx;
  97.   _DX = tmpdx;
  98.   geninterrupt(0x21);
  99.   
  100.   _AH = 0x3e;                                 /* close output file */
  101.   _BX = handle;
  102.   geninterrupt(0x21);
  103. }
  104. /*
  105. -----------------------------------------------------
  106. */
  107. void setfileattrib(char *fname, char attrib)  /* set file attributes */
  108. {
  109.   _AH = 0x43;
  110.   _AL = 0x01;
  111.   _CH = 0x00;
  112.   _CL = attrib;
  113.   _DS = FP_SEG(fname);
  114.   _DX = FP_OFF(fname);
  115.   geninterrupt(0x21);
  116. }
  117. /*
  118. -----------------------------------------------------
  119. */
  120. void checkfrom(char *whattomove)  /* determine if valid source supplied */
  121. {
  122.   struct ffblk flrec;
  123.   char tmpfrom[STRSIZ];
  124.   fexpand(tmpfrom, whattomove);
  125.   if (findfirst(tmpfrom, &flrec, MOVEABLE_FILES) != 0)  /* none found */
  126.   {
  127.     printf("Error: no such file exists to MOVE.\n");
  128.     exit(NO_SUCH_SOURCE);
  129.   }
  130.   if (strchr(tmpfrom, '?') > 0) srctype = T_TEMP;     /* template or file? */
  131.   else srctype = T_FILE;
  132. }
  133. /*
  134. -----------------------------------------------------
  135. */
  136. void checkto(char *wheretomoveit)   /* check if valid destination */
  137. {
  138.   struct ffblk flrec;
  139.   int i;
  140.   char tmpdest[STRSIZ];
  141.   fexpand(tmpdest, wheretomoveit);
  142.   i = strlen(tmpdest) - 1;
  143.   while ((i >= 0) && (tmpdest[i] == '\\')) tmpdest[i--] = '\0';
  144.   if (strchr(tmpdest, '?') > 0)
  145.   {
  146.     dsttype = T_TEMP;
  147.     i = strlen(tmpdest) - 1;
  148.     while ((i >= 0) && (tmpdest[i] != '\\')) tmpdest[i--] = '\0';
  149.     while ((i >= 0) && (tmpdest[i] == '\\')) tmpdest[i--] = '\0';
  150.     if (tmpdest[2] != '\0')
  151.     {
  152.       if (findfirst(tmpdest, &flrec, FA_DIREC) != 0)
  153.       {
  154.         printf("Error: invalid path to destination.\n");
  155.         exit(NO_SUCH_DESTINATION);
  156.       }
  157.     }
  158.   }
  159.   else if (tmpdest[2] == '\0')
  160.   {
  161.     dsttype = T_DIR;
  162.   }
  163.   else
  164.   {
  165.     dsttype = T_FILE;
  166.     if (findfirst(tmpdest, &flrec, EXISTING_FILES) == 0)
  167.     {
  168.       if (flrec.ff_attrib & FA_LABEL == FA_LABEL)
  169.       {
  170.         printf("Error: destination is a volume label.\n");
  171.         exit(EXISTING_BAD_DESTINATION);
  172.       }
  173.       if ((flrec.ff_attrib & FA_DIREC) == FA_DIREC)
  174.       {
  175.         dsttype = T_DIR;
  176.       }
  177.       else
  178.       {
  179.         if (srctype == T_TEMP)
  180.         {
  181.           printf("Error: multiple files cannot be MOVEd to a single file.\n");
  182.           exit(SOURCE_TEMP_DEST_FILE);
  183.         }
  184.       }
  185.     }
  186.     else
  187.     {
  188.       dsttype = T_FILE;
  189.       if (srctype == T_TEMP)
  190.       {
  191.         printf("Error: multiple files cannot be MOVEd to a single file.\n");
  192.         exit(SOURCE_TEMP_DEST_FILE);
  193.       }
  194.       i = strlen(tmpdest) - 1;
  195.       while ((i >= 0) && (tmpdest[i] != '\\')) tmpdest[i--] = '\0';
  196.       while ((i >= 0) && (tmpdest[i] == '\\')) tmpdest[i--] = '\0';
  197.       if (tmpdest[2] != '\0')
  198.       {
  199.         if (findfirst(tmpdest, &flrec, FA_DIREC) != 0)
  200.         {
  201.           printf("Error: invalid path to destination.\n");
  202.           exit(NO_SUCH_DESTINATION);
  203.         }
  204.       }
  205.     }
  206.   }
  207. }
  208. /*
  209. -----------------------------------------------------
  210. */
  211. void parsepath(char *full, char *path, char *file)  /* split path & file */
  212. {
  213.   int i;
  214.   strcpy(path, full);
  215.   i = strlen(path) - 1;
  216.   while (path[i] != '\\') i--;        /* find final slash; split there */
  217.   i++;
  218.   strcpy(file, path + i);
  219.   path[i] = '\0';
  220. }
  221. /*
  222. -----------------------------------------------------
  223. */
  224. void parsefile(char *fullname, char *name, char *ext)   /* split name & ext */
  225. {
  226.   char *chrptr;
  227.   strcpy(name, fullname);
  228.   chrptr = strchr(name, '.');
  229.   if (chrptr == NULL)             /* no '.' -- no ext */
  230.   {
  231.     *ext = '\0';
  232.   }
  233.   else
  234.   {
  235.     strcpy(ext, chrptr + 1);      /* ext is the part after the '.' */
  236.     *chrptr = '\0';
  237.   }
  238. }
  239. /*
  240. -----------------------------------------------------
  241. */
  242. void xlatname(char *dfil, char *sfil)
  243.  
  244. /* construct destination file name, given actual input file name and
  245.    destination template */
  246.  
  247. {
  248.   char sfname[13], sfext[4], dtname[13], dtext[4];
  249.   int dstcnt, srccnt, tmpcnt;
  250.   
  251.   /* split input and template names into filename & ext */
  252.   
  253.   parsefile(sfil, sfname, sfext);
  254.   parsefile(dstfile, dtname, dtext);
  255.   srccnt = 0;
  256.   tmpcnt = 0;
  257.   dstcnt = 0;
  258.   
  259.   /* translate filename */
  260.   
  261.   while ((sfname[srccnt] != '\0') && (dtname[tmpcnt] != '\0'))
  262.   {
  263.     if (dtname[tmpcnt] == '?') dfil[dstcnt] = sfname[srccnt];
  264.                           else dfil[dstcnt] = dtname[tmpcnt];
  265.     srccnt++;
  266.     tmpcnt++;
  267.     dstcnt++;
  268.   }
  269.   
  270.   /* tacking on any final chars specified in template's filename */
  271.   
  272.   while ((dtname[tmpcnt] != '\0') && (dtname[tmpcnt] != '?'))
  273.   {
  274.     dfil[dstcnt] = dtname[tmpcnt];
  275.     tmpcnt++;
  276.     dstcnt++;
  277.   }
  278.   
  279.   /* put decimal */
  280.   
  281.   dfil[dstcnt] = '.';
  282.   dstcnt++;
  283.   srccnt = 0;
  284.   tmpcnt = 0;
  285.   
  286.   /* translate extension */
  287.   
  288.   while ((sfext[srccnt] != '\0') && (dtext[tmpcnt] != '\0'))
  289.   {
  290.     if (dtext[tmpcnt] == '?') dfil[dstcnt] = sfext[srccnt];
  291.                          else dfil[dstcnt] = dtext[tmpcnt];
  292.     srccnt++;
  293.     tmpcnt++;
  294.     dstcnt++;
  295.   }
  296.   
  297.   /* tacking on any final chars specified in template's extension */
  298.   
  299.   while ((dtext[tmpcnt] != '\0') && (dtext[tmpcnt] != '?'))
  300.   {
  301.     dfil[dstcnt] = dtext[tmpcnt];
  302.     tmpcnt++;
  303.     dstcnt++;
  304.   }
  305.   dfil[dstcnt] = '\0';
  306. }
  307. /*
  308. -----------------------------------------------------
  309. */
  310. void copy(char *fnin, char *fnout, struct ffblk flrec)  /* copy file */
  311. {
  312.   FILE *fin, *fout;
  313.   size_t numread, numwritten;
  314.   fin  = fopen(fnin,  "rb");
  315.   if (fin == NULL)                        /* open input file */
  316.   {
  317.     printf("Error opening %s\n", fnin);
  318.     exit(FILE_OPEN_ERROR);
  319.   }
  320.   fout = fopen(fnout, "wb");              /* open output file */
  321.   if (fout == NULL)
  322.   {
  323.     printf("Error opening %s\n", fnout);
  324.     exit(FILE_OPEN_ERROR);
  325.   }
  326.   do                            /* copy file, one buffer's worth at a time */
  327.   {
  328.     numread = fread(buffy, 1, bufsize, fin);
  329.     if (numread > 0)
  330.     {
  331.       numwritten = fwrite(buffy, 1, numread, fout);
  332.       if (numread > numwritten)
  333.       {
  334.         fclose(fin);
  335.         fclose(fout);
  336.         printf("Error transfering data from %s to %s.\n", fnin, fnout);
  337.         exit(COPY_ERROR);
  338.       }
  339.     }
  340.   } while (numread == bufsize);
  341.   fclose(fin);
  342.   fclose(fout);
  343.   matchfiletime(fnin, fnout);               /* fix output file time */
  344.   setfileattrib(fnout, flrec.ff_attrib);    /* fix output file attribs */
  345. }
  346. /*
  347. -----------------------------------------------------
  348. */
  349. void erase(char *fname)                     /* erase a file */
  350. {
  351.   setfileattrib(fname, 0);
  352.   if (remove(fname) != 0)
  353.   {
  354.     printf("Error erasing %s.\n", fname);
  355.     exit(ERASE_ERROR);
  356.   }
  357. }
  358. /*
  359. -----------------------------------------------------
  360. */
  361. void performmoves()
  362. {
  363.   struct ffblk srcflrec, dstflrec;
  364.   char sfil[13], dfil[13], fullin[STRSIZ], fullout[STRSIZ], yn[STRSIZ];
  365.   int doserror;
  366.   BOOLEAN copyit;
  367.   doserror = findfirst(fullsrc, &srcflrec, MOVEABLE_FILES);
  368.   while (doserror == 0)                                   /* loop thru files */
  369.   {
  370.     strcpy(sfil, srcflrec.ff_name);
  371.     xlatname(dfil, sfil);
  372.     strcpy(fullin,  srcpath); strcat(fullin,  sfil);
  373.     strcpy(fullout, dstpath); strcat(fullout, dfil);
  374.     printf("%s --> %s\n", fullin, fullout);
  375.     if (findfirst(fullout, &dstflrec, EXISTING_FILES) == 0)
  376.     {
  377.       if ((dstflrec.ff_attrib & FA_DIREC) == FA_DIREC)
  378.       {
  379.         printf(" -- Cannot move %s to %s:\n    %s is an existing directory.\n",
  380.                fullin, fullout, fullout);
  381.         copyit = FALSE;
  382.       }
  383.       else if ((dstflrec.ff_attrib & FA_LABEL) == FA_LABEL)
  384.       {
  385.         printf(" -- Cannot move %s to %s:\n    %s is a volume label.\n",
  386.                fullin, fullout, fullout);
  387.         copyit = FALSE;
  388.       }
  389.       else
  390.       {
  391.         if (!always_overwrite)
  392.         {
  393.           do
  394.           {
  395.             printf("Overwrite %s with %s? (y/n) ", fullout, fullin);
  396.             scanf("%s", yn);
  397.             strupr(yn);
  398.           } while ((yn[0] != 'Y') && (yn[0] != 'N'));
  399.         }
  400.         if ((always_overwrite) || (yn[0] == 'Y'))
  401.         {
  402.           copyit = TRUE;
  403.           if (TESTMODE)
  404.           {
  405.             printf("  Deleting %s ...\n", fullout);
  406.           }
  407.           else
  408.           {
  409.             erase(fullout);
  410.           }
  411.         }
  412.         else copyit = FALSE;
  413.       }
  414.     }
  415.     else copyit = TRUE;
  416.     if (copyit && !TESTMODE)
  417.     {
  418.       if (fullin[0] == fullout[0])
  419.       {
  420.         if (rename(fullin, fullout) != 0)
  421.         {
  422.           printf("Error occurred renaming %s to %s.\n", fullin, fullout);
  423.           exit(RENAME_ERROR);
  424.         }
  425.       }
  426.       else
  427.       {
  428.         copy(fullin, fullout, srcflrec);
  429.         erase(fullin);
  430.       }
  431.     }
  432.     doserror = findnext(&srcflrec);
  433.   }
  434. }
  435. /*
  436. -----------------------------------------------------
  437. */
  438. void explanation_screen()       /* show proper syntax */
  439. {
  440.   printf("\nMOVE\n\n");
  441.   printf("Syntax: MOVE [/options] <source> [destination]\n\n");
  442.   printf("        where <source> and [destination] are files or templates.\n");
  443.   printf("        If [destination] is omitted, the current directory is assumed.\n\n");
  444.   printf("OPTIONS: O    overwrite any existing files without asking\n");
  445.   printf("         H    MOVE hidden files\n");
  446.   printf("         S    MOVE system files\n");
  447.   printf("         ?    Display this screen\n");
  448.   exit(EXPLANATIONS);
  449. }
  450. /*
  451. -----------------------------------------------------
  452. */
  453. void process_argument(char *arg)  /* interpret a command-line argument */
  454. {
  455.   char opt;
  456.   int i;
  457.   if (arg[0] == '/')                        /* '/' options */
  458.   {
  459.     if (arg[1] == '\0')
  460.     {
  461.       printf("Invalid MOVE option.\n");
  462.       explanation_screen();
  463.     }
  464.     i = 1;
  465.     while (arg[i] != '\0')
  466.     {
  467.       opt = arg[i];
  468.       if ((opt >= 'a') && (opt <= 'z')) opt -= 0x20;
  469.       if      (opt == 'H') MOVEABLE_FILES = (MOVEABLE_FILES | FA_HIDDEN);
  470.       else if (opt == 'S') MOVEABLE_FILES = (MOVEABLE_FILES | FA_SYSTEM);
  471.       else if (opt == 'O') always_overwrite = TRUE;
  472.       else if (opt == '?') explanation_screen();
  473.       else
  474.       {
  475.         printf("Invalid MOVE option -- %c\n", arg[i]);
  476.         explanation_screen();
  477.       }
  478.       i++;
  479.     }
  480.   }
  481.   else if (source[0] == '\0') strcpy(source, arg);  /* no '/': must be file */
  482.   else if (dest[0]   == '\0') strcpy(dest, arg);
  483.   else
  484.   {
  485.     printf("Error: another file besides source and dest was specified.\n");
  486.     explanation_screen();
  487.   }
  488. }
  489. /*
  490. -----------------------------------------------------
  491. */
  492. void main(int argc, char *argv[])   /* main drag */
  493. {
  494.   int i;
  495.   source[0] = '\0';
  496.   dest[0] = '\0';
  497.   i = 1;
  498.   while (i < argc)                            /* process command line args */
  499.   {
  500.     process_argument(argv[i]);
  501.     i++;
  502.   }
  503.   if (source[0] == '\0')                      /* no source -- terminate */
  504.   {
  505.     printf("No source named!\n");
  506.     explanation_screen();
  507.   }
  508.   if (dest[0] == '\0') strcpy(dest, ".");     /* no dest -- assume current */
  509.   checkfrom(source);
  510.   checkto(dest);
  511.   fexpand(fullsrc, source);
  512.   parsepath(fullsrc, srcpath, srcfile);
  513.   fexpand(fulldst, dest);
  514.   if (dsttype == T_DIR)                       /* make full dest template */
  515.   {
  516.     if (fulldst[strlen(fulldst) - 1] != '\\') strcat(fulldst, "\\");
  517.     strcat(fulldst, srcfile);
  518.     dsttype = T_TEMP;
  519.   }
  520.   parsepath(fulldst, dstpath, dstfile);
  521.   if (strcmp(fullsrc, fulldst) == 0)
  522.   {
  523.     printf("Source and destination files are identical.\n");
  524.     exit(IDENTICAL_SOURCE_AND_DEST);
  525.   }
  526.   if (fullsrc[0] != fulldst[0])       /* MOVE between drives -- make buffer */
  527.   {
  528.     if (farcoreleft() < BUFMAX) bufsize = farcoreleft();
  529.                            else bufsize = BUFMAX;
  530.     buffy = malloc(bufsize);
  531.     if ((bufsize <= 0) || (buffy == NULL))
  532.     {
  533.       printf("Error: could not allocate buffer for file transfer.\n");
  534.       exit(MALLOC_ERROR);
  535.     }
  536.   }
  537.   performmoves();
  538.   if (fullsrc[0] != fulldst[0])       /* MOVE between drives -- lose buffer */
  539.   {
  540.     free(buffy);
  541.   }
  542. }
  543.