[Libguestfs] [PATCH 1/2] copy-in: print tar stderr when it fails

Pino Toscano ptoscano at redhat.com
Tue Sep 29 09:38:51 UTC 2015


Get also the fd for the tar subprocess, and drain and print its content
if the tar invocation fails.
---
 src/copy-in-out.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 61 insertions(+), 4 deletions(-)

diff --git a/src/copy-in-out.c b/src/copy-in-out.c
index dc9e7b7..0dd8cd3 100644
--- a/src/copy-in-out.c
+++ b/src/copy-in-out.c
@@ -34,17 +34,19 @@
 #include "guestfs-internal-actions.h"
 
 static int split_path (guestfs_h *g, char *buf, size_t buf_size, const char *path, const char **dirname, const char **basename);
+static int drain_fd (guestfs_h *g, int fd, char **ret);
 
 int
 guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir)
 {
   CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
-  int fd;
+  int fd, err_fd;
   int r;
   char fdbuf[64];
   size_t buf_len = strlen (localpath) + 1;
   char buf[buf_len];
   const char *dirname, *basename;
+  CLEANUP_FREE char *tar_buf = NULL;
 
   int remote_is_dir = guestfs_is_dir (g, remotedir);
   if (remote_is_dir == -1)
@@ -67,7 +69,7 @@ guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir
   guestfs_int_cmd_add_arg (cmd, "-");
   guestfs_int_cmd_add_arg (cmd, basename);
 
-  r = guestfs_int_cmd_run_async (cmd, NULL, NULL, &fd, NULL);
+  r = guestfs_int_cmd_run_async (cmd, NULL, NULL, &fd, &err_fd);
   if (r == -1)
     return -1;
 
@@ -81,10 +83,20 @@ guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir
   }
 
   r = guestfs_int_cmd_wait (cmd);
-  if (r == -1)
+  if (r == -1) {
+    if (drain_fd (g, err_fd, &tar_buf) == 0) {
+      close (err_fd);
+      error (g, _("tar command failed: %s"), tar_buf);
+    }
     return -1;
-  if (!(WIFEXITED (r) && WEXITSTATUS (r) == 0))
+  }
+  if (!(WIFEXITED (r) && WEXITSTATUS (r) == 0)) {
+    if (drain_fd (g, err_fd, &tar_buf) == 0) {
+      close (err_fd);
+      error (g, _("tar command failed with %d: %s"), WEXITSTATUS (r), tar_buf);
+    }
     return -1;
+  }
 
   return 0;
 }
@@ -248,3 +260,48 @@ split_path (guestfs_h *g, char *buf, size_t buf_size,
 
   return 0;
 }
+
+static int
+drain_fd (guestfs_h *g, int fd, char **ret)
+{
+  char *data = NULL;
+  size_t size = 0;
+  size_t n = 0;
+  size_t left = 0;
+  ssize_t r;
+
+  while (1) {
+    size_t to_read;
+    if (left > 0) {
+      to_read = left;
+    } else {
+      to_read = 1024;
+      size += to_read;
+      data = safe_realloc (g, data, size);
+    }
+    r = read (fd, &data[n], to_read);
+    if (r == -1) {
+      perrorf (g, _("drain_fd: read"));
+      free (data);
+      close (fd);
+      return -1;
+    }
+    if (r == 0)
+      break;
+    n += r;
+    left = 1024 - r;
+  }
+
+  if (close (fd) == -1) {
+    perrorf (g, _("drain_fd: close"));
+    free (data);
+    return -1;
+  }
+
+  data[n] = 0;
+  if (n > 0 && data[n-1] == '\n')
+    data[n-1] = 0;
+
+  *ret = data;
+  return 0;
+}
-- 
2.1.0




More information about the Libguestfs mailing list