This implements the guestmount --fd option to allow you to run
guestmount captive under another process (typically using
`guestmount --fd=<FD> --no-fork').
See:
https://bugzilla.redhat.com/show_bug.cgi?id=1100498
---
fuse/guestmount.c | 37 ++++++++++++++++++++++++++++++++++++-
fuse/guestmount.pod | 7 +++++++
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/fuse/guestmount.c b/fuse/guestmount.c
index 4f98471..88c6024 100644
--- a/fuse/guestmount.c
+++ b/fuse/guestmount.c
@@ -41,6 +41,7 @@
#include "options.h"
+static int write_pipe_fd (int fd);
static int write_pid_file (const char *pid_file, pid_t pid);
#ifndef HAVE_FUSE_OPT_ADD_OPT_ESCAPED
@@ -111,6 +112,7 @@ usage (int status)
" --dir-cache-timeout Set readdir cache timeout (default 5
sec)\n"
" -d|--domain guest Add disks from libvirt guest\n"
" --echo-keys Don't turn off echo for
passphrases\n"
+ " --fd=FD Write to pipe FD when mountpoint is
ready\n"
" --format[=raw|..] Force disk format for -a option\n"
" --fuse-help Display extra FUSE options\n"
" -i|--inspector Automatically mount filesystems\n"
@@ -155,6 +157,7 @@ main (int argc, char *argv[])
{ "dir-cache-timeout", 1, 0, 0 },
{ "domain", 1, 0, 'd' },
{ "echo-keys", 0, 0, 0 },
+ { "fd", 1, 0, 0 },
{ "format", 2, 0, 0 },
{ "fuse-help", 0, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
@@ -190,6 +193,7 @@ main (int argc, char *argv[])
int do_fork = 1;
char *fuse_options = NULL;
char *pid_file = NULL;
+ int pipe_fd = -1;
struct guestfs_mount_local_argv optargs;
@@ -237,6 +241,12 @@ main (int argc, char *argv[])
pid_file = optarg;
} else if (STREQ (long_options[option_index].name, "no-fork")) {
do_fork = 0;
+ } else if (STREQ (long_options[option_index].name, "fd")) {
+ if (sscanf (optarg, "%d", &pipe_fd) != 1 || pipe_fd < 0) {
+ fprintf (stderr, _("%s: unable to parse --fd option value: %s\n"),
+ program_name, optarg);
+ exit (EXIT_FAILURE);
+ }
} else {
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
program_name, long_options[option_index].name, option_index);
@@ -413,6 +423,8 @@ main (int argc, char *argv[])
if (pid != 0) { /* parent */
if (write_pid_file (pid_file, pid) == -1)
_exit (EXIT_FAILURE);
+ if (write_pipe_fd (pipe_fd) == -1)
+ _exit (EXIT_FAILURE);
_exit (EXIT_SUCCESS);
}
@@ -435,9 +447,11 @@ main (int argc, char *argv[])
}
}
else {
- /* not forking, write PID file anyway */
+ /* not forking, write PID file and pipe FD anyway */
if (write_pid_file (pid_file, getpid ()) == -1)
exit (EXIT_FAILURE);
+ if (write_pipe_fd (pipe_fd) == -1)
+ _exit (EXIT_FAILURE);
}
/* At the last minute, remove the libguestfs error handler. In code
@@ -487,3 +501,24 @@ write_pid_file (const char *pid_file, pid_t pid)
return 0;
}
+
+static int
+write_pipe_fd (int fd)
+{
+ char c = 0;
+
+ if (fd < 0)
+ return 0;
+
+ if (write (fd, &c, 1) != 1) {
+ perror ("write (--fd option)");
+ return -1;
+ }
+
+ if (close (fd) == -1) {
+ perror ("close (--fd option)");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/fuse/guestmount.pod b/fuse/guestmount.pod
index 05a3c1d..7eddc1c 100644
--- a/fuse/guestmount.pod
+++ b/fuse/guestmount.pod
@@ -212,6 +212,13 @@ echoing off so you cannot see what you are typing. If you are not
worried about Tempest attacks and there is no one else in the room
you can specify this flag to see what you are typing.
+=item B<--fd=FD>
+
+Specify a pipe or eventfd file descriptor. When the mountpoint is
+ready to be used, guestmount writes a single byte to this file
+descriptor. This can be used in conjunction with I<--no-fork> in
+order to run guestmount captive under another process.
+
=item B<--format=raw|qcow2|..>
=item B<--format>
--
1.9.0