1: /* 2: * Make 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(); 25: static void empty_dir(); 26: 27: main(argc, argv) 28: int argc; 29: char *argv[]; 30: { 31: int i, entry, slot, fargn, verbose, oops; 32: extern unsigned int end_fat; 33: unsigned int fat, dot, next_fat(); 34: char filename[13], *newfile, drive, get_drive(), *get_path(); 35: char *strcpy(), *fix_mcwd(), *pathname, *unix_name(), last_drive; 36: unsigned char *fixed, *dos_name(); 37: void exit(), fat_write(), dir_write(), disk_flush(), dir_flush(); 38: struct directory *dir, *dir_read(), *mk_entry(); 39: long time(), now; 40: /* catch signals */ 41: signal(SIGINT, (SIG_TYPE(*) ()) got_signal); 42: signal(SIGTERM, (SIG_TYPE(*) ()) got_signal); 43: signal(SIGQUIT, (SIG_TYPE(*) ()) got_signal); 44: 45: fargn = 1; 46: verbose = 0; 47: oops = 0; 48: if (argc > 1) { 49: if (!strcmp(argv[1], "-v")) { 50: fargn = 2; 51: verbose = 1; 52: } 53: if (argv[1][0] == '-' && !verbose) 54: oops++; 55: } 56: if (argc == 1 || oops) { 57: fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE); 58: fprintf(stderr, "Usage: %s [-v] msdosdirectory [msdosdirectories...]\n", argv[0]); 59: exit(1); 60: } 61: last_drive = 'x'; 62: mcwd = fix_mcwd(); 63: 64: for (i = fargn; i < argc; i++) { 65: drive = get_drive(argv[i]); 66: if (drive != last_drive) { 67: if (last_drive != 'x') { 68: fat_write(); 69: dir_flush(); 70: disk_flush(); 71: } 72: 73: if (init(drive, 2)) { 74: fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive); 75: continue; 76: } 77: last_drive = drive; 78: } 79: /* serves the get_name() function too */ 80: fixed = dos_name(argv[i], verbose); 81: 82: strcpy(filename, unix_name(fixed, fixed + 8)); 83: pathname = get_path(argv[i]); 84: 85: if (subdir(drive, pathname)) 86: continue; 87: /* see if exists and get slot */ 88: slot = -1; 89: dot = 0; 90: oops = 0; 91: for (entry = 0; entry < dir_entries; entry++) { 92: dir = dir_read(entry); 93: 94: /* if empty */ 95: if (dir->name[0] == 0x0) { 96: if (slot < 0) 97: slot = entry; 98: break; 99: } 100: /* if erased */ 101: if (dir->name[0] == 0xe5) { 102: if (slot < 0) 103: slot = entry; 104: continue; 105: } 106: /* if not a directory */ 107: if (!(dir->attr & 0x10)) 108: continue; 109: 110: newfile = unix_name(dir->name, dir->ext); 111: /* save the 'dot' directory info */ 112: if (!strcmp(".", newfile)) 113: dot = dir->start[1] * 0x100 + dir->start[0]; 114: 115: if (!strcmp(filename, newfile)) { 116: fprintf(stderr, "%s: Directory \"%s\" already exists\n", argv[0], filename); 117: oops++; 118: break; 119: } 120: } 121: if (oops) 122: continue; 123: /* no '.' entry means root directory */ 124: if (dot == 0 && slot < 0) { 125: fprintf(stderr, "%s: No directory slots\n", argv[0]); 126: continue; 127: } 128: /* make the directory grow */ 129: if (dot && slot < 0) { 130: if (dir_grow(dot)) { 131: fprintf(stderr, "%s: Disk full\n", argv[0]); 132: continue; 133: } 134: /* first slot in the new part */ 135: slot = entry; 136: } 137: /* grab a starting cluster */ 138: if ((fat = next_fat(0)) == 1) { 139: fprintf(stderr, "%s: Disk full\n", argv[0]); 140: continue; 141: } 142: /* make directory entry */ 143: time(&now); 144: dir = mk_entry(fixed, 0x10, fat, 0L, now); 145: dir_write(slot, dir); 146: /* write the cluster */ 147: empty_dir(fat, dot); 148: fat_encode(fat, end_fat); 149: } 150: /* write the FAT, flush the buffers */ 151: fat_write(); 152: dir_flush(); 153: disk_flush(); 154: close(fd); 155: exit(0); 156: } 157: 158: /* 159: * Write an empty directory 'template' to the cluster starting at 'dot'. 160: */ 161: 162: static void 163: empty_dir(dot, dot_dot) 164: unsigned int dot, dot_dot; 165: { 166: int buflen; 167: long start; 168: char buf[MAX_CLUSTER], *memcpy(), *memset(); 169: struct directory *dir, *mk_entry(); 170: void disk_write(); 171: long time(), now; 172: 173: start = (long) (dot - 2) * clus_size + dir_start + dir_len; 174: 175: buflen = clus_size * MSECTOR_SIZE; 176: time(&now); 177: /* make the '.' and '..' entries */ 178: dir = mk_entry((unsigned char *) ". ", 0x10, dot, 0L, now); 179: memcpy(&buf[0], (char *) dir, MDIR_SIZE); 180: dir = mk_entry((unsigned char *) ".. ", 0x10, dot_dot, 0L, now); 181: memcpy(&buf[MDIR_SIZE], (char *) dir, MDIR_SIZE); 182: 183: /* zero the remainder */ 184: memset(&buf[2 * MDIR_SIZE], '\0', buflen - (2 * MDIR_SIZE)); 185: 186: /* write the cluster */ 187: disk_write(start, (unsigned char *) buf, buflen); 188: return; 189: } 190: 191: /* 192: * Do a graceful exit if the program is interrupted. This will reduce 193: * (but not eliminate) the risk of generating a corrupted disk on 194: * a user abort. 195: */ 196: 197: static int 198: got_signal() 199: { 200: void exit(), disk_flush(), fat_write(), dir_flush(); 201: 202: if (fd < 0) 203: exit(1); 204: fat_write(); 205: dir_flush(); 206: disk_flush(); 207: close(fd); 208: exit(1); 209: }