diff --git a/fuse/guestmount.c b/fuse/guestmount.c index 4f9847102..273d3d7ce 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 05a3c1d13..7eddc1c12 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>