55int 56checkdirty(int fs, struct bootblock *boot) 57{ 58 off_t off; 59 u_char *buffer; 60 int ret = 0; 61 62 if (boot->ClustMask == CLUST12_MASK) 63 return 0; 64 65 off = boot->ResSectors; 66 off *= boot->BytesPerSec; 67 68 buffer = malloc(boot->BytesPerSec); 69 if (buffer == NULL) { 70 perror("No space for FAT"); 71 return 1; 72 } 73 74 if (lseek(fs, off, SEEK_SET) != off) { 75 perror("Unable to read FAT"); 76 goto err; 77 } 78 79 if (read(fs, buffer, boot->BytesPerSec) != boot->BytesPerSec) { 80 perror("Unable to read FAT"); 81 goto err; 82 } 83 84 if (buffer[0] == boot->Media && buffer[1] == 0xff && buffer[2] == 0xff 85 && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) 86 || (boot->ClustMask == CLUST32_MASK && buffer[3] == 0x0f 87 && buffer[4] == 0xff && buffer[5] == 0xff 88 && buffer[6] == 0xff && buffer[7] == 0x07))) 89 ret = 0; 90 else 91 ret = 1; 92 93err: 94 free(buffer); 95 return ret; 96} 97 98/* 99 * Check a cluster number for valid value 100 */ 101static int 102checkclnum(struct bootblock *boot, int fat, cl_t cl, cl_t *next) 103{ 104 if (*next >= (CLUST_RSRVD&boot->ClustMask)) 105 *next |= ~boot->ClustMask; 106 if (*next == CLUST_FREE) { 107 boot->NumFree++; 108 return FSOK; 109 } 110 if (*next == CLUST_BAD) { 111 boot->NumBad++; 112 return FSOK; 113 } 114 if (*next < CLUST_FIRST 115 || (*next >= boot->NumClusters && *next < CLUST_EOFS)) { 116 pwarn("Cluster %u in FAT %d continues with %s cluster number %u\n", 117 cl, fat, 118 *next < CLUST_RSRVD ? "out of range" : "reserved", 119 *next&boot->ClustMask); 120 if (ask(0, "Truncate")) { 121 *next = CLUST_EOF; 122 return FSFATMOD; 123 } 124 return FSERROR; 125 } 126 return FSOK; 127} 128 129/* 130 * Read a FAT from disk. Returns 1 if successful, 0 otherwise. 131 */ 132static int 133_readfat(int fs, struct bootblock *boot, int no, u_char **buffer) 134{ 135 off_t off; 136 137 *buffer = malloc(boot->FATsecs * boot->BytesPerSec); 138 if (*buffer == NULL) { 139 perror("No space for FAT"); 140 return 0; 141 } 142 143 off = boot->ResSectors + no * boot->FATsecs; 144 off *= boot->BytesPerSec; 145 146 if (lseek(fs, off, SEEK_SET) != off) { 147 perror("Unable to read FAT"); 148 goto err; 149 } 150 151 if (read(fs, *buffer, boot->FATsecs * boot->BytesPerSec) 152 != boot->FATsecs * boot->BytesPerSec) { 153 perror("Unable to read FAT"); 154 goto err; 155 } 156 157 return 1; 158 159 err: 160 free(*buffer); 161 return 0; 162} 163 164/* 165 * Read a FAT and decode it into internal format 166 */ 167int 168readfat(int fs, struct bootblock *boot, int no, struct fatEntry **fp) 169{ 170 struct fatEntry *fat; 171 u_char *buffer, *p; 172 cl_t cl; 173 int ret = FSOK; 174 175 boot->NumFree = boot->NumBad = 0; 176 177 if (!_readfat(fs, boot, no, &buffer)) 178 return FSFATAL; 179 180 fat = calloc(boot->NumClusters, sizeof(struct fatEntry)); 181 if (fat == NULL) { 182 perror("No space for FAT"); 183 free(buffer); 184 return FSFATAL; 185 } 186 187 if (buffer[0] != boot->Media 188 || buffer[1] != 0xff || buffer[2] != 0xff 189 || (boot->ClustMask == CLUST16_MASK && buffer[3] != 0xff) 190 || (boot->ClustMask == CLUST32_MASK 191 && ((buffer[3]&0x0f) != 0x0f 192 || buffer[4] != 0xff || buffer[5] != 0xff 193 || buffer[6] != 0xff || (buffer[7]&0x0f) != 0x0f))) { 194 195 /* Windows 95 OSR2 (and possibly any later) changes 196 * the FAT signature to 0xXXffff7f for FAT16 and to 197 * 0xXXffff0fffffff07 for FAT32 upon boot, to know that the 198 * file system is dirty if it doesn't reboot cleanly. 199 * Check this special condition before errorring out. 200 */ 201 if (buffer[0] == boot->Media && buffer[1] == 0xff 202 && buffer[2] == 0xff 203 && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) 204 || (boot->ClustMask == CLUST32_MASK 205 && buffer[3] == 0x0f && buffer[4] == 0xff 206 && buffer[5] == 0xff && buffer[6] == 0xff 207 && buffer[7] == 0x07))) 208 ret |= FSDIRTY; 209 else { 210 /* just some odd byte sequence in FAT */ 211 212 switch (boot->ClustMask) { 213 case CLUST32_MASK: 214 pwarn("%s (%02x%02x%02x%02x%02x%02x%02x%02x)\n", 215 "FAT starts with odd byte sequence", 216 buffer[0], buffer[1], buffer[2], buffer[3], 217 buffer[4], buffer[5], buffer[6], buffer[7]); 218 break; 219 case CLUST16_MASK: 220 pwarn("%s (%02x%02x%02x%02x)\n", 221 "FAT starts with odd byte sequence", 222 buffer[0], buffer[1], buffer[2], buffer[3]); 223 break; 224 default: 225 pwarn("%s (%02x%02x%02x)\n", 226 "FAT starts with odd byte sequence", 227 buffer[0], buffer[1], buffer[2]); 228 break; 229 } 230 231 232 if (ask(1, "Correct")) 233 ret |= FSFIXFAT; 234 } 235 } 236 switch (boot->ClustMask) { 237 case CLUST32_MASK: 238 p = buffer + 8; 239 break; 240 case CLUST16_MASK: 241 p = buffer + 4; 242 break; 243 default: 244 p = buffer + 3; 245 break; 246 } 247 for (cl = CLUST_FIRST; cl < boot->NumClusters;) { 248 switch (boot->ClustMask) { 249 case CLUST32_MASK: 250 fat[cl].next = p[0] + (p[1] << 8) 251 + (p[2] << 16) + (p[3] << 24); 252 fat[cl].next &= boot->ClustMask; 253 ret |= checkclnum(boot, no, cl, &fat[cl].next); 254 cl++; 255 p += 4; 256 break; 257 case CLUST16_MASK: 258 fat[cl].next = p[0] + (p[1] << 8); 259 ret |= checkclnum(boot, no, cl, &fat[cl].next); 260 cl++; 261 p += 2; 262 break; 263 default: 264 fat[cl].next = (p[0] + (p[1] << 8)) & 0x0fff; 265 ret |= checkclnum(boot, no, cl, &fat[cl].next); 266 cl++; 267 if (cl >= boot->NumClusters) 268 break; 269 fat[cl].next = ((p[1] >> 4) + (p[2] << 4)) & 0x0fff; 270 ret |= checkclnum(boot, no, cl, &fat[cl].next); 271 cl++; 272 p += 3; 273 break; 274 } 275 } 276 277 free(buffer); 278 *fp = fat; 279 return ret; 280} 281 282/* 283 * Get type of reserved cluster 284 */ 285char * 286rsrvdcltype(cl_t cl) 287{ 288 if (cl == CLUST_FREE) 289 return "free"; 290 if (cl < CLUST_BAD) 291 return "reserved"; 292 if (cl > CLUST_BAD) 293 return "as EOF"; 294 return "bad"; 295} 296 297static int 298clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum) 299{ 300 if (*cp1 == CLUST_FREE || *cp1 >= CLUST_RSRVD) { 301 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 302 if ((*cp1 != CLUST_FREE && *cp1 < CLUST_BAD 303 && *cp2 != CLUST_FREE && *cp2 < CLUST_BAD) 304 || (*cp1 > CLUST_BAD && *cp2 > CLUST_BAD)) { 305 pwarn("Cluster %u is marked %s with different indicators, ", 306 cl, rsrvdcltype(*cp1)); 307 if (ask(1, "fix")) { 308 *cp2 = *cp1; 309 return FSFATMOD; 310 } 311 return FSFATAL; 312 } 313 pwarn("Cluster %u is marked %s in FAT 0, %s in FAT %d\n", 314 cl, rsrvdcltype(*cp1), rsrvdcltype(*cp2), fatnum); 315 if (ask(0, "use FAT 0's entry")) { 316 *cp2 = *cp1; 317 return FSFATMOD; 318 } 319 if (ask(0, "use FAT %d's entry", fatnum)) { 320 *cp1 = *cp2; 321 return FSFATMOD; 322 } 323 return FSFATAL; 324 } 325 pwarn("Cluster %u is marked %s in FAT 0, but continues with cluster %u in FAT %d\n", 326 cl, rsrvdcltype(*cp1), *cp2, fatnum); 327 if (ask(0, "Use continuation from FAT %d", fatnum)) { 328 *cp1 = *cp2; 329 return FSFATMOD; 330 } 331 if (ask(0, "Use mark from FAT 0")) { 332 *cp2 = *cp1; 333 return FSFATMOD; 334 } 335 return FSFATAL; 336 } 337 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 338 pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %d\n", 339 cl, *cp1, rsrvdcltype(*cp2), fatnum); 340 if (ask(0, "Use continuation from FAT 0")) { 341 *cp2 = *cp1; 342 return FSFATMOD; 343 } 344 if (ask(0, "Use mark from FAT %d", fatnum)) { 345 *cp1 = *cp2; 346 return FSFATMOD; 347 } 348 return FSERROR; 349 } 350 pwarn("Cluster %u continues with cluster %u in FAT 0, but with cluster %u in FAT %d\n", 351 cl, *cp1, *cp2, fatnum); 352 if (ask(0, "Use continuation from FAT 0")) { 353 *cp2 = *cp1; 354 return FSFATMOD; 355 } 356 if (ask(0, "Use continuation from FAT %d", fatnum)) { 357 *cp1 = *cp2; 358 return FSFATMOD; 359 } 360 return FSERROR; 361} 362 363/* 364 * Compare two FAT copies in memory. Resolve any conflicts and merge them 365 * into the first one. 366 */ 367int 368comparefat(struct bootblock *boot, struct fatEntry *first, 369 struct fatEntry *second, int fatnum) 370{ 371 cl_t cl; 372 int ret = FSOK; 373 374 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) 375 if (first[cl].next != second[cl].next) 376 ret |= clustdiffer(cl, &first[cl].next, &second[cl].next, fatnum); 377 return ret; 378} 379 380void 381clearchain(struct bootblock *boot, struct fatEntry *fat, cl_t head) 382{ 383 cl_t p, q; 384 385 for (p = head; p >= CLUST_FIRST && p < boot->NumClusters; p = q) { 386 if (fat[p].head != head) 387 break; 388 q = fat[p].next; 389 fat[p].next = fat[p].head = CLUST_FREE; 390 fat[p].length = 0; 391 } 392} 393 394int 395tryclear(struct bootblock *boot, struct fatEntry *fat, cl_t head, cl_t *trunc) 396{ 397 if (ask(0, "Clear chain starting at %u", head)) { 398 clearchain(boot, fat, head); 399 return FSFATMOD; 400 } else if (ask(0, "Truncate")) { 401 *trunc = CLUST_EOF; 402 return FSFATMOD; 403 } else 404 return FSERROR; 405} 406 407/* 408 * Check a complete FAT in-memory for crosslinks 409 */ 410int 411checkfat(struct bootblock *boot, struct fatEntry *fat) 412{ 413 cl_t head, p, h, n; 414 u_int len; 415 int ret = 0; 416 int conf; 417 418 /* 419 * pass 1: figure out the cluster chains. 420 */ 421 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 422 /* find next untravelled chain */ 423 if (fat[head].head != 0 /* cluster already belongs to some chain */ 424 || fat[head].next == CLUST_FREE 425 || fat[head].next == CLUST_BAD) 426 continue; /* skip it. */ 427 428 /* follow the chain and mark all clusters on the way */ 429 for (len = 0, p = head; 430 p >= CLUST_FIRST && p < boot->NumClusters; 431 p = fat[p].next) { 432 fat[p].head = head; 433 len++; 434 } 435 436 /* the head record gets the length */ 437 fat[head].length = fat[head].next == CLUST_FREE ? 0 : len; 438 } 439 440 /* 441 * pass 2: check for crosslinked chains (we couldn't do this in pass 1 because 442 * we didn't know the real start of the chain then - would have treated partial 443 * chains as interlinked with their main chain) 444 */ 445 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 446 /* find next untravelled chain */ 447 if (fat[head].head != head) 448 continue; 449 450 /* follow the chain to its end (hopefully) */ 451 for (p = head; 452 (n = fat[p].next) >= CLUST_FIRST && n < boot->NumClusters; 453 p = n) 454 if (fat[n].head != head) 455 break; 456 if (n >= CLUST_EOFS) 457 continue; 458 459 if (n == CLUST_FREE || n >= CLUST_RSRVD) { 460 pwarn("Cluster chain starting at %u ends with cluster marked %s\n", 461 head, rsrvdcltype(n)); 462 ret |= tryclear(boot, fat, head, &fat[p].next); 463 continue; 464 } 465 if (n < CLUST_FIRST || n >= boot->NumClusters) { 466 pwarn("Cluster chain starting at %u ends with cluster out of range (%u)\n", 467 head, n); 468 ret |= tryclear(boot, fat, head, &fat[p].next); 469 continue; 470 } 471 pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n", 472 head, fat[n].head, n); 473 conf = tryclear(boot, fat, head, &fat[p].next); 474 if (ask(0, "Clear chain starting at %u", h = fat[n].head)) { 475 if (conf == FSERROR) { 476 /* 477 * Transfer the common chain to the one not cleared above. 478 */ 479 for (p = n; 480 p >= CLUST_FIRST && p < boot->NumClusters; 481 p = fat[p].next) { 482 if (h != fat[p].head) { 483 /* 484 * Have to reexamine this chain. 485 */ 486 head--; 487 break; 488 } 489 fat[p].head = head; 490 } 491 } 492 clearchain(boot, fat, h); 493 conf |= FSFATMOD; 494 } 495 ret |= conf; 496 } 497 498 return ret; 499} 500 501/* 502 * Write out FATs encoding them from the internal format 503 */ 504int 505writefat(int fs, struct bootblock *boot, struct fatEntry *fat, int correct_fat) 506{ 507 u_char *buffer, *p; 508 cl_t cl; 509 int i; 510 u_int32_t fatsz; 511 off_t off; 512 int ret = FSOK; 513 514 buffer = malloc(fatsz = boot->FATsecs * boot->BytesPerSec); 515 if (buffer == NULL) { 516 perror("No space for FAT"); 517 return FSFATAL; 518 } 519 memset(buffer, 0, fatsz); 520 boot->NumFree = 0; 521 p = buffer; 522 if (correct_fat) { 523 *p++ = (u_char)boot->Media; 524 *p++ = 0xff; 525 *p++ = 0xff; 526 switch (boot->ClustMask) { 527 case CLUST16_MASK: 528 *p++ = 0xff; 529 break; 530 case CLUST32_MASK: 531 *p++ = 0x0f; 532 *p++ = 0xff; 533 *p++ = 0xff; 534 *p++ = 0xff; 535 *p++ = 0x0f; 536 break; 537 } 538 } else { 539 /* use same FAT signature as the old FAT has */ 540 int count; 541 u_char *old_fat; 542 543 switch (boot->ClustMask) { 544 case CLUST32_MASK: 545 count = 8; 546 break; 547 case CLUST16_MASK: 548 count = 4; 549 break; 550 default: 551 count = 3; 552 break; 553 } 554 555 if (!_readfat(fs, boot, boot->ValidFat >= 0 ? boot->ValidFat :0, 556 &old_fat)) { 557 free(buffer); 558 return FSFATAL; 559 } 560 561 memcpy(p, old_fat, count); 562 free(old_fat); 563 p += count; 564 } 565 566 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) { 567 switch (boot->ClustMask) { 568 case CLUST32_MASK: 569 if (fat[cl].next == CLUST_FREE) 570 boot->NumFree++; 571 *p++ = (u_char)fat[cl].next; 572 *p++ = (u_char)(fat[cl].next >> 8); 573 *p++ = (u_char)(fat[cl].next >> 16); 574 *p &= 0xf0; 575 *p++ |= (fat[cl].next >> 24)&0x0f; 576 break; 577 case CLUST16_MASK: 578 if (fat[cl].next == CLUST_FREE) 579 boot->NumFree++; 580 *p++ = (u_char)fat[cl].next; 581 *p++ = (u_char)(fat[cl].next >> 8); 582 break; 583 default: 584 if (fat[cl].next == CLUST_FREE) 585 boot->NumFree++; 586 if (cl + 1 < boot->NumClusters 587 && fat[cl + 1].next == CLUST_FREE) 588 boot->NumFree++; 589 *p++ = (u_char)fat[cl].next; 590 *p++ = (u_char)((fat[cl].next >> 8) & 0xf) 591 |(u_char)(fat[cl+1].next << 4); 592 *p++ = (u_char)(fat[++cl].next >> 4); 593 break; 594 } 595 } 596 for (i = 0; i < boot->FATs; i++) { 597 off = boot->ResSectors + i * boot->FATsecs; 598 off *= boot->BytesPerSec; 599 if (lseek(fs, off, SEEK_SET) != off 600 || write(fs, buffer, fatsz) != fatsz) { 601 perror("Unable to write FAT"); 602 ret = FSFATAL; /* Return immediately? XXX */ 603 } 604 } 605 free(buffer); 606 return ret; 607} 608 609/* 610 * Check a complete in-memory FAT for lost cluster chains 611 */ 612int 613checklost(int dosfs, struct bootblock *boot, struct fatEntry *fat) 614{ 615 cl_t head; 616 int mod = FSOK; 617 int ret; 618 619 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 620 /* find next untravelled chain */ 621 if (fat[head].head != head 622 || fat[head].next == CLUST_FREE 623 || (fat[head].next >= CLUST_RSRVD 624 && fat[head].next < CLUST_EOFS) 625 || (fat[head].flags & FAT_USED)) 626 continue; 627 628 pwarn("Lost cluster chain at cluster %u\n%d Cluster(s) lost\n", 629 head, fat[head].length); 630 mod |= ret = reconnect(dosfs, boot, fat, head); 631 if (mod & FSFATAL) 632 break; 633 if (ret == FSERROR && ask(0, "Clear")) { 634 clearchain(boot, fat, head); 635 mod |= FSFATMOD; 636 } 637 } 638 finishlf(); 639 640 if (boot->FSInfo) { 641 ret = 0; 642 if (boot->FSFree != boot->NumFree) { 643 pwarn("Free space in FSInfo block (%d) not correct (%d)\n", 644 boot->FSFree, boot->NumFree); 645 if (ask(1, "fix")) { 646 boot->FSFree = boot->NumFree; 647 ret = 1; 648 } 649 } 650 if (boot->NumFree && fat[boot->FSNext].next != CLUST_FREE) { 651 pwarn("Next free cluster in FSInfo block (%u) not free\n", 652 boot->FSNext); 653 if (ask(1, "fix")) 654 for (head = CLUST_FIRST; head < boot->NumClusters; head++) 655 if (fat[head].next == CLUST_FREE) { 656 boot->FSNext = head; 657 ret = 1; 658 break; 659 } 660 } 661 if (ret) 662 mod |= writefsinfo(dosfs, boot); 663 } 664 665 return mod; 666}
| 73int 74checkdirty(int fs, struct bootblock *boot) 75{ 76 off_t off; 77 u_char *buffer; 78 int ret = 0; 79 80 if (boot->ClustMask == CLUST12_MASK) 81 return 0; 82 83 off = boot->ResSectors; 84 off *= boot->BytesPerSec; 85 86 buffer = malloc(boot->BytesPerSec); 87 if (buffer == NULL) { 88 perror("No space for FAT"); 89 return 1; 90 } 91 92 if (lseek(fs, off, SEEK_SET) != off) { 93 perror("Unable to read FAT"); 94 goto err; 95 } 96 97 if (read(fs, buffer, boot->BytesPerSec) != boot->BytesPerSec) { 98 perror("Unable to read FAT"); 99 goto err; 100 } 101 102 if (buffer[0] == boot->Media && buffer[1] == 0xff && buffer[2] == 0xff 103 && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) 104 || (boot->ClustMask == CLUST32_MASK && buffer[3] == 0x0f 105 && buffer[4] == 0xff && buffer[5] == 0xff 106 && buffer[6] == 0xff && buffer[7] == 0x07))) 107 ret = 0; 108 else 109 ret = 1; 110 111err: 112 free(buffer); 113 return ret; 114} 115 116/* 117 * Check a cluster number for valid value 118 */ 119static int 120checkclnum(struct bootblock *boot, int fat, cl_t cl, cl_t *next) 121{ 122 if (*next >= (CLUST_RSRVD&boot->ClustMask)) 123 *next |= ~boot->ClustMask; 124 if (*next == CLUST_FREE) { 125 boot->NumFree++; 126 return FSOK; 127 } 128 if (*next == CLUST_BAD) { 129 boot->NumBad++; 130 return FSOK; 131 } 132 if (*next < CLUST_FIRST 133 || (*next >= boot->NumClusters && *next < CLUST_EOFS)) { 134 pwarn("Cluster %u in FAT %d continues with %s cluster number %u\n", 135 cl, fat, 136 *next < CLUST_RSRVD ? "out of range" : "reserved", 137 *next&boot->ClustMask); 138 if (ask(0, "Truncate")) { 139 *next = CLUST_EOF; 140 return FSFATMOD; 141 } 142 return FSERROR; 143 } 144 return FSOK; 145} 146 147/* 148 * Read a FAT from disk. Returns 1 if successful, 0 otherwise. 149 */ 150static int 151_readfat(int fs, struct bootblock *boot, int no, u_char **buffer) 152{ 153 off_t off; 154 155 *buffer = malloc(boot->FATsecs * boot->BytesPerSec); 156 if (*buffer == NULL) { 157 perror("No space for FAT"); 158 return 0; 159 } 160 161 off = boot->ResSectors + no * boot->FATsecs; 162 off *= boot->BytesPerSec; 163 164 if (lseek(fs, off, SEEK_SET) != off) { 165 perror("Unable to read FAT"); 166 goto err; 167 } 168 169 if (read(fs, *buffer, boot->FATsecs * boot->BytesPerSec) 170 != boot->FATsecs * boot->BytesPerSec) { 171 perror("Unable to read FAT"); 172 goto err; 173 } 174 175 return 1; 176 177 err: 178 free(*buffer); 179 return 0; 180} 181 182/* 183 * Read a FAT and decode it into internal format 184 */ 185int 186readfat(int fs, struct bootblock *boot, int no, struct fatEntry **fp) 187{ 188 struct fatEntry *fat; 189 u_char *buffer, *p; 190 cl_t cl; 191 int ret = FSOK; 192 193 boot->NumFree = boot->NumBad = 0; 194 195 if (!_readfat(fs, boot, no, &buffer)) 196 return FSFATAL; 197 198 fat = calloc(boot->NumClusters, sizeof(struct fatEntry)); 199 if (fat == NULL) { 200 perror("No space for FAT"); 201 free(buffer); 202 return FSFATAL; 203 } 204 205 if (buffer[0] != boot->Media 206 || buffer[1] != 0xff || buffer[2] != 0xff 207 || (boot->ClustMask == CLUST16_MASK && buffer[3] != 0xff) 208 || (boot->ClustMask == CLUST32_MASK 209 && ((buffer[3]&0x0f) != 0x0f 210 || buffer[4] != 0xff || buffer[5] != 0xff 211 || buffer[6] != 0xff || (buffer[7]&0x0f) != 0x0f))) { 212 213 /* Windows 95 OSR2 (and possibly any later) changes 214 * the FAT signature to 0xXXffff7f for FAT16 and to 215 * 0xXXffff0fffffff07 for FAT32 upon boot, to know that the 216 * file system is dirty if it doesn't reboot cleanly. 217 * Check this special condition before errorring out. 218 */ 219 if (buffer[0] == boot->Media && buffer[1] == 0xff 220 && buffer[2] == 0xff 221 && ((boot->ClustMask == CLUST16_MASK && buffer[3] == 0x7f) 222 || (boot->ClustMask == CLUST32_MASK 223 && buffer[3] == 0x0f && buffer[4] == 0xff 224 && buffer[5] == 0xff && buffer[6] == 0xff 225 && buffer[7] == 0x07))) 226 ret |= FSDIRTY; 227 else { 228 /* just some odd byte sequence in FAT */ 229 230 switch (boot->ClustMask) { 231 case CLUST32_MASK: 232 pwarn("%s (%02x%02x%02x%02x%02x%02x%02x%02x)\n", 233 "FAT starts with odd byte sequence", 234 buffer[0], buffer[1], buffer[2], buffer[3], 235 buffer[4], buffer[5], buffer[6], buffer[7]); 236 break; 237 case CLUST16_MASK: 238 pwarn("%s (%02x%02x%02x%02x)\n", 239 "FAT starts with odd byte sequence", 240 buffer[0], buffer[1], buffer[2], buffer[3]); 241 break; 242 default: 243 pwarn("%s (%02x%02x%02x)\n", 244 "FAT starts with odd byte sequence", 245 buffer[0], buffer[1], buffer[2]); 246 break; 247 } 248 249 250 if (ask(1, "Correct")) 251 ret |= FSFIXFAT; 252 } 253 } 254 switch (boot->ClustMask) { 255 case CLUST32_MASK: 256 p = buffer + 8; 257 break; 258 case CLUST16_MASK: 259 p = buffer + 4; 260 break; 261 default: 262 p = buffer + 3; 263 break; 264 } 265 for (cl = CLUST_FIRST; cl < boot->NumClusters;) { 266 switch (boot->ClustMask) { 267 case CLUST32_MASK: 268 fat[cl].next = p[0] + (p[1] << 8) 269 + (p[2] << 16) + (p[3] << 24); 270 fat[cl].next &= boot->ClustMask; 271 ret |= checkclnum(boot, no, cl, &fat[cl].next); 272 cl++; 273 p += 4; 274 break; 275 case CLUST16_MASK: 276 fat[cl].next = p[0] + (p[1] << 8); 277 ret |= checkclnum(boot, no, cl, &fat[cl].next); 278 cl++; 279 p += 2; 280 break; 281 default: 282 fat[cl].next = (p[0] + (p[1] << 8)) & 0x0fff; 283 ret |= checkclnum(boot, no, cl, &fat[cl].next); 284 cl++; 285 if (cl >= boot->NumClusters) 286 break; 287 fat[cl].next = ((p[1] >> 4) + (p[2] << 4)) & 0x0fff; 288 ret |= checkclnum(boot, no, cl, &fat[cl].next); 289 cl++; 290 p += 3; 291 break; 292 } 293 } 294 295 free(buffer); 296 *fp = fat; 297 return ret; 298} 299 300/* 301 * Get type of reserved cluster 302 */ 303char * 304rsrvdcltype(cl_t cl) 305{ 306 if (cl == CLUST_FREE) 307 return "free"; 308 if (cl < CLUST_BAD) 309 return "reserved"; 310 if (cl > CLUST_BAD) 311 return "as EOF"; 312 return "bad"; 313} 314 315static int 316clustdiffer(cl_t cl, cl_t *cp1, cl_t *cp2, int fatnum) 317{ 318 if (*cp1 == CLUST_FREE || *cp1 >= CLUST_RSRVD) { 319 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 320 if ((*cp1 != CLUST_FREE && *cp1 < CLUST_BAD 321 && *cp2 != CLUST_FREE && *cp2 < CLUST_BAD) 322 || (*cp1 > CLUST_BAD && *cp2 > CLUST_BAD)) { 323 pwarn("Cluster %u is marked %s with different indicators, ", 324 cl, rsrvdcltype(*cp1)); 325 if (ask(1, "fix")) { 326 *cp2 = *cp1; 327 return FSFATMOD; 328 } 329 return FSFATAL; 330 } 331 pwarn("Cluster %u is marked %s in FAT 0, %s in FAT %d\n", 332 cl, rsrvdcltype(*cp1), rsrvdcltype(*cp2), fatnum); 333 if (ask(0, "use FAT 0's entry")) { 334 *cp2 = *cp1; 335 return FSFATMOD; 336 } 337 if (ask(0, "use FAT %d's entry", fatnum)) { 338 *cp1 = *cp2; 339 return FSFATMOD; 340 } 341 return FSFATAL; 342 } 343 pwarn("Cluster %u is marked %s in FAT 0, but continues with cluster %u in FAT %d\n", 344 cl, rsrvdcltype(*cp1), *cp2, fatnum); 345 if (ask(0, "Use continuation from FAT %d", fatnum)) { 346 *cp1 = *cp2; 347 return FSFATMOD; 348 } 349 if (ask(0, "Use mark from FAT 0")) { 350 *cp2 = *cp1; 351 return FSFATMOD; 352 } 353 return FSFATAL; 354 } 355 if (*cp2 == CLUST_FREE || *cp2 >= CLUST_RSRVD) { 356 pwarn("Cluster %u continues with cluster %u in FAT 0, but is marked %s in FAT %d\n", 357 cl, *cp1, rsrvdcltype(*cp2), fatnum); 358 if (ask(0, "Use continuation from FAT 0")) { 359 *cp2 = *cp1; 360 return FSFATMOD; 361 } 362 if (ask(0, "Use mark from FAT %d", fatnum)) { 363 *cp1 = *cp2; 364 return FSFATMOD; 365 } 366 return FSERROR; 367 } 368 pwarn("Cluster %u continues with cluster %u in FAT 0, but with cluster %u in FAT %d\n", 369 cl, *cp1, *cp2, fatnum); 370 if (ask(0, "Use continuation from FAT 0")) { 371 *cp2 = *cp1; 372 return FSFATMOD; 373 } 374 if (ask(0, "Use continuation from FAT %d", fatnum)) { 375 *cp1 = *cp2; 376 return FSFATMOD; 377 } 378 return FSERROR; 379} 380 381/* 382 * Compare two FAT copies in memory. Resolve any conflicts and merge them 383 * into the first one. 384 */ 385int 386comparefat(struct bootblock *boot, struct fatEntry *first, 387 struct fatEntry *second, int fatnum) 388{ 389 cl_t cl; 390 int ret = FSOK; 391 392 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) 393 if (first[cl].next != second[cl].next) 394 ret |= clustdiffer(cl, &first[cl].next, &second[cl].next, fatnum); 395 return ret; 396} 397 398void 399clearchain(struct bootblock *boot, struct fatEntry *fat, cl_t head) 400{ 401 cl_t p, q; 402 403 for (p = head; p >= CLUST_FIRST && p < boot->NumClusters; p = q) { 404 if (fat[p].head != head) 405 break; 406 q = fat[p].next; 407 fat[p].next = fat[p].head = CLUST_FREE; 408 fat[p].length = 0; 409 } 410} 411 412int 413tryclear(struct bootblock *boot, struct fatEntry *fat, cl_t head, cl_t *trunc) 414{ 415 if (ask(0, "Clear chain starting at %u", head)) { 416 clearchain(boot, fat, head); 417 return FSFATMOD; 418 } else if (ask(0, "Truncate")) { 419 *trunc = CLUST_EOF; 420 return FSFATMOD; 421 } else 422 return FSERROR; 423} 424 425/* 426 * Check a complete FAT in-memory for crosslinks 427 */ 428int 429checkfat(struct bootblock *boot, struct fatEntry *fat) 430{ 431 cl_t head, p, h, n; 432 u_int len; 433 int ret = 0; 434 int conf; 435 436 /* 437 * pass 1: figure out the cluster chains. 438 */ 439 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 440 /* find next untravelled chain */ 441 if (fat[head].head != 0 /* cluster already belongs to some chain */ 442 || fat[head].next == CLUST_FREE 443 || fat[head].next == CLUST_BAD) 444 continue; /* skip it. */ 445 446 /* follow the chain and mark all clusters on the way */ 447 for (len = 0, p = head; 448 p >= CLUST_FIRST && p < boot->NumClusters; 449 p = fat[p].next) { 450 fat[p].head = head; 451 len++; 452 } 453 454 /* the head record gets the length */ 455 fat[head].length = fat[head].next == CLUST_FREE ? 0 : len; 456 } 457 458 /* 459 * pass 2: check for crosslinked chains (we couldn't do this in pass 1 because 460 * we didn't know the real start of the chain then - would have treated partial 461 * chains as interlinked with their main chain) 462 */ 463 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 464 /* find next untravelled chain */ 465 if (fat[head].head != head) 466 continue; 467 468 /* follow the chain to its end (hopefully) */ 469 for (p = head; 470 (n = fat[p].next) >= CLUST_FIRST && n < boot->NumClusters; 471 p = n) 472 if (fat[n].head != head) 473 break; 474 if (n >= CLUST_EOFS) 475 continue; 476 477 if (n == CLUST_FREE || n >= CLUST_RSRVD) { 478 pwarn("Cluster chain starting at %u ends with cluster marked %s\n", 479 head, rsrvdcltype(n)); 480 ret |= tryclear(boot, fat, head, &fat[p].next); 481 continue; 482 } 483 if (n < CLUST_FIRST || n >= boot->NumClusters) { 484 pwarn("Cluster chain starting at %u ends with cluster out of range (%u)\n", 485 head, n); 486 ret |= tryclear(boot, fat, head, &fat[p].next); 487 continue; 488 } 489 pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n", 490 head, fat[n].head, n); 491 conf = tryclear(boot, fat, head, &fat[p].next); 492 if (ask(0, "Clear chain starting at %u", h = fat[n].head)) { 493 if (conf == FSERROR) { 494 /* 495 * Transfer the common chain to the one not cleared above. 496 */ 497 for (p = n; 498 p >= CLUST_FIRST && p < boot->NumClusters; 499 p = fat[p].next) { 500 if (h != fat[p].head) { 501 /* 502 * Have to reexamine this chain. 503 */ 504 head--; 505 break; 506 } 507 fat[p].head = head; 508 } 509 } 510 clearchain(boot, fat, h); 511 conf |= FSFATMOD; 512 } 513 ret |= conf; 514 } 515 516 return ret; 517} 518 519/* 520 * Write out FATs encoding them from the internal format 521 */ 522int 523writefat(int fs, struct bootblock *boot, struct fatEntry *fat, int correct_fat) 524{ 525 u_char *buffer, *p; 526 cl_t cl; 527 int i; 528 u_int32_t fatsz; 529 off_t off; 530 int ret = FSOK; 531 532 buffer = malloc(fatsz = boot->FATsecs * boot->BytesPerSec); 533 if (buffer == NULL) { 534 perror("No space for FAT"); 535 return FSFATAL; 536 } 537 memset(buffer, 0, fatsz); 538 boot->NumFree = 0; 539 p = buffer; 540 if (correct_fat) { 541 *p++ = (u_char)boot->Media; 542 *p++ = 0xff; 543 *p++ = 0xff; 544 switch (boot->ClustMask) { 545 case CLUST16_MASK: 546 *p++ = 0xff; 547 break; 548 case CLUST32_MASK: 549 *p++ = 0x0f; 550 *p++ = 0xff; 551 *p++ = 0xff; 552 *p++ = 0xff; 553 *p++ = 0x0f; 554 break; 555 } 556 } else { 557 /* use same FAT signature as the old FAT has */ 558 int count; 559 u_char *old_fat; 560 561 switch (boot->ClustMask) { 562 case CLUST32_MASK: 563 count = 8; 564 break; 565 case CLUST16_MASK: 566 count = 4; 567 break; 568 default: 569 count = 3; 570 break; 571 } 572 573 if (!_readfat(fs, boot, boot->ValidFat >= 0 ? boot->ValidFat :0, 574 &old_fat)) { 575 free(buffer); 576 return FSFATAL; 577 } 578 579 memcpy(p, old_fat, count); 580 free(old_fat); 581 p += count; 582 } 583 584 for (cl = CLUST_FIRST; cl < boot->NumClusters; cl++) { 585 switch (boot->ClustMask) { 586 case CLUST32_MASK: 587 if (fat[cl].next == CLUST_FREE) 588 boot->NumFree++; 589 *p++ = (u_char)fat[cl].next; 590 *p++ = (u_char)(fat[cl].next >> 8); 591 *p++ = (u_char)(fat[cl].next >> 16); 592 *p &= 0xf0; 593 *p++ |= (fat[cl].next >> 24)&0x0f; 594 break; 595 case CLUST16_MASK: 596 if (fat[cl].next == CLUST_FREE) 597 boot->NumFree++; 598 *p++ = (u_char)fat[cl].next; 599 *p++ = (u_char)(fat[cl].next >> 8); 600 break; 601 default: 602 if (fat[cl].next == CLUST_FREE) 603 boot->NumFree++; 604 if (cl + 1 < boot->NumClusters 605 && fat[cl + 1].next == CLUST_FREE) 606 boot->NumFree++; 607 *p++ = (u_char)fat[cl].next; 608 *p++ = (u_char)((fat[cl].next >> 8) & 0xf) 609 |(u_char)(fat[cl+1].next << 4); 610 *p++ = (u_char)(fat[++cl].next >> 4); 611 break; 612 } 613 } 614 for (i = 0; i < boot->FATs; i++) { 615 off = boot->ResSectors + i * boot->FATsecs; 616 off *= boot->BytesPerSec; 617 if (lseek(fs, off, SEEK_SET) != off 618 || write(fs, buffer, fatsz) != fatsz) { 619 perror("Unable to write FAT"); 620 ret = FSFATAL; /* Return immediately? XXX */ 621 } 622 } 623 free(buffer); 624 return ret; 625} 626 627/* 628 * Check a complete in-memory FAT for lost cluster chains 629 */ 630int 631checklost(int dosfs, struct bootblock *boot, struct fatEntry *fat) 632{ 633 cl_t head; 634 int mod = FSOK; 635 int ret; 636 637 for (head = CLUST_FIRST; head < boot->NumClusters; head++) { 638 /* find next untravelled chain */ 639 if (fat[head].head != head 640 || fat[head].next == CLUST_FREE 641 || (fat[head].next >= CLUST_RSRVD 642 && fat[head].next < CLUST_EOFS) 643 || (fat[head].flags & FAT_USED)) 644 continue; 645 646 pwarn("Lost cluster chain at cluster %u\n%d Cluster(s) lost\n", 647 head, fat[head].length); 648 mod |= ret = reconnect(dosfs, boot, fat, head); 649 if (mod & FSFATAL) 650 break; 651 if (ret == FSERROR && ask(0, "Clear")) { 652 clearchain(boot, fat, head); 653 mod |= FSFATMOD; 654 } 655 } 656 finishlf(); 657 658 if (boot->FSInfo) { 659 ret = 0; 660 if (boot->FSFree != boot->NumFree) { 661 pwarn("Free space in FSInfo block (%d) not correct (%d)\n", 662 boot->FSFree, boot->NumFree); 663 if (ask(1, "fix")) { 664 boot->FSFree = boot->NumFree; 665 ret = 1; 666 } 667 } 668 if (boot->NumFree && fat[boot->FSNext].next != CLUST_FREE) { 669 pwarn("Next free cluster in FSInfo block (%u) not free\n", 670 boot->FSNext); 671 if (ask(1, "fix")) 672 for (head = CLUST_FIRST; head < boot->NumClusters; head++) 673 if (fat[head].next == CLUST_FREE) { 674 boot->FSNext = head; 675 ret = 1; 676 break; 677 } 678 } 679 if (ret) 680 mod |= writefsinfo(dosfs, boot); 681 } 682 683 return mod; 684}
|