1 /* 2 * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank 3 * Copyright (c) 1995 Martin Husemann 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 27 #include <sys/cdefs.h> 28 #ifndef lint 29 __RCSID("$NetBSD: fat.c,v 1.12 2000/10/10 20:24:52 is Exp $"); 30 static const char rcsid[] = 31 "$FreeBSD$"; 32 #endif /* not lint */ 33 34 #include <stdlib.h> 35 #include <string.h> 36 #include <ctype.h> 37 #include <stdio.h> 38 #include <unistd.h> 39 40 #include "ext.h" 41 #include "fsutil.h" 42 43 static int checkclnum(struct bootblock *, u_int, cl_t, cl_t *); 44 static int clustdiffer(cl_t, cl_t *, cl_t *, u_int); 45 static int tryclear(struct bootblock *, struct fatEntry *, cl_t, cl_t *); 46 static int _readfat(int, struct bootblock *, u_int, u_char **); 47 48 /*- 49 * The first 2 FAT entries contain pseudo-cluster numbers with the following 50 * layout: 51 * 52 * 31...... ........ ........ .......0 53 * rrrr1111 11111111 11111111 mmmmmmmm FAT32 entry 0 54 * rrrrsh11 11111111 11111111 11111xxx FAT32 entry 1 55 * 56 * 11111111 mmmmmmmm FAT16 entry 0 57 * sh111111 11111xxx FAT16 entry 1 58 * 59 * r = reserved 60 * m = BPB media ID byte 61 * s = clean flag (1 = dismounted; 0 = still mounted) 62 * h = hard error flag (1 = ok; 0 = I/O error) 63 * x = any value ok 64 */ 65 66 int 67 checkdirty(int fs, struct bootblock *boot) 68 { 69 off_t off; 70 u_char *buffer; 71 int ret = 0; 72 73 if (boot->ClustMask != CLUST16_MASK && boot->ClustMask != CLUST32_MASK) 74 return 0; 75 76 off = boot->bpbResSectors; 77 off *= boot->bpbBytesPerSec; 78 79 buffer = malloc(boot->bpbBytesPerSec); 80 if (buffer == NULL) { 81 perror("No space for FAT"); 82 return 1; 83 } 84 85 if (lseek(fs, off, SEEK_SET) != off) { 86 perror("Unable to read FAT"); 87 goto err; 88 } 89 90 if (read(fs, buffer, boot->bpbBytesPerSec) != boot->bpbBytesPerSec) { 91 perror("Unable to read FAT"); 92 goto err; 93 } 94 95 /* 96 * If we don't understand the FAT, then the file system must be 97 * assumed to be unclean. 98 */ 99 if (buffer[0] != boot->bpbMedia || buffer[1] != 0xff) 100 goto err; 101 if (boot->ClustMask == CLUST16_MASK) { 102 if ((buffer[2] & 0xf8) != 0xf8 || (buffer[3] & 0x3f) != 0x3f) 103 goto err; 104 } else { 105 if (buffer[2] != 0xff || (buffer[3] & 0x0f) != 0x0f 106 || (buffer[4] & 0xf8) != 0xf8 || buffer[5] != 0xff 107 || buffer[6] != 0xff || (buffer[7] & 0x03) != 0x03) 108 goto err; 109 } 110 111 /* 112 * Now check the actual clean flag (and the no-error flag). 113 */ 114 if (boot->ClustMask == CLUST16_MASK) { 115 if ((buffer[3] & 0xc0) == 0xc0) 116 ret = 1; 117 } else { 118 if ((buffer[7] & 0x0c) == 0x0c) 119 ret = 1; 120 } 121 122 err: 123 free(buffer); 124 return ret; 125 } 126 127 /* 128 * Check a cluster number for valid value 129 */ 130 static int 131 checkclnum(struct bootblock *boot, u_int fat, cl_t cl, cl_t *next) 132 { 133 if (*next >= (CLUST_RSRVD&boot->ClustMask)) 134 *next |= ~boot->ClustMask; 135 if (*next == CLUST_FREE) { 136 boot->NumFree++; 137 return FSOK; 138 } 139 if (*next == CLUST_BAD) { 140 boot->NumBad++; 141 return FSOK; 142 } 143 if (*next < CLUST_FIRST 144 || (*next >= boot->NumClusters && *next < CLUST_EOFS)) { 145 pwarn("Cluster %u in FAT %d continues with %s cluster number %u\n", 146 cl, fat, 147 *next < CLUST_RSRVD ? "out of range" : "reserved", 148 *next&boot->ClustMask); 149 if (ask(0, "Truncate")) { 150 *next = CLUST_EOF; 151 return FSFATMOD; 152 } 153 return FSERROR; 154 } 155 return FSOK; 156 } 157 158 /* 159 * Read a FAT from disk. Returns 1 if successful, 0 otherwise. 160 */ 161 static int 162 _readfat(int fs, struct bootblock *boot, u_int no, u_char **buffer) 163 { 164 off_t off; 165 166 *buffer = malloc(boot->FATsecs * boot->bpbBytesPerSec); 167 if (*buffer == NULL) { 168 perror("No space for FAT"); 169 return 0; 170 } 171 172 off = boot->bpbResSectors + no * boot->FATsecs; 173 off *= boot->bpbBytesPerSec; 174 175 if (lseek(fs, off, SEEK_SET) != off) { 176 perror("Unable to read FAT"); 177 goto err; 178 } 179 180 if ((size_t)read(fs, *buffer, boot->FATsecs * boot->bpbBytesPerSec) 181 != boot->FATsecs * boot->bpbBytesPerSec) { 182 perror("Unable to read FAT"); 183 goto err; 184 } 185 186 return 1; 187 188 err: 189 free(*buffer); 190 return 0; 191 } 192 193 /* 194 * Read a FAT and decode it into internal format 195 */ 196 int 197 readfat(int fs, struct bootblock *boot, u_int no, struct fatEntry **fp) 198 { 199 struct fatEntry *fat; 200 u_char *buffer, *p; 201 cl_t cl; 202 int ret = FSOK; 203 size_t len; 204 205 boot->NumFree = boot->NumBad = 0; 206 207 if (!_readfat(fs, boot, no, &buffer)) 208 return FSFATAL; 209 210 fat = malloc(len = boot->NumClusters * sizeof(struct fatEntry)); 211 if (fat == NULL) { 212 perror("No space for FAT"); 213 free(buffer); 214 return FSFATAL; 215 } 216 (void)memset(fat, 0, len); 217 218 if (buffer[0] != boot->bpbMedia 219 || buffer[1] != 0xff || buffer[2] != 0xff 220 || (boot->ClustMask == CLUST16_MASK && buffer[3] != 0xff) 221 || (boot->ClustMask == CLUST32_MASK 222 && ((buffer[3]&0x0f) != 0x0f 223 || buffer[4] != 0xff || buffer[5] != 0xff 224 || buffer[6] != 0xff || (buffer[7]&0x0f) != 0x0f))) { 225 226 /* Windows 95 OSR2 (and possibly any later) changes 227 * the FAT signature to 0xXXffff7f for FAT16 and to 228 * 0xXXffff0fffffff07 for FAT32 upon boot, to know that the 229 * file system is dirty if it doesn't reboot cleanly. 230 * Check this special condition before errorring out. 231 */ 232 if (buffer[0] == boot->bpbMedia && buffer[1] == 0xff 233 && buffer[2] == 0xff 234 && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) 235 || (boot->ClustMask == CLUST32_MASK 236 && buffer[3] == 0x0f && buffer[4] == 0xff 237 && buffer[5] == 0xff && buffer[6] == 0xff 238 && buffer[7] == 0x07))) 239 ret |= FSDIRTY; 240 else { 241 /* just some odd byte sequence in FAT */ 242 243 switch (boot->ClustMask) { 244 case CLUST32_MASK: 245 pwarn("%s (%02x%02x%02x%02x%02x%02x%02x%02x)\n", 246 "FAT starts with odd byte sequence", 247 buffer[0], buffer[1], buffer[2], buffer[3], 248 buffer[4], buffer[5], buffer[6], buffer[7]); 249 break; 250 case CLUST16_MASK: 251 pwarn("%s (%02x%02x%02x%02x)\n", 252 "FAT starts with odd byte sequence", 253 buffer[0], buffer[1], buffer[2], buffer[3]); 254 break; 255 default: 256 pwarn("%s (%02x%02x%02x)\n", 257 "FAT starts with odd byte sequence", 258 buffer[0], buffer[1], buffer[2]); 259 break; 260 } 261 262 263 if (ask(1, "Correct")) 264 ret |= FSFIXFAT; 265 } 266 } 267 switch (boot->ClustMask) { 268 case CLUST32_MASK: 269 p = buffer + 8; 270 break; 271 case CLUST16_MASK: 272 p = buffer + 4; 273 break; 274 default: 275 p = buffer + 3; 276 break; 277 } 278 for (cl = CLUST_FIRST; cl < boot->NumClusters;) { 279 switch (boot->ClustMask) { 280 case CLUST32_MASK: 281 fat[cl].next = p[0] + (p[1] << 8) 282 + (p[2] << 16) + (p[3] << 24); 283 fat[cl].next &= boot->ClustMask; 284 ret |= checkclnum(boot, no, cl, &fat[cl].next); 285 cl++; 286 p += 4; 287 break; 288 case CLUST16_MASK: 289 fat[cl].next = p[0] + (p[1] << 8); 290 ret |= checkclnum(boot, no, cl, &fat[cl].next); 291 cl++; 292 p += 2; 293 break; 294 default: 295 fat[cl].next = (p[0] + (p[1] << 8)) & 0x0fff; 296 ret |= checkclnum(boot, no, cl, &fat[cl].next); 297 cl++; 298 if (cl >= boot->NumClusters) 299 break; 300 fat[cl].next = ((p[1] >> 4) + (p[2] << 4)) & 0x0fff; 301 ret |= checkclnum(boot, no, cl, &fat[cl].next); 302 cl++; 303 p += 3; 304 break; 305 } 306 } 307 308 free(buffer); 309 if (ret & FSFATAL) { 310 free(fat); 311 *fp = NULL; 312 } else 313 *fp = fat; 314 return ret; 315 } 316 317 /* 318 * Get type of reserved cluster 319 */ 320 char * 321 rsrvdcltype(cl_t cl) 322 { 323 if (cl == CLUST_FREE) 324 return "free"; 325 if (cl < CLUST_BAD) 326 return "reserved"; 327 if (cl > CLUST_BAD) 328 return "as EOF"; 329 return "bad"; 330 } 331 332 static int 333 clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, u_int fatnum) 334 { 335 if (*cp1 == CLUST_FREE || *cp1 >= CLUST_RSRVD) { 336 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 337 if ((*cp1 != CLUST_FREE && *cp1 < CLUST_BAD 338 && *cp2 != CLUST_FREE && *cp2 < CLUST_BAD) 339 || (*cp1 > CLUST_BAD && *cp2 > CLUST_BAD)) { 340 pwarn("Cluster %u is marked %s with different indicators\n", 341 cl, rsrvdcltype(*cp1)); 342 if (ask(1, "Fix")) { 343 *cp2 = *cp1; 344 return FSFATMOD; 345 } 346 return FSFATAL; 347 } 348 pwarn("Cluster %u is marked %s in FAT 0, %s in FAT %u\n", 349 cl, rsrvdcltype(*cp1), rsrvdcltype(*cp2), fatnum); 350 if (ask(0, "Use FAT 0's entry")) { 351 *cp2 = *cp1; 352 return FSFATMOD; 353 } 354 if (ask(0, "Use FAT %u's entry", fatnum)) { 355 *cp1 = *cp2; 356 return FSFATMOD; 357 } 358 return FSFATAL; 359 } 360 pwarn("Cluster %u is marked %s in FAT 0, but continues with cluster %u in FAT %d\n", 361 cl, rsrvdcltype(*cp1), *cp2, fatnum); 362 if (ask(0, "Use continuation from FAT %u", fatnum)) { 363 *cp1 = *cp2; 364 return FSFATMOD; 365 } 366 if (ask(0, "Use mark from FAT 0")) { 367 *cp2 = *cp1; 368 return FSFATMOD; 369 } 370 return FSFATAL; 371 } 372 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 373 pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %u\n", 374 cl, *cp1, rsrvdcltype(*cp2), fatnum); 375 if (ask(0, "Use continuation from FAT 0")) { 376 *cp2 = *cp1; 377 return FSFATMOD; 378 } 379 if (ask(0, "Use mark from FAT %d", fatnum)) { 380 *cp1 = *cp2; 381 return FSFATMOD; 382 } 383 return FSERROR; 384 } 385 pwarn("Cluster %u continues with cluster %u in FAT 0, but with cluster %u in FAT %u\n", 386 cl, *cp1, *cp2, fatnum); 387 if (ask(0, "Use continuation from FAT 0")) { 388 *cp2 = *cp1; 389 return FSFATMOD; 390 } 391 if (ask(0, "Use continuation from FAT %u", fatnum)) { 392 *cp1 = *cp2; 393 return FSFATMOD; 394 } 395 return FSERROR; 396 } 397 398 /* 399 * Compare two FAT copies in memory. Resolve any conflicts and merge them 400 * into the first one. 401 */ 402 int 403 comparefat(struct bootblock *boot, struct fatEntry *first, 404 struct fatEntry *second, u_int fatnum) 405 { 406 cl_t cl; 407 int ret = FSOK; 408 409 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) 410 if (first[cl].next != second[cl].next) 411 ret |= clustdiffer(cl, &first[cl].next, &second[cl].next, fatnum); 412 return ret; 413 } 414 415 void 416 clearchain(struct bootblock *boot, struct fatEntry *fat, cl_t head) 417 { 418 cl_t p, q; 419 420 for (p = head; p >= CLUST_FIRST && p < boot->NumClusters; p = q) { 421 if (fat[p].head != head) 422 break; 423 q = fat[p].next; 424 fat[p].next = fat[p].head = CLUST_FREE; 425 fat[p].length = 0; 426 } 427 } 428 429 int 430 tryclear(struct bootblock *boot, struct fatEntry *fat, cl_t head, cl_t *trunc) 431 { 432 if (ask(0, "Clear chain starting at %u", head)) { 433 clearchain(boot, fat, head); 434 return FSFATMOD; 435 } else if (ask(0, "Truncate")) { 436 *trunc = CLUST_EOF; 437 return FSFATMOD; 438 } else 439 return FSERROR; 440 } 441 442 /* 443 * Check a complete FAT in-memory for crosslinks 444 */ 445 int 446 checkfat(struct bootblock *boot, struct fatEntry *fat) 447 { 448 cl_t head, p, h, n; 449 u_int len; 450 int ret = 0; 451 int conf; 452 453 /* 454 * pass 1: figure out the cluster chains. 455 */ 456 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 457 /* find next untravelled chain */ 458 if (fat[head].head != 0 /* cluster already belongs to some chain */ 459 || fat[head].next == CLUST_FREE 460 || fat[head].next == CLUST_BAD) 461 continue; /* skip it. */ 462 463 /* follow the chain and mark all clusters on the way */ 464 for (len = 0, p = head; 465 p >= CLUST_FIRST && p < boot->NumClusters; 466 p = fat[p].next) { 467 fat[p].head = head; 468 len++; 469 } 470 471 /* the head record gets the length */ 472 fat[head].length = fat[head].next == CLUST_FREE ? 0 : len; 473 } 474 475 /* 476 * pass 2: check for crosslinked chains (we couldn't do this in pass 1 because 477 * we didn't know the real start of the chain then - would have treated partial 478 * chains as interlinked with their main chain) 479 */ 480 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 481 /* find next untravelled chain */ 482 if (fat[head].head != head) 483 continue; 484 485 /* follow the chain to its end (hopefully) */ 486 for (p = head; 487 (n = fat[p].next) >= CLUST_FIRST && n < boot->NumClusters; 488 p = n) 489 if (fat[n].head != head) 490 break; 491 if (n >= CLUST_EOFS) 492 continue; 493 494 if (n == CLUST_FREE || n >= CLUST_RSRVD) { 495 pwarn("Cluster chain starting at %u ends with cluster marked %s\n", 496 head, rsrvdcltype(n)); 497 ret |= tryclear(boot, fat, head, &fat[p].next); 498 continue; 499 } 500 if (n < CLUST_FIRST || n >= boot->NumClusters) { 501 pwarn("Cluster chain starting at %u ends with cluster out of range (%u)\n", 502 head, n); 503 ret |= tryclear(boot, fat, head, &fat[p].next); 504 continue; 505 } 506 pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n", 507 head, fat[n].head, n); 508 conf = tryclear(boot, fat, head, &fat[p].next); 509 if (ask(0, "Clear chain starting at %u", h = fat[n].head)) { 510 if (conf == FSERROR) { 511 /* 512 * Transfer the common chain to the one not cleared above. 513 */ 514 for (p = n; 515 p >= CLUST_FIRST && p < boot->NumClusters; 516 p = fat[p].next) { 517 if (h != fat[p].head) { 518 /* 519 * Have to reexamine this chain. 520 */ 521 head--; 522 break; 523 } 524 fat[p].head = head; 525 } 526 } 527 clearchain(boot, fat, h); 528 conf |= FSFATMOD; 529 } 530 ret |= conf; 531 } 532 533 return ret; 534 } 535 536 /* 537 * Write out FATs encoding them from the internal format 538 */ 539 int 540 writefat(int fs, struct bootblock *boot, struct fatEntry *fat, int correct_fat) 541 { 542 u_char *buffer, *p; 543 cl_t cl; 544 u_int i; 545 size_t fatsz; 546 off_t off; 547 int ret = FSOK; 548 549 buffer = malloc(fatsz = boot->FATsecs * boot->bpbBytesPerSec); 550 if (buffer == NULL) { 551 perror("No space for FAT"); 552 return FSFATAL; 553 } 554 memset(buffer, 0, fatsz); 555 boot->NumFree = 0; 556 p = buffer; 557 if (correct_fat) { 558 *p++ = (u_char)boot->bpbMedia; 559 *p++ = 0xff; 560 *p++ = 0xff; 561 switch (boot->ClustMask) { 562 case CLUST16_MASK: 563 *p++ = 0xff; 564 break; 565 case CLUST32_MASK: 566 *p++ = 0x0f; 567 *p++ = 0xff; 568 *p++ = 0xff; 569 *p++ = 0xff; 570 *p++ = 0x0f; 571 break; 572 } 573 } else { 574 /* use same FAT signature as the old FAT has */ 575 int count; 576 u_char *old_fat; 577 578 switch (boot->ClustMask) { 579 case CLUST32_MASK: 580 count = 8; 581 break; 582 case CLUST16_MASK: 583 count = 4; 584 break; 585 default: 586 count = 3; 587 break; 588 } 589 590 if (!_readfat(fs, boot, boot->ValidFat >= 0 ? boot->ValidFat :0, 591 &old_fat)) { 592 free(buffer); 593 return FSFATAL; 594 } 595 596 memcpy(p, old_fat, count); 597 free(old_fat); 598 p += count; 599 } 600 601 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) { 602 switch (boot->ClustMask) { 603 case CLUST32_MASK: 604 if (fat[cl].next == CLUST_FREE) 605 boot->NumFree++; 606 *p++ = (u_char)fat[cl].next; 607 *p++ = (u_char)(fat[cl].next >> 8); 608 *p++ = (u_char)(fat[cl].next >> 16); 609 *p &= 0xf0; 610 *p++ |= (fat[cl].next >> 24)&0x0f; 611 break; 612 case CLUST16_MASK: 613 if (fat[cl].next == CLUST_FREE) 614 boot->NumFree++; 615 *p++ = (u_char)fat[cl].next; 616 *p++ = (u_char)(fat[cl].next >> 8); 617 break; 618 default: 619 if (fat[cl].next == CLUST_FREE) 620 boot->NumFree++; 621 if (cl + 1 < boot->NumClusters 622 && fat[cl + 1].next == CLUST_FREE) 623 boot->NumFree++; 624 *p++ = (u_char)fat[cl].next; 625 *p++ = (u_char)((fat[cl].next >> 8) & 0xf) 626 |(u_char)(fat[cl+1].next << 4); 627 *p++ = (u_char)(fat[++cl].next >> 4); 628 break; 629 } 630 } 631 for (i = 0; i < boot->bpbFATs; i++) { 632 off = boot->bpbResSectors + i * boot->FATsecs; 633 off *= boot->bpbBytesPerSec; 634 if (lseek(fs, off, SEEK_SET) != off 635 || (size_t)write(fs, buffer, fatsz) != fatsz) { 636 perror("Unable to write FAT"); 637 ret = FSFATAL; /* Return immediately? XXX */ 638 } 639 } 640 free(buffer); 641 return ret; 642 } 643 644 /* 645 * Check a complete in-memory FAT for lost cluster chains 646 */ 647 int 648 checklost(int dosfs, struct bootblock *boot, struct fatEntry *fat) 649 { 650 cl_t head; 651 int mod = FSOK; 652 int ret; 653 654 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 655 /* find next untravelled chain */ 656 if (fat[head].head != head 657 || fat[head].next == CLUST_FREE 658 || (fat[head].next >= CLUST_RSRVD 659 && fat[head].next < CLUST_EOFS) 660 || (fat[head].flags & FAT_USED)) 661 continue; 662 663 pwarn("Lost cluster chain at cluster %u\n%d Cluster(s) lost\n", 664 head, fat[head].length); 665 mod |= ret = reconnect(dosfs, boot, fat, head); 666 if (mod & FSFATAL) 667 break; 668 if (ret == FSERROR && ask(0, "Clear")) { 669 clearchain(boot, fat, head); 670 mod |= FSFATMOD; 671 } 672 } 673 finishlf(); 674 675 if (boot->bpbFSInfo) { 676 ret = 0; 677 if (boot->FSFree != boot->NumFree) { 678 pwarn("Free space in FSInfo block (%d) not correct (%d)\n", 679 boot->FSFree, boot->NumFree); 680 if (ask(1, "Fix")) { 681 boot->FSFree = boot->NumFree; 682 ret = 1; 683 } 684 } 685 if (ret) 686 mod |= writefsinfo(dosfs, boot); 687 } 688 689 return mod; 690 } 691