Android-x86
Fork
Spenden

  • R/O
  • HTTP
  • SSH
  • HTTPS

external-ntfs-3g: Commit

external/ntfs-3g


Commit MetaInfo

Revision23a4e18bfaa64a15019bee1960992bd51bd7363a (tree)
Zeit2019-02-22 01:33:58
AutorChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Log Message

Merge branch 'edge' of git://git.code.sf.net/p/ntfs-3g/ntfs-3g into oreo-x86

Ändern Zusammenfassung

Diff

--- a/include/ntfs-3g/compat.h
+++ b/include/ntfs-3g/compat.h
@@ -1,9 +1,10 @@
11 /*
2- * compat.h - Tweaks for Windows compatibility.
2+ * compat.h - Tweaks for compatibility with non-Linux systems.
33 *
44 * Copyright (c) 2002 Richard Russon
55 * Copyright (c) 2002-2004 Anton Altaparmakov
66 * Copyright (c) 2008-2009 Szabolcs Szakacsits
7+ * Copyright (c) 2019 Jean-Pierre Andre
78 *
89 * This program/include file is free software; you can redistribute it and/or
910 * modify it under the terms of the GNU General Public License as published
@@ -41,6 +42,10 @@
4142 #define ELIBBAD ENOEXEC
4243 #endif
4344
45+#ifndef ELIBACC
46+#define ELIBACC ENOENT
47+#endif
48+
4449 #ifndef PATH_MAX
4550 #define PATH_MAX 4096
4651 #endif
--- a/include/ntfs-3g/layout.h
+++ b/include/ntfs-3g/layout.h
@@ -2403,17 +2403,23 @@ typedef struct {
24032403 *
24042404 * 1. The least significant 16 bits (i.e. bits 0 to 15) specify the type of
24052405 * the reparse point.
2406- * 2. The 13 bits after this (i.e. bits 16 to 28) are reserved for future use.
2407- * 3. The most significant three bits are flags describing the reparse point.
2406+ * 2. The 12 bits after this (i.e. bits 16 to 27) are reserved for future use.
2407+ * 3. The most significant four bits are flags describing the reparse point.
24082408 * They are defined as follows:
2409+ * bit 28: Directory bit. If set, the directory is not a surrogate
2410+ * and can be used the usual way.
24092411 * bit 29: Name surrogate bit. If set, the filename is an alias for
24102412 * another object in the system.
24112413 * bit 30: High-latency bit. If set, accessing the first byte of data will
24122414 * be slow. (E.g. the data is stored on a tape drive.)
24132415 * bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User
24142416 * defined tags have to use zero here.
2417+ * 4. Moreover, on Windows 10 :
2418+ * Some flags may be used in bits 12 to 15 to further describe the
2419+ * reparse point.
24152420 */
24162421 typedef enum {
2422+ IO_REPARSE_TAG_DIRECTORY = const_cpu_to_le32(0x10000000),
24172423 IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000),
24182424 IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000),
24192425 IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000),
@@ -2436,10 +2442,12 @@ typedef enum {
24362442 IO_REPARSE_TAG_DFM = const_cpu_to_le32(0x80000016),
24372443 IO_REPARSE_TAG_WOF = const_cpu_to_le32(0x80000017),
24382444 IO_REPARSE_TAG_WCI = const_cpu_to_le32(0x80000018),
2445+ IO_REPARSE_TAG_CLOUD = const_cpu_to_le32(0x9000001A),
24392446 IO_REPARSE_TAG_GVFS = const_cpu_to_le32(0x9000001C),
24402447 IO_REPARSE_TAG_LX_SYMLINK = const_cpu_to_le32(0xA000001D),
24412448
24422449 IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xf000ffff),
2450+ IO_REPARSE_PLUGIN_SELECT = const_cpu_to_le32(0xffff0fff),
24432451 } PREDEFINED_REPARSE_TAGS;
24442452
24452453 /**
--- a/include/ntfs-3g/param.h
+++ b/include/ntfs-3g/param.h
@@ -40,6 +40,13 @@ enum {
4040 };
4141
4242 /*
43+ * Parameters for formatting
44+ */
45+
46+ /* Up to Windows 10, the cluster size was limited to 64K */
47+#define NTFS_MAX_CLUSTER_SIZE 2097152 /* Windows 10 Creators allows 2MB */
48+
49+/*
4350 * Parameters for compression
4451 */
4552
--- a/libfuse-lite/Makefile.am
+++ b/libfuse-lite/Makefile.am
@@ -7,7 +7,10 @@ endif
77
88 libfuse_lite_la_CFLAGS= \
99 $(AM_CFLAGS) \
10- $(LIBFUSE_LITE_CFLAGS) \
10+ $(LIBFUSE_LITE_CFLAGS)
11+
12+libfuse_lite_la_CPPFLAGS= \
13+ $(AM_CPPFLAGS) \
1114 -I$(top_srcdir)/include/fuse-lite
1215
1316 libfuse_lite_la_LIBADD = $(LIBFUSE_LITE_LIBS)
--- a/libfuse-lite/fuse.c
+++ b/libfuse-lite/fuse.c
@@ -134,7 +134,6 @@ struct fuse_dh {
134134 struct fuse *fuse;
135135 fuse_req_t req;
136136 char *contents;
137- int allocated;
138137 unsigned len;
139138 unsigned size;
140139 unsigned needlen;
@@ -2782,8 +2781,10 @@ static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
27822781 fuse_finish_interrupt(f, req, &d);
27832782 free(path);
27842783
2785- fuse_reply_ioctl(req, err, out_buf, out_bufsz);
2784+ if (err >= 0) { /* not an error */
2785+ fuse_reply_ioctl(req, err, out_buf, out_bufsz);
27862786 goto out;
2787+ }
27872788 err:
27882789 reply_err(req, err);
27892790 out:
--- a/libntfs-3g/Makefile.am
+++ b/libntfs-3g/Makefile.am
@@ -9,8 +9,8 @@ else
99 noinst_LTLIBRARIES = libntfs-3g.la
1010 endif
1111
12-libntfs_3g_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include/ntfs-3g
13-libntfs_3g_la_CPPFLAGS= $(AM_CPPFLAGS) $(LIBNTFS_CPPFLAGS)
12+libntfs_3g_la_CFLAGS = $(AM_CFLAGS)
13+libntfs_3g_la_CPPFLAGS= $(AM_CPPFLAGS) $(LIBNTFS_CPPFLAGS) -I$(top_srcdir)/include/ntfs-3g
1414 libntfs_3g_la_LIBADD = $(LIBNTFS_LIBS)
1515 libntfs_3g_la_LDFLAGS = -version-info $(LIBNTFS_3G_VERSION) -no-undefined
1616
--- a/libntfs-3g/bootsect.c
+++ b/libntfs-3g/bootsect.c
@@ -38,6 +38,7 @@
3838 #include <errno.h>
3939 #endif
4040
41+#include "param.h"
4142 #include "compat.h"
4243 #include "bootsect.h"
4344 #include "debug.h"
@@ -61,6 +62,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
6162 {
6263 u32 i;
6364 BOOL ret = FALSE;
65+ u16 sectors_per_cluster;
6466
6567 ntfs_log_debug("Beginning bootsector check.\n");
6668
@@ -83,15 +85,27 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
8385 case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
8486 break;
8587 default:
86- ntfs_log_error("Unexpected sectors per cluster value (%d).\n",
87- b->bpb.sectors_per_cluster);
88- goto not_ntfs;
88+ if ((b->bpb.sectors_per_cluster < 240)
89+ || (b->bpb.sectors_per_cluster > 249)) {
90+ if (b->bpb.sectors_per_cluster > 128)
91+ ntfs_log_error("Unexpected sectors"
92+ " per cluster value (code 0x%x)\n",
93+ b->bpb.sectors_per_cluster);
94+ else
95+ ntfs_log_error("Unexpected sectors"
96+ " per cluster value (%d).\n",
97+ b->bpb.sectors_per_cluster);
98+ goto not_ntfs;
99+ }
89100 }
90101
91102 ntfs_log_debug("Checking cluster size.\n");
92- i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
93- b->bpb.sectors_per_cluster;
94- if (i > 65536) {
103+ if (b->bpb.sectors_per_cluster > 128)
104+ sectors_per_cluster = 1 << (256 - b->bpb.sectors_per_cluster);
105+ else
106+ sectors_per_cluster = b->bpb.sectors_per_cluster;
107+ i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * sectors_per_cluster;
108+ if (i > NTFS_MAX_CLUSTER_SIZE) {
95109 ntfs_log_error("Unexpected cluster size (%d).\n", i);
96110 goto not_ntfs;
97111 }
@@ -171,7 +185,7 @@ static const char *last_sector_error =
171185 int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
172186 {
173187 s64 sectors;
174- u8 sectors_per_cluster;
188+ u16 sectors_per_cluster;
175189 s8 c;
176190
177191 /* We return -1 with errno = EINVAL on error. */
@@ -186,7 +200,10 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
186200 * below or equal the number_of_clusters) really belong in the
187201 * ntfs_boot_sector_is_ntfs but in this way we can just do this once.
188202 */
189- sectors_per_cluster = bs->bpb.sectors_per_cluster;
203+ if (bs->bpb.sectors_per_cluster > 128)
204+ sectors_per_cluster = 1 << (256 - bs->bpb.sectors_per_cluster);
205+ else
206+ sectors_per_cluster = bs->bpb.sectors_per_cluster;
190207 ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
191208 if (sectors_per_cluster & (sectors_per_cluster - 1)) {
192209 ntfs_log_error("sectors_per_cluster (%d) is not a power of 2."
--- a/libntfs-3g/inode.c
+++ b/libntfs-3g/inode.c
@@ -837,7 +837,7 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
837837 if (!err)
838838 err = errno;
839839 ntfs_log_perror("Failed to open inode %lld with index",
840- (long long)le64_to_cpu(fn->parent_directory));
840+ (long long)MREF_LE(fn->parent_directory));
841841 continue;
842842 }
843843 ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
@@ -1518,14 +1518,16 @@ int ntfs_inode_set_times(ntfs_inode *ni, const char *value, size_t size,
15181518 ntfs_attr_search_ctx *ctx;
15191519 STANDARD_INFORMATION *std_info;
15201520 FILE_NAME_ATTR *fn;
1521- const u64 *times;
1521+ u64 times[4];
15221522 ntfs_time now;
15231523 int cnt;
15241524 int ret;
15251525
15261526 ret = -1;
15271527 if ((size >= 8) && !(flags & XATTR_CREATE)) {
1528- times = (const u64*)value;
1528+ /* Copy, to avoid alignment issue encountered on ARM */
1529+ memcpy(times, value,
1530+ (size < sizeof(times) ? size : sizeof(times)));
15291531 now = ntfs_current_time();
15301532 /* update the standard information attribute */
15311533 ctx = ntfs_attr_get_search_ctx(ni, NULL);
--- a/libntfs-3g/ioctl.c
+++ b/libntfs-3g/ioctl.c
@@ -3,7 +3,7 @@
33 *
44 * This module is part of ntfs-3g library
55 *
6- * Copyright (c) 2014-2015 Jean-Pierre Andre
6+ * Copyright (c) 2014-2019 Jean-Pierre Andre
77 * Copyright (c) 2014 Red Hat, Inc.
88 *
99 * This program/include file is free software; you can redistribute it and/or
@@ -225,6 +225,24 @@ not_found:
225225 return 0;
226226 }
227227
228+static inline LCN align_up(ntfs_volume *vol, LCN lcn, u64 granularity)
229+{
230+ u64 aligned;
231+
232+ aligned = (lcn << vol->cluster_size_bits) + granularity - 1;
233+ aligned -= aligned % granularity;
234+ return (aligned >> vol->cluster_size_bits);
235+}
236+
237+static inline u64 align_down(ntfs_volume *vol, u64 count, u64 granularity)
238+{
239+ u64 aligned;
240+
241+ aligned = count << vol->cluster_size_bits;
242+ aligned -= aligned % granularity;
243+ return (aligned >> vol->cluster_size_bits);
244+}
245+
228246 #define FSTRIM_BUFSIZ 4096
229247
230248 /* Trim the filesystem.
@@ -255,11 +273,11 @@ static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
255273 * XXX We could fix these limitations in future.
256274 */
257275 if (start != 0 || len != (uint64_t)-1) {
258- ntfs_log_debug("fstrim: setting start or length is not supported\n");
276+ ntfs_log_error("fstrim: setting start or length is not supported\n");
259277 return -EINVAL;
260278 }
261279 if (minlen > vol->cluster_size) {
262- ntfs_log_debug("fstrim: minlen > cluster size is not supported\n");
280+ ntfs_log_error("fstrim: minlen > cluster size is not supported\n");
263281 return -EINVAL;
264282 }
265283
@@ -269,7 +287,7 @@ static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
269287 * different.
270288 */
271289 if (!NDevBlock(vol->dev)) {
272- ntfs_log_debug("fstrim: not supported for non-block-device\n");
290+ ntfs_log_error("fstrim: not supported for non-block-device\n");
273291 return -EOPNOTSUPP;
274292 }
275293
@@ -278,15 +296,12 @@ static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
278296 if (ret)
279297 return ret;
280298 if (discard_alignment != 0) {
281- ntfs_log_debug("fstrim: backing device is not aligned for discards\n");
282- return -EOPNOTSUPP;
283- }
284- if (discard_granularity > vol->cluster_size) {
285- ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n");
299+ ntfs_log_error("fstrim: backing device is not aligned for discards\n");
286300 return -EOPNOTSUPP;
287301 }
302+
288303 if (discard_max_bytes == 0) {
289- ntfs_log_debug("fstrim: backing device does not support discard (discard_max_bytes == 0)\n");
304+ ntfs_log_error("fstrim: backing device does not support discard (discard_max_bytes == 0)\n");
290305 return -EOPNOTSUPP;
291306 }
292307
@@ -323,11 +338,14 @@ static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
323338 }
324339
325340 /* Trim the clusters in large as possible blocks, but
326- * not larger than discard_max_bytes.
341+ * not larger than discard_max_bytes, and compatible
342+ * with the supported trim granularity.
327343 */
328344 for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) {
329345 if (!ntfs_bit_get(buf, start_lcn-start_buf)) {
330346 LCN end_lcn;
347+ LCN aligned_lcn;
348+ u64 aligned_count;
331349
332350 /* Cluster 'start_lcn' is not in use,
333351 * find end of this run.
@@ -338,14 +356,25 @@ static int fstrim(ntfs_volume *vol, void *data, u64 *trimmed)
338356 < discard_max_bytes &&
339357 !ntfs_bit_get(buf, end_lcn-start_buf))
340358 end_lcn++;
341-
342- ret = fstrim_clusters(vol,
343- start_lcn, end_lcn-start_lcn);
344- if (ret)
345- goto free_out;
346-
347- *trimmed += (end_lcn - start_lcn)
359+ aligned_lcn = align_up(vol, start_lcn,
360+ discard_granularity);
361+ if (aligned_lcn >= end_lcn)
362+ aligned_count = 0;
363+ else {
364+ aligned_count =
365+ align_down(vol,
366+ end_lcn - aligned_lcn,
367+ discard_granularity);
368+ }
369+ if (aligned_count) {
370+ ret = fstrim_clusters(vol,
371+ aligned_lcn, aligned_count);
372+ if (ret)
373+ goto free_out;
374+
375+ *trimmed += aligned_count
348376 << vol->cluster_size_bits;
377+ }
349378 start_lcn = end_lcn-1;
350379 }
351380 }
--- a/libntfs-3g/mft.c
+++ b/libntfs-3g/mft.c
@@ -5,7 +5,7 @@
55 * Copyright (c) 2004-2005 Richard Russon
66 * Copyright (c) 2004-2008 Szabolcs Szakacsits
77 * Copyright (c) 2005 Yura Pakhuchiy
8- * Copyright (c) 2014-2015 Jean-Pierre Andre
8+ * Copyright (c) 2014-2018 Jean-Pierre Andre
99 *
1010 * This program/include file is free software; you can redistribute it and/or
1111 * modify it under the terms of the GNU General Public License as published
@@ -1389,16 +1389,27 @@ ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol, BOOL mft_data)
13891389 */
13901390 if (ext_ni) {
13911391 /*
1392- * Make sure record 15 is a base extent and has
1393- * no extents.
1394- * Also make sure it has no name : a base inode with
1395- * no extents and no name cannot be in use.
1396- * Otherwise apply standard procedure.
1392+ * Make sure record 15 is a base extent and it has
1393+ * no name. A base inode with no name cannot be in use.
1394+ * The test based on base_mft_record fails for
1395+ * extents of MFT, so we need a special check.
1396+ * If already used, apply standard procedure.
13971397 */
13981398 if (!ext_ni->mrec->base_mft_record
1399- && !ext_ni->nr_extents)
1399+ && !ext_ni->mrec->link_count)
14001400 forced_mft_data = TRUE;
14011401 ntfs_inode_close(ext_ni);
1402+ /* Double-check, in case it is used for MFT */
1403+ if (forced_mft_data && base_ni->nr_extents) {
1404+ int i;
1405+
1406+ for (i=0; i<base_ni->nr_extents; i++) {
1407+ if (base_ni->extent_nis[i]
1408+ && (base_ni->extent_nis[i]->mft_no
1409+ == FILE_mft_data))
1410+ forced_mft_data = FALSE;
1411+ }
1412+ }
14021413 }
14031414 }
14041415 if (forced_mft_data)
--- a/libntfs-3g/object_id.c
+++ b/libntfs-3g/object_id.c
@@ -3,7 +3,7 @@
33 *
44 * This module is part of ntfs-3g library
55 *
6- * Copyright (c) 2009 Jean-Pierre Andre
6+ * Copyright (c) 2009-2019 Jean-Pierre Andre
77 *
88 * This program/include file is free software; you can redistribute it and/or
99 * modify it under the terms of the GNU General Public License as published
@@ -63,9 +63,13 @@
6363 * significant byte first, and the six fields be compared individually
6464 * for ordering. RFC 4122 does not define the internal representation.
6565 *
66+ * Windows apparently stores the first three fields in little endian
67+ * order, and the last two fields in big endian order.
68+ *
6669 * Here we always copy disk images with no endianness change,
6770 * and, for indexing, GUIDs are compared as if they were a sequence
68- * of four unsigned 32 bit integers.
71+ * of four little-endian unsigned 32 bit integers (as Windows
72+ * does it that way.)
6973 *
7074 * --------------------- begin from RFC 4122 ----------------------
7175 * Consider each field of the UUID to be an unsigned integer as shown
@@ -329,7 +333,7 @@ static int update_object_id(ntfs_inode *ni, ntfs_index_context *xo,
329333
330334 na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
331335 if (na) {
332-
336+ memset(&old_attr, 0, sizeof(OBJECT_ID_ATTR));
333337 /* remove the existing index entry */
334338 oldsize = remove_object_id_index(na,xo,&old_attr);
335339 if (oldsize < 0)
@@ -349,10 +353,12 @@ static int update_object_id(ntfs_inode *ni, ntfs_index_context *xo,
349353 res = -1;
350354 }
351355 }
352- /* write index part if provided */
356+ /* overwrite index data with new value */
357+ memcpy(&old_attr, value,
358+ (size < sizeof(OBJECT_ID_ATTR)
359+ ? size : sizeof(OBJECT_ID_ATTR)));
353360 if (!res
354- && ((size < sizeof(OBJECT_ID_ATTR))
355- || set_object_id_index(ni,xo,value))) {
361+ && set_object_id_index(ni,xo,&old_attr)) {
356362 /*
357363 * If cannot index, try to remove the object
358364 * id and log the error. There will be an
@@ -500,9 +506,11 @@ int ntfs_get_ntfs_object_id(ntfs_inode *ni, char *value, size_t size)
500506 /*
501507 * Set the object id from an extended attribute
502508 *
503- * If the size is 64, the attribute and index are set.
504- * else if the size is not less than 16 only the attribute is set.
505- * The object id index is set accordingly.
509+ * The first 16 bytes are the new object id, they can be followed
510+ * by the birth volume id, the birth object id and the domain id.
511+ * If they are not present, their previous value is kept.
512+ * Only the object id is stored into the attribute, all the fields
513+ * are stored into the index.
506514 *
507515 * Returns 0, or -1 if there is a problem
508516 */
@@ -519,10 +527,12 @@ int ntfs_set_ntfs_object_id(ntfs_inode *ni,
519527 if (ni && value && (size >= sizeof(GUID))) {
520528 xo = open_object_id_index(ni->vol);
521529 if (xo) {
522- /* make sure the GUID was not used somewhere */
530+ /* make sure the GUID was not used elsewhere */
523531 memcpy(&key.object_id, value, sizeof(GUID));
524- if (ntfs_index_lookup(&key,
525- sizeof(OBJECT_ID_INDEX_KEY), xo)) {
532+ if ((ntfs_index_lookup(&key,
533+ sizeof(OBJECT_ID_INDEX_KEY), xo))
534+ || (MREF_LE(((struct OBJECT_ID_INDEX*)xo->entry)
535+ ->data.file_id) == ni->mft_no)) {
526536 ntfs_index_ctx_reinit(xo);
527537 res = add_object_id(ni, flags);
528538 if (!res) {
--- a/libntfs-3g/unix_io.c
+++ b/libntfs-3g/unix_io.c
@@ -53,6 +53,9 @@
5353 #ifdef HAVE_LINUX_FD_H
5454 #include <linux/fd.h>
5555 #endif
56+#ifdef HAVE_LINUX_FS_H
57+#include <linux/fs.h>
58+#endif
5659
5760 #include "types.h"
5861 #include "mst.h"
@@ -140,8 +143,26 @@ static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags)
140143 *(int*)dev->d_private = open(dev->d_name, flags);
141144 if (*(int*)dev->d_private == -1) {
142145 err = errno;
146+ /* if permission error and rw, retry read-only */
147+ if ((err == EACCES) && ((flags & O_RDWR) == O_RDWR))
148+ err = EROFS;
143149 goto err_out;
144150 }
151+#ifdef HAVE_LINUX_FS_H
152+ /* Check whether the device was forced read-only */
153+ if (NDevBlock(dev) && ((flags & O_RDWR) == O_RDWR)) {
154+ int r;
155+ int state;
156+
157+ r = ioctl(DEV_FD(dev), BLKROGET, &state);
158+ if (!r && state) {
159+ err = EROFS;
160+ if (close(DEV_FD(dev)))
161+ err = errno;
162+ goto err_out;
163+ }
164+ }
165+#endif
145166
146167 if ((flags & O_RDWR) != O_RDWR)
147168 NDevSetReadOnly(dev);
--- a/libntfs-3g/volume.c
+++ b/libntfs-3g/volume.c
@@ -533,7 +533,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
533533 dev->d_name);
534534 goto error_exit;
535535 } else {
536- ntfs_log_info("Can only open '%s' as read-only\n",
536+ ntfs_log_info("Error opening '%s' read-write\n",
537537 dev->d_name);
538538 NVolSetReadOnly(vol);
539539 }
@@ -963,7 +963,8 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
963963 vol->mftmirr_size = l;
964964 }
965965 ntfs_log_debug("Comparing $MFTMirr to $MFT...\n");
966- for (i = 0; i < vol->mftmirr_size; ++i) {
966+ /* Windows 10 does not update the full $MFTMirr any more */
967+ for (i = 0; (i < vol->mftmirr_size) && (i < FILE_first_user); ++i) {
967968 MFT_RECORD *mrec, *mrec2;
968969 const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
969970 "$Volume", "$AttrDef", "root directory", "$Bitmap",
--- a/ntfsprogs/mkntfs.8.in
+++ b/ntfsprogs/mkntfs.8.in
@@ -132,7 +132,7 @@ actual writing to the device.
132132 .TP
133133 \fB\-c\fR, \fB\-\-cluster\-size\fR BYTES
134134 Specify the size of clusters in bytes. Valid cluster size values are powers of
135-two, with at least 256, and at most 65536 bytes per cluster. If omitted,
135+two, with at least 256, and at most 2097152 bytes (2MB) per cluster. If omitted,
136136 .B mkntfs
137137 uses 4096 bytes as the default cluster size.
138138 .sp
--- a/ntfsprogs/mkntfs.c
+++ b/ntfsprogs/mkntfs.c
@@ -6,7 +6,7 @@
66 * Copyright (c) 2002-2006 Szabolcs Szakacsits
77 * Copyright (c) 2005 Erik Sornes
88 * Copyright (c) 2007 Yura Pakhuchiy
9- * Copyright (c) 2010-2014 Jean-Pierre Andre
9+ * Copyright (c) 2010-2018 Jean-Pierre Andre
1010 *
1111 * This utility will create an NTFS 1.2 or 3.1 volume on a user
1212 * specified (block) device.
@@ -119,6 +119,7 @@
119119 # endif
120120 #endif
121121
122+#include "param.h"
122123 #include "security.h"
123124 #include "types.h"
124125 #include "attrib.h"
@@ -287,7 +288,7 @@ static void mkntfs_version(void)
287288 ntfs_log_info("Copyright (c) 2002-2006 Szabolcs Szakacsits\n");
288289 ntfs_log_info("Copyright (c) 2005 Erik Sornes\n");
289290 ntfs_log_info("Copyright (c) 2007 Yura Pakhuchiy\n");
290- ntfs_log_info("Copyright (c) 2010-2014 Jean-Pierre Andre\n");
291+ ntfs_log_info("Copyright (c) 2010-2018 Jean-Pierre Andre\n");
291292 ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
292293 }
293294
@@ -669,7 +670,7 @@ static int mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *o
669670 break;
670671 case 'L':
671672 if (!opts2->label) {
672- opts2->label = argv[optind-1];
673+ opts2->label = optarg;
673674 } else {
674675 ntfs_log_error("You may only specify the label "
675676 "once.\n");
@@ -3719,11 +3720,11 @@ static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
37193720 /*
37203721 * For huge volumes, grow the cluster size until the number of
37213722 * clusters fits into 32 bits or the cluster size exceeds the
3722- * maximum limit of 64kiB.
3723+ * maximum limit of NTFS_MAX_CLUSTER_SIZE.
37233724 */
37243725 while (volume_size >> (ffs(vol->cluster_size) - 1 + 32)) {
37253726 vol->cluster_size <<= 1;
3726- if (vol->cluster_size > 65535) {
3727+ if (vol->cluster_size >= NTFS_MAX_CLUSTER_SIZE) {
37273728 ntfs_log_error("Device is too large to hold an "
37283729 "NTFS volume (maximum size is "
37293730 "256TiB).\n");
@@ -3744,15 +3745,18 @@ static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
37443745 "to, or larger than, the sector size.\n");
37453746 return FALSE;
37463747 }
3747- if (vol->cluster_size > 128 * (u32)opts.sector_size) {
3748+ /* Before Windows 10 Creators, the limit was 128 */
3749+ if (vol->cluster_size > 4096 * (u32)opts.sector_size) {
37483750 ntfs_log_error("The cluster size is invalid. It cannot be "
3749- "more that 128 times the size of the sector "
3751+ "more that 4096 times the size of the sector "
37503752 "size.\n");
37513753 return FALSE;
37523754 }
3753- if (vol->cluster_size > 65536) {
3755+ if (vol->cluster_size > NTFS_MAX_CLUSTER_SIZE) {
37543756 ntfs_log_error("The cluster size is invalid. The maximum "
3755- "cluster size is 65536 bytes (64kiB).\n");
3757+ "cluster size is %lu bytes (%lukiB).\n",
3758+ (unsigned long)NTFS_MAX_CLUSTER_SIZE,
3759+ (unsigned long)(NTFS_MAX_CLUSTER_SIZE >> 10));
37563760 return FALSE;
37573761 }
37583762 vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
@@ -4387,6 +4391,7 @@ static BOOL mkntfs_create_root_structures(void)
43874391 u8 *sd;
43884392 FILE_ATTR_FLAGS extend_flags;
43894393 VOLUME_FLAGS volume_flags = const_cpu_to_le16(0);
4394+ int sectors_per_cluster;
43904395 int nr_sysfiles;
43914396 int buf_sds_first_size;
43924397 char *buf_sds;
@@ -4639,8 +4644,11 @@ static BOOL mkntfs_create_root_structures(void)
46394644 * already inserted, so no need to worry about these things.
46404645 */
46414646 bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size);
4642- bs->bpb.sectors_per_cluster = (u8)(g_vol->cluster_size /
4643- opts.sector_size);
4647+ sectors_per_cluster = g_vol->cluster_size / opts.sector_size;
4648+ if (sectors_per_cluster > 128)
4649+ bs->bpb.sectors_per_cluster = 257 - ffs(sectors_per_cluster);
4650+ else
4651+ bs->bpb.sectors_per_cluster = sectors_per_cluster;
46444652 bs->bpb.media_type = 0xf8; /* hard disk */
46454653 bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
46464654 ntfs_log_debug("sectors per track = %ld (0x%lx)\n",
--- a/ntfsprogs/ntfsclone.c
+++ b/ntfsprogs/ntfsclone.c
@@ -3,7 +3,7 @@
33 *
44 * Copyright (c) 2003-2006 Szabolcs Szakacsits
55 * Copyright (c) 2004-2006 Anton Altaparmakov
6- * Copyright (c) 2010-2017 Jean-Pierre Andre
6+ * Copyright (c) 2010-2018 Jean-Pierre Andre
77 * Special image format support copyright (c) 2004 Per Olofsson
88 *
99 * Clone NTFS data and/or metadata to a sparse file, image, device or stdout.
@@ -71,6 +71,7 @@
7171 */
7272 #define NTFS_DO_NOT_CHECK_ENDIANS
7373
74+#include "param.h"
7475 #include "debug.h"
7576 #include "types.h"
7677 #include "support.h"
@@ -270,7 +271,6 @@ static int compare_bitmaps(struct bitmap *a, BOOL copy);
270271
271272 #define LAST_METADATA_INODE 11
272273
273-#define NTFS_MAX_CLUSTER_SIZE 65536
274274 #define NTFS_SECTOR_SIZE 512
275275
276276 #define rounded_up_division(a, b) (((a) + (b - 1)) / (b))
@@ -393,7 +393,7 @@ static void version(void)
393393 "Efficiently clone, image, restore or rescue an NTFS Volume.\n\n"
394394 "Copyright (c) 2003-2006 Szabolcs Szakacsits\n"
395395 "Copyright (c) 2004-2006 Anton Altaparmakov\n"
396- "Copyright (c) 2010-2016 Jean-Pierre Andre\n\n");
396+ "Copyright (c) 2010-2018 Jean-Pierre Andre\n\n");
397397 fprintf(stderr, "%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
398398 exit(0);
399399 }
@@ -756,7 +756,7 @@ static void read_rescue(void *fd, char *buff, u32 csize, u32 bytes_per_sector,
756756
757757 static void copy_cluster(int rescue, u64 rescue_lcn, u64 lcn)
758758 {
759- char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
759+ char *buff;
760760 /* vol is NULL if opt.restore_image is set */
761761 s32 csize = le32_to_cpu(image_hdr.cluster_size);
762762 BOOL backup_bootsector;
@@ -773,6 +773,9 @@ static void copy_cluster(int rescue, u64 rescue_lcn, u64 lcn)
773773 }
774774
775775 rescue_pos = (off_t)(rescue_lcn * csize);
776+ buff = (char*)ntfs_malloc(csize);
777+ if (!buff)
778+ err_exit("Not enough memory");
776779
777780 /* possible partial cluster holding the backup boot sector */
778781 backup_bootsector = (lcn + 1)*csize >= full_device_size;
@@ -858,6 +861,7 @@ static void copy_cluster(int rescue, u64 rescue_lcn, u64 lcn)
858861 perr_printf("Write failed");
859862 #endif
860863 }
864+ free(buff);
861865 }
862866
863867 static s64 lseek_out(int fd, s64 pos, int mode)
@@ -995,7 +999,11 @@ static void write_empty_clusters(s32 csize, s64 count,
995999 struct progress_bar *progress, u64 *p_counter)
9961000 {
9971001 s64 i;
998- char buff[NTFS_MAX_CLUSTER_SIZE];
1002+ char *buff;
1003+
1004+ buff = (char*)ntfs_malloc(csize);
1005+ if (!buff)
1006+ err_exit("Not enough memory");
9991007
10001008 memset(buff, 0, csize);
10011009
@@ -1004,6 +1012,7 @@ static void write_empty_clusters(s32 csize, s64 count,
10041012 perr_exit("write_all");
10051013 progress_update(progress, ++(*p_counter));
10061014 }
1015+ free(buff);
10071016 }
10081017
10091018 static void restore_image(void)
@@ -1492,11 +1501,12 @@ static void write_set(char *buff, u32 csize, s64 *current_lcn,
14921501
14931502 static void copy_wipe_mft(ntfs_walk_clusters_ctx *image, runlist *rl)
14941503 {
1495- char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
1504+ char *buff;
14961505 void *fd;
14971506 s64 mft_no;
14981507 u32 mft_record_size;
14991508 u32 csize;
1509+ u32 buff_size;
15001510 u32 bytes_per_sector;
15011511 u32 records_per_set;
15021512 u32 clusters_per_set;
@@ -1514,14 +1524,21 @@ static void copy_wipe_mft(ntfs_walk_clusters_ctx *image, runlist *rl)
15141524 /*
15151525 * Depending on the sizes, there may be several records
15161526 * per cluster, or several clusters per record.
1527+ * Anyway, records are read and rescued by full clusters.
15171528 */
15181529 if (csize >= mft_record_size) {
15191530 records_per_set = csize/mft_record_size;
15201531 clusters_per_set = 1;
1532+ buff_size = csize;
15211533 } else {
15221534 clusters_per_set = mft_record_size/csize;
15231535 records_per_set = 1;
1536+ buff_size = mft_record_size;
15241537 }
1538+ buff = (char*)ntfs_malloc(buff_size);
1539+ if (!buff)
1540+ err_exit("Not enough memory");
1541+
15251542 mft_no = 0;
15261543 ri = rj = 0;
15271544 wi = wj = 0;
@@ -1554,6 +1571,7 @@ static void copy_wipe_mft(ntfs_walk_clusters_ctx *image, runlist *rl)
15541571 }
15551572 }
15561573 image->current_lcn = current_lcn;
1574+ free(buff);
15571575 }
15581576
15591577 /*
@@ -1566,10 +1584,11 @@ static void copy_wipe_mft(ntfs_walk_clusters_ctx *image, runlist *rl)
15661584
15671585 static void copy_wipe_i30(ntfs_walk_clusters_ctx *image, runlist *rl)
15681586 {
1569- char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
1587+ char *buff;
15701588 void *fd;
15711589 u32 indx_record_size;
15721590 u32 csize;
1591+ u32 buff_size;
15731592 u32 bytes_per_sector;
15741593 u32 records_per_set;
15751594 u32 clusters_per_set;
@@ -1586,15 +1605,22 @@ static void copy_wipe_i30(ntfs_walk_clusters_ctx *image, runlist *rl)
15861605 /*
15871606 * Depending on the sizes, there may be several records
15881607 * per cluster, or several clusters per record.
1608+ * Anyway, records are read and rescued by full clusters.
15891609 */
15901610 indx_record_size = image->ni->vol->indx_record_size;
15911611 if (csize >= indx_record_size) {
15921612 records_per_set = csize/indx_record_size;
15931613 clusters_per_set = 1;
1614+ buff_size = csize;
15941615 } else {
15951616 clusters_per_set = indx_record_size/csize;
15961617 records_per_set = 1;
1618+ buff_size = indx_record_size;
15971619 }
1620+ buff = (char*)ntfs_malloc(buff_size);
1621+ if (!buff)
1622+ err_exit("Not enough memory");
1623+
15981624 ri = rj = 0;
15991625 wi = wj = 0;
16001626 if (rl[ri].length)
@@ -1627,6 +1653,7 @@ static void copy_wipe_i30(ntfs_walk_clusters_ctx *image, runlist *rl)
16271653 }
16281654 }
16291655 image->current_lcn = current_lcn;
1656+ free(buff);
16301657 }
16311658
16321659 static void dump_clusters(ntfs_walk_clusters_ctx *image, runlist *rl)
--- a/ntfsprogs/ntfscluster.8.in
+++ b/ntfsprogs/ntfscluster.8.in
@@ -69,7 +69,7 @@ This option is not yet implemented.
6969 .TP
7070 \fB\-q\fR, \fB\-\-quiet\fR
7171 Reduce the amount of output to a minimum. Naturally, it doesn't make sense to
72-combine this option with
72+combine this option with \fB\-\-verbose\fR
7373 .TP
7474 \fB\-s\fR, \fB\-\-sector\fR RANGE
7575 Any files whose data is in this range of sectors will be displayed.
--- a/ntfsprogs/ntfscp.8.in
+++ b/ntfsprogs/ntfscp.8.in
@@ -59,6 +59,10 @@ Show a list of options with a brief description of each one.
5959 \fB\-q\fR, \fB\-\-quiet\fR
6060 Suppress some debug/warning/error messages.
6161 .TP
62+\fB\-t\fR, \fB\-\-timestamp\fR
63+Copy the modification time of source_file to destination. This is
64+not compatible with \fB\-\-attr\-name\fR and \fB\-\-attribute\fR.
65+.TP
6266 \fB\-V\fR, \fB\-\-version\fR
6367 Show the version number, copyright and license
6468 .BR ntfscp .
--- a/ntfsprogs/ntfscp.c
+++ b/ntfsprogs/ntfscp.c
@@ -4,7 +4,7 @@
44 * Copyright (c) 2004-2007 Yura Pakhuchiy
55 * Copyright (c) 2005 Anton Altaparmakov
66 * Copyright (c) 2006 Hil Liao
7- * Copyright (c) 2014 Jean-Pierre Andre
7+ * Copyright (c) 2014-2019 Jean-Pierre Andre
88 *
99 * This utility will copy file to an NTFS volume.
1010 *
@@ -58,6 +58,7 @@
5858 #include "debug.h"
5959 /* #include "version.h" */
6060 #include "logging.h"
61+#include "ntfstime.h"
6162 #include "misc.h"
6263
6364 struct options {
@@ -69,6 +70,7 @@ struct options {
6970 int quiet; /* Less output */
7071 int verbose; /* Extra output */
7172 int minfragments; /* Do minimal fragmentation */
73+ int timestamp; /* Copy the modification time */
7274 int noaction; /* Do not write to disk */
7375 ATTR_TYPES attribute; /* Write to this attribute. */
7476 int inode; /* Treat dest_file as inode number. */
@@ -129,6 +131,7 @@ static void usage(void)
129131 " -N, --attr-name NAME Write to attribute with this name\n"
130132 " -n, --no-action Do not write to disk\n"
131133 " -q, --quiet Less output\n"
134+ " -t, --timestamp Copy the modification time\n"
132135 " -V, --version Version information\n"
133136 " -v, --verbose More output\n\n",
134137 EXEC_NAME);
@@ -146,7 +149,7 @@ static void usage(void)
146149 */
147150 static int parse_options(int argc, char **argv)
148151 {
149- static const char *sopt = "-a:ifh?mN:no:qVv";
152+ static const char *sopt = "-a:ifh?mN:no:qtVv";
150153 static const struct option lopt[] = {
151154 { "attribute", required_argument, NULL, 'a' },
152155 { "inode", no_argument, NULL, 'i' },
@@ -156,6 +159,7 @@ static int parse_options(int argc, char **argv)
156159 { "attr-name", required_argument, NULL, 'N' },
157160 { "no-action", no_argument, NULL, 'n' },
158161 { "quiet", no_argument, NULL, 'q' },
162+ { "timestamp", no_argument, NULL, 't' },
159163 { "version", no_argument, NULL, 'V' },
160164 { "verbose", no_argument, NULL, 'v' },
161165 { NULL, 0, NULL, 0 }
@@ -175,6 +179,7 @@ static int parse_options(int argc, char **argv)
175179 opts.attr_name = NULL;
176180 opts.inode = 0;
177181 opts.attribute = AT_DATA;
182+ opts.timestamp = 0;
178183
179184 opterr = 0; /* We'll handle the errors, thank you. */
180185
@@ -235,6 +240,9 @@ static int parse_options(int argc, char **argv)
235240 opts.quiet++;
236241 ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
237242 break;
243+ case 't':
244+ opts.timestamp++;
245+ break;
238246 case 'V':
239247 ver++;
240248 break;
@@ -284,6 +292,12 @@ static int parse_options(int argc, char **argv)
284292 "at the same time.\n");
285293 err++;
286294 }
295+ if (opts.timestamp
296+ && (opts.attr_name || (opts.attribute != AT_DATA))) {
297+ ntfs_log_error("Setting --timestamp is only possible"
298+ " with unname data attribute.\n");
299+ err++;
300+ }
287301 }
288302
289303 if (ver)
@@ -822,6 +836,7 @@ static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni,
822836 int main(int argc, char *argv[])
823837 {
824838 FILE *in;
839+ struct stat st;
825840 ntfs_volume *vol;
826841 ntfs_inode *out;
827842 ntfs_attr *na;
@@ -1136,6 +1151,16 @@ int main(int argc, char *argv[])
11361151 free(buf);
11371152 close_attr:
11381153 ntfs_attr_close(na);
1154+ if (opts.timestamp) {
1155+ if (!fstat(fileno(in),&st)) {
1156+ s64 change_time = st.st_mtime*10000000LL
1157+ + NTFS_TIME_OFFSET;
1158+ out->last_data_change_time = cpu_to_le64(change_time);
1159+ ntfs_inode_update_times(out, 0);
1160+ } else {
1161+ ntfs_log_error("Failed to get the time stamp.\n");
1162+ }
1163+ }
11391164 close_dst:
11401165 while (ntfs_inode_close(out) && !opts.noaction) {
11411166 if (errno != EBUSY) {
--- a/ntfsprogs/ntfsfix.c
+++ b/ntfsprogs/ntfsfix.c
@@ -506,6 +506,11 @@ static int fix_mftmirr(ntfs_volume *vol)
506506
507507 ntfs_log_info("Comparing $MFTMirr to $MFT... ");
508508 done = FALSE;
509+ /*
510+ * Since 2017, Windows 10 does not mirror to full $MFTMirr when
511+ * using big clusters, and some records may be found different.
512+ * Nevertheless chkdsk.exe mirrors it fully, so we do similarly.
513+ */
509514 for (i = 0; i < vol->mftmirr_size; ++i) {
510515 MFT_RECORD *mrec, *mrec2;
511516 const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
--- a/ntfsprogs/ntfsinfo.c
+++ b/ntfsprogs/ntfsinfo.c
@@ -8,7 +8,7 @@
88 * Copyright (c) 2004-2005 Yuval Fledel
99 * Copyright (c) 2004-2007 Yura Pakhuchiy
1010 * Copyright (c) 2005 Cristian Klein
11- * Copyright (c) 2011-2017 Jean-Pierre Andre
11+ * Copyright (c) 2011-2018 Jean-Pierre Andre
1212 *
1313 * This utility will dump a file's attributes.
1414 *
@@ -119,7 +119,7 @@ static void version(void)
119119 printf(" 2003 Leonard Norrgård\n");
120120 printf(" 2004-2005 Yuval Fledel\n");
121121 printf(" 2004-2007 Yura Pakhuchiy\n");
122- printf(" 2011-2017 Jean-Pierre Andre\n");
122+ printf(" 2011-2018 Jean-Pierre Andre\n");
123123 printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
124124 }
125125
@@ -411,8 +411,10 @@ static char *ntfs_attr_get_name_mbs(ATTR_RECORD *attr)
411411 static const char *reparse_type_name(le32 tag)
412412 {
413413 const char *name;
414+ le32 seltag;
414415
415- switch (tag) {
416+ seltag = tag & IO_REPARSE_PLUGIN_SELECT;
417+ switch (seltag) {
416418 case IO_REPARSE_TAG_MOUNT_POINT :
417419 name = " (mount point)";
418420 break;
@@ -428,6 +430,9 @@ static const char *reparse_type_name(le32 tag)
428430 case IO_REPARSE_TAG_WCI :
429431 name = " (Windows container)";
430432 break;
433+ case IO_REPARSE_TAG_CLOUD :
434+ name = " (Cloud)";
435+ break;
431436 case IO_REPARSE_TAG_NFS :
432437 name = " (NFS symlink)";
433438 break;
--- a/ntfsprogs/ntfsrecover.c
+++ b/ntfsprogs/ntfsrecover.c
@@ -3698,7 +3698,7 @@ static int walkback(CONTEXT *ctx, const struct BUFFER *buf, u32 blk,
36983698 * use a different layout of temporary blocks.
36993699 */
37003700
3701-const struct BUFFER *find_latest_block(CONTEXT *ctx, u32 baseblk,
3701+static const struct BUFFER *find_latest_block(CONTEXT *ctx, u32 baseblk,
37023702 const struct BUFFER *basebuf)
37033703 {
37043704 le64 offset;
@@ -3710,6 +3710,9 @@ const struct BUFFER *find_latest_block(CONTEXT *ctx, u32 baseblk,
37103710 const struct BUFFER *curbuf;
37113711
37123712 offset = basebuf->block.record.copy.file_offset;
3713+ curbuf = (const struct BUFFER*)NULL;
3714+ curlsn = const_cpu_to_le64(0);
3715+ prevblk = 0;
37133716 curblk = baseblk;
37143717 do {
37153718 if (curblk < BASEBLKS) {
--- a/ntfsprogs/ntfsresize.8.in
+++ b/ntfsprogs/ntfsresize.8.in
@@ -243,10 +243,9 @@ Display help and exit.
243243 .SH EXIT CODES
244244 The exit code is 0 on success, non\-zero otherwise.
245245 .SH KNOWN ISSUES
246-No reliability problem is known. If you need
247-help please try the Ntfsresize FAQ first (see below) and if you
248-don't find your answer then send your question, comment or bug report to
249-the development team:
246+No reliability problem is known.
247+If you find a bug please send an email describing the problem to the
248+development team at:
250249 .br
251250 .nh
252251 ntfs\-3g\-devel@lists.sf.net
@@ -308,14 +307,6 @@ package and is available from:
308307 .nh
309308 http://www.tuxera.com/community/
310309 .hy
311-.sp
312-.B Ntfsresize
313-related news, example of usage, troubleshooting, statically linked binary and
314-FAQ (frequently asked questions) are maintained at:
315-.br
316-.nh
317-http://mlf.linux.rulez.org/mlf/ezaz/ntfsresize.html
318-.hy
319310 .SH SEE ALSO
320311 .BR fdisk (8),
321312 .BR cfdisk (8),
--- a/ntfsprogs/ntfsresize.c
+++ b/ntfsprogs/ntfsresize.c
@@ -5,7 +5,7 @@
55 * Copyright (c) 2002-2005 Anton Altaparmakov
66 * Copyright (c) 2002-2003 Richard Russon
77 * Copyright (c) 2007 Yura Pakhuchiy
8- * Copyright (c) 2011-2016 Jean-Pierre Andre
8+ * Copyright (c) 2011-2018 Jean-Pierre Andre
99 *
1010 * This utility will resize an NTFS volume without data loss.
1111 *
@@ -59,6 +59,7 @@
5959 #include <fcntl.h>
6060 #endif
6161
62+#include "param.h"
6263 #include "debug.h"
6364 #include "types.h"
6465 #include "support.h"
@@ -137,6 +138,8 @@ static const char *many_bad_sectors_msg =
137138 "* other reason. We suggest to get a replacement disk as soon as possible. *\n"
138139 "***************************************************************************\n";
139140
141+enum mirror_source { MIRR_OLD, MIRR_NEWMFT, MIRR_MFT };
142+
140143 static struct {
141144 int verbose;
142145 int debug;
@@ -226,6 +229,7 @@ typedef struct {
226229 struct llcn_t last_compressed;
227230 struct llcn_t last_lcn;
228231 s64 last_unsupp; /* last unsupported cluster */
232+ enum mirror_source mirr_from;
229233 } ntfs_resize_t;
230234
231235 /* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster
@@ -243,8 +247,6 @@ static s64 max_free_cluster_range = 0;
243247 #define DIRTY_INODE (1)
244248 #define DIRTY_ATTRIB (2)
245249
246-#define NTFS_MAX_CLUSTER_SIZE (65536)
247-
248250 static s64 rounded_up_division(s64 numer, s64 denom)
249251 {
250252 return (numer + (denom - 1)) / denom;
@@ -404,7 +406,7 @@ static void version(void)
404406 printf("Copyright (c) 2002-2005 Anton Altaparmakov\n");
405407 printf("Copyright (c) 2002-2003 Richard Russon\n");
406408 printf("Copyright (c) 2007 Yura Pakhuchiy\n");
407- printf("Copyright (c) 2011-2016 Jean-Pierre Andre\n");
409+ printf("Copyright (c) 2011-2018 Jean-Pierre Andre\n");
408410 printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
409411 }
410412
@@ -1459,10 +1461,13 @@ static int record_mft_in_bitmap(ntfs_resize_t *resize)
14591461 static void delayed_updates(ntfs_resize_t *resize)
14601462 {
14611463 struct DELAYED *delayed;
1464+ struct DELAYED *delayed_mft_data;
1465+ int nr_extents;
14621466
14631467 if (ntfs_volume_get_free_space(resize->vol))
14641468 err_exit("Failed to determine free space\n");
14651469
1470+ delayed_mft_data = (struct DELAYED*)NULL;
14661471 if (resize->delayed_runlists && reload_mft(resize))
14671472 err_exit("Failed to reload the MFT for delayed updates\n");
14681473
@@ -1476,19 +1481,55 @@ static void delayed_updates(ntfs_resize_t *resize)
14761481 * So we update MFT data first, and we record the MFT
14771482 * extents again in the MFT bitmap if they were recorded
14781483 * in the old location.
1484+ *
1485+ * However, if we are operating in "no action" mode, the
1486+ * MFT records to update are not written to their new location
1487+ * and the MFT data runlist has to be updated last in order
1488+ * to have the entries read from their old location.
1489+ * In this situation the MFT bitmap is never written to
1490+ * disk, so the same extents are reallocated repeatedly,
1491+ * which is not what would be done in a real resizing.
14791492 */
14801493
1494+ if (opt.ro_flag
1495+ && resize->delayed_runlists
1496+ && (resize->delayed_runlists->mref == FILE_MFT)
1497+ && (resize->delayed_runlists->type == AT_DATA)) {
1498+ /* Update the MFT data runlist later */
1499+ delayed_mft_data = resize->delayed_runlists;
1500+ resize->delayed_runlists = resize->delayed_runlists->next;
1501+ }
1502+
14811503 while (resize->delayed_runlists) {
14821504 delayed = resize->delayed_runlists;
14831505 expand_attribute_runlist(resize->vol, delayed);
1484- if ((delayed->mref == FILE_MFT) && (delayed->type == AT_BITMAP))
1485- record_mft_in_bitmap(resize);
1506+ if (delayed->mref == FILE_MFT) {
1507+ if (delayed->type == AT_BITMAP)
1508+ record_mft_in_bitmap(resize);
1509+ if (delayed->type == AT_DATA)
1510+ resize->mirr_from = MIRR_MFT;
1511+ }
14861512 resize->delayed_runlists = resize->delayed_runlists->next;
14871513 if (delayed->attr_name)
14881514 free(delayed->attr_name);
14891515 free(delayed->head_rl);
14901516 free(delayed);
14911517 }
1518+ if (opt.ro_flag && delayed_mft_data) {
1519+ /* in "no action" mode, check updating the MFT runlist now */
1520+ expand_attribute_runlist(resize->vol, delayed_mft_data);
1521+ resize->mirr_from = MIRR_MFT;
1522+ if (delayed_mft_data->attr_name)
1523+ free(delayed_mft_data->attr_name);
1524+ free(delayed_mft_data->head_rl);
1525+ free(delayed_mft_data);
1526+ }
1527+ /* Beware of MFT fragmentation when the target size is too small */
1528+ nr_extents = resize->vol->mft_ni->nr_extents;
1529+ if (nr_extents > 2) {
1530+ printf("WARNING: The MFT is now severely fragmented"
1531+ " (%d extents)\n", nr_extents);
1532+ }
14921533 }
14931534
14941535 /*
@@ -1849,9 +1890,13 @@ static void lseek_to_cluster(ntfs_volume *vol, s64 lcn)
18491890 static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len)
18501891 {
18511892 s64 i;
1852- char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
1893+ char *buff;
18531894 ntfs_volume *vol = resize->vol;
18541895
1896+ buff = (char*)ntfs_malloc(vol->cluster_size);
1897+ if (!buff)
1898+ perr_exit("ntfs_malloc");
1899+
18551900 for (i = 0; i < len; i++) {
18561901
18571902 lseek_to_cluster(vol, src + i);
@@ -1875,6 +1920,7 @@ static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len)
18751920 resize->relocations++;
18761921 progress_update(&resize->progress, resize->relocations);
18771922 }
1923+ free(buff);
18781924 }
18791925
18801926 static void relocate_clusters(ntfs_resize_t *r, runlist *dest_rl, s64 src_lcn)
@@ -2262,6 +2308,7 @@ static void relocate_inodes(ntfs_resize_t *resize)
22622308 err_exit("Could not allocate 16 records in"
22632309 " the first MFT chunk\n");
22642310 }
2311+ resize->mirr_from = MIRR_NEWMFT;
22652312 }
22662313
22672314 for (mref = 0; mref < (MFT_REF)nr_mft_records; mref++)
@@ -2715,19 +2762,34 @@ static void update_bootsector(ntfs_resize_t *r)
27152762 if (vol->dev->d_ops->read(vol->dev, bs, bs_size) == -1)
27162763 perr_exit("read() error");
27172764
2718- bs->number_of_sectors = cpu_to_sle64(r->new_volume_size *
2719- bs->bpb.sectors_per_cluster);
2765+ if (bs->bpb.sectors_per_cluster > 128)
2766+ bs->number_of_sectors = cpu_to_sle64(r->new_volume_size
2767+ << (256 - bs->bpb.sectors_per_cluster));
2768+ else
2769+ bs->number_of_sectors = cpu_to_sle64(r->new_volume_size *
2770+ bs->bpb.sectors_per_cluster);
27202771
2721- if (r->mftmir_old) {
2772+ if (r->mftmir_old || (r->mirr_from == MIRR_MFT)) {
27222773 r->progress.flags |= NTFS_PROGBAR_SUPPRESS;
27232774 /* Be sure the MFTMirr holds the updated MFT runlist */
2724- if (r->new_mft_start)
2775+ switch (r->mirr_from) {
2776+ case MIRR_MFT :
2777+ /* The late updates of MFT have not been synced */
2778+ ntfs_inode_sync(vol->mft_ni);
2779+ copy_clusters(r, r->mftmir_rl.lcn,
2780+ vol->mft_na->rl->lcn, r->mftmir_rl.length);
2781+ break;
2782+ case MIRR_NEWMFT :
27252783 copy_clusters(r, r->mftmir_rl.lcn,
27262784 r->new_mft_start->lcn, r->mftmir_rl.length);
2727- else
2785+ break;
2786+ default :
27282787 copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old,
27292788 r->mftmir_rl.length);
2730- bs->mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
2789+ break;
2790+ }
2791+ if (r->mftmir_old)
2792+ bs->mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
27312793 r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS;
27322794 }
27332795 /* Set the start of the relocated MFT */
@@ -3904,6 +3966,7 @@ static int update_runlist(expand_t *expand, s64 inum,
39043966 ctx.mrec = mrec;
39053967 resize.mref = inum;
39063968 resize.delayed_runlists = expand->delayed_runlists;
3969+ resize.mirr_from = MIRR_OLD;
39073970 must_delay = 1;
39083971 replace_later(&resize,rl,head_rl);
39093972 expand->delayed_runlists = resize.delayed_runlists;
@@ -4577,6 +4640,7 @@ int main(int argc, char **argv)
45774640
45784641 resize.inuse = fsck.inuse;
45794642 resize.lcn_bitmap = fsck.lcn_bitmap;
4643+ resize.mirr_from = MIRR_OLD;
45804644
45814645 set_resize_constraints(&resize);
45824646 set_disk_usage_constraint(&resize);
--- a/ntfsprogs/ntfsundelete.c
+++ b/ntfsprogs/ntfsundelete.c
@@ -5,7 +5,7 @@
55 * Copyright (c) 2004-2005 Holger Ohmacht
66 * Copyright (c) 2005 Anton Altaparmakov
77 * Copyright (c) 2007 Yura Pakhuchiy
8- * Copyright (c) 2013-2014 Jean-Pierre Andre
8+ * Copyright (c) 2013-2018 Jean-Pierre Andre
99 *
1010 * This utility will recover deleted files from an NTFS volume.
1111 *
@@ -392,7 +392,7 @@ static void version(void)
392392 "Copyright (c) 2004-2005 Holger Ohmacht\n"
393393 "Copyright (c) 2005 Anton Altaparmakov\n"
394394 "Copyright (c) 2007 Yura Pakhuchiy\n"
395- "Copyright (c) 2013-2014 Jean-Pierre Andre\n");
395+ "Copyright (c) 2013-2018 Jean-Pierre Andre\n");
396396 ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
397397 }
398398
@@ -1835,19 +1835,49 @@ static unsigned int write_data(int fd, const char *buffer,
18351835 static int create_pathname(const char *dir, const char *name,
18361836 const char *stream, char *buffer, int bufsize)
18371837 {
1838+ struct stat st;
1839+ int s;
1840+ int len;
1841+ int suffix;
1842+
18381843 if (!name)
18391844 name = UNKNOWN;
18401845
1841- if (dir)
1846+ if (dir) {
1847+#ifdef HAVE_WINDOWS_H
18421848 if (stream)
1843- snprintf(buffer, bufsize, "%s/%s:%s", dir, name, stream);
1849+ snprintf(buffer, bufsize, "%s\\%s:%s", dir, name,
1850+ stream);
1851+ else
1852+ snprintf(buffer, bufsize, "%s\\%s", dir, name);
1853+#else
1854+ if (stream)
1855+ snprintf(buffer, bufsize, "%s/%s:%s", dir, name,
1856+ stream);
18441857 else
18451858 snprintf(buffer, bufsize, "%s/%s", dir, name);
1846- else
1859+#endif
1860+ } else
18471861 if (stream)
18481862 snprintf(buffer, bufsize, "%s:%s", name, stream);
18491863 else
18501864 snprintf(buffer, bufsize, "%s", name);
1865+ len = strlen(buffer);
1866+ suffix = 0;
1867+#ifdef HAVE_WINDOWS_H
1868+ s = stat(buffer, &st);
1869+#else
1870+ s = lstat(buffer, &st);
1871+#endif
1872+ while (!s && (suffix < 999)) {
1873+ suffix++;
1874+ snprintf(&buffer[len], bufsize - len, ".%d", suffix);
1875+#ifdef HAVE_WINDOWS_H
1876+ s = stat(buffer, &st);
1877+#else
1878+ s = lstat(buffer, &st);
1879+#endif
1880+ }
18511881
18521882 return strlen(buffer);
18531883 }
@@ -2012,7 +2042,8 @@ static int undelete_file(ntfs_volume *vol, long long inode)
20122042 if (d->resident) {
20132043 fd = open_file(pathname);
20142044 if (fd < 0) {
2015- ntfs_log_perror("Couldn't create file");
2045+ ntfs_log_perror("Couldn't create file %s",
2046+ pathname);
20162047 goto free;
20172048 }
20182049
@@ -2041,7 +2072,8 @@ static int undelete_file(ntfs_volume *vol, long long inode)
20412072
20422073 fd = open_file(pathname);
20432074 if (fd < 0) {
2044- ntfs_log_perror("Couldn't create output file");
2075+ ntfs_log_perror("Couldn't create file %s",
2076+ pathname);
20452077 goto free;
20462078 }
20472079
@@ -2151,9 +2183,11 @@ static int undelete_file(ntfs_volume *vol, long long inode)
21512183 }
21522184 set_date(pathname, file->date);
21532185 if (d->name)
2154- ntfs_log_quiet("Undeleted '%s:%s' successfully.\n", file->pref_name, d->name);
2186+ ntfs_log_quiet("Undeleted '%s:%s' successfully to %s.\n",
2187+ file->pref_name, d->name, pathname);
21552188 else
2156- ntfs_log_quiet("Undeleted '%s' successfully.\n", file->pref_name);
2189+ ntfs_log_quiet("Undeleted '%s' successfully to %s.\n",
2190+ file->pref_name, pathname);
21572191 }
21582192 result = 1;
21592193 free:
@@ -2348,7 +2382,7 @@ static int copy_mft(ntfs_volume *vol, long long mft_begin, long long mft_end)
23482382 create_pathname(opts.dest, name, NULL, pathname, sizeof(pathname));
23492383 fd = open_file(pathname);
23502384 if (fd < 0) {
2351- ntfs_log_perror("Couldn't open output file '%s'", name);
2385+ ntfs_log_perror("Couldn't create output file '%s'", name);
23522386 goto attr;
23532387 }
23542388
@@ -2376,6 +2410,7 @@ static int copy_mft(ntfs_volume *vol, long long mft_begin, long long mft_end)
23762410 }
23772411
23782412 ntfs_log_verbose("Read %lld MFT Records\n", mft_end - mft_begin + 1);
2413+ ntfs_log_quiet("MFT extracted to file %s\n", pathname);
23792414 result = 0;
23802415 close:
23812416 close(fd);
--- a/src/lowntfs-3g.c
+++ b/src/lowntfs-3g.c
@@ -4,7 +4,7 @@
44 * Copyright (c) 2005-2007 Yura Pakhuchiy
55 * Copyright (c) 2005 Yuval Fledel
66 * Copyright (c) 2006-2009 Szabolcs Szakacsits
7- * Copyright (c) 2007-2017 Jean-Pierre Andre
7+ * Copyright (c) 2007-2019 Jean-Pierre Andre
88 * Copyright (c) 2009 Erik Larsson
99 *
1010 * This file is originated from the Linux-NTFS project.
@@ -263,7 +263,7 @@ static const char *usage_msg =
263263 "\n"
264264 "Copyright (C) 2005-2007 Yura Pakhuchiy\n"
265265 "Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
266-"Copyright (C) 2007-2017 Jean-Pierre Andre\n"
266+"Copyright (C) 2007-2019 Jean-Pierre Andre\n"
267267 "Copyright (C) 2009 Erik Larsson\n"
268268 "\n"
269269 "Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
@@ -1074,10 +1074,9 @@ static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
10741074 REPARSE_POINT *reparse;
10751075
10761076 res = CALL_REPARSE_PLUGIN(ni, readlink, &buf);
1077- if (res) {
1077+ if (res || !buf) {
10781078 buf = strdup(ntfs_bad_reparse);
1079- if (!buf)
1080- res = -errno;
1079+ res = (buf ? 0 : -errno);
10811080 }
10821081 #else /* DISABLE_PLUGINS */
10831082 errno = 0;
@@ -3152,7 +3151,7 @@ static ntfs_inode *ntfs_check_access_xattr(fuse_req_t req,
31523151 || !(ctx->secure_flags & (1 << SECURITY_ACL))
31533152 || (setting && ctx->inherit))
31543153 && foracl) {
3155- if (ctx->silent)
3154+ if (ctx->silent && !ctx->security.mapping[MAPUSERS])
31563155 errno = 0;
31573156 else
31583157 errno = EOPNOTSUPP;
@@ -4411,7 +4410,8 @@ int main(int argc, char *argv[])
44114410 else {
44124411 ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
44134412 if (ctx->abs_mnt_point) {
4414- if (getcwd(ctx->abs_mnt_point,
4413+ if ((strlen(opts.mnt_point) < PATH_MAX)
4414+ && getcwd(ctx->abs_mnt_point,
44154415 PATH_MAX - strlen(opts.mnt_point) - 1)) {
44164416 strcat(ctx->abs_mnt_point, "/");
44174417 strcat(ctx->abs_mnt_point, opts.mnt_point);
@@ -4419,6 +4419,9 @@ int main(int argc, char *argv[])
44194419 /* Solaris also wants the absolute mount point */
44204420 opts.mnt_point = ctx->abs_mnt_point;
44214421 #endif /* defined(__sun) && defined (__SVR4) */
4422+ } else {
4423+ free(ctx->abs_mnt_point);
4424+ ctx->abs_mnt_point = (char*)NULL;
44224425 }
44234426 }
44244427 }
--- a/src/ntfs-3g.8.in
+++ b/src/ntfs-3g.8.in
@@ -52,6 +52,8 @@ hibernation and fast restarting :
5252 powercfg /h off
5353 .sp
5454 .RE
55+If either Windows is hibernated or its fast restart is enabled, partitions
56+on internal disks are forced to be mounted in read-only mode.
5557 .SS Access Handling and Security
5658 By default, files and directories are owned by the effective
5759 user and group of the mounting process, and everybody has
--- a/src/ntfs-3g.c
+++ b/src/ntfs-3g.c
@@ -2879,7 +2879,7 @@ static ntfs_inode *ntfs_check_access_xattr(struct SECURITY_CONTEXT *security,
28792879 || !(ctx->secure_flags & (1 << SECURITY_ACL))
28802880 || (setting && ctx->inherit))
28812881 && foracl) {
2882- if (ctx->silent)
2882+ if (ctx->silent && !ctx->security.mapping[MAPUSERS])
28832883 errno = 0;
28842884 else
28852885 errno = EOPNOTSUPP;
@@ -4148,7 +4148,8 @@ int main(int argc, char *argv[])
41484148 else {
41494149 ctx->abs_mnt_point = (char*)ntfs_malloc(PATH_MAX);
41504150 if (ctx->abs_mnt_point) {
4151- if (getcwd(ctx->abs_mnt_point,
4151+ if ((strlen(opts.mnt_point) < PATH_MAX)
4152+ && getcwd(ctx->abs_mnt_point,
41524153 PATH_MAX - strlen(opts.mnt_point) - 1)) {
41534154 strcat(ctx->abs_mnt_point, "/");
41544155 strcat(ctx->abs_mnt_point, opts.mnt_point);
@@ -4156,6 +4157,9 @@ int main(int argc, char *argv[])
41564157 /* Solaris also wants the absolute mount point */
41574158 opts.mnt_point = ctx->abs_mnt_point;
41584159 #endif /* defined(__sun) && defined (__SVR4) */
4160+ } else {
4161+ free(ctx->abs_mnt_point);
4162+ ctx->abs_mnt_point = (char*)NULL;
41594163 }
41604164 }
41614165 }
--- a/src/ntfs-3g_common.c
+++ b/src/ntfs-3g_common.c
@@ -1,7 +1,7 @@
11 /**
22 * ntfs-3g_common.c - Common definitions for ntfs-3g and lowntfs-3g.
33 *
4- * Copyright (c) 2010-2016 Jean-Pierre Andre
4+ * Copyright (c) 2010-2019 Jean-Pierre Andre
55 * Copyright (c) 2010 Erik Larsson
66 *
77 * This program/include file is free software; you can redistribute it and/or
@@ -801,7 +801,7 @@ const struct plugin_operations *select_reparse_plugin(ntfs_fuse_context_t *ctx,
801801 const struct plugin_operations *ops;
802802 void *handle;
803803 REPARSE_POINT *reparse;
804- le32 tag;
804+ le32 tag, seltag;
805805 plugin_list_t *plugin;
806806 plugin_init_t pinit;
807807
@@ -809,7 +809,8 @@ const struct plugin_operations *select_reparse_plugin(ntfs_fuse_context_t *ctx,
809809 reparse = ntfs_get_reparse_point(ni);
810810 if (reparse) {
811811 tag = reparse->reparse_tag;
812- for (plugin=ctx->plugins; plugin && (plugin->tag != tag);
812+ seltag = tag & IO_REPARSE_PLUGIN_SELECT;
813+ for (plugin=ctx->plugins; plugin && (plugin->tag != seltag);
813814 plugin = plugin->next) { }
814815 if (plugin) {
815816 ops = plugin->ops;
@@ -819,12 +820,12 @@ const struct plugin_operations *select_reparse_plugin(ntfs_fuse_context_t *ctx,
819820
820821 snprintf(name,sizeof(name), PLUGIN_DIR
821822 "/ntfs-plugin-%08lx.so",
822- (long)le32_to_cpu(tag));
823+ (long)le32_to_cpu(seltag));
823824 #else
824825 char name[64];
825826
826827 snprintf(name,sizeof(name), "ntfs-plugin-%08lx.so",
827- (long)le32_to_cpu(tag));
828+ (long)le32_to_cpu(seltag));
828829 #endif
829830 handle = dlopen(name, RTLD_LAZY);
830831 if (handle) {
@@ -833,13 +834,14 @@ const struct plugin_operations *select_reparse_plugin(ntfs_fuse_context_t *ctx,
833834 /* pinit() should set errno if it fails */
834835 ops = (*pinit)(tag);
835836 if (ops && register_reparse_plugin(ctx,
836- tag, ops, handle))
837+ seltag, ops, handle))
837838 ops = (struct plugin_operations*)NULL;
838839 } else
839840 errno = ELIBBAD;
840841 if (!ops)
841842 dlclose(handle);
842843 } else {
844+ errno = ELIBACC;
843845 if (!(ctx->errors_logged & ERR_PLUGIN)) {
844846 ntfs_log_perror(
845847 "Could not load plugin %s",
Show on old repository browser