X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Flaunch.c;h=40a58e0000b9d06312ea29cc37de95fbea0f9f32;hb=913d5cd3a950a35f19581262250f58a871689d8c;hp=047a1e154df540fc03cba1b0bad1342aa40cf61d;hpb=61da709722ec244da1c3c7d4f1a8706f76687cb3;p=libguestfs.git diff --git a/src/launch.c b/src/launch.c index 047a1e1..40a58e0 100644 --- a/src/launch.c +++ b/src/launch.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,8 @@ #include "guestfs-internal-actions.h" #include "guestfs_protocol.h" +static int launch_appliance (guestfs_h *g); +static int64_t timeval_diff (const struct timeval *x, const struct timeval *y); static int qemu_supports (guestfs_h *g, const char *option); /* Add a string to the current command line. */ @@ -101,6 +104,49 @@ add_cmdline (guestfs_h *g, const char *str) } int +guestfs___checkpoint_cmdline (guestfs_h *g) +{ + return g->cmdline_size; +} + +void +guestfs___rollback_cmdline (guestfs_h *g, int pos) +{ + int i; + + assert (g->cmdline_size >= pos); + + for (i = g->cmdline_size - 1; i >= pos; --i) + free (g->cmdline[i]); + + g->cmdline_size = pos; +} + +/* Internal command to return the command line. */ +char ** +guestfs__debug_cmdline (guestfs_h *g) +{ + int i; + char **r; + + if (g->cmdline == NULL) { + r = safe_malloc (g, sizeof (char *) * 1); + r[0] = NULL; + return r; + } + + r = safe_malloc (g, sizeof (char *) * (g->cmdline_size + 1)); + r[0] = safe_strdup (g, g->qemu); /* g->cmdline[0] is always NULL */ + + for (i = 1; i < g->cmdline_size; ++i) + r[i] = safe_strdup (g, g->cmdline[i]); + + r[g->cmdline_size] = NULL; + + return r; /* caller frees */ +} + +int guestfs__config (guestfs_h *g, const char *qemu_param, const char *qemu_value) { @@ -302,38 +348,23 @@ guestfs__add_cdrom (guestfs_h *g, const char *filename) } static int is_openable (guestfs_h *g, const char *path, int flags); -static void print_cmdline (guestfs_h *g); int guestfs__launch (guestfs_h *g) { - int r; - int wfd[2], rfd[2]; - int tries; - char unixsock[256]; - struct sockaddr_un addr; - /* Configured? */ - if (!g->cmdline) { - error (g, _("you must call guestfs_add_drive before guestfs_launch")); - return -1; - } - if (g->state != CONFIG) { error (g, _("the libguestfs handle has already been launched")); return -1; } - /* Start the clock ... */ - gettimeofday (&g->launch_t, NULL); - /* Make the temporary directory. */ if (!g->tmpdir) { TMP_TEMPLATE_ON_STACK (dir_template); g->tmpdir = safe_strdup (g, dir_template); if (mkdtemp (g->tmpdir) == NULL) { perrorf (g, _("%s: cannot create temporary directory"), dir_template); - goto cleanup0; + return -1; } } @@ -344,6 +375,28 @@ guestfs__launch (guestfs_h *g) if (chmod (g->tmpdir, 0755) == -1) fprintf (stderr, "chmod: %s: %m (ignored)\n", g->tmpdir); + return launch_appliance (g); +} + +static int +launch_appliance (guestfs_h *g) +{ + int r; + int wfd[2], rfd[2]; + char guestfsd_sock[256]; + struct sockaddr_un addr; + + /* At present you must add drives before starting the appliance. In + * future when we enable hotplugging you won't need to do this. + */ + if (!g->cmdline) { + error (g, _("you must call guestfs_add_drive before guestfs_launch")); + return -1; + } + + /* Start the clock ... */ + gettimeofday (&g->launch_t, NULL); + /* Locate and/or build the appliance. */ char *kernel = NULL, *initrd = NULL, *appliance = NULL; if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1) @@ -359,8 +412,8 @@ guestfs__launch (guestfs_h *g) /* Using virtio-serial, we need to create a local Unix domain socket * for qemu to connect to. */ - snprintf (unixsock, sizeof unixsock, "%s/sock", g->tmpdir); - unlink (unixsock); + snprintf (guestfsd_sock, sizeof guestfsd_sock, "%s/guestfsd.sock", g->tmpdir); + unlink (guestfsd_sock); g->sock = socket (AF_UNIX, SOCK_STREAM, 0); if (g->sock == -1) { @@ -374,7 +427,7 @@ guestfs__launch (guestfs_h *g) } addr.sun_family = AF_UNIX; - strncpy (addr.sun_path, unixsock, UNIX_PATH_MAX); + strncpy (addr.sun_path, guestfsd_sock, UNIX_PATH_MAX); addr.sun_path[UNIX_PATH_MAX-1] = '\0'; if (bind (g->sock, &addr, sizeof addr) == -1) { @@ -483,7 +536,7 @@ guestfs__launch (guestfs_h *g) /* Set up virtio-serial for the communications channel. */ add_cmdline (g, "-chardev"); - snprintf (buf, sizeof buf, "socket,path=%s,id=channel0", unixsock); + snprintf (buf, sizeof buf, "socket,path=%s,id=channel0", guestfsd_sock); add_cmdline (g, buf); add_cmdline (g, "-device"); add_cmdline (g, "virtserialport,chardev=channel0,name=org.libguestfs.channel.0"); @@ -546,7 +599,7 @@ guestfs__launch (guestfs_h *g) g->cmdline[g->cmdline_size-1] = NULL; if (g->verbose) - print_cmdline (g); + guestfs___print_timestamped_argv (g, (const char **)g->cmdline); if (!g->direct) { /* Set up stdin, stdout. */ @@ -706,7 +759,7 @@ guestfs__launch (guestfs_h *g) } if (g->pid > 0) kill (g->pid, 9); if (g->recoverypid > 0) kill (g->recoverypid, 9); - waitpid (g->pid, NULL, 0); + if (g->pid > 0) waitpid (g->pid, NULL, 0); if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0); g->fd[0] = -1; g->fd[1] = -1; @@ -746,26 +799,41 @@ guestfs_tmpdir (void) return tmpdir; } -/* This function is used to print the qemu command line before it gets - * executed, when in verbose mode. +/* Compute Y - X and return the result in milliseconds. + * Approximately the same as this code: + * http://www.mpp.mpg.de/~huber/util/timevaldiff.c */ -static void -print_cmdline (guestfs_h *g) +static int64_t +timeval_diff (const struct timeval *x, const struct timeval *y) +{ + int64_t msec; + + msec = (y->tv_sec - x->tv_sec) * 1000; + msec += (y->tv_usec - x->tv_usec) / 1000; + return msec; +} + +void +guestfs___print_timestamped_argv (guestfs_h *g, const char * argv[]) { int i = 0; int needs_quote; - while (g->cmdline[i]) { - if (g->cmdline[i][0] == '-') /* -option starts a new line */ + struct timeval tv; + gettimeofday (&tv, NULL); + fprintf (stderr, "[%05" PRIi64 "ms] ", timeval_diff (&g->launch_t, &tv)); + + while (argv[i]) { + if (argv[i][0] == '-') /* -option starts a new line */ fprintf (stderr, " \\\n "); if (i > 0) fputc (' ', stderr); /* Does it need shell quoting? This only deals with simple cases. */ - needs_quote = strcspn (g->cmdline[i], " ") != strlen (g->cmdline[i]); + needs_quote = strcspn (argv[i], " ") != strlen (argv[i]); if (needs_quote) fputc ('\'', stderr); - fprintf (stderr, "%s", g->cmdline[i]); + fprintf (stderr, "%s", argv[i]); if (needs_quote) fputc ('\'', stderr); i++; } @@ -773,20 +841,6 @@ print_cmdline (guestfs_h *g) fputc ('\n', stderr); } -/* Compute Y - X and return the result in milliseconds. - * Approximately the same as this code: - * http://www.mpp.mpg.de/~huber/util/timevaldiff.c - */ -static int64_t -timeval_diff (const struct timeval *x, const struct timeval *y) -{ - int64_t msec; - - msec = (y->tv_sec - x->tv_sec) * 1000; - msec += (y->tv_usec - x->tv_usec) / 1000; - return msec; -} - void guestfs___print_timestamped_message (guestfs_h *g, const char *fs, ...) {