X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fproto.c;h=5d924e86bbeb46775f24b0b0b55cb3caa5adfddb;hp=fc1fedc3bc2c9d6868fc6c6ba1fe3814fbf869a9;hb=7e3d76e41b3c2862ae04744b01e5e23b245393e4;hpb=41f25ab3df5f306ac717fa7a6efd58328d30c1ae diff --git a/src/proto.c b/src/proto.c index fc1fedc..5d924e8 100644 --- a/src/proto.c +++ b/src/proto.c @@ -299,7 +299,7 @@ check_for_daemon_cancellation_or_eof (guestfs_h *g, int fd) * child_cleanup function above. */ int -guestfs__send_to_daemon (guestfs_h *g, const void *v_buf, size_t n) +guestfs___send_to_daemon (guestfs_h *g, const void *v_buf, size_t n) { const char *buf = v_buf; fd_set rset, rset2; @@ -373,9 +373,17 @@ guestfs__send_to_daemon (guestfs_h *g, const void *v_buf, size_t n) * * It also checks for EOF (qemu died) and passes that up through the * child_cleanup function above. + * + * Progress notifications are handled transparently by this function. + * If the callback exists, it is called. The caller of this function + * will not see GUESTFS_PROGRESS_FLAG. */ + +/* Size of guestfs_progress message on the wire. */ +#define PROGRESS_MESSAGE_SIZE 24 + int -guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) +guestfs___recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) { fd_set rset, rset2; @@ -400,7 +408,13 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) */ ssize_t nr = -4; - while (nr < (ssize_t) *size_rtn) { + for (;;) { + ssize_t message_size = + *size_rtn != GUESTFS_PROGRESS_FLAG ? + *size_rtn : PROGRESS_MESSAGE_SIZE; + if (nr >= message_size) + break; + rset2 = rset; int r = select (max_fd+1, &rset2, NULL, NULL, NULL); if (r == -1) { @@ -450,6 +464,11 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) xdr_uint32_t (&xdr, size_rtn); xdr_destroy (&xdr); + /* *size_rtn changed, recalculate message_size */ + message_size = + *size_rtn != GUESTFS_PROGRESS_FLAG ? + *size_rtn : PROGRESS_MESSAGE_SIZE; + if (*size_rtn == GUESTFS_LAUNCH_FLAG) { if (g->state != LAUNCHING) error (g, _("received magic signature from guestfsd, but in state %d"), @@ -463,6 +482,8 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) } else if (*size_rtn == GUESTFS_CANCEL_FLAG) return 0; + else if (*size_rtn == GUESTFS_PROGRESS_FLAG) + /*FALLTHROUGH*/; /* If this happens, it's pretty bad and we've probably lost * synchronization. */ @@ -473,11 +494,11 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) } /* Allocate the complete buffer, size now known. */ - *buf_rtn = safe_malloc (g, *size_rtn); + *buf_rtn = safe_malloc (g, message_size); /*FALLTHROUGH*/ } - size_t sizetoread = *size_rtn - nr; + size_t sizetoread = message_size - nr; if (sizetoread > BUFSIZ) sizetoread = BUFSIZ; r = read (g->sock, (char *) (*buf_rtn) + nr, sizetoread); @@ -524,6 +545,26 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) } #endif + if (*size_rtn == GUESTFS_PROGRESS_FLAG) { + if (g->state == BUSY && g->progress_cb) { + guestfs_progress message; + XDR xdr; + xdrmem_create (&xdr, *buf_rtn, PROGRESS_MESSAGE_SIZE, XDR_DECODE); + xdr_guestfs_progress (&xdr, &message); + xdr_destroy (&xdr); + + g->progress_cb (g, g->progress_cb_data, + message.proc, message.serial, + message.position, message.total); + } + + free (*buf_rtn); + *buf_rtn = NULL; + + /* Process next message. */ + return guestfs___recv_from_daemon (g, size_rtn, buf_rtn); + } + return 0; } @@ -533,7 +574,7 @@ guestfs__recv_from_daemon (guestfs_h *g, uint32_t *size_rtn, void **buf_rtn) * accepted socket. */ int -guestfs__accept_from_daemon (guestfs_h *g) +guestfs___accept_from_daemon (guestfs_h *g) { fd_set rset, rset2; @@ -646,7 +687,7 @@ guestfs___send (guestfs_h *g, int proc_nr, xdrproc_t xdrp, char *args) xdr_uint32_t (&xdr, &len); again: - r = guestfs__send_to_daemon (g, msg_out, msg_out_size); + r = guestfs___send_to_daemon (g, msg_out, msg_out_size); if (r == -2) /* Ignore stray daemon cancellations. */ goto again; if (r == -1) @@ -790,7 +831,7 @@ send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t buflen) xdrmem_create (&xdr, msg_out, 4, XDR_ENCODE); xdr_uint32_t (&xdr, &len); - r = guestfs__send_to_daemon (g, msg_out, msg_out_size); + r = guestfs___send_to_daemon (g, msg_out, msg_out_size); /* Did the daemon send a cancellation message? */ if (r == -2) { @@ -824,7 +865,7 @@ guestfs___recv (guestfs_h *g, const char *fn, int r; again: - r = guestfs__recv_from_daemon (g, &size, &buf); + r = guestfs___recv_from_daemon (g, &size, &buf); if (r == -1) return -1; @@ -946,7 +987,7 @@ receive_file_data (guestfs_h *g, void **buf_r) XDR xdr; guestfs_chunk chunk; - r = guestfs__recv_from_daemon (g, &len, &buf); + r = guestfs___recv_from_daemon (g, &len, &buf); if (r == -1) { error (g, _("receive_file_data: parse error in reply callback")); return -1;