You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
14 KiB
345 lines
14 KiB
14 years ago
|
X-Git-Url: http://ntfs-3g.git.sourceforge.net/git/gitweb.cgi?p=ntfs-3g%2Fntfs-3g_ntfsprogs;a=blobdiff_plain;f=ntfsprogs%2Fntfsck.c;h=0964a4de57a385308f9b5bf61b04b25812e17b7f;hp=ff6946dfe286a87e0dafd4c6a509a8b7bc69625e;hb=HEAD;hpb=0289d1a6c31942609b96fdf2c1baeb7355fee2bc
|
||
|
|
||
|
diff --git a/ntfsprogs/ntfsck.c b/ntfsprogs/ntfsck.c
|
||
|
index ff6946d..0964a4d 100644
|
||
|
--- a/ntfsprogs/ntfsck.c
|
||
|
+++ b/ntfsprogs/ntfsck.c
|
||
|
@@ -125,7 +125,7 @@ static s64 current_mft_record;
|
||
|
* This is just a preliminary volume.
|
||
|
* Filled while checking the boot sector and used in the preliminary MFT check.
|
||
|
*/
|
||
|
-static ntfs_volume vol;
|
||
|
+//static ntfs_volume vol;
|
||
|
|
||
|
static runlist_element *mft_rl, *mft_bitmap_rl;
|
||
|
|
||
|
@@ -144,7 +144,7 @@ static int assert_u32_equal(u32 val, u32 ok, const char *name)
|
||
|
{
|
||
|
if (val!=ok) {
|
||
|
check_failed("Assertion failed for '%lld:%s'. should be 0x%x, "
|
||
|
- "was 0x%x.\n", current_mft_record, name,
|
||
|
+ "was 0x%x.\n", (long long)current_mft_record, name,
|
||
|
(int)ok, (int)val);
|
||
|
//errors++;
|
||
|
return 1;
|
||
|
@@ -156,7 +156,8 @@ static int assert_u32_noteq(u32 val, u32 wrong, const char *name)
|
||
|
{
|
||
|
if (val==wrong) {
|
||
|
check_failed("Assertion failed for '%lld:%s'. should not be "
|
||
|
- "0x%x.\n", current_mft_record, name, (int)wrong);
|
||
|
+ "0x%x.\n", (long long)current_mft_record, name,
|
||
|
+ (int)wrong);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
@@ -190,7 +191,7 @@ static int assert_u32_less(u32 val1, u32 val2, const char *name)
|
||
|
* todo: may we use ntfs_boot_sector_is_ntfs() instead?
|
||
|
* It already does the checks but will not be able to fix anything.
|
||
|
*/
|
||
|
-static BOOL verify_boot_sector(struct ntfs_device *dev)
|
||
|
+static BOOL verify_boot_sector(struct ntfs_device *dev, ntfs_volume *rawvol)
|
||
|
{
|
||
|
u8 buf[512];
|
||
|
NTFS_BOOT_SECTOR *ntfs_boot = (NTFS_BOOT_SECTOR *)&buf;
|
||
|
@@ -208,7 +209,7 @@ static BOOL verify_boot_sector(struct ntfs_device *dev)
|
||
|
(buf[2]!=0x90)) {
|
||
|
check_failed("Boot sector: Bad jump.\n");
|
||
|
}
|
||
|
- if (ntfs_boot->oem_id != NTFS_SB_MAGIC) {
|
||
|
+ if (ntfs_boot->oem_id != magicNTFS) {
|
||
|
check_failed("Boot sector: Bad NTFS magic.\n");
|
||
|
}
|
||
|
bytes_per_sector = le16_to_cpu(ntfs_boot->bpb.bytes_per_sector);
|
||
|
@@ -223,9 +224,9 @@ static BOOL verify_boot_sector(struct ntfs_device *dev)
|
||
|
|
||
|
// todo: if partition, query bios and match heads/tracks? */
|
||
|
|
||
|
- // Initialize some values from vol. We will need those later.
|
||
|
- ntfs_boot_sector_parse(&vol, (NTFS_BOOT_SECTOR *)buf);
|
||
|
- vol.dev = dev;
|
||
|
+ // Initialize some values into rawvol. We will need those later.
|
||
|
+ rawvol->dev = dev;
|
||
|
+ ntfs_boot_sector_parse(rawvol, (NTFS_BOOT_SECTOR *)buf);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -246,7 +247,7 @@ static BOOL verify_boot_sector(struct ntfs_device *dev)
|
||
|
*
|
||
|
* Assumes dev is open.
|
||
|
*/
|
||
|
-static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record, u32 attr_type, u32 size_of_file_record)
|
||
|
+static runlist *load_runlist(ntfs_volume *rawvol, s64 offset_to_file_record, u32 attr_type, u32 size_of_file_record)
|
||
|
{
|
||
|
u8 *buf;
|
||
|
u16 attrs_offset;
|
||
|
@@ -260,9 +261,11 @@ static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record,
|
||
|
if (!buf)
|
||
|
return NULL;
|
||
|
|
||
|
- if (ntfs_pread(dev, offset_to_file_record, size_of_file_record, buf) !=
|
||
|
+ if (ntfs_pread(rawvol->dev, offset_to_file_record, size_of_file_record, buf) !=
|
||
|
size_of_file_record) {
|
||
|
- check_failed("Failed to read file record at offset %lld (0x%llx).\n", offset_to_file_record, offset_to_file_record);
|
||
|
+ check_failed("Failed to read file record at offset %lld (0x%llx).\n",
|
||
|
+ (long long)offset_to_file_record,
|
||
|
+ (long long)offset_to_file_record);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -279,7 +282,9 @@ static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record,
|
||
|
//printf("Attr type: 0x%x.\n", attr_rec->type);
|
||
|
// Check attribute record. (Only what is in the buffer)
|
||
|
if (attr_rec->type==AT_END) {
|
||
|
- check_failed("Attribute 0x%x not found in file record at offset %lld (0x%llx).\n", (int)le32_to_cpu(attr_rec->type), offset_to_file_record, offset_to_file_record);
|
||
|
+ check_failed("Attribute 0x%x not found in file record at offset %lld (0x%llx).\n", (int)le32_to_cpu(attr_rec->type),
|
||
|
+ (long long)offset_to_file_record,
|
||
|
+ (long long)offset_to_file_record);
|
||
|
return NULL;
|
||
|
}
|
||
|
if ((u8*)attr_rec>buf+size_of_file_record-8) {
|
||
|
@@ -295,7 +300,9 @@ static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record,
|
||
|
// Check that this attribute does not overflow the mft_record
|
||
|
if ((u8*)attr_rec+length >= buf+size_of_file_record) {
|
||
|
check_failed("Attribute (0x%x) is larger than FILE record at offset %lld (0x%llx).\n",
|
||
|
- (int)le32_to_cpu(attr_rec->type), offset_to_file_record, offset_to_file_record);
|
||
|
+ (int)le32_to_cpu(attr_rec->type),
|
||
|
+ (long long)offset_to_file_record,
|
||
|
+ (long long)offset_to_file_record);
|
||
|
return NULL;
|
||
|
}
|
||
|
// todo: what ATTRIBUTE_LIST (0x20)?
|
||
|
@@ -307,13 +314,15 @@ static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record,
|
||
|
// todo: it will also use vol->major_ver if defined(DEBUG). But only for printing purposes.
|
||
|
|
||
|
// Assume ntfs_boot_sector_parse() was called.
|
||
|
- return ntfs_mapping_pairs_decompress(&vol, attr_rec, NULL);
|
||
|
+ return ntfs_mapping_pairs_decompress(rawvol, attr_rec, NULL);
|
||
|
}
|
||
|
|
||
|
attr_rec = (ATTR_RECORD*)((u8*)attr_rec+length);
|
||
|
}
|
||
|
// If we got here, there was an overflow.
|
||
|
- check_failed("file record corrupted at offset %lld (0x%llx).\n", offset_to_file_record, offset_to_file_record);
|
||
|
+ check_failed("file record corrupted at offset %lld (0x%llx).\n",
|
||
|
+ (long long)offset_to_file_record,
|
||
|
+ (long long)offset_to_file_record);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -330,8 +339,8 @@ static VCN get_last_vcn(runlist *rl)
|
||
|
|
||
|
res = LCN_EINVAL;
|
||
|
while (rl->length) {
|
||
|
- ntfs_log_verbose("vcn: %lld, length: %lld.\n", rl->vcn,
|
||
|
- rl->length);
|
||
|
+ ntfs_log_verbose("vcn: %lld, length: %lld.\n",
|
||
|
+ (long long)rl->vcn, (long long)rl->length);
|
||
|
if (rl->vcn<0)
|
||
|
res = rl->vcn;
|
||
|
else
|
||
|
@@ -350,7 +359,7 @@ static u8 *mft_bitmap_buf;
|
||
|
* return: 0 ok.
|
||
|
* RETURN_OPERATIONAL_ERROR on error.
|
||
|
*/
|
||
|
-static int mft_bitmap_load(struct ntfs_device *dev)
|
||
|
+static int mft_bitmap_load(ntfs_volume *rawvol)
|
||
|
{
|
||
|
VCN vcn;
|
||
|
u32 mft_bitmap_length;
|
||
|
@@ -362,16 +371,16 @@ static int mft_bitmap_load(struct ntfs_device *dev)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- mft_bitmap_length = vcn * vol.cluster_size;
|
||
|
- mft_bitmap_records = 8 * mft_bitmap_length * vol.cluster_size /
|
||
|
- vol.mft_record_size;
|
||
|
+ mft_bitmap_length = vcn * rawvol->cluster_size;
|
||
|
+ mft_bitmap_records = 8 * mft_bitmap_length * rawvol->cluster_size /
|
||
|
+ rawvol->mft_record_size;
|
||
|
|
||
|
//printf("sizes: %d, %d.\n", mft_bitmap_length, mft_bitmap_records);
|
||
|
|
||
|
mft_bitmap_buf = (u8*)ntfs_malloc(mft_bitmap_length);
|
||
|
if (!mft_bitmap_buf)
|
||
|
goto error;
|
||
|
- if (ntfs_rl_pread(&vol, mft_bitmap_rl, 0, mft_bitmap_length,
|
||
|
+ if (ntfs_rl_pread(rawvol, mft_bitmap_rl, 0, mft_bitmap_length,
|
||
|
mft_bitmap_buf)!=mft_bitmap_length)
|
||
|
goto error;
|
||
|
return 0;
|
||
|
@@ -419,7 +428,7 @@ static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
|
||
|
// Check that this attribute does not overflow the mft_record
|
||
|
if ((u8*)attr_rec+length >= ((u8*)mft_rec)+buflen) {
|
||
|
check_failed("Attribute (0x%x) is larger than FILE record (%lld).\n",
|
||
|
- (int)attr_type, current_mft_record);
|
||
|
+ (int)attr_type, (long long)current_mft_record);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -432,7 +441,8 @@ static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
|
||
|
|
||
|
if (length<24) {
|
||
|
check_failed("Attribute %lld:0x%x Length too short (%u).\n",
|
||
|
- current_mft_record, (int)attr_type, (int)length);
|
||
|
+ (long long)current_mft_record, (int)attr_type,
|
||
|
+ (int)length);
|
||
|
goto check_attr_record_next_attr;
|
||
|
}
|
||
|
|
||
|
@@ -461,13 +471,13 @@ static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
|
||
|
// Check flags.
|
||
|
if (attr_rec->flags & ~(const_cpu_to_le16(0xc0ff))) {
|
||
|
check_failed("Attribute %lld:0x%x Unknown flags (0x%x).\n",
|
||
|
- current_mft_record, (int)attr_type,
|
||
|
+ (long long)current_mft_record, (int)attr_type,
|
||
|
(int)le16_to_cpu(attr_rec->flags));
|
||
|
}
|
||
|
|
||
|
if (attr_rec->non_resident>1) {
|
||
|
check_failed("Attribute %lld:0x%x Unknown non-resident "
|
||
|
- "flag (0x%x).\n", current_mft_record,
|
||
|
+ "flag (0x%x).\n", (long long)current_mft_record,
|
||
|
(int)attr_type, (int)attr_rec->non_resident);
|
||
|
goto check_attr_record_next_attr;
|
||
|
}
|
||
|
@@ -487,12 +497,14 @@ static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
|
||
|
// Make sure all the fields exist.
|
||
|
if (length<64) {
|
||
|
check_failed("Non-resident attribute %lld:0x%x too short (%u).\n",
|
||
|
- current_mft_record, (int)attr_type, (int)length);
|
||
|
+ (long long)current_mft_record, (int)attr_type,
|
||
|
+ (int)length);
|
||
|
goto check_attr_record_next_attr;
|
||
|
}
|
||
|
if (attr_rec->compression_unit && (length<72)) {
|
||
|
check_failed("Compressed attribute %lld:0x%x too short (%u).\n",
|
||
|
- current_mft_record, (int)attr_type, (int)length);
|
||
|
+ (long long)current_mft_record, (int)attr_type,
|
||
|
+ (int)length);
|
||
|
goto check_attr_record_next_attr;
|
||
|
}
|
||
|
|
||
|
@@ -646,7 +658,7 @@ static BOOL check_file_record(u8 *buffer, u16 buflen)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
-static void replay_log(ntfs_volume *vol)
|
||
|
+static void replay_log(ntfs_volume *vol __attribute__((unused)))
|
||
|
{
|
||
|
// At this time, only check that the log is fully replayed.
|
||
|
ntfs_log_warning("Unsupported: replay_log()\n");
|
||
|
@@ -663,9 +675,11 @@ static void verify_mft_record(ntfs_volume *vol, s64 mft_num)
|
||
|
|
||
|
is_used = mft_bitmap_get_bit(mft_num);
|
||
|
if (is_used<0) {
|
||
|
- ntfs_log_error("Error getting bit value for record %lld.\n", mft_num);
|
||
|
+ ntfs_log_error("Error getting bit value for record %lld.\n",
|
||
|
+ (long long)mft_num);
|
||
|
} else if (!is_used) {
|
||
|
- ntfs_log_verbose("Record %lld unused. Skipping.\n", mft_num);
|
||
|
+ ntfs_log_verbose("Record %lld unused. Skipping.\n",
|
||
|
+ (long long)mft_num);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -673,9 +687,9 @@ static void verify_mft_record(ntfs_volume *vol, s64 mft_num)
|
||
|
if (!buffer)
|
||
|
goto verify_mft_record_error;
|
||
|
|
||
|
- ntfs_log_verbose("MFT record %lld\n", mft_num);
|
||
|
+ ntfs_log_verbose("MFT record %lld\n", (long long)mft_num);
|
||
|
if (ntfs_attr_pread(vol->mft_na, mft_num*vol->mft_record_size, vol->mft_record_size, buffer) < 0) {
|
||
|
- ntfs_log_perror("Couldn't read $MFT record %lld", mft_num);
|
||
|
+ ntfs_log_perror("Couldn't read $MFT record %lld", (long long)mft_num);
|
||
|
goto verify_mft_record_error;
|
||
|
}
|
||
|
|
||
|
@@ -704,7 +718,7 @@ verify_mft_record_error:
|
||
|
* It should not depend on other checks or we may have a circular dependancy.
|
||
|
* Also, this loadng must be forgiving, unlike the comprehensive checks.
|
||
|
*/
|
||
|
-static int verify_mft_preliminary(struct ntfs_device *dev)
|
||
|
+static int verify_mft_preliminary(ntfs_volume *rawvol)
|
||
|
{
|
||
|
current_mft_record = 0;
|
||
|
s64 mft_offset, mftmirr_offset;
|
||
|
@@ -713,12 +727,12 @@ static int verify_mft_preliminary(struct ntfs_device *dev)
|
||
|
ntfs_log_trace("Entering verify_mft_preliminary().\n");
|
||
|
// todo: get size_of_file_record from boot sector
|
||
|
// Load the first segment of the $MFT/DATA runlist.
|
||
|
- mft_offset = vol.mft_lcn * vol.cluster_size;
|
||
|
- mftmirr_offset = vol.mftmirr_lcn * vol.cluster_size;
|
||
|
- mft_rl = load_runlist(dev, mft_offset, AT_DATA, 1024);
|
||
|
+ mft_offset = rawvol->mft_lcn * rawvol->cluster_size;
|
||
|
+ mftmirr_offset = rawvol->mftmirr_lcn * rawvol->cluster_size;
|
||
|
+ mft_rl = load_runlist(rawvol, mft_offset, AT_DATA, 1024);
|
||
|
if (!mft_rl) {
|
||
|
check_failed("Loading $MFT runlist failed. Trying $MFTMirr.\n");
|
||
|
- mft_rl = load_runlist(dev, mftmirr_offset, AT_DATA, 1024);
|
||
|
+ mft_rl = load_runlist(rawvol, mftmirr_offset, AT_DATA, 1024);
|
||
|
}
|
||
|
if (!mft_rl) {
|
||
|
check_failed("Loading $MFTMirr runlist failed too. Aborting.\n");
|
||
|
@@ -730,10 +744,10 @@ static int verify_mft_preliminary(struct ntfs_device *dev)
|
||
|
|
||
|
// Load the runlist of $MFT/Bitmap.
|
||
|
// todo: what about ATTRIBUTE_LIST? Can we reuse code?
|
||
|
- mft_bitmap_rl = load_runlist(dev, mft_offset, AT_BITMAP, 1024);
|
||
|
+ mft_bitmap_rl = load_runlist(rawvol, mft_offset, AT_BITMAP, 1024);
|
||
|
if (!mft_bitmap_rl) {
|
||
|
check_failed("Loading $MFT/Bitmap runlist failed. Trying $MFTMirr.\n");
|
||
|
- mft_bitmap_rl = load_runlist(dev, mftmirr_offset, AT_BITMAP, 1024);
|
||
|
+ mft_bitmap_rl = load_runlist(rawvol, mftmirr_offset, AT_BITMAP, 1024);
|
||
|
}
|
||
|
if (!mft_bitmap_rl) {
|
||
|
check_failed("Loading $MFTMirr/Bitmap runlist failed too. Aborting.\n");
|
||
|
@@ -742,7 +756,7 @@ static int verify_mft_preliminary(struct ntfs_device *dev)
|
||
|
}
|
||
|
|
||
|
/* Load $MFT/Bitmap */
|
||
|
- if ((res = mft_bitmap_load(dev)))
|
||
|
+ if ((res = mft_bitmap_load(rawvol)))
|
||
|
return res;
|
||
|
return -1; /* FIXME: Just added to fix compiler warning without
|
||
|
thinking about what should be here. (Yura) */
|
||
|
@@ -758,7 +772,7 @@ static void check_volume(ntfs_volume *vol)
|
||
|
// For each mft record, verify that it contains a valid file record.
|
||
|
nr_mft_records = vol->mft_na->initialized_size >>
|
||
|
vol->mft_record_size_bits;
|
||
|
- ntfs_log_info("Checking %lld MFT records.\n", nr_mft_records);
|
||
|
+ ntfs_log_info("Checking %lld MFT records.\n", (long long)nr_mft_records);
|
||
|
|
||
|
for (mft_num=0; mft_num < nr_mft_records; mft_num++) {
|
||
|
verify_mft_record(vol, mft_num);
|
||
|
@@ -799,6 +813,7 @@ static int reset_dirty(ntfs_volume *vol)
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
struct ntfs_device *dev;
|
||
|
+ ntfs_volume rawvol;
|
||
|
ntfs_volume *vol;
|
||
|
const char *name;
|
||
|
int ret;
|
||
|
@@ -814,20 +829,19 @@ int main(int argc, char **argv)
|
||
|
dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
|
||
|
if (!dev)
|
||
|
return RETURN_OPERATIONAL_ERROR;
|
||
|
-
|
||
|
if (dev->d_ops->open(dev, O_RDONLY)) { //O_RDWR/O_RDONLY?
|
||
|
ntfs_log_perror("Error opening partition device");
|
||
|
ntfs_device_free(dev);
|
||
|
return RETURN_OPERATIONAL_ERROR;
|
||
|
}
|
||
|
|
||
|
- if ((ret = verify_boot_sector(dev))) {
|
||
|
+ if ((ret = verify_boot_sector(dev,&rawvol))) {
|
||
|
dev->d_ops->close(dev);
|
||
|
return ret;
|
||
|
}
|
||
|
ntfs_log_verbose("Boot sector verification complete. Proceeding to $MFT");
|
||
|
|
||
|
- verify_mft_preliminary(dev);
|
||
|
+ verify_mft_preliminary(&rawvol);
|
||
|
|
||
|
/* ntfs_device_mount() expects the device to be closed. */
|
||
|
if (dev->d_ops->close(dev))
|