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

epel9
Tom "spot" Callaway 14 years ago
parent 07688d0327
commit 41564fbb78

@ -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@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@fedoraproject.org> - 2:2011.4.12-3
- add Obsoletes to resolve multi-lib upgrade issue (bz702671)

@ -0,0 +1,362 @@
From 571dbc5784af042c94ed0f025c4d2d842c591d1f Mon Sep 17 00:00:00 2001
From: =?utf8?q?Jean-Pierre=20Andr=C3=A9?= <jpandre@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

@ -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))

@ -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
Loading…
Cancel
Save