X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fguestfsd.c;h=e398b7d8348410fad052a94ebe27bde014e4b0a9;hp=cd51f442486c1537c37618abed1fdf6495926ea0;hb=e44cf42f362d793c47d892a18a6853d88abd6ecb;hpb=07369cb77a07f965cbf8e02f485c78a22c091f85 diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c index cd51f44..e398b7d 100644 --- a/daemon/guestfsd.c +++ b/daemon/guestfsd.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef HAVE_PRINTF_H # include @@ -55,24 +56,21 @@ static char *read_cmdline (void); -/* This is the default address we connect to for very old libraries - * which didn't specify the address and port number explicitly on the - * kernel command line. It's now recommended to always specify the - * address and port number on the command line, so this will not be - * used any more. - */ -#define OLD_GUESTFWD_ADDR "10.0.2.4" -#define OLD_GUESTFWD_PORT "6666" - -/* This is only a hint. If not defined, ignore it. */ -#ifndef AI_ADDRCONFIG -# define AI_ADDRCONFIG 0 -#endif - #ifndef MAX # define MAX(a,b) ((a)>(b)?(a):(b)) #endif +/* Not the end of the world if this open flag is not defined. */ +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif + +/* If root device is an ext2 filesystem, this is the major and minor. + * This is so we can ignore this device from the point of view of the + * user, eg. in guestfs_list_devices and many other places. + */ +static dev_t root_device = 0; + int verbose = 0; static int print_shell_quote (FILE *stream, const struct printf_info *info, const void *const *args); @@ -127,15 +125,14 @@ static void usage (void) { fprintf (stderr, - "guestfsd [-f|--foreground] [-c|--channel vmchannel] [-v|--verbose]\n"); + "guestfsd [-f|--foreground] [-v|--verbose]\n"); } int main (int argc, char *argv[]) { - static const char *options = "fc:v?"; + static const char *options = "fv?"; static const struct option long_options[] = { - { "channel", required_argument, 0, 'c' }, { "foreground", 0, 0, 'f' }, { "help", 0, 0, '?' }, { "verbose", 0, 0, 'v' }, @@ -144,7 +141,6 @@ main (int argc, char *argv[]) int c; int dont_fork = 0; char *cmdline; - char *vmchannel = NULL; if (winsock_init () == -1) error (EXIT_FAILURE, 0, "winsock initialization failed"); @@ -162,15 +158,15 @@ main (int argc, char *argv[]) #endif #endif + struct stat statbuf; + if (stat ("/", &statbuf) == 0) + root_device = statbuf.st_dev; + for (;;) { c = getopt_long (argc, argv, options, long_options, NULL); if (c == -1) break; switch (c) { - case 'c': - vmchannel = optarg; - break; - case 'f': dont_fork = 1; break; @@ -245,118 +241,13 @@ main (int argc, char *argv[]) _umask (0); #endif - /* Get the vmchannel string. - * - * Sources: - * --channel/-c option on the command line - * guestfs_vmchannel=... from the kernel command line - * guestfs=... from the kernel command line - * built-in default - * - * At the moment we expect this to contain "tcp:ip:port" but in - * future it might contain a device name, eg. "/dev/vcon4" for - * virtio-console vmchannel. - */ - if (vmchannel == NULL && cmdline) { - char *p; - size_t len; - - p = strstr (cmdline, "guestfs_vmchannel="); - if (p) { - len = strcspn (p + 18, " \t\n"); - vmchannel = strndup (p + 18, len); - if (!vmchannel) { - perror ("strndup"); - exit (EXIT_FAILURE); - } - } - - /* Old libraries passed guestfs=host:port. Rewrite it as tcp:host:port. */ - if (vmchannel == NULL) { - /* We will rewrite it part of the "guestfs=" string with - * "tcp:" hence p + 4 below. */ - p = strstr (cmdline, "guestfs="); - if (p) { - len = strcspn (p + 4, " \t\n"); - vmchannel = strndup (p + 4, len); - if (!vmchannel) { - perror ("strndup"); - exit (EXIT_FAILURE); - } - memcpy (vmchannel, "tcp:", 4); - } - } - } - - /* Default vmchannel. */ - if (vmchannel == NULL) { - vmchannel = strdup ("tcp:" OLD_GUESTFWD_ADDR ":" OLD_GUESTFWD_PORT); - if (!vmchannel) { - perror ("strdup"); - exit (EXIT_FAILURE); - } - } - - if (verbose) - printf ("vmchannel: %s\n", vmchannel); - - /* Connect to vmchannel. */ - int sock = -1; - - if (STREQLEN (vmchannel, "tcp:", 4)) { - /* Resolve the hostname. */ - struct addrinfo *res, *rr; - struct addrinfo hints; - int r; - char *host, *port; - - host = vmchannel+4; - port = strchr (host, ':'); - if (port) { - port[0] = '\0'; - port++; - } else { - fprintf (stderr, "vmchannel: expecting \"tcp::\": %s\n", - vmchannel); - exit (EXIT_FAILURE); - } - - memset (&hints, 0, sizeof hints); - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG; - r = getaddrinfo (host, port, &hints, &res); - if (r != 0) { - fprintf (stderr, "%s:%s: %s\n", - host, port, gai_strerror (r)); - exit (EXIT_FAILURE); - } - - /* Connect to the given TCP socket. */ - for (rr = res; rr != NULL; rr = rr->ai_next) { - sock = socket (rr->ai_family, rr->ai_socktype, rr->ai_protocol); - if (sock != -1) { - if (connect (sock, rr->ai_addr, rr->ai_addrlen) == 0) - break; - perror ("connect"); - - close (sock); - sock = -1; - } - } - freeaddrinfo (res); - } else { - fprintf (stderr, - "unknown vmchannel connection type: %s\n" - "expecting \"tcp::\"\n", - vmchannel); - exit (EXIT_FAILURE); - } - + /* Connect to virtio-serial channel. */ + int sock = open ("/dev/virtio-ports/org.libguestfs.channel.0", + O_RDWR | O_CLOEXEC); if (sock == -1) { fprintf (stderr, "\n" - "Failed to connect to any vmchannel implementation.\n" - "vmchannel: %s\n" + "Failed to connect to virtio-serial channel.\n" "\n" "This is a fatal error and the appliance will now exit.\n" "\n" @@ -366,8 +257,7 @@ main (int argc, char *argv[]) "'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", - vmchannel); + "\n"); exit (EXIT_FAILURE); } @@ -448,6 +338,22 @@ read_cmdline (void) return r; } +/* Return true iff device is the root device (and therefore should be + * ignored from the point of view of user calls). + */ +int +is_root_device (const char *device) +{ + struct stat statbuf; + if (stat (device, &statbuf) == -1) { + perror (device); + return 0; + } + if (statbuf.st_rdev == root_device) + return 1; + return 0; +} + /* Turn "/path" into "/sysroot/path". * * Caller must check for NULL and call reply_with_perror ("malloc") @@ -543,16 +449,23 @@ add_string (char ***argv, int *size, int *alloc, const char *str) return 0; } -int +size_t count_strings (char *const *argv) { - int argc; + size_t argc; for (argc = 0; argv[argc] != NULL; ++argc) ; return argc; } +/* http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 */ +int +is_power_of_2 (unsigned long v) +{ + return v && ((v & (v - 1)) == 0); +} + static int compare (const void *vp1, const void *vp2) { @@ -758,20 +671,20 @@ commandrvf (char **stdoutput, char **stderror, int flags, */ if (pipe (so_fd) == -1 || pipe (se_fd) == -1) { - perror ("pipe"); + error (0, errno, "pipe"); abort (); } if (flag_copy_stdin) { if (pipe (stdin_fd) == -1) { - perror ("pipe"); + error (0, errno, "pipe"); abort (); } } pid = fork (); if (pid == -1) { - perror ("fork"); + error (0, errno, "fork"); abort (); } @@ -781,9 +694,10 @@ commandrvf (char **stdoutput, char **stderror, int flags, dup2 (stdin_fd[0], 0); close (stdin_fd[0]); close (stdin_fd[1]); - } else + } else { /* Set stdin to /dev/null (ignore failure) */ open ("/dev/null", O_RDONLY); + } close (so_fd[0]); close (se_fd[0]); if (!(flags & COMMAND_FLAG_FOLD_STDOUT_ON_STDERR)) @@ -804,7 +718,7 @@ commandrvf (char **stdoutput, char **stderror, int flags, stdin_pid = fork (); if (stdin_pid == -1) { - perror ("fork"); + error (0, errno, "fork"); abort (); }