+ return -2;
+}
+
+/* This writes the whole N bytes of BUF to the daemon socket.
+ *
+ * If the whole write is successful, it returns 0.
+ * If there was an error, it returns -1.
+ * If the daemon sent a cancellation message, it returns -2.
+ *
+ * It also checks qemu stdout for log messages and passes those up
+ * through log_message_cb.
+ *
+ * It also checks for EOF (qemu died) and passes that up through the
+ * child_cleanup function above.
+ */
+static int
+send_to_daemon (guestfs_h *g, const void *v_buf, size_t n)
+{
+ const char *buf = v_buf;
+ fd_set rset, rset2;
+ fd_set wset, wset2;
+
+ if (g->verbose)
+ fprintf (stderr,
+ "send_to_daemon: %p g->state = %d, n = %zu\n", g, g->state, n);
+
+ FD_ZERO (&rset);
+ FD_ZERO (&wset);
+
+ FD_SET (g->fd[1], &rset); /* Read qemu stdout for log messages & EOF. */
+ FD_SET (g->sock, &rset); /* Read socket for cancellation & EOF. */
+ FD_SET (g->sock, &wset); /* Write to socket to send the data. */
+
+ int max_fd = MAX (g->sock, g->fd[1]);
+
+ while (n > 0) {
+ rset2 = rset;
+ wset2 = wset;
+ int r = select (max_fd+1, &rset2, &wset2, NULL, NULL);
+ if (r == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perrorf (g, "select");
+ return -1;
+ }
+
+ if (FD_ISSET (g->fd[1], &rset2)) {
+ if (read_log_message_or_eof (g, g->fd[1]) == -1)
+ return -1;
+ }
+ if (FD_ISSET (g->sock, &rset2)) {
+ r = check_for_daemon_cancellation_or_eof (g, g->sock);
+ if (r < 0)
+ return r;
+ }
+ if (FD_ISSET (g->sock, &wset2)) {
+ r = write (g->sock, buf, n);
+ if (r == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ perrorf (g, "write");
+ if (errno == EPIPE) /* Disconnected from guest (RHBZ#508713). */
+ child_cleanup (g);
+ return -1;
+ }
+ buf += r;
+ n -= r;
+ }
+ }
+
+ return 0;
+}
+
+/* This reads a single message, file chunk, launch flag or
+ * cancellation flag from the daemon. If something was read, it
+ * returns 0, otherwise -1.
+ *
+ * Both size_rtn and buf_rtn must be passed by the caller as non-NULL.
+ *
+ * *size_rtn returns the size of the returned message or it may be
+ * GUESTFS_LAUNCH_FLAG or GUESTFS_CANCEL_FLAG.
+ *
+ * *buf_rtn is returned containing the message (if any) or will be set
+ * to NULL. *buf_rtn must be freed by the caller.
+ *
+ * It also checks qemu stdout for log messages and passes those up
+ * through log_message_cb.
+ *
+ * It also checks for EOF (qemu died) and passes that up through the
+ * child_cleanup function above.
+ */
+static int
+recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn)
+{
+ fd_set rset, rset2;
+
+ if (g->verbose)
+ fprintf (stderr,
+ "recv_from_daemon: %p g->state = %d, size_rtn = %p, buf_rtn = %p\n",
+ g, g->state, size_rtn, buf_rtn);
+
+ FD_ZERO (&rset);