From 621e96af7696aa1e35da94f17486e36f9f8f9f93 Mon Sep 17 00:00:00 2001 From: Release Configuration Management Date: Thu, 20 Dec 2012 10:52:13 -0500 Subject: [PATCH 01/10] New branch setup --- .gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 From b495315e3d1211be19db13ce8575e170637bd76c Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 20 Dec 2012 16:38:01 +0000 Subject: [PATCH 02/10] New package for RHEL 7 resolves: rhbz#819939 - Resync against Rawhide package. --- .gitignore | 6 + 20-ntfs-config-write-policy.fdi | 11 ++ libguestfs-winsupport.spec | 181 +++++++++++++++++ ...9163c9ef1f0cdbbf533317b291220c7fd1c7.patch | 42 ++++ ...70a8f67c77a7ce51246c23d2b2837bcff0c9.patch | 109 ++++++++++ ntfs-3g-junction-point-fix.patch | 187 ++++++++++++++++++ ....10.9-RC-ntfsck-unsupported-return-0.patch | 16 ++ sources | 1 + 8 files changed, 553 insertions(+) create mode 100644 20-ntfs-config-write-policy.fdi create mode 100644 libguestfs-winsupport.spec create mode 100644 ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch create mode 100644 ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch create mode 100644 ntfs-3g-junction-point-fix.patch create mode 100644 ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch create mode 100644 sources diff --git a/.gitignore b/.gitignore index e69de29..325cb73 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,6 @@ +*~ +*.rpm +.build*.log +clog +ntfs-3g_ntfsprogs-*.tgz +ntfs-3g_ntfsprogs-*/ diff --git a/20-ntfs-config-write-policy.fdi b/20-ntfs-config-write-policy.fdi new file mode 100644 index 0000000..82731c5 --- /dev/null +++ b/20-ntfs-config-write-policy.fdi @@ -0,0 +1,11 @@ + + + + + ntfs-3g + ntfs-3g + locale= + + + + diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec new file mode 100644 index 0000000..64ad322 --- /dev/null +++ b/libguestfs-winsupport.spec @@ -0,0 +1,181 @@ +%global debug_package %{nil} + +%global ntfs_version 2012.1.15 + +Name: libguestfs-winsupport +Version: 7.0 +Release: 1%{?dist} +Summary: Add support for Windows guests to libguestfs + +License: GPLv2+ +ExclusiveArch: x86_64 + +# This package shouldn't be installed without installing the base +# libguestfs package. +Requires: libguestfs >= 1:1.20.0 + +# Needs fuse-libs (RHBZ#599300). +Requires: fuse-libs + +# Source and patches for ntfs. Try to keep this in step with Fedora. +Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.tgz +Source1: 20-ntfs-config-write-policy.fdi + +Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch +Patch1: ntfs-3g-junction-point-fix.patch +# Windows 8 safety checks +Patch2: ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch +Patch3: ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch + +BuildRequires: fuse-devel +Requires: fuse + +BuildRequires: libtool, libattr-devel +BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel + +# Required by binaries in the supermin appliance. +Requires: libgcrypt, gnutls, p11-kit, libtasn1, zlib + + +%description +This optional package adds support for Windows guests (NTFS) to the +base libguestfs Red Hat Enterprise Linux (RHEL) package. This is +useful for examining Windows virtual machines running on RHEL, and for +performing V2V of Windows guests from another hypervisor to RHEL. + +To enable Windows support, simply install this package. + +To disable Windows support, uninstall this package. + + +%prep +%setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} +%patch0 -p1 -b .unsupported +%patch1 -p1 -b .junction-fix +%patch2 -p1 -b .4d0b9163 +%patch3 -p1 -b .559270a8 + + +%build +CFLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64" +%configure \ + --disable-static \ + --disable-ldconfig \ + --with-fuse=external \ + --exec-prefix=/ \ + --enable-crypto \ + --enable-extras +make %{?_smp_mflags} LIBTOOL=%{_bindir}/libtool + +# Create a README file. +cat <<'EOF' > README +This optional package adds support for Windows guests (NTFS) to the +base libguestfs Red Hat Enterprise Linux (RHEL) package. This is +useful for examining Windows virtual machines running on RHEL, and for +performing V2V of Windows guests from another hypervisor to RHEL. + +The package contains NTFS programs from ntfsprogs %{ntfsprogs_version} +and NTFS FUSE filesystem support from ntfs-3g %{ntfs_3g_version}. +EOF + + +%install +mkdir ntfs +export DESTDIR=$(pwd)/ntfs + +#----- Standard package install rule, but installing into ntfs/ subdir. +make LIBTOOL=%{_bindir}/libtool install +rm -rf $DESTDIR%{_libdir}/*.la +rm -rf $DESTDIR%{_libdir}/*.a + +rm -rf $DESTDIR%{_sbindir}/mount.ntfs-3g +cp -a $DESTDIR%{_bindir}/ntfs-3g $DESTDIR%{_sbindir}/mount.ntfs-3g + +# Actually make some symlinks for simplicity... +# ... since we're obsoleting ntfsprogs-fuse +pushd $DESTDIR%{_bindir} +ln -s ntfs-3g ntfsmount +popd +pushd $DESTDIR%{_sbindir} +ln -s mount.ntfs-3g mount.ntfs-fuse +# And since there is no other package in Fedora that provides an ntfs +# mount... +ln -s mount.ntfs-3g mount.ntfs +# Need this for fsck to find it +ln -s ../bin/ntfsck fsck.ntfs +popd +mv $DESTDIR/sbin/* $DESTDIR%{_sbindir} +rmdir $DESTDIR/sbin + +# We get this on our own, thanks. +rm -rf $DESTDIR%{_defaultdocdir}/%{name}/README + +mkdir -p $DESTDIR%{_datadir}/hal/fdi/policy/10osvendor/ +cp -a %{SOURCE1} $DESTDIR%{_datadir}/hal/fdi/policy/10osvendor/ +#----- End of standard package install rule. + +# Copy the files we need to a static supermin appliance. +rm -f files +echo . >> files +echo usr >> files +echo usr/bin >> files +echo usr/lib64 >> files +echo usr/sbin >> files +pushd ntfs +find | egrep '/s?bin/|/lib(64)/' >> ../files +cpio --quiet -o -H newc < ../files > ../ntfs.img +popd + +# Supporting hostfiles. +cat <<'EOF' > ntfs.hostfiles +. +./usr +.%{_libdir} +.%{_libdir}/libfuse.so.* +.%{_libdir}/libgcrypt.so.* +.%{_libdir}/libgnutls.so.* +.%{_libdir}/libgpg-error.so.* +.%{_libdir}/libp11-kit.so.* +.%{_libdir}/libtasn1.so.* +.%{_libdir}/libz.so.* +./lib64 +./lib64/libfuse.so.* +EOF + +mkdir -p $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d +install -m 0644 ntfs.img $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d/ +install -m 0644 ntfs.hostfiles $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d/ + + +%files +%doc COPYING README +%{_libdir}/guestfs/supermin.d/ntfs.img +%{_libdir}/guestfs/supermin.d/ntfs.hostfiles + + +%changelog +* Thu Dec 20 2011 Richard W.M. Jones - 7.0-1 +- New package for RHEL 7 + resolves: rhbz#819939 +- Resync against Rawhide package. + +* Mon Mar 28 2011 Richard W.M. Jones - 1.0-7 +- Disable debuginfo package. + resolves: RHBZ#691555. + +* Tue Mar 8 2011 Richard W.M. Jones - 1.0-6 +- Require libguestfs 1.7.17 (newer version in RHEL 6.1). +- Require febootstrap-supermin-helper instead of febootstrap + resolves: RHBZ#670299. + +* Thu Jul 1 2010 Richard W.M. Jones - 1.0-5 +- Make sure intermediate lib* directories are created in hostfiles (RHBZ#603429) + +* Thu Jun 3 2010 Richard W.M. Jones - 1.0-4 +- Requires fuse-libs (RHBZ#599300). + +* Fri May 21 2010 Richard W.M. Jones - 1.0-3 +- ExclusiveArch x86_64. + +* Tue May 18 2010 Richard W.M. Jones - 1.0-2 +- Package Windows support for libguestfs. diff --git a/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch b/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch new file mode 100644 index 0000000..ec1a762 --- /dev/null +++ b/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch @@ -0,0 +1,42 @@ +From 4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7 Mon Sep 17 00:00:00 2001 +From: =?utf8?q?Jean-Pierre=20Andr=C3=A9?= +Date: Wed, 12 Sep 2012 09:42:24 +0200 +Subject: [PATCH] Accepted processing restart pages v 2.0 with no warning (used by Windows 8) + +In the $LogFile, Windows 8 defines restart pages with version 2.0. +The checks designed for version 1.1 appear to apply, so accept v 2.0 +and apply the usual checks. +--- + libntfs-3g/logfile.c | 15 +++++++++------ + 1 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/libntfs-3g/logfile.c b/libntfs-3g/logfile.c +index a4f00d5..83811fa 100644 +--- a/libntfs-3g/logfile.c ++++ b/libntfs-3g/logfile.c +@@ -84,13 +84,16 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos) + "position in $LogFile.\n"); + return FALSE; + } +- /* We only know how to handle version 1.1. */ +- if (sle16_to_cpu(rp->major_ver) != 1 || +- sle16_to_cpu(rp->minor_ver) != 1) { ++ /* We only know how to handle version 1.1 and 2.0. */ ++ if (((rp->major_ver != const_cpu_to_le16(1)) ++ || (rp->minor_ver != const_cpu_to_le16(1))) ++ && ((rp->major_ver != const_cpu_to_le16(2)) ++ || (rp->minor_ver != const_cpu_to_le16(0)))) { + ntfs_log_error("$LogFile version %i.%i is not " +- "supported. (This driver supports version " +- "1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver), +- (int)sle16_to_cpu(rp->minor_ver)); ++ "supported.\n (This driver supports version " ++ "1.1 and 2.0 only.)\n", ++ (int)sle16_to_cpu(rp->major_ver), ++ (int)sle16_to_cpu(rp->minor_ver)); + return FALSE; + } + /* +-- +1.7.4.1 + diff --git a/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch b/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch new file mode 100644 index 0000000..9b92298 --- /dev/null +++ b/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch @@ -0,0 +1,109 @@ +diff -up ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c.559270a8 ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c +--- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c.559270a8 2012-10-04 16:14:28.439011268 -0400 ++++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c 2012-10-04 16:14:28.443011272 -0400 +@@ -84,7 +84,12 @@ static BOOL ntfs_check_restart_page_head + "position in $LogFile.\n"); + return FALSE; + } +- /* We only know how to handle version 1.1 and 2.0. */ ++ /* ++ * We only know how to handle version 1.1 and 2.0, though ++ * version 2.0 is probably related to cached metadata in ++ * Windows 8, and we will refuse to mount. ++ * Nevertheless, do all the relevant checks before rejecting. ++ */ + if (((rp->major_ver != const_cpu_to_le16(1)) + || (rp->minor_ver != const_cpu_to_le16(1))) + && ((rp->major_ver != const_cpu_to_le16(2)) +diff -up ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c.559270a8 ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c +--- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c.559270a8 2012-01-15 08:26:14.000000000 -0500 ++++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c 2012-10-04 16:16:55.324071714 -0400 +@@ -89,13 +89,9 @@ static const char *corrupt_volume_msg = + "for more details.\n"; + + static const char *hibernated_volume_msg = +-"The NTFS partition is hibernated. Please resume and shutdown Windows\n" +-"properly, or mount the volume read-only with the 'ro' mount option, or\n" +-"mount the volume read-write with the 'remove_hiberfile' mount option.\n" +-"For example type on the command line:\n" +-"\n" +-" mount -t ntfs-3g -o remove_hiberfile %s %s\n" +-"\n"; ++"The NTFS partition is in an unsafe state. Please resume and shutdown\n" ++"Windows fully (no hibernation or fast restarting), or mount the volume\n" ++"read-only with the 'ro' mount option.\n"; + + static const char *unclean_journal_msg = + "Write access is denied because the disk wasn't safely powered\n" +@@ -649,6 +645,24 @@ static int ntfs_volume_check_logfile(ntf + + if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) + err = EOPNOTSUPP; ++ /* ++ * If the latest restart page was identified as version ++ * 2.0, then Windows may have kept a cached copy of ++ * metadata for fast restarting, and we should not mount. ++ * Hibernation will be seen the same way on a non ++ * Windows-system partition, so we have to use the same ++ * error code (EPERM). ++ * The restart page may also be identified as version 2.0 ++ * when access to the file system is terminated abruptly ++ * by unplugging or power cut, so mounting is also rejected ++ * after such an event. ++ */ ++ if (rp ++ && (rp->major_ver == const_cpu_to_le16(2)) ++ && (rp->minor_ver == const_cpu_to_le16(0))) { ++ ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n"); ++ err = EPERM; ++ } + free(rp); + ntfs_attr_close(na); + out: +@@ -1200,7 +1214,8 @@ ntfs_volume *ntfs_device_mount(struct nt + ntfs_volume_check_hiberfile(vol, 1) < 0) + goto error_exit; + if (ntfs_volume_check_logfile(vol) < 0) { +- if (!(flags & MS_RECOVER)) ++ /* Always reject cached metadata for now */ ++ if (!(flags & MS_RECOVER) || (errno == EPERM)) + goto error_exit; + ntfs_log_info("The file system wasn't safely " + "closed on Windows. Fixing.\n"); +@@ -1642,6 +1657,10 @@ int ntfs_volume_error(int err) + ret = NTFS_VOLUME_CORRUPT; + break; + case EPERM: ++ /* ++ * Hibernation and fast restarting are seen the ++ * same way on a non Windows-system partition. ++ */ + ret = NTFS_VOLUME_HIBERNATED; + break; + case EOPNOTSUPP: +diff -up ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in.559270a8 ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in +--- ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in.559270a8 2012-01-15 08:26:14.000000000 -0500 ++++ ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in 2012-10-04 16:14:28.445011274 -0400 +@@ -36,6 +36,22 @@ a few differences mentioned below in rel + .PP + The \fIvolume\fR to be mounted can be either a block device or + an image file. ++.SS Windows hibernation and fast restarting ++On computers which can be dual-booted into Windows or Linux, Windows has ++to be fully shut down before booting into Linux, otherwise the NTFS file ++systems on internal disks may be left in an inconsistent state and changes ++made by Linux may be ignored by Windows. ++.P ++So, Windows may not be left in hibernation when starting Linux, in order ++to avoid inconsistencies. Moreover, the fast restart feature available on ++recent Windows systems has to be disabled. This can be achieved by issuing ++as an Administrator the Windows command which disables both ++hibernation and fast restarting : ++.RS ++.sp ++powercfg /h off ++.sp ++.RE + .SS Access Handling and Security + By default, files and directories are owned by the effective + user and group of the mounting process, and everybody has diff --git a/ntfs-3g-junction-point-fix.patch b/ntfs-3g-junction-point-fix.patch new file mode 100644 index 0000000..90c72ae --- /dev/null +++ b/ntfs-3g-junction-point-fix.patch @@ -0,0 +1,187 @@ +--- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c.ref 2012-08-18 09:46:22.000000000 +0200 ++++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c 2012-08-18 11:07:57.000000000 +0200 +@@ -867,6 +867,83 @@ + INDEX_TYPE_ALLOCATION, /* index allocation */ + } INDEX_TYPE; + ++/* ++ * Decode Interix file types ++ * ++ * Non-Interix types are returned as plain files, because a ++ * Windows user may force patterns very similar to Interix. ++ */ ++ ++static u32 ntfs_interix_types(ntfs_inode *ni) ++{ ++ ntfs_attr *na; ++ u32 dt_type; ++ le64 magic; ++ ++ dt_type = NTFS_DT_UNKNOWN; ++ na = ntfs_attr_open(ni, AT_DATA, NULL, 0); ++ if (na) { ++ /* Unrecognized patterns (eg HID + SYST) are plain files */ ++ dt_type = NTFS_DT_REG; ++ if (na->data_size <= 1) { ++ if (!(ni->flags & FILE_ATTR_HIDDEN)) ++ dt_type = (na->data_size ? ++ NTFS_DT_SOCK : NTFS_DT_FIFO); ++ } else { ++ if ((na->data_size >= (s64)sizeof(magic)) ++ && (ntfs_attr_pread(na, 0, sizeof(magic), &magic) ++ == sizeof(magic))) { ++ if (magic == INTX_SYMBOLIC_LINK) ++ dt_type = NTFS_DT_LNK; ++ else if (magic == INTX_BLOCK_DEVICE) ++ dt_type = NTFS_DT_BLK; ++ else if (magic == INTX_CHARACTER_DEVICE) ++ dt_type = NTFS_DT_CHR; ++ } ++ } ++ ntfs_attr_close(na); ++ } ++ return (dt_type); ++} ++ ++/* ++ * Decode file types ++ * ++ * Better only use for Interix types and junctions, ++ * unneeded complexity when used for plain files or directories ++ * ++ * Error cases are logged and returned as unknown. ++ */ ++ ++static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref, FILE_ATTR_FLAGS attributes) ++{ ++ ntfs_inode *ni; ++ u32 dt_type; ++ ++ dt_type = NTFS_DT_UNKNOWN; ++ ni = ntfs_inode_open(dir_ni->vol, mref); ++ if (ni) { ++ if ((attributes & FILE_ATTR_REPARSE_POINT) ++ && ntfs_possible_symlink(ni)) ++ dt_type = NTFS_DT_LNK; ++ else ++ if ((attributes & FILE_ATTR_SYSTEM) ++ && !(attributes & FILE_ATTR_I30_INDEX_PRESENT)) ++ dt_type = ntfs_interix_types(ni); ++ else ++ dt_type = (attributes ++ & FILE_ATTR_I30_INDEX_PRESENT ++ ? NTFS_DT_DIR : NTFS_DT_REG); ++ if (ntfs_inode_close(ni)) { ++ /* anything special to do ? */ ++ } ++ } ++ if (dt_type == NTFS_DT_UNKNOWN) ++ ntfs_log_error("Could not decode the type of inode %lld\n", ++ (long long)MREF(mref)); ++ return (dt_type); ++} ++ + /** + * ntfs_filldir - ntfs specific filldir method + * @dir_ni: ntfs inode of current directory +@@ -901,19 +978,23 @@ + dir_ni->vol->mft_record_size; + else /* if (index_type == INDEX_TYPE_ROOT) */ + *pos = (u8*)ie - (u8*)iu.ir; ++ mref = le64_to_cpu(ie->indexed_file); ++ metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); + /* Skip root directory self reference entry. */ + if (MREF_LE(ie->indexed_file) == FILE_root) + return 0; +- if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT) ++ if ((ie->key.file_name.file_attributes ++ & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM)) ++ && !metadata) ++ dt_type = ntfs_dir_entry_type(dir_ni, mref, ++ ie->key.file_name.file_attributes); ++ else if (ie->key.file_name.file_attributes ++ & FILE_ATTR_I30_INDEX_PRESENT) + dt_type = NTFS_DT_DIR; +- else if (fn->file_attributes & FILE_ATTR_SYSTEM) +- dt_type = NTFS_DT_UNKNOWN; + else + dt_type = NTFS_DT_REG; + + /* return metadata files and hidden files if requested */ +- mref = le64_to_cpu(ie->indexed_file); +- metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); + if ((!metadata && (NVolShowHidFiles(dir_ni->vol) + || !(fn->file_attributes & FILE_ATTR_HIDDEN))) + || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol) +--- ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c.ref 2012-08-18 09:44:57.000000000 +0200 ++++ ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c 2012-08-18 09:47:41.000000000 +0200 +@@ -1017,10 +1017,30 @@ + } else { + struct stat st = { .st_ino = MREF(mref) }; + +- if (dt_type == NTFS_DT_REG) +- st.st_mode = S_IFREG | (0777 & ~ctx->fmask); +- else if (dt_type == NTFS_DT_DIR) ++ switch (dt_type) { ++ case NTFS_DT_DIR : + st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); ++ break; ++ case NTFS_DT_LNK : ++ st.st_mode = S_IFLNK | 0777; ++ break; ++ case NTFS_DT_FIFO : ++ st.st_mode = S_IFIFO; ++ break; ++ case NTFS_DT_SOCK : ++ st.st_mode = S_IFSOCK; ++ break; ++ case NTFS_DT_BLK : ++ st.st_mode = S_IFBLK; ++ break; ++ case NTFS_DT_CHR : ++ st.st_mode = S_IFCHR; ++ break; ++ default : /* unexpected types shown as plain files */ ++ case NTFS_DT_REG : ++ st.st_mode = S_IFREG | (0777 & ~ctx->fmask); ++ break; ++ } + + #if defined(__APPLE__) || defined(__DARWIN__) + /* +--- ntfs-3g_ntfsprogs-2012.1.15/src/lowntfs-3g.c.ref 2012-08-18 09:44:57.000000000 +0200 ++++ ntfs-3g_ntfsprogs-2012.1.15/src/lowntfs-3g.c 2012-08-18 09:47:41.000000000 +0200 +@@ -920,10 +920,30 @@ + if (MREF(mref) > 1) { + struct stat st = { .st_ino = MREF(mref) }; + +- if (dt_type == NTFS_DT_REG) +- st.st_mode = S_IFREG | (0777 & ~ctx->fmask); +- else if (dt_type == NTFS_DT_DIR) ++ switch (dt_type) { ++ case NTFS_DT_DIR : + st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); ++ break; ++ case NTFS_DT_LNK : ++ st.st_mode = S_IFLNK | 0777; ++ break; ++ case NTFS_DT_FIFO : ++ st.st_mode = S_IFIFO; ++ break; ++ case NTFS_DT_SOCK : ++ st.st_mode = S_IFSOCK; ++ break; ++ case NTFS_DT_BLK : ++ st.st_mode = S_IFBLK; ++ break; ++ case NTFS_DT_CHR : ++ st.st_mode = S_IFCHR; ++ break; ++ default : /* unexpected types shown as plain files */ ++ case NTFS_DT_REG : ++ st.st_mode = S_IFREG | (0777 & ~ctx->fmask); ++ break; ++ } + + #if defined(__APPLE__) || defined(__DARWIN__) + /* diff --git a/ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch b/ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch new file mode 100644 index 0000000..8fd39c6 --- /dev/null +++ b/ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch @@ -0,0 +1,16 @@ +diff -up ntfs-3g_ntfsprogs-2011.10.9-RC/ntfsprogs/ntfsck.c.OLD ntfs-3g_ntfsprogs-2011.10.9-RC/ntfsprogs/ntfsck.c +--- ntfs-3g_ntfsprogs-2011.10.9-RC/ntfsprogs/ntfsck.c.OLD 2011-10-11 10:24:02.381335115 -0400 ++++ ntfs-3g_ntfsprogs-2011.10.9-RC/ntfsprogs/ntfsck.c 2011-10-11 10:26:41.513559206 -0400 +@@ -877,7 +877,11 @@ int main(int argc, char **argv) + if (errors) + return 2; + if (unsupported) +- return 1; ++ ntfs_log_info("ntfsck was unable to run properly.\n"); ++ // If we return 1 here, we fail for ntfs services fscking on boot just because ++ // ntfsck isn't smart enough to handle 99% of cases. So, we just return 0. ++ // return 1; ++ return 0; + return 0; + } + diff --git a/sources b/sources new file mode 100644 index 0000000..89d5b8e --- /dev/null +++ b/sources @@ -0,0 +1 @@ +341acae00a290cab9b00464db65015cc ntfs-3g_ntfsprogs-2012.1.15.tgz From b98a1ed2c301050008f51e83d9be3472c2a07dc2 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 3 Apr 2013 15:46:52 +0100 Subject: [PATCH 03/10] Resync against Rawhide package (ntfs-3g 2013.1.13). - Drop HAL file since HAL is dead. resolves: rhbz#819939 --- 20-ntfs-config-write-policy.fdi | 11 -- libguestfs-winsupport.spec | 27 ++- ...9163c9ef1f0cdbbf533317b291220c7fd1c7.patch | 42 ---- ...70a8f67c77a7ce51246c23d2b2837bcff0c9.patch | 109 ---------- ntfs-3g-junction-point-fix.patch | 187 ------------------ sources | 2 +- 6 files changed, 12 insertions(+), 366 deletions(-) delete mode 100644 20-ntfs-config-write-policy.fdi delete mode 100644 ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch delete mode 100644 ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch delete mode 100644 ntfs-3g-junction-point-fix.patch diff --git a/20-ntfs-config-write-policy.fdi b/20-ntfs-config-write-policy.fdi deleted file mode 100644 index 82731c5..0000000 --- a/20-ntfs-config-write-policy.fdi +++ /dev/null @@ -1,11 +0,0 @@ - - - - - ntfs-3g - ntfs-3g - locale= - - - - diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 64ad322..7d67173 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -1,10 +1,10 @@ %global debug_package %{nil} -%global ntfs_version 2012.1.15 +%global ntfs_version 2013.1.13 Name: libguestfs-winsupport Version: 7.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Add support for Windows guests to libguestfs License: GPLv2+ @@ -19,13 +19,8 @@ Requires: fuse-libs # Source and patches for ntfs. Try to keep this in step with Fedora. Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.tgz -Source1: 20-ntfs-config-write-policy.fdi Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch -Patch1: ntfs-3g-junction-point-fix.patch -# Windows 8 safety checks -Patch2: ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch -Patch3: ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch BuildRequires: fuse-devel Requires: fuse @@ -51,9 +46,6 @@ To disable Windows support, uninstall this package. %prep %setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} %patch0 -p1 -b .unsupported -%patch1 -p1 -b .junction-fix -%patch2 -p1 -b .4d0b9163 -%patch3 -p1 -b .559270a8 %build @@ -64,7 +56,7 @@ CFLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64" --with-fuse=external \ --exec-prefix=/ \ --enable-crypto \ - --enable-extras + --enable-extras make %{?_smp_mflags} LIBTOOL=%{_bindir}/libtool # Create a README file. @@ -74,8 +66,8 @@ base libguestfs Red Hat Enterprise Linux (RHEL) package. This is useful for examining Windows virtual machines running on RHEL, and for performing V2V of Windows guests from another hypervisor to RHEL. -The package contains NTFS programs from ntfsprogs %{ntfsprogs_version} -and NTFS FUSE filesystem support from ntfs-3g %{ntfs_3g_version}. +The package contains NTFS FUSE filesystem support from +ntfs-3g %{ntfs_3g_version}. EOF @@ -110,8 +102,6 @@ rmdir $DESTDIR/sbin # We get this on our own, thanks. rm -rf $DESTDIR%{_defaultdocdir}/%{name}/README -mkdir -p $DESTDIR%{_datadir}/hal/fdi/policy/10osvendor/ -cp -a %{SOURCE1} $DESTDIR%{_datadir}/hal/fdi/policy/10osvendor/ #----- End of standard package install rule. # Copy the files we need to a static supermin appliance. @@ -154,7 +144,12 @@ install -m 0644 ntfs.hostfiles $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d/ %changelog -* Thu Dec 20 2011 Richard W.M. Jones - 7.0-1 +* Wed Apr 3 2013 Richard W.M. Jones - 7.0-2 +- Resync against Rawhide package (ntfs-3g 2013.1.13). +- Drop HAL file since HAL is dead. + resolves: rhbz#819939 + +* Thu Dec 20 2012 Richard W.M. Jones - 7.0-1 - New package for RHEL 7 resolves: rhbz#819939 - Resync against Rawhide package. diff --git a/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch b/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch deleted file mode 100644 index ec1a762..0000000 --- a/ntfs-3g-4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 4d0b9163c9ef1f0cdbbf533317b291220c7fd1c7 Mon Sep 17 00:00:00 2001 -From: =?utf8?q?Jean-Pierre=20Andr=C3=A9?= -Date: Wed, 12 Sep 2012 09:42:24 +0200 -Subject: [PATCH] Accepted processing restart pages v 2.0 with no warning (used by Windows 8) - -In the $LogFile, Windows 8 defines restart pages with version 2.0. -The checks designed for version 1.1 appear to apply, so accept v 2.0 -and apply the usual checks. ---- - libntfs-3g/logfile.c | 15 +++++++++------ - 1 files changed, 9 insertions(+), 6 deletions(-) - -diff --git a/libntfs-3g/logfile.c b/libntfs-3g/logfile.c -index a4f00d5..83811fa 100644 ---- a/libntfs-3g/logfile.c -+++ b/libntfs-3g/logfile.c -@@ -84,13 +84,16 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos) - "position in $LogFile.\n"); - return FALSE; - } -- /* We only know how to handle version 1.1. */ -- if (sle16_to_cpu(rp->major_ver) != 1 || -- sle16_to_cpu(rp->minor_ver) != 1) { -+ /* We only know how to handle version 1.1 and 2.0. */ -+ if (((rp->major_ver != const_cpu_to_le16(1)) -+ || (rp->minor_ver != const_cpu_to_le16(1))) -+ && ((rp->major_ver != const_cpu_to_le16(2)) -+ || (rp->minor_ver != const_cpu_to_le16(0)))) { - ntfs_log_error("$LogFile version %i.%i is not " -- "supported. (This driver supports version " -- "1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver), -- (int)sle16_to_cpu(rp->minor_ver)); -+ "supported.\n (This driver supports version " -+ "1.1 and 2.0 only.)\n", -+ (int)sle16_to_cpu(rp->major_ver), -+ (int)sle16_to_cpu(rp->minor_ver)); - return FALSE; - } - /* --- -1.7.4.1 - diff --git a/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch b/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch deleted file mode 100644 index 9b92298..0000000 --- a/ntfs-3g-559270a8f67c77a7ce51246c23d2b2837bcff0c9.patch +++ /dev/null @@ -1,109 +0,0 @@ -diff -up ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c.559270a8 ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c ---- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c.559270a8 2012-10-04 16:14:28.439011268 -0400 -+++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/logfile.c 2012-10-04 16:14:28.443011272 -0400 -@@ -84,7 +84,12 @@ static BOOL ntfs_check_restart_page_head - "position in $LogFile.\n"); - return FALSE; - } -- /* We only know how to handle version 1.1 and 2.0. */ -+ /* -+ * We only know how to handle version 1.1 and 2.0, though -+ * version 2.0 is probably related to cached metadata in -+ * Windows 8, and we will refuse to mount. -+ * Nevertheless, do all the relevant checks before rejecting. -+ */ - if (((rp->major_ver != const_cpu_to_le16(1)) - || (rp->minor_ver != const_cpu_to_le16(1))) - && ((rp->major_ver != const_cpu_to_le16(2)) -diff -up ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c.559270a8 ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c ---- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c.559270a8 2012-01-15 08:26:14.000000000 -0500 -+++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/volume.c 2012-10-04 16:16:55.324071714 -0400 -@@ -89,13 +89,9 @@ static const char *corrupt_volume_msg = - "for more details.\n"; - - static const char *hibernated_volume_msg = --"The NTFS partition is hibernated. Please resume and shutdown Windows\n" --"properly, or mount the volume read-only with the 'ro' mount option, or\n" --"mount the volume read-write with the 'remove_hiberfile' mount option.\n" --"For example type on the command line:\n" --"\n" --" mount -t ntfs-3g -o remove_hiberfile %s %s\n" --"\n"; -+"The NTFS partition is in an unsafe state. Please resume and shutdown\n" -+"Windows fully (no hibernation or fast restarting), or mount the volume\n" -+"read-only with the 'ro' mount option.\n"; - - static const char *unclean_journal_msg = - "Write access is denied because the disk wasn't safely powered\n" -@@ -649,6 +645,24 @@ static int ntfs_volume_check_logfile(ntf - - if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) - err = EOPNOTSUPP; -+ /* -+ * If the latest restart page was identified as version -+ * 2.0, then Windows may have kept a cached copy of -+ * metadata for fast restarting, and we should not mount. -+ * Hibernation will be seen the same way on a non -+ * Windows-system partition, so we have to use the same -+ * error code (EPERM). -+ * The restart page may also be identified as version 2.0 -+ * when access to the file system is terminated abruptly -+ * by unplugging or power cut, so mounting is also rejected -+ * after such an event. -+ */ -+ if (rp -+ && (rp->major_ver == const_cpu_to_le16(2)) -+ && (rp->minor_ver == const_cpu_to_le16(0))) { -+ ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n"); -+ err = EPERM; -+ } - free(rp); - ntfs_attr_close(na); - out: -@@ -1200,7 +1214,8 @@ ntfs_volume *ntfs_device_mount(struct nt - ntfs_volume_check_hiberfile(vol, 1) < 0) - goto error_exit; - if (ntfs_volume_check_logfile(vol) < 0) { -- if (!(flags & MS_RECOVER)) -+ /* Always reject cached metadata for now */ -+ if (!(flags & MS_RECOVER) || (errno == EPERM)) - goto error_exit; - ntfs_log_info("The file system wasn't safely " - "closed on Windows. Fixing.\n"); -@@ -1642,6 +1657,10 @@ int ntfs_volume_error(int err) - ret = NTFS_VOLUME_CORRUPT; - break; - case EPERM: -+ /* -+ * Hibernation and fast restarting are seen the -+ * same way on a non Windows-system partition. -+ */ - ret = NTFS_VOLUME_HIBERNATED; - break; - case EOPNOTSUPP: -diff -up ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in.559270a8 ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in ---- ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in.559270a8 2012-01-15 08:26:14.000000000 -0500 -+++ ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.8.in 2012-10-04 16:14:28.445011274 -0400 -@@ -36,6 +36,22 @@ a few differences mentioned below in rel - .PP - The \fIvolume\fR to be mounted can be either a block device or - an image file. -+.SS Windows hibernation and fast restarting -+On computers which can be dual-booted into Windows or Linux, Windows has -+to be fully shut down before booting into Linux, otherwise the NTFS file -+systems on internal disks may be left in an inconsistent state and changes -+made by Linux may be ignored by Windows. -+.P -+So, Windows may not be left in hibernation when starting Linux, in order -+to avoid inconsistencies. Moreover, the fast restart feature available on -+recent Windows systems has to be disabled. This can be achieved by issuing -+as an Administrator the Windows command which disables both -+hibernation and fast restarting : -+.RS -+.sp -+powercfg /h off -+.sp -+.RE - .SS Access Handling and Security - By default, files and directories are owned by the effective - user and group of the mounting process, and everybody has diff --git a/ntfs-3g-junction-point-fix.patch b/ntfs-3g-junction-point-fix.patch deleted file mode 100644 index 90c72ae..0000000 --- a/ntfs-3g-junction-point-fix.patch +++ /dev/null @@ -1,187 +0,0 @@ ---- ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c.ref 2012-08-18 09:46:22.000000000 +0200 -+++ ntfs-3g_ntfsprogs-2012.1.15/libntfs-3g/dir.c 2012-08-18 11:07:57.000000000 +0200 -@@ -867,6 +867,83 @@ - INDEX_TYPE_ALLOCATION, /* index allocation */ - } INDEX_TYPE; - -+/* -+ * Decode Interix file types -+ * -+ * Non-Interix types are returned as plain files, because a -+ * Windows user may force patterns very similar to Interix. -+ */ -+ -+static u32 ntfs_interix_types(ntfs_inode *ni) -+{ -+ ntfs_attr *na; -+ u32 dt_type; -+ le64 magic; -+ -+ dt_type = NTFS_DT_UNKNOWN; -+ na = ntfs_attr_open(ni, AT_DATA, NULL, 0); -+ if (na) { -+ /* Unrecognized patterns (eg HID + SYST) are plain files */ -+ dt_type = NTFS_DT_REG; -+ if (na->data_size <= 1) { -+ if (!(ni->flags & FILE_ATTR_HIDDEN)) -+ dt_type = (na->data_size ? -+ NTFS_DT_SOCK : NTFS_DT_FIFO); -+ } else { -+ if ((na->data_size >= (s64)sizeof(magic)) -+ && (ntfs_attr_pread(na, 0, sizeof(magic), &magic) -+ == sizeof(magic))) { -+ if (magic == INTX_SYMBOLIC_LINK) -+ dt_type = NTFS_DT_LNK; -+ else if (magic == INTX_BLOCK_DEVICE) -+ dt_type = NTFS_DT_BLK; -+ else if (magic == INTX_CHARACTER_DEVICE) -+ dt_type = NTFS_DT_CHR; -+ } -+ } -+ ntfs_attr_close(na); -+ } -+ return (dt_type); -+} -+ -+/* -+ * Decode file types -+ * -+ * Better only use for Interix types and junctions, -+ * unneeded complexity when used for plain files or directories -+ * -+ * Error cases are logged and returned as unknown. -+ */ -+ -+static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref, FILE_ATTR_FLAGS attributes) -+{ -+ ntfs_inode *ni; -+ u32 dt_type; -+ -+ dt_type = NTFS_DT_UNKNOWN; -+ ni = ntfs_inode_open(dir_ni->vol, mref); -+ if (ni) { -+ if ((attributes & FILE_ATTR_REPARSE_POINT) -+ && ntfs_possible_symlink(ni)) -+ dt_type = NTFS_DT_LNK; -+ else -+ if ((attributes & FILE_ATTR_SYSTEM) -+ && !(attributes & FILE_ATTR_I30_INDEX_PRESENT)) -+ dt_type = ntfs_interix_types(ni); -+ else -+ dt_type = (attributes -+ & FILE_ATTR_I30_INDEX_PRESENT -+ ? NTFS_DT_DIR : NTFS_DT_REG); -+ if (ntfs_inode_close(ni)) { -+ /* anything special to do ? */ -+ } -+ } -+ if (dt_type == NTFS_DT_UNKNOWN) -+ ntfs_log_error("Could not decode the type of inode %lld\n", -+ (long long)MREF(mref)); -+ return (dt_type); -+} -+ - /** - * ntfs_filldir - ntfs specific filldir method - * @dir_ni: ntfs inode of current directory -@@ -901,19 +978,23 @@ - dir_ni->vol->mft_record_size; - else /* if (index_type == INDEX_TYPE_ROOT) */ - *pos = (u8*)ie - (u8*)iu.ir; -+ mref = le64_to_cpu(ie->indexed_file); -+ metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); - /* Skip root directory self reference entry. */ - if (MREF_LE(ie->indexed_file) == FILE_root) - return 0; -- if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT) -+ if ((ie->key.file_name.file_attributes -+ & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM)) -+ && !metadata) -+ dt_type = ntfs_dir_entry_type(dir_ni, mref, -+ ie->key.file_name.file_attributes); -+ else if (ie->key.file_name.file_attributes -+ & FILE_ATTR_I30_INDEX_PRESENT) - dt_type = NTFS_DT_DIR; -- else if (fn->file_attributes & FILE_ATTR_SYSTEM) -- dt_type = NTFS_DT_UNKNOWN; - else - dt_type = NTFS_DT_REG; - - /* return metadata files and hidden files if requested */ -- mref = le64_to_cpu(ie->indexed_file); -- metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); - if ((!metadata && (NVolShowHidFiles(dir_ni->vol) - || !(fn->file_attributes & FILE_ATTR_HIDDEN))) - || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol) ---- ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c.ref 2012-08-18 09:44:57.000000000 +0200 -+++ ntfs-3g_ntfsprogs-2012.1.15/src/ntfs-3g.c 2012-08-18 09:47:41.000000000 +0200 -@@ -1017,10 +1017,30 @@ - } else { - struct stat st = { .st_ino = MREF(mref) }; - -- if (dt_type == NTFS_DT_REG) -- st.st_mode = S_IFREG | (0777 & ~ctx->fmask); -- else if (dt_type == NTFS_DT_DIR) -+ switch (dt_type) { -+ case NTFS_DT_DIR : - st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); -+ break; -+ case NTFS_DT_LNK : -+ st.st_mode = S_IFLNK | 0777; -+ break; -+ case NTFS_DT_FIFO : -+ st.st_mode = S_IFIFO; -+ break; -+ case NTFS_DT_SOCK : -+ st.st_mode = S_IFSOCK; -+ break; -+ case NTFS_DT_BLK : -+ st.st_mode = S_IFBLK; -+ break; -+ case NTFS_DT_CHR : -+ st.st_mode = S_IFCHR; -+ break; -+ default : /* unexpected types shown as plain files */ -+ case NTFS_DT_REG : -+ st.st_mode = S_IFREG | (0777 & ~ctx->fmask); -+ break; -+ } - - #if defined(__APPLE__) || defined(__DARWIN__) - /* ---- ntfs-3g_ntfsprogs-2012.1.15/src/lowntfs-3g.c.ref 2012-08-18 09:44:57.000000000 +0200 -+++ ntfs-3g_ntfsprogs-2012.1.15/src/lowntfs-3g.c 2012-08-18 09:47:41.000000000 +0200 -@@ -920,10 +920,30 @@ - if (MREF(mref) > 1) { - struct stat st = { .st_ino = MREF(mref) }; - -- if (dt_type == NTFS_DT_REG) -- st.st_mode = S_IFREG | (0777 & ~ctx->fmask); -- else if (dt_type == NTFS_DT_DIR) -+ switch (dt_type) { -+ case NTFS_DT_DIR : - st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); -+ break; -+ case NTFS_DT_LNK : -+ st.st_mode = S_IFLNK | 0777; -+ break; -+ case NTFS_DT_FIFO : -+ st.st_mode = S_IFIFO; -+ break; -+ case NTFS_DT_SOCK : -+ st.st_mode = S_IFSOCK; -+ break; -+ case NTFS_DT_BLK : -+ st.st_mode = S_IFBLK; -+ break; -+ case NTFS_DT_CHR : -+ st.st_mode = S_IFCHR; -+ break; -+ default : /* unexpected types shown as plain files */ -+ case NTFS_DT_REG : -+ st.st_mode = S_IFREG | (0777 & ~ctx->fmask); -+ break; -+ } - - #if defined(__APPLE__) || defined(__DARWIN__) - /* diff --git a/sources b/sources index 89d5b8e..e6d7a84 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -341acae00a290cab9b00464db65015cc ntfs-3g_ntfsprogs-2012.1.15.tgz +2d6fb47ddf62b51733227126fe9227fe ntfs-3g_ntfsprogs-2013.1.13.tgz From 289bb11a76b5ada26025b2352a184a563f5b85ff Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 21 Jul 2014 21:05:41 +0100 Subject: [PATCH 04/10] New package for RHEL 7.1 - Rebase to ntfs-3g 2014.2.15 resolves: rhbz#1100319 - Change the package so it works with supermin5. - Remove dependency on external FUSE. --- libguestfs-winsupport.spec | 151 ++++++++++++++++++++----------------- sources | 2 +- 2 files changed, 81 insertions(+), 72 deletions(-) diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 7d67173..0afc5cd 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -1,36 +1,32 @@ %global debug_package %{nil} -%global ntfs_version 2013.1.13 +%global ntfs_version 2014.2.15 Name: libguestfs-winsupport -Version: 7.0 +Version: 7.1 Release: 2%{?dist} Summary: Add support for Windows guests to libguestfs +URL: http://www.ntfs-3g.org/ License: GPLv2+ ExclusiveArch: x86_64 # This package shouldn't be installed without installing the base # libguestfs package. -Requires: libguestfs >= 1:1.20.0 +Requires: libguestfs >= 1:1.27.19 -# Needs fuse-libs (RHBZ#599300). -Requires: fuse-libs +# Built for supermin 5. This will not work with older supermin. +BuildRequires: supermin5 +Requires: supermin5 # Source and patches for ntfs. Try to keep this in step with Fedora. Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.tgz Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch -BuildRequires: fuse-devel -Requires: fuse - BuildRequires: libtool, libattr-devel BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel -# Required by binaries in the supermin appliance. -Requires: libgcrypt, gnutls, p11-kit, libtasn1, zlib - %description This optional package adds support for Windows guests (NTFS) to the @@ -42,6 +38,9 @@ To enable Windows support, simply install this package. To disable Windows support, uninstall this package. +The package contains NTFS FUSE filesystem support from +ntfs-3g %{ntfs_3g_version}. + %prep %setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} @@ -53,42 +52,26 @@ CFLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64" %configure \ --disable-static \ --disable-ldconfig \ - --with-fuse=external \ --exec-prefix=/ \ --enable-crypto \ --enable-extras make %{?_smp_mflags} LIBTOOL=%{_bindir}/libtool -# Create a README file. -cat <<'EOF' > README -This optional package adds support for Windows guests (NTFS) to the -base libguestfs Red Hat Enterprise Linux (RHEL) package. This is -useful for examining Windows virtual machines running on RHEL, and for -performing V2V of Windows guests from another hypervisor to RHEL. - -The package contains NTFS FUSE filesystem support from -ntfs-3g %{ntfs_3g_version}. -EOF - %install -mkdir ntfs -export DESTDIR=$(pwd)/ntfs +make LIBTOOL=%{_bindir}/libtool DESTDIR=%{buildroot} install +rm -rf %{buildroot}%{_libdir}/*.la +rm -rf %{buildroot}%{_libdir}/*.a -#----- Standard package install rule, but installing into ntfs/ subdir. -make LIBTOOL=%{_bindir}/libtool install -rm -rf $DESTDIR%{_libdir}/*.la -rm -rf $DESTDIR%{_libdir}/*.a - -rm -rf $DESTDIR%{_sbindir}/mount.ntfs-3g -cp -a $DESTDIR%{_bindir}/ntfs-3g $DESTDIR%{_sbindir}/mount.ntfs-3g +rm -rf %{buildroot}/%{_sbindir}/mount.ntfs-3g +cp -a %{buildroot}/%{_bindir}/ntfs-3g %{buildroot}/%{_sbindir}/mount.ntfs-3g # Actually make some symlinks for simplicity... # ... since we're obsoleting ntfsprogs-fuse -pushd $DESTDIR%{_bindir} +pushd %{buildroot}/%{_bindir} ln -s ntfs-3g ntfsmount popd -pushd $DESTDIR%{_sbindir} +pushd %{buildroot}/%{_sbindir} ln -s mount.ntfs-3g mount.ntfs-fuse # And since there is no other package in Fedora that provides an ntfs # mount... @@ -96,54 +79,80 @@ ln -s mount.ntfs-3g mount.ntfs # Need this for fsck to find it ln -s ../bin/ntfsck fsck.ntfs popd -mv $DESTDIR/sbin/* $DESTDIR%{_sbindir} -rmdir $DESTDIR/sbin +mv %{buildroot}/sbin/* %{buildroot}/%{_sbindir} +rmdir %{buildroot}/sbin # We get this on our own, thanks. -rm -rf $DESTDIR%{_defaultdocdir}/%{name}/README +rm %{buildroot}%{_defaultdocdir}/ntfs-3g/README -#----- End of standard package install rule. +# Add this package to the libguestfs appliance. +mkdir -p %{buildroot}%{_libdir}/guestfs/supermin.d +echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsupport -# Copy the files we need to a static supermin appliance. -rm -f files -echo . >> files -echo usr >> files -echo usr/bin >> files -echo usr/lib64 >> files -echo usr/sbin >> files -pushd ntfs -find | egrep '/s?bin/|/lib(64)/' >> ../files -cpio --quiet -o -H newc < ../files > ../ntfs.img -popd -# Supporting hostfiles. -cat <<'EOF' > ntfs.hostfiles -. -./usr -.%{_libdir} -.%{_libdir}/libfuse.so.* -.%{_libdir}/libgcrypt.so.* -.%{_libdir}/libgnutls.so.* -.%{_libdir}/libgpg-error.so.* -.%{_libdir}/libp11-kit.so.* -.%{_libdir}/libtasn1.so.* -.%{_libdir}/libz.so.* -./lib64 -./lib64/libfuse.so.* -EOF - -mkdir -p $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d -install -m 0644 ntfs.img $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d/ -install -m 0644 ntfs.hostfiles $RPM_BUILD_ROOT%{_libdir}/guestfs/supermin.d/ +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig %files -%doc COPYING README -%{_libdir}/guestfs/supermin.d/ntfs.img -%{_libdir}/guestfs/supermin.d/ntfs.hostfiles +%doc AUTHORS ChangeLog COPYING CREDITS NEWS README + +# From ntfs-3g package: +%{_sbindir}/mount.ntfs +%{_sbindir}/mount.ntfs-3g +%{_sbindir}/mount.ntfs-fuse +%{_sbindir}/mount.lowntfs-3g +%{_bindir}/ntfs-3g +%{_bindir}/ntfsmount +%{_bindir}/ntfs-3g.probe +%{_bindir}/ntfs-3g.secaudit +%{_bindir}/ntfs-3g.usermap +%{_bindir}/lowntfs-3g +%{_libdir}/libntfs-3g.so.* + +# From -devel subpackage: +%{_includedir}/ntfs-3g/ +%{_libdir}/libntfs-3g.so +%{_libdir}/pkgconfig/libntfs-3g.pc + +# From ntfsprogs package: +%{_bindir}/ntfscat +%{_bindir}/ntfscluster +%{_bindir}/ntfscmp +%{_bindir}/ntfsfix +%{_bindir}/ntfsinfo +%{_bindir}/ntfsls +%{_bindir}/ntfsck +%{_bindir}/ntfsdecrypt +%{_bindir}/ntfsdump_logfile +%{_bindir}/ntfsmftalloc +%{_bindir}/ntfsmove +%{_bindir}/ntfstruncate +%{_bindir}/ntfswipe +%{_sbindir}/fsck.ntfs +%{_sbindir}/mkfs.ntfs +%{_sbindir}/mkntfs +%{_sbindir}/ntfsclone +%{_sbindir}/ntfscp +%{_sbindir}/ntfslabel +%{_sbindir}/ntfsresize +%{_sbindir}/ntfsundelete + +# Documentation. +%{_mandir}/man8/*.8* + +# For libguestfs appliance: +%{_libdir}/guestfs/supermin.d/zz-winsupport %changelog +* Mon Jul 21 2014 Richard W.M. Jones - 7.1-2 +- New package for RHEL 7.1 +- Rebase to ntfs-3g 2014.2.15 + resolves: rhbz#1100319 +- Change the package so it works with supermin5. +- Remove dependency on external FUSE. + * Wed Apr 3 2013 Richard W.M. Jones - 7.0-2 - Resync against Rawhide package (ntfs-3g 2013.1.13). - Drop HAL file since HAL is dead. diff --git a/sources b/sources index e6d7a84..cc19fcf 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -2d6fb47ddf62b51733227126fe9227fe ntfs-3g_ntfsprogs-2013.1.13.tgz +f11d563816249d730a00498983485f3a ntfs-3g_ntfsprogs-2014.2.15.tgz From 4ad78f5afca86ac82e2f47ef6a8746138512b960 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 28 Aug 2014 22:06:59 +0100 Subject: [PATCH 05/10] Add patches from Fedora package which add fstrim support. resolves: rhbz#1100319 --- ...Fixed-fstrim-8-applied-to-partitions.patch | 217 ++++++ ...Upgraded-fuse-lite-to-support-ioctls.patch | 610 +++++++++++++++++ 0002-Implemented-fstrim-8.patch | 648 ++++++++++++++++++ libguestfs-winsupport.spec | 22 +- 4 files changed, 1496 insertions(+), 1 deletion(-) create mode 100644 0001-Fixed-fstrim-8-applied-to-partitions.patch create mode 100644 0001-Upgraded-fuse-lite-to-support-ioctls.patch create mode 100644 0002-Implemented-fstrim-8.patch diff --git a/0001-Fixed-fstrim-8-applied-to-partitions.patch b/0001-Fixed-fstrim-8-applied-to-partitions.patch new file mode 100644 index 0000000..b67cb71 --- /dev/null +++ b/0001-Fixed-fstrim-8-applied-to-partitions.patch @@ -0,0 +1,217 @@ +From c26a519da1ed182e7cfd67e7a353932dda53d811 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= +Date: Mon, 4 Aug 2014 17:39:50 +0200 +Subject: [PATCH] Fixed fstrim(8) applied to partitions + +The new way goes via /sys/dev/block/MAJOR:MINOR to map partitions to +devices and get discard parameters of the parent device. It also ensures +that the partition is aligned to the discard block size. + +Contributed by Richard W.M. Jones +--- + libntfs-3g/ioctl.c | 140 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 68 insertions(+), 72 deletions(-) + +diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c +index bbbceb9..eb7c8e7 100644 +--- a/libntfs-3g/ioctl.c ++++ b/libntfs-3g/ioctl.c +@@ -66,8 +66,6 @@ + #include + #endif + +-#include +- + #include "compat.h" + #include "debug.h" + #include "bitmap.h" +@@ -135,17 +133,14 @@ static int read_u64(const char *path, u64 *n) + } + + /* Find discard limits for current backing device. +- * XXX Kernel makes this a pain in the neck. + */ +-static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, ++static int fstrim_limits(ntfs_volume *vol, ++ u64 *discard_alignment, ++ u64 *discard_granularity, + u64 *discard_max_bytes) + { + struct stat statbuf; +- DIR *dir; +- struct dirent *d; +- char path[80]; +- char line[64]; +- char dev[64]; ++ char path1[80], path2[80]; + int ret; + + /* Stat the backing device. Caller has ensured it is a block device. */ +@@ -155,82 +150,78 @@ static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, + return -errno; + } + +- /* Now look for a /sys/block//dev file which contains +- * "major:minor\n". ++ /* For whole devices, ++ * /sys/dev/block/MAJOR:MINOR/discard_alignment ++ * /sys/dev/block/MAJOR:MINOR/queue/discard_granularity ++ * /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes ++ * will exist. ++ * For partitions, we also need to check the parent device: ++ * /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity ++ * /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes + */ +- snprintf(dev, sizeof dev, "%d:%d\n", ++ snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d", + major(statbuf.st_rdev), minor(statbuf.st_rdev)); + +- dir = opendir("/sys/block"); +- if (dir == NULL) { +- ntfs_log_debug("fstrim_limits: could not open /sys/block\n"); +- return -errno; ++ snprintf(path2, sizeof path2, "%s/discard_alignment", path1); ++ ret = read_u64(path2, discard_alignment); ++ if (ret) { ++ if (ret != -ENOENT) ++ return ret; ++ else ++ /* We would expect this file to exist on all ++ * modern kernels. But for the sake of very ++ * old kernels: ++ */ ++ goto not_found; + } +- for (;;) { +- errno = 0; +- d = readdir(dir); +- if (!d) break; + +- snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name); +- ret = read_line(path, line, sizeof line); +- if (ret) +- continue; +- if (strcmp(line, dev) == 0) +- goto found; ++ snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1); ++ ret = read_u64(path2, discard_granularity); ++ if (ret) { ++ if (ret != -ENOENT) ++ return ret; ++ else { ++ snprintf(path2, sizeof path2, ++ "%s/../queue/discard_granularity", path1); ++ ret = read_u64(path2, discard_granularity); ++ if (ret) { ++ if (ret != -ENOENT) ++ return ret; ++ else ++ goto not_found; ++ } ++ } + } + +- /* Check readdir didn't fail. */ +- if (errno != 0) { +- ret = -errno; +- ntfs_log_debug("fstrim_limits: readdir failed\n"); +- goto out; ++ snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1); ++ ret = read_u64(path2, discard_max_bytes); ++ if (ret) { ++ if (ret != -ENOENT) ++ return ret; ++ else { ++ snprintf(path2, sizeof path2, ++ "%s/../queue/discard_max_bytes", path1); ++ ret = read_u64(path2, discard_max_bytes); ++ if (ret) { ++ if (ret != -ENOENT) ++ return ret; ++ else ++ goto not_found; ++ } ++ } + } + ++ return 0; ++ ++not_found: + /* If we reach here then we didn't find the device. This is + * not an error, but set discard_max_bytes = 0 to indicate + * that discard is not available. + */ ++ *discard_alignment = 0; + *discard_granularity = 0; + *discard_max_bytes = 0; +- ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n", +- vol->dev->d_name); +- ret = 0; +- goto out; +- +-found: +- /* Found the device at /sys/block/ + d->d_name */ +- snprintf (path, sizeof path, +- "/sys/block/%s/queue/discard_granularity", +- d->d_name); +- ret = read_u64(path, discard_granularity); +- if (ret) { +- ntfs_log_debug("fstrim_limits: could not read %s\n", path); +- goto out; +- } +- +- snprintf (path, sizeof path, +- "/sys/block/%s/queue/discard_max_bytes", +- d->d_name); +- ret = read_u64(path, discard_max_bytes); +- if (ret) { +- ntfs_log_debug("fstrim_limits: could not read %s\n", path); +- goto out; +- } +- +- ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n", +- d->d_name, +- (unsigned long long) *discard_granularity, +- (unsigned long long) *discard_max_bytes); +- +- ret = 0; +-out: +- if (closedir (dir) == -1) { +- ret = -errno; +- ntfs_log_debug("fstrim_limits: closedir failed\n"); +- return ret; +- } +- +- return ret; ++ return 0; + } + + #define FSTRIM_BUFSIZ 4096 +@@ -247,7 +238,7 @@ static int fstrim(ntfs_volume *vol, void *data) + u64 start = range->start; + u64 len = range->len; + u64 minlen = range->minlen; +- u64 discard_granularity, discard_max_bytes; ++ u64 discard_alignment, discard_granularity, discard_max_bytes; + u8 *buf = NULL; + LCN start_buf; + int ret; +@@ -279,9 +270,14 @@ static int fstrim(ntfs_volume *vol, void *data) + return -EOPNOTSUPP; + } + +- ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes); ++ ret = fstrim_limits(vol, &discard_alignment, ++ &discard_granularity, &discard_max_bytes); + if (ret) + return ret; ++ if (discard_alignment != 0) { ++ ntfs_log_debug("fstrim: backing device is not aligned for discards\n"); ++ return -EOPNOTSUPP; ++ } + if (discard_granularity > vol->cluster_size) { + ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n"); + return -EOPNOTSUPP; +-- +1.9.3 + diff --git a/0001-Upgraded-fuse-lite-to-support-ioctls.patch b/0001-Upgraded-fuse-lite-to-support-ioctls.patch new file mode 100644 index 0000000..0c9b7cc --- /dev/null +++ b/0001-Upgraded-fuse-lite-to-support-ioctls.patch @@ -0,0 +1,610 @@ +diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h +--- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h 2014-07-31 13:47:17.401904166 +0100 +@@ -49,6 +49,22 @@ + #endif + + #define FUSE_CAP_BIG_WRITES (1 << 5) ++#define FUSE_CAP_IOCTL_DIR (1 << 11) ++ ++/** ++ * Ioctl flags ++ * ++ * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine ++ * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed ++ * FUSE_IOCTL_RETRY: retry with new iovecs ++ * FUSE_IOCTL_DIR: is a directory ++ */ ++#define FUSE_IOCTL_COMPAT (1 << 0) ++#define FUSE_IOCTL_UNRESTRICTED (1 << 1) ++#define FUSE_IOCTL_RETRY (1 << 2) ++#define FUSE_IOCTL_DIR (1 << 4) ++ ++#define FUSE_IOCTL_MAX_IOV 256 + + /** + * Information about open files +diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h +--- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h 2014-07-31 13:47:17.401904166 +0100 +@@ -420,9 +420,27 @@ + * Introduced in version 2.6 + */ + int (*bmap) (const char *, size_t blocksize, uint64_t *idx); +- unsigned int flag_nullpath_ok : 1; + + /** ++ * Ioctl ++ * ++ * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in ++ * 64bit environment. The size and direction of data is ++ * determined by _IOC_*() decoding of cmd. For _IOC_NONE, ++ * data will be NULL, for _IOC_WRITE data is out area, for ++ * _IOC_READ in area and if both are set in/out area. In all ++ * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. ++ * ++ * Introduced in version 2.8 ++ */ ++ int (*ioctl) (const char *, int cmd, void *arg, ++ struct fuse_file_info *, unsigned int flags, void *data); ++ ++ /* ++ * The flags below have been discarded, they should not be used ++ */ ++ unsigned int flag_nullpath_ok : 1; ++ /** + * Reserved flags, don't set + */ + unsigned int flag_reserved : 30; +@@ -450,10 +468,8 @@ + /** Private filesystem data */ + void *private_data; + +-#ifdef POSIXACLS + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +-#endif + }; + + /* ----------------------------------------------------------- * +@@ -601,6 +617,8 @@ + const char *name); + int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, + uint64_t *idx); ++int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, ++ struct fuse_file_info *fi, unsigned int flags, void *data); + void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); + void fuse_fs_destroy(struct fuse_fs *fs); + +diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h +--- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h 2014-07-31 13:47:17.401904166 +0100 +@@ -48,13 +48,19 @@ + /** Version number of this interface */ + #define FUSE_KERNEL_VERSION 7 + +-/** Minor version number of this interface */ +-#ifdef POSIXACLS +-#define FUSE_KERNEL_MINOR_VERSION 12 ++/** Minor version number of this interface ++ * We introduce ourself as 7.18 (Posix ACLS : 7.12, IOCTL_DIR : 7.18) ++ * and we expect features features defined for 7.18, but not implemented ++ * here to not be triggered by ntfs-3g. ++ */ ++#define FUSE_KERNEL_MINOR_VERSION 18 ++ ++/* ++ * For binary compatibility with old kernels we accept falling back to 7.8 ++ */ ++ ++#define FUSE_KERNEL_MAJOR_FALLBACK 7 + #define FUSE_KERNEL_MINOR_FALLBACK 8 +-#else +-#define FUSE_KERNEL_MINOR_VERSION 8 +-#endif + + /** The node ID of the root inode */ + #define FUSE_ROOT_ID 1 +@@ -83,9 +89,7 @@ + __u32 uid; + __u32 gid; + __u32 rdev; +-#ifdef POSIXACLS + __u64 filling; /* JPA needed for minor >= 12, but meaning unknown */ +-#endif + }; + + struct fuse_kstatfs { +@@ -132,11 +136,13 @@ + * INIT request/reply flags + * FUSE_BIG_WRITES: allow big writes to be issued to the file system + * FUSE_DONT_MASK: don't apply umask to file mode on create operations ++ * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories + */ + #define FUSE_ASYNC_READ (1 << 0) + #define FUSE_POSIX_LOCKS (1 << 1) + #define FUSE_BIG_WRITES (1 << 5) + #define FUSE_DONT_MASK (1 << 6) ++#define FUSE_HAS_IOCTL_DIR (1 << 11) + + /** + * Release flags +@@ -180,6 +186,7 @@ + FUSE_INTERRUPT = 36, + FUSE_BMAP = 37, + FUSE_DESTROY = 38, ++ FUSE_IOCTL = 39, + }; + + /* The read buffer is required to be at least 8k, but may be much larger */ +@@ -215,10 +222,8 @@ + struct fuse_mknod_in { + __u32 mode; + __u32 rdev; +-#ifdef POSIXACLS + __u32 umask; + __u32 padding; +-#endif + }; + + struct fuse_mkdir_in { +@@ -255,20 +260,14 @@ + + struct fuse_open_in { + __u32 flags; +-#ifdef POSIXACLS +- __u32 unused; +-#else +- __u32 mode; +-#endif ++ __u32 mode; /* unused for protocol < 7.12 */ + }; + + struct fuse_create_in { + __u32 flags; + __u32 mode; +-#ifdef POSIXACLS + __u32 umask; + __u32 padding; +-#endif + }; + + struct fuse_open_out { +@@ -305,11 +304,9 @@ + __u64 offset; + __u32 size; + __u32 write_flags; +-#ifdef POSIXACLS + __u64 lock_owner; /* JPA */ + __u32 flags; /* JPA */ + __u32 padding; /* JPA */ +-#endif + }; + + struct fuse_write_out { +@@ -389,6 +386,27 @@ + __u64 block; + }; + ++struct fuse_ioctl_in { ++ __u64 fh; ++ __u32 flags; ++ __u32 cmd; ++ __u64 arg; ++ __u32 in_size; ++ __u32 out_size; ++}; ++ ++struct fuse_ioctl_iovec { ++ __u64 base; ++ __u64 len; ++}; ++ ++struct fuse_ioctl_out { ++ __s32 result; ++ __u32 flags; ++ __u32 in_iovs; ++ __u32 out_iovs; ++}; ++ + struct fuse_in_header { + __u32 len; + __u32 opcode; +diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h +--- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h 2014-07-31 13:47:17.402904167 +0100 +@@ -101,10 +101,8 @@ + /** Thread ID of the calling process */ + pid_t pid; + +-#ifdef POSIXACLS + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +-#endif + }; + + /* 'to_set' flags in setattr */ +@@ -805,6 +803,37 @@ + */ + void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t idx); ++ /** ++ * Ioctl ++ * ++ * Note: For unrestricted ioctls (not allowed for FUSE ++ * servers), data in and out areas can be discovered by giving ++ * iovs and setting FUSE_IOCTL_RETRY in @flags. For ++ * restricted ioctls, kernel prepares in/out data area ++ * according to the information encoded in cmd. ++ * ++ * Introduced in version 2.8 ++ * ++ * Valid replies: ++ * fuse_reply_ioctl_retry ++ * fuse_reply_ioctl ++ * fuse_reply_ioctl_iov ++ * fuse_reply_err ++ * ++ * @param req request handle ++ * @param ino the inode number ++ * @param cmd ioctl command ++ * @param arg ioctl argument ++ * @param fi file information ++ * @param flags for FUSE_IOCTL_* flags ++ * @param in_buf data fetched from the caller ++ * @param in_bufsz number of fetched bytes ++ * @param out_bufsz maximum size of output data ++ */ ++ void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, ++ struct fuse_file_info *fi, unsigned flags, ++ const void *in_buf, size_t in_bufsz, size_t out_bufsz); ++ + }; + + /** +@@ -1022,6 +1051,20 @@ + const char *name, const struct stat *stbuf, + off_t off); + ++/** ++ * Reply to finish ioctl ++ * ++ * Possible requests: ++ * ioctl ++ * ++ * @param req request handle ++ * @param result result to be passed to the caller ++ * @param buf buffer containing output data ++ * @param size length of output data ++ */ ++int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size); ++ ++ + /* ----------------------------------------------------------- * + * Utility functions * + * ----------------------------------------------------------- */ +diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c +--- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c 2014-07-31 13:47:17.403904167 +0100 +@@ -1040,6 +1040,21 @@ + return -ENOSYS; + } + ++int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, ++ struct fuse_file_info *fi, unsigned int flags, void *data) ++{ ++ fuse_get_context()->private_data = fs->user_data; ++ if (fs->op.ioctl) { ++/* ++ if (fs->debug) ++ fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n", ++ (unsigned long long) fi->fh, cmd, flags); ++*/ ++ return fs->op.ioctl(path, cmd, arg, fi, flags, data); ++ } else ++ return -ENOSYS; ++} ++ + static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) + { + struct node *node; +@@ -2716,6 +2731,60 @@ + reply_err(req, err); + } + ++static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, ++ struct fuse_file_info *llfi, unsigned int flags, ++ const void *in_buf, size_t in_bufsz, ++ size_t out_bufsz) ++{ ++ struct fuse *f = req_fuse_prepare(req); ++ struct fuse_intr_data d; ++ struct fuse_file_info fi; ++ char *path, *out_buf = NULL; ++ int err; ++ ++ err = -EPERM; ++ if (flags & FUSE_IOCTL_UNRESTRICTED) ++ goto err; ++ ++ if (flags & FUSE_IOCTL_DIR) ++ get_dirhandle(llfi, &fi); ++ else ++ fi = *llfi; ++ ++ if (out_bufsz) { ++ err = -ENOMEM; ++ out_buf = malloc(out_bufsz); ++ if (!out_buf) ++ goto err; ++ } ++ ++ assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz); ++ if (out_buf) ++ memcpy(out_buf, in_buf, in_bufsz); ++ ++ path = get_path(f, ino); /* Should be get_path_nullok() */ ++ if (!path) { ++ err = ENOENT; ++ goto err; ++ } ++ ++ fuse_prepare_interrupt(f, req, &d); ++ ++ /* Note : const qualifier dropped */ ++ err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags, ++ out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf); ++ ++ fuse_finish_interrupt(f, req, &d); ++ free(path); ++ ++ fuse_reply_ioctl(req, err, out_buf, out_bufsz); ++ goto out; ++err: ++ reply_err(req, err); ++out: ++ free(out_buf); ++} ++ + static struct fuse_lowlevel_ops fuse_path_ops = { + .init = fuse_lib_init, + .destroy = fuse_lib_destroy, +@@ -2751,6 +2820,7 @@ + .getlk = fuse_lib_getlk, + .setlk = fuse_lib_setlk, + .bmap = fuse_lib_bmap, ++ .ioctl = fuse_lib_ioctl, + }; + + struct fuse_session *fuse_get_session(struct fuse *f) +diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c +--- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c 2014-07-31 13:47:17.403904167 +0100 +@@ -333,12 +333,8 @@ + + memset(&arg, 0, sizeof(arg)); + fill_entry(&arg, e); +-#ifdef POSIXACLS + return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 + ? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE)); +-#else +- return send_reply_ok(req, &arg, sizeof(arg)); +-#endif + } + + int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, +@@ -351,7 +347,6 @@ + + memset(&arg, 0, sizeof(arg)); + fill_entry(&arg.e, e); +-#ifdef POSIXACLS + if (req->f->conn.proto_minor < 12) { + fill_open((struct fuse_open_out*) + ((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f); +@@ -361,10 +356,6 @@ + fill_open(&arg.o, f); + return send_reply_ok(req, &arg, sizeof(arg)); + } +-#else +- fill_open(&arg.o, f); +- return send_reply_ok(req, &arg, sizeof(arg)); +-#endif + } + + int fuse_reply_attr(fuse_req_t req, const struct stat *attr, +@@ -377,12 +368,8 @@ + arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); + convert_stat(attr, &arg.attr); + +-#ifdef POSIXACLS + return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 + ? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE)); +-#else +- return send_reply_ok(req, &arg, sizeof(arg)); +-#endif + } + + int fuse_reply_readlink(fuse_req_t req, const char *linkname) +@@ -462,6 +449,28 @@ + return send_reply_ok(req, &arg, sizeof(arg)); + } + ++int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) ++{ ++ struct fuse_ioctl_out arg; ++ struct iovec iov[3]; ++ size_t count = 1; ++ ++ memset(&arg, 0, sizeof(arg)); ++ arg.result = result; ++ iov[count].iov_base = &arg; ++ iov[count].iov_len = sizeof(arg); ++ count++; ++ ++ if (size) { ++ /* Note : const qualifier dropped */ ++ iov[count].iov_base = (char *)(uintptr_t) buf; ++ iov[count].iov_len = size; ++ count++; ++ } ++ ++ return send_reply_iov(req, 0, iov, count); ++} ++ + static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) + { + const char *name = (const char *) inarg; +@@ -538,11 +547,9 @@ + const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg; + const char *name = PARAM(arg); + +-#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else +-#endif + name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; + + if (req->f->op.mknod) +@@ -555,10 +562,8 @@ + { + const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg; + +-#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; +-#endif + + if (req->f->op.mkdir) + req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); +@@ -630,11 +635,9 @@ + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + +-#ifdef POSIXACLS + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else +-#endif + name = (const char *) inarg + sizeof(struct fuse_open_in); + + req->f->op.create(req, nodeid, name, arg->mode, &fi); +@@ -682,7 +685,6 @@ + fi.writepage = arg->write_flags & 1; + + if (req->f->op.write) { +-#ifdef POSIXACLS + const char *buf; + + if (req->f->conn.proto_minor >= 12) +@@ -690,9 +692,6 @@ + else + buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE; + req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi); +-#else +- req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi); +-#endif + } else + fuse_reply_err(req, ENOSYS); + } +@@ -1011,6 +1010,39 @@ + fuse_reply_err(req, ENOSYS); + } + ++static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) ++{ ++ const struct fuse_ioctl_in *arg = (const struct fuse_ioctl_in *) inarg; ++ unsigned int flags = arg->flags; ++ const void *in_buf = arg->in_size ? PARAM(arg) : NULL; ++ struct fuse_file_info fi; ++ ++ if (flags & FUSE_IOCTL_DIR && ++ !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) { ++ fuse_reply_err(req, ENOTTY); ++ return; ++ } ++ ++ memset(&fi, 0, sizeof(fi)); ++ fi.fh = arg->fh; ++ ++/* TODO JPA (need req->ioctl_64bit in obscure fuse_req_t) ++// probably a 64 bit ioctl on a 32-bit cpu ++// this is to forward a request from the kernel ++ if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 && ++ !(flags & FUSE_IOCTL_32BIT)) { ++ req->ioctl_64bit = 1; ++ } ++*/ ++ ++ if (req->f->op.ioctl) ++ req->f->op.ioctl(req, nodeid, arg->cmd, ++ (void *)(uintptr_t)arg->arg, &fi, flags, ++ in_buf, arg->in_size, arg->out_size); ++ else ++ fuse_reply_err(req, ENOSYS); ++} ++ + static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) + { + const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg; +@@ -1047,6 +1079,8 @@ + #endif + if (arg->flags & FUSE_BIG_WRITES) + f->conn.capable |= FUSE_CAP_BIG_WRITES; ++ if (arg->flags & FUSE_HAS_IOCTL_DIR) ++ f->conn.capable |= FUSE_CAP_IOCTL_DIR; + } else { + f->conn.async_read = 0; + f->conn.max_readahead = 0; +@@ -1069,28 +1103,28 @@ + memset(&outarg, 0, sizeof(outarg)); + outarg.major = FUSE_KERNEL_VERSION; + /* +- * if POSIXACLS is not set, protocol 7.8 provides a good +- * compatibility with older kernel modules. +- * if POSIXACLS is set, we try to use protocol 7.12 supposed +- * to have the ability to process the umask conditionnally, +- * but, when using an older kernel module, we fallback to 7.8 ++ * Suggest using protocol 7.18 when available, and fallback ++ * to 7.8 when running on an old kernel. ++ * Protocol 7.12 has the ability to process the umask ++ * conditionnally (as needed if POSIXACLS is set) ++ * Protocol 7.18 has the ability to process the ioctls + */ +-#ifdef POSIXACLS +- if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12)) ++ if (arg->major > 7 || (arg->major == 7 && arg->minor >= 18)) { + outarg.minor = FUSE_KERNEL_MINOR_VERSION; +- else +- outarg.minor = FUSE_KERNEL_MINOR_FALLBACK; +-#else +- outarg.minor = FUSE_KERNEL_MINOR_VERSION; ++ if (f->conn.want & FUSE_CAP_IOCTL_DIR) ++ outarg.flags |= FUSE_HAS_IOCTL_DIR; ++#ifdef POSIXACLS ++ if (f->conn.want & FUSE_CAP_DONT_MASK) ++ outarg.flags |= FUSE_DONT_MASK; + #endif ++ } else { ++ outarg.major = FUSE_KERNEL_MAJOR_FALLBACK; ++ outarg.minor = FUSE_KERNEL_MINOR_FALLBACK; ++ } + if (f->conn.async_read) + outarg.flags |= FUSE_ASYNC_READ; + if (f->op.getlk && f->op.setlk) + outarg.flags |= FUSE_POSIX_LOCKS; +-#ifdef POSIXACLS +- if (f->conn.want & FUSE_CAP_DONT_MASK) +- outarg.flags |= FUSE_DONT_MASK; +-#endif + if (f->conn.want & FUSE_CAP_BIG_WRITES) + outarg.flags |= FUSE_BIG_WRITES; + outarg.max_readahead = f->conn.max_readahead; +@@ -1191,6 +1225,7 @@ + [FUSE_CREATE] = { do_create, "CREATE" }, + [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, + [FUSE_BMAP] = { do_bmap, "BMAP" }, ++ [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, + [FUSE_DESTROY] = { do_destroy, "DESTROY" }, + }; + diff --git a/0002-Implemented-fstrim-8.patch b/0002-Implemented-fstrim-8.patch new file mode 100644 index 0000000..467f5d6 --- /dev/null +++ b/0002-Implemented-fstrim-8.patch @@ -0,0 +1,648 @@ +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac ntfs-3g_ntfsprogs-2014.2.15/configure.ac +--- ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15/configure.ac 2014-07-31 13:51:24.425065808 +0100 +@@ -463,7 +463,8 @@ + regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \ + sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \ + sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \ +- linux/hdreg.h machine/endian.h windows.h syslog.h pwd.h malloc.h]) ++ linux/fs.h inttypes.h linux/hdreg.h \ ++ machine/endian.h windows.h syslog.h pwd.h malloc.h]) + + # Checks for typedefs, structures, and compiler characteristics. + AC_HEADER_STDBOOL +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h +--- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h 1970-01-01 01:00:00.000000000 +0100 ++++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h 2014-07-31 13:51:24.426065810 +0100 +@@ -0,0 +1,30 @@ ++/* ++ * ++ * Copyright (c) 2014 Jean-Pierre Andre ++ * ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program (in the main directory of the NTFS-3G ++ * distribution in the file COPYING); if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef IOCTL_H ++#define IOCTL_H ++ ++int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg, ++ unsigned int flags, void *data); ++ ++#endif /* IOCTL_H */ +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h +--- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h 2014-07-31 13:51:24.426065810 +0100 +@@ -36,9 +36,7 @@ + #ifdef HAVE_SYS_PARAM_H + #include + #endif +-#ifdef HAVE_SYS_MOUNT_H +-#include +-#endif ++ /* Do not #include here : conflicts with */ + #ifdef HAVE_MNTENT_H + #include + #endif +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c +--- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c 1970-01-01 01:00:00.000000000 +0100 ++++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c 2014-07-31 13:51:24.427065813 +0100 +@@ -0,0 +1,382 @@ ++/** ++ * ioctl.c - Processing of ioctls ++ * ++ * This module is part of ntfs-3g library ++ * ++ * Copyright (c) 2014 Jean-Pierre Andre ++ * Copyright (c) 2014 Red Hat, Inc. ++ * ++ * This program/include file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program/include file is distributed in the hope that it will be ++ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program (in the main directory of the NTFS-3G ++ * distribution in the file COPYING); if not, write to the Free Software ++ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include "config.h" ++ ++#ifdef HAVE_STDIO_H ++#include ++#endif ++#ifdef HAVE_INTTYPES_H ++#include ++#endif ++#ifdef HAVE_STRING_H ++#include ++#endif ++#ifdef HAVE_ERRNO_H ++#include ++#endif ++#ifdef HAVE_FCNTL_H ++#include ++#endif ++#ifdef HAVE_UNISTD_H ++#include ++#endif ++#ifdef HAVE_STDLIB_H ++#include ++#endif ++#ifdef HAVE_LIMITS_H ++#include ++#endif ++#include ++ ++#ifdef HAVE_SETXATTR ++#include ++#endif ++ ++#ifdef HAVE_SYS_TYPES_H ++#include ++#endif ++ ++#ifdef HAVE_SYS_STAT_H ++#include ++#endif ++ ++#ifdef HAVE_LINUX_FS_H ++#include ++#endif ++ ++#include ++ ++#include "compat.h" ++#include "debug.h" ++#include "bitmap.h" ++#include "attrib.h" ++#include "inode.h" ++#include "layout.h" ++#include "volume.h" ++#include "index.h" ++#include "logging.h" ++#include "ntfstime.h" ++#include "unistr.h" ++#include "dir.h" ++#include "security.h" ++#include "ioctl.h" ++#include "misc.h" ++ ++#if defined(FITRIM) && defined(BLKDISCARD) ++ ++/* Issue a TRIM request to the underlying device for the given clusters. */ ++static int fstrim_clusters(ntfs_volume *vol, LCN lcn, s64 length) ++{ ++ struct ntfs_device *dev = vol->dev; ++ uint64_t range[2]; ++ ++ ntfs_log_debug("fstrim_clusters: %lld length %lld\n", ++ (long long) lcn, (long long) length); ++ ++ range[0] = lcn << vol->cluster_size_bits; ++ range[1] = length << vol->cluster_size_bits; ++ ++ if (dev->d_ops->ioctl(dev, BLKDISCARD, range) == -1) { ++ ntfs_log_debug("fstrim_one_cluster: ioctl failed: %m\n"); ++ return -errno; ++ } ++ return 0; ++} ++ ++static int read_line(const char *path, char *line, size_t max_bytes) ++{ ++ FILE *fp; ++ ++ fp = fopen(path, "r"); ++ if (fp == NULL) ++ return -errno; ++ if (fgets(line, max_bytes, fp) == NULL) { ++ int ret = -EIO; /* fgets doesn't set errno */ ++ fclose(fp); ++ return ret; ++ } ++ fclose (fp); ++ return 0; ++} ++ ++static int read_u64(const char *path, u64 *n) ++{ ++ char line[64]; ++ int ret; ++ ++ ret = read_line(path, line, sizeof line); ++ if (ret) ++ return ret; ++ if (sscanf(line, "%" SCNu64, n) != 1) ++ return -EINVAL; ++ return 0; ++} ++ ++/* Find discard limits for current backing device. ++ * XXX Kernel makes this a pain in the neck. ++ */ ++static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, ++ u64 *discard_max_bytes) ++{ ++ struct stat statbuf; ++ DIR *dir; ++ struct dirent *d; ++ char path[80]; ++ char line[64]; ++ char dev[64]; ++ int ret; ++ ++ /* Stat the backing device. Caller has ensured it is a block device. */ ++ if (stat(vol->dev->d_name, &statbuf) == -1) { ++ ntfs_log_debug("fstrim_limits: could not stat %s\n", ++ vol->dev->d_name); ++ return -errno; ++ } ++ ++ /* Now look for a /sys/block//dev file which contains ++ * "major:minor\n". ++ */ ++ snprintf(dev, sizeof dev, "%d:%d\n", ++ major(statbuf.st_rdev), minor(statbuf.st_rdev)); ++ ++ dir = opendir("/sys/block"); ++ if (dir == NULL) { ++ ntfs_log_debug("fstrim_limits: could not open /sys/block\n"); ++ return -errno; ++ } ++ for (;;) { ++ errno = 0; ++ d = readdir(dir); ++ if (!d) break; ++ ++ snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name); ++ ret = read_line(path, line, sizeof line); ++ if (ret) ++ continue; ++ if (strcmp(line, dev) == 0) ++ goto found; ++ } ++ ++ /* Check readdir didn't fail. */ ++ if (errno != 0) { ++ ret = -errno; ++ ntfs_log_debug("fstrim_limits: readdir failed\n"); ++ goto out; ++ } ++ ++ /* If we reach here then we didn't find the device. This is ++ * not an error, but set discard_max_bytes = 0 to indicate ++ * that discard is not available. ++ */ ++ *discard_granularity = 0; ++ *discard_max_bytes = 0; ++ ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n", ++ vol->dev->d_name); ++ ret = 0; ++ goto out; ++ ++found: ++ /* Found the device at /sys/block/ + d->d_name */ ++ snprintf (path, sizeof path, ++ "/sys/block/%s/queue/discard_granularity", ++ d->d_name); ++ ret = read_u64(path, discard_granularity); ++ if (ret) { ++ ntfs_log_debug("fstrim_limits: could not read %s\n", path); ++ goto out; ++ } ++ ++ snprintf (path, sizeof path, ++ "/sys/block/%s/queue/discard_max_bytes", ++ d->d_name); ++ ret = read_u64(path, discard_max_bytes); ++ if (ret) { ++ ntfs_log_debug("fstrim_limits: could not read %s\n", path); ++ goto out; ++ } ++ ++ ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n", ++ d->d_name, ++ (unsigned long long) *discard_granularity, ++ (unsigned long long) *discard_max_bytes); ++ ++ ret = 0; ++out: ++ if (closedir (dir) == -1) { ++ ret = -errno; ++ ntfs_log_debug("fstrim_limits: closedir failed\n"); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++#define FSTRIM_BUFSIZ 4096 ++ ++/* Trim the filesystem. ++ * ++ * Free blocks between 'start' and 'start+len-1' (both byte offsets) ++ * are found and TRIM requests are sent to the block device. 'minlen' ++ * is the minimum continguous free range to discard. ++ */ ++static int fstrim(ntfs_volume *vol, void *data) ++{ ++ struct fstrim_range *range = data; ++ u64 start = range->start; ++ u64 len = range->len; ++ u64 minlen = range->minlen; ++ u64 discard_granularity, discard_max_bytes; ++ u8 *buf = NULL; ++ LCN start_buf; ++ int ret; ++ ++ ntfs_log_debug("fstrim: start=%llu len=%llu minlen=%llu\n", ++ (unsigned long long) start, ++ (unsigned long long) len, ++ (unsigned long long) minlen); ++ ++ /* Fail if user tries to use the fstrim -o/-l/-m options. ++ * XXX We could fix these limitations in future. ++ */ ++ if (start != 0 || len != (uint64_t)-1) { ++ ntfs_log_debug("fstrim: setting start or length is not supported\n"); ++ return -EINVAL; ++ } ++ if (minlen > vol->cluster_size) { ++ ntfs_log_debug("fstrim: minlen > cluster size is not supported\n"); ++ return -EINVAL; ++ } ++ ++ /* Only block devices are supported. It would be possible to ++ * support backing files (ie. without using loop) but the ++ * ioctls used to punch holes in files are completely ++ * different. ++ */ ++ if (!NDevBlock(vol->dev)) { ++ ntfs_log_debug("fstrim: not supported for non-block-device\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes); ++ if (ret) ++ return ret; ++ if (discard_granularity > vol->cluster_size) { ++ ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n"); ++ return -EOPNOTSUPP; ++ } ++ if (discard_max_bytes == 0) { ++ ntfs_log_debug("fstrim: backing device does not support discard (discard_max_bytes == 0)\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Sync the device before doing anything. */ ++ ret = ntfs_device_sync(vol->dev); ++ if (ret) ++ return ret; ++ ++ /* Read through the bitmap. */ ++ buf = ntfs_malloc(FSTRIM_BUFSIZ); ++ if (buf == NULL) ++ return -errno; ++ for (start_buf = 0; start_buf < vol->nr_clusters; ++ start_buf += FSTRIM_BUFSIZ * 8) { ++ s64 count; ++ s64 br; ++ LCN end_buf, start_lcn; ++ ++ /* start_buf is LCN of first cluster in the current buffer. ++ * end_buf is LCN of last cluster + 1 in the current buffer. ++ */ ++ end_buf = start_buf + FSTRIM_BUFSIZ*8; ++ if (end_buf > vol->nr_clusters) ++ end_buf = vol->nr_clusters; ++ count = (end_buf - start_buf) / 8; ++ ++ br = ntfs_attr_pread(vol->lcnbmp_na, start_buf/8, count, buf); ++ if (br != count) { ++ if (br >= 0) ++ ret = -EIO; ++ else ++ ret = -errno; ++ goto free_out; ++ } ++ ++ /* Trim the clusters in large as possible blocks, but ++ * not larger than discard_max_bytes. ++ */ ++ for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) { ++ if (!ntfs_bit_get(buf, start_lcn-start_buf)) { ++ LCN end_lcn; ++ ++ /* Cluster 'start_lcn' is not in use, ++ * find end of this run. ++ */ ++ end_lcn = start_lcn+1; ++ while (end_lcn < end_buf && ++ (u64) (end_lcn-start_lcn) << vol->cluster_size_bits ++ < discard_max_bytes && ++ !ntfs_bit_get(buf, end_lcn-start_buf)) ++ end_lcn++; ++ ++ ret = fstrim_clusters(vol, ++ start_lcn, end_lcn-start_lcn); ++ if (ret) ++ goto free_out; ++ ++ start_lcn = end_lcn-1; ++ } ++ } ++ } ++ ++ ret = 0; ++free_out: ++ free(buf); ++ return ret; ++} ++ ++#endif /* FITRIM && BLKDISCARD */ ++ ++int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg __attribute__((unused)), ++ unsigned int flags __attribute__((unused)), void *data) ++{ ++ int ret = 0; ++ ++ switch (cmd) { ++#if defined(FITRIM) && defined(BLKDISCARD) ++ case FITRIM: ++ if (!ni || !data) ++ ret = -EINVAL; ++ else ++ ret = fstrim(ni->vol, data); ++ break; ++#else ++#warning FITRIM or BLKDISCARD not defined ++#endif ++ default : ++ ret = -EINVAL; ++ break; ++ } ++ return (ret); ++} +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am +--- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am 2014-07-31 13:51:24.426065810 +0100 +@@ -30,6 +30,7 @@ + efs.c \ + index.c \ + inode.c \ ++ ioctl.c \ + lcnalloc.c \ + logfile.c \ + logging.c \ +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c +--- ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c 2014-07-31 13:51:24.429065815 +0100 +@@ -81,7 +81,12 @@ + #include + #endif /* defined(__APPLE__) || defined(__DARWIN__) */ + ++#ifdef HAVE_LINUX_FS_H ++#include ++#endif ++ + #include "compat.h" ++#include "bitmap.h" + #include "attrib.h" + #include "inode.h" + #include "volume.h" +@@ -97,6 +102,7 @@ + #include "logging.h" + #include "xattrs.h" + #include "misc.h" ++#include "ioctl.h" + + #include "ntfs-3g_common.h" + +@@ -564,8 +570,6 @@ + } + #endif /* defined(__APPLE__) || defined(__DARWIN__) */ + +-#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ +- || (defined(__APPLE__) || defined(__DARWIN__)) + static void ntfs_init(void *userdata __attribute__((unused)), + struct fuse_conn_info *conn) + { +@@ -582,8 +586,8 @@ + >= SAFE_CAPACITY_FOR_BIG_WRITES)) + conn->want |= FUSE_CAP_BIG_WRITES; + #endif ++ conn->want |= FUSE_CAP_IOCTL_DIR; + } +-#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */ + + static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, struct stat *stbuf) +@@ -2573,6 +2577,48 @@ + fuse_reply_err(req, 0); + } + ++static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)), ++ fuse_ino_t ino __attribute__((unused)), ++ int cmd, void *arg, ++ struct fuse_file_info *fi __attribute__((unused)), ++ unsigned flags, const void *data, ++ size_t in_bufsz, size_t out_bufsz) ++{ ++ ntfs_inode *ni; ++ char *buf = (char*)NULL; ++ int bufsz; ++ int ret = 0; ++ ++ if (flags & FUSE_IOCTL_COMPAT) { ++ ret = -ENOSYS; ++ } else { ++ ni = ntfs_inode_open(ctx->vol, INODE(ino)); ++ if (!ni) { ++ ret = -errno; ++ goto fail; ++ } ++ bufsz = (in_bufsz > out_bufsz ? in_bufsz : out_bufsz); ++ if (bufsz) { ++ buf = ntfs_malloc(bufsz); ++ if (!buf) { ++ ret = ENOMEM; ++ goto fail; ++ } ++ memcpy(buf, data, in_bufsz); ++ } ++ ret = ntfs_ioctl(ni, cmd, arg, flags, buf); ++ if (ntfs_inode_close (ni)) ++ set_fuse_error(&ret); ++ } ++ if (ret) ++fail : ++ fuse_reply_err(req, -ret); ++ else ++ fuse_reply_ioctl(req, 0, buf, out_bufsz); ++ if (buf) ++ free(buf); ++} ++ + static void ntfs_fuse_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t vidx) + { +@@ -3496,6 +3542,7 @@ + .fsyncdir = ntfs_fuse_fsync, + .bmap = ntfs_fuse_bmap, + .destroy = ntfs_fuse_destroy2, ++ .ioctl = ntfs_fuse_ioctl, + #if !KERNELPERMS | (POSIXACLS & !KERNELACLS) + .access = ntfs_fuse_access, + #endif +@@ -3512,10 +3559,7 @@ + .setbkuptime = ntfs_macfuse_setbkuptime, + .setchgtime = ntfs_macfuse_setchgtime, + #endif /* defined(__APPLE__) || defined(__DARWIN__) */ +-#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ +- || (defined(__APPLE__) || defined(__DARWIN__)) + .init = ntfs_init +-#endif + }; + + static int ntfs_fuse_init(void) +diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c +--- ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c 2014-02-15 14:07:52.000000000 +0000 ++++ ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c 2014-07-31 13:51:24.430065816 +0100 +@@ -96,6 +96,7 @@ + #include "logging.h" + #include "xattrs.h" + #include "misc.h" ++#include "ioctl.h" + + #include "ntfs-3g_common.h" + +@@ -636,8 +637,6 @@ + } + #endif /* defined(__APPLE__) || defined(__DARWIN__) */ + +-#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ +- || (defined(__APPLE__) || defined(__DARWIN__)) + static void *ntfs_init(struct fuse_conn_info *conn) + { + #if defined(__APPLE__) || defined(__DARWIN__) +@@ -653,9 +652,9 @@ + >= SAFE_CAPACITY_FOR_BIG_WRITES)) + conn->want |= FUSE_CAP_BIG_WRITES; + #endif ++ conn->want |= FUSE_CAP_IOCTL_DIR; + return NULL; + } +-#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */ + + static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) + { +@@ -2412,6 +2411,28 @@ + return (ret); + } + ++static int ntfs_fuse_ioctl(const char *path, ++ int cmd, void *arg, ++ struct fuse_file_info *fi __attribute__((unused)), ++ unsigned int flags, void *data) ++{ ++ ntfs_inode *ni; ++ int ret; ++ ++ if (flags & FUSE_IOCTL_COMPAT) ++ return -ENOSYS; ++ ++ ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); ++ if (!ni) ++ return -errno; ++ ++ ret = ntfs_ioctl(ni, cmd, arg, flags, data); ++ ++ if (ntfs_inode_close (ni)) ++ set_fuse_error(&ret); ++ return ret; ++} ++ + static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx) + { + ntfs_inode *ni; +@@ -3335,6 +3356,7 @@ + .fsyncdir = ntfs_fuse_fsync, + .bmap = ntfs_fuse_bmap, + .destroy = ntfs_fuse_destroy2, ++ .ioctl = ntfs_fuse_ioctl, + #if !KERNELPERMS | (POSIXACLS & !KERNELACLS) + .access = ntfs_fuse_access, + .opendir = ntfs_fuse_opendir, +@@ -3352,10 +3374,7 @@ + .setbkuptime = ntfs_macfuse_setbkuptime, + .setchgtime = ntfs_macfuse_setchgtime, + #endif /* defined(__APPLE__) || defined(__DARWIN__) */ +-#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ +- || (defined(__APPLE__) || defined(__DARWIN__)) + .init = ntfs_init +-#endif + }; + + static int ntfs_fuse_init(void) diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 0afc5cd..8078265 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -4,7 +4,7 @@ Name: libguestfs-winsupport Version: 7.1 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Add support for Windows guests to libguestfs URL: http://www.ntfs-3g.org/ @@ -24,6 +24,18 @@ Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.t Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch +# Upstream patches which add fstrim support. +# ae9aeebbbf1523f3e37221b1172cf05775ef8ec9 +Patch1: 0001-Upgraded-fuse-lite-to-support-ioctls.patch +# f4e3f126df0a577903ec043dbcbe38e2863ce3d6 +Patch2: 0002-Implemented-fstrim-8.patch +# c26a519da1ed182e7cfd67e7a353932dda53d811 +Patch3: 0001-Fixed-fstrim-8-applied-to-partitions.patch +# Patch2 requires that libntfs-3g/Makefile is regenerated. This can +# be removed, as well as the call to autoreconf below, when we move to +# a released version of ntfs-3g that includes the new feature. +BuildRequires: autoconf automake + BuildRequires: libtool, libattr-devel BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel @@ -45,6 +57,10 @@ ntfs-3g %{ntfs_3g_version}. %prep %setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} %patch0 -p1 -b .unsupported +%patch1 -p1 -b .ioctl +%patch2 -p1 -b .fstrim +%patch3 -p1 -b .parts +autoreconf -i %build @@ -146,6 +162,10 @@ echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsup %changelog +* Thu Aug 28 2014 Richard W.M. Jones - 7.1-3 +- Add patches from Fedora package which add fstrim support. + resolves: rhbz#1100319 + * Mon Jul 21 2014 Richard W.M. Jones - 7.1-2 - New package for RHEL 7.1 - Rebase to ntfs-3g 2014.2.15 From 222f51b0015d8de1179e35da93658fc59eb2af08 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 4 Sep 2014 18:23:32 +0100 Subject: [PATCH 06/10] Enable debuginfo support and stripping. resolves: rhbz#1100319 --- libguestfs-winsupport.spec | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 8078265..1689c62 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -1,10 +1,8 @@ -%global debug_package %{nil} - %global ntfs_version 2014.2.15 Name: libguestfs-winsupport Version: 7.1 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Add support for Windows guests to libguestfs URL: http://www.ntfs-3g.org/ @@ -162,6 +160,10 @@ echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsup %changelog +* Thu Aug 28 2014 Richard W.M. Jones - 7.1-4 +- Enable debuginfo support and stripping. + resolves: rhbz#1100319 + * Thu Aug 28 2014 Richard W.M. Jones - 7.1-3 - Add patches from Fedora package which add fstrim support. resolves: rhbz#1100319 From 100ba3c7d2244afdf364d2b193ef705f92995d9a Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 15 May 2015 12:24:55 -0400 Subject: [PATCH 07/10] Enable aarch64 architecture. resolves: rhbz#1221583 --- libguestfs-winsupport.spec | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 1689c62..3b91be0 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -2,12 +2,12 @@ Name: libguestfs-winsupport Version: 7.1 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Add support for Windows guests to libguestfs URL: http://www.ntfs-3g.org/ License: GPLv2+ -ExclusiveArch: x86_64 +ExclusiveArch: aarch64 x86_64 # This package shouldn't be installed without installing the base # libguestfs package. @@ -160,6 +160,10 @@ echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsup %changelog +* Fri May 15 2015 Richard W.M. Jones - 7.1-5 +- Enable aarch64 architecture. + resolves: rhbz#1221583 + * Thu Aug 28 2014 Richard W.M. Jones - 7.1-4 - Enable debuginfo support and stripping. resolves: rhbz#1100319 From 807d19429511173901ed729e6657595186caa822 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 30 Jun 2015 13:36:35 -0400 Subject: [PATCH 08/10] Bump version and rebuild. related: rhbz#1221583 --- libguestfs-winsupport.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 3b91be0..b0ceda8 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -2,7 +2,7 @@ Name: libguestfs-winsupport Version: 7.1 -Release: 5%{?dist} +Release: 6%{?dist} Summary: Add support for Windows guests to libguestfs URL: http://www.ntfs-3g.org/ @@ -160,6 +160,10 @@ echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsup %changelog +* Tue Jun 30 2015 Richard W.M. Jones - 7.1-6 +- Bump version and rebuild. + related: rhbz#1221583 + * Fri May 15 2015 Richard W.M. Jones - 7.1-5 - Enable aarch64 architecture. resolves: rhbz#1221583 From 2cd5f58b39e3749f0d828360c3d53636b39f7172 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 7 Jul 2015 07:20:11 -0400 Subject: [PATCH 09/10] Rebase and rebuild for RHEL 7.2 resolves: rhbz#1240278 --- ...Fixed-fstrim-8-applied-to-partitions.patch | 217 ------ ...Upgraded-fuse-lite-to-support-ioctls.patch | 610 ----------------- 0002-Implemented-fstrim-8.patch | 648 ------------------ CVE-2015-3202.patch | 80 +++ libguestfs-winsupport.spec | 136 +--- sources | 2 +- 6 files changed, 119 insertions(+), 1574 deletions(-) delete mode 100644 0001-Fixed-fstrim-8-applied-to-partitions.patch delete mode 100644 0001-Upgraded-fuse-lite-to-support-ioctls.patch delete mode 100644 0002-Implemented-fstrim-8.patch create mode 100644 CVE-2015-3202.patch diff --git a/0001-Fixed-fstrim-8-applied-to-partitions.patch b/0001-Fixed-fstrim-8-applied-to-partitions.patch deleted file mode 100644 index b67cb71..0000000 --- a/0001-Fixed-fstrim-8-applied-to-partitions.patch +++ /dev/null @@ -1,217 +0,0 @@ -From c26a519da1ed182e7cfd67e7a353932dda53d811 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= -Date: Mon, 4 Aug 2014 17:39:50 +0200 -Subject: [PATCH] Fixed fstrim(8) applied to partitions - -The new way goes via /sys/dev/block/MAJOR:MINOR to map partitions to -devices and get discard parameters of the parent device. It also ensures -that the partition is aligned to the discard block size. - -Contributed by Richard W.M. Jones ---- - libntfs-3g/ioctl.c | 140 ++++++++++++++++++++++++++--------------------------- - 1 file changed, 68 insertions(+), 72 deletions(-) - -diff --git a/libntfs-3g/ioctl.c b/libntfs-3g/ioctl.c -index bbbceb9..eb7c8e7 100644 ---- a/libntfs-3g/ioctl.c -+++ b/libntfs-3g/ioctl.c -@@ -66,8 +66,6 @@ - #include - #endif - --#include -- - #include "compat.h" - #include "debug.h" - #include "bitmap.h" -@@ -135,17 +133,14 @@ static int read_u64(const char *path, u64 *n) - } - - /* Find discard limits for current backing device. -- * XXX Kernel makes this a pain in the neck. - */ --static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, -+static int fstrim_limits(ntfs_volume *vol, -+ u64 *discard_alignment, -+ u64 *discard_granularity, - u64 *discard_max_bytes) - { - struct stat statbuf; -- DIR *dir; -- struct dirent *d; -- char path[80]; -- char line[64]; -- char dev[64]; -+ char path1[80], path2[80]; - int ret; - - /* Stat the backing device. Caller has ensured it is a block device. */ -@@ -155,82 +150,78 @@ static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, - return -errno; - } - -- /* Now look for a /sys/block//dev file which contains -- * "major:minor\n". -+ /* For whole devices, -+ * /sys/dev/block/MAJOR:MINOR/discard_alignment -+ * /sys/dev/block/MAJOR:MINOR/queue/discard_granularity -+ * /sys/dev/block/MAJOR:MINOR/queue/discard_max_bytes -+ * will exist. -+ * For partitions, we also need to check the parent device: -+ * /sys/dev/block/MAJOR:MINOR/../queue/discard_granularity -+ * /sys/dev/block/MAJOR:MINOR/../queue/discard_max_bytes - */ -- snprintf(dev, sizeof dev, "%d:%d\n", -+ snprintf(path1, sizeof path1, "/sys/dev/block/%d:%d", - major(statbuf.st_rdev), minor(statbuf.st_rdev)); - -- dir = opendir("/sys/block"); -- if (dir == NULL) { -- ntfs_log_debug("fstrim_limits: could not open /sys/block\n"); -- return -errno; -+ snprintf(path2, sizeof path2, "%s/discard_alignment", path1); -+ ret = read_u64(path2, discard_alignment); -+ if (ret) { -+ if (ret != -ENOENT) -+ return ret; -+ else -+ /* We would expect this file to exist on all -+ * modern kernels. But for the sake of very -+ * old kernels: -+ */ -+ goto not_found; - } -- for (;;) { -- errno = 0; -- d = readdir(dir); -- if (!d) break; - -- snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name); -- ret = read_line(path, line, sizeof line); -- if (ret) -- continue; -- if (strcmp(line, dev) == 0) -- goto found; -+ snprintf(path2, sizeof path2, "%s/queue/discard_granularity", path1); -+ ret = read_u64(path2, discard_granularity); -+ if (ret) { -+ if (ret != -ENOENT) -+ return ret; -+ else { -+ snprintf(path2, sizeof path2, -+ "%s/../queue/discard_granularity", path1); -+ ret = read_u64(path2, discard_granularity); -+ if (ret) { -+ if (ret != -ENOENT) -+ return ret; -+ else -+ goto not_found; -+ } -+ } - } - -- /* Check readdir didn't fail. */ -- if (errno != 0) { -- ret = -errno; -- ntfs_log_debug("fstrim_limits: readdir failed\n"); -- goto out; -+ snprintf(path2, sizeof path2, "%s/queue/discard_max_bytes", path1); -+ ret = read_u64(path2, discard_max_bytes); -+ if (ret) { -+ if (ret != -ENOENT) -+ return ret; -+ else { -+ snprintf(path2, sizeof path2, -+ "%s/../queue/discard_max_bytes", path1); -+ ret = read_u64(path2, discard_max_bytes); -+ if (ret) { -+ if (ret != -ENOENT) -+ return ret; -+ else -+ goto not_found; -+ } -+ } - } - -+ return 0; -+ -+not_found: - /* If we reach here then we didn't find the device. This is - * not an error, but set discard_max_bytes = 0 to indicate - * that discard is not available. - */ -+ *discard_alignment = 0; - *discard_granularity = 0; - *discard_max_bytes = 0; -- ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n", -- vol->dev->d_name); -- ret = 0; -- goto out; -- --found: -- /* Found the device at /sys/block/ + d->d_name */ -- snprintf (path, sizeof path, -- "/sys/block/%s/queue/discard_granularity", -- d->d_name); -- ret = read_u64(path, discard_granularity); -- if (ret) { -- ntfs_log_debug("fstrim_limits: could not read %s\n", path); -- goto out; -- } -- -- snprintf (path, sizeof path, -- "/sys/block/%s/queue/discard_max_bytes", -- d->d_name); -- ret = read_u64(path, discard_max_bytes); -- if (ret) { -- ntfs_log_debug("fstrim_limits: could not read %s\n", path); -- goto out; -- } -- -- ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n", -- d->d_name, -- (unsigned long long) *discard_granularity, -- (unsigned long long) *discard_max_bytes); -- -- ret = 0; --out: -- if (closedir (dir) == -1) { -- ret = -errno; -- ntfs_log_debug("fstrim_limits: closedir failed\n"); -- return ret; -- } -- -- return ret; -+ return 0; - } - - #define FSTRIM_BUFSIZ 4096 -@@ -247,7 +238,7 @@ static int fstrim(ntfs_volume *vol, void *data) - u64 start = range->start; - u64 len = range->len; - u64 minlen = range->minlen; -- u64 discard_granularity, discard_max_bytes; -+ u64 discard_alignment, discard_granularity, discard_max_bytes; - u8 *buf = NULL; - LCN start_buf; - int ret; -@@ -279,9 +270,14 @@ static int fstrim(ntfs_volume *vol, void *data) - return -EOPNOTSUPP; - } - -- ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes); -+ ret = fstrim_limits(vol, &discard_alignment, -+ &discard_granularity, &discard_max_bytes); - if (ret) - return ret; -+ if (discard_alignment != 0) { -+ ntfs_log_debug("fstrim: backing device is not aligned for discards\n"); -+ return -EOPNOTSUPP; -+ } - if (discard_granularity > vol->cluster_size) { - ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n"); - return -EOPNOTSUPP; --- -1.9.3 - diff --git a/0001-Upgraded-fuse-lite-to-support-ioctls.patch b/0001-Upgraded-fuse-lite-to-support-ioctls.patch deleted file mode 100644 index 0c9b7cc..0000000 --- a/0001-Upgraded-fuse-lite-to-support-ioctls.patch +++ /dev/null @@ -1,610 +0,0 @@ -diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h ---- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_common.h 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_common.h 2014-07-31 13:47:17.401904166 +0100 -@@ -49,6 +49,22 @@ - #endif - - #define FUSE_CAP_BIG_WRITES (1 << 5) -+#define FUSE_CAP_IOCTL_DIR (1 << 11) -+ -+/** -+ * Ioctl flags -+ * -+ * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine -+ * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed -+ * FUSE_IOCTL_RETRY: retry with new iovecs -+ * FUSE_IOCTL_DIR: is a directory -+ */ -+#define FUSE_IOCTL_COMPAT (1 << 0) -+#define FUSE_IOCTL_UNRESTRICTED (1 << 1) -+#define FUSE_IOCTL_RETRY (1 << 2) -+#define FUSE_IOCTL_DIR (1 << 4) -+ -+#define FUSE_IOCTL_MAX_IOV 256 - - /** - * Information about open files -diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h ---- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse.h 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse.h 2014-07-31 13:47:17.401904166 +0100 -@@ -420,9 +420,27 @@ - * Introduced in version 2.6 - */ - int (*bmap) (const char *, size_t blocksize, uint64_t *idx); -- unsigned int flag_nullpath_ok : 1; - - /** -+ * Ioctl -+ * -+ * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in -+ * 64bit environment. The size and direction of data is -+ * determined by _IOC_*() decoding of cmd. For _IOC_NONE, -+ * data will be NULL, for _IOC_WRITE data is out area, for -+ * _IOC_READ in area and if both are set in/out area. In all -+ * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. -+ * -+ * Introduced in version 2.8 -+ */ -+ int (*ioctl) (const char *, int cmd, void *arg, -+ struct fuse_file_info *, unsigned int flags, void *data); -+ -+ /* -+ * The flags below have been discarded, they should not be used -+ */ -+ unsigned int flag_nullpath_ok : 1; -+ /** - * Reserved flags, don't set - */ - unsigned int flag_reserved : 30; -@@ -450,10 +468,8 @@ - /** Private filesystem data */ - void *private_data; - --#ifdef POSIXACLS - /** Umask of the calling process (introduced in version 2.8) */ - mode_t umask; --#endif - }; - - /* ----------------------------------------------------------- * -@@ -601,6 +617,8 @@ - const char *name); - int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, - uint64_t *idx); -+int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, -+ struct fuse_file_info *fi, unsigned int flags, void *data); - void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); - void fuse_fs_destroy(struct fuse_fs *fs); - -diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h ---- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_kernel.h 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_kernel.h 2014-07-31 13:47:17.401904166 +0100 -@@ -48,13 +48,19 @@ - /** Version number of this interface */ - #define FUSE_KERNEL_VERSION 7 - --/** Minor version number of this interface */ --#ifdef POSIXACLS --#define FUSE_KERNEL_MINOR_VERSION 12 -+/** Minor version number of this interface -+ * We introduce ourself as 7.18 (Posix ACLS : 7.12, IOCTL_DIR : 7.18) -+ * and we expect features features defined for 7.18, but not implemented -+ * here to not be triggered by ntfs-3g. -+ */ -+#define FUSE_KERNEL_MINOR_VERSION 18 -+ -+/* -+ * For binary compatibility with old kernels we accept falling back to 7.8 -+ */ -+ -+#define FUSE_KERNEL_MAJOR_FALLBACK 7 - #define FUSE_KERNEL_MINOR_FALLBACK 8 --#else --#define FUSE_KERNEL_MINOR_VERSION 8 --#endif - - /** The node ID of the root inode */ - #define FUSE_ROOT_ID 1 -@@ -83,9 +89,7 @@ - __u32 uid; - __u32 gid; - __u32 rdev; --#ifdef POSIXACLS - __u64 filling; /* JPA needed for minor >= 12, but meaning unknown */ --#endif - }; - - struct fuse_kstatfs { -@@ -132,11 +136,13 @@ - * INIT request/reply flags - * FUSE_BIG_WRITES: allow big writes to be issued to the file system - * FUSE_DONT_MASK: don't apply umask to file mode on create operations -+ * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories - */ - #define FUSE_ASYNC_READ (1 << 0) - #define FUSE_POSIX_LOCKS (1 << 1) - #define FUSE_BIG_WRITES (1 << 5) - #define FUSE_DONT_MASK (1 << 6) -+#define FUSE_HAS_IOCTL_DIR (1 << 11) - - /** - * Release flags -@@ -180,6 +186,7 @@ - FUSE_INTERRUPT = 36, - FUSE_BMAP = 37, - FUSE_DESTROY = 38, -+ FUSE_IOCTL = 39, - }; - - /* The read buffer is required to be at least 8k, but may be much larger */ -@@ -215,10 +222,8 @@ - struct fuse_mknod_in { - __u32 mode; - __u32 rdev; --#ifdef POSIXACLS - __u32 umask; - __u32 padding; --#endif - }; - - struct fuse_mkdir_in { -@@ -255,20 +260,14 @@ - - struct fuse_open_in { - __u32 flags; --#ifdef POSIXACLS -- __u32 unused; --#else -- __u32 mode; --#endif -+ __u32 mode; /* unused for protocol < 7.12 */ - }; - - struct fuse_create_in { - __u32 flags; - __u32 mode; --#ifdef POSIXACLS - __u32 umask; - __u32 padding; --#endif - }; - - struct fuse_open_out { -@@ -305,11 +304,9 @@ - __u64 offset; - __u32 size; - __u32 write_flags; --#ifdef POSIXACLS - __u64 lock_owner; /* JPA */ - __u32 flags; /* JPA */ - __u32 padding; /* JPA */ --#endif - }; - - struct fuse_write_out { -@@ -389,6 +386,27 @@ - __u64 block; - }; - -+struct fuse_ioctl_in { -+ __u64 fh; -+ __u32 flags; -+ __u32 cmd; -+ __u64 arg; -+ __u32 in_size; -+ __u32 out_size; -+}; -+ -+struct fuse_ioctl_iovec { -+ __u64 base; -+ __u64 len; -+}; -+ -+struct fuse_ioctl_out { -+ __s32 result; -+ __u32 flags; -+ __u32 in_iovs; -+ __u32 out_iovs; -+}; -+ - struct fuse_in_header { - __u32 len; - __u32 opcode; -diff -ur ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h ---- ntfs-3g_ntfsprogs-2014.2.15/include/fuse-lite/fuse_lowlevel.h 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/include/fuse-lite/fuse_lowlevel.h 2014-07-31 13:47:17.402904167 +0100 -@@ -101,10 +101,8 @@ - /** Thread ID of the calling process */ - pid_t pid; - --#ifdef POSIXACLS - /** Umask of the calling process (introduced in version 2.8) */ - mode_t umask; --#endif - }; - - /* 'to_set' flags in setattr */ -@@ -805,6 +803,37 @@ - */ - void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, - uint64_t idx); -+ /** -+ * Ioctl -+ * -+ * Note: For unrestricted ioctls (not allowed for FUSE -+ * servers), data in and out areas can be discovered by giving -+ * iovs and setting FUSE_IOCTL_RETRY in @flags. For -+ * restricted ioctls, kernel prepares in/out data area -+ * according to the information encoded in cmd. -+ * -+ * Introduced in version 2.8 -+ * -+ * Valid replies: -+ * fuse_reply_ioctl_retry -+ * fuse_reply_ioctl -+ * fuse_reply_ioctl_iov -+ * fuse_reply_err -+ * -+ * @param req request handle -+ * @param ino the inode number -+ * @param cmd ioctl command -+ * @param arg ioctl argument -+ * @param fi file information -+ * @param flags for FUSE_IOCTL_* flags -+ * @param in_buf data fetched from the caller -+ * @param in_bufsz number of fetched bytes -+ * @param out_bufsz maximum size of output data -+ */ -+ void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, -+ struct fuse_file_info *fi, unsigned flags, -+ const void *in_buf, size_t in_bufsz, size_t out_bufsz); -+ - }; - - /** -@@ -1022,6 +1051,20 @@ - const char *name, const struct stat *stbuf, - off_t off); - -+/** -+ * Reply to finish ioctl -+ * -+ * Possible requests: -+ * ioctl -+ * -+ * @param req request handle -+ * @param result result to be passed to the caller -+ * @param buf buffer containing output data -+ * @param size length of output data -+ */ -+int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size); -+ -+ - /* ----------------------------------------------------------- * - * Utility functions * - * ----------------------------------------------------------- */ -diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c ---- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse.c 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse.c 2014-07-31 13:47:17.403904167 +0100 -@@ -1040,6 +1040,21 @@ - return -ENOSYS; - } - -+int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, -+ struct fuse_file_info *fi, unsigned int flags, void *data) -+{ -+ fuse_get_context()->private_data = fs->user_data; -+ if (fs->op.ioctl) { -+/* -+ if (fs->debug) -+ fprintf(stderr, "ioctl[%llu] 0x%x flags: 0x%x\n", -+ (unsigned long long) fi->fh, cmd, flags); -+*/ -+ return fs->op.ioctl(path, cmd, arg, fi, flags, data); -+ } else -+ return -ENOSYS; -+} -+ - static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) - { - struct node *node; -@@ -2716,6 +2731,60 @@ - reply_err(req, err); - } - -+static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, -+ struct fuse_file_info *llfi, unsigned int flags, -+ const void *in_buf, size_t in_bufsz, -+ size_t out_bufsz) -+{ -+ struct fuse *f = req_fuse_prepare(req); -+ struct fuse_intr_data d; -+ struct fuse_file_info fi; -+ char *path, *out_buf = NULL; -+ int err; -+ -+ err = -EPERM; -+ if (flags & FUSE_IOCTL_UNRESTRICTED) -+ goto err; -+ -+ if (flags & FUSE_IOCTL_DIR) -+ get_dirhandle(llfi, &fi); -+ else -+ fi = *llfi; -+ -+ if (out_bufsz) { -+ err = -ENOMEM; -+ out_buf = malloc(out_bufsz); -+ if (!out_buf) -+ goto err; -+ } -+ -+ assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz); -+ if (out_buf) -+ memcpy(out_buf, in_buf, in_bufsz); -+ -+ path = get_path(f, ino); /* Should be get_path_nullok() */ -+ if (!path) { -+ err = ENOENT; -+ goto err; -+ } -+ -+ fuse_prepare_interrupt(f, req, &d); -+ -+ /* Note : const qualifier dropped */ -+ err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags, -+ out_buf ? (void*)out_buf : (void*)(uintptr_t)in_buf); -+ -+ fuse_finish_interrupt(f, req, &d); -+ free(path); -+ -+ fuse_reply_ioctl(req, err, out_buf, out_bufsz); -+ goto out; -+err: -+ reply_err(req, err); -+out: -+ free(out_buf); -+} -+ - static struct fuse_lowlevel_ops fuse_path_ops = { - .init = fuse_lib_init, - .destroy = fuse_lib_destroy, -@@ -2751,6 +2820,7 @@ - .getlk = fuse_lib_getlk, - .setlk = fuse_lib_setlk, - .bmap = fuse_lib_bmap, -+ .ioctl = fuse_lib_ioctl, - }; - - struct fuse_session *fuse_get_session(struct fuse *f) -diff -ur ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c ---- ntfs-3g_ntfsprogs-2014.2.15/libfuse-lite/fuse_lowlevel.c 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15.new/libfuse-lite/fuse_lowlevel.c 2014-07-31 13:47:17.403904167 +0100 -@@ -333,12 +333,8 @@ - - memset(&arg, 0, sizeof(arg)); - fill_entry(&arg, e); --#ifdef POSIXACLS - return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 - ? sizeof(arg) : FUSE_COMPAT_ENTRY_OUT_SIZE)); --#else -- return send_reply_ok(req, &arg, sizeof(arg)); --#endif - } - - int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, -@@ -351,7 +347,6 @@ - - memset(&arg, 0, sizeof(arg)); - fill_entry(&arg.e, e); --#ifdef POSIXACLS - if (req->f->conn.proto_minor < 12) { - fill_open((struct fuse_open_out*) - ((char*)&arg + FUSE_COMPAT_ENTRY_OUT_SIZE), f); -@@ -361,10 +356,6 @@ - fill_open(&arg.o, f); - return send_reply_ok(req, &arg, sizeof(arg)); - } --#else -- fill_open(&arg.o, f); -- return send_reply_ok(req, &arg, sizeof(arg)); --#endif - } - - int fuse_reply_attr(fuse_req_t req, const struct stat *attr, -@@ -377,12 +368,8 @@ - arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); - convert_stat(attr, &arg.attr); - --#ifdef POSIXACLS - return send_reply_ok(req, &arg, (req->f->conn.proto_minor >= 12 - ? sizeof(arg) : FUSE_COMPAT_FUSE_ATTR_OUT_SIZE)); --#else -- return send_reply_ok(req, &arg, sizeof(arg)); --#endif - } - - int fuse_reply_readlink(fuse_req_t req, const char *linkname) -@@ -462,6 +449,28 @@ - return send_reply_ok(req, &arg, sizeof(arg)); - } - -+int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) -+{ -+ struct fuse_ioctl_out arg; -+ struct iovec iov[3]; -+ size_t count = 1; -+ -+ memset(&arg, 0, sizeof(arg)); -+ arg.result = result; -+ iov[count].iov_base = &arg; -+ iov[count].iov_len = sizeof(arg); -+ count++; -+ -+ if (size) { -+ /* Note : const qualifier dropped */ -+ iov[count].iov_base = (char *)(uintptr_t) buf; -+ iov[count].iov_len = size; -+ count++; -+ } -+ -+ return send_reply_iov(req, 0, iov, count); -+} -+ - static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) - { - const char *name = (const char *) inarg; -@@ -538,11 +547,9 @@ - const struct fuse_mknod_in *arg = (const struct fuse_mknod_in *) inarg; - const char *name = PARAM(arg); - --#ifdef POSIXACLS - if (req->f->conn.proto_minor >= 12) - req->ctx.umask = arg->umask; - else --#endif - name = (const char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; - - if (req->f->op.mknod) -@@ -555,10 +562,8 @@ - { - const struct fuse_mkdir_in *arg = (const struct fuse_mkdir_in *) inarg; - --#ifdef POSIXACLS - if (req->f->conn.proto_minor >= 12) - req->ctx.umask = arg->umask; --#endif - - if (req->f->op.mkdir) - req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); -@@ -630,11 +635,9 @@ - memset(&fi, 0, sizeof(fi)); - fi.flags = arg->flags; - --#ifdef POSIXACLS - if (req->f->conn.proto_minor >= 12) - req->ctx.umask = arg->umask; - else --#endif - name = (const char *) inarg + sizeof(struct fuse_open_in); - - req->f->op.create(req, nodeid, name, arg->mode, &fi); -@@ -682,7 +685,6 @@ - fi.writepage = arg->write_flags & 1; - - if (req->f->op.write) { --#ifdef POSIXACLS - const char *buf; - - if (req->f->conn.proto_minor >= 12) -@@ -690,9 +692,6 @@ - else - buf = ((const char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE; - req->f->op.write(req, nodeid, buf, arg->size, arg->offset, &fi); --#else -- req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi); --#endif - } else - fuse_reply_err(req, ENOSYS); - } -@@ -1011,6 +1010,39 @@ - fuse_reply_err(req, ENOSYS); - } - -+static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) -+{ -+ const struct fuse_ioctl_in *arg = (const struct fuse_ioctl_in *) inarg; -+ unsigned int flags = arg->flags; -+ const void *in_buf = arg->in_size ? PARAM(arg) : NULL; -+ struct fuse_file_info fi; -+ -+ if (flags & FUSE_IOCTL_DIR && -+ !(req->f->conn.want & FUSE_CAP_IOCTL_DIR)) { -+ fuse_reply_err(req, ENOTTY); -+ return; -+ } -+ -+ memset(&fi, 0, sizeof(fi)); -+ fi.fh = arg->fh; -+ -+/* TODO JPA (need req->ioctl_64bit in obscure fuse_req_t) -+// probably a 64 bit ioctl on a 32-bit cpu -+// this is to forward a request from the kernel -+ if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 && -+ !(flags & FUSE_IOCTL_32BIT)) { -+ req->ioctl_64bit = 1; -+ } -+*/ -+ -+ if (req->f->op.ioctl) -+ req->f->op.ioctl(req, nodeid, arg->cmd, -+ (void *)(uintptr_t)arg->arg, &fi, flags, -+ in_buf, arg->in_size, arg->out_size); -+ else -+ fuse_reply_err(req, ENOSYS); -+} -+ - static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) - { - const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg; -@@ -1047,6 +1079,8 @@ - #endif - if (arg->flags & FUSE_BIG_WRITES) - f->conn.capable |= FUSE_CAP_BIG_WRITES; -+ if (arg->flags & FUSE_HAS_IOCTL_DIR) -+ f->conn.capable |= FUSE_CAP_IOCTL_DIR; - } else { - f->conn.async_read = 0; - f->conn.max_readahead = 0; -@@ -1069,28 +1103,28 @@ - memset(&outarg, 0, sizeof(outarg)); - outarg.major = FUSE_KERNEL_VERSION; - /* -- * if POSIXACLS is not set, protocol 7.8 provides a good -- * compatibility with older kernel modules. -- * if POSIXACLS is set, we try to use protocol 7.12 supposed -- * to have the ability to process the umask conditionnally, -- * but, when using an older kernel module, we fallback to 7.8 -+ * Suggest using protocol 7.18 when available, and fallback -+ * to 7.8 when running on an old kernel. -+ * Protocol 7.12 has the ability to process the umask -+ * conditionnally (as needed if POSIXACLS is set) -+ * Protocol 7.18 has the ability to process the ioctls - */ --#ifdef POSIXACLS -- if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12)) -+ if (arg->major > 7 || (arg->major == 7 && arg->minor >= 18)) { - outarg.minor = FUSE_KERNEL_MINOR_VERSION; -- else -- outarg.minor = FUSE_KERNEL_MINOR_FALLBACK; --#else -- outarg.minor = FUSE_KERNEL_MINOR_VERSION; -+ if (f->conn.want & FUSE_CAP_IOCTL_DIR) -+ outarg.flags |= FUSE_HAS_IOCTL_DIR; -+#ifdef POSIXACLS -+ if (f->conn.want & FUSE_CAP_DONT_MASK) -+ outarg.flags |= FUSE_DONT_MASK; - #endif -+ } else { -+ outarg.major = FUSE_KERNEL_MAJOR_FALLBACK; -+ outarg.minor = FUSE_KERNEL_MINOR_FALLBACK; -+ } - if (f->conn.async_read) - outarg.flags |= FUSE_ASYNC_READ; - if (f->op.getlk && f->op.setlk) - outarg.flags |= FUSE_POSIX_LOCKS; --#ifdef POSIXACLS -- if (f->conn.want & FUSE_CAP_DONT_MASK) -- outarg.flags |= FUSE_DONT_MASK; --#endif - if (f->conn.want & FUSE_CAP_BIG_WRITES) - outarg.flags |= FUSE_BIG_WRITES; - outarg.max_readahead = f->conn.max_readahead; -@@ -1191,6 +1225,7 @@ - [FUSE_CREATE] = { do_create, "CREATE" }, - [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, - [FUSE_BMAP] = { do_bmap, "BMAP" }, -+ [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, - [FUSE_DESTROY] = { do_destroy, "DESTROY" }, - }; - diff --git a/0002-Implemented-fstrim-8.patch b/0002-Implemented-fstrim-8.patch deleted file mode 100644 index 467f5d6..0000000 --- a/0002-Implemented-fstrim-8.patch +++ /dev/null @@ -1,648 +0,0 @@ -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac ntfs-3g_ntfsprogs-2014.2.15/configure.ac ---- ntfs-3g_ntfsprogs-2014.2.15.old/configure.ac 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15/configure.ac 2014-07-31 13:51:24.425065808 +0100 -@@ -463,7 +463,8 @@ - regex.h endian.h byteswap.h sys/byteorder.h sys/disk.h sys/endian.h \ - sys/param.h sys/ioctl.h sys/mkdev.h sys/mount.h sys/stat.h sys/types.h \ - sys/vfs.h sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h \ -- linux/hdreg.h machine/endian.h windows.h syslog.h pwd.h malloc.h]) -+ linux/fs.h inttypes.h linux/hdreg.h \ -+ machine/endian.h windows.h syslog.h pwd.h malloc.h]) - - # Checks for typedefs, structures, and compiler characteristics. - AC_HEADER_STDBOOL -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h ---- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/ioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/ioctl.h 2014-07-31 13:51:24.426065810 +0100 -@@ -0,0 +1,30 @@ -+/* -+ * -+ * Copyright (c) 2014 Jean-Pierre Andre -+ * -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program (in the main directory of the NTFS-3G -+ * distribution in the file COPYING); if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef IOCTL_H -+#define IOCTL_H -+ -+int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg, -+ unsigned int flags, void *data); -+ -+#endif /* IOCTL_H */ -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h ---- ntfs-3g_ntfsprogs-2014.2.15.old/include/ntfs-3g/volume.h 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15/include/ntfs-3g/volume.h 2014-07-31 13:51:24.426065810 +0100 -@@ -36,9 +36,7 @@ - #ifdef HAVE_SYS_PARAM_H - #include - #endif --#ifdef HAVE_SYS_MOUNT_H --#include --#endif -+ /* Do not #include here : conflicts with */ - #ifdef HAVE_MNTENT_H - #include - #endif -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c ---- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/ioctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/ioctl.c 2014-07-31 13:51:24.427065813 +0100 -@@ -0,0 +1,382 @@ -+/** -+ * ioctl.c - Processing of ioctls -+ * -+ * This module is part of ntfs-3g library -+ * -+ * Copyright (c) 2014 Jean-Pierre Andre -+ * Copyright (c) 2014 Red Hat, Inc. -+ * -+ * This program/include file is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as published -+ * by the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program/include file is distributed in the hope that it will be -+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program (in the main directory of the NTFS-3G -+ * distribution in the file COPYING); if not, write to the Free Software -+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include "config.h" -+ -+#ifdef HAVE_STDIO_H -+#include -+#endif -+#ifdef HAVE_INTTYPES_H -+#include -+#endif -+#ifdef HAVE_STRING_H -+#include -+#endif -+#ifdef HAVE_ERRNO_H -+#include -+#endif -+#ifdef HAVE_FCNTL_H -+#include -+#endif -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+#ifdef HAVE_STDLIB_H -+#include -+#endif -+#ifdef HAVE_LIMITS_H -+#include -+#endif -+#include -+ -+#ifdef HAVE_SETXATTR -+#include -+#endif -+ -+#ifdef HAVE_SYS_TYPES_H -+#include -+#endif -+ -+#ifdef HAVE_SYS_STAT_H -+#include -+#endif -+ -+#ifdef HAVE_LINUX_FS_H -+#include -+#endif -+ -+#include -+ -+#include "compat.h" -+#include "debug.h" -+#include "bitmap.h" -+#include "attrib.h" -+#include "inode.h" -+#include "layout.h" -+#include "volume.h" -+#include "index.h" -+#include "logging.h" -+#include "ntfstime.h" -+#include "unistr.h" -+#include "dir.h" -+#include "security.h" -+#include "ioctl.h" -+#include "misc.h" -+ -+#if defined(FITRIM) && defined(BLKDISCARD) -+ -+/* Issue a TRIM request to the underlying device for the given clusters. */ -+static int fstrim_clusters(ntfs_volume *vol, LCN lcn, s64 length) -+{ -+ struct ntfs_device *dev = vol->dev; -+ uint64_t range[2]; -+ -+ ntfs_log_debug("fstrim_clusters: %lld length %lld\n", -+ (long long) lcn, (long long) length); -+ -+ range[0] = lcn << vol->cluster_size_bits; -+ range[1] = length << vol->cluster_size_bits; -+ -+ if (dev->d_ops->ioctl(dev, BLKDISCARD, range) == -1) { -+ ntfs_log_debug("fstrim_one_cluster: ioctl failed: %m\n"); -+ return -errno; -+ } -+ return 0; -+} -+ -+static int read_line(const char *path, char *line, size_t max_bytes) -+{ -+ FILE *fp; -+ -+ fp = fopen(path, "r"); -+ if (fp == NULL) -+ return -errno; -+ if (fgets(line, max_bytes, fp) == NULL) { -+ int ret = -EIO; /* fgets doesn't set errno */ -+ fclose(fp); -+ return ret; -+ } -+ fclose (fp); -+ return 0; -+} -+ -+static int read_u64(const char *path, u64 *n) -+{ -+ char line[64]; -+ int ret; -+ -+ ret = read_line(path, line, sizeof line); -+ if (ret) -+ return ret; -+ if (sscanf(line, "%" SCNu64, n) != 1) -+ return -EINVAL; -+ return 0; -+} -+ -+/* Find discard limits for current backing device. -+ * XXX Kernel makes this a pain in the neck. -+ */ -+static int fstrim_limits(ntfs_volume *vol, u64 *discard_granularity, -+ u64 *discard_max_bytes) -+{ -+ struct stat statbuf; -+ DIR *dir; -+ struct dirent *d; -+ char path[80]; -+ char line[64]; -+ char dev[64]; -+ int ret; -+ -+ /* Stat the backing device. Caller has ensured it is a block device. */ -+ if (stat(vol->dev->d_name, &statbuf) == -1) { -+ ntfs_log_debug("fstrim_limits: could not stat %s\n", -+ vol->dev->d_name); -+ return -errno; -+ } -+ -+ /* Now look for a /sys/block//dev file which contains -+ * "major:minor\n". -+ */ -+ snprintf(dev, sizeof dev, "%d:%d\n", -+ major(statbuf.st_rdev), minor(statbuf.st_rdev)); -+ -+ dir = opendir("/sys/block"); -+ if (dir == NULL) { -+ ntfs_log_debug("fstrim_limits: could not open /sys/block\n"); -+ return -errno; -+ } -+ for (;;) { -+ errno = 0; -+ d = readdir(dir); -+ if (!d) break; -+ -+ snprintf(path, sizeof path, "/sys/block/%s/dev", d->d_name); -+ ret = read_line(path, line, sizeof line); -+ if (ret) -+ continue; -+ if (strcmp(line, dev) == 0) -+ goto found; -+ } -+ -+ /* Check readdir didn't fail. */ -+ if (errno != 0) { -+ ret = -errno; -+ ntfs_log_debug("fstrim_limits: readdir failed\n"); -+ goto out; -+ } -+ -+ /* If we reach here then we didn't find the device. This is -+ * not an error, but set discard_max_bytes = 0 to indicate -+ * that discard is not available. -+ */ -+ *discard_granularity = 0; -+ *discard_max_bytes = 0; -+ ntfs_log_debug("fstrim_limits: /sys/block entry corresponding to device %s not found\n", -+ vol->dev->d_name); -+ ret = 0; -+ goto out; -+ -+found: -+ /* Found the device at /sys/block/ + d->d_name */ -+ snprintf (path, sizeof path, -+ "/sys/block/%s/queue/discard_granularity", -+ d->d_name); -+ ret = read_u64(path, discard_granularity); -+ if (ret) { -+ ntfs_log_debug("fstrim_limits: could not read %s\n", path); -+ goto out; -+ } -+ -+ snprintf (path, sizeof path, -+ "/sys/block/%s/queue/discard_max_bytes", -+ d->d_name); -+ ret = read_u64(path, discard_max_bytes); -+ if (ret) { -+ ntfs_log_debug("fstrim_limits: could not read %s\n", path); -+ goto out; -+ } -+ -+ ntfs_log_debug("fstrim_limits: device %s discard granularity = %llu max_bytes = %llu\n", -+ d->d_name, -+ (unsigned long long) *discard_granularity, -+ (unsigned long long) *discard_max_bytes); -+ -+ ret = 0; -+out: -+ if (closedir (dir) == -1) { -+ ret = -errno; -+ ntfs_log_debug("fstrim_limits: closedir failed\n"); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+#define FSTRIM_BUFSIZ 4096 -+ -+/* Trim the filesystem. -+ * -+ * Free blocks between 'start' and 'start+len-1' (both byte offsets) -+ * are found and TRIM requests are sent to the block device. 'minlen' -+ * is the minimum continguous free range to discard. -+ */ -+static int fstrim(ntfs_volume *vol, void *data) -+{ -+ struct fstrim_range *range = data; -+ u64 start = range->start; -+ u64 len = range->len; -+ u64 minlen = range->minlen; -+ u64 discard_granularity, discard_max_bytes; -+ u8 *buf = NULL; -+ LCN start_buf; -+ int ret; -+ -+ ntfs_log_debug("fstrim: start=%llu len=%llu minlen=%llu\n", -+ (unsigned long long) start, -+ (unsigned long long) len, -+ (unsigned long long) minlen); -+ -+ /* Fail if user tries to use the fstrim -o/-l/-m options. -+ * XXX We could fix these limitations in future. -+ */ -+ if (start != 0 || len != (uint64_t)-1) { -+ ntfs_log_debug("fstrim: setting start or length is not supported\n"); -+ return -EINVAL; -+ } -+ if (minlen > vol->cluster_size) { -+ ntfs_log_debug("fstrim: minlen > cluster size is not supported\n"); -+ return -EINVAL; -+ } -+ -+ /* Only block devices are supported. It would be possible to -+ * support backing files (ie. without using loop) but the -+ * ioctls used to punch holes in files are completely -+ * different. -+ */ -+ if (!NDevBlock(vol->dev)) { -+ ntfs_log_debug("fstrim: not supported for non-block-device\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ ret = fstrim_limits(vol, &discard_granularity, &discard_max_bytes); -+ if (ret) -+ return ret; -+ if (discard_granularity > vol->cluster_size) { -+ ntfs_log_debug("fstrim: discard granularity of backing device is larger than cluster size\n"); -+ return -EOPNOTSUPP; -+ } -+ if (discard_max_bytes == 0) { -+ ntfs_log_debug("fstrim: backing device does not support discard (discard_max_bytes == 0)\n"); -+ return -EOPNOTSUPP; -+ } -+ -+ /* Sync the device before doing anything. */ -+ ret = ntfs_device_sync(vol->dev); -+ if (ret) -+ return ret; -+ -+ /* Read through the bitmap. */ -+ buf = ntfs_malloc(FSTRIM_BUFSIZ); -+ if (buf == NULL) -+ return -errno; -+ for (start_buf = 0; start_buf < vol->nr_clusters; -+ start_buf += FSTRIM_BUFSIZ * 8) { -+ s64 count; -+ s64 br; -+ LCN end_buf, start_lcn; -+ -+ /* start_buf is LCN of first cluster in the current buffer. -+ * end_buf is LCN of last cluster + 1 in the current buffer. -+ */ -+ end_buf = start_buf + FSTRIM_BUFSIZ*8; -+ if (end_buf > vol->nr_clusters) -+ end_buf = vol->nr_clusters; -+ count = (end_buf - start_buf) / 8; -+ -+ br = ntfs_attr_pread(vol->lcnbmp_na, start_buf/8, count, buf); -+ if (br != count) { -+ if (br >= 0) -+ ret = -EIO; -+ else -+ ret = -errno; -+ goto free_out; -+ } -+ -+ /* Trim the clusters in large as possible blocks, but -+ * not larger than discard_max_bytes. -+ */ -+ for (start_lcn = start_buf; start_lcn < end_buf; ++start_lcn) { -+ if (!ntfs_bit_get(buf, start_lcn-start_buf)) { -+ LCN end_lcn; -+ -+ /* Cluster 'start_lcn' is not in use, -+ * find end of this run. -+ */ -+ end_lcn = start_lcn+1; -+ while (end_lcn < end_buf && -+ (u64) (end_lcn-start_lcn) << vol->cluster_size_bits -+ < discard_max_bytes && -+ !ntfs_bit_get(buf, end_lcn-start_buf)) -+ end_lcn++; -+ -+ ret = fstrim_clusters(vol, -+ start_lcn, end_lcn-start_lcn); -+ if (ret) -+ goto free_out; -+ -+ start_lcn = end_lcn-1; -+ } -+ } -+ } -+ -+ ret = 0; -+free_out: -+ free(buf); -+ return ret; -+} -+ -+#endif /* FITRIM && BLKDISCARD */ -+ -+int ntfs_ioctl(ntfs_inode *ni, int cmd, void *arg __attribute__((unused)), -+ unsigned int flags __attribute__((unused)), void *data) -+{ -+ int ret = 0; -+ -+ switch (cmd) { -+#if defined(FITRIM) && defined(BLKDISCARD) -+ case FITRIM: -+ if (!ni || !data) -+ ret = -EINVAL; -+ else -+ ret = fstrim(ni->vol, data); -+ break; -+#else -+#warning FITRIM or BLKDISCARD not defined -+#endif -+ default : -+ ret = -EINVAL; -+ break; -+ } -+ return (ret); -+} -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am ---- ntfs-3g_ntfsprogs-2014.2.15.old/libntfs-3g/Makefile.am 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15/libntfs-3g/Makefile.am 2014-07-31 13:51:24.426065810 +0100 -@@ -30,6 +30,7 @@ - efs.c \ - index.c \ - inode.c \ -+ ioctl.c \ - lcnalloc.c \ - logfile.c \ - logging.c \ -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c ---- ntfs-3g_ntfsprogs-2014.2.15.old/src/lowntfs-3g.c 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15/src/lowntfs-3g.c 2014-07-31 13:51:24.429065815 +0100 -@@ -81,7 +81,12 @@ - #include - #endif /* defined(__APPLE__) || defined(__DARWIN__) */ - -+#ifdef HAVE_LINUX_FS_H -+#include -+#endif -+ - #include "compat.h" -+#include "bitmap.h" - #include "attrib.h" - #include "inode.h" - #include "volume.h" -@@ -97,6 +102,7 @@ - #include "logging.h" - #include "xattrs.h" - #include "misc.h" -+#include "ioctl.h" - - #include "ntfs-3g_common.h" - -@@ -564,8 +570,6 @@ - } - #endif /* defined(__APPLE__) || defined(__DARWIN__) */ - --#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ -- || (defined(__APPLE__) || defined(__DARWIN__)) - static void ntfs_init(void *userdata __attribute__((unused)), - struct fuse_conn_info *conn) - { -@@ -582,8 +586,8 @@ - >= SAFE_CAPACITY_FOR_BIG_WRITES)) - conn->want |= FUSE_CAP_BIG_WRITES; - #endif -+ conn->want |= FUSE_CAP_IOCTL_DIR; - } --#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */ - - static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx, - ntfs_inode *ni, struct stat *stbuf) -@@ -2573,6 +2577,48 @@ - fuse_reply_err(req, 0); - } - -+static void ntfs_fuse_ioctl(fuse_req_t req __attribute__((unused)), -+ fuse_ino_t ino __attribute__((unused)), -+ int cmd, void *arg, -+ struct fuse_file_info *fi __attribute__((unused)), -+ unsigned flags, const void *data, -+ size_t in_bufsz, size_t out_bufsz) -+{ -+ ntfs_inode *ni; -+ char *buf = (char*)NULL; -+ int bufsz; -+ int ret = 0; -+ -+ if (flags & FUSE_IOCTL_COMPAT) { -+ ret = -ENOSYS; -+ } else { -+ ni = ntfs_inode_open(ctx->vol, INODE(ino)); -+ if (!ni) { -+ ret = -errno; -+ goto fail; -+ } -+ bufsz = (in_bufsz > out_bufsz ? in_bufsz : out_bufsz); -+ if (bufsz) { -+ buf = ntfs_malloc(bufsz); -+ if (!buf) { -+ ret = ENOMEM; -+ goto fail; -+ } -+ memcpy(buf, data, in_bufsz); -+ } -+ ret = ntfs_ioctl(ni, cmd, arg, flags, buf); -+ if (ntfs_inode_close (ni)) -+ set_fuse_error(&ret); -+ } -+ if (ret) -+fail : -+ fuse_reply_err(req, -ret); -+ else -+ fuse_reply_ioctl(req, 0, buf, out_bufsz); -+ if (buf) -+ free(buf); -+} -+ - static void ntfs_fuse_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, - uint64_t vidx) - { -@@ -3496,6 +3542,7 @@ - .fsyncdir = ntfs_fuse_fsync, - .bmap = ntfs_fuse_bmap, - .destroy = ntfs_fuse_destroy2, -+ .ioctl = ntfs_fuse_ioctl, - #if !KERNELPERMS | (POSIXACLS & !KERNELACLS) - .access = ntfs_fuse_access, - #endif -@@ -3512,10 +3559,7 @@ - .setbkuptime = ntfs_macfuse_setbkuptime, - .setchgtime = ntfs_macfuse_setchgtime, - #endif /* defined(__APPLE__) || defined(__DARWIN__) */ --#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ -- || (defined(__APPLE__) || defined(__DARWIN__)) - .init = ntfs_init --#endif - }; - - static int ntfs_fuse_init(void) -diff -urN ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c ---- ntfs-3g_ntfsprogs-2014.2.15.old/src/ntfs-3g.c 2014-02-15 14:07:52.000000000 +0000 -+++ ntfs-3g_ntfsprogs-2014.2.15/src/ntfs-3g.c 2014-07-31 13:51:24.430065816 +0100 -@@ -96,6 +96,7 @@ - #include "logging.h" - #include "xattrs.h" - #include "misc.h" -+#include "ioctl.h" - - #include "ntfs-3g_common.h" - -@@ -636,8 +637,6 @@ - } - #endif /* defined(__APPLE__) || defined(__DARWIN__) */ - --#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ -- || (defined(__APPLE__) || defined(__DARWIN__)) - static void *ntfs_init(struct fuse_conn_info *conn) - { - #if defined(__APPLE__) || defined(__DARWIN__) -@@ -653,9 +652,9 @@ - >= SAFE_CAPACITY_FOR_BIG_WRITES)) - conn->want |= FUSE_CAP_BIG_WRITES; - #endif -+ conn->want |= FUSE_CAP_IOCTL_DIR; - return NULL; - } --#endif /* defined(FUSE_CAP_DONT_MASK) || (defined(__APPLE__) || defined(__DARWIN__)) */ - - static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf) - { -@@ -2412,6 +2411,28 @@ - return (ret); - } - -+static int ntfs_fuse_ioctl(const char *path, -+ int cmd, void *arg, -+ struct fuse_file_info *fi __attribute__((unused)), -+ unsigned int flags, void *data) -+{ -+ ntfs_inode *ni; -+ int ret; -+ -+ if (flags & FUSE_IOCTL_COMPAT) -+ return -ENOSYS; -+ -+ ni = ntfs_pathname_to_inode(ctx->vol, NULL, path); -+ if (!ni) -+ return -errno; -+ -+ ret = ntfs_ioctl(ni, cmd, arg, flags, data); -+ -+ if (ntfs_inode_close (ni)) -+ set_fuse_error(&ret); -+ return ret; -+} -+ - static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx) - { - ntfs_inode *ni; -@@ -3335,6 +3356,7 @@ - .fsyncdir = ntfs_fuse_fsync, - .bmap = ntfs_fuse_bmap, - .destroy = ntfs_fuse_destroy2, -+ .ioctl = ntfs_fuse_ioctl, - #if !KERNELPERMS | (POSIXACLS & !KERNELACLS) - .access = ntfs_fuse_access, - .opendir = ntfs_fuse_opendir, -@@ -3352,10 +3374,7 @@ - .setbkuptime = ntfs_macfuse_setbkuptime, - .setchgtime = ntfs_macfuse_setchgtime, - #endif /* defined(__APPLE__) || defined(__DARWIN__) */ --#if defined(FUSE_CAP_DONT_MASK) || defined(FUSE_CAP_BIG_WRITES) \ -- || (defined(__APPLE__) || defined(__DARWIN__)) - .init = ntfs_init --#endif - }; - - static int ntfs_fuse_init(void) diff --git a/CVE-2015-3202.patch b/CVE-2015-3202.patch new file mode 100644 index 0000000..6e5cf08 --- /dev/null +++ b/CVE-2015-3202.patch @@ -0,0 +1,80 @@ +--- ntfs-3g_ntfsprogs-2015.3.14/libfuse-lite/mount_util.c.ref 2015-03-14 15:10:12.000000000 +0100 ++++ ntfs-3g_ntfsprogs-2015.3.14/libfuse-lite/mount_util.c 2015-05-18 11:02:50.330654300 +0200 +@@ -66,6 +66,7 @@ + return -1; + } + if (res == 0) { ++ char *env = NULL; + char templ[] = "/tmp/fusermountXXXXXX"; + char *tmp; + +@@ -87,8 +88,8 @@ + exit(1); + } + rmdir(tmp); +- execl("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts, +- fsname, mnt, NULL); ++ execle("/sbin/mount", "/sbin/mount", "-F", type, "-o", opts, ++ fsname, mnt, NULL, &env); + fprintf(stderr, "%s: failed to execute /sbin/mount: %s\n", progname, + strerror(errno)); + exit(1); +@@ -120,9 +121,16 @@ + return -1; + } + if (res == 0) { ++ char *env = NULL; ++ + setuid(geteuid()); +- execl("/sbin/umount", "/sbin/umount", !lazy ? "-f" : NULL, mnt, +- NULL); ++ if (lazy) { ++ execle("/sbin/umount", "/sbin/umount", mnt, ++ NULL, &env); ++ } else { ++ execle("/sbin/umount", "/sbin/umount", "-f", mnt, ++ NULL, &env); ++ } + fprintf(stderr, "%s: failed to execute /sbin/umount: %s\n", progname, + strerror(errno)); + exit(1); +@@ -302,6 +310,7 @@ + return 0; + } + if (res == 0) { ++ char *env = NULL; + char templ[] = "/tmp/fusermountXXXXXX"; + char *tmp; + +@@ -325,8 +334,8 @@ + exit(1); + } + rmdir(tmp); +- execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts, +- fsname, mnt, NULL); ++ execle("/bin/mount", "/bin/mount", "-i", "-f", "-t", type, "-o", opts, ++ fsname, mnt, NULL, &env); + fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", progname, + strerror(errno)); + exit(1); +@@ -353,11 +362,18 @@ + return -1; + } + if (res == 0) { ++ char *env = NULL; ++ + if (setuid(geteuid())) + fprintf(stderr, "%s: failed to setuid : %s\n", progname, + strerror(errno)); +- execl("/bin/umount", "/bin/umount", "-i", mnt, lazy ? "-l" : NULL, +- NULL); ++ if (lazy) { ++ execle("/bin/umount", "/bin/umount", "-i", mnt, "-l", ++ NULL, &env); ++ } else { ++ execle("/bin/umount", "/bin/umount", "-i", mnt, ++ NULL, &env); ++ } + fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname, + strerror(errno)); + exit(1); diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index b0ceda8..4f53382 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -1,9 +1,12 @@ -%global ntfs_version 2014.2.15 +%global ntfs_version 2015.3.14 + +# debuginfo makes no sense for this package, so disable it +%global debug_package %{nil} Name: libguestfs-winsupport -Version: 7.1 -Release: 6%{?dist} -Summary: Add support for Windows guests to libguestfs +Version: 7.2 +Release: 1%{?dist} +Summary: Add support for Windows guests to virt-v2v and virt-p2v URL: http://www.ntfs-3g.org/ License: GPLv2+ @@ -11,28 +14,13 @@ ExclusiveArch: aarch64 x86_64 # This package shouldn't be installed without installing the base # libguestfs package. -Requires: libguestfs >= 1:1.27.19 - -# Built for supermin 5. This will not work with older supermin. -BuildRequires: supermin5 -Requires: supermin5 +Requires: libguestfs >= 1:1.28.1 # Source and patches for ntfs. Try to keep this in step with Fedora. Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.tgz Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch - -# Upstream patches which add fstrim support. -# ae9aeebbbf1523f3e37221b1172cf05775ef8ec9 -Patch1: 0001-Upgraded-fuse-lite-to-support-ioctls.patch -# f4e3f126df0a577903ec043dbcbe38e2863ce3d6 -Patch2: 0002-Implemented-fstrim-8.patch -# c26a519da1ed182e7cfd67e7a353932dda53d811 -Patch3: 0001-Fixed-fstrim-8-applied-to-partitions.patch -# Patch2 requires that libntfs-3g/Makefile is regenerated. This can -# be removed, as well as the call to autoreconf below, when we move to -# a released version of ntfs-3g that includes the new feature. -BuildRequires: autoconf automake +Patch1: CVE-2015-3202.patch BuildRequires: libtool, libattr-devel BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel @@ -40,25 +28,13 @@ BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel %description This optional package adds support for Windows guests (NTFS) to the -base libguestfs Red Hat Enterprise Linux (RHEL) package. This is -useful for examining Windows virtual machines running on RHEL, and for -performing V2V of Windows guests from another hypervisor to RHEL. - -To enable Windows support, simply install this package. - -To disable Windows support, uninstall this package. - -The package contains NTFS FUSE filesystem support from -ntfs-3g %{ntfs_3g_version}. +virt-v2v and virt-p2v programs. %prep %setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} %patch0 -p1 -b .unsupported -%patch1 -p1 -b .ioctl -%patch2 -p1 -b .fstrim -%patch3 -p1 -b .parts -autoreconf -i +%patch1 -p1 -b .cve %build @@ -68,24 +44,27 @@ CFLAGS="$RPM_OPT_FLAGS -D_FILE_OFFSET_BITS=64" --disable-ldconfig \ --exec-prefix=/ \ --enable-crypto \ - --enable-extras + --enable-extras \ + --enable-quarantined make %{?_smp_mflags} LIBTOOL=%{_bindir}/libtool %install -make LIBTOOL=%{_bindir}/libtool DESTDIR=%{buildroot} install -rm -rf %{buildroot}%{_libdir}/*.la -rm -rf %{buildroot}%{_libdir}/*.a +# Build it into a destdir which is not the final buildroot. +mkdir destdir +make LIBTOOL=%{_bindir}/libtool DESTDIR=$(pwd)/destdir install +rm -rf destdir/%{_libdir}/*.la +rm -rf destdir/%{_libdir}/*.a -rm -rf %{buildroot}/%{_sbindir}/mount.ntfs-3g -cp -a %{buildroot}/%{_bindir}/ntfs-3g %{buildroot}/%{_sbindir}/mount.ntfs-3g +rm -rf destdir/%{_sbindir}/mount.ntfs-3g +cp -a destdir/%{_bindir}/ntfs-3g destdir/%{_sbindir}/mount.ntfs-3g # Actually make some symlinks for simplicity... # ... since we're obsoleting ntfsprogs-fuse -pushd %{buildroot}/%{_bindir} +pushd destdir/%{_bindir} ln -s ntfs-3g ntfsmount popd -pushd %{buildroot}/%{_sbindir} +pushd destdir/%{_sbindir} ln -s mount.ntfs-3g mount.ntfs-fuse # And since there is no other package in Fedora that provides an ntfs # mount... @@ -93,73 +72,34 @@ ln -s mount.ntfs-3g mount.ntfs # Need this for fsck to find it ln -s ../bin/ntfsck fsck.ntfs popd -mv %{buildroot}/sbin/* %{buildroot}/%{_sbindir} -rmdir %{buildroot}/sbin +mv destdir/sbin/* destdir/%{_sbindir} +rmdir destdir/sbin # We get this on our own, thanks. -rm %{buildroot}%{_defaultdocdir}/ntfs-3g/README +rm -r destdir/%{_defaultdocdir} -# Add this package to the libguestfs appliance. +# Remove development files. +rm -r destdir/%{_includedir} +rm -r destdir/%{_libdir}/pkgconfig + +# Take the destdir and put it into a tarball for the libguestfs appliance. mkdir -p %{buildroot}%{_libdir}/guestfs/supermin.d -echo libguestfs-winsupport > %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsupport - - -%post -p /sbin/ldconfig -%postun -p /sbin/ldconfig +pushd destdir +tar zcf %{buildroot}%{_libdir}/guestfs/supermin.d/zz-winsupport.tar.gz . +popd %files %doc AUTHORS ChangeLog COPYING CREDITS NEWS README -# From ntfs-3g package: -%{_sbindir}/mount.ntfs -%{_sbindir}/mount.ntfs-3g -%{_sbindir}/mount.ntfs-fuse -%{_sbindir}/mount.lowntfs-3g -%{_bindir}/ntfs-3g -%{_bindir}/ntfsmount -%{_bindir}/ntfs-3g.probe -%{_bindir}/ntfs-3g.secaudit -%{_bindir}/ntfs-3g.usermap -%{_bindir}/lowntfs-3g -%{_libdir}/libntfs-3g.so.* - -# From -devel subpackage: -%{_includedir}/ntfs-3g/ -%{_libdir}/libntfs-3g.so -%{_libdir}/pkgconfig/libntfs-3g.pc - -# From ntfsprogs package: -%{_bindir}/ntfscat -%{_bindir}/ntfscluster -%{_bindir}/ntfscmp -%{_bindir}/ntfsfix -%{_bindir}/ntfsinfo -%{_bindir}/ntfsls -%{_bindir}/ntfsck -%{_bindir}/ntfsdecrypt -%{_bindir}/ntfsdump_logfile -%{_bindir}/ntfsmftalloc -%{_bindir}/ntfsmove -%{_bindir}/ntfstruncate -%{_bindir}/ntfswipe -%{_sbindir}/fsck.ntfs -%{_sbindir}/mkfs.ntfs -%{_sbindir}/mkntfs -%{_sbindir}/ntfsclone -%{_sbindir}/ntfscp -%{_sbindir}/ntfslabel -%{_sbindir}/ntfsresize -%{_sbindir}/ntfsundelete - -# Documentation. -%{_mandir}/man8/*.8* - -# For libguestfs appliance: -%{_libdir}/guestfs/supermin.d/zz-winsupport +%{_libdir}/guestfs/supermin.d/zz-winsupport.tar.gz %changelog +* Tue Jul 07 2015 Richard W.M. Jones - 7.2-1 +- Rebase and rebuild for RHEL 7.2 + resolves: rhbz#1240278 + * Tue Jun 30 2015 Richard W.M. Jones - 7.1-6 - Bump version and rebuild. related: rhbz#1221583 diff --git a/sources b/sources index cc19fcf..47a5bc0 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -f11d563816249d730a00498983485f3a ntfs-3g_ntfsprogs-2014.2.15.tgz +8cd57768310e3b2be39b3191d808e241 ntfs-3g_ntfsprogs-2015.3.14.tgz From 8b9aad09c8679c3ffd3f7475a0fe861b0258cb5f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 22 Feb 2017 11:20:42 +0000 Subject: [PATCH 10/10] Fix for handling guest filenames with invalid or incomplete multibyte or wide characters resolves: rhbz#1301593 --- ...encoding-broken-UTF-16-into-broken-U.patch | 172 ++++++++++++++++++ ...he-two-defines-NOREVBOM-and-ALLOW_BR.patch | 170 +++++++++++++++++ libguestfs-winsupport.spec | 12 +- 3 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 0001-unistr.c-Enable-encoding-broken-UTF-16-into-broken-U.patch create mode 100644 0002-unistr.c-Unify-the-two-defines-NOREVBOM-and-ALLOW_BR.patch diff --git a/0001-unistr.c-Enable-encoding-broken-UTF-16-into-broken-U.patch b/0001-unistr.c-Enable-encoding-broken-UTF-16-into-broken-U.patch new file mode 100644 index 0000000..7412dc4 --- /dev/null +++ b/0001-unistr.c-Enable-encoding-broken-UTF-16-into-broken-U.patch @@ -0,0 +1,172 @@ +From d9c61dd60ec484909f70b7a916ada3a93af94b60 Mon Sep 17 00:00:00 2001 +From: Erik Larsson +Date: Fri, 8 Apr 2016 05:39:48 +0200 +Subject: [PATCH 1/2] unistr.c: Enable encoding broken UTF-16 into broken + UTF-8, A.K.A. WTF-8. + +Windows filenames may contain invalid UTF-16 sequences (specifically +broken surrogate pairs), which cannot be converted to UTF-8 if we do +strict conversion. + +This patch enables encoding broken UTF-16 into similarly broken UTF-8 by +encoding any surrogate character that don't have a match into a separate +3-byte UTF-8 sequence. + +This is "sort of" valid UTF-8, but not valid Unicode since the code +points used for surrogate pair encoding are not supposed to occur in a +valid Unicode string... but on the other hand the source UTF-16 data is +also broken, so we aren't really making things any worse. + +This format is sometimes referred to as WTF-8 (Wobbly Translation +Format, 8-bit encoding) and is a common solution to represent broken +UTF-16 as UTF-8. + +It is a lossless round-trip conversion, i.e converting from broken +UTF-16 to "WTF-8" and back to UTF-16 yields the same broken UTF-16 +sequence. Because of this property it enables accessing these files +by filename through ntfs-3g and the ntfsprogs (e.g. ls -la works as +expected). + +To disable this behaviour you can pass the preprocessor/compiler flag +'-DALLOW_BROKEN_SURROGATES=0' when building ntfs-3g. +--- + libntfs-3g/unistr.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 65 insertions(+), 2 deletions(-) + +diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c +index 7f278cd..71802aa 100644 +--- a/libntfs-3g/unistr.c ++++ b/libntfs-3g/unistr.c +@@ -61,6 +61,11 @@ + + #define NOREVBOM 0 /* JPA rejecting U+FFFE and U+FFFF, open to debate */ + ++#ifndef ALLOW_BROKEN_SURROGATES ++/* Erik allowing broken UTF-16 surrogate pairs by default, open to debate. */ ++#define ALLOW_BROKEN_SURROGATES 1 ++#endif /* !defined(ALLOW_BROKEN_SURROGATES) */ ++ + /* + * IMPORTANT + * ========= +@@ -462,8 +467,22 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + if ((c >= 0xdc00) && (c < 0xe000)) { + surrog = FALSE; + count += 4; +- } else ++ } else { ++#if ALLOW_BROKEN_SURROGATES ++ /* The first UTF-16 unit of a surrogate pair has ++ * a value between 0xd800 and 0xdc00. It can be ++ * encoded as an individual UTF-8 sequence if we ++ * cannot combine it with the next UTF-16 unit ++ * unit as a surrogate pair. */ ++ surrog = FALSE; ++ count += 3; ++ ++ --i; ++ continue; ++#else + goto fail; ++#endif /* ALLOW_BROKEN_SURROGATES */ ++ } + } else + if (c < 0x80) + count++; +@@ -473,6 +492,10 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + count += 3; + else if (c < 0xdc00) + surrog = TRUE; ++#if ALLOW_BROKEN_SURROGATES ++ else if (c < 0xe000) ++ count += 3; ++#endif /* ALLOW_BROKEN_SURROGATES */ + #if NOREVBOM + else if ((c >= 0xe000) && (c < 0xfffe)) + #else +@@ -487,7 +510,11 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + } + } + if (surrog) ++#if ALLOW_BROKEN_SURROGATES ++ count += 3; /* ending with a single surrogate */ ++#else + goto fail; ++#endif /* ALLOW_BROKEN_SURROGATES */ + + ret = count; + out: +@@ -548,8 +575,24 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + *t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4); + *t++ = 0x80 + (c & 63); + halfpair = 0; +- } else ++ } else { ++#if ALLOW_BROKEN_SURROGATES ++ /* The first UTF-16 unit of a surrogate pair has ++ * a value between 0xd800 and 0xdc00. It can be ++ * encoded as an individual UTF-8 sequence if we ++ * cannot combine it with the next UTF-16 unit ++ * unit as a surrogate pair. */ ++ *t++ = 0xe0 | (halfpair >> 12); ++ *t++ = 0x80 | ((halfpair >> 6) & 0x3f); ++ *t++ = 0x80 | (halfpair & 0x3f); ++ halfpair = 0; ++ ++ --i; ++ continue; ++#else + goto fail; ++#endif /* ALLOW_BROKEN_SURROGATES */ ++ } + } else if (c < 0x80) { + *t++ = c; + } else { +@@ -562,6 +605,13 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + *t++ = 0x80 | (c & 0x3f); + } else if (c < 0xdc00) + halfpair = c; ++#if ALLOW_BROKEN_SURROGATES ++ else if (c < 0xe000) { ++ *t++ = 0xe0 | (c >> 12); ++ *t++ = 0x80 | ((c >> 6) & 0x3f); ++ *t++ = 0x80 | (c & 0x3f); ++ } ++#endif /* ALLOW_BROKEN_SURROGATES */ + else if (c >= 0xe000) { + *t++ = 0xe0 | (c >> 12); + *t++ = 0x80 | ((c >> 6) & 0x3f); +@@ -570,6 +620,13 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + goto fail; + } + } ++#if ALLOW_BROKEN_SURROGATES ++ if (halfpair) { /* ending with a single surrogate */ ++ *t++ = 0xe0 | (halfpair >> 12); ++ *t++ = 0x80 | ((halfpair >> 6) & 0x3f); ++ *t++ = 0x80 | (halfpair & 0x3f); ++ } ++#endif /* ALLOW_BROKEN_SURROGATES */ + *t = '\0'; + + #if defined(__APPLE__) || defined(__DARWIN__) +@@ -693,10 +750,16 @@ static int utf8_to_unicode(u32 *wc, const char *s) + /* Check valid ranges */ + #if NOREVBOM + if (((*wc >= 0x800) && (*wc <= 0xD7FF)) ++#if ALLOW_BROKEN_SURROGATES ++ || ((*wc >= 0xD800) && (*wc <= 0xDFFF)) ++#endif /* ALLOW_BROKEN_SURROGATES */ + || ((*wc >= 0xe000) && (*wc <= 0xFFFD))) + return 3; + #else + if (((*wc >= 0x800) && (*wc <= 0xD7FF)) ++#if ALLOW_BROKEN_SURROGATES ++ || ((*wc >= 0xD800) && (*wc <= 0xDFFF)) ++#endif /* ALLOW_BROKEN_SURROGATES */ + || ((*wc >= 0xe000) && (*wc <= 0xFFFF))) + return 3; + #endif +-- +2.10.2 + diff --git a/0002-unistr.c-Unify-the-two-defines-NOREVBOM-and-ALLOW_BR.patch b/0002-unistr.c-Unify-the-two-defines-NOREVBOM-and-ALLOW_BR.patch new file mode 100644 index 0000000..3467837 --- /dev/null +++ b/0002-unistr.c-Unify-the-two-defines-NOREVBOM-and-ALLOW_BR.patch @@ -0,0 +1,170 @@ +From f0370bfa9c47575d4e47c94e443aa91983683a43 Mon Sep 17 00:00:00 2001 +From: Erik Larsson +Date: Tue, 12 Apr 2016 17:02:40 +0200 +Subject: [PATCH 2/2] unistr.c: Unify the two defines NOREVBOM and + ALLOW_BROKEN_SURROGATES. + +In the mailing list discussion we came to the conclusion that there +doesn't seem to be any reason to keep these declarations separate since +they address the same issue, namely libntfs-3g's tolerance for bad +Unicode data in filenames and other UTF-16 strings in the file system, +so merge the two defines into the new define ALLOW_BROKEN_UNICODE. +--- + libntfs-3g/unistr.c | 58 +++++++++++++++++++++++------------------------------ + 1 file changed, 25 insertions(+), 33 deletions(-) + +diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c +index 71802aa..753acc0 100644 +--- a/libntfs-3g/unistr.c ++++ b/libntfs-3g/unistr.c +@@ -59,12 +59,11 @@ + #include "logging.h" + #include "misc.h" + +-#define NOREVBOM 0 /* JPA rejecting U+FFFE and U+FFFF, open to debate */ +- +-#ifndef ALLOW_BROKEN_SURROGATES +-/* Erik allowing broken UTF-16 surrogate pairs by default, open to debate. */ +-#define ALLOW_BROKEN_SURROGATES 1 +-#endif /* !defined(ALLOW_BROKEN_SURROGATES) */ ++#ifndef ALLOW_BROKEN_UNICODE ++/* Erik allowing broken UTF-16 surrogate pairs and U+FFFE and U+FFFF by default, ++ * open to debate. */ ++#define ALLOW_BROKEN_UNICODE 1 ++#endif /* !defined(ALLOW_BROKEN_UNICODE) */ + + /* + * IMPORTANT +@@ -468,7 +467,7 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + surrog = FALSE; + count += 4; + } else { +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + /* The first UTF-16 unit of a surrogate pair has + * a value between 0xd800 and 0xdc00. It can be + * encoded as an individual UTF-8 sequence if we +@@ -481,7 +480,7 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + continue; + #else + goto fail; +-#endif /* ALLOW_BROKEN_SURROGATES */ ++#endif /* ALLOW_BROKEN_UNICODE */ + } + } else + if (c < 0x80) +@@ -492,15 +491,13 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + count += 3; + else if (c < 0xdc00) + surrog = TRUE; +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + else if (c < 0xe000) + count += 3; +-#endif /* ALLOW_BROKEN_SURROGATES */ +-#if NOREVBOM +- else if ((c >= 0xe000) && (c < 0xfffe)) +-#else + else if (c >= 0xe000) +-#endif ++#else ++ else if ((c >= 0xe000) && (c < 0xfffe)) ++#endif /* ALLOW_BROKEN_UNICODE */ + count += 3; + else + goto fail; +@@ -510,11 +507,11 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l + } + } + if (surrog) +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + count += 3; /* ending with a single surrogate */ + #else + goto fail; +-#endif /* ALLOW_BROKEN_SURROGATES */ ++#endif /* ALLOW_BROKEN_UNICODE */ + + ret = count; + out: +@@ -576,7 +573,7 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + *t++ = 0x80 + (c & 63); + halfpair = 0; + } else { +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + /* The first UTF-16 unit of a surrogate pair has + * a value between 0xd800 and 0xdc00. It can be + * encoded as an individual UTF-8 sequence if we +@@ -591,7 +588,7 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + continue; + #else + goto fail; +-#endif /* ALLOW_BROKEN_SURROGATES */ ++#endif /* ALLOW_BROKEN_UNICODE */ + } + } else if (c < 0x80) { + *t++ = c; +@@ -605,13 +602,13 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + *t++ = 0x80 | (c & 0x3f); + } else if (c < 0xdc00) + halfpair = c; +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + else if (c < 0xe000) { + *t++ = 0xe0 | (c >> 12); + *t++ = 0x80 | ((c >> 6) & 0x3f); + *t++ = 0x80 | (c & 0x3f); + } +-#endif /* ALLOW_BROKEN_SURROGATES */ ++#endif /* ALLOW_BROKEN_UNICODE */ + else if (c >= 0xe000) { + *t++ = 0xe0 | (c >> 12); + *t++ = 0x80 | ((c >> 6) & 0x3f); +@@ -620,13 +617,13 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len, + goto fail; + } + } +-#if ALLOW_BROKEN_SURROGATES ++#if ALLOW_BROKEN_UNICODE + if (halfpair) { /* ending with a single surrogate */ + *t++ = 0xe0 | (halfpair >> 12); + *t++ = 0x80 | ((halfpair >> 6) & 0x3f); + *t++ = 0x80 | (halfpair & 0x3f); + } +-#endif /* ALLOW_BROKEN_SURROGATES */ ++#endif /* ALLOW_BROKEN_UNICODE */ + *t = '\0'; + + #if defined(__APPLE__) || defined(__DARWIN__) +@@ -748,21 +745,16 @@ static int utf8_to_unicode(u32 *wc, const char *s) + | ((u32)(s[1] & 0x3F) << 6) + | ((u32)(s[2] & 0x3F)); + /* Check valid ranges */ +-#if NOREVBOM ++#if ALLOW_BROKEN_UNICODE + if (((*wc >= 0x800) && (*wc <= 0xD7FF)) +-#if ALLOW_BROKEN_SURROGATES + || ((*wc >= 0xD800) && (*wc <= 0xDFFF)) +-#endif /* ALLOW_BROKEN_SURROGATES */ +- || ((*wc >= 0xe000) && (*wc <= 0xFFFD))) +- return 3; +-#else +- if (((*wc >= 0x800) && (*wc <= 0xD7FF)) +-#if ALLOW_BROKEN_SURROGATES +- || ((*wc >= 0xD800) && (*wc <= 0xDFFF)) +-#endif /* ALLOW_BROKEN_SURROGATES */ + || ((*wc >= 0xe000) && (*wc <= 0xFFFF))) + return 3; +-#endif ++#else ++ if (((*wc >= 0x800) && (*wc <= 0xD7FF)) ++ || ((*wc >= 0xe000) && (*wc <= 0xFFFD))) ++ return 3; ++#endif /* ALLOW_BROKEN_UNICODE */ + } + goto fail; + /* four-byte */ +-- +2.10.2 + diff --git a/libguestfs-winsupport.spec b/libguestfs-winsupport.spec index 4f53382..3b54c1c 100644 --- a/libguestfs-winsupport.spec +++ b/libguestfs-winsupport.spec @@ -5,7 +5,7 @@ Name: libguestfs-winsupport Version: 7.2 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Add support for Windows guests to virt-v2v and virt-p2v URL: http://www.ntfs-3g.org/ @@ -21,6 +21,9 @@ Source0: http://tuxera.com/opensource/ntfs-3g_ntfsprogs-%{ntfs_version}.t Patch0: ntfs-3g_ntfsprogs-2011.10.9-RC-ntfsck-unsupported-return-0.patch Patch1: CVE-2015-3202.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1301593#c8 +Patch2: 0001-unistr.c-Enable-encoding-broken-UTF-16-into-broken-U.patch +Patch3: 0002-unistr.c-Unify-the-two-defines-NOREVBOM-and-ALLOW_BR.patch BuildRequires: libtool, libattr-devel BuildRequires: libconfig-devel, libgcrypt-devel, gnutls-devel, libuuid-devel @@ -35,6 +38,8 @@ virt-v2v and virt-p2v programs. %setup -q -n ntfs-3g_ntfsprogs-%{ntfs_version} %patch0 -p1 -b .unsupported %patch1 -p1 -b .cve +%patch2 -p1 +%patch3 -p1 %build @@ -96,6 +101,11 @@ popd %changelog +* Wed Feb 22 2017 Richard W.M. Jones - 7.2-2 +- Fix for handling guest filenames with invalid or incomplete + multibyte or wide characters + resolves: rhbz#1301593 + * Tue Jul 07 2015 Richard W.M. Jones - 7.2-1 - Rebase and rebuild for RHEL 7.2 resolves: rhbz#1240278