/* libguestfs - the guestfsd daemon
- * Copyright (C) 2009 Red Hat Inc.
+ * Copyright (C) 2009 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
char lenbuf[4];
unsigned len;
struct guestfs_message_header hdr;
+ struct timeval start_t, end_t;
+ int64_t start_us, end_us, elapsed_us;
sock = _sock;
for (;;) {
+#if 0
+ /* Most common errors are leaked memory and leaked file descriptors,
+ * so run this between each command:
+ */
+ if (verbose)
+ system ("ls -l /proc/self/fd");
+#endif
+
/* Read the length word. */
xread (sock, lenbuf, 4);
xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
if (len > GUESTFS_MESSAGE_MAX) {
fprintf (stderr, "guestfsd: incoming message is too long (%u bytes)\n",
- len);
+ len);
exit (1);
}
xread (sock, buf, len);
+#if 0
if (verbose) {
int i, j;
for (i = 0; i < len; i += 16) {
- printf ("%04x: ", i);
- for (j = i; j < MIN (i+16, len); ++j)
- printf ("%02x ", (unsigned char) buf[j]);
- for (; j < i+16; ++j)
- printf (" ");
- printf ("|");
- for (j = i; j < MIN (i+16, len); ++j)
- if (isprint (buf[j]))
- printf ("%c", buf[j]);
- else
- printf (".");
- for (; j < i+16; ++j)
- printf (" ");
- printf ("|\n");
+ printf ("%04x: ", i);
+ for (j = i; j < MIN (i+16, len); ++j)
+ printf ("%02x ", (unsigned char) buf[j]);
+ for (; j < i+16; ++j)
+ printf (" ");
+ printf ("|");
+ for (j = i; j < MIN (i+16, len); ++j)
+ if (isprint (buf[j]))
+ printf ("%c", buf[j]);
+ else
+ printf (".");
+ for (; j < i+16; ++j)
+ printf (" ");
+ printf ("|\n");
}
}
+#endif
+
+ /* In verbose mode, display the time taken to run each command. */
+ if (verbose)
+ gettimeofday (&start_t, NULL);
/* Decode the message header. */
xdrmem_create (&xdr, buf, len, XDR_DECODE);
dispatch_incoming_message (&xdr);
/* Note that dispatch_incoming_message will also send a reply. */
+ /* In verbose mode, display the time taken to run each command. */
+ if (verbose) {
+ gettimeofday (&end_t, NULL);
+
+ start_us = (int64_t) start_t.tv_sec * 1000000 + start_t.tv_usec;
+ end_us = (int64_t) end_t.tv_sec * 1000000 + end_t.tv_usec;
+ elapsed_us = end_us - start_us;
+ fprintf (stderr, "proc %d (%s) took %d.%02d seconds\n",
+ proc_nr,
+ proc_nr >= 0 && proc_nr < GUESTFS_PROC_NR_PROCS
+ ? function_names[proc_nr] : "UNKNOWN PROCEDURE",
+ (int) (elapsed_us / 1000000),
+ (int) ((elapsed_us / 10000) % 100));
+ }
+
cont:
xdr_destroy (&xdr);
free (buf);
xdr_uint32_t (&xdr, &len);
xdr_destroy (&xdr);
- (void) xwrite (sock, lenbuf, 4);
- (void) xwrite (sock, buf, len);
+ if (xwrite (sock, lenbuf, 4) == -1) {
+ fprintf (stderr, "xwrite failed\n");
+ exit (1);
+ }
+ if (xwrite (sock, buf, len) == -1) {
+ fprintf (stderr, "xwrite failed\n");
+ exit (1);
+ }
}
void
}
if (xdrp) {
+ /* This can fail if the reply body is too large, for example
+ * if it exceeds the maximum message size. In that case
+ * we want to return an error message instead. (RHBZ#509597).
+ */
if (!(*xdrp) (&xdr, ret)) {
- fprintf (stderr, "guestfsd: failed to encode reply body\n");
- exit (1);
+ reply_with_perror ("guestfsd: failed to encode reply body\n");
+ xdr_destroy (&xdr);
+ return;
}
}
xdr_uint32_t (&xdr, &len);
xdr_destroy (&xdr);
- (void) xwrite (sock, lenbuf, 4);
- (void) xwrite (sock, buf, len);
+ if (xwrite (sock, lenbuf, 4) == -1) {
+ fprintf (stderr, "xwrite failed\n");
+ exit (1);
+ }
+ if (xwrite (sock, buf, len) == -1) {
+ fprintf (stderr, "xwrite failed\n");
+ exit (1);
+ }
}
/* Receive file chunks, repeatedly calling 'cb'. */
if (len > GUESTFS_MESSAGE_MAX) {
fprintf (stderr, "guestfsd: incoming message is too long (%u bytes)\n",
- len);
+ len);
exit (1);
}
if (verbose)
printf ("receive_file: got chunk: cancel = %d, len = %d, buf = %p\n",
- chunk.cancel, chunk.data.data_len, chunk.data.data_val);
+ chunk.cancel, chunk.data.data_len, chunk.data.data_val);
if (chunk.cancel) {
fprintf (stderr, "receive_file: received cancellation from library\n");
if (len > GUESTFS_MAX_CHUNK_SIZE) {
fprintf (stderr, "send_file_write: len (%d) > GUESTFS_MAX_CHUNK_SIZE (%d)\n",
- len, GUESTFS_MAX_CHUNK_SIZE);
+ len, GUESTFS_MAX_CHUNK_SIZE);
return -1;
}
if (flag != GUESTFS_CANCEL_FLAG) {
fprintf (stderr, "check_for_library_cancellation: read 0x%x from library, expected 0x%x\n",
- flag, GUESTFS_CANCEL_FLAG);
+ flag, GUESTFS_CANCEL_FLAG);
return 0;
}
return 1;
}
-void
+int
send_file_end (int cancel)
{
guestfs_chunk chunk;
chunk.cancel = cancel;
chunk.data.data_len = 0;
chunk.data.data_val = NULL;
- send_chunk (&chunk);
+ return send_chunk (&chunk);
}
static int
xdr_uint32_t (&xdr, &len);
xdr_destroy (&xdr);
- (void) xwrite (sock, lenbuf, 4);
- (void) xwrite (sock, buf, len);
+ int err = (xwrite (sock, lenbuf, 4) == 0
+ && xwrite (sock, buf, len) == 0 ? 0 : -1);
+ if (err) {
+ fprintf (stderr, "send_chunk: write failed\n");
+ exit (1);
+ }
- return 0;
+ return err;
}