int guestfs___recv_file (guestfs_h *g, const char *filename) { void *buf; int fd, r; g->user_cancel = 0; fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perrorf (g, "open: %s", filename); goto cancel; } fadvise_sequential (fd); /* Receive the file in chunked encoding. */ while ((r = receive_file_data (g, &buf)) > 0) { if (xwrite (fd, buf, r) == -1) { perrorf (g, "%s: write", filename); free (buf); close (fd); goto cancel; } free (buf); if (g->user_cancel) { close (fd); goto cancel; } } if (r == -1) { error (g, _("%s: error in chunked encoding"), filename); close (fd); return -1; } if (close (fd) == -1) { perrorf (g, "close: %s", filename); return -1; } return 0; cancel: ; /* Send cancellation message to daemon, then wait until it * cancels (just throwing away data). */ XDR xdr; char fbuf[4]; uint32_t flag = GUESTFS_CANCEL_FLAG; debug (g, "%s: waiting for daemon to acknowledge cancellation", __func__); xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE); xdr_uint32_t (&xdr, &flag); xdr_destroy (&xdr); if (xwrite (g->sock, fbuf, sizeof fbuf) == -1) { perrorf (g, _("write to daemon socket")); return -1; } while (receive_file_data (g, NULL) > 0) ; /* just discard it */ return -1; }
/** * Returns C<-1> = error, C<0> = EOF, C<E<gt>0> = more data */ int guestfs_int_recv_file (guestfs_h *g, const char *filename) { void *buf; int fd, r; g->user_cancel = 0; /* If downloading to /dev/stdout or /dev/stderr, dup the file * descriptor instead of reopening the file, so that redirected * stdout/stderr work properly. */ if (STREQ (filename, "/dev/stdout")) fd = dup (1); else if (STREQ (filename, "/dev/stderr")) fd = dup (2); else fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perrorf (g, "%s", filename); goto cancel; } guestfs_int_fadvise_sequential (fd); /* Receive the file in chunked encoding. */ while ((r = receive_file_data (g, &buf)) > 0) { if (xwrite (fd, buf, r) == -1) { perrorf (g, "%s: write", filename); free (buf); close (fd); goto cancel; } free (buf); if (g->user_cancel) { close (fd); goto cancel; } } if (r == -1) { close (fd); return -1; } if (close (fd) == -1) { perrorf (g, "close: %s", filename); return -1; } return 0; cancel: ; /* Send cancellation message to daemon, then wait until it * cancels (just throwing away data). */ XDR xdr; char fbuf[4]; uint32_t flag = GUESTFS_CANCEL_FLAG; debug (g, "%s: waiting for daemon to acknowledge cancellation", __func__); xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE); xdr_uint32_t (&xdr, &flag); xdr_destroy (&xdr); if (g->conn->ops->write_data (g, g->conn, fbuf, sizeof fbuf) == -1) { perrorf (g, _("write to daemon socket")); return -1; } while (receive_file_data (g, NULL) > 0) ; /* just discard it */ return -1; }