patch-2.4.7 linux/fs/ntfs/super.c

Next file: linux/fs/ntfs/super.h
Previous file: linux/fs/ntfs/struct.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.6/linux/fs/ntfs/super.c linux/fs/ntfs/super.c
@@ -1,9 +1,10 @@
-/*  super.c
+/*
+ * super.c
  *
- *  Copyright (C) 1995-1997, 1999 Martin von Löwis
- *  Copyright (C) 1996-1997 Régis Duchesne
- *  Copyright (C) 1999 Steve Dodd
- *  Copyright (C) 2000-2001 Anton Altparmakov (AIA)
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2000-2001 Anton Altparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -40,17 +41,17 @@
 	start = NTFS_GETU16(record + 4);
 	count = NTFS_GETU16(record + 6);
 	count--;
-	if(size && vol->blocksize * count != size)
+	if(size && vol->sector_size * count != size)
 		return 0;
 	fixup = NTFS_GETU16(record + start);
 	start += 2;
-	offset = vol->blocksize - 2;
+	offset = vol->sector_size - 2;
 	while (count--){
 		if (NTFS_GETU16(record + offset) != fixup)
 			return 0;
 		NTFS_PUTU16(record + offset, NTFS_GETU16(record + start));
 		start += 2;
-		offset += vol->blocksize;
+		offset += vol->sector_size;
 	}
 	return 1;
 }
@@ -61,6 +62,8 @@
  */
 int ntfs_init_volume(ntfs_volume *vol, char *boot)
 {
+	int sectors_per_cluster_bits;
+
 	/* Historical default values, in case we don't load $AttrDef. */
 	vol->at_standard_information = 0x10;
 	vol->at_attribute_list = 0x20;
@@ -75,53 +78,71 @@
 	vol->at_bitmap = 0xB0;
 	vol->at_symlink = 0xC0;
 	/* Sector size */
-	vol->blocksize = NTFS_GETU16(boot + 0xB);
-	vol->clusterfactorbits = ffs(NTFS_GETU8(boot + 0xD)) - 1;
+	vol->sector_size = NTFS_GETU16(boot + 0xB);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->sector_size = 0x%x\n",
+				vol->sector_size);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster = "
+				"0x%x\n", NTFS_GETU8(boot + 0xD));
+	sectors_per_cluster_bits = ffs(NTFS_GETU8(boot + 0xD)) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster_bits "
+				"= 0x%x\n", sectors_per_cluster_bits); 
 	vol->mft_clusters_per_record = NTFS_GETS8(boot + 0x40);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_clusters_per_record"
+				" = 0x%x\n", vol->mft_clusters_per_record); 
 	vol->index_clusters_per_record = NTFS_GETS8(boot + 0x44);
-	/* Just some consistency checks. */
-	if (NTFS_GETU32(boot + 0x40) > 256)
-		ntfs_error("Unexpected data #1 in boot block\n");
-	if (NTFS_GETU32(boot+ 0x44) > 256)
-		ntfs_error("Unexpected data #2 in boot block\n");
-	vol->clustersize = vol->blocksize << vol->clusterfactorbits;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: "
+				"vol->index_clusters_per_record = 0x%x\n",
+				vol->index_clusters_per_record); 
+	vol->cluster_size = vol->sector_size << sectors_per_cluster_bits;
+	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size = 0x%x\n",
+				vol->cluster_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size_bits = "
+				"0x%x\n", vol->cluster_size_bits); 
 	if (vol->mft_clusters_per_record > 0)
-		vol->mft_recordsize =
-			       vol->clustersize * vol->mft_clusters_per_record;
-	else {
-		/* If mft_recordsize < clustersize then mft_clusters_per_record
-		   = -log2(mft_recordsize) bytes. Mft_recordsize normaly equals
-		   1024 bytes, which is encoded as 0xF6. */
-		if (vol->mft_clusters_per_record < -31 ||
-					-9 < vol->mft_clusters_per_record) {
-			ntfs_error("Unexpected mft clusters per record value "
-				   "in boot block.\n");
-			return -1;
-		}
-		vol->mft_recordsize = 1 << (-vol->mft_clusters_per_record);
-	}
+		vol->mft_record_size = vol->cluster_size <<
+				(ffs(vol->mft_clusters_per_record) - 1);
+	else
+		/*
+		 * When mft_record_size < cluster_size, mft_clusters_per_record
+		 * = -log2(mft_record_size) bytes. mft_record_size normaly is
+		 * 1024 bytes, which is encoded as 0xF6 (-10 in decimal).
+		 */
+		vol->mft_record_size = 1 << -vol->mft_clusters_per_record;
+	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size = 0x%x"
+				"\n", vol->mft_record_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size_bits = "
+				"0x%x\n", vol->mft_record_size_bits); 
 	if (vol->index_clusters_per_record > 0)
-		vol->index_recordsize =
-			vol->clustersize * vol->index_clusters_per_record;
-	else {
-		/* If index_recordsize < clustersize then
-		   index_clusters_per_record = -log2(index_recordsize) bytes.
-		   Index_recordsize normaly equals 1024 bytes, which is
-		   encoded as 0xF6. */
-		if (vol->index_clusters_per_record < -31 ||
-					-9 < vol->index_clusters_per_record) {
-			ntfs_error("Unexpected index clusters per record "
-				   "value in boot block.\n");
-			return -1;
-		}
-		vol->index_recordsize = 1 << (-vol->index_clusters_per_record);
-	}
-	if (NTFS_GETU64(boot + 0x30) >= (1ULL << 32)) {
-		ntfs_error("Would require 64-bit inodes to mount partition.");
+		vol->index_record_size = vol->cluster_size <<
+				(ffs(vol->index_clusters_per_record) - 1);
+	else
+		/*
+		 * When index_record_size < cluster_size,
+		 * index_clusters_per_record = -log2(index_record_size) bytes.
+		 * index_record_size normaly equals 4096 bytes, which is
+		 * encoded as 0xF4 (-12 in decimal).
+		 */
+		vol->index_record_size = 1 << -vol->index_clusters_per_record;
+	vol->index_record_size_bits = ffs(vol->index_record_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size = "
+				"0x%x\n", vol->index_record_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size_bits "
+				"= 0x%x\n", vol->index_record_size_bits); 
+	/*
+	 * Check mft and mftmirr locations for 64-bit-ness. NOTE: This is a
+	 * crude check only as many other things could be out of bounds later
+	 * on, but it will catch at least some of the cases, since the mftmirr
+	 * is located in the middle of the volume so if the volume is very
+	 * large the mftmirr probably will be out of 32-bit bounds.
+	 */
+	vol->mft_lcn = NTFS_GETS64(boot + 0x30);
+	if (vol->mft_lcn >= (__s64)1 << 31 ||
+	    NTFS_GETS64(boot + 0x38) >= (__s64)1 << 31) {
+		ntfs_error("Cannot handle 64-bit clusters yet.\n");
 		return -1;
 	}
-	/* FIXME: long long value */
-	vol->mft_cluster = NTFS_GETU64(boot + 0x30);
 	/* This will be initialized later. */
 	vol->upcase = 0;
 	vol->upcase_length = 0;
@@ -151,6 +172,11 @@
 	ntfs_volume *vol = attrdef->vol;
 	ntfs_u16* name = (ntfs_u16*)def;
 
+	if (!type) {
+		ntfs_debug(DEBUG_OTHER, "process_atrdef: finished processing "
+							"and returning 1\n");
+		return 1;
+	}
 	if (ntfs_ua_strncmp(name, "$STANDARD_INFORMATION", 64) == 0) {
 		vol->at_standard_information = type;
 		check_type = 0x10;
@@ -190,9 +216,12 @@
 		check_type = 0xC0;
 	}
 	if (check_type && check_type != type) {
-		ntfs_error("Unexpected type %x for %x\n", type, check_type);
+		ntfs_error("process_attrdef: unexpected type 0x%x for 0x%x\n",
+							type, check_type);
 		return -EINVAL;
 	}
+	ntfs_debug(DEBUG_OTHER, "process_attrdef: found %s attribute of type "
+			"0x%x\n", check_type ? "known" : "unknown", type);
 	return 0;
 }
 
@@ -200,9 +229,12 @@
 {
 	ntfs_u8 *buf;
 	ntfs_io io;
-	int offset, error,i;
+	__s64 offset;
+	unsigned i;
+	int error;
 	ntfs_attribute *data;
 
+	ntfs_debug(DEBUG_BSD, "Entered ntfs_init_attrdef()\n");
 	buf = ntfs_malloc(4050); /* 90*45 */
 	if (!buf)
 		return -ENOMEM;
@@ -211,6 +243,8 @@
 	io.do_read = 1;
 	offset = 0;
 	data = ntfs_find_attr(attrdef, attrdef->vol->at_data, 0);
+	ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "
+			"ntfs_find_attr.\n");
 	if (!data) {
 		ntfs_free(buf);
 		return -EINVAL;
@@ -218,13 +252,23 @@
 	do {
 		io.param = buf;
 		io.size = 4050;
+		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going to call "
+				"ntfs_readwrite_attr.\n");
 		error = ntfs_readwrite_attr(attrdef, data, offset, &io);
-		for (i = 0; !error && i < io.size - 0xA0; i += 0xA0)
+		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "
+				"ntfs_readwrite_attr.\n");
+		for (i = 0; !error && i <= io.size - 0xA0; i += 0xA0) {
+			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going "
+					"to call process_attrdef.\n");
 			error = process_attrdef(attrdef, buf + i);
+			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after "
+					"call to process_attrdef.\n");
+		}
 		offset += 4096;
 	} while (!error && io.size);
+	ntfs_debug(DEBUG_BSD, "Exiting ntfs_init_attrdef()\n");
 	ntfs_free(buf);
-	return error;
+	return error == 1 ? 0 : error;
 }
 
 /* ntfs_get_version will determine the NTFS version of the volume and will
@@ -253,7 +297,10 @@
 	int error;
 	ntfs_inode upcase, attrdef, volume;
 
-	vol->mft_ino = (ntfs_inode*)ntfs_calloc(3 * sizeof(ntfs_inode));
+	vol->mft_ino = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->mftmirr = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->bitmap = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->ino_flags = 4 | 2 | 1;
 	error = -ENOMEM;
 	ntfs_debug(DEBUG_BSD, "Going to load MFT\n");
 	if (!vol->mft_ino || (error = ntfs_init_inode(vol->mft_ino, vol,
@@ -263,13 +310,11 @@
 		return error;
 	}
 	ntfs_debug(DEBUG_BSD, "Going to load MIRR\n");
-	vol->mftmirr = vol->mft_ino + 1;
 	if ((error = ntfs_init_inode(vol->mftmirr, vol, FILE_$MftMirr))) {
 		ntfs_error("Problem %d loading MFTMirr\n", error);
 		return error;
 	}
 	ntfs_debug(DEBUG_BSD, "Going to load BITMAP\n");
-	vol->bitmap = vol->mft_ino + 2;
 	if ((error = ntfs_init_inode(vol->bitmap, vol, FILE_$BitMap))) {
 		ntfs_error("Problem loading Bitmap\n");
 		return error;
@@ -311,36 +356,48 @@
 
 int ntfs_release_volume(ntfs_volume *vol)
 {
-	if (vol->mft_ino) {
+	if (((vol->ino_flags & 1) == 1) && vol->mft_ino) {
 		ntfs_clear_inode(vol->mft_ino);
-		ntfs_clear_inode(vol->mftmirr);
-		ntfs_clear_inode(vol->bitmap);
 		ntfs_free(vol->mft_ino);
 		vol->mft_ino = 0;
 	}
+	if (((vol->ino_flags & 2) == 2) && vol->mftmirr) {
+		ntfs_clear_inode(vol->mftmirr);
+		ntfs_free(vol->mftmirr);
+		vol->mftmirr = 0;
+	}
+	if (((vol->ino_flags & 4) == 4) && vol->bitmap) {
+		ntfs_clear_inode(vol->bitmap);
+		ntfs_free(vol->bitmap);
+		vol->bitmap = 0;
+	}
 	ntfs_free(vol->mft);
 	ntfs_free(vol->upcase);
 	return 0;
 }
 
-/* Writes the volume size into vol_size. Returns 0 if successful or error. */
-int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size)
+/*
+ * Writes the volume size (units of clusters) into vol_size.
+ * Returns 0 if successful or error.
+ */
+int ntfs_get_volumesize(ntfs_volume *vol, ntfs_s64 *vol_size)
 {
 	ntfs_io io;
 	char *cluster0;
 
 	if (!vol_size)
 		return -EFAULT;
-	cluster0 = ntfs_malloc(vol->clustersize);
+	cluster0 = ntfs_malloc(vol->cluster_size);
 	if (!cluster0)
 		return -ENOMEM;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	io.param = cluster0;
 	io.do_read = 1;
-	io.size = vol->clustersize;
+	io.size = vol->cluster_size;
 	ntfs_getput_clusters(vol, 0, 0, &io);
-	*vol_size = NTFS_GETU64(cluster0 + 0x28) >> vol->clusterfactorbits;
+	*vol_size = NTFS_GETU64(cluster0 + 0x28) >>
+					(ffs(NTFS_GETU8(cluster0 + 0xD)) - 1);
 	ntfs_free(cluster0);
 	return 0;
 }
@@ -349,12 +406,12 @@
 
 int ntfs_get_free_cluster_count(ntfs_inode *bitmap)
 {
-	unsigned char bits[2048];
-	int offset, error;
-	int clusters = 0;
 	ntfs_io io;
-
-	offset = 0;
+	int offset, error, clusters;
+	unsigned char *bits = ntfs_malloc(2048);
+	if (!bits)
+		return -ENOMEM;
+	offset = clusters = 0;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	while (1) {
@@ -382,6 +439,7 @@
 		}
 		offset += io.size;
 	}
+	ntfs_free(bits);
 	return clusters;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)