/* * CHAINSAW.... Chop down an entire directory tree. * * This program will remove an entire directory tree or portion thereof * (outward from any branch), including all sub-directories... * USE WITH EXTREME CAUTION!!! Careless use of this program could result * in the loss of LARGE amounts of data. * * To minimize the chances of disaster, the program does error checking * on every critical operation, and aborts if a failure occures. If this * happens fix the problem, and run CHAINSAW again. * * Copyright 1992-1995 Dave Dunfield * All rights reserved. * * Permission granted to use for personal (non-commercial) use only. * * Compile command: cc chainsaw -fop */ #include #include #define MAXDIRS 500 /* Maximum number of directories to stack */ /* Stack of directory names... + top of stack marker */ char names[MAXDIRS][13]; unsigned ndir = 0, fcount = 0, dcount = 0, rc; /* Command line switches */ char message = -1, yesno = -1, system = 0; /* File control block for delete file function */ char fcb[37] = { "\000???????????" }; /* Register holders for int86() function */ extern int _AX_, _DX_; /* * Main program... parse arguments, ask permission, and KILL! KILL! KILL! */ main(int argc, char *argv[]) { int i; char buffer[25], directory[68], old_dir[68], *ptr, flag; /* Record our current position */ old_dir[0] = get_drive() + 'A'; old_dir[1] = ':'; old_dir[2] = '\\'; getdir(&old_dir[3]); /* If argument is passed, parse directory */ for(flag=i=1; i < argc; ++i) { ptr = argv[i]; switch((toupper(*ptr) << 8) | toupper(*(ptr+1))) { case '/Q' : case '-Q' : message = 0; break; case '/Y' : case '-Y' : yesno = 0; break; case '/S' : case '-S' : system = -1; break; default: if(flag) { if(*((ptr = argv[1])+1) == ':') { set_drive(toupper(*ptr) - 'A'); ptr += 2; } if(cd(ptr)) abort("Unable to access directory"); break; } case '/?' : case '?' << 8 : abort("Use: CHAINSAW [directory] [/Quiet /System /Yes]"); } } if(message) printf("CHAINSAW by Dave Dunfield\n"); /* Prompt with selected directory, and make sure he really wants to do it */ directory[0] = get_drive() + 'A'; directory[1] = ':'; directory[2] = '\\'; getdir(&directory[3]); if(yesno) { printf("Delete tree below %s (ARE YOU SURE)?", directory); fgets(buffer, sizeof(buffer)-1, stdin); } /* If he really wants to.... kill off everything */ if((!yesno) || (toupper(*buffer) == 'Y')) { kill_tree(); /* Kill files & subdirs */ if(!cd("..")) /* Up to parent */ dcount += !rmdir(directory); } /* Kill base directory */ /* Try and restore our former directory position */ set_drive(old_dir[0] - 'A'); cd(old_dir); if(message) printf("\nRemoved %u files and %u directories.\n", fcount, dcount); } /* * Kill all files in current directory, and then recursively call * self to exterminate any sub-directories. */ kill_tree() { int j, attr, n; char name[65]; /* If no files or sub-directories... do nothing */ if(find_first("*.*", HIDDEN|SYSTEM|DIRECTORY, name, &j, &j, &attr, &j, &j)) return; /* Search and record sub-directories, insure all files delete-able */ n = ndir; do { if(attr & DIRECTORY) { if(strcmp(name,".") && strcmp(name,"..")) strcpy(names[ndir++], name); } else { if((attr & (SYSTEM|READONLY)) && system) { if(rc = set_attr(name, 0)) { printf("Can't set attributes of file: %s (%d)\n", name, rc); exit(-1); } } ++fcount; } } while(!find_next(name, &j, &j, &attr, &j, &j)); /* Using FCB's, delete all files in this directory */ _AX_ = 0x1300; _DX_ = fcb; int86(0x21); /* Kill off sub-directories */ while(ndir > n) { if(rc = cd(names[ndir-1])) { printf("Can't enter subdirectory: %s (%d)\n", names[ndir-1], rc); exit(-1); } kill_tree(); if(rc = cd("..")) { printf("Can't access next higher directory. (%d)\n", rc); exit(-1); } if(rc = rmdir(names[--ndir])) { printf("Can't remove subdirectory: %s (%d)\n", names[ndir], rc); exit(-1); } ++dcount; } }