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.2