home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / diskutil / mtools / mrd.c < prev    next >
C/C++ Source or Header  |  1993-08-05  |  4KB  |  186 lines

  1. /*
  2.  * Delete an MSDOS subdirectory
  3.  *
  4.  * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  5.  * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  6.  * fthood!egray@uxc.cso.uiuc.edu    Directorate of Engineering & Housing
  7.  *                     Environmental Management Office
  8.  *                     Fort Hood, TX 76544-5057
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <signal.h>
  13. #include "msdos.h"
  14. #include "patchlevel.h"
  15.  
  16. int fd = -1;                /* the file descriptor for the device */
  17. int dir_start;                /* starting sector for directory */
  18. int dir_len;                /* length of directory (in sectors) */
  19. int dir_entries;            /* number of directory entries */
  20. int clus_size;                /* cluster size (in sectors) */
  21. char *mcwd;                /* the Current Working Directory */
  22. int fat_error;                /* FAT error detected? */
  23.  
  24. static int got_signal(), is_empty();
  25.  
  26. main(argc, argv)
  27. int argc;
  28. char *argv[];
  29. {
  30.     int i, ismatch, entry, oops, empty;
  31.     unsigned int start;
  32.     char *filename, *newfile, *get_name(), drive, *pathname, *get_path();
  33.     char *unix_name(), get_drive(), last_drive, *fix_mcwd();
  34.     void exit(), fat_write(), dir_write(), disk_flush(), dir_flush();
  35.     struct directory *dir, *dir_read();
  36.                     /* catch signals */
  37.     signal(SIGINT, (SIG_TYPE(*) ()) got_signal);
  38.     signal(SIGTERM, (SIG_TYPE(*) ()) got_signal);
  39.     signal(SIGQUIT, (SIG_TYPE(*) ()) got_signal);
  40.  
  41.     if (argc == 1) {
  42.         fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
  43.         fprintf(stderr, "Usage: %s mdsosdirectory [msdosdirectories...]\n", argv[0]);
  44.         exit(1);
  45.     }
  46.  
  47.     last_drive = 'x';
  48.     mcwd = fix_mcwd();
  49.  
  50.     for (i = 1; i < argc; i++) {
  51.         drive = get_drive(argv[i]);
  52.         if (drive != last_drive) {
  53.             if (last_drive != 'x') {
  54.                 fat_write();
  55.                 dir_flush();
  56.                 disk_flush();
  57.             }
  58.  
  59.             if (init(drive, 2)) {
  60.                 fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
  61.                 continue;
  62.             }
  63.             last_drive = drive;
  64.         }
  65.  
  66.         filename = get_name(argv[i]);
  67.         pathname = get_path(argv[i]);
  68.         if (subdir(drive, pathname))
  69.             continue;
  70.  
  71.         oops = 0;
  72.         ismatch = 0;
  73.         for (entry = 0; entry < dir_entries; entry++) {
  74.             dir = dir_read(entry);
  75.                     /* if empty */
  76.             if (dir->name[0] == 0x0)
  77.                 break;
  78.                     /* if erased */
  79.             if (dir->name[0] == 0xe5)
  80.                 continue;
  81.                     /* if not dir */
  82.             if (!(dir->attr & 0x10))
  83.                 continue;
  84.  
  85.             newfile = unix_name(dir->name, dir->ext);
  86.             if (match(newfile, filename)) {
  87.                 start = dir->start[1] * 0x100 + dir->start[0];
  88.                 if ((empty = is_empty(start)) < 0)
  89.                     break;
  90.                 if (!empty) {
  91.                     fprintf(stderr, "%s: Directory \"%s\" is not empty\n", argv[0], filename);
  92.                     oops++;
  93.                     break;
  94.                 }
  95.                 if (!start) {
  96.                     fprintf(stderr, "%s: Can't remove root directory\n", argv[0]);
  97.                     oops++;
  98.                     break;
  99.                 }
  100.                 if (fat_free(start))
  101.                     break;
  102.                 dir->name[0] = 0xe5;
  103.                 dir_write(entry, dir);
  104.                 ismatch = 1;
  105.             }
  106.         }
  107.         if (fat_error)
  108.             break;
  109.  
  110.         if (oops)
  111.             continue;
  112.  
  113.         if (!ismatch)
  114.             fprintf(stderr, "%s: Directory \"%s\" not found\n", argv[0], filename);
  115.     }
  116.                     /* write the FAT, flush the buffers */
  117.     fat_write();
  118.     dir_flush();
  119.     disk_flush();
  120.     close(fd);
  121.     exit(0);
  122. }
  123.  
  124. /*
  125.  * See if directory is empty.  Returns 1 if empty, 0 if not, and -1 on error.
  126.  * Can't use subdir() and dir_read() as it would clobber the globals.
  127.  */
  128.  
  129. static int
  130. is_empty(fat)
  131. unsigned int fat;
  132. {
  133.     register int i;
  134.     int next, buflen;
  135.     long sector;
  136.     extern unsigned int last_fat, fat_decode();
  137.     unsigned char tbuf[MAX_CLUSTER];
  138.     void disk_read();
  139.  
  140.     /* CONSTCOND */
  141.     while (1) {
  142.         sector = (long) (fat - 2) * clus_size + dir_start + dir_len;
  143.         buflen = clus_size * MSECTOR_SIZE;
  144.         disk_read(sector, tbuf, buflen);
  145.  
  146.                     /* check first character of name */
  147.         for (i = 0; i < MSECTOR_SIZE; i += MDIR_SIZE) {
  148.             if (tbuf[i] == '.')
  149.                 continue;
  150.             if (tbuf[i] != 0x0 && tbuf[i] != 0xe5)
  151.                 return(0);
  152.         }
  153.                     /* get next cluster number */
  154.         next = fat_decode(fat);
  155.         if (next == 1) {
  156.             fprintf(stderr, "is_empty: FAT problem\n");
  157.             return(-1);
  158.         }
  159.                     /* end of cluster chain */
  160.         if (next >= last_fat)
  161.             break;
  162.         fat = next;
  163.     }
  164.     return(1);
  165. }
  166.  
  167. /*
  168.  * Do a graceful exit if the program is interrupted.  This will reduce
  169.  * (but not eliminate) the risk of generating a corrupted disk on
  170.  * a user abort.
  171.  */
  172.  
  173. static int
  174. got_signal()
  175. {
  176.     void exit(), disk_flush(), fat_write(), dir_flush();
  177.  
  178.     if (fd < 0)
  179.         exit(1);
  180.     fat_write();
  181.     dir_flush();
  182.     disk_flush();
  183.     close(fd);
  184.     exit(1);
  185. }
  186.