1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
|
/*
// Program: Format
// Version: 0.91p
// (0.90b/c - avoid saving info when inappropriate - Eric Auer 2003)
// (0.91d - handle non-standard FAT12/FAT16 formats, debugging: Eric Auer 2003)
// (0.91k - w/o Convert_Huge_To_Integers, preserving bad sector list - EA 2004)
// (0.91l - adds Restore_File_System() written by EA 2004)
// (0.91p - merged "NOT saving..." messages, better FAT32 support - EA 2004)
// Written By: Brian E. Reifsnyder
// Copyright: 2002-2004 under the terms of the GNU GPL, Version 2
// Module Name: savefs.c
// Module Description: Save File System Function
*/
#include "format.h"
#include "floppy.h"
#include "driveio.h"
#include "btstrct.h"
#include "savefs.h"
#include "hdisk.h" /* Force_Drive_Recheck */
#include "userint.h" /* Display_Percentage_Formatted */
#include <string.h> /* strncmp */
/* write one sector somewhere ;-) 0.91k */
void MMapWrite(unsigned long unsigned mmapsec, unsigned long * mmapbuf);
void MMapWrite(unsigned long unsigned mmapsec, unsigned long * mmapbuf)
{
memcpy((void *)§or_buffer[0], (void *)mmapbuf, 512);
if (debug_prog==TRUE)
#if 0
// printf("[DEBUG] ** Writing mirror map data to sector %lu **\n",
// mmapsec);
#else
printf(" [map %lu] ", mmapsec);
#endif
if (Drive_IO(WRITE, mmapsec, -1) != 0)
printf("Error writing MIRROR MAP sector %lu - UNFORMAT spoiled!\n",
mmapsec);
}
/* Save the old file system for possible recovery with unformat */
/* */
/* *** WARNING: This only works if (...) the root directory follows *** */
/* *** right after the 2nd FAT. This is NOT always true for FAT32! *** */
/* Changed in 0.91d to handle != 2 FATs and != 1 reserved/boot sector... */
/* Depends on the unformat data format whether this can be more flexible! */
/* Changed in 0.91p to save more of FAT32 data area (-> root dir) */
/* Changed in 0.91p to save all reserved sectors, not only 1 boot sector */
/* */
void Save_File_System(void)
{
int bad_boot_sector = TRUE;
int end_of_root_directory_flag;
unsigned long mirror_map[512/4]; /* 0.91k: only 1 sector for ANY FAT type */
unsigned pointer = 0;
unsigned long offset_from_end;
unsigned long destination_sector;
unsigned long source_sector;
unsigned long mirror_beginning;
unsigned long mirror_map_beginning;
unsigned long mirror_map_size;
unsigned long mirror_size;
unsigned long mirror_map_sector;
unsigned long number_of_bytes_in_mirror_map;
unsigned long number_of_logical_sectors_on_drive;
unsigned long number_of_root_directory_entries;
unsigned long beginning_of_fat;
unsigned long beginning_of_root_directory;
unsigned long sectors_per_fat;
unsigned long reserved_sectors; /* usually 1 - boot sector [0e]w */
unsigned long number_of_fats; /* usually 2, but can be 1 [10]b */
unsigned long sectors_per_cluster; /* 0.91k */
unsigned long end_of_root_directory;
#define MAXCHUNKSIZE 16 /* could use one huge_sector_buffer completely */
unsigned long chunksize; /* 0.91o optimization */
unsigned long percentage = 0;
int fat_type = param.fat_type; /* Save_File_System default, from def. BPB */
#define BSWord(ofs) ( (unsigned int *)(§or_buffer[ofs]) )[0]
#define BSLong(ofs) ( (unsigned long *)(§or_buffer[ofs]) )[0]
/* write one sector of the mirror map whenever the buffer gets full 0.91k */
#define MMapCheckWrite if (pointer == (512/4)) { \
if ((debug_prog==TRUE) && (source_sector >= beginning_of_root_directory)) \
printf("\n"); \
MMapWrite(mirror_map_sector, &mirror_map[0]); \
mirror_map_sector++; \
pointer = 0; \
}
offset_from_end = (param.drive_type == HARD) ? 20 : 5;
/* Get the boot sector, compute the FAT size, compute the root dir size,*/
/* and get the end of the logical drive. */
Drive_IO(READ,0,1);
if ( (sector_buffer[510]==0x55) && (sector_buffer[511]==0xaa) )
{
bad_boot_sector = FALSE;
if ( BSWord(0x0b) != 512 )
{
printf("Sector size is not 512 bytes. Cannot save UNFORMAT data.\n");
bad_boot_sector = TRUE;
}
number_of_fats = sector_buffer[0x10];
if ( (number_of_fats < 1) || (number_of_fats > 2) )
{
printf("There <1 or >2 FAT copies. Cannot save UNFORMAT data.\n");
bad_boot_sector = TRUE;
}
reserved_sectors = BSWord(0x0e);
if ((param.fat_type != FAT32) && (reserved_sectors != 1))
{
printf("WARNING: Number of reserved / boot sectors is %u, not 1.\n",
reserved_sectors);
if ((reserved_sectors < 1) || (reserved_sectors > 64))
bad_boot_sector = TRUE;
}
if ((param.fat_type == FAT32) &&
(reserved_sectors != parameter_block.bpb.reserved_sectors))
{
printf("WARNING: Reserved sectors are %u but will be %u after format.\n",
reserved_sectors, parameter_block.bpb.reserved_sectors);
if ((reserved_sectors < 1) || (reserved_sectors > 64));
bad_boot_sector = TRUE;
}
number_of_root_directory_entries = BSWord(0x11);
if ( ( (number_of_root_directory_entries == 0) ||
(BSWord(0x16) == 0) ) /* FAT1x size zero? */
&& (fat_type != FAT32))
{
printf(" Confusing: FAT32 detected. Thought it would be %s!\n",
(fat_type == FAT12) ? "FAT12" : "FAT16");
/* 0 root dir entries or FAT1x size in Save_File_System */
nomirror_wimp: /* common bailout point avoids duplicated code (0.91p) */
printf(" NOT saving unformat info, not preserving bad cluster list.\n");
return;
}
if ( (number_of_root_directory_entries != 0) && (fat_type == FAT32) )
{
printf("WARNING: FAT32 with FAT1x style extra root directory???\n");
goto nomirror_wimp; /* 0.91p */
}
number_of_logical_sectors_on_drive = BSWord(0x13);
if (number_of_logical_sectors_on_drive==0)
number_of_logical_sectors_on_drive = /* if it was 0, use 32bit value */
BSLong(0x20);
sectors_per_fat = BSWord(0x16);
if (sectors_per_fat == 0)
{ /* FAT32 case: 32bit sectors per fat value */
sectors_per_fat = BSLong(0x24);
if (fat_type != FAT32)
{
printf(" This must be FAT32, it has a zero FAT1x size.\n");
goto nomirror_wimp; /* 0.91p */
}
}
else
{ /* FAT1x case: 16bit sectors per fat value nonzero */
if (number_of_root_directory_entries == 0)
{
printf(" This has a FAT32 type root directory but a FAT1x type FAT size!\n");
goto nomirror_wimp; /* 0.91p */
}
if (fat_type != ( (sectors_per_fat <= 12) ? FAT12 : FAT16 ))
{
printf(" Would be %s by FAT size rule but is supposed to be FAT32!\n",
(sectors_per_fat <= 12) ? "FAT12" : "FAT16");
goto nomirror_wimp; /* 0.91p */
}
/* FAT12 is max 12 sectors, FAT16 min 16 sectors. Of course this */
/* goes wrong if the FAT12 fat is bigger than needed. To be really */
/* foolproof, one had to count clusters and compare to 4085... */
} /* FAT1x case: 16bit sectors per fat value nonzero */
/* cluster size, geometry, media descriptor and hidden sectors are */
/* not relevant for the UNFORMAT information */
if ( ((number_of_root_directory_entries & 15) != 0) ||
( (param.fat_type != FAT32) && (number_of_root_directory_entries < 16) ) ||
( (param.fat_type == FAT32) && (number_of_root_directory_entries != 0) ) ||
(sectors_per_fat < 1) ||
(number_of_logical_sectors_on_drive < 200) )
{ /* not plausible root directory or FAT or drive size */
printf(" Root directory or FAT or drive size not plausible!\n");
printf(" Not saving UNFORMAT info, not using bad cluster list! Bad boot sector?\n");
bad_boot_sector = TRUE; /* -ea */
} else {
if ( ( 1 + sectors_per_fat + (number_of_root_directory_entries >> 4) +
5 ) > ( number_of_logical_sectors_on_drive >> 1 ) ) /* estimate only */
{
printf(" UNFORMAT info would take more than half the space?\n");
printf(" Not saving UNFORMAT info, not using bad cluster list! Bad boot sector?\n");
bad_boot_sector = TRUE;
}
} /* root directory an FAT and drive size was plausible */
sectors_per_cluster = BSWord(0x0d) & 0xff; /* only a byte */
if (fat_type == FAT32)
{
beginning_of_root_directory = reserved_sectors +
#if 0
( (BSLong(0x2c)-2) * sectors_per_cluster ) + /* NOT USED YET */
#endif
( number_of_fats * (unsigned long)sectors_per_fat );
/* new 0.91p: */
if (sectors_per_cluster < 32) /* first root cluster < 512 dir entries big? */
{
end_of_root_directory = beginning_of_root_directory
+ 32 - 1; /* just backup first 16k of data area */
} else {
end_of_root_directory = beginning_of_root_directory
+ sectors_per_cluster - 1; /* just backup ONE root dir cluster */
}
if (BSLong(0x2c) != 2)
printf("Root directory NOT in first cluster, not saving it!\n");
/* would have to change some code below to save it properly... */
}
else
{
beginning_of_root_directory = reserved_sectors +
(number_of_fats * (unsigned long)sectors_per_fat);
end_of_root_directory = beginning_of_root_directory +
(number_of_root_directory_entries/16) - 1;
/* (last sector which is still PART of the root directory) */
}
/* Compute the locations of the second FAT and the root directory */
/* *** We use the LAST FAT - root directory follows after it! *** */
beginning_of_fat = ((unsigned long)sectors_per_fat * (number_of_fats-1))
+ reserved_sectors;
} /* boot sector had 0x55 0xaa magic and looks sane */
/* If the boot sector is not any good, don't save the file system. */
if (bad_boot_sector==TRUE)
{
printf(" Drive appears unformatted, UNFORMAT information not saved.\n");
return;
}
if ((fat_type == param.fat_type) &&
(reserved_sectors == parameter_block.bpb.reserved_sectors) &&
(number_of_fats == parameter_block.bpb.number_of_fats) &&
(sectors_per_cluster == parameter_block.bpb.sectors_per_cluster) &&
( (sectors_per_fat & 0xffff) ==
( (fat_type == FAT32) ? parameter_block.xbpb.fat_size_low
: parameter_block.bpb.sectors_per_fat ) )
)
{
/* printf(" Scanning existing FAT for bad cluster marks...\n"); */
BadClustPreserve(); /* uses param...bpb values and global bad sect list */
}
else
{
unsigned long scratch;
printf("Old and new filesystem will not have same properties,\n");
printf("preserving (maybe empty) old bad cluster list NOT is possible!\n");
printf("Run a surface scan tool or use FORMAT /U to find bad clusters.\n");
if (reserved_sectors != parameter_block.bpb.reserved_sectors)
printf("Reserved sector count differs: FOUND %lu / PLANNED %u.\n",
reserved_sectors, parameter_block.bpb.reserved_sectors);
if (number_of_fats != parameter_block.bpb.number_of_fats)
printf("Number of FAT copies differs: FOUND %lu / PLANNED %hu\n",
number_of_fats, parameter_block.bpb.number_of_fats);
if (sectors_per_cluster != parameter_block.bpb.sectors_per_cluster)
printf("Cluster size differs: FOUND %lu / PLANNED %hu (sectors)\n",
sectors_per_cluster, parameter_block.bpb.sectors_per_cluster);
scratch = parameter_block.xbpb.fat_size_high;
scratch <<= 16;
scratch |= parameter_block.xbpb.fat_size_low;
if (param.fat_type != FAT32)
scratch = parameter_block.bpb.sectors_per_fat;
printf("FAT sizes are: FOUND %lu %s / PLANNED %lu %s\n",
(BSWord(0x16)) ? BSWord(0x16) : BSLong(0x24),
(BSWord(0x16)) ? "FAT1x" : "FAT32",
scratch,
(param.fat_type == FAT32) ? "FAT32" : "FAT1x");
} /* filesystem parameter mismatch */
printf(" Saving UNFORMAT information...\n");
/* Compute the beginning sector of the mirror map and the size of */
/* the mirror image. */
/* Always mirroring only ONE boot sector and ONE (the last) FAT. */
#if 0 /* pre 0.91p */
mirror_size = 1 + sectors_per_fat +
((fat_type != FAT32) ? (number_of_root_directory_entries/16)
: (sectors_per_cluster)); /* see above... */
#else
mirror_size = reserved_sectors + sectors_per_fat +
(1 + end_of_root_directory - beginning_of_root_directory);
#endif
mirror_map_size = ( (mirror_size+(88/8)+63) / 64 );
/* added +(88/8)+63, removed +1 (for better rounding) in 0.91d */
/* 84+4 bytes are header/trailer, plus 8 bytes per mirrored sector! */
/* each slot is 8 bytes, so there are 64 of them in each map sector */
mirror_beginning = ((number_of_logical_sectors_on_drive-1) - mirror_size)
- offset_from_end; /* -1 because last=num-1, correct? */
mirror_map_beginning = mirror_beginning - mirror_map_size;
/* select beginning to have space for mirror data, mirror map and offset */
/* Write the mirror map pointer to the last sectors of the logical drive. */
/* layout: 1. map... 2. boot 3. fat2... 4. root... 5. pointer */
Clear_Sector_Buffer();
((unsigned long *)§or_buffer[0])[0] = mirror_map_beginning;
memcpy((void *)§or_buffer[4], "AMSESLIFVASRORIMESAEP", 21);
/* pease mirorsav.fil sesam (?) */ /* Add pointer sector flag */
if (debug_prog==TRUE)
{
printf("[DEBUG] Writing mirror map pointer to sector -> %lu\n",
((number_of_logical_sectors_on_drive-1) - offset_from_end) );
/* -1 correct??? */
printf("[DEBUG] Mirror map will start at sector -> %lu\n",
mirror_map_beginning);
}
if (
Drive_IO(WRITE, ((number_of_logical_sectors_on_drive-1) - offset_from_end),
-1) != 0) /* -1 correct??? */
{
printf("Mirror map pointer write error - UNFORMAT will fail for you!\n");
printf("Skipping UNFORMAT / mirror data backup step.\n");
Clear_Sector_Buffer(); /* just to be sure... */
return; /* abort this SAVEFS attempt. Continue with CREATEFS. - 0.91n */
}
/* Create the mirror map and copy the file system to the mirror. */
Clear_Sector_Buffer();
memset(mirror_map, 0, sizeof(mirror_map)); /* Clear mirror_map buffer */
mirror_map_sector = mirror_map_beginning; /* first sector to be used */
memcpy((void *)&mirror_map[0], "X:\\MIRROR.FIL",13);
mirror_map[0] &= 0xffffff00UL; /* remove the "X" */
mirror_map[0] |= param.drive_letter[0]; /* add the real drive letter */
/* Main mirror map creation and copying loop follows: */
pointer = 84/4;
number_of_bytes_in_mirror_map = 84;
source_sector = 0;
destination_sector = mirror_beginning;
end_of_root_directory_flag = FALSE;
do
{
if ( (source_sector>=reserved_sectors) /* "> 0" before 0.91p */ &&
(source_sector<beginning_of_fat) )
source_sector = beginning_of_fat;
/* skip first FAT if 2 FATs present, skip additional res. sectors */
if (debug_prog==TRUE)
{
if (source_sector <= beginning_of_fat) /* 0.91d */
{
if (source_sector < beginning_of_fat) /* (some) BOOT sector */
{
if (source_sector == 0) /* better messages (0.91p) */
{
printf("[DEBUG] Mirroring BOOT sector %lu at sector %lu\n",
source_sector, destination_sector);
if (beginning_of_fat > 1)
printf("[DEBUG] (Messages for other RESERVED sectors skipped...)\n");
}
if ( (beginning_of_fat > 1) &&
(source_sector == reserved_sectors-1) ) /* new 0.91p */
printf("[DEBUG] Mirroring last RESERVED sector %lu at sector %lu\n",
source_sector, destination_sector);
/* could change this and suppress multiple messages in FAT32 */
}
else /* beginning of (last) FAT */
{
printf("[DEBUG] Mirroring FAT %lu sector %lu at sector %lu, ...\n",
number_of_fats, source_sector, destination_sector);
}
}
else /* after FATs */
{
if (source_sector == beginning_of_root_directory)
{
printf("done.\n");
printf("[DEBUG] Mirroring ROOT DIR sector %lu at sector %lu, ",
source_sector, destination_sector);
}
else
{
/* 0.91l - less verbose. Even too unverbose now? */
if (source_sector == (beginning_of_root_directory-1))
printf("[DEBUG] ... mirroring last FAT sector %lu at %lu, ",
source_sector, destination_sector);
}
}
} /* debug_prog */
chunksize = 0; /* chunking loop added 0.91o for multi sector I/O */
do {
unsigned long perc_new = 100UL *
(source_sector + chunksize - beginning_of_fat) /
(beginning_of_root_directory - beginning_of_fat);
/* Enter mapping information into mirror map buffer */
mirror_map[pointer] = source_sector + chunksize;
pointer++;
MMapCheckWrite;
mirror_map[pointer] = destination_sector + chunksize;
pointer++;
MMapCheckWrite;
chunksize++;
if ((source_sector+chunksize) > end_of_root_directory)
end_of_root_directory_flag = TRUE;
/* changed >= into > in 0.91d (save ALL root dir sectors) */
if ( (source_sector >= beginning_of_fat) &&
(perc_new != percentage) &&
(perc_new <= 100) /* do not count root dir progress */ )
{
percentage = perc_new;
Display_Percentage_Formatted(percentage);
} /* percentage display added 0.91o */
} while ( (chunksize < (sizeof(huge_sector_buffer_0) >> 9)) &&
(source_sector >= beginning_of_fat) &&
(end_of_root_directory_flag != TRUE) );
/* chunking loop: only use multi sector I/O in FAT and root dir, */
/* which are assumed to be consecutive - not for boot sector! */
/* printf("%lu-[%lu]->%lu ", source_sector, chunksize, destination_sector); */
/* Copy mirror image one sector at a time */
if (Drive_IO(READ, source_sector, -(int)chunksize) != 0)
printf("Read error at sector %lu - UNFORMAT data damaged\n",
source_sector);
if (Drive_IO(WRITE, destination_sector, -(int)chunksize) != 0)
printf("Write error at sector %lu - UNFORMAT data damaged\n",
destination_sector);
source_sector += chunksize;
destination_sector += chunksize;
number_of_bytes_in_mirror_map += (chunksize << 3); /* chunksize * 8 */
} while (end_of_root_directory_flag==FALSE);
/* End of main mirror map creation and copying loop! */
/* if (debug_prog==TRUE) printf("done.\n"); */
Display_Percentage_Formatted(100);
/* Write trailer in mirror map */
mirror_map[pointer] = 0;
pointer = 512/4; /* force writing */
MMapCheckWrite;
number_of_bytes_in_mirror_map += 4; /* add trailer - 0.91d */
printf(" Mirror map is %lu bytes long, ", number_of_bytes_in_mirror_map);
printf(" %lu sectors mirrored.\n", (number_of_bytes_in_mirror_map - 88) / 8);
return;
}
/* copy back MIRROR data, overwriting both(!) FATs, boot sector and root dir */
/* TODO: Optimize this to pool access when sectors n ... n+m are all copied */
/* to sectors x ... x+m: Just doing one read and one write of m sectors */
/* size saves a lot of disk seek time. The limit for m is the buffer size. */
void Restore_File_System(void)
{
/* FAT32 FIXME: if used root directory data is longer than 1 cluster, */
/* not all of it will be mirrored, and the restored cluster chain will */
/* probably point to some old data for the remaining clusters. */
unsigned long mirror_map_sector;
unsigned long mirror_map[512/4]; /* 0.91k: only 1 sector for ANY FAT type */
int pointer = 0; /* pointer into mirror_map */
unsigned long number_of_logical_sectors_on_drive;
unsigned long beginning_of_fat = 0;
unsigned long sectors_per_fat = 0;
unsigned char number_of_fats = 0; /* unsigned CHAR this time! */
/* default (x)BPB already read using Set_Hard_Drive_Media_Parameters() */
if (parameter_block.bpb.total_sectors)
{
number_of_logical_sectors_on_drive = parameter_block.bpb.total_sectors;
}
else
{
number_of_logical_sectors_on_drive = parameter_block.bpb.large_sector_count_high;
number_of_logical_sectors_on_drive <<= 16;
number_of_logical_sectors_on_drive |= parameter_block.bpb.large_sector_count_low;
}
#ifndef BSWord
#define BSWord(ofs) ( (unsigned int *)(§or_buffer[ofs]) )[0]
#define BSLong(ofs) ( (unsigned long *)(§or_buffer[ofs]) )[0]
#endif
Drive_IO(READ, (number_of_logical_sectors_on_drive-1) -
( (param.drive_type == HARD) ? 20 : 5 ), 1);
if (strncmp((void *)§or_buffer[4], "AMSESLIFVASRORIMESAEP", 21))
{
printf("No MIRROR / UNDELETE data found: Wrong pointer magic.\n");
return;
}
mirror_map_sector = BSLong(0); /* read sector number of mirror map */
pointer = 84/4; /* start reading after headers! */
Drive_IO(READ, mirror_map_sector, 1);
memcpy((void *)&mirror_map[0], (void *)§or_buffer[0], 512);
sector_buffer[13] = 0; /* force string termination */
if (debug_prog==TRUE) printf("[DEBUG] Mirror map at sector %lu, description '%s'\n",
mirror_map_sector, (char *)§or_buffer[0]);
/* mirror map should start with string "x:\mirror.fil" */
if (debug_prog==TRUE) printf("[DEBUG] First mirrored sector is %lu stored at %lu\n",
mirror_map[pointer], mirror_map[pointer+1]);
while (1)
{
unsigned long backup_sector;
unsigned long original_sector;
original_sector = mirror_map[pointer];
pointer++;
if (pointer == (512/4)) /* if beyond sector size */
{
mirror_map_sector++; /* fetch next mirror map sector */
if (debug_prog==TRUE)
printf("\n[DEBUG] Processing mirror map sector %lu.\n",
mirror_map_sector);
else
printf("*");
Drive_IO(READ, mirror_map_sector, 1);
memcpy((void *)&mirror_map[0], (void *)§or_buffer[0], 512);
pointer -= (512/4); /* pointer will be 0 now */
}
backup_sector = mirror_map[pointer];
pointer++;
/* printf("%lu->%lu ", backup_sector, original_sector); */
if ((number_of_fats > 0) &&
( (original_sector == 0UL) || (backup_sector == 0UL) ))
{
printf("\n End marker of mirror map encountered. UNFORMAT done.\n");
if (param.fat_type == FAT32)
{
Drive_IO(READ, 0, 1);
backup_sector = BSWord(0x32);
if (backup_sector && (backup_sector < beginning_of_fat))
{
printf(" Cloning boot sector into backup.\n");
if (Drive_IO(WRITE, backup_sector, -1)) printf("Failed.\n");
}
else
backup_sector = 0; /* no backups */
original_sector = BSWord(0x30);
if (original_sector && (original_sector < beginning_of_fat)
&& ((original_sector+backup_sector) < beginning_of_fat) )
{
printf(" Invalidating filesystem info sector data.\n");
Drive_IO(READ, original_sector, 1);
memset((void *)§or_buffer[488], 0xff, 8);
/* set free_count and next_free long int values to -1 */
/* the OS will then re-initialize them on next reboot */
if (Drive_IO(WRITE, original_sector, -1)) printf("Failed.\n");
if (Drive_IO(WRITE, original_sector+backup_sector, -1))
printf("Failed.\n");
}
} /* FAT32 postprocessing */
return;
}
if (Drive_IO(READ, backup_sector, -1))
{
printf("*** Could not copy backup sector %lu to sector %lu ***\n",
backup_sector, original_sector);
}
else
{
if ( (original_sector == 0) &&
( (sector_buffer[0x10] > 7) || (sector_buffer[0x10] < 1) ) )
{
printf("Boot sector would be overwritten by nonsense!\n");
printf("Aborting to avoid damage (FAT count 0 or above 7).\n");
exit(1);
} /* nonsense boot protection */
if (Drive_IO(WRITE, original_sector, -1))
printf("*** Could not restore sector %lu ***\n", original_sector);
if (debug_prog==TRUE) printf(".");
if ( (number_of_fats > 1) && /* recreate 2nd FAT copy if needed */
(original_sector >= beginning_of_fat) &&
( (original_sector-beginning_of_fat) < (2*sectors_per_fat) ) )
{
unsigned long cloned_sector = original_sector;
if (original_sector >= (beginning_of_fat+sectors_per_fat))
{
cloned_sector -= sectors_per_fat; /* clone 2nd into 1st */
if (debug_prog==TRUE) printf("<");
}
else
{
cloned_sector += sectors_per_fat; /* clone 1st into 2nd */
if (debug_prog==TRUE) printf(">");
}
if (Drive_IO(WRITE, cloned_sector, -1))
printf("*** Could not clone FAT sector %lu into sector %lu ***\n",
original_sector, cloned_sector);
} /* FAT cloning */
if (original_sector == 0UL)
{
number_of_fats = sector_buffer[0x10]; /* should be or 1 2 */
if ((number_of_fats < 0) || (number_of_fats > 2))
{
if (!number_of_fats) number_of_fats++;
if (number_of_fats > 2) number_of_fats = 2;
printf("WARNING: %hu FAT copies requested, using %hu instead.\n",
sector_buffer[0x10], number_of_fats);
}
beginning_of_fat = BSWord(0x0e); /* FAT begins after reserved sectors */
sectors_per_fat = BSWord(0x16); /* FAT16 style */
if (!sectors_per_fat)
{
sectors_per_fat = BSLong(0x24); /* FAT32 style */
if (param.fat_type != FAT32)
printf("Correction: must be FAT32 according to recorded boot sector.\n");
param.fat_type = FAT32; /* 0 FAT1x size: FAT32 I/O style needed in Restore_File_System */
}
else
{
if (param.fat_type == FAT32)
printf("WARNING: UNFORMAT turns FAT32 drive into FAT1x!?\n");
}
Force_Drive_Recheck(); /* if we have just written the boot sector */
printf("\n Boot sector data: %hu FAT copies (offset %lu), %lu sectors per FAT\n",
number_of_fats, beginning_of_fat, sectors_per_fat);
} /* boot sector updated */
} /* READ worked */
} /* while */
/* return; */ /* never reached */
}
|