From 8a1358fff439d2fe464ab67ba5d5394060880457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Wed, 6 Apr 2016 09:51:47 +0200 Subject: [PATCH] Enabled fallback to read-only mount when volume is hibernated When a volume is found hibernated (or prepared for fast restarting), it is force-mounted as read-only. --- include/ntfs-3g/volume.h | 1 + libntfs-3g/volume.c | 42 ++++++++++++++++++++++++++++++---------- src/lowntfs-3g.c | 2 ++ src/ntfs-3g.c | 2 ++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/include/ntfs-3g/volume.h b/include/ntfs-3g/volume.h index 2720864c..cee91e21 100644 --- a/include/ntfs-3g/volume.h +++ b/include/ntfs-3g/volume.h @@ -60,6 +60,7 @@ typedef struct _ntfs_volume ntfs_volume; enum { NTFS_MNT_NONE = 0x00000000, NTFS_MNT_RDONLY = 0x00000001, + NTFS_MNT_MAY_RDONLY = 0x02000000, /* Allow fallback to ro */ NTFS_MNT_FORENSIC = 0x04000000, /* No modification during * mount. */ NTFS_MNT_EXCLUSIVE = 0x08000000, diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c index 916f1c02..4861d2f8 100644 --- a/libntfs-3g/volume.c +++ b/libntfs-3g/volume.c @@ -97,6 +97,11 @@ static const char *hibernated_volume_msg = "Windows fully (no hibernation or fast restarting), or mount the volume\n" "read-only with the 'ro' mount option.\n"; +static const char *fallback_readonly_msg = +"Falling back to read-only mount because the NTFS partition is in an\n" +"unsafe state. Please resume and shutdown Windows fully (no hibernation\n" +"or fast restarting.)\n"; + static const char *unclean_journal_msg = "Write access is denied because the disk wasn't safely powered\n" "off and the 'norecover' mount option was specified.\n"; @@ -914,7 +919,9 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) int i, j, eo; unsigned int k; u32 u; + BOOL need_fallback_ro; + need_fallback_ro = FALSE; vol = ntfs_volume_startup(dev, flags); if (!vol) return NULL; @@ -1233,20 +1240,35 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) */ if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) { if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) && - ntfs_volume_check_hiberfile(vol, 1) < 0) - goto error_exit; + ntfs_volume_check_hiberfile(vol, 1) < 0) { + if (flags & NTFS_MNT_MAY_RDONLY) + need_fallback_ro = TRUE; + else + goto error_exit; + } if (ntfs_volume_check_logfile(vol) < 0) { /* Always reject cached metadata for now */ - if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM)) - goto error_exit; - ntfs_log_info("The file system wasn't safely " - "closed on Windows. Fixing.\n"); - if (ntfs_logfile_reset(vol)) - goto error_exit; + if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM)) { + if (flags & NTFS_MNT_MAY_RDONLY) + need_fallback_ro = TRUE; + else + goto error_exit; + } else { + ntfs_log_info("The file system wasn't safely " + "closed on Windows. Fixing.\n"); + if (ntfs_logfile_reset(vol)) + goto error_exit; + } } /* make $TXF_DATA resident if present on the root directory */ - if (fix_txf_data(vol)) - goto error_exit; + if (!(flags & NTFS_MNT_RDONLY) && !need_fallback_ro) { + if (fix_txf_data(vol)) + goto error_exit; + } + } + if (need_fallback_ro) { + NVolSetReadOnly(vol); + ntfs_log_error("%s", fallback_readonly_msg); } return vol; diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 899586c1..683ac0c6 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -3940,6 +3940,8 @@ static int ntfs_open(const char *device) flags |= NTFS_MNT_EXCLUSIVE; if (ctx->ro) flags |= NTFS_MNT_RDONLY; + else + flags |= NTFS_MNT_MAY_RDONLY; if (ctx->recover) flags |= NTFS_MNT_RECOVER; if (ctx->hiberfile) diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index e3a23e58..5b19b1dc 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -3744,6 +3744,8 @@ static int ntfs_open(const char *device) flags |= NTFS_MNT_EXCLUSIVE; if (ctx->ro) flags |= NTFS_MNT_RDONLY; + else + flags |= NTFS_MNT_MAY_RDONLY; if (ctx->recover) flags |= NTFS_MNT_RECOVER; if (ctx->hiberfile)