Adding ntfscat_i command for downloading files based on their inode number.
This allows the dowload of files unaccessible otherwise from a NTFS guest disk
image.
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
---
daemon/ntfs.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++
generator/actions.ml | 15 +++++++++++++
2 files changed, 77 insertions(+)
diff --git a/daemon/ntfs.c b/daemon/ntfs.c
index 568899e..58f62fa 100644
--- a/daemon/ntfs.c
+++ b/daemon/ntfs.c
@@ -266,3 +266,65 @@ do_ntfsfix (const char *device, int clearbadsectors)
return 0;
}
+
+int
+do_ntfscat_i (const mountable_t *mountable, int64_t inode)
+{
+ int r;
+ FILE *fp;
+ CLEANUP_FREE char *cmd = NULL;
+ char buffer[GUESTFS_MAX_CHUNK_SIZE];
+
+ /* Inode must be greater than 0 */
+ if (inode < 0) {
+ reply_with_error("Inode must be greater than 0");
+ return -1;
+ }
+
+ /* Construct the command. */
+ if (asprintf_nowarn (&cmd, "ntfscat -i %ld %s",
+ inode, mountable->device) == -1) {
+ reply_with_perror ("asprintf");
+ return -1;
+ }
+
+ if (verbose)
+ fprintf (stderr, "%s\n", cmd);
+
+ fp = popen (cmd, "r");
+ if (fp == NULL) {
+ reply_with_perror ("%s", cmd);
+ return -1;
+ }
+
+ /* Now we must send the reply message, before the file contents. After
+ * this there is no opportunity in the protocol to send any error
+ * message back. Instead we can only cancel the transfer.
+ */
+ reply (NULL, NULL);
+
+ while ((r = fread (buffer, 1, sizeof buffer, fp)) > 0) {
+ if (send_file_write (buffer, r) < 0) {
+ pclose (fp);
+ return -1;
+ }
+ }
+
+ if (ferror (fp)) {
+ fprintf (stderr, "fread: %ld: %m\n", inode);
+ send_file_end (1); /* Cancel. */
+ pclose (fp);
+ return -1;
+ }
+
+ if (pclose (fp) != 0) {
+ fprintf (stderr, "pclose: %ld: %m\n", inode);
+ send_file_end (1); /* Cancel. */
+ return -1;
+ }
+
+ if (send_file_end (0)) /* Normal end of file. */
+ return -1;
+
+ return 0;
+}
diff --git a/generator/actions.ml b/generator/actions.ml
index eb45392..18418aa 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12891,6 +12891,21 @@ This is equivalent to C<sgdisk -e>.
See also L<sgdisk(8)>." };
+ { defaults with
+ name = "ntfscat_i"; added = (1, 33, 2);
+ style = RErr, [Mountable "device"; Int64 "inode";
FileOut "filename"], [];
+ proc_nr = Some 463;
+ progress = true; cancellable = true;
+ shortdesc = "download a file to the local machine given its
inode";
+ longdesc = "\
+Download a file given its inode from a NTFS filesystem and save it as
F<filename>
+on the local machine.
+
+This allows to download some otherwise unaccessible files such as the ones
+within the $Extend folder.
+
+F<filename> can also be a named pipe." };
+
]
(* Non-API meta-commands available only in guestfish.
--
2.7.0
Test is based on file signature, it checks whether the extracted file is the
$MFT.
Signed-off-by: Matteo Cafasso <noxdafox@gmail.com>
---
Makefile.am | 1 +
configure.ac | 1 +
generator/actions.ml | 6 ++++-
tests/ntfscat/Makefile.am | 26 +++++++++++++++++++++
tests/ntfscat/test-ntfscat.sh | 53 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 86 insertions(+), 1 deletion(-)
create mode 100644 tests/ntfscat/Makefile.am
create mode 100755 tests/ntfscat/test-ntfscat.sh
diff --git a/Makefile.am b/Makefile.am
index ba99feb..1ab85e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,6 +66,7 @@ SUBDIRS += tests/luks
SUBDIRS += tests/md
SUBDIRS += tests/selinux
SUBDIRS += tests/ntfsclone
+SUBDIRS += tests/ntfscat
SUBDIRS += tests/btrfs
SUBDIRS += tests/xfs
SUBDIRS += tests/charsets
diff --git a/configure.ac b/configure.ac
index 29b5092..7598b5f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -272,6 +272,7 @@ AC_CONFIG_FILES([Makefile
tests/nbd/Makefile
tests/network/Makefile
tests/ntfsclone/Makefile
+ tests/ntfscat/Makefile
tests/parallel/Makefile
tests/protocol/Makefile
tests/qemu/Makefile
diff --git a/generator/actions.ml b/generator/actions.ml
index 18418aa..0c71389 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12892,10 +12892,11 @@ This is equivalent to C<sgdisk -e>.
See also L<sgdisk(8)>." };
{ defaults with
- name = "ntfscat_i"; added = (1, 33, 2);
+ name = "ntfscat_i"; added = (1, 33, 12);
style = RErr, [Mountable "device"; Int64 "inode";
FileOut "filename"], [];
proc_nr = Some 463;
progress = true; cancellable = true;
+ test_excuse = "tested in tests/ntfscat";
shortdesc = "download a file to the local machine given its
inode";
longdesc = "\
Download a file given its inode from a NTFS filesystem and save it as
F<filename>
@@ -12904,6 +12905,9 @@ on the local machine.
This allows to download some otherwise unaccessible files such as the ones
within the $Extend folder.
+The filesystem from which to extract the file must be unmounted,
+otherwise the call will fail.
+
F<filename> can also be a named pipe." };
]
diff --git a/tests/ntfscat/Makefile.am b/tests/ntfscat/Makefile.am
new file mode 100644
index 0000000..dc64c3d
--- /dev/null
+++ b/tests/ntfscat/Makefile.am
@@ -0,0 +1,26 @@
+# libguestfs
+# Copyright (C) 2016 Red Hat Inc.
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+include $(top_srcdir)/subdir-rules.mk
+
+TESTS = \
+ test-ntfscat.sh
+
+TESTS_ENVIRONMENT = $(top_builddir)/run --test
+
+EXTRA_DIST = \
+ $(TESTS)
diff --git a/tests/ntfscat/test-ntfscat.sh b/tests/ntfscat/test-ntfscat.sh
new file mode 100755
index 0000000..5cfdd95
--- /dev/null
+++ b/tests/ntfscat/test-ntfscat.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -
+# libguestfs
+# Copyright (C) 2016 Red Hat Inc.
+#
+# 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; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Test the ntfscat-i command.
+
+set -e
+
+if [ -n "$SKIP_TEST_NTFSCAT_SH" ]; then
+ echo "$0: test skipped because environment variable is set."
+ exit 77
+fi
+
+rm -f test-mft.bin
+
+# Skip if ntfs-3g is not supported by the appliance.
+if ! guestfish add /dev/null : run : available "ntfs3g"; then
+ echo "$0: skipped because ntfs-3g is not supported by the
appliance"
+ exit 77
+fi
+
+if [ ! -s ../../test-data/phony-guests/windows.img ]; then
+ echo "$0: skipped because windows.img is zero-sized"
+ exit 77
+fi
+
+# download Master File Table ($MFT).
+guestfish --ro -a ../../test-data/phony-guests/windows.img <<EOF
+run
+ntfscat-i /dev/sda2 0 test-mft.bin
+EOF
+
+# test extracted file is the Master File Table
+if [ `head -c 5 test-mft.bin` != "FILE0" ]; then
+ echo "$0: wrong file extracted."
+ exit 1
+fi
+
+rm -f test-mft.bin
--
2.7.0
Richard W.M. Jones
2016-Mar-01 09:07 UTC
Re: [Libguestfs] [PATCH 2/2] added ntfscat_i tests
Thanks - I have pushed both. Note that I made some minor cleanups to both patches. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v