- return g->main_loop;
-}
-
-guestfs_main_loop *
-guestfs_get_default_main_loop (void)
-{
- return (guestfs_main_loop *) &default_main_loop;
-}
-
-/* Change the daemon socket handler so that we are now writing.
- * This sets the handle to sock_write_event.
- */
-int
-guestfs__switch_to_sending (guestfs_h *g)
-{
- if (g->sock_watch >= 0) {
- if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
- error (g, _("remove_handle failed"));
- g->sock_watch = -1;
- return -1;
- }
- }
-
- g->sock_watch =
- g->main_loop->add_handle (g->main_loop, g, g->sock,
- GUESTFS_HANDLE_WRITABLE,
- sock_write_event, NULL);
- if (g->sock_watch == -1) {
- error (g, _("add_handle failed"));
- return -1;
- }
-
- return 0;
-}
-
-int
-guestfs__switch_to_receiving (guestfs_h *g)
-{
- if (g->sock_watch >= 0) {
- if (g->main_loop->remove_handle (g->main_loop, g, g->sock_watch) == -1) {
- error (g, _("remove_handle failed"));
- g->sock_watch = -1;
- return -1;
- }
- }
-
- g->sock_watch =
- g->main_loop->add_handle (g->main_loop, g, g->sock,
- GUESTFS_HANDLE_READABLE,
- sock_read_event, NULL);
- if (g->sock_watch == -1) {
- error (g, _("add_handle failed"));
- return -1;
- }
-
- return 0;
-}
-
-/* Dispatch a call (len + header + args) to the remote daemon,
- * synchronously (ie. using the guest's main loop to wait until
- * it has been sent). Returns -1 for error, or the serial
- * number of the message.
- */
-static void
-send_cb (guestfs_h *g, void *data)
-{
- guestfs_main_loop *ml = guestfs_get_main_loop (g);
-
- *((int *)data) = 1;
- ml->main_loop_quit (ml, g);
-}
-
-int
-guestfs__send_sync (guestfs_h *g, int proc_nr,
- xdrproc_t xdrp, char *args)
-{
- struct guestfs_message_header hdr;
- XDR xdr;
- u_int32_t len;
- int serial = g->msg_next_serial++;
- int sent;
- guestfs_main_loop *ml = guestfs_get_main_loop (g);
-
- if (g->state != BUSY) {
- error (g, _("guestfs__send_sync: state %d != BUSY"), g->state);
- return -1;
- }
-
- /* This is probably an internal error. Or perhaps we should just
- * free the buffer anyway?
- */
- if (g->msg_out != NULL) {
- error (g, _("guestfs__send_sync: msg_out should be NULL"));
- return -1;
- }
-
- /* We have to allocate this message buffer on the heap because
- * it is quite large (although will be mostly unused). We
- * can't allocate it on the stack because in some environments
- * we have quite limited stack space available, notably when
- * running in the JVM.
- */
- g->msg_out = safe_malloc (g, GUESTFS_MESSAGE_MAX + 4);
- xdrmem_create (&xdr, g->msg_out + 4, GUESTFS_MESSAGE_MAX, XDR_ENCODE);
-
- /* Serialize the header. */
- hdr.prog = GUESTFS_PROGRAM;
- hdr.vers = GUESTFS_PROTOCOL_VERSION;
- hdr.proc = proc_nr;
- hdr.direction = GUESTFS_DIRECTION_CALL;
- hdr.serial = serial;
- hdr.status = GUESTFS_STATUS_OK;
-
- if (!xdr_guestfs_message_header (&xdr, &hdr)) {
- error (g, _("xdr_guestfs_message_header failed"));
- goto cleanup1;
- }
-
- /* Serialize the args. If any, because some message types
- * have no parameters.
- */
- if (xdrp) {
- if (!(*xdrp) (&xdr, args)) {
- error (g, _("dispatch failed to marshal args"));
- goto cleanup1;
- }
- }
-
- /* Get the actual length of the message, resize the buffer to match
- * the actual length, and write the length word at the beginning.
- */
- len = xdr_getpos (&xdr);
- xdr_destroy (&xdr);
-
- g->msg_out = safe_realloc (g, g->msg_out, len + 4);
- g->msg_out_size = len + 4;
- g->msg_out_pos = 0;
-
- xdrmem_create (&xdr, g->msg_out, 4, XDR_ENCODE);
- xdr_uint32_t (&xdr, &len);
-
- if (guestfs__switch_to_sending (g) == -1)
- goto cleanup1;
-
- sent = 0;
- guestfs_set_send_callback (g, send_cb, &sent);
- if (ml->main_loop_run (ml, g) == -1)
- goto cleanup1;
- if (sent != 1) {
- error (g, _("send failed, see earlier error messages"));
- goto cleanup1;
- }
-
- return serial;
-
- cleanup1:
- free (g->msg_out);
- g->msg_out = NULL;
- g->msg_out_size = 0;
- return -1;
-}
-
-static int cancel = 0; /* XXX Implement file cancellation. */
-static int send_file_chunk_sync (guestfs_h *g, int cancel, const char *buf, size_t len);
-static int send_file_data_sync (guestfs_h *g, const char *buf, size_t len);
-static int send_file_cancellation_sync (guestfs_h *g);
-static int send_file_complete_sync (guestfs_h *g);
-
-/* Synchronously send a file.
- * Returns:
- * 0 OK
- * -1 error
- * -2 daemon cancelled (we must read the error message)
- */
-int
-guestfs__send_file_sync (guestfs_h *g, const char *filename)
-{
- char buf[GUESTFS_MAX_CHUNK_SIZE];
- int fd, r, err;
-
- fd = open (filename, O_RDONLY);
- if (fd == -1) {
- perrorf (g, "open: %s", filename);
- send_file_cancellation_sync (g);
- /* Daemon sees cancellation and won't reply, so caller can
- * just return here.
- */
- return -1;
- }
-
- /* Send file in chunked encoding. */
- while (!cancel) {
- r = read (fd, buf, sizeof buf);
- if (r == -1 && (errno == EINTR || errno == EAGAIN))
- continue;
- if (r <= 0) break;
- err = send_file_data_sync (g, buf, r);
- if (err < 0) {
- if (err == -2) /* daemon sent cancellation */
- send_file_cancellation_sync (g);
- return err;
- }