1: /* 2: * Display an MSDOS directory 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 "msdos.h" 13: #include "patchlevel.h" 14: 15: int fd = -1; /* the file descriptor for the device */ 16: int dir_start; /* starting sector for directory */ 17: int dir_len; /* length of directory (in sectors) */ 18: int dir_entries; /* number of directory entries */ 19: int clus_size; /* cluster size (in sectors) */ 20: char *mcwd; /* the Current Working Directory */ 21: int fat_error; /* FAT error detected? */ 22: 23: static long getfree(); 24: static char *conv_date(), *conv_time(); 25: 26: main(argc, argv) 27: int argc; 28: char *argv[]; 29: { 30: int i, entry, files, fargn, wide, faked; 31: long size, blocks; 32: char *date, *time, last_drive, *fix_mcwd(); 33: char *strncpy(), newpath[MAX_PATH], *get_name(), *get_path(), *pathname; 34: char *newfile, *filename, *unix_name(), volume[12], drive, *strpbrk(); 35: char *strcpy(), *strcat(), newname[13], *strncat(), get_drive(); 36: void exit(); 37: struct directory *dir, *dir_read(); 38: 39: fargn = 1; 40: wide = 0; 41: files = 0; 42: /* first argument */ 43: if (argc > 1) { 44: if (!strcmp(argv[1], "-w")) { 45: wide = 1; 46: fargn = 2; 47: } 48: if (argv[1][0] == '-' && !wide) { 49: fprintf(stderr, "%s: illegal option -- %c\n", argv[0], argv[1][1]); 50: fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE); 51: fprintf(stderr, "Usage: %s: [-w] msdosdirectory\n", argv[0]); 52: fprintf(stderr, " %s: [-w] msdosfile [msdosfiles...]\n", argv[0]); 53: exit(1); 54: } 55: } 56: /* fake an argument */ 57: faked = 0; 58: if (argc == fargn) { 59: faked++; 60: argc++; 61: } 62: last_drive = 'x'; 63: mcwd = fix_mcwd(); 64: 65: for (i = fargn; i < argc; i++) { 66: if (faked) { 67: drive = get_drive(""); 68: filename = get_name(""); 69: pathname = get_path(""); 70: } 71: else { 72: drive = get_drive(argv[i]); 73: filename = get_name(argv[i]); 74: pathname = get_path(argv[i]); 75: } 76: /* is this a new device? */ 77: if (drive != last_drive) { 78: if (last_drive != 'x') { 79: blocks = getfree() * MSECTOR_SIZE; 80: if (!files) 81: printf("File \"%s\" not found\n\n", newname); 82: else 83: printf(" %3d File(s) %6ld bytes free\n\n", files, blocks); 84: } 85: if (init(drive, 0)) { 86: fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive); 87: continue; 88: } 89: last_drive = drive; 90: files = 0; 91: /* find the volume label */ 92: volume[0] = '\0'; 93: for (entry = 0; entry < dir_entries; entry++) { 94: dir = dir_read(entry); 95: 96: /* if empty */ 97: if (dir->name[0] == 0x0) 98: break; 99: 100: /* if erased */ 101: if (dir->name[0] == 0xe5) 102: continue; 103: 104: /* if not volume label */ 105: if (!(dir->attr & 0x08)) 106: continue; 107: 108: strncpy(volume, (char *) dir->name, 8); 109: volume[8] = '\0'; 110: strncat(volume, (char *) dir->ext, 3); 111: volume[11] = '\0'; 112: break; 113: } 114: if (volume[0] == '\0') 115: printf(" Volume in drive %c has no label\n", drive); 116: else 117: printf(" Volume in drive %c is %s\n", drive, volume); 118: } 119: 120: /* 121: * Move to "first guess" subdirectory, so that is_dir() can 122: * search to see if filename is also a directory. 123: */ 124: if (subdir(drive, pathname)) 125: continue; 126: 127: /* 128: * Under MSDOS, wildcards that match directories don't 129: * display the contents of that directory. So I guess I'll 130: * do that too. 131: */ 132: if ((strpbrk(filename, "*[?") == NULL) && is_dir(filename)) { 133: strcpy(newpath, pathname); 134: if (newpath[strlen(newpath) -1] != '/') 135: strcat(newpath, "/"); 136: strcat(newpath, filename); 137: 138: /* move to real subdirectory */ 139: if (subdir(drive, newpath)) 140: continue; 141: 142: strcpy(newname, "*"); 143: } 144: else { 145: strcpy(newpath, pathname); 146: strcpy(newname, filename); 147: } 148: /* if no files, assume '*' */ 149: if (*filename == '\0') 150: strcpy(newname, "*"); 151: 152: printf(" Directory for %c:%s\n\n", drive, newpath); 153: 154: for (entry = 0; entry < dir_entries; entry++) { 155: dir = dir_read(entry); 156: /* if empty */ 157: if (dir->name[0] == 0x0) 158: break; 159: /* if erased */ 160: if (dir->name[0] == 0xe5) 161: continue; 162: /* if a volume label */ 163: if (dir->attr & 0x08) 164: continue; 165: 166: newfile = unix_name(dir->name, dir->ext); 167: if (!match(newfile, newname)) 168: continue; 169: 170: files++; 171: if (wide && files != 1) { 172: if (!((files - 1) % 5)) 173: putchar('\n'); 174: } 175: date = conv_date(dir->date[1], dir->date[0]); 176: time = conv_time(dir->time[1], dir->time[0]); 177: size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0]; 178: /* is a subdirectory */ 179: if (dir->attr & 0x10) { 180: if (wide) 181: printf("%-8.8s %-3.3s ", dir->name, dir->ext); 182: else 183: printf("%-8.8s %-3.3s <DIR> %s %s\n", dir->name, dir->ext, date, time); 184: continue; 185: } 186: if (wide) 187: printf("%-8.8s %-3.3s ", dir->name, dir->ext); 188: else 189: printf("%-8.8s %-3.3s %8ld %s %s\n", dir->name, dir->ext, size, date, time); 190: } 191: if (argc > 2) 192: putchar('\n'); 193: } 194: if (fd < 0) 195: exit(1); 196: 197: blocks = getfree() * MSECTOR_SIZE; 198: if (!files) 199: printf("File \"%s\" not found\n", newname); 200: else 201: printf(" %3d File(s) %6ld bytes free\n", files, blocks); 202: close(fd); 203: exit(0); 204: } 205: 206: /* 207: * Get the amount of free space on the diskette 208: */ 209: 210: static long 211: getfree() 212: { 213: register unsigned int i; 214: long total; 215: extern unsigned int num_clus; 216: unsigned int fat_decode(); 217: 218: total = 0L; 219: for (i = 2; i < num_clus + 2; i++) { 220: /* if fat_decode returns zero */ 221: if (!fat_decode(i)) 222: total += clus_size; 223: } 224: return(total); 225: } 226: 227: /* 228: * Convert an MSDOS directory date stamp to ASCII 229: */ 230: 231: static char * 232: conv_date(date_high, date_low) 233: unsigned date_high, date_low; 234: { 235: /* 236: * hi byte | low byte 237: * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0| 238: * | | | | | | | | | | | | | | | | | 239: * \ 7 bits /\4 bits/\ 5 bits / 240: * year +80 month day 241: */ 242: static char ans[9]; 243: unsigned char year, month_hi, month_low, day; 244: 245: year = (date_high >> 1) + 80; 246: month_hi = (date_high & 0x1) << 3; 247: month_low = date_low >> 5; 248: day = date_low & 0x1f; 249: sprintf(ans, "%2d-%02d-%02d", month_hi + month_low, day, year); 250: return(ans); 251: } 252: 253: /* 254: * Convert an MSDOS directory time stamp to ASCII. 255: */ 256: 257: static char * 258: conv_time(time_high, time_low) 259: unsigned time_high, time_low; 260: { 261: /* 262: * hi byte | low byte 263: * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0| 264: * | | | | | | | | | | | | | | | | | 265: * \ 5 bits /\ 6 bits /\ 5 bits / 266: * hour minutes sec*2 267: */ 268: static char ans[7]; 269: char am_pm; 270: unsigned char hour, min_hi, min_low; 271: 272: hour = time_high >> 3; 273: am_pm = (hour >= 12) ? 'p' : 'a'; 274: if (hour > 12) 275: hour = hour - 12; 276: if (hour == 0) 277: hour = 12; 278: min_hi = (time_high & 0x7) << 3; 279: min_low = time_low >> 5; 280: sprintf(ans, "%2d:%02d%c", hour, min_hi + min_low, am_pm); 281: return(ans); 282: } 283: 284: /* 285: * stubs for read-only programs 286: */ 287: 288: void 289: disk_flush() 290: { 291: extern int disk_dirty; 292: 293: disk_dirty = 0; 294: return; 295: } 296: 297: void 298: dir_flush() 299: { 300: extern int dir_dirty; 301: 302: dir_dirty = 0; 303: return; 304: }