[Libguestfs] [PATCH] api: Don't truncate /dev/stdout or /dev/stderr when used as FileOut.

Richard W.M. Jones rjones at redhat.com
Tue May 26 07:52:03 UTC 2015


In APIs such as guestfs_download, when the FileOut parameter exactly
matches "/dev/stdout" or "/dev/stderr", don't reopen the possibly
redirected output file with O_TRUNC (truncate).  Instead dup the file
descriptor.

This magic behaviour doesn't happen for /dev/fd/* (or any other output
file) allowing callers the choice of using /dev/stderr or /dev/fd/2
depending on whether or not they want truncation.

This works around an annoying virt-builder bug.  If you do:

  $ virt-builder fedora-21 --install no_such_package -v -x >& /tmp/log

then when the `--install' command fails, virt-builder will download
the log file using `guestfs_download (g, log, "/dev/stderr")'.  Since
this truncates the redirected /dev/stderr, the final log file is
truncated and corrupted.

With this patch the log file is no longer corrupted.
---
 customize/customize_run.ml |  7 +------
 src/proto.c                | 13 +++++++++++--
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 5a7e209..d9547a0 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -45,12 +45,7 @@ let run (g : Guestfs.guestfs) root (ops : ops) =
 
   (* Function to cat the log file, for debugging and error messages. *)
   let debug_logfile () =
-    try
-      (* XXX If stderr is redirected this actually truncates the
-       * redirection file, which is pretty annoying to say the
-       * least.
-       *)
-      g#download logfile "/dev/stderr"
+    try g#download logfile "/dev/stderr"
     with exn ->
       warning (f_"log file %s: %s (ignored)") logfile (Printexc.to_string exn) in
 
diff --git a/src/proto.c b/src/proto.c
index a019625..a46a382 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -756,9 +756,18 @@ guestfs_int_recv_file (guestfs_h *g, const char *filename)
 
   g->user_cancel = 0;
 
-  fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
+  /* If downloading to /dev/stdout or /dev/stderr, dup the file
+   * descriptor instead of reopening the file, so that redirected
+   * stdout/stderr work properly.
+   */
+  if (STREQ (filename, "/dev/stdout"))
+    fd = dup (1);
+  else if (STREQ (filename, "/dev/stderr"))
+    fd = dup (2);
+  else
+    fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
   if (fd == -1) {
-    perrorf (g, "open: %s", filename);
+    perrorf (g, "%s", filename);
     goto cancel;
   }
 
-- 
2.3.1




More information about the Libguestfs mailing list