parent
07688d0327
commit
41564fbb78
@ -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…
Reference in new issue