home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DIR / DFS097.ZIP / DFS.C next >
Encoding:
C/C++ Source or Header  |  1992-03-06  |  13.3 KB  |  529 lines

  1. /*
  2. *
  3. *  DFS 0.97
  4. *  (c) Copyright Dan Vasaru 1991.
  5. *
  6. *
  7. *
  8. *  Delete directory tree,find/list files with certain patterns in their names,
  9. * computes dir./lists size
  10. *
  11. *
  12. *  Usage :
  13. *  dfs [-flags] dirpath filespecs -x excl_filespecs
  14. *
  15. *  Deletes filespecs in dirpath and below, excluding    excl_filespecs.
  16. *
  17. *  Flags :
  18. *     -v verbose, use it to count files while deleting
  19. *        check filenames ,don't do delfcb before looking for subdirs.
  20. *        Verbose will skip the fcb deletion phase (which offers no control
  21. *        over what is deleted. )
  22. *     -d DEBUG lists all the files and exits. Use it to check what you
  23. *        are deleting .Implies verbose.
  24. *     -u no recurse in subdirectories
  25. *     -n no prompts . DANGEROUS !
  26. *     -c just count the files and sizes
  27. *     -k keep dirs even if they are empty
  28. *     -h prompt before deleting hidden/readonly/system files
  29. *
  30. *  Param
  31. *    dirpath : any valid DOS path ( without terminating backslash )
  32. *      filespec : a wildchar'd filename. '*' replaces any string, while
  33. *                          '?' replaces a char.Thus, use '*wp?t*' denotes all files
  34. *                         containg the string 'wp' followed by an other letter
  35. *                         followed by a 't'. Don't forget the ending in '*'as matching
  36. *                         stops only on end_of_strings.
  37. *
  38. *  WARNING ( take it as a hint ). Always use the -D option to check what you
  39. *                     actually are deleting.
  40. *    examples :
  41. *             1.    dfs -v a:\ -x *.com
  42. *                         --deletes all the files on a: less those with com extension
  43. *
  44. *             2.    dfs -d c:\ *.sys *.pys *.asa -presents a list of all the files on
  45. *                         the c: drive that has the extension .sys or .pys or .asa.
  46. *
  47. *             3.    dfs -n c:\ *old\*.sys --to delete all the .sys files in and
  48. *                                             under the c:\ directory, which have old\ as
  49. *                                             part of their pathnames
  50. *
  51. *       4. Find file :
  52. *           dfs -d path filename
  53. *               ^^
  54. *
  55. *       5. Compute dir size :
  56. *          dfs -d -u -c path
  57. *
  58. *       6. Compute dir&subdir size
  59. *          dfs -d -c path
  60. *
  61. *       7. List files that are in the usr subdirectory of any diretory, that
  62. *          has the  extension .c
  63. *          dfs -d \ *usr\*.c
  64. *
  65. *       8. Delete empty directories :
  66. *          dfs -v -h startpath invalid_file_name
  67. *
  68. *       9. Delete all files with \old\ in the path, except the .c and makefile
  69. *          files
  70. *          dfs \ *\old\*.* -x *.c makefile
  71. *
  72. *
  73. * FILENAME can be a string that contains * ? which will stand for any
  74. *                  number of chars (*) or any char (?) in the full path name
  75. *          of the current evaluated file
  76. *
  77. * Wishlist :
  78. *     I would like to introduce kind of recover file,so that a
  79. *     100% reliable quick unerase in case of disasters(del all files)
  80. *      is possible.
  81. *
  82. *  Warning : Version 0.950123 deleted all my files on the working partition !
  83. *                      (I forgot to use -d)
  84. *                      But now things should (!!!) be ok.
  85. *  Bugs:
  86. *                     Sometimes the size reports are inaccurate
  87. *                     Other UI related problems.Does work,though.
  88. *
  89. *  History :
  90. *
  91. *     10.07.1991 0.96 dan Fixed del RO HI bug, prettied the interface
  92. *     29.06.1991 0.95 dan bug fixes, introduced simple wildchar match, added
  93. *                                             file exclusion with match.
  94. *
  95. *  Any bug reports, congratulations *grin* etc can be mailed to :
  96. * A
  97. *              Dan Vasaru
  98. * C          studpost. 206 NTH
  99. *              N-7034 Trondheim,Norway
  100. *
  101. *  E-mail : dvasaru@lise.unit.no
  102. *
  103. *  Copyright :
  104. *             This software is hereby placed in the Public Domain.You can distribute,
  105. *             modify and distribute the modified files as long as the original copyright
  106. *          notice is not removed.Changes should be added to history.
  107. *  Contributions :
  108. *                 If you do like the program , nobody can stop you from sending a small
  109. *                 contribution (big enough for a beer in Norway, though: ~7 $).Higher
  110. *                 contributions would earn you a Disk of Honour with the latest version
  111. *                 of the program and the right to ask more from me (that is docs,features).
  112. *                 But, no promise unless you hire me :-).
  113. *
  114. *  Disclaimer :
  115. *                 Since this is PD software , I assume no responsabilies for losses or
  116. *                 damages caused by the misuse of this program.
  117. *
  118. *  REMAINDER :
  119. *                 Don't Forget The -d parameter the first time U use the prgrm ...
  120. *
  121. *  OBS : There will never be a >1.0 Release. Watch out for modified copies, since
  122. *              the program *is* potentially dangerous.
  123. */
  124.  
  125. #include <stdio.h>
  126. #include <stdlib.h>
  127. #include <ctype.h>
  128. #include <string.h>
  129. #include <direct.h>
  130. #include <conio.h>
  131. #include <signal.h>
  132. #include <dos.h>
  133. #include <errno.h>
  134.  
  135. int recurse(void);
  136. int fremove(struct find_t *f);
  137.  
  138. char                        fullname[_MAX_PATH];
  139. int                         countfiles, countdir;
  140. long                        countbytes;
  141.  
  142. struct fcb {
  143.     unsigned char   dev;
  144.     char            name[8];
  145.     char            ext[3];
  146.     char            rest[26];
  147. }               alldel;
  148.  
  149. union REGS      regs;
  150. struct SREGS    sregs;
  151. char           *dirp;
  152. char           *wildchar;
  153. char           **fspec;
  154.  
  155. struct options {
  156. unsigned   prompter : 1;
  157. unsigned   delempty : 1;
  158. unsigned   recur : 1;
  159. unsigned   regular : 1;
  160. unsigned   c : 1, prompt : 1, check : 1, verbose : 1;
  161. unsigned   justcount : 1;
  162. } opt={1,1,1,0,0,1,0,0,0};
  163.  
  164. int           delete_drive;
  165. int           _fastcall  matchstring(register char _near * n, register char _near * pat);
  166. char          **eargv,**exclude ;
  167. int OrigDrive,_flag_exit;
  168. char OrigDir[64];
  169.  
  170. void go_back(void)
  171. {
  172.   if (_flag_exit) {
  173.   puts("CTRL+BREAK pressed.\n");
  174.   _chdrive(OrigDrive);
  175.   chdir(OrigDir);
  176.   exit(2);
  177.  }
  178. }
  179.  
  180. void flagexit(void)
  181. {
  182.   _flag_exit=1;
  183. }
  184.  
  185. main(int argc, char *argv[])
  186. {
  187.     int             drive1;
  188.   char *s;
  189.     struct diskfree_t disks;
  190.     long            before, after;
  191.  
  192.   puts("DFS 0.97- delete,find,calc size of files\\directory tree");
  193.     puts("(c) Dan Vasaru 1991.\n");
  194.  
  195.   if (argc==1){
  196.   usage:
  197.             puts("Usage :\n deldir [-u|d|n|h|v] dirpath filspec1 filespec2 ... -x filename3 filename4 ..");
  198.             exit(-1);
  199.     }
  200.     eargv = argv;
  201.     eargv++;
  202.     while (*eargv) {
  203.     strupr(*eargv);
  204.     if (!strcmp(*eargv, "-H"))
  205.             opt.prompt = 0;
  206.     else if (!strcmp(*eargv, "-N"))
  207.             opt.prompt = opt.prompter = 0;
  208.     else if (!strcmp(*eargv, "-K"))
  209.             opt.delempty = 0;
  210.     else if (!strcmp(*eargv, "-C"))
  211.             opt.justcount = 1;
  212.     else if (!strcmp(*eargv, "-U"))
  213.             opt.recur = 0;
  214.     else if (!strcmp(*eargv, "-D")) {
  215.             opt.verbose = 1;
  216.             opt.check = 1;
  217.     } else if (!strcmp(*eargv, "-V"))
  218.             opt.verbose = 1;
  219.         else if (!dirp)
  220.             dirp = strupr(*eargv);
  221.     else if (!strcmp(*eargv, "-X"))  {
  222.         if ((*eargv)[2]) {
  223.         exclude=eargv; /* in case some zooniie writes -xfilename */
  224.         strcpy(*eargv,*eargv+2);
  225.         } else
  226.         exclude=eargv+1;
  227.         break;
  228.         }
  229.     else if (!fspec)
  230.           fspec = eargv;
  231.         eargv++;
  232.     }
  233.  
  234.   delete_drive=dirp[0]-'A'+1;
  235.   OrigDrive=_getdrive();
  236.   getcwd(OrigDir,64);
  237.   if (dirp[1]!=':') 
  238.     delete_drive=_getdrive();
  239.   else
  240.     if (_chdrive(delete_drive)) {
  241.         perror("Couldn't change to specified drive :");
  242.         exit(-1);
  243.     }
  244.   
  245.     _fullpath(fullname, dirp, _MAX_PATH);
  246.  
  247.   if (chdir(dirp)) {
  248.         perror("Couldn't change to specified directory :");
  249.     exit(1);
  250.     }
  251.  
  252.   if (opt.prompter && !opt.check) {
  253.     int c;
  254.     printf("Are you sure that you want to delete  the specified files in the \n%s directory %s ? (Y/N)\n",
  255.                         fullname,opt.recur ?"and below":"");
  256.         c = getch();
  257.         if (c != 'y' && c != 'Y')
  258.             exit(1);
  259.     }
  260.   signal(SIGINT, flagexit);
  261.  
  262.   if (fspec && (s = strchr(*fspec, '.')) != NULL)
  263.     if (!*(s + 1)) { /* spec fil. ==> fil\0 */
  264.       *s = '\0';
  265.         }
  266.     
  267.     _chdrive(tolower(fullname[0]) - 'a' + 1);
  268.     drive1 = _getdrive();
  269.  
  270.     _dos_getdiskfree(drive1, &disks);
  271.  
  272.     before = (long) disks.avail_clusters *
  273.         disks.sectors_per_cluster *
  274.         disks.bytes_per_sector;
  275.     alldel.dev = drive1;
  276.  
  277.  
  278.     if (!fspec) 
  279.         strcpy(alldel.name, "*       *  ");
  280.  
  281.     regs.h.ah = 0x13;    /* delete fcb file */
  282.  
  283.     sregs.ds = (long) ((int _far *) (&alldel)) >> 16;
  284.     regs.x.dx = ((long) &alldel) & 0xffff;
  285.  
  286.     recurse();
  287.     chdir("..");
  288.     rmdir(dirp);
  289.     _dos_getdiskfree(drive1, &disks);
  290.     after = (long) disks.avail_clusters *
  291.         disks.sectors_per_cluster *
  292.         disks.bytes_per_sector;
  293.  
  294.     if (!opt.verbose || opt.check)
  295.         printf("\nDirectories count: %d\nFiles count: %d \nTotal data : %ld\nDisk free space: %ld\n",
  296.                      countdir, countfiles, countbytes, after );
  297.     else
  298.     printf("\nDirectories count: %d\nDisk freespace : %ld",
  299.                countdir, after);
  300.   _flag_exit=1;
  301.   _chdrive(OrigDrive);
  302.   chdir(OrigDir);
  303.   exit(0);
  304. }
  305.  
  306. #define ALL_FILES   _A_ARCH|_A_HIDDEN|_A_NORMAL|_A_RDONLY| _A_SUBDIR|_A_SYSTEM
  307.  
  308. int match(char *n, long size)
  309. {
  310.     char           *p;
  311.   char           **a;
  312.     static int      i;
  313.  
  314.     n = _fullpath(fullname, n, _MAX_PATH);
  315.   go_back();
  316.     if (!strchr(fullname,'.')) {
  317.              fullname[strlen(fullname)+1]='\0';
  318.              fullname[strlen(fullname)]='.';
  319.   }
  320.  
  321.     if (!n) {
  322.         perror(" _fullpath error");
  323.         return 0;
  324.     }
  325.  
  326.   for (a=fspec;*a && a!=exclude;a++ ) {
  327.     if (matchstring(fullname,*a))
  328.     break;
  329.   }
  330.     if ( a && (!*a || a==exclude))
  331.                                                 return 0;
  332.                        /* not in match list */
  333.  
  334.     /* Check if file in exclude list */
  335.   if (exclude)
  336.   for (a=exclude ; *a ;a++ ) {
  337.     if (matchstring(fullname,*a))
  338.     return 0;
  339.   }
  340.  
  341.     if ( !opt.prompter && !opt.check)
  342.         return 1;
  343.  
  344.   countfiles++;
  345.   countbytes += size;
  346.  
  347.     if (opt.check) {
  348.         printf("%s\n",fullname);
  349.         return 0;
  350.     }
  351.  
  352.   if (!opt.justcount)
  353.   if (i != 'C'){
  354.       if (!opt.check)
  355.                 strcat(fullname, " matchs spec, delete(Y) ,continue without asking(C) ?");
  356.                 puts(fullname);
  357.         i = getch();
  358.         puts("\n");
  359.     }
  360.     else
  361.       return 1;
  362.  
  363.     i = toupper(i);
  364.   if (i == 'Y' || i== 'C')
  365.         return 1;
  366.     return 0;
  367. }
  368.  
  369.  
  370.  
  371. int recurse()
  372. {
  373.     struct find_t   f;
  374.  
  375.   go_back();
  376.   if (_dos_findfirst("*.*", ALL_FILES, &f)) {
  377.         perror("Find first returns : ");
  378.         return 0;
  379.     }
  380.     if (!opt.verbose && !exclude) {
  381.   char **a;
  382.   if (fspec)
  383.   for(a=fspec;*a && a!=exclude ; a++) {
  384.     char           *p = strchr(*a, '.');
  385.     go_back();
  386.     if (!p) {
  387.             strcpy(alldel.ext, "*  ");
  388.         } else {
  389.             strncpy(alldel.ext, p + 1, 3);
  390.         }
  391.     strncpy(alldel.name, *a, 8);
  392.         intdosx(®s, ®s, &sregs);
  393.      } else
  394.         intdosx(®s, ®s, &sregs); /* do it for all */
  395.   }
  396.  
  397.  
  398.     for (;;) {
  399.     go_back();
  400.     if ((f.attrib & _A_SUBDIR) && opt.recur) {
  401.             if (!strcmp(".", f.name) ||
  402.                 !strcmp("..", f.name)) {
  403.             } else {
  404.                 if (chdir(f.name)) {
  405.                     perror("Error recursing in dir :");
  406.                 } else {
  407.                     recurse();
  408.                     chdir("..");    /* daddy */
  409.           if (!opt.check && opt.delempty)   {
  410.               char **a=NULL;
  411.               if (exclude)
  412.                   for ( a=exclude ; *a ;a++ ) {
  413.                       if ( matchstring(f.name,*a) )
  414.                                                break;
  415.                   }
  416.  
  417.               if ( (!a || !*a) &&  rmdir(f.name) && !fspec) { /* don't complain if fspec given */
  418.                 printf("Can't delete directory : %s\n",f.name);
  419.               }
  420.           }
  421.           countdir++;
  422.                 }
  423.             }
  424.         } else {
  425.       if (!fspec) {
  426.                     countfiles++;
  427.                     countbytes += f.size;
  428.                 }
  429.       if (opt.check) {
  430.                 if (!fspec || match(f.name, f.size) && !opt.justcount) {
  431.                     _fullpath(fullname, f.name, _MAX_PATH);
  432.                     puts(fullname);
  433.                 }
  434.             } else {
  435.                 if (!fspec || match(f.name, f.size))
  436.           if (fremove(&f))
  437.             perror("Cannot delete file : ");
  438.             }
  439.         }
  440.         if (_dos_findnext(&f))
  441.             break;
  442.     }
  443. }
  444.  
  445.  
  446. #pragma check_stack ( off )
  447. int _fastcall  matchstring(register char _near * n, register char _near * pat)
  448. {
  449.     char _near     *p = NULL, _near * poldstar = NULL;
  450.     int                         state = 0,isbegin=1;
  451.  
  452.     if (!*pat)
  453.     return *pat == *n;
  454.  
  455.     while (*pat && *n) {
  456.         /* Remove next lines to make a general string match */
  457.  
  458.     if (*n == '.') {
  459.         n++;
  460.         continue;
  461.     }
  462.     if (*pat == '.') {
  463.             pat++;
  464.             continue;
  465.     }
  466.         /* some files have no extension , but this is NOT
  467.         important in our strings */
  468.  
  469.         if (*pat == '*') {
  470.             state = 1; /* all match */
  471.             pat++;
  472.             if (!*pat)
  473.                 return 1;    /* it ends in '*' */
  474.         }
  475.         if (*pat == '?')
  476.             state |= 2;
  477.         if (toupper(*pat) != toupper(*n) && !(state & 2)) {
  478.             if (state & 1) {
  479.                 n++;    /* no match, but in '*' */
  480.                 continue;
  481.             } else if (poldstar) {
  482.                 pat = poldstar;
  483.                 n = ++p;    /* push it further */
  484.             } else
  485.                 return 0;
  486.             state &= 1;
  487.         } else {
  488.             if (state & 1) {
  489.                 poldstar = pat; /* matched one char, but
  490.                          * don't be sure */
  491.                 p = n;    /* where were I in the orig statering ? n !!*/
  492.             }
  493.             pat++;
  494.             state = 0;
  495.             n++;
  496.             continue;
  497.         }
  498.     }
  499.     if (state == 1 && !*pat)
  500.         return 1;
  501.     if (*pat || *n)
  502.         return 0;
  503.     else
  504.         return 1;
  505. }
  506.  
  507. int fremove(struct find_t *f)
  508. {
  509.       if (!opt.check)
  510.         if (f->attrib & (_A_SYSTEM | _A_RDONLY | _A_HIDDEN)) {
  511.           int c;
  512.                     c = 0;
  513.           if (opt.prompt) {
  514.                         printf("The following file is marked as RO,hidden or system,delete it anyway ? : %s\n", _fullpath(fullname, f->name, _MAX_PATH));
  515.                         c = getch();
  516.             puts("\n");
  517.                     }
  518.           if (c == 'y' || c == 'Y')
  519.             if (_dos_setfileattr(f->name, 0)) {
  520.               perror("Couldn't change file attrib : ");
  521.                             c = 1;
  522.               return 1;
  523.                         }
  524.         }
  525. /*    printf("removing : %s\n",f->name);*/
  526.     return  remove(f->name);
  527. }
  528.  
  529.