X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=daemon%2Ftar.c;h=9e45dee94af7f953f0da7b2a8def086a27c711c2;hb=bcd2dba76efa4da4edb1b04f6348b0a0dfb109c2;hp=1e9698c23bcdc9cfa983f65cabd0d35770f2f19a;hpb=b76fd51e142494058ca0082b547aa5e747ad4b79;p=libguestfs.git diff --git a/daemon/tar.c b/daemon/tar.c index 1e9698c..9e45dee 100644 --- a/daemon/tar.c +++ b/daemon/tar.c @@ -1,5 +1,5 @@ /* libguestfs - the guestfsd daemon - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009-2011 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 @@ -13,7 +13,7 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -23,9 +23,42 @@ #include #include -#include "../src/guestfs_protocol.h" +#include "read-file.h" + +#include "guestfs_protocol.h" #include "daemon.h" #include "actions.h" +#include "optgroups.h" + +int +optgroup_xz_available (void) +{ + return prog_exists ("xz"); +} + +/* Read the error file. Returns a string that the caller must free. */ +static char * +read_error_file (char *error_file) +{ + size_t len; + char *str; + + str = read_file (error_file, &len); + if (str == NULL) { + str = strdup ("(no error)"); + if (str == NULL) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + len = strlen (str); + } + + /* Remove trailing \n character if any. */ + if (len > 0 && str[len-1] == '\n') + str[--len] = '\0'; + + return str; /* caller frees */ +} static int write_cb (void *fd_ptr, const void *buf, size_t len) @@ -41,14 +74,25 @@ do_tXz_in (const char *dir, const char *filter) int err, r; FILE *fp; char *cmd; + char error_file[] = "/tmp/tarXXXXXX"; + int fd; + + fd = mkstemp (error_file); + if (fd == -1) { + reply_with_perror ("mkstemp"); + return -1; + } + + close (fd); /* "tar -C /sysroot%s -xf -" but we have to quote the dir. */ - if (asprintf_nowarn (&cmd, "tar -C %R -%sxf -", - dir, filter) == -1) { + if (asprintf_nowarn (&cmd, "tar -C %R -%sxf - 2> %s", + dir, filter, error_file) == -1) { err = errno; r = cancel_receive (); errno = err; - if (r != -2) reply_with_perror ("asprintf"); + reply_with_perror ("asprintf"); + unlink (error_file); return -1; } @@ -60,7 +104,8 @@ do_tXz_in (const char *dir, const char *filter) err = errno; r = cancel_receive (); errno = err; - if (r != -2) reply_with_perror ("%s", cmd); + reply_with_perror ("%s", cmd); + unlink (error_file); free (cmd); return -1; } @@ -69,29 +114,39 @@ do_tXz_in (const char *dir, const char *filter) /* The semantics of fwrite are too undefined, so write to the * file descriptor directly instead. */ - int fd = fileno (fp); + fd = fileno (fp); r = receive_file (write_cb, &fd); if (r == -1) { /* write error */ - if (cancel_receive () != -2) - reply_with_error ("write error on directory: %s", dir); + cancel_receive (); + char *errstr = read_error_file (error_file); + reply_with_error ("write error on directory: %s: %s", dir, errstr); + free (errstr); + unlink (error_file); pclose (fp); return -1; } if (r == -2) { /* cancellation from library */ + /* This error is ignored by the library since it initiated the + * cancel. Nevertheless we must send an error reply here. + */ + reply_with_error ("file upload cancelled"); pclose (fp); - /* Do NOT send any error. */ + unlink (error_file); return -1; } if (pclose (fp) != 0) { - if (r == -1) /* if r == 0, file transfer ended already */ - r = cancel_receive (); - if (r != -2) - reply_with_error ("tar subcommand failed on directory: %s", dir); + char *errstr = read_error_file (error_file); + reply_with_error ("tar subcommand failed on directory: %s: %s", + dir, errstr); + free (errstr); + unlink (error_file); return -1; } + unlink (error_file); + return 0; }