home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * DFS 0.97
- * (c) Copyright Dan Vasaru 1991.
- *
- *
- *
- * Delete directory tree,find/list files with certain patterns in their names,
- * computes dir./lists size
- *
- *
- * Usage :
- * dfs [-flags] dirpath filespecs -x excl_filespecs
- *
- * Deletes filespecs in dirpath and below, excluding excl_filespecs.
- *
- * Flags :
- * -v verbose, use it to count files while deleting
- * check filenames ,don't do delfcb before looking for subdirs.
- * Verbose will skip the fcb deletion phase (which offers no control
- * over what is deleted. )
- * -d DEBUG lists all the files and exits. Use it to check what you
- * are deleting .Implies verbose.
- * -u no recurse in subdirectories
- * -n no prompts . DANGEROUS !
- * -c just count the files and sizes
- * -k keep dirs even if they are empty
- * -h prompt before deleting hidden/readonly/system files
- *
- * Param
- * dirpath : any valid DOS path ( without terminating backslash )
- * filespec : a wildchar'd filename. '*' replaces any string, while
- * '?' replaces a char.Thus, use '*wp?t*' denotes all files
- * containg the string 'wp' followed by an other letter
- * followed by a 't'. Don't forget the ending in '*'as matching
- * stops only on end_of_strings.
- *
- * WARNING ( take it as a hint ). Always use the -D option to check what you
- * actually are deleting.
- * examples :
- * 1. dfs -v a:\ -x *.com
- * --deletes all the files on a: less those with com extension
- *
- * 2. dfs -d c:\ *.sys *.pys *.asa -presents a list of all the files on
- * the c: drive that has the extension .sys or .pys or .asa.
- *
- * 3. dfs -n c:\ *old\*.sys --to delete all the .sys files in and
- * under the c:\ directory, which have old\ as
- * part of their pathnames
- *
- * 4. Find file :
- * dfs -d path filename
- * ^^
- *
- * 5. Compute dir size :
- * dfs -d -u -c path
- *
- * 6. Compute dir&subdir size
- * dfs -d -c path
- *
- * 7. List files that are in the usr subdirectory of any diretory, that
- * has the extension .c
- * dfs -d \ *usr\*.c
- *
- * 8. Delete empty directories :
- * dfs -v -h startpath invalid_file_name
- *
- * 9. Delete all files with \old\ in the path, except the .c and makefile
- * files
- * dfs \ *\old\*.* -x *.c makefile
- *
- *
- * FILENAME can be a string that contains * ? which will stand for any
- * number of chars (*) or any char (?) in the full path name
- * of the current evaluated file
- *
- * Wishlist :
- * I would like to introduce kind of recover file,so that a
- * 100% reliable quick unerase in case of disasters(del all files)
- * is possible.
- *
- * Warning : Version 0.950123 deleted all my files on the working partition !
- * (I forgot to use -d)
- * But now things should (!!!) be ok.
- * Bugs:
- * Sometimes the size reports are inaccurate
- * Other UI related problems.Does work,though.
- *
- * History :
- *
- * 10.07.1991 0.96 dan Fixed del RO HI bug, prettied the interface
- * 29.06.1991 0.95 dan bug fixes, introduced simple wildchar match, added
- * file exclusion with match.
- *
- * Any bug reports, congratulations *grin* etc can be mailed to :
- * A
- * Dan Vasaru
- * C studpost. 206 NTH
- * N-7034 Trondheim,Norway
- *
- * E-mail : dvasaru@lise.unit.no
- *
- * Copyright :
- * This software is hereby placed in the Public Domain.You can distribute,
- * modify and distribute the modified files as long as the original copyright
- * notice is not removed.Changes should be added to history.
- * Contributions :
- * If you do like the program , nobody can stop you from sending a small
- * contribution (big enough for a beer in Norway, though: ~7 $).Higher
- * contributions would earn you a Disk of Honour with the latest version
- * of the program and the right to ask more from me (that is docs,features).
- * But, no promise unless you hire me :-).
- *
- * Disclaimer :
- * Since this is PD software , I assume no responsabilies for losses or
- * damages caused by the misuse of this program.
- *
- * REMAINDER :
- * Don't Forget The -d parameter the first time U use the prgrm ...
- *
- * OBS : There will never be a >1.0 Release. Watch out for modified copies, since
- * the program *is* potentially dangerous.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include <direct.h>
- #include <conio.h>
- #include <signal.h>
- #include <dos.h>
- #include <errno.h>
-
- int recurse(void);
- int fremove(struct find_t *f);
-
- char fullname[_MAX_PATH];
- int countfiles, countdir;
- long countbytes;
-
- struct fcb {
- unsigned char dev;
- char name[8];
- char ext[3];
- char rest[26];
- } alldel;
-
- union REGS regs;
- struct SREGS sregs;
- char *dirp;
- char *wildchar;
- char **fspec;
-
- struct options {
- unsigned prompter : 1;
- unsigned delempty : 1;
- unsigned recur : 1;
- unsigned regular : 1;
- unsigned c : 1, prompt : 1, check : 1, verbose : 1;
- unsigned justcount : 1;
- } opt={1,1,1,0,0,1,0,0,0};
-
- int delete_drive;
- int _fastcall matchstring(register char _near * n, register char _near * pat);
- char **eargv,**exclude ;
- int OrigDrive,_flag_exit;
- char OrigDir[64];
-
- void go_back(void)
- {
- if (_flag_exit) {
- puts("CTRL+BREAK pressed.\n");
- _chdrive(OrigDrive);
- chdir(OrigDir);
- exit(2);
- }
- }
-
- void flagexit(void)
- {
- _flag_exit=1;
- }
-
- main(int argc, char *argv[])
- {
- int drive1;
- char *s;
- struct diskfree_t disks;
- long before, after;
-
- puts("DFS 0.97- delete,find,calc size of files\\directory tree");
- puts("(c) Dan Vasaru 1991.\n");
-
- if (argc==1){
- usage:
- puts("Usage :\n deldir [-u|d|n|h|v] dirpath filspec1 filespec2 ... -x filename3 filename4 ..");
- exit(-1);
- }
- eargv = argv;
- eargv++;
- while (*eargv) {
- strupr(*eargv);
- if (!strcmp(*eargv, "-H"))
- opt.prompt = 0;
- else if (!strcmp(*eargv, "-N"))
- opt.prompt = opt.prompter = 0;
- else if (!strcmp(*eargv, "-K"))
- opt.delempty = 0;
- else if (!strcmp(*eargv, "-C"))
- opt.justcount = 1;
- else if (!strcmp(*eargv, "-U"))
- opt.recur = 0;
- else if (!strcmp(*eargv, "-D")) {
- opt.verbose = 1;
- opt.check = 1;
- } else if (!strcmp(*eargv, "-V"))
- opt.verbose = 1;
- else if (!dirp)
- dirp = strupr(*eargv);
- else if (!strcmp(*eargv, "-X")) {
- if ((*eargv)[2]) {
- exclude=eargv; /* in case some zooniie writes -xfilename */
- strcpy(*eargv,*eargv+2);
- } else
- exclude=eargv+1;
- break;
- }
- else if (!fspec)
- fspec = eargv;
- eargv++;
- }
-
- delete_drive=dirp[0]-'A'+1;
- OrigDrive=_getdrive();
- getcwd(OrigDir,64);
- if (dirp[1]!=':')
- delete_drive=_getdrive();
- else
- if (_chdrive(delete_drive)) {
- perror("Couldn't change to specified drive :");
- exit(-1);
- }
-
- _fullpath(fullname, dirp, _MAX_PATH);
-
- if (chdir(dirp)) {
- perror("Couldn't change to specified directory :");
- exit(1);
- }
-
- if (opt.prompter && !opt.check) {
- int c;
- printf("Are you sure that you want to delete the specified files in the \n%s directory %s ? (Y/N)\n",
- fullname,opt.recur ?"and below":"");
- c = getch();
- if (c != 'y' && c != 'Y')
- exit(1);
- }
- signal(SIGINT, flagexit);
-
- if (fspec && (s = strchr(*fspec, '.')) != NULL)
- if (!*(s + 1)) { /* spec fil. ==> fil\0 */
- *s = '\0';
- }
-
- _chdrive(tolower(fullname[0]) - 'a' + 1);
- drive1 = _getdrive();
-
- _dos_getdiskfree(drive1, &disks);
-
- before = (long) disks.avail_clusters *
- disks.sectors_per_cluster *
- disks.bytes_per_sector;
- alldel.dev = drive1;
-
-
- if (!fspec)
- strcpy(alldel.name, "* * ");
-
- regs.h.ah = 0x13; /* delete fcb file */
-
- sregs.ds = (long) ((int _far *) (&alldel)) >> 16;
- regs.x.dx = ((long) &alldel) & 0xffff;
-
- recurse();
- chdir("..");
- rmdir(dirp);
- _dos_getdiskfree(drive1, &disks);
- after = (long) disks.avail_clusters *
- disks.sectors_per_cluster *
- disks.bytes_per_sector;
-
- if (!opt.verbose || opt.check)
- printf("\nDirectories count: %d\nFiles count: %d \nTotal data : %ld\nDisk free space: %ld\n",
- countdir, countfiles, countbytes, after );
- else
- printf("\nDirectories count: %d\nDisk freespace : %ld",
- countdir, after);
- _flag_exit=1;
- _chdrive(OrigDrive);
- chdir(OrigDir);
- exit(0);
- }
-
- #define ALL_FILES _A_ARCH|_A_HIDDEN|_A_NORMAL|_A_RDONLY| _A_SUBDIR|_A_SYSTEM
-
- int match(char *n, long size)
- {
- char *p;
- char **a;
- static int i;
-
- n = _fullpath(fullname, n, _MAX_PATH);
- go_back();
- if (!strchr(fullname,'.')) {
- fullname[strlen(fullname)+1]='\0';
- fullname[strlen(fullname)]='.';
- }
-
- if (!n) {
- perror(" _fullpath error");
- return 0;
- }
-
- for (a=fspec;*a && a!=exclude;a++ ) {
- if (matchstring(fullname,*a))
- break;
- }
- if ( a && (!*a || a==exclude))
- return 0;
- /* not in match list */
-
- /* Check if file in exclude list */
- if (exclude)
- for (a=exclude ; *a ;a++ ) {
- if (matchstring(fullname,*a))
- return 0;
- }
-
- if ( !opt.prompter && !opt.check)
- return 1;
-
- countfiles++;
- countbytes += size;
-
- if (opt.check) {
- printf("%s\n",fullname);
- return 0;
- }
-
- if (!opt.justcount)
- if (i != 'C'){
- if (!opt.check)
- strcat(fullname, " matchs spec, delete(Y) ,continue without asking(C) ?");
- puts(fullname);
- i = getch();
- puts("\n");
- }
- else
- return 1;
-
- i = toupper(i);
- if (i == 'Y' || i== 'C')
- return 1;
- return 0;
- }
-
-
-
- int recurse()
- {
- struct find_t f;
-
- go_back();
- if (_dos_findfirst("*.*", ALL_FILES, &f)) {
- perror("Find first returns : ");
- return 0;
- }
- if (!opt.verbose && !exclude) {
- char **a;
- if (fspec)
- for(a=fspec;*a && a!=exclude ; a++) {
- char *p = strchr(*a, '.');
- go_back();
- if (!p) {
- strcpy(alldel.ext, "* ");
- } else {
- strncpy(alldel.ext, p + 1, 3);
- }
- strncpy(alldel.name, *a, 8);
- intdosx(®s, ®s, &sregs);
- } else
- intdosx(®s, ®s, &sregs); /* do it for all */
- }
-
-
- for (;;) {
- go_back();
- if ((f.attrib & _A_SUBDIR) && opt.recur) {
- if (!strcmp(".", f.name) ||
- !strcmp("..", f.name)) {
- } else {
- if (chdir(f.name)) {
- perror("Error recursing in dir :");
- } else {
- recurse();
- chdir(".."); /* daddy */
- if (!opt.check && opt.delempty) {
- char **a=NULL;
- if (exclude)
- for ( a=exclude ; *a ;a++ ) {
- if ( matchstring(f.name,*a) )
- break;
- }
-
- if ( (!a || !*a) && rmdir(f.name) && !fspec) { /* don't complain if fspec given */
- printf("Can't delete directory : %s\n",f.name);
- }
- }
- countdir++;
- }
- }
- } else {
- if (!fspec) {
- countfiles++;
- countbytes += f.size;
- }
- if (opt.check) {
- if (!fspec || match(f.name, f.size) && !opt.justcount) {
- _fullpath(fullname, f.name, _MAX_PATH);
- puts(fullname);
- }
- } else {
- if (!fspec || match(f.name, f.size))
- if (fremove(&f))
- perror("Cannot delete file : ");
- }
- }
- if (_dos_findnext(&f))
- break;
- }
- }
-
-
- #pragma check_stack ( off )
- int _fastcall matchstring(register char _near * n, register char _near * pat)
- {
- char _near *p = NULL, _near * poldstar = NULL;
- int state = 0,isbegin=1;
-
- if (!*pat)
- return *pat == *n;
-
- while (*pat && *n) {
- /* Remove next lines to make a general string match */
-
- if (*n == '.') {
- n++;
- continue;
- }
- if (*pat == '.') {
- pat++;
- continue;
- }
- /* some files have no extension , but this is NOT
- important in our strings */
-
- if (*pat == '*') {
- state = 1; /* all match */
- pat++;
- if (!*pat)
- return 1; /* it ends in '*' */
- }
- if (*pat == '?')
- state |= 2;
- if (toupper(*pat) != toupper(*n) && !(state & 2)) {
- if (state & 1) {
- n++; /* no match, but in '*' */
- continue;
- } else if (poldstar) {
- pat = poldstar;
- n = ++p; /* push it further */
- } else
- return 0;
- state &= 1;
- } else {
- if (state & 1) {
- poldstar = pat; /* matched one char, but
- * don't be sure */
- p = n; /* where were I in the orig statering ? n !!*/
- }
- pat++;
- state = 0;
- n++;
- continue;
- }
- }
- if (state == 1 && !*pat)
- return 1;
- if (*pat || *n)
- return 0;
- else
- return 1;
- }
-
- int fremove(struct find_t *f)
- {
- if (!opt.check)
- if (f->attrib & (_A_SYSTEM | _A_RDONLY | _A_HIDDEN)) {
- int c;
- c = 0;
- if (opt.prompt) {
- printf("The following file is marked as RO,hidden or system,delete it anyway ? : %s\n", _fullpath(fullname, f->name, _MAX_PATH));
- c = getch();
- puts("\n");
- }
- if (c == 'y' || c == 'Y')
- if (_dos_setfileattr(f->name, 0)) {
- perror("Couldn't change file attrib : ");
- c = 1;
- return 1;
- }
- }
- /* printf("removing : %s\n",f->name);*/
- return remove(f->name);
- }
-
-