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. --- 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