static void send_error (int errnum, char *msg) { XDR xdr; CLEANUP_FREE char *buf = NULL; char lenbuf[4]; struct guestfs_message_header hdr; struct guestfs_message_error err; unsigned len; /* Print the full length error message. */ fprintf (stderr, "guestfsd: error: %s\n", msg); /* We want to truncate the error message to GUESTFS_ERROR_LEN bytes * (not including the \0 since it is not encoded in XDR). This is * so that the xdr_guestfs_message_error call below won't fail on * very long error messages. We can overwrite the message since all * callers of send_error pass a temporary buffer. */ if (strlen (msg) > GUESTFS_ERROR_LEN) msg[GUESTFS_ERROR_LEN] = '\0'; buf = malloc (GUESTFS_ERROR_LEN + 200); if (!buf) error (EXIT_FAILURE, errno, "malloc"); xdrmem_create (&xdr, buf, GUESTFS_ERROR_LEN + 200, XDR_ENCODE); memset (&hdr, 0, sizeof hdr); hdr.prog = GUESTFS_PROGRAM; hdr.vers = GUESTFS_PROTOCOL_VERSION; hdr.direction = GUESTFS_DIRECTION_REPLY; hdr.status = GUESTFS_STATUS_ERROR; hdr.proc = proc_nr; hdr.serial = serial; if (!xdr_guestfs_message_header (&xdr, &hdr)) error (EXIT_FAILURE, 0, "failed to encode error message header"); /* These strings are not going to be freed. We just cast them * to (char *) because they are defined that way in the XDR structs. */ err.errno_string = (char *) (errnum > 0 ? guestfs_int_errno_to_string (errnum) : ""); err.error_message = (char *) msg; if (!xdr_guestfs_message_error (&xdr, &err)) error (EXIT_FAILURE, 0, "failed to encode error message body"); len = xdr_getpos (&xdr); xdr_destroy (&xdr); xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE); xdr_u_int (&xdr, &len); xdr_destroy (&xdr); if (xwrite (sock, lenbuf, 4) == -1) error (EXIT_FAILURE, 0, "xwrite failed"); if (xwrite (sock, buf, len) == -1) error (EXIT_FAILURE, 0, "xwrite failed"); }
/* Receive a reply. */ int guestfs___recv (guestfs_h *g, const char *fn, guestfs_message_header *hdr, guestfs_message_error *err, xdrproc_t xdrp, char *ret) { XDR xdr; 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; } xdrmem_create (&xdr, buf, size, XDR_DECODE); if (!xdr_guestfs_message_header (&xdr, hdr)) { error (g, "%s: failed to parse reply header", fn); xdr_destroy (&xdr); free (buf); return -1; } if (hdr->status == GUESTFS_STATUS_ERROR) { if (!xdr_guestfs_message_error (&xdr, err)) { error (g, "%s: failed to parse reply error", fn); xdr_destroy (&xdr); free (buf); return -1; } } else { if (xdrp && ret && !xdrp (&xdr, ret)) { error (g, "%s: failed to parse reply", fn); xdr_destroy (&xdr); free (buf); return -1; } } xdr_destroy (&xdr); free (buf); return 0; }
static void send_error (int errnum, const char *msg) { XDR xdr; char buf[GUESTFS_ERROR_LEN + 200]; char lenbuf[4]; struct guestfs_message_header hdr; struct guestfs_message_error err; unsigned len; fprintf (stderr, "guestfsd: error: %s\n", msg); xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE); memset (&hdr, 0, sizeof hdr); hdr.prog = GUESTFS_PROGRAM; hdr.vers = GUESTFS_PROTOCOL_VERSION; hdr.direction = GUESTFS_DIRECTION_REPLY; hdr.status = GUESTFS_STATUS_ERROR; hdr.proc = proc_nr; hdr.serial = serial; if (!xdr_guestfs_message_header (&xdr, &hdr)) { fprintf (stderr, "guestfsd: failed to encode error message header\n"); exit (EXIT_FAILURE); } /* These strings are not going to be freed. We just cast them * to (char *) because they are defined that way in the XDR structs. */ err.errno_string = (char *) (errnum > 0 ? guestfs___errno_to_string (errnum) : ""); err.error_message = (char *) msg; if (!xdr_guestfs_message_error (&xdr, &err)) { fprintf (stderr, "guestfsd: failed to encode error message body\n"); exit (EXIT_FAILURE); } len = xdr_getpos (&xdr); xdr_destroy (&xdr); xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE); xdr_u_int (&xdr, &len); xdr_destroy (&xdr); if (xwrite (sock, lenbuf, 4) == -1) { fprintf (stderr, "guestfsd: xwrite failed\n"); exit (EXIT_FAILURE); } if (xwrite (sock, buf, len) == -1) { fprintf (stderr, "guestfsd: xwrite failed\n"); exit (EXIT_FAILURE); } }