[ntfs-3g] fix ntfsfix, ntfsck, make fsck.ntfs symlink, fix errors with certain volume types

Tom Callaway spot at fedoraproject.org
Wed Sep 7 14:43:14 UTC 2011


commit 41564fbb78d511939b1f7b046dc6b40fd9f7eb4b
Author: Tom "spot" Callaway <tcallawa at redhat.com>
Date:   Wed Sep 7 10:43:02 2011 -0400

    fix ntfsfix, ntfsck, make fsck.ntfs symlink, fix errors with certain volume types

 ntfs-3g.spec                                       |   23 ++-
 ...-571dbc5784af042c94ed0f025c4d2d842c591d1f.patch |  362 ++++++++++++++++++++
 ntfsprogs-ntfsck-cleanups-from-git.patch           |  344 +++++++++++++++++++
 ntfsprogs-ntfsfix-cleanups-from-git.patch          |  152 ++++++++
 4 files changed, 880 insertions(+), 1 deletions(-)
---
diff --git a/ntfs-3g.spec b/ntfs-3g.spec
index cbea316..54a309e 100644
--- a/ntfs-3g.spec
+++ b/ntfs-3g.spec
@@ -8,7 +8,7 @@
 Name:		ntfs-3g
 Summary:	Linux NTFS userspace driver
 Version:	2011.4.12
-Release:	3%{?dist}
+Release:	4%{?dist}
 License:	GPLv2+
 Group:		System Environment/Base
 Source0:	http://tuxera.com/opensource/%{name}_ntfsprogs-%{version}%{?subver}.tgz
@@ -27,6 +27,14 @@ Obsoletes:	ntfsprogs-fuse
 Provides:	fuse-ntfs-3g = %{epoch}:%{version}-%{release}
 Patch0:		ntfs-3g-2011.4.12-ntfsprogs-header-fix.patch
 Patch1:		ntfs-3g_ntfsprogs-2011.4.12-enable-extras-option-full.patch
+# http://ntfs-3g.git.sourceforge.net/git/gitweb.cgi?p=ntfs-3g/ntfs-3g_ntfsprogs;a=commit;h=571dbc5784af042c94ed0f025c4d2d842c591d1f
+# https://bugzilla.redhat.com/show_bug.cgi?id=735862
+Patch2:		ntfs-3g_ntfsprogs-571dbc5784af042c94ed0f025c4d2d842c591d1f.patch
+# http://ntfs-3g.git.sourceforge.net/git/gitweb.cgi?p=ntfs-3g/ntfs-3g_ntfsprogs;a=blobdiff;f=ntfsprogs/ntfsck.c;h=0964a4de57a385308f9b5bf61b04b25812e17b7f;hp=ff6946dfe286a87e0dafd4c6a509a8b7bc69625e;hb=HEAD;hpb=0289d1a6c31942609b96fdf2c1baeb7355fee2bc
+Patch3:		ntfsprogs-ntfsck-cleanups-from-git.patch
+# http://ntfs-3g.git.sourceforge.net/git/gitweb.cgi?p=ntfs-3g/ntfs-3g_ntfsprogs;a=blobdiff;f=ntfsprogs/ntfsfix.c;h=9b3d5eeb368ff85fa6ef3c18b44c2dcc2ba5ea07;hp=97a14a59b6318c0f2baa1c7a111bde3254e42d5a;hb=HEAD;hpb=44116675cad2055b326a9ac797c5105d78896475
+# bz 711662, 723562
+Patch4:		ntfsprogs-ntfsfix-cleanups-from-git.patch
 
 %description
 NTFS-3G is a stable, open source, GPL licensed, POSIX, read/write NTFS 
@@ -69,6 +77,10 @@ included utilities see man 8 ntfsprogs after installation).
 %setup -q -n %{name}_ntfsprogs-%{version}%{?subver}
 %patch0 -p1 -b .header-fix
 %patch1 -p1 -b .enable-extras
+%patch2 -p1 -b .735862
+%patch3 -p1 -b .fsckfixes
+%patch4 -p1 -b .ntfsfixfixes
+autoreconf -if
 
 %build
 CFLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64"
@@ -105,6 +117,8 @@ ln -s mount.ntfs-3g mount.ntfs-fuse
 # And since there is no other package in Fedora that provides an ntfs 
 # mount...
 ln -s mount.ntfs-3g mount.ntfs
+# Need this for fsck to find it
+ln -s ../ntfsck fsck.ntfs
 popd
 
 # Compat symlinks
@@ -168,6 +182,7 @@ cp -a %{SOURCE1} %{buildroot}%{_datadir}/hal/fdi/policy/10osvendor/
 /bin/ntfsmove
 /bin/ntfstruncate
 /bin/ntfswipe
+/sbin/fsck.ntfs
 /sbin/mkfs.ntfs
 /sbin/mkntfs
 /sbin/ntfsclone
@@ -180,6 +195,12 @@ cp -a %{SOURCE1} %{buildroot}%{_datadir}/hal/fdi/policy/10osvendor/
 %{_mandir}/man8/ntfs[^m][^o]*.8*
 
 %changelog
+* Wed Sep  7 2011 Tom Callaway <spot at fedoraproject.org> - 2:2011.4.12-4
+- fix issue preventing some volume types from not working properly (bz735862)
+- create fsck.ntfs symlink to ntfsck (bz735612).
+- apply cleanups from git trunk for ntfsck (bz 706638)
+- apply cleanups from git trunk for ntfsfix (bz 711662, 723562)
+
 * Mon May  9 2011 Tom Callaway <spot at fedoraproject.org> - 2:2011.4.12-3
 - add Obsoletes to resolve multi-lib upgrade issue (bz702671)
 
diff --git a/ntfs-3g_ntfsprogs-571dbc5784af042c94ed0f025c4d2d842c591d1f.patch b/ntfs-3g_ntfsprogs-571dbc5784af042c94ed0f025c4d2d842c591d1f.patch
new file mode 100644
index 0000000..cd89863
--- /dev/null
+++ b/ntfs-3g_ntfsprogs-571dbc5784af042c94ed0f025c4d2d842c591d1f.patch
@@ -0,0 +1,362 @@
+From 571dbc5784af042c94ed0f025c4d2d842c591d1f Mon Sep 17 00:00:00 2001
+From: =?utf8?q?Jean-Pierre=20Andr=C3=A9?= <jpandre at users.sourceforge.net>
+Date: Tue, 5 Jul 2011 12:17:12 +0200
+Subject: [PATCH] Fixed device path canonicalization for use by devmapper (basilinya)
+
+For some reason, when the monted device is "/dev/mapper/*", a record
+in the form "/dev/dm-*" ends up in /etc/mtab and the device cannot be
+unmounted.
+
+The reason is unclear, the /dev/mapper name is not a symlink, and the
+function doing the name change is not known. No detailed feedback from
+the users having met the issue.
+
+The patch changes the name back to the /dev/mapper name after realpath()
+is called, and, if there is an actual change, both the name passed to
+ntfs-3g and the one passed to fuse and mount are logged in the hope
+of getting a clue about what is happening.
+
+But ntfs-3g is probably not the right place for a fix.
+---
+ include/ntfs-3g/Makefile.am |    1 +
+ include/ntfs-3g/param.h     |    5 ++
+ include/ntfs-3g/realpath.h  |   24 ++++++++++
+ libntfs-3g/Makefile.am      |    1 +
+ libntfs-3g/realpath.c       |  103 +++++++++++++++++++++++++++++++++++++++++++
+ libntfs-3g/volume.c         |   17 +------
+ src/lowntfs-3g.c            |   13 +----
+ src/ntfs-3g.c               |   13 +----
+ src/ntfs-3g_common.c        |    5 ++-
+ src/ntfs-3g_common.h        |    1 +
+ 10 files changed, 148 insertions(+), 35 deletions(-)
+ create mode 100644 include/ntfs-3g/realpath.h
+ create mode 100644 libntfs-3g/realpath.c
+
+diff --git a/include/ntfs-3g/Makefile.am b/include/ntfs-3g/Makefile.am
+index 6067346..33343df 100644
+--- a/include/ntfs-3g/Makefile.am
++++ b/include/ntfs-3g/Makefile.am
+@@ -29,6 +29,7 @@ headers = \
+ 	ntfstime.h	\
+ 	object_id.h	\
+ 	param.h	\
++	realpath.h	\
+ 	reparse.h	\
+ 	runlist.h	\
+ 	security.h	\
+diff --git a/include/ntfs-3g/param.h b/include/ntfs-3g/param.h
+index 57d122e..985fdb7 100644
+--- a/include/ntfs-3g/param.h
++++ b/include/ntfs-3g/param.h
+@@ -63,6 +63,11 @@ enum {
+ 
+ #define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */
+ 
++/*
++ *		Parameters for path canonicalization
++ */
++
++#define MAPPERNAMELTH 256
+ 
+ /*
+  *		Permission checking modes for high level and low level
+diff --git a/include/ntfs-3g/realpath.h b/include/ntfs-3g/realpath.h
+new file mode 100644
+index 0000000..970d2af
+--- /dev/null
++++ b/include/ntfs-3g/realpath.h
+@@ -0,0 +1,24 @@
++/*
++ * realpath.h - realpath() aware of device mapper
++ */
++
++#ifndef REALPATH_H
++#define REALPATH_H
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#ifdef HAVE_REALPATH
++#define ntfs_realpath realpath
++#else
++extern char *ntfs_realpath(const char *path, char *resolved_path);
++#endif
++
++#ifdef linux
++extern char *ntfs_realpath_canonicalize(const char *path, char *resolved_path);
++#else
++#define ntfs_realpath_canonicalize ntfs_realpath
++#endif
++
++#endif /* REALPATH_H */
+diff --git a/libntfs-3g/Makefile.am b/libntfs-3g/Makefile.am
+index 292233a..b84cf64 100644
+--- a/libntfs-3g/Makefile.am
++++ b/libntfs-3g/Makefile.am
+@@ -36,6 +36,7 @@ libntfs_3g_la_SOURCES =	\
+ 	misc.c 		\
+ 	mst.c 		\
+ 	object_id.c 	\
++	realpath.c	\
+ 	reparse.c 	\
+ 	runlist.c 	\
+ 	security.c 	\
+diff --git a/libntfs-3g/realpath.c b/libntfs-3g/realpath.c
+new file mode 100644
+index 0000000..a93bc69
+--- /dev/null
++++ b/libntfs-3g/realpath.c
+@@ -0,0 +1,103 @@
++/*
++ * realpath.c - realpath() aware of device mapper
++ * Originated from the util-linux project.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++
++#ifdef HAVE_LIMITS_H
++#include <limits.h>
++#endif
++#ifdef HAVE_CTYPE_H
++#include <ctype.h>
++#endif
++
++#include "param.h"
++#include "realpath.h"
++
++/* If there is no realpath() on the system, provide a dummy one. */
++#ifndef HAVE_REALPATH
++char *ntfs_realpath(const char *path, char *resolved_path)
++{
++       strncpy(resolved_path, path, PATH_MAX);
++       resolved_path[PATH_MAX] = '\0';
++       return resolved_path;
++}
++#endif
++
++
++#ifdef linux
++
++/*
++ * Converts private "dm-N" names to "/dev/mapper/<name>"
++ *
++ * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs
++ * provides the real DM device names in /sys/block/<ptname>/dm/name
++ */
++static char *
++canonicalize_dm_name(const char *ptname, char *canonical)
++{
++	FILE	*f;
++	size_t	sz;
++	char	path[MAPPERNAMELTH + 24];
++	char	name[MAPPERNAMELTH + 16];
++	char	*res = NULL;
++
++	snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptname);
++	if (!(f = fopen(path, "r")))
++		return NULL;
++
++	/* read "<name>\n" from sysfs */
++	if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
++		name[sz - 1] = '\0';
++		snprintf(path, sizeof(path), "/dev/mapper/%s", name);
++		res = strcpy(canonical, path);
++	}
++	fclose(f);
++	return res;
++}
++
++/*
++ *		Canonicalize a device path
++ *
++ *	Workaround from "basinilya" for fixing device mapper paths.
++ *
++ *  Background (Phillip Susi, 2011-04-09)
++ *	- ntfs-3g canonicalizes the device name so that if you mount with
++ *	  /dev/mapper/foo, the device name listed in mtab is /dev/dm-n,
++ *	  so you can not umount /dev/mapper/foo
++ *	- umount won't even recognize and translate /dev/dm-n to the mount
++ *	  point, apparently because of the '-' involved. Editing mtab and
++ *	  removing the '-' allows you to umount /dev/dmn successfully.
++ *
++ *	This code restores the devmapper name after canonicalization,
++ *	until a proper fix is implemented.
++ */
++
++char *ntfs_realpath_canonicalize(const char *path, char *canonical)
++{
++	char *p;
++
++	if (path == NULL)
++		return NULL;
++
++	if (!ntfs_realpath(path, canonical))
++		return NULL;
++
++	p = strrchr(canonical, '/');
++	if (p && strncmp(p, "/dm-", 4) == 0 && isdigit(*(p + 4))) {
++		p = canonicalize_dm_name(p+1, canonical);
++		if (p)
++			return p;
++	}
++
++	return canonical;
++}
++
++#endif
+diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c
+index 28e4c90..ca30585 100644
+--- a/libntfs-3g/volume.c
++++ b/libntfs-3g/volume.c
+@@ -67,6 +67,7 @@
+ #include "dir.h"
+ #include "logging.h"
+ #include "cache.h"
++#include "realpath.h"
+ #include "misc.h"
+ 
+ const char *ntfs_home = 
+@@ -1359,18 +1360,6 @@ int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused)))
+ 
+ #ifdef HAVE_MNTENT_H
+ 
+-#ifndef HAVE_REALPATH
+-/**
+- * realpath - If there is no realpath on the system
+- */
+-static char *realpath(const char *path, char *resolved_path)
+-{
+-	strncpy(resolved_path, path, PATH_MAX);
+-	resolved_path[PATH_MAX] = '\0';
+-	return resolved_path;
+-}
+-#endif
+-
+ /**
+  * ntfs_mntent_check - desc
+  *
+@@ -1394,7 +1383,7 @@ static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
+ 		err = errno;
+ 		goto exit;
+ 	}
+-	if (!realpath(file, real_file)) {
++	if (!ntfs_realpath_canonicalize(file, real_file)) {
+ 		err = errno;
+ 		goto exit;
+ 	}
+@@ -1403,7 +1392,7 @@ static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
+ 		goto exit;
+ 	}
+ 	while ((mnt = getmntent(f))) {
+-		if (!realpath(mnt->mnt_fsname, real_fsname))
++		if (!ntfs_realpath_canonicalize(mnt->mnt_fsname, real_fsname))
+ 			continue;
+ 		if (!strcmp(real_file, real_fsname))
+ 			break;
+diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c
+index aeadb17..9fa177f 100644
+--- a/src/lowntfs-3g.c
++++ b/src/lowntfs-3g.c
+@@ -3457,16 +3457,6 @@ static void usage(void)
+ 			EXEC_NAME, ntfs_home);
+ }
+ 
+-#ifndef HAVE_REALPATH
+-/* If there is no realpath() on the system, provide a dummy one. */
+-static char *realpath(const char *path, char *resolved_path)
+-{
+-	strncpy(resolved_path, path, PATH_MAX);
+-	resolved_path[PATH_MAX] = '\0';
+-	return resolved_path;
+-}
+-#endif
+-
+ #if defined(linux) || defined(__uClinux__)
+ 
+ static const char *dev_fuse_msg =
+@@ -3668,6 +3658,9 @@ static void setup_logging(char *parsed_options)
+ 	ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
+ 
+ 	ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
++	if (strcmp(opts.arg_device,opts.device))
++		ntfs_log_info("Requested device %s canonicalized as %s\n",
++				opts.arg_device,opts.device);
+ 	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
+ 			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
+ 			ctx->vol->vol_name, ctx->vol->major_ver,
+diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c
+index 80c084d..956f04d 100644
+--- a/src/ntfs-3g.c
++++ b/src/ntfs-3g.c
+@@ -3372,16 +3372,6 @@ static void usage(void)
+ 			EXEC_NAME, ntfs_home);
+ }
+ 
+-#ifndef HAVE_REALPATH
+-/* If there is no realpath() on the system, provide a dummy one. */
+-static char *realpath(const char *path, char *resolved_path)
+-{
+-	strncpy(resolved_path, path, PATH_MAX);
+-	resolved_path[PATH_MAX] = '\0';
+-	return resolved_path;
+-}
+-#endif
+-
+ #if defined(linux) || defined(__uClinux__)
+ 
+ static const char *dev_fuse_msg =
+@@ -3588,6 +3578,9 @@ static void setup_logging(char *parsed_options)
+ 	ctx->seccache = (struct PERMISSIONS_CACHE*)NULL;
+ 
+ 	ntfs_log_info("Version %s %s %d\n", VERSION, FUSE_TYPE, fuse_version());
++	if (strcmp(opts.arg_device,opts.device))
++		ntfs_log_info("Requested device %s canonicalized as %s\n",
++				opts.arg_device,opts.device);
+ 	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",
+ 			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",
+ 			ctx->vol->vol_name, ctx->vol->major_ver,
+diff --git a/src/ntfs-3g_common.c b/src/ntfs-3g_common.c
+index 1ec24e0..b246b9c 100644
+--- a/src/ntfs-3g_common.c
++++ b/src/ntfs-3g_common.c
+@@ -47,6 +47,7 @@
+ #include "security.h"
+ #include "xattrs.h"
+ #include "ntfs-3g_common.h"
++#include "realpath.h"
+ #include "misc.h"
+ 
+ const char xattr_ntfs_3g[] = "ntfs-3g.";
+@@ -509,7 +510,9 @@ int ntfs_parse_options(struct ntfs_options *popts, void (*usage)(void),
+ 					return -1;
+ 				
+ 				/* Canonicalize device name (mtab, etc) */
+-				if (!realpath(optarg, popts->device)) {
++				popts->arg_device = optarg;
++				if (!ntfs_realpath_canonicalize(optarg,
++						popts->device)) {
+ 					ntfs_log_perror("%s: Failed to access "
+ 					     "volume '%s'", EXEC_NAME, optarg);
+ 					free(popts->device);
+diff --git a/src/ntfs-3g_common.h b/src/ntfs-3g_common.h
+index 383dbe0..978569d 100644
+--- a/src/ntfs-3g_common.h
++++ b/src/ntfs-3g_common.h
+@@ -29,6 +29,7 @@ struct ntfs_options {
+         char    *mnt_point;     /* Mount point */    
+         char    *options;       /* Mount options */  
+         char    *device;        /* Device to mount */
++	char	*arg_device;	/* Device requested in argv */
+ } ;
+ 
+ typedef enum {
+-- 
+1.7.4.1
+
diff --git a/ntfsprogs-ntfsck-cleanups-from-git.patch b/ntfsprogs-ntfsck-cleanups-from-git.patch
new file mode 100644
index 0000000..0fc6ba3
--- /dev/null
+++ b/ntfsprogs-ntfsck-cleanups-from-git.patch
@@ -0,0 +1,344 @@
+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))
diff --git a/ntfsprogs-ntfsfix-cleanups-from-git.patch b/ntfsprogs-ntfsfix-cleanups-from-git.patch
new file mode 100644
index 0000000..bd5d853
--- /dev/null
+++ b/ntfsprogs-ntfsfix-cleanups-from-git.patch
@@ -0,0 +1,152 @@
+diff -up ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsfix.c.ntfsfixfixes ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsfix.c
+--- ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsfix.c.ntfsfixfixes	2011-04-10 14:04:41.000000000 -0400
++++ ntfs-3g_ntfsprogs-2011.4.12/ntfsprogs/ntfsfix.c	2011-09-07 10:18:48.367406438 -0400
+@@ -93,6 +93,7 @@ static const char FAILED[]   = "FAILED\n
+ static struct {
+ 	char *volume;
+ 	BOOL no_action;
++	BOOL clear_bad_sectors;
+ } opt;
+ 
+ /**
+@@ -106,9 +107,10 @@ static void usage(void)
+ 		   "Usage: %s [options] device\n"
+ 		   "    Attempt to fix an NTFS partition.\n"
+ 		   "\n"
+-		   "    -h, --help             Display this help\n"
+-		   "    -n, --no-action        Do not write anything\n"
+-		   "    -V, --version          Display version information\n"
++		   "    -b, --clear-bad-sectors Clear the bad sector list\n"
++		   "    -h, --help              Display this help\n"
++		   "    -n, --no-action         Do not write anything\n"
++		   "    -V, --version           Display version information\n"
+ 		   "\n"
+ 		   "For example: %s /dev/hda6\n\n",
+ 		   EXEC_NAME, VERSION, EXEC_NAME,
+@@ -127,7 +129,8 @@ static void version(void)
+ 		   "Attempt to fix an NTFS partition.\n\n"
+ 		   "Copyright (c) 2000-2006 Anton Altaparmakov\n"
+ 		   "Copyright (c) 2002-2006 Szabolcs Szakacsits\n"
+-		   "Copyright (c) 2007      Yura Pakhuchiy\n\n",
++		   "Copyright (c) 2007      Yura Pakhuchiy\n\n"
++		   "Copyright (c) 2011      Jean-Pierre Andre\n\n",
+ 		   EXEC_NAME, VERSION);
+ 	ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
+ 	exit(1);
+@@ -139,12 +142,13 @@ static void version(void)
+ static void parse_options(int argc, char **argv)
+ {
+ 	int c;
+-	static const char *sopt = "-hnV";
++	static const char *sopt = "-bhnV";
+ 	static const struct option lopt[] = {
+-		{ "help",	no_argument,	NULL, 'h' },
+-		{ "no-action",	no_argument,	NULL, 'n' },
+-		{ "version",	no_argument,	NULL, 'V' },
+-		{ NULL, 0, NULL, 0 }
++		{ "help",		no_argument,	NULL, 'h' },
++		{ "no-action",		no_argument,	NULL, 'n' },
++		{ "clear-bad-sectors",	no_argument,	NULL, 'b' },
++		{ "version",		no_argument,	NULL, 'V' },
++		{ NULL, 		0, NULL, 0 }
+ 	};
+ 
+ 	memset(&opt, 0, sizeof(opt));
+@@ -159,6 +163,9 @@ static void parse_options(int argc, char
+ 				usage();
+ 			}
+ 			break;
++		case 'b':
++			opt.clear_bad_sectors = TRUE;
++			break;
+ 		case 'n':
+ 			opt.no_action = TRUE;
+ 			break;
+@@ -306,6 +313,57 @@ static int empty_journal(ntfs_volume *vo
+ }
+ 
+ /**
++ *		Clear the bad cluster marks (option)
++ */
++static int clear_badclus(ntfs_volume *vol)
++{
++	static ntfschar badstream[] = {
++				const_cpu_to_le16('$'), const_cpu_to_le16('B'),
++				const_cpu_to_le16('a'), const_cpu_to_le16('d')
++	} ;
++	ntfs_inode *ni;
++	ntfs_attr *na;
++	BOOL ok;
++
++	ok = FALSE;
++	ntfs_log_info("Going to un-mark the bad clusters ($BadClus)... ");
++	ni = ntfs_inode_open(vol, FILE_BadClus);
++	if (ni) {
++		na = ntfs_attr_open(ni, AT_DATA, badstream, 4);
++		if (na) {
++			if (na->initialized_size) {
++			/*
++			 * Truncate the stream to free all its clusters,
++			 * then reallocate a sparse stream to full size
++			 * of volume.
++			 */
++				if (!ntfs_attr_truncate(na,0)
++				    && !ntfs_attr_truncate(na,vol->nr_clusters
++						<< vol->cluster_size_bits)) {
++					ni->flags |= FILE_ATTR_SPARSE_FILE;
++					NInoFileNameSetDirty(ni);
++					ok = TRUE;
++				} else {
++					ntfs_log_perror("Failed to un-mark the bad clusters");
++				}
++			} else {
++				ntfs_log_info("No bad clusters...");
++				ok = TRUE;
++			}
++			ntfs_attr_close(na);
++		} else {
++			ntfs_log_perror("Failed to open $BadClus::$Bad");
++		}
++		ntfs_inode_close(ni);
++	} else {
++		ntfs_log_perror("Failed to open inode FILE_BadClus");
++	}
++	if (ok)
++		ntfs_log_info(OK);
++	return (ok ? 0 : -1);
++}
++
++/**
+  * fix_mftmirr
+  */
+ static int fix_mftmirr(ntfs_volume *vol)
+@@ -767,6 +825,7 @@ static int fix_startup(struct ntfs_devic
+ 	errno = 0;
+ 	res = -1;
+ 	dev_open = FALSE;
++	full_bs = (char*)NULL;
+ 	if (!dev || !dev->d_ops || !dev->d_name) {
+ 		errno = EINVAL;
+ 		ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
+@@ -847,7 +906,7 @@ error_exit:
+ 		}
+ 	}
+ 	eo = errno;
+-	free(bs);
++	free(full_bs);
+ 	if (vol) {
+ 		free(vol->upcase);
+ 		free(vol);
+@@ -985,6 +1044,12 @@ int main(int argc, char **argv)
+ 		ntfs_log_error("Error: Unknown NTFS version.\n");
+ 		goto error_exit;
+ 	}
++	if (opt.clear_bad_sectors && !opt.no_action) {
++		if (clear_badclus(vol)) {
++			ntfs_log_error("Error: Failed to un-mark bad sectors.\n");
++			goto error_exit;
++		}
++	}
+ 	if (vol->major_ver >= 3) {
+ 		/*
+ 		 * FIXME: If on NTFS 3.0+, check for presence of the usn


More information about the scm-commits mailing list