Fix comparison of $MFT and $MFTMirr to not bail out when there are

unused, invalid mft records which are the same in both $MFT and
$MFTMirr.  Ported from kernel driver 2.1.27 release and aplied both
to libntfs/volume.c mount related code and to ntfsprogs/ntfsfix.c's
fixup code.  (Anton)
edge.strict_endians
antona 2006-03-27 22:43:09 +00:00
parent f4344d6261
commit cf631e3398
3 changed files with 94 additions and 58 deletions

View File

@ -22,6 +22,11 @@ xx/xx/2006 - 1.13.1-WIP
numbers in hex (and octal if anyone is crazy enough to use that) in
addition to decimal numbers on the command line options to most if
not all utilities. (Anton)
- Fix comparison of $MFT and $MFTMirr to not bail out when there are
unused, invalid mft records which are the same in both $MFT and
$MFTMirr. Ported from kernel driver 2.1.27 release and aplied both
to libntfs/volume.c mount related code and to ntfsprogs/ntfsfix.c's
fixup code. (Anton)
27/02/2006 - 1.13.0 - Lots and lots and lots of fixes and enhancements.

View File

@ -816,6 +816,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
}
ntfs_log_debug("Comparing $MFTMirr to $MFT... ");
for (i = 0; i < vol->mftmirr_size; ++i) {
MFT_RECORD *mrec, *mrec2;
const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
"$Volume", "$AttrDef", "root directory", "$Bitmap",
"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
@ -828,33 +829,39 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
else
s = "mft record";
if (ntfs_is_baad_recordp(m + i * vol->mft_record_size)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFT error: Incomplete multi sector transfer "
"detected in %s.\n", s);
goto io_error_exit;
mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
if (mrec->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFT error: Incomplete multi "
"sector transfer detected in "
"%s.\n", s);
goto io_error_exit;
}
if (!ntfs_is_mft_recordp(mrec)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFT error: Invalid mft "
"record for %s.\n", s);
goto io_error_exit;
}
}
if (!ntfs_is_mft_recordp(m + i * vol->mft_record_size)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFT error: Invalid mft record for %s.\n", s);
goto io_error_exit;
mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
if (mrec2->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec2)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFTMirr error: Incomplete "
"multi sector transfer "
"detected in %s.\n", s);
goto io_error_exit;
}
if (!ntfs_is_mft_recordp(mrec2)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFTMirr error: Invalid mft "
"record for %s.\n", s);
goto io_error_exit;
}
}
if (ntfs_is_baad_recordp(m2 + i * vol->mft_record_size)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFTMirr error: Incomplete multi sector "
"transfer detected in %s.\n", s);
goto io_error_exit;
}
if (!ntfs_is_mft_recordp(m2 + i * vol->mft_record_size)) {
ntfs_log_debug("FAILED\n");
ntfs_log_debug("$MFTMirr error: Invalid mft record for "
"%s.\n", s);
goto io_error_exit;
}
if (memcmp((u8*)m + i * vol->mft_record_size, (u8*)m2 +
i * vol->mft_record_size,
ntfs_mft_record_get_data_size((MFT_RECORD*)(
(u8*)m + i * vol->mft_record_size)))) {
if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
ntfs_log_debug(FAILED);
ntfs_log_debug("$MFTMirr does not match $MFT. Run "
"chkdsk.\n");

View File

@ -380,10 +380,12 @@ static int fix_mftmirr(ntfs_volume *vol)
ntfs_log_info("Comparing $MFTMirr to $MFT... ");
done = FALSE;
for (i = 0; i < vol->mftmirr_size; ++i) {
MFT_RECORD *mrec, *mrec2;
const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
"$Volume", "$AttrDef", "root directory", "$Bitmap",
"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
const char *s;
BOOL use_mirr;
if (i < 12)
s = ESTR[i];
@ -392,46 +394,68 @@ static int fix_mftmirr(ntfs_volume *vol)
else
s = "mft record";
if (ntfs_is_baad_recordp(m + i * vol->mft_record_size)) {
ntfs_log_info("FAILED");
ntfs_log_error("$MFT error: Incomplete multi sector "
"transfer detected in %s.\nCannot "
"handle this yet. )-:\n", s);
goto error_exit;
}
if (!ntfs_is_mft_recordp(m + i * vol->mft_record_size)) {
ntfs_log_info("FAILED");
ntfs_log_error("$MFT error: Invalid mft record for "
"%s.\nCannot handle this yet. )-:\n",
s);
goto error_exit;
}
if (ntfs_is_baad_recordp(m2 + i * vol->mft_record_size)) {
ntfs_log_info("FAILED");
ntfs_log_error("$MFTMirr error: Incomplete multi "
"sector transfer detected in %s.\n", s);
goto error_exit;
}
if (memcmp((u8*)m + i * vol->mft_record_size, (u8*)m2 +
i * vol->mft_record_size,
ntfs_mft_record_get_data_size((MFT_RECORD*)(
(u8*)m + i * vol->mft_record_size)))) {
if (!done) {
done = TRUE;
use_mirr = FALSE;
mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
if (mrec->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec)) {
ntfs_log_info(FAILED);
ntfs_log_info("Correcting differences in $MFTMirr...");
ntfs_log_error("$MFT error: Incomplete multi "
"sector transfer detected in "
"%s.\nCannot handle this yet. "
")-:\n", s);
goto error_exit;
}
br = ntfs_mft_record_write(vol, i, (MFT_RECORD*)(m +
i * vol->mft_record_size));
if (br) {
if (!ntfs_is_mft_recordp(mrec)) {
ntfs_log_info(FAILED);
ntfs_log_perror("Error correcting $MFTMirr");
ntfs_log_error("$MFT error: Invalid mft "
"record for %s.\nCannot "
"handle this yet. )-:\n", s);
goto error_exit;
}
}
mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
if (mrec2->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec2)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFTMirr error: Incomplete "
"multi sector transfer "
"detected in %s.\n", s);
goto error_exit;
}
if (!ntfs_is_mft_recordp(mrec2)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFTMirr error: Invalid mft "
"record for %s.\n", s);
goto error_exit;
}
/* $MFT is corrupt but $MFTMirr is ok, use $MFTMirr. */
if (!(mrec->flags & MFT_RECORD_IN_USE) &&
!ntfs_is_mft_recordp(mrec))
use_mirr = TRUE;
}
if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
if (!done) {
done = TRUE;
ntfs_log_info(FAILED);
}
ntfs_log_info("Correcting differences in $MFT%s "
"record %d...", use_mirr ? "" : "Mirr",
i);
br = ntfs_mft_record_write(vol, i,
use_mirr ? mrec2 : mrec);
if (br) {
ntfs_log_info(FAILED);
ntfs_log_perror("Error correcting $MFT%s",
use_mirr ? "" : "Mirr");
goto error_exit;
}
ntfs_log_info(OK);
}
}
ntfs_log_info(OK);
ntfs_log_info("Processing of $MFT and $MFTMirr completed successfully.\n");
if (!done)
ntfs_log_info(OK);
ntfs_log_info("Processing of $MFT and $MFTMirr completed "
"successfully.\n");
ret = 0;
error_exit:
free(m);