On Sun, Feb 21, 2016 at 11:22:23PM +0200, Matteo Cafasso wrote:
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.
The patch seems fine, but it really needs a test otherwise this
feature could silently break.
Have a look at the tests/ntfsclone/ subdirectory for the general idea.
One problem with writing the test (indeed, with the general idea) is
how do you discover which inode numbers can be downloaded? Does NTFS
have some standard inode numbers for things like the MFT?
Rich.
---
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, 12);
+ 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
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
libguestfs lets you edit virtual machines. Supports shell scripting,
bindings from many languages.
http://libguestfs.org