Allow to specify a file descriptor for the machine readable output.
Sadly, the OCaml C glue for the channels is not public API, so enable
the internals for this...
---
common/mltools/tools_utils-c.c | 17 +++++++++++++++++
common/mltools/tools_utils.ml | 10 +++++++++-
lib/guestfs.pod | 5 +++++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c
index c88c95082..553aa6631 100644
--- a/common/mltools/tools_utils-c.c
+++ b/common/mltools/tools_utils-c.c
@@ -29,6 +29,9 @@
#include <caml/memory.h>
#include <caml/mlvalues.h>
#include <caml/unixsupport.h>
+/* Evil ... */
+#define CAML_INTERNALS
+#include <caml/io.h>
#include <guestfs.h>
@@ -37,6 +40,7 @@
extern value guestfs_int_mllib_inspect_decrypt (value gv, value gpv, value keysv);
extern value guestfs_int_mllib_set_echo_keys (value unitv);
extern value guestfs_int_mllib_set_keys_from_stdin (value unitv);
+extern value guestfs_int_mllib_open_out_channel_from_fd (value fdv);
/* Interface with the guestfish inspection and decryption code. */
int echo_keys = 0;
@@ -103,3 +107,16 @@ guestfs_int_mllib_set_keys_from_stdin (value unitv)
keys_from_stdin = 1;
return Val_unit;
}
+
+value
+guestfs_int_mllib_open_out_channel_from_fd (value fdv)
+{
+ CAMLparam1 (fdv);
+ struct channel *chan;
+
+ chan = caml_open_descriptor_out (Int_val (fdv));
+ if (!chan)
+ caml_raise_out_of_memory ();
+
+ CAMLreturn (caml_alloc_channel (chan));
+}
diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml
index ade4cb37f..3c54cd4a0 100644
--- a/common/mltools/tools_utils.ml
+++ b/common/mltools/tools_utils.ml
@@ -32,6 +32,7 @@ and key_store_key =
external c_inspect_decrypt : Guestfs.t -> int64 -> (string * key_store_key) list
-> unit = "guestfs_int_mllib_inspect_decrypt"
external c_set_echo_keys : unit -> unit = "guestfs_int_mllib_set_echo_keys"
"noalloc"
external c_set_keys_from_stdin : unit -> unit =
"guestfs_int_mllib_set_keys_from_stdin" "noalloc"
+external c_out_channel_from_fd : int -> out_channel =
"guestfs_int_mllib_open_out_channel_from_fd"
type machine_readable_fn = {
pr : 'a. ('a, unit, string, unit) format4 -> 'a;
@@ -41,6 +42,7 @@ type machine_readable_output_type =
| NoOutput
| Channel of out_channel
| File of string
+ | Fd of int
let machine_readable_output = ref NoOutput
let machine_readable_channel = ref None
let machine_readable () =
@@ -50,7 +52,8 @@ let machine_readable () =
match !machine_readable_output with
| NoOutput -> None
| Channel chan -> Some chan
- | File f -> Some (open_out f) in
+ | File f -> Some (open_out f)
+ | Fd fd -> Some (c_out_channel_from_fd fd) in
machine_readable_channel := chan
);
!machine_readable_channel
@@ -296,6 +299,11 @@ let create_standard_options argspec ?anon_fun ?(key_opts = false)
?(machine_read
| n ->
error (f_"invalid output stream for --machine-readable: %s") fmt
in
machine_readable_output := Channel chan
+ | "fd" ->
+ (try
+ machine_readable_output := Fd (int_of_string outname)
+ with Failure _ ->
+ error (f_"invalid output fd for --machine-readable: %s") fmt)
| n ->
error (f_"invalid output for --machine-readable: %s") fmt
)
diff --git a/lib/guestfs.pod b/lib/guestfs.pod
index 53cece2da..f11028466 100644
--- a/lib/guestfs.pod
+++ b/lib/guestfs.pod
@@ -3287,6 +3287,11 @@ The possible values are:
=over 4
+=item B<fd:>I<fd>
+
+The output goes to the specified I<fd>, which is a file descriptor
+already opened for writing.
+
=item B<file:>F<filename>
The output goes to the specified F<filename>.
--
2.20.1