コード例 #1
0
ファイル: proto.c プロジェクト: ArikaChen/libguestfs
static int
send_chunk (const guestfs_chunk *chunk)
{
  char buf[GUESTFS_MAX_CHUNK_SIZE + 48];
  char lenbuf[4];
  XDR xdr;
  uint32_t len;

  xdrmem_create (&xdr, buf, sizeof buf, XDR_ENCODE);
  if (!xdr_guestfs_chunk (&xdr, (guestfs_chunk *) chunk)) {
    fprintf (stderr, "guestfsd: send_chunk: failed to encode chunk\n");
    xdr_destroy (&xdr);
    return -1;
  }

  len = xdr_getpos (&xdr);
  xdr_destroy (&xdr);

  xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE);
  xdr_u_int (&xdr, &len);
  xdr_destroy (&xdr);

  int err = (xwrite (sock, lenbuf, 4) == 0
             && xwrite (sock, buf, len) == 0 ? 0 : -1);
  if (err) {
    fprintf (stderr, "guestfsd: send_chunk: write failed\n");
    exit (EXIT_FAILURE);
  }

  return err;
}
コード例 #2
0
ファイル: proto.c プロジェクト: msmhrt/libguestfs
static int
send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t buflen)
{
  u_int32_t len;
  int r;
  guestfs_chunk chunk;
  XDR xdr;
  char *msg_out;
  size_t msg_out_size;

  /* Allocate the chunk buffer.  Don't use the stack to avoid
   * excessive stack usage and unnecessary copies.
   */
  msg_out = safe_malloc (g, GUESTFS_MAX_CHUNK_SIZE + 4 + 48);
  xdrmem_create (&xdr, msg_out + 4, GUESTFS_MAX_CHUNK_SIZE + 48, XDR_ENCODE);

  /* Serialize the chunk. */
  chunk.cancel = cancel;
  chunk.data.data_len = buflen;
  chunk.data.data_val = (char *) buf;

  if (!xdr_guestfs_chunk (&xdr, &chunk)) {
    error (g, _("xdr_guestfs_chunk failed (buf = %p, buflen = %zu)"),
           buf, buflen);
    xdr_destroy (&xdr);
    goto cleanup1;
  }

  len = xdr_getpos (&xdr);
  xdr_destroy (&xdr);

  /* Reduce the size of the outgoing message buffer to the real length. */
  msg_out = safe_realloc (g, msg_out, len + 4);
  msg_out_size = len + 4;

  xdrmem_create (&xdr, msg_out, 4, XDR_ENCODE);
  xdr_uint32_t (&xdr, &len);

  r = guestfs___send_to_daemon (g, msg_out, msg_out_size);

  /* Did the daemon send a cancellation message? */
  if (r == -2) {
    debug (g, "got daemon cancellation");
    return -2;
  }

  if (r == -1)
    goto cleanup1;

  free (msg_out);

  return 0;

 cleanup1:
  free (msg_out);
  return -1;
}
コード例 #3
0
ファイル: proto.c プロジェクト: msmhrt/libguestfs
/* Returns -1 = error, 0 = EOF, > 0 = more data */
static ssize_t
receive_file_data (guestfs_h *g, void **buf_r)
{
  int r;
  void *buf;
  uint32_t len;
  XDR xdr;
  guestfs_chunk chunk;

  r = guestfs___recv_from_daemon (g, &len, &buf);
  if (r == -1) {
    error (g, _("receive_file_data: parse error in reply callback"));
    return -1;
  }

  if (len == GUESTFS_LAUNCH_FLAG || len == GUESTFS_CANCEL_FLAG) {
    error (g, _("receive_file_data: unexpected flag received when reading file chunks"));
    return -1;
  }

  memset (&chunk, 0, sizeof chunk);

  xdrmem_create (&xdr, buf, len, XDR_DECODE);
  if (!xdr_guestfs_chunk (&xdr, &chunk)) {
    error (g, _("failed to parse file chunk"));
    free (buf);
    return -1;
  }
  xdr_destroy (&xdr);
  /* After decoding, the original buffer is no longer used. */
  free (buf);

  if (chunk.cancel) {
    if (g->user_cancel) {
      error (g, _("operation cancelled by user"));
      g->last_errnum = EINTR;
    }
    else
      error (g, _("file receive cancelled by daemon"));
    free (chunk.data.data_val);
    return -1;
  }

  if (chunk.data.data_len == 0) { /* end of transfer */
    free (chunk.data.data_val);
    return 0;
  }

  if (buf_r) *buf_r = chunk.data.data_val;
  else free (chunk.data.data_val); /* else caller frees */

  return chunk.data.data_len;
}
コード例 #4
0
ファイル: proto.c プロジェクト: AlphaStaxLLC/libguestfs
/**
 * Receive a chunk of file data.
 *
 * Returns C<-1> = error, C<0> = EOF, C<E<gt>0> = more data
 */
static ssize_t
receive_file_data (guestfs_h *g, void **buf_r)
{
  int r;
  CLEANUP_FREE void *buf = NULL;
  uint32_t len;
  XDR xdr;
  guestfs_chunk chunk;

  r = guestfs_int_recv_from_daemon (g, &len, &buf);
  if (r == -1)
    return -1;

  if (len == GUESTFS_LAUNCH_FLAG || len == GUESTFS_CANCEL_FLAG) {
    error (g, _("receive_file_data: unexpected flag received when reading file chunks"));
    return -1;
  }

  memset (&chunk, 0, sizeof chunk);

  xdrmem_create (&xdr, buf, len, XDR_DECODE);
  if (!xdr_guestfs_chunk (&xdr, &chunk)) {
    error (g, _("failed to parse file chunk"));
    return -1;
  }
  xdr_destroy (&xdr);

  if (chunk.cancel) {
    if (g->user_cancel)
      guestfs_int_error_errno (g, EINTR, _("operation cancelled by user"));
    else
      error (g, _("file receive cancelled by daemon"));
    free (chunk.data.data_val);
    return -1;
  }

  if (chunk.data.data_len == 0) { /* end of transfer */
    free (chunk.data.data_val);
    return 0;
  }

  if (buf_r) *buf_r = chunk.data.data_val;
  else free (chunk.data.data_val); /* else caller frees */

  return chunk.data.data_len;
}
コード例 #5
0
ファイル: proto.c プロジェクト: rwmjones/libguestfs
static int
send_chunk (const guestfs_chunk *chunk)
{
  const size_t buf_len = GUESTFS_MAX_CHUNK_SIZE + 48;
  CLEANUP_FREE char *buf = NULL;
  char lenbuf[4];
  XDR xdr;
  uint32_t len;

  buf = malloc (buf_len);
  if (buf == NULL) {
    perror ("malloc");
    return -1;
  }

  xdrmem_create (&xdr, buf, buf_len, XDR_ENCODE);
  if (!xdr_guestfs_chunk (&xdr, (guestfs_chunk *) chunk)) {
    fprintf (stderr, "guestfsd: send_chunk: failed to encode chunk\n");
    xdr_destroy (&xdr);
    return -1;
  }

  len = xdr_getpos (&xdr);
  xdr_destroy (&xdr);

  xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE);
  xdr_u_int (&xdr, &len);
  xdr_destroy (&xdr);

  int err = (xwrite (sock, lenbuf, 4) == 0
             && xwrite (sock, buf, len) == 0 ? 0 : -1);
  if (err) {
    fprintf (stderr, "guestfsd: send_chunk: write failed\n");
    exit (EXIT_FAILURE);
  }

  return err;
}
コード例 #6
0
ファイル: proto.c プロジェクト: AlphaStaxLLC/libguestfs
static int
send_file_chunk (guestfs_h *g, int cancel, const char *buf, size_t buflen)
{
  uint32_t len;
  ssize_t r;
  guestfs_chunk chunk;
  XDR xdr;
  CLEANUP_FREE char *msg_out = NULL;
  size_t msg_out_size;

  /* Allocate the chunk buffer.  Don't use the stack to avoid
   * excessive stack usage and unnecessary copies.
   */
  msg_out = safe_malloc (g, GUESTFS_MAX_CHUNK_SIZE + 4 + 48);
  xdrmem_create (&xdr, msg_out + 4, GUESTFS_MAX_CHUNK_SIZE + 48, XDR_ENCODE);

  /* Serialize the chunk. */
  chunk.cancel = cancel;
  chunk.data.data_len = buflen;
  chunk.data.data_val = (char *) buf;

  if (!xdr_guestfs_chunk (&xdr, &chunk)) {
    error (g, _("xdr_guestfs_chunk failed (buf = %p, buflen = %zu)"),
           buf, buflen);
    xdr_destroy (&xdr);
    return -1;
  }

  len = xdr_getpos (&xdr);
  xdr_destroy (&xdr);

  /* Reduce the size of the outgoing message buffer to the real length. */
  msg_out = safe_realloc (g, msg_out, len + 4);
  msg_out_size = len + 4;

  xdrmem_create (&xdr, msg_out, 4, XDR_ENCODE);
  xdr_uint32_t (&xdr, &len);

  /* Did the daemon send a cancellation message? */
  r = check_daemon_socket (g);
  if (r == -2) {
    debug (g, "got daemon cancellation");
    return -2;
  }
  if (r == -1)
    return -1;
  if (r == 0) {
    guestfs_int_unexpected_close_error (g);
    child_cleanup (g);
    return -1;
  }

  /* Send the chunk. */
  r = g->conn->ops->write_data (g, g->conn, msg_out, msg_out_size);
  if (r == -1)
    return -1;
  if (r == 0) {
    guestfs_int_unexpected_close_error (g);
    child_cleanup (g);
    return -1;
  }

  return 0;
}
コード例 #7
0
ファイル: proto.c プロジェクト: libguestfs/libguestfs
/* Receive file chunks, repeatedly calling 'cb'. */
int
receive_file (receive_cb cb, void *opaque)
{
  guestfs_chunk chunk;
  char lenbuf[4];
  XDR xdr;
  int r;
  uint32_t len;

  for (;;) {
    CLEANUP_FREE char *buf = NULL;

    if (verbose)
      fprintf (stderr, "guestfsd: receive_file: reading length word\n");

    /* Read the length word. */
    if (xread (sock, lenbuf, 4) == -1)
      exit (EXIT_FAILURE);

    xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE);
    xdr_u_int (&xdr, &len);
    xdr_destroy (&xdr);

    if (len == GUESTFS_CANCEL_FLAG)
      continue;			/* Just ignore it. */

    if (len > GUESTFS_MESSAGE_MAX)
      error (EXIT_FAILURE, 0, "incoming message is too long (%u bytes)", len);

    buf = malloc (len);
    if (!buf) {
      perror ("malloc");
      return -1;
    }

    if (xread (sock, buf, len) == -1)
      exit (EXIT_FAILURE);

    xdrmem_create (&xdr, buf, len, XDR_DECODE);
    memset (&chunk, 0, sizeof chunk);
    if (!xdr_guestfs_chunk (&xdr, &chunk)) {
      xdr_destroy (&xdr);
      return -1;
    }
    xdr_destroy (&xdr);

    if (verbose)
      fprintf (stderr,
               "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %u, buf = %p\n",
               (unsigned) chunk.cancel,
               chunk.data.data_len, chunk.data.data_val);

    if (chunk.cancel != 0 && chunk.cancel != 1) {
      fprintf (stderr,
               "guestfsd: receive_file: chunk.cancel != [0|1] ... "
               "continuing even though we have probably lost synchronization with the library\n");
      return -1;
    }

    if (chunk.cancel) {
      if (verbose)
        fprintf (stderr,
		 "guestfsd: receive_file: received cancellation from library\n");
      xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
      return -2;
    }
    if (chunk.data.data_len == 0) {
      if (verbose)
        fprintf (stderr,
		 "guestfsd: receive_file: end of file, leaving function\n");
      xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
      return 0;			/* end of file */
    }

    /* Note that the callback can generate progress messages. */
    if (cb)
      r = cb (opaque, chunk.data.data_val, chunk.data.data_len);
    else
      r = 0;

    xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
    if (r == -1) {		/* write error */
      if (verbose)
        fprintf (stderr, "guestfsd: receive_file: write error\n");
      return -1;
    }
  }
}