[3ae31e9] | 1 | /*
|
---|
| 2 | =============================================================================
|
---|
| 3 | fsck.c -- Atari ST file system checker
|
---|
| 4 | Written by: D.N. Lynx Crowe
|
---|
| 5 |
|
---|
| 6 | See VERMSG (below) for version information.
|
---|
| 7 |
|
---|
| 8 | This version checks files in the root directory on floppy drive A only.
|
---|
| 9 | =============================================================================
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | #define PROGID "fsck"
|
---|
| 13 | #define VERMSG "1.8 -- 1988-03-25"
|
---|
| 14 |
|
---|
| 15 | #include "stddefs.h"
|
---|
| 16 | #include "stdio.h"
|
---|
| 17 | #include "osbind.h"
|
---|
| 18 | #include "ctype.h"
|
---|
| 19 | #include "strings.h"
|
---|
| 20 | #include "bpb.h"
|
---|
| 21 | #include "dirent.h"
|
---|
| 22 | #include "bootsec.h"
|
---|
| 23 |
|
---|
| 24 | #define MAXSECLN 512 /* maximum sector length */
|
---|
| 25 |
|
---|
| 26 | #define PERLINE 16 /* bytes per line for mdump */
|
---|
| 27 | #define MAXCLINE 10 /* number of clusters per line */
|
---|
| 28 | #define FNLEN 13 /* file name buffer length */
|
---|
| 29 |
|
---|
| 30 | #define MAXFATSZ 9 /* maximum FAT size */
|
---|
| 31 | #define MAXRDSZ 14 /* maximum root directory size */
|
---|
| 32 |
|
---|
| 33 | #define MAXFATLN (MAXSECLN * MAXFATSZ)
|
---|
| 34 | #define MAXRDLN (MAXSECLN * MAXRDSZ)
|
---|
| 35 |
|
---|
| 36 | #define MAXFATNM (MAXFATLN / 2)
|
---|
| 37 |
|
---|
| 38 | /* |
---|
| 39 |
|
---|
| 40 | */
|
---|
| 41 | char fat1[MAXFATLN]; /* FAT 1 image */
|
---|
| 42 | char fat2[MAXFATLN]; /* FAT 2 image */
|
---|
| 43 | char rdir[MAXRDLN]; /* root directory image */
|
---|
| 44 |
|
---|
| 45 | short bsec[MAXSECLN / 2]; /* boot sector image */
|
---|
| 46 |
|
---|
| 47 | short drive; /* drive number */
|
---|
| 48 | short rdsize; /* number of root directory entries */
|
---|
| 49 | short cltype; /* FAT entry type - 0 = 12, 1 = 16 */
|
---|
| 50 |
|
---|
| 51 | long fatlen; /* length of FAT in bytes */
|
---|
| 52 |
|
---|
| 53 | BOOL errflag; /* error flag */
|
---|
| 54 | BOOL quiet; /* quiet flag */
|
---|
| 55 | BOOL verbose; /* verbose flag */
|
---|
| 56 | BOOL errdump; /* dump on errors flag */
|
---|
| 57 | BOOL clslist; /* list clusters */
|
---|
| 58 | BOOL bscdump; /* dump boot sector */
|
---|
| 59 | BOOL dirlist; /* list directory entries */
|
---|
| 60 |
|
---|
| 61 | short fatmap[MAXFATNM]; /* FAT check map */
|
---|
| 62 |
|
---|
| 63 | unsigned fat1loc; /* starting sector of FAT 1 */
|
---|
| 64 | unsigned fat2loc; /* starting sector of FAT 2 */
|
---|
| 65 | unsigned rdloc; /* starting sector of root directory */
|
---|
| 66 | unsigned datloc; /* starting sector of data */
|
---|
| 67 | unsigned eofclus; /* cluster value limit for EOF */
|
---|
| 68 | unsigned badclus; /* cluster value limit for errors */
|
---|
| 69 |
|
---|
| 70 | struct BPB bpb; /* copy of BPB for the drive */
|
---|
| 71 |
|
---|
| 72 | /* |
---|
| 73 |
|
---|
| 74 | */
|
---|
| 75 |
|
---|
| 76 | /*
|
---|
| 77 | =============================================================================
|
---|
| 78 | pipc() -- print if printable characters
|
---|
| 79 | =============================================================================
|
---|
| 80 | */
|
---|
| 81 |
|
---|
| 82 | static
|
---|
| 83 | pipc(chars, length)
|
---|
| 84 | char chars[];
|
---|
| 85 | int length;
|
---|
| 86 | {
|
---|
| 87 | int i;
|
---|
| 88 |
|
---|
| 89 | for (i = 0; i < length; i++)
|
---|
| 90 | if (isascii(0x00FF & chars[i]) AND (isprint(0x00FF & chars[i])))
|
---|
| 91 | printf("%c", chars[i]);
|
---|
| 92 | else
|
---|
| 93 | printf(".");
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | /* |
---|
| 97 |
|
---|
| 98 | */
|
---|
| 99 |
|
---|
| 100 | /*
|
---|
| 101 | =============================================================================
|
---|
| 102 | mdump() -- dump a memory area in hexadecimal
|
---|
| 103 | =============================================================================
|
---|
| 104 | */
|
---|
| 105 |
|
---|
| 106 | mdump(begin, end, start)
|
---|
| 107 | char *begin, *end;
|
---|
| 108 | long start;
|
---|
| 109 | {
|
---|
| 110 | long i, ii;
|
---|
| 111 | int j, jj, k;
|
---|
| 112 | char c, chars[PERLINE];
|
---|
| 113 |
|
---|
| 114 | i = 0L;
|
---|
| 115 | ii = start;
|
---|
| 116 | j = 0;
|
---|
| 117 |
|
---|
| 118 | if (begin GT end)
|
---|
| 119 | return;
|
---|
| 120 |
|
---|
| 121 | while (begin LE end) {
|
---|
| 122 |
|
---|
| 123 | c = *begin++;
|
---|
| 124 |
|
---|
| 125 | if (! (i % PERLINE)) {
|
---|
| 126 |
|
---|
| 127 | if (i) {
|
---|
| 128 |
|
---|
| 129 | j=0;
|
---|
| 130 | printf(" ");
|
---|
| 131 | pipc(chars, PERLINE);
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | printf("\n%08.8lx:", ii);
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | ii++;
|
---|
| 138 | i++;
|
---|
| 139 | printf(" %02.2x", (c & 0x00FF));
|
---|
| 140 | chars[j++] = c;
|
---|
| 141 | }
|
---|
| 142 |
|
---|
| 143 | if (k = (i % PERLINE)) {
|
---|
| 144 |
|
---|
| 145 | k = PERLINE - k;
|
---|
| 146 |
|
---|
| 147 | for (jj = 0; jj < (3 * k); ++jj)
|
---|
| 148 | printf(" ");
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | printf(" ");
|
---|
| 152 | pipc(chars, PERLINE);
|
---|
| 153 | printf("\n");
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | /* |
---|
| 157 |
|
---|
| 158 | */
|
---|
| 159 |
|
---|
| 160 | /*
|
---|
| 161 | =============================================================================
|
---|
| 162 | getiwd() -- get an Intel byte reversed word
|
---|
| 163 | =============================================================================
|
---|
| 164 | */
|
---|
| 165 |
|
---|
| 166 | unsigned
|
---|
| 167 | getiwd(wp)
|
---|
| 168 | register char wp[];
|
---|
| 169 | {
|
---|
| 170 | register unsigned val;
|
---|
| 171 |
|
---|
| 172 | val = ((wp[1] & 0x00FF) << 8) | (wp[0] & 0x00FF);
|
---|
| 173 | return(val);
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | /*
|
---|
| 177 | =============================================================================
|
---|
| 178 | trim() -- trim trailing blanks from a string
|
---|
| 179 | =============================================================================
|
---|
| 180 | */
|
---|
| 181 |
|
---|
| 182 | char *
|
---|
| 183 | trim(s)
|
---|
| 184 | register char *s;
|
---|
| 185 | {
|
---|
| 186 | register char *sp;
|
---|
| 187 |
|
---|
| 188 | if (*s EQ '\0') /* handle empty string */
|
---|
| 189 | return(s);
|
---|
| 190 |
|
---|
| 191 | sp = s;
|
---|
| 192 |
|
---|
| 193 | while (*sp) /* find end of string */
|
---|
| 194 | ++sp;
|
---|
| 195 |
|
---|
| 196 | while (' ' EQ *--sp) {
|
---|
| 197 |
|
---|
| 198 | *sp = '\0';
|
---|
| 199 |
|
---|
| 200 | if (sp EQ s)
|
---|
| 201 | break;
|
---|
| 202 | }
|
---|
| 203 |
|
---|
| 204 | return(s);
|
---|
| 205 | }
|
---|
| 206 |
|
---|
| 207 | /* |
---|
| 208 |
|
---|
| 209 | */
|
---|
| 210 |
|
---|
| 211 | /*
|
---|
| 212 | =============================================================================
|
---|
| 213 | fileid() -- get a file identifier from a directory entry
|
---|
| 214 | =============================================================================
|
---|
| 215 | */
|
---|
| 216 |
|
---|
| 217 | char *
|
---|
| 218 | fileid(dir, buf)
|
---|
| 219 | struct Dirent *dir;
|
---|
| 220 | char *buf;
|
---|
| 221 | {
|
---|
| 222 | memset(buf, 0, 13);
|
---|
| 223 | strncat(buf, dir->name, 8);
|
---|
| 224 | trim(buf);
|
---|
| 225 |
|
---|
| 226 | if (strncmp(dir->ext, " ", 3)) {
|
---|
| 227 |
|
---|
| 228 | strcat(buf, ".");
|
---|
| 229 | strncat(buf, dir->ext, 3);
|
---|
| 230 | trim(buf);
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | return(buf);
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 |
|
---|
| 237 | /* |
---|
| 238 |
|
---|
| 239 | */
|
---|
| 240 |
|
---|
| 241 | /*
|
---|
| 242 | =============================================================================
|
---|
| 243 | _gtcl12(fat, cl) -- return 12 bit cluster entry 'cl' from FAT pointed
|
---|
| 244 | to by 'fat'
|
---|
| 245 | =============================================================================
|
---|
| 246 | */
|
---|
| 247 |
|
---|
| 248 | unsigned
|
---|
| 249 | _gtcl12(fat, cl)
|
---|
| 250 | register char *fat;
|
---|
| 251 | unsigned cl;
|
---|
| 252 | {
|
---|
| 253 | register unsigned cla, clt;
|
---|
| 254 |
|
---|
| 255 | cla = cl + (cl >> 1);
|
---|
| 256 | clt = ((unsigned)0xFF00 & (fat[cla+1] << 8))
|
---|
| 257 | | ((unsigned)0x00FF & fat[cla]);
|
---|
| 258 |
|
---|
| 259 | if (cl & 1)
|
---|
| 260 | clt >>= 4;
|
---|
| 261 |
|
---|
| 262 | clt &= (unsigned)0x0FFF;
|
---|
| 263 | return(clt);
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | /*
|
---|
| 267 | =============================================================================
|
---|
| 268 | getcl() -- get a FAT entry
|
---|
| 269 | =============================================================================
|
---|
| 270 | */
|
---|
| 271 |
|
---|
| 272 | unsigned
|
---|
| 273 | getcl(fp, ncl, ft)
|
---|
| 274 | char *fp;
|
---|
| 275 | unsigned ncl;
|
---|
| 276 | short ft;
|
---|
| 277 | {
|
---|
| 278 | if (ft)
|
---|
| 279 | return(getiwd(fp[ncl << 1]));
|
---|
| 280 | else
|
---|
| 281 | return(_gtcl12(fp, ncl));
|
---|
| 282 | }
|
---|
| 283 |
|
---|
| 284 | /* |
---|
| 285 |
|
---|
| 286 | */
|
---|
| 287 |
|
---|
| 288 | /*
|
---|
| 289 | =============================================================================
|
---|
| 290 | ckdir() -- check a directory entry
|
---|
| 291 | =============================================================================
|
---|
| 292 | */
|
---|
| 293 |
|
---|
| 294 | BOOL
|
---|
| 295 | ckdir(fat, dir, ent)
|
---|
| 296 | char *fat;
|
---|
| 297 | struct Dirent *dir;
|
---|
| 298 | short ent;
|
---|
| 299 | {
|
---|
| 300 | unsigned dirclus;
|
---|
| 301 | unsigned curclus;
|
---|
| 302 | short cln;
|
---|
| 303 | BOOL ok;
|
---|
| 304 | char fn1[FNLEN];
|
---|
| 305 | char fn2[FNLEN];
|
---|
| 306 |
|
---|
| 307 | if ((dir[ent].name[0] & 0x00FF) EQ 0x00E5)
|
---|
| 308 | return(FALSE);
|
---|
| 309 |
|
---|
| 310 | if ((dir[ent].name[0] & 0x00FF) EQ 0)
|
---|
| 311 | return(TRUE);
|
---|
| 312 |
|
---|
| 313 | if (verbose OR clslist OR dirlist) {
|
---|
| 314 |
|
---|
| 315 | printf(" Checking entry %d: \"%s\"",
|
---|
| 316 | ent, fileid(&dir[ent], fn1));
|
---|
| 317 |
|
---|
| 318 | if (dir[ent].atrib & F_VOLUME) {
|
---|
| 319 |
|
---|
| 320 | printf(" -- Volume label\n");
|
---|
| 321 | return(FALSE);
|
---|
| 322 |
|
---|
| 323 | } else {
|
---|
| 324 |
|
---|
| 325 | printf(" -- Flags: ");
|
---|
| 326 |
|
---|
| 327 | printf("%c", dir[ent].atrib & F_ARCHIV ? 'A' : '.');
|
---|
| 328 | printf("%c", dir[ent].atrib & F_SUBDIR ? 'D' : '.');
|
---|
| 329 | printf("%c", dir[ent].atrib & F_SYSTEM ? 'S' : '.');
|
---|
| 330 | printf("%c", dir[ent].atrib & F_HIDDEN ? 'H' : '.');
|
---|
| 331 | printf("%c", dir[ent].atrib & F_RDONLY ? 'R' : '.');
|
---|
| 332 |
|
---|
| 333 | printf("\n");
|
---|
| 334 | }
|
---|
| 335 | }
|
---|
| 336 | /* |
---|
| 337 |
|
---|
| 338 | */
|
---|
| 339 | dirclus = getiwd(dir[ent].clus);
|
---|
| 340 |
|
---|
| 341 | if (fatmap[dirclus] NE -1) {
|
---|
| 342 |
|
---|
| 343 | printf("ERROR: Overlapping allocations --\n");
|
---|
| 344 | printf(" %s overlaps %s at cluster %u\n\n",
|
---|
| 345 | fileid(&dir[ent], fn1),
|
---|
| 346 | fileid(&dir[fatmap[dirclus]], fn2),
|
---|
| 347 | dirclus);
|
---|
| 348 |
|
---|
| 349 | errflag = TRUE;
|
---|
| 350 | return(FALSE);
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | if (clslist)
|
---|
| 354 | printf(" allocated clusters:\n ");
|
---|
| 355 |
|
---|
| 356 | cln = 0;
|
---|
| 357 | ok = TRUE;
|
---|
| 358 |
|
---|
| 359 | while (ok) {
|
---|
| 360 |
|
---|
| 361 | fatmap[dirclus] = ent;
|
---|
| 362 |
|
---|
| 363 | if (clslist) {
|
---|
| 364 |
|
---|
| 365 | if (cln EQ MAXCLINE) {
|
---|
| 366 |
|
---|
| 367 | printf("\n ");
|
---|
| 368 | cln = 0;
|
---|
| 369 | }
|
---|
| 370 |
|
---|
| 371 | ++cln;
|
---|
| 372 | printf(" %5u", dirclus);
|
---|
| 373 | }
|
---|
| 374 |
|
---|
| 375 | curclus = getcl(fat, dirclus, cltype);
|
---|
| 376 | /* |
---|
| 377 |
|
---|
| 378 | */
|
---|
| 379 | if (curclus LT 2) {
|
---|
| 380 |
|
---|
| 381 | printf("ERROR: Bad FAT entry ($%x) at %u ($%x)",
|
---|
| 382 | curclus, dirclus, dirclus);
|
---|
| 383 |
|
---|
| 384 | printf(" for file \"%s\"\n", fileid(&dir[ent], fn1));
|
---|
| 385 | errflag = TRUE;
|
---|
| 386 | ok = FALSE;
|
---|
| 387 |
|
---|
| 388 | } else if (curclus LT badclus) {
|
---|
| 389 |
|
---|
| 390 | if (fatmap[curclus] NE -1) {
|
---|
| 391 |
|
---|
| 392 | printf("ERROR: Overlapping allocations --\n");
|
---|
| 393 | printf(" \"%s\" overlaps \"%s\" at cluster %u\n\n",
|
---|
| 394 | fileid(&dir[ent], fn1),
|
---|
| 395 | fileid(&dir[fatmap[dirclus]], fn2),
|
---|
| 396 | dirclus);
|
---|
| 397 |
|
---|
| 398 | errflag = TRUE;
|
---|
| 399 | return(FALSE);
|
---|
| 400 | }
|
---|
| 401 |
|
---|
| 402 | dirclus = curclus;
|
---|
| 403 |
|
---|
| 404 | } else if (curclus LT eofclus) {
|
---|
| 405 |
|
---|
| 406 | printf("ERROR: Bad FAT entry ($%x) at %u ($%x)",
|
---|
| 407 | curclus, dirclus, dirclus);
|
---|
| 408 |
|
---|
| 409 | printf(" for file \"%s\"\n", fileid(&dir[ent], fn1));
|
---|
| 410 | errflag = TRUE;
|
---|
| 411 | ok = FALSE;
|
---|
| 412 |
|
---|
| 413 | } else {
|
---|
| 414 |
|
---|
| 415 | if (clslist AND cln)
|
---|
| 416 | printf("\n");
|
---|
| 417 |
|
---|
| 418 | ok = FALSE;
|
---|
| 419 | }
|
---|
| 420 | }
|
---|
| 421 |
|
---|
| 422 | return(FALSE);
|
---|
| 423 | }
|
---|
| 424 |
|
---|
| 425 | /* |
---|
| 426 |
|
---|
| 427 | */
|
---|
| 428 |
|
---|
| 429 | /*
|
---|
| 430 | =============================================================================
|
---|
| 431 | main() -- main driver function for fsck.c
|
---|
| 432 | =============================================================================
|
---|
| 433 | */
|
---|
| 434 |
|
---|
| 435 | main(argc, argv)
|
---|
| 436 | short argc;
|
---|
| 437 | char *argv[];
|
---|
| 438 | {
|
---|
| 439 | char *bpp;
|
---|
| 440 | char *ap;
|
---|
| 441 | short c;
|
---|
| 442 | long rc;
|
---|
| 443 | register long i;
|
---|
| 444 | register short j;
|
---|
| 445 | register struct BootSec *bsp;
|
---|
| 446 |
|
---|
| 447 | /* setup miscellaneous variables and defaults */
|
---|
| 448 |
|
---|
| 449 | drive = 0; /* drive A */
|
---|
| 450 | cltype = 0; /* 12 bit FAT entries */
|
---|
| 451 | eofclus = 0x0FF8; /* EOF cluster limit */
|
---|
| 452 | badclus = 0x0FF0; /* bad cluster limit */
|
---|
| 453 |
|
---|
| 454 | quiet = FALSE; /* log all activity */
|
---|
| 455 | verbose = FALSE; /* log details */
|
---|
| 456 | errdump = FALSE; /* dump on errors */
|
---|
| 457 | clslist = FALSE; /* list cluster allocations */
|
---|
| 458 | bscdump = FALSE; /* dump boot sector */
|
---|
| 459 | dirlist = FALSE; /* list directory entries */
|
---|
| 460 | /* |
---|
| 461 |
|
---|
| 462 | */
|
---|
| 463 | /* parse command line */
|
---|
| 464 |
|
---|
| 465 | if (argc > 1) {
|
---|
| 466 |
|
---|
| 467 | ap = argv[1];
|
---|
| 468 |
|
---|
| 469 | while (c = 0x00FF & *ap++) {
|
---|
| 470 |
|
---|
| 471 | c = tolower(c);
|
---|
| 472 |
|
---|
| 473 | switch (c) {
|
---|
| 474 |
|
---|
| 475 | case 'a': /* set options b, c, d, e, v */
|
---|
| 476 |
|
---|
| 477 | bscdump = TRUE; /* b option */
|
---|
| 478 | clslist = TRUE; /* c option */
|
---|
| 479 | dirlist = TRUE; /* d option */
|
---|
| 480 | errdump = TRUE; /* e option */
|
---|
| 481 | verbose = TRUE; /* v option */
|
---|
| 482 | break;
|
---|
| 483 |
|
---|
| 484 | case 'b': /* dump boot sector */
|
---|
| 485 |
|
---|
| 486 | bscdump = TRUE;
|
---|
| 487 | break;
|
---|
| 488 |
|
---|
| 489 | case 'c': /* list clusters */
|
---|
| 490 |
|
---|
| 491 | clslist = TRUE;
|
---|
| 492 | break;
|
---|
| 493 |
|
---|
| 494 | case 'd': /* list directory entries */
|
---|
| 495 |
|
---|
| 496 | dirlist = TRUE;
|
---|
| 497 | break;
|
---|
| 498 |
|
---|
| 499 | case 'e': /* dump on errors */
|
---|
| 500 |
|
---|
| 501 | errdump = TRUE;
|
---|
| 502 | break;
|
---|
| 503 | /* |
---|
| 504 |
|
---|
| 505 | */
|
---|
| 506 | case 'q': /* quiet mode */
|
---|
| 507 |
|
---|
| 508 | quiet = TRUE;
|
---|
| 509 | break;
|
---|
| 510 |
|
---|
| 511 | case 'v': /* verbose mode */
|
---|
| 512 |
|
---|
| 513 | verbose = TRUE;
|
---|
| 514 | break;
|
---|
| 515 |
|
---|
| 516 | default: /* invalid option */
|
---|
| 517 |
|
---|
| 518 | printf("%s: ERROR - invalid option \"%c\" [$%02.2x]\n\n",
|
---|
| 519 | PROGID, c, c);
|
---|
| 520 |
|
---|
| 521 | printf("usage: %s [abcdeqv]\n", PROGID);
|
---|
| 522 | printf(" a set options b, c, d, e, v\n");
|
---|
| 523 | printf(" b dump boot sector\n");
|
---|
| 524 | printf(" c list cluster allocations\n");
|
---|
| 525 | printf(" d list directory entries\n");
|
---|
| 526 | printf(" e dump FATS and DIR on errors\n");
|
---|
| 527 | printf(" q quiet mode\n");
|
---|
| 528 | printf(" v verbose mode\n");
|
---|
| 529 | exit(1);
|
---|
| 530 | }
|
---|
| 531 | }
|
---|
| 532 | }
|
---|
| 533 | /* |
---|
| 534 |
|
---|
| 535 | */
|
---|
| 536 | errflag = FALSE; /* reset the error flag */
|
---|
| 537 |
|
---|
| 538 | /* identify the program */
|
---|
| 539 |
|
---|
| 540 | if (NOT quiet)
|
---|
| 541 | printf("\n%s for the Atari ST -- Version %s\n\n",
|
---|
| 542 | PROGID, VERMSG);
|
---|
| 543 |
|
---|
| 544 | if (verbose)
|
---|
| 545 | printf("Reading boot sector ...\n");
|
---|
| 546 |
|
---|
| 547 | if (rc = Floprd(bsec, 0L, drive, 1, 0, 0, 1)) {
|
---|
| 548 |
|
---|
| 549 | printf("ERROR -- Unable to read boot sector\n");
|
---|
| 550 | exit(1);
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 | if (verbose)
|
---|
| 554 | printf("Boot sector read OK\n");
|
---|
| 555 |
|
---|
| 556 | bsp = (struct BootSec *)bsec;
|
---|
| 557 |
|
---|
| 558 | if (bscdump) {
|
---|
| 559 |
|
---|
| 560 | printf("\nBoot sector contents --\n\n");
|
---|
| 561 |
|
---|
| 562 | printf(" Branch word = $%02.2x $%02.2x\n",
|
---|
| 563 | bsp->branch[0], bsp->branch[1]);
|
---|
| 564 |
|
---|
| 565 | printf(" OEM area =");
|
---|
| 566 |
|
---|
| 567 | for (j = 0; j < 6; j++)
|
---|
| 568 | printf(" $%02.2x", bsp->oem[j]);
|
---|
| 569 |
|
---|
| 570 | printf("\n Volume S/N =");
|
---|
| 571 |
|
---|
| 572 | for (j = 0; j < 3; j++)
|
---|
| 573 | printf(" $%02.2x", bsp->vsn[j]);
|
---|
| 574 |
|
---|
| 575 | printf("\n Bytes / Sector = %u\n", getiwd(bsp->bps));
|
---|
| 576 | printf(" Sectors / Cluster = %u\n", bsp->spc);
|
---|
| 577 | printf(" Reserved sectors = %u\n", getiwd(bsp->res));
|
---|
| 578 | printf(" Number of FATS = %u\n", bsp->nfats);
|
---|
| 579 | printf(" Directory entries = %u\n", getiwd(bsp->ndirs));
|
---|
| 580 | printf(" Total Sectors = %u\n", getiwd(bsp->nsects));
|
---|
| 581 | printf(" Media byte = $%02.2x\n", bsp->media);
|
---|
| 582 | printf(" Sectors / FAT = %u\n", getiwd(bsp->spf));
|
---|
| 583 | printf(" Sectors / Track = %u\n", getiwd(bsp->spt));
|
---|
| 584 | printf(" Sides = %u\n", getiwd(bsp->nsides));
|
---|
| 585 | printf(" Hidden files = %u\n", getiwd(bsp->nhid));
|
---|
| 586 | printf(" Checksum = $%04.4x\n", getiwd(bsp->cksum));
|
---|
| 587 |
|
---|
| 588 | printf("\nBoot record data area --\n\n");
|
---|
| 589 | mdump(bsp->boot, &bsp->boot[479], 0L);
|
---|
| 590 | printf("\n");
|
---|
| 591 | }
|
---|
| 592 | /* |
---|
| 593 |
|
---|
| 594 | */
|
---|
| 595 | /* get the BPB */
|
---|
| 596 |
|
---|
| 597 | if (bpp = (char *)Getbpb(drive)) {
|
---|
| 598 |
|
---|
| 599 | memcpy(&bpb, bpp, sizeof (struct BPB));
|
---|
| 600 |
|
---|
| 601 | } else {
|
---|
| 602 |
|
---|
| 603 | printf("ERROR: Unable to get BPB for drive");
|
---|
| 604 | exit(1);
|
---|
| 605 | }
|
---|
| 606 |
|
---|
| 607 | /* determine where things live, etc. */
|
---|
| 608 |
|
---|
| 609 | fat2loc = bpb.fatrec;
|
---|
| 610 | fat1loc = bpb.fatrec - bpb.fsiz;
|
---|
| 611 | rdloc = bpb.fatrec + bpb.fsiz;
|
---|
| 612 | datloc = bpb.fatrec + bpb.fsiz + bpb.rdlen;
|
---|
| 613 | rdsize = (bpb.recsiz * bpb.rdlen) / sizeof (struct Dirent);
|
---|
| 614 | fatlen = bpb.fsiz * bpb.recsiz;
|
---|
| 615 |
|
---|
| 616 | /* check BPB values for consistency */
|
---|
| 617 |
|
---|
| 618 | if (verbose)
|
---|
| 619 | printf("Checking BPB for consistency ...\n");
|
---|
| 620 |
|
---|
| 621 | if (datloc NE bpb.datrec) {
|
---|
| 622 |
|
---|
| 623 | printf("ERROR: Data locations inconsistent:\n");
|
---|
| 624 | printf(" BPB value: %u\n", bpb.datrec);
|
---|
| 625 | printf(" Calculated: %u\n", datloc);
|
---|
| 626 | exit(1);
|
---|
| 627 | }
|
---|
| 628 | /* |
---|
| 629 |
|
---|
| 630 | */
|
---|
| 631 | /* read FAT 1 */
|
---|
| 632 |
|
---|
| 633 | if (verbose)
|
---|
| 634 | printf("Reading FAT 1 ...\n");
|
---|
| 635 |
|
---|
| 636 | if (rc = Rwabs(0, fat1, bpb.fsiz, fat1loc, drive)) {
|
---|
| 637 |
|
---|
| 638 | printf("ERROR: Unable to read FAT 1 -- error code = %ld\n",
|
---|
| 639 | rc);
|
---|
| 640 |
|
---|
| 641 | exit(1);
|
---|
| 642 | }
|
---|
| 643 |
|
---|
| 644 | if (verbose)
|
---|
| 645 | printf("FAT 1 read OK\n");
|
---|
| 646 |
|
---|
| 647 | /* read FAT 2 */
|
---|
| 648 |
|
---|
| 649 | if (verbose)
|
---|
| 650 | printf("Reading FAT 2 ...\n");
|
---|
| 651 |
|
---|
| 652 | if (rc = Rwabs(0, fat2, bpb.fsiz, fat2loc, drive)) {
|
---|
| 653 |
|
---|
| 654 | printf("ERROR: Unable to read FAT 2 -- error code = %ld\n",
|
---|
| 655 | rc);
|
---|
| 656 |
|
---|
| 657 | exit(1);
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 | if (verbose)
|
---|
| 661 | printf("FAT 2 read OK\n");
|
---|
| 662 |
|
---|
| 663 | /* read the root directory */
|
---|
| 664 |
|
---|
| 665 | if (verbose)
|
---|
| 666 | printf("Reading root directory ...\n");
|
---|
| 667 |
|
---|
| 668 | if (rc = Rwabs(0, rdir, bpb.rdlen, rdloc, drive)) {
|
---|
| 669 |
|
---|
| 670 | printf("ERROR: Unable to read root directory -- error code = %ld\n",
|
---|
| 671 | rc);
|
---|
| 672 |
|
---|
| 673 | exit(1);
|
---|
| 674 | }
|
---|
| 675 |
|
---|
| 676 | if (verbose)
|
---|
| 677 | printf("Root directory read OK\n");
|
---|
| 678 | /* |
---|
| 679 |
|
---|
| 680 | */
|
---|
| 681 | /* compare the FATs */
|
---|
| 682 |
|
---|
| 683 | if (verbose)
|
---|
| 684 | printf("Comparing FATs ...\n");
|
---|
| 685 |
|
---|
| 686 | for (i = 0; i < fatlen; i++) {
|
---|
| 687 |
|
---|
| 688 | if (fat1[i] NE fat2[i]) {
|
---|
| 689 |
|
---|
| 690 | printf("ERROR: FATs differ at offset %lu ($%lx)\n\n",
|
---|
| 691 | i, i);
|
---|
| 692 |
|
---|
| 693 | if (errdump) {
|
---|
| 694 |
|
---|
| 695 | printf("FAT 1:\n\n");
|
---|
| 696 | mdump(fat1, fat1 + (long)(fatlen - 1), 0L);
|
---|
| 697 |
|
---|
| 698 | printf("\fFAT 2:\n\n");
|
---|
| 699 | mdump(fat2, fat2 + (long)(fatlen - 1), 0L);
|
---|
| 700 |
|
---|
| 701 | printf("\f");
|
---|
| 702 |
|
---|
| 703 | } else {
|
---|
| 704 |
|
---|
| 705 | printf("WARNING -- Primary file system damaged.\n");
|
---|
| 706 | }
|
---|
| 707 |
|
---|
| 708 | exit(1);
|
---|
| 709 | }
|
---|
| 710 | }
|
---|
| 711 |
|
---|
| 712 | if (verbose)
|
---|
| 713 | printf("FATs are consistent\n");
|
---|
| 714 |
|
---|
| 715 | /* check the root directory files */
|
---|
| 716 |
|
---|
| 717 | if (verbose | clslist)
|
---|
| 718 | printf("Checking root directory ...\n");
|
---|
| 719 |
|
---|
| 720 | memsetw(fatmap, -1, MAXFATNM);
|
---|
| 721 |
|
---|
| 722 | for (j = 0; j < rdsize; j++)
|
---|
| 723 | if (ckdir(fat1, rdir, j))
|
---|
| 724 | break;
|
---|
| 725 | /* |
---|
| 726 |
|
---|
| 727 | */
|
---|
| 728 | if (errflag)
|
---|
| 729 | if (errdump) {
|
---|
| 730 |
|
---|
| 731 | printf("\fDirectory dump:\n\n");
|
---|
| 732 | mdump(rdir,
|
---|
| 733 | rdir + (long)(sizeof (struct Dirent) * rdsize) - 1L,
|
---|
| 734 | 0L);
|
---|
| 735 |
|
---|
| 736 | printf("\fFAT dump:\n\n");
|
---|
| 737 | mdump(fat1, fat1 + (long)(fatlen - 1), 0L);
|
---|
| 738 |
|
---|
| 739 | printf("\n");
|
---|
| 740 |
|
---|
| 741 | } else {
|
---|
| 742 |
|
---|
| 743 | printf("\nWARNING -- Primary file system damaged.\n");
|
---|
| 744 | }
|
---|
| 745 |
|
---|
| 746 | if (NOT quiet)
|
---|
| 747 | printf("\nPrimary file system check complete on drive %c.\n\n",
|
---|
| 748 | drive + 'A');
|
---|
| 749 |
|
---|
| 750 | exit(errflag ? 1 : 0);
|
---|
| 751 | }
|
---|