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 - 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 - 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?= +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 ++#include ++#include ++ ++#ifdef HAVE_LIMITS_H ++#include ++#endif ++#ifdef HAVE_CTYPE_H ++#include ++#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/" ++ * ++ * Since 2.6.29 (patch 784aae735d9b0bba3f8b9faef4c8b30df3bf0128) kernel sysfs ++ * provides the real DM device names in /sys/block//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 "\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