/* 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
#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. */
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)
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;
}
}
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)
/* 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) {
}
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) {
/* 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");
}
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;