X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fguestfs.c;h=e55b9bae874e0ef5d45ddf708a25a7914ca27c33;hb=8f549bd20a193bc61c6e78019c55aeb2efeb7bda;hp=fe08cb56ffee46430171e41703e108c5f240d8be;hpb=cd7a5b8ddfccf5641e52de7660fe50a093f7bb89;p=libguestfs.git diff --git a/src/guestfs.c b/src/guestfs.c index fe08cb5..e55b9ba 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -110,7 +110,26 @@ static int qemu_supports (guestfs_h *g, const char *option); #define xdr_uint32_t xdr_u_int32_t #endif -/* Also in guestfsd.c */ +/* Network configuration of the appliance. Note these addresses are + * only meaningful within the context of the running appliance. QEMU + * translates network connections to these magic addresses into + * userspace calls on the host (eg. connect(2)). qemu-doc has a nice + * diagram which is also useful to refer to. + * + * NETWORK: The network. + * + * ROUTER: The address of the "host", ie. this library. + * + * [Note: If you change NETWORK and ROUTER then you also have to + * change the network configuration in appliance/init]. + * + * GUESTFWD_ADDR, GUESTFWD_PORT: The guestfwd feature of qemu + * magically connects this pseudo-address to the guestfwd channel. In + * typical Linux configurations of libguestfs, guestfwd is not + * actually used any more. + */ +#define NETWORK "10.0.2.0/8" +#define ROUTER "10.0.2.2" #define GUESTFWD_ADDR "10.0.2.4" #define GUESTFWD_PORT "6666" @@ -811,6 +830,9 @@ int guestfs__add_drive_ro_with_if (guestfs_h *g, const char *filename, const char *drive_if) { + size_t len = strlen (filename) + 64; + char buf[len]; + if (strchr (filename, ',') != NULL) { error (g, _("filename cannot contain ',' (comma) character")); return -1; @@ -821,24 +843,7 @@ guestfs__add_drive_ro_with_if (guestfs_h *g, const char *filename, return -1; } - if (qemu_supports (g, NULL) == -1) - return -1; - - /* Only SCSI and virtio drivers support readonly mode. - * This is only supported as a QEMU feature since 2010/01. - */ - int supports_ro = 0; - if ((STREQ (drive_if, "scsi") || STREQ (drive_if, "virtio")) && - qemu_supports (g, "readonly=on")) - supports_ro = 1; - - size_t len = strlen (filename) + 100; - char buf[len]; - - snprintf (buf, len, "file=%s,snapshot=on,%sif=%s", - filename, - supports_ro ? "readonly=on," : "", - drive_if); + snprintf (buf, len, "file=%s,snapshot=on,if=%s", filename, drive_if); return guestfs__config (g, "-drive", buf); } @@ -929,9 +934,21 @@ guestfs__launch (guestfs_h *g) 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. */ #ifdef P_tmpdir tmpdir = P_tmpdir; #else @@ -941,18 +958,6 @@ guestfs__launch (guestfs_h *g) tmpdir = getenv ("TMPDIR") ? : tmpdir; snprintf (dir_template, sizeof dir_template, "%s/libguestfsXXXXXX", tmpdir); - /* Configured? */ - if (!g->cmdline) { - error (g, _("you must call guestfs_add_drive before guestfs_launch")); - return -1; - } - - if (g->state != CONFIG) { - error (g, _("qemu has already been launched")); - return -1; - } - - /* Make the temporary directory. */ if (!g->tmpdir) { g->tmpdir = safe_strdup (g, dir_template); if (mkdtemp (g->tmpdir) == NULL) { @@ -1189,10 +1194,11 @@ guestfs__launch (guestfs_h *g) */ if (null_vmchannel_sock) { add_cmdline (g, "-net"); - add_cmdline (g, "user,vlan=0,net=10.0.2.0/8"); + add_cmdline (g, "user,vlan=0,net=" NETWORK); snprintf (buf, sizeof buf, - "guestfs_vmchannel=tcp:10.0.2.2:%d", null_vmchannel_sock); + "guestfs_vmchannel=tcp:" ROUTER ":%d", + null_vmchannel_sock); vmchannel = strdup (buf); } @@ -1215,7 +1221,7 @@ guestfs__launch (guestfs_h *g) add_cmdline (g, buf); snprintf (buf, sizeof buf, - "user,vlan=0,net=10.0.2.0/8," + "user,vlan=0,net=" NETWORK "," "guestfwd=tcp:" GUESTFWD_ADDR ":" GUESTFWD_PORT "-chardev:guestfsvmc"); @@ -1235,7 +1241,7 @@ guestfs__launch (guestfs_h *g) add_cmdline (g, "-net"); add_cmdline (g, buf); add_cmdline (g, "-net"); - add_cmdline (g, "user,vlan=0,net=10.0.2.0/8"); + add_cmdline (g, "user,vlan=0,net=" NETWORK); vmchannel = "guestfs_vmchannel=tcp:" GUESTFWD_ADDR ":" GUESTFWD_PORT; } @@ -2018,7 +2024,7 @@ child_cleanup (guestfs_h *g) } static int -read_log_message_or_eof (guestfs_h *g, int fd) +read_log_message_or_eof (guestfs_h *g, int fd, int error_if_eof) { char buf[BUFSIZ]; int n; @@ -2039,6 +2045,13 @@ read_log_message_or_eof (guestfs_h *g, int fd) if (n == 0) { /* Hopefully this indicates the qemu child process has died. */ child_cleanup (g); + + if (error_if_eof) { + /* We weren't expecting eof here (called from launch) so place + * something in the error buffer. RHBZ#588851. + */ + error (g, "child process died unexpectedly"); + } return -1; } @@ -2146,7 +2159,7 @@ send_to_daemon (guestfs_h *g, const void *v_buf, size_t n) } if (FD_ISSET (g->fd[1], &rset2)) { - if (read_log_message_or_eof (g, g->fd[1]) == -1) + if (read_log_message_or_eof (g, g->fd[1], 0) == -1) return -1; } if (FD_ISSET (g->sock, &rset2)) { @@ -2229,7 +2242,7 @@ recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) } if (FD_ISSET (g->fd[1], &rset2)) { - if (read_log_message_or_eof (g, g->fd[1]) == -1) { + if (read_log_message_or_eof (g, g->fd[1], 0) == -1) { free (*buf_rtn); *buf_rtn = NULL; return -1; @@ -2384,7 +2397,7 @@ accept_from_daemon (guestfs_h *g) } if (FD_ISSET (g->fd[1], &rset2)) { - if (read_log_message_or_eof (g, g->fd[1]) == -1) + if (read_log_message_or_eof (g, g->fd[1], 1) == -1) return -1; } if (FD_ISSET (g->sock, &rset2)) {