[Libguestfs] [PATCH v6 38/41] daemon: Implement command flag CommandFlagFoldStdoutOnStderr.

Richard W.M. Jones
Thu, 15 Jun 2017 17:06:28 -0000

Used to handle broken commands like parted, sgdisk which print errors
on stdout.
---
 daemon/utils.ml  | 19 ++++++++++++++-----
 daemon/utils.mli | 11 +++++++++--
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/daemon/utils.ml b/daemon/utils.ml
index 48f6b9c5c..808e575fd 100644
--- a/daemon/utils.ml
+++ b/daemon/utils.ml
@@ -25,9 +25,15 @@ let prog_exists prog    try ignore (which prog); true
   with Executable_not_found _ -> false

-let commandr prog args +type command_flag +  CommandFlagFoldStdoutOnStderr
+
+let commandr ?(flags = []) prog args +  let fold_stdout_on_stderr = List.mem
CommandFlagFoldStdoutOnStderr flags in
+
   if verbose () then
-    eprintf "command: %s %s\n%!"
+    eprintf "command:%s %s %s\n%!"
+            (if fold_stdout_on_stderr then " fold-stdout-on-stderr"
else "")
             prog (String.concat " " args);

   let argv = Array.of_list (prog :: args) in
@@ -43,7 +49,10 @@ let commandr prog args      (* Child process. *)
     dup2 stdin_fd stdin;
     close stdin_fd;
-    dup2 stdout_fd stdout;
+    if not fold_stdout_on_stderr then
+      dup2 stdout_fd stdout
+    else
+      dup2 stderr_fd stdout;
     close stdout_fd;
     dup2 stderr_fd stderr;
     close stderr_fd;
@@ -91,8 +100,8 @@ let commandr prog args
   (r, stdout, stderr)

-let command prog args -  let r, stdout, stderr = commandr prog args in
+let command ?flags prog args +  let r, stdout, stderr = commandr ?flags prog
args in
   if r <> 0 then
     failwithf "%s exited with status %d: %s" prog r stderr;
   stdout
diff --git a/daemon/utils.mli b/daemon/utils.mli
index a1f956be3..d3c8bdf4d 100644
--- a/daemon/utils.mli
+++ b/daemon/utils.mli
@@ -60,7 +60,14 @@ val proc_unmangle_path : string -> string
 (** Reverse kernel path escaping done in fs/seq_file.c:mangle_path.
     This is inconsistently used for /proc fields. *)

-val command : string -> string list -> string
+type command_flag +  CommandFlagFoldStdoutOnStderr
+    (** For broken external commands that send error messages to stdout
+        (hello, parted) but that don't have any useful stdout information,
+        use this flag to capture the error messages in the [stderr]
+        buffer.  Nothing will be captured on stdout if you use this flag. *)
+
+val command : ?flags:command_flag list -> string -> string list ->
string
 (** Run an external command without using the shell, and collect
     stdout and stderr separately.  Returns stdout if the command
     runs successfully.
@@ -68,7 +75,7 @@ val command : string -> string list -> string
     On failure of the command, this throws an exception containing
     the stderr from the command. *)

-val commandr : string -> string list -> (int * string * string)
+val commandr : ?flags:command_flag list -> string -> string list ->
(int * string * string)
 (** Run an external command without using the shell, and collect
     stdout and stderr separately.

--
2.13.0