guestfs(3): Indent line to keep code together.
[libguestfs.git] / src / proto.c
index 0d63af6..125c126 100644 (file)
@@ -404,8 +404,19 @@ guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n)
     }
     if (FD_ISSET (g->sock, &rset2)) {
       r = check_for_daemon_cancellation_or_eof (g, g->sock);
-      if (r < 0)
-        return r;
+      if (r == -1)
+       return r;
+      if (r == -2) {
+       /* Daemon sent cancel message.  But to maintain
+        * synchronization we must write out the remainder of the
+        * write buffer before we return (RHBZ#576879).
+        */
+       if (xwrite (g->sock, buf, n) == -1) {
+         perrorf (g, "write");
+         return -1;
+       }
+       return -2; /* cancelled */
+      }
     }
     if (FD_ISSET (g->sock, &wset2)) {
       r = write (g->sock, buf, n);
@@ -793,9 +804,6 @@ guestfs___send_file (guestfs_h *g, const char *filename)
   if (fd == -1) {
     perrorf (g, "open: %s", filename);
     send_file_cancellation (g);
-    /* Daemon sees cancellation and won't reply, so caller can
-     * just return here.
-     */
     return -1;
   }
 
@@ -980,6 +988,34 @@ guestfs___recv (guestfs_h *g, const char *fn,
   return 0;
 }
 
+/* Same as guestfs___recv, but it discards the reply message. */
+int
+guestfs___recv_discard (guestfs_h *g, const char *fn)
+{
+  void *buf;
+  uint32_t size;
+  int r;
+
+ again:
+  r = guestfs___recv_from_daemon (g, &size, &buf);
+  if (r == -1)
+    return -1;
+
+  /* This can happen if a cancellation happens right at the end
+   * of us sending a FileIn parameter to the daemon.  Discard.  The
+   * daemon should send us an error message next.
+   */
+  if (size == GUESTFS_CANCEL_FLAG)
+    goto again;
+
+  if (size == GUESTFS_LAUNCH_FLAG) {
+    error (g, "%s: received unexpected launch flag from daemon when expecting reply", fn);
+    return -1;
+  }
+
+  return 0;
+}
+
 /* Receive a file. */
 
 /* Returns -1 = error, 0 = EOF, > 0 = more data */