File ntfsprogs-1.13.1-vistahotfix.diff of Package ntfsprogs

Index: include/ntfs/volume.h
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/include/ntfs/volume.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- include/ntfs/volume.h	25 Nov 2006 17:37:37 -0000	1.26
+++ include/ntfs/volume.h	28 Nov 2006 10:09:57 -0000	1.27
@@ -54,6 +54,11 @@
 	NTFS_MNT_RDONLY	 	= 1,
 	NTFS_MNT_NOATIME 	= 2,
 	NTFS_MNT_CASE_SENSITIVE	= 4,
+ 	NTFS_MNT_NOT_EXCLUSIVE	= 8,
+	NTFS_MNT_FORENSIC	= 16, /* Mount for forensic purposes, i.e. do
+					 not do any writing at all during the
+					 mount, i.e. no journal emptying, no
+					 dirty bit setting, etc. */
 };
 
 /**
@@ -79,6 +83,10 @@
 	NV_CaseSensitive,	/* 1: Volume is mounted case-sensitive. */
 	NV_LogFileEmpty,	/* 1: $logFile journal is empty. */
 	NV_NoATime,		/* 1: Do not update access time. */
+	NV_WasDirty,		/* 1: Volume was marked dirty before we mounted
+				      it. */
+	NV_ForensicMount,	/* 1: Mount is forensic, i.e. no modifications
+				      are to be done by mount/umount. */
 } ntfs_volume_state_bits;
 
 #define  test_nvol_flag(nv, flag)	 test_bit(NV_##flag, (nv)->state)
@@ -101,6 +109,14 @@
 #define NVolSetNoATime(nv)		  set_nvol_flag(nv, NoATime)
 #define NVolClearNoATime(nv)		clear_nvol_flag(nv, NoATime)
 
+#define NVolWasDirty(nv)		 test_nvol_flag(nv, WasDirty)
+#define NVolSetWasDirty(nv)		  set_nvol_flag(nv, WasDirty)
+#define NVolClearWasDirty(nv)		clear_nvol_flag(nv, WasDirty)
+
+#define NVolForensicMount(nv)		 test_nvol_flag(nv, ForensicMount)
+#define NVolSetForensicMount(nv)	  set_nvol_flag(nv, ForensicMount)
+#define NVolClearForensicMount(nv)	clear_nvol_flag(nv, ForensicMount)
+
 /*
  * NTFS version 1.1 and 1.2 are used by Windows NT4.
  * NTFS version 2.x is used by Windows 2000 Beta
Index: libntfs/volume.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/libntfs/volume.c,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -r1.81 -r1.82
--- libntfs/volume.c	25 Nov 2006 21:35:39 -0000	1.81
+++ libntfs/volume.c	28 Nov 2006 10:09:57 -0000	1.82
@@ -88,6 +88,14 @@
  */
 static void __ntfs_volume_release(ntfs_volume *v)
 {
+	/*
+	 * Clear the dirty bit if it was not set before we mounted and this is
+	 * not a forensic mount.
+	 */
+	if (!NVolReadOnly(v) && !NVolWasDirty(v) && !NVolForensicMount(v)) {
+		v->flags &= ~VOLUME_IS_DIRTY;
+		(void)ntfs_volume_write_flags(v, v->flags);
+	}
 	if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni))
 		ntfs_inode_sync(v->lcnbmp_ni);
 	if (v->vol_ni)
@@ -780,7 +788,9 @@
 		ntfs_log_perror("Failed to startup volume");
 		return NULL;
 	}
-
+	/* Record whether this is a forensic mount. */
+	if (flags & NTFS_MNT_FORENSIC)
+		NVolSetForensicMount(vol);
 	/* Load data from $MFT and $MFTMirr and compare the contents. */
 	m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
 	m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
@@ -997,9 +1007,14 @@
 	/* Setup vol from the volume information attribute value. */
 	vol->major_ver = vinf->major_ver;
 	vol->minor_ver = vinf->minor_ver;
-	/* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are
-	   defined using cpu_to_le16() macro and hence are consistent. */
+	/*
+	 * Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are defined
+	 * using cpu_to_le16() macro and hence are consistent.
+	 */
 	vol->flags = vinf->flags;
+	/* Record whether the volume was dirty or not. */
+	if (vol->flags & VOLUME_IS_DIRTY)
+		NVolSetWasDirty(vol);
 	/*
 	 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.
 	 */
@@ -1115,12 +1130,26 @@
 	/*
 	 * Check for dirty logfile and hibernated Windows.
 	 * We care only about read-write mounts.
+	 *
+	 * If all is ok, reset the logfile and set the dirty bit on the volume.
+	 *
+	 * But do not do that if this is a FORENSIC mount.
 	 */
 	if (!(flags & NTFS_MNT_RDONLY)) {
 		if (ntfs_volume_check_logfile(vol) < 0)
 			goto error_exit;
 		if (ntfs_volume_check_hiberfile(vol) < 0)
 			goto error_exit;
+		if (!NVolForensicMount(vol)) {
+			if (ntfs_logfile_reset(vol) < 0)
+				goto error_exit;
+			if (!NVolWasDirty(vol)) {
+				vol->flags |= VOLUME_IS_DIRTY;
+				if (ntfs_volume_write_flags(vol, vol->flags) <
+						0)
+					goto error_exit;
+			}
+		}
 	}
 
 	return vol;
Index: ntfsprogs/ntfsclone.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsclone.c,v
retrieving revision 1.94
retrieving revision 1.95
diff -u -r1.94 -r1.95
--- ntfsprogs/ntfsclone.c	12 Nov 2006 22:46:50 -0000	1.94
+++ ntfsprogs/ntfsclone.c	28 Nov 2006 10:09:57 -0000	1.95
@@ -1328,7 +1328,7 @@
 		exit(1);
 	}
 
-	if (vol->flags & VOLUME_IS_DIRTY)
+	if (NVolWasDirty(vol))
 		if (opt.force-- <= 0)
 			err_exit(dirty_volume_msg, opt.volume);
 
Index: ntfsprogs/ntfscp.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfscp.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- ntfsprogs/ntfscp.c	12 Nov 2006 22:46:50 -0000	1.39
+++ ntfsprogs/ntfscp.c	28 Nov 2006 10:09:57 -0000	1.40
@@ -320,7 +320,7 @@
 		return 1;
 	}
 
-	if ((vol->flags & VOLUME_IS_DIRTY) && (!opts.force))
+	if (NVolWasDirty(vol) && !opts.force)
 		goto umount;
 
 	{
Index: ntfsprogs/ntfsdump_logfile.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsdump_logfile.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- ntfsprogs/ntfsdump_logfile.c	12 Nov 2006 22:46:50 -0000	1.35
+++ ntfsprogs/ntfsdump_logfile.c	28 Nov 2006 10:09:57 -0000	1.36
@@ -197,7 +197,7 @@
 		ntfs_inode *ni;
 		ntfs_attr *na;
 
-		vol = ntfs_mount(filename, NTFS_MNT_RDONLY);
+		vol = ntfs_mount(filename, NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC);
 		if (!vol)
 			log_err_exit(NULL, "Failed to mount %s: %s\n",
 					filename, strerror(errno));
Index: ntfsprogs/ntfsfix.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsfix.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- ntfsprogs/ntfsfix.c	5 Apr 2006 12:43:07 -0000	1.33
+++ ntfsprogs/ntfsfix.c	28 Nov 2006 10:09:57 -0000	1.34
@@ -82,8 +82,6 @@
 static const char *EXEC_NAME = "ntfsfix";
 static const char *OK        = "OK\n";
 static const char *FAILED    = "FAILED\n";
-static BOOL vol_is_dirty     = FALSE;
-static BOOL journal_is_empty = FALSE;
 
 struct {
 	char *volume;
@@ -247,9 +245,8 @@
 {
 	u16 flags;
 
-	if (vol_is_dirty == TRUE)
+	if (NVolWasDirty(vol))
 		return 0;
-
 	ntfs_log_info("Setting required flags on partition... ");
 	/*
 	 * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
@@ -264,37 +261,9 @@
 		ntfs_log_error("Error setting volume flags.\n");
 		return -1;
 	}
+	vol->flags = flags;
 	ntfs_log_info(OK);
-	vol_is_dirty = TRUE;
-	return 0;
-}
-
-/**
- * set_dirty_flag_mount
- */
-static int set_dirty_flag_mount(ntfs_volume *vol)
-{
-	u16 flags;
-
-	if (vol_is_dirty == TRUE)
-		return 0;
-
-	ntfs_log_info("Setting required flags on partition... ");
-	/*
-	 * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
-	 * and fix it for us.
-	 */
-	flags = vol->flags | VOLUME_IS_DIRTY;
-	/* If NTFS volume version >= 2.0 then set mounted on NT4 flag. */
-	if (vol->major_ver >= 2)
-		flags |= VOLUME_MOUNTED_ON_NT4;
-	if (ntfs_volume_write_flags(vol, flags)) {
-		ntfs_log_info(FAILED);
-		ntfs_log_error("Error setting volume flags.\n");
-		return -1;
-	}
-	ntfs_log_info(OK);
-	vol_is_dirty = TRUE;
+	NVolSetWasDirty(vol);
 	return 0;
 }
 
@@ -303,9 +272,8 @@
  */
 static int empty_journal(ntfs_volume *vol)
 {
-	if (journal_is_empty == TRUE)
+	if (NVolLogFileEmpty(vol))
 		return 0;
-
 	ntfs_log_info("Going to empty the journal ($LogFile)... ");
 	if (ntfs_logfile_reset(vol)) {
 		ntfs_log_info(FAILED);
@@ -313,7 +281,6 @@
 		return -1;
 	}
 	ntfs_log_info(OK);
-	journal_is_empty = TRUE;
 	return 0;
 }
 
@@ -475,13 +442,13 @@
 
 	ntfs_log_info("Attempting to correct errors... ");
 
-	dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops, NULL);
+	dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
+			NULL);
 	if (!dev) {
 		ntfs_log_info(FAILED);
 		ntfs_log_perror("Failed to allocate device");
 		return -1;
 	}
-
 	vol = ntfs_volume_startup(dev, 0);
 	if (!vol) {
 		ntfs_log_info(FAILED);
@@ -490,17 +457,12 @@
 		ntfs_device_free(dev);
 		return -1;
 	}
-
 	if (fix_mftmirr(vol) < 0)
 		goto error_exit;
-
-	/* FIXME: Will this fail?  Probably... */
 	if (set_dirty_flag(vol) < 0)
 		goto error_exit;
-
 	if (empty_journal(vol) < 0)
 		goto error_exit;
-
 	ret = 0;
 error_exit:
 	/* ntfs_umount() will invoke ntfs_device_free() for us. */
@@ -550,7 +512,8 @@
 			exit(1);
 		}
 	}
-
+	/* So the unmount does not clear it again. */
+	NVolSetWasDirty(vol);
 	/* Check NTFS version is ok for us (in $Volume) */
 	ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
 			vol->minor_ver);
@@ -558,22 +521,13 @@
 		ntfs_log_error("Error: Unknown NTFS version.\n");
 		goto error_exit;
 	}
-
-	if (set_dirty_flag_mount(vol) < 0)
-		goto error_exit;
-
-	if (empty_journal(vol) < 0)
-		goto error_exit;
-
 	if (vol->major_ver >= 3) {
-	/* FIXME: If on NTFS 3.0+, check for presence of the usn journal and
-	   disable it (if present) as Win2k might be unhappy otherwise and Bad
-	   Things(TM) could happen depending on what applications are actually
-	   using it for. */
+		/*
+		 * FIXME: If on NTFS 3.0+, check for presence of the usn
+		 * journal and stamp it if present.
+		 */
 	}
-
-	/* FIXME: Should we be marking the quota out of date, too? */
-
+	/* FIXME: We should be marking the quota out of date, too. */
 	/* That's all for now! */
 	ntfs_log_info("NTFS partition %s was processed successfully.\n",
 			vol->dev->d_name);
Index: ntfsprogs/ntfsinfo.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsinfo.c,v
retrieving revision 1.154
retrieving revision 1.155
diff -u -r1.154 -r1.155
--- ntfsprogs/ntfsinfo.c	25 Nov 2006 18:38:47 -0000	1.154
+++ ntfsprogs/ntfsinfo.c	28 Nov 2006 10:09:57 -0000	1.155
@@ -1165,7 +1165,7 @@
 			runlist *rlc = rl;
 			printf("\tRunlist:\tVCN\t\tLCN\t\tLength\n");
 			while (rlc->length) {
-				printf("\t\t\t%lld\t\t%lld\t\t%lld\n",
+				printf("\t\t\t0x%llx\t\t0x%llx\t\t0x%llx\n",
 					rlc->vcn, rlc->lcn, rlc->length);
 				rlc++;
 			}
Index: ntfsprogs/ntfsmove.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsmove.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- ntfsprogs/ntfsmove.c	12 Nov 2006 22:46:50 -0000	1.24
+++ ntfsprogs/ntfsmove.c	28 Nov 2006 10:09:57 -0000	1.25
@@ -889,10 +889,7 @@
 
 	count = move_file(vol, inode, opts.location, 0);
 	if ((count > 0) && (!opts.nodirty)) {
-		if (ntfs_volume_write_flags(vol, vol->flags | VOLUME_IS_DIRTY) <
-				0) {
-			ntfs_log_error("Couldn't mark volume dirty\n");
-		}
+		NVolSetWasDirty(vol);
 		ntfs_log_info("Relocated %lld bytes\n", count);
 	}
 	if (count >= 0)
Index: ntfsprogs/ntfsresize.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfsresize.c,v
retrieving revision 1.123
retrieving revision 1.124
diff -u -r1.123 -r1.124
--- ntfsprogs/ntfsresize.c	12 Nov 2006 22:46:50 -0000	1.123
+++ ntfsprogs/ntfsresize.c	28 Nov 2006 10:09:57 -0000	1.124
@@ -2256,7 +2256,7 @@
 		exit(1);
 	}
 
-	if (vol->flags & VOLUME_IS_DIRTY)
+	if (NVolWasDirty(vol))
 		if (opt.force-- <= 0)
 			err_exit("Volume is scheduled for check.\nRun chkdsk /f"
 				 " and please try again, or see option -f.\n");
@@ -2280,32 +2280,16 @@
 /**
  * prepare_volume_fixup
  *
- * Set the volume's dirty flag and wipe the filesystem journal.  When Windows
- * boots it will automatically run chkdsk to check for any problems.  If the
- * read-only command line option was given, this function will do nothing.
+ * Make sure the volume's dirty flag does not get cleared at umount time.  When
+ * Windows boots it will automatically run chkdsk to check for any problems.
+ * If the read-only command line option was given, this function will do
+ * nothing.
  */
 static void prepare_volume_fixup(ntfs_volume *vol)
 {
-	u16 flags;
-
-	flags = vol->flags | VOLUME_IS_DIRTY;
-	if (vol->major_ver >= 2)
-		flags |= VOLUME_MOUNTED_ON_NT4;
-
 	printf("Schedule chkdsk for NTFS consistency check at Windows "
 		"boot time ...\n");
-
-	if (ntfs_volume_write_flags(vol, flags))
-		perr_exit("Failed to set $Volume dirty");
-
-	if (vol->dev->d_ops->sync(vol->dev) == -1)
-		perr_exit("Failed to sync device");
-
-	printf("Resetting $LogFile ... (this might take a while)\n");
-
-	if (ntfs_logfile_reset(vol))
-		perr_exit("Failed to reset $LogFile");
-
+	NVolSetWasDirty(vol);
 	if (vol->dev->d_ops->sync(vol->dev) == -1)
 		perr_exit("Failed to sync device");
 }
Index: ntfsprogs/ntfswipe.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/ntfswipe.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- ntfsprogs/ntfswipe.c	12 Nov 2006 22:46:51 -0000	1.45
+++ ntfsprogs/ntfswipe.c	28 Nov 2006 10:09:57 -0000	1.46
@@ -1346,7 +1346,7 @@
 	if (!vol)
 		goto free;
 
-	if ((vol->flags & VOLUME_IS_DIRTY) && (!opts.force))
+	if (NVolWasDirty(vol) && !opts.force)
 		goto umount;
 
 	if (opts.info) {
Index: ntfsprogs/utils.c
===================================================================
RCS file: /cvs/linux-ntfs/ntfsprogs/ntfsprogs/utils.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -r1.69 -r1.70
--- ntfsprogs/utils.c	25 Nov 2006 21:44:36 -0000	1.69
+++ ntfsprogs/utils.c	28 Nov 2006 10:09:57 -0000	1.70
@@ -196,7 +196,7 @@
 		return NULL;
 	}
 
-	if (vol->flags & VOLUME_IS_DIRTY) {
+	if (NVolWasDirty(vol)) {
		ntfs_log_warning("Volume is dirty.\n");
		if (!force) {
			ntfs_log_error("Run chkdsk and try again, or use the "
					"force option.\n");