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
parent
f4344d6261
commit
cf631e3398
|
@ -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.
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue