diff --git a/daemon/Makefile.am b/daemon/Makefile.am index caba83ebe..4e2051bf0 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -179,6 +179,7 @@ guestfsd_SOURCES = \ syslinux.c \ tar.c \ truncate.c \ + tsk.c \ umask.c \ upload.c \ utimens.c \ diff --git a/daemon/tsk.c b/daemon/tsk.c new file mode 100644 index 000000000..647d1e7b1 --- /dev/null +++ b/daemon/tsk.c @@ -0,0 +1,114 @@ +/* libguestfs - the guestfsd daemon + * 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 + +#include +#include +#include +#include +#include + +#include "guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" +#include "optgroups.h" + +static int file_out (const char *cmd); + +GUESTFSD_EXT_CMD(str_tsk_probe, icat); + +int +optgroup_icat_available (void) +{ + return prog_exists (str_tsk_probe); +} + +int +do_icat (const mountable_t *mountable, int64_t inode) +{ + CLEANUP_FREE char *cmd = NULL; + + /* Inode must be greater than 0 */ + if (inode < 0) { + reply_with_error ("inode must be >= 0"); + return -1; + } + + /* Construct the command. */ + if (asprintf (&cmd, "icat -r %s %" PRIi64, mountable->device, inode) == -1) { + reply_with_perror ("asprintf"); + return -1; + } + + return file_out (cmd); +} + +static int +file_out (const char *cmd) +{ + int r; + FILE *fp; + CLEANUP_FREE char *buffer = NULL; + + if (verbose) + fprintf (stderr, "%s\n", cmd); + + buffer = malloc (GUESTFS_MAX_CHUNK_SIZE); + if (buffer == NULL) { + reply_with_perror ("malloc"); + return -1; + } + + 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: %m"); + send_file_end (1); /* Cancel. */ + pclose (fp); + return -1; + } + + if (pclose (fp) != 0) { + fprintf (stderr, "pclose: %m"); + 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 287d7f58e..36d08ade7 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -12919,6 +12919,19 @@ within the C<$Extend> folder. The filesystem from which to extract the file must be unmounted, otherwise the call will fail." }; + { defaults with + name = "icat"; added = (1, 33, 14); + style = RErr, [Mountable "device"; Int64 "inode"; FileOut "filename"], []; + proc_nr = Some 464; + optional = Some "icat"; + progress = true; cancellable = true; + shortdesc = "download a file to the local machine given its inode"; + longdesc = "\ +Download a file given its inode from the disk partition (eg. F) +and save it as F on the local machine. + +This allows to download deleted or inaccessible files." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/po/POTFILES b/po/POTFILES index 0fb99b0ab..4fbc55193 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -108,6 +108,7 @@ daemon/sync.c daemon/syslinux.c daemon/tar.c daemon/truncate.c +daemon/tsk.c daemon/umask.c daemon/upload.c daemon/utimens.c diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index 26551cf13..3bb8a497c 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -463 +464