[Libguestfs] [PATCH v2 4/9] daemon: Add -l / --listen flag.

Richard W.M. Jones
Thu, 25 Jun 2015 14:56:56 -0000

This option, used for testing, causes the daemon to create the Unix
domain socket (from guestfs_channel), listen on it, and accept a
single connection.
---
 daemon/guestfsd.c   | 65 ++++++++++++++++++++++++++++++++++++++---------------
 daemon/guestfsd.pod |  9 ++++++++
 2 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 8285d27..1bcdfa3 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -139,15 +139,17 @@ usage (void)
 int
 main (int argc, char *argv[])
 {
-  static const char *options = "rtv?";
+  static const char *options = "lrtv?";
   static const struct option long_options[] = {
     { "help", 0, 0, '?' },
+    { "listen", 0, 0, 'l' },
     { "test", 0, 0, 't' },
     { "verbose", 0, 0, 'v' },
     { 0, 0, 0, 0 }
   };
   int c;
   char *cmdline;
+  int listen_mode = 0;

   ignore_value (chdir ("/"));

@@ -186,6 +188,10 @@ main (int argc, char *argv[])
     if (c == -1) break;

     switch (c) {
+    case 'l':
+      listen_mode = 1;
+      break;
+
       /* The -r flag is used when running standalone.  It changes
        * several aspects of the daemon.
        */
@@ -292,23 +298,46 @@ main (int argc, char *argv[])
   if (verbose)
     printf ("trying to open virtio-serial channel '%s'\n",
channel);

-  int sock = open (channel, O_RDWR|O_CLOEXEC);
-  if (sock == -1) {
-    fprintf (stderr,
-             "\n"
-             "Failed to connect to virtio-serial channel.\n"
-             "\n"
-             "This is a fatal error and the appliance will now
exit.\n"
-             "\n"
-             "Usually this error is caused by either QEMU or the
appliance\n"
-             "kernel not supporting the vmchannel method that the\n"
-             "libguestfs library chose to use.  Please run\n"
-             "'libguestfs-test-tool' and provide the complete,
unedited\n"
-             "output to the libguestfs developers, either in a bug
report\n"
-             "or on the libguestfs redhat com mailing list.\n"
-             "\n");
-    perror (channel);
-    exit (EXIT_FAILURE);
+  int sock;
+  if (!listen_mode) {
+    sock = open (channel, O_RDWR|O_CLOEXEC);
+    if (sock == -1) {
+      fprintf (stderr,
+               "\n"
+               "Failed to connect to virtio-serial channel.\n"
+               "\n"
+               "This is a fatal error and the appliance will now
exit.\n"
+               "\n"
+               "Usually this error is caused by either QEMU or the
appliance\n"
+               "kernel not supporting the vmchannel method that
the\n"
+               "libguestfs library chose to use.  Please run\n"
+               "'libguestfs-test-tool' and provide the complete,
unedited\n"
+               "output to the libguestfs developers, either in a bug
report\n"
+               "or on the libguestfs redhat com mailing list.\n"
+               "\n");
+      perror (channel);
+      exit (EXIT_FAILURE);
+    }
+  }
+  else {
+    struct sockaddr_un addr;
+
+    sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
+    if (sock == -1)
+      error (EXIT_FAILURE, errno, "socket");
+    addr.sun_family = AF_UNIX;
+    strncpy (addr.sun_path, channel, UNIX_PATH_MAX);
+    addr.sun_path[UNIX_PATH_MAX-1] = '\0';
+
+    if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1)
+      error (EXIT_FAILURE, errno, "bind: %s", channel);
+
+    if (listen (sock, 4) == -1)
+      error (EXIT_FAILURE, errno, "listen");
+
+    sock = accept4 (sock, NULL, NULL, SOCK_CLOEXEC);
+    if (sock == -1)
+      error (EXIT_FAILURE, errno, "accept");
   }

   /* If it's a serial-port like device then it probably has echoing
diff --git a/daemon/guestfsd.pod b/daemon/guestfsd.pod
index 1ed31a9..22c8003 100644
--- a/daemon/guestfsd.pod
+++ b/daemon/guestfsd.pod
@@ -50,6 +50,15 @@ removed.

 Display brief help.

+=item B<-l>
+
+=item B<--listen>
+
+Instead of opening the C<guestfs_channel> and thus expecting that it
+already exists, create the channel as a Unix domain socket, listen on
+it, and accept a single connection.  This is mainly used for testing
+the daemon.
+
 =item B<-r>

 Set the root filesystem to be F</> (instead of the default which is
--
2.3.1