Example #1
0
int
guestfs___recv_file (guestfs_h *g, const char *filename)
{
  void *buf;
  int fd, r;

  g->user_cancel = 0;

  fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
  if (fd == -1) {
    perrorf (g, "open: %s", filename);
    goto cancel;
  }

  fadvise_sequential (fd);

  /* Receive the file in chunked encoding. */
  while ((r = receive_file_data (g, &buf)) > 0) {
    if (xwrite (fd, buf, r) == -1) {
      perrorf (g, "%s: write", filename);
      free (buf);
      close (fd);
      goto cancel;
    }
    free (buf);

    if (g->user_cancel) {
      close (fd);
      goto cancel;
    }
  }

  if (r == -1) {
    error (g, _("%s: error in chunked encoding"), filename);
    close (fd);
    return -1;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", filename);
    return -1;
  }

  return 0;

 cancel: ;
  /* Send cancellation message to daemon, then wait until it
   * cancels (just throwing away data).
   */
  XDR xdr;
  char fbuf[4];
  uint32_t flag = GUESTFS_CANCEL_FLAG;

  debug (g, "%s: waiting for daemon to acknowledge cancellation",
         __func__);

  xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE);
  xdr_uint32_t (&xdr, &flag);
  xdr_destroy (&xdr);

  if (xwrite (g->sock, fbuf, sizeof fbuf) == -1) {
    perrorf (g, _("write to daemon socket"));
    return -1;
  }

  while (receive_file_data (g, NULL) > 0)
    ;                           /* just discard it */

  return -1;
}
Example #2
0
/**
 * Returns C<-1> = error, C<0> = EOF, C<E<gt>0> = more data
 */
int
guestfs_int_recv_file (guestfs_h *g, const char *filename)
{
  void *buf;
  int fd, r;

  g->user_cancel = 0;

  /* If downloading to /dev/stdout or /dev/stderr, dup the file
   * descriptor instead of reopening the file, so that redirected
   * stdout/stderr work properly.
   */
  if (STREQ (filename, "/dev/stdout"))
    fd = dup (1);
  else if (STREQ (filename, "/dev/stderr"))
    fd = dup (2);
  else
    fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0666);
  if (fd == -1) {
    perrorf (g, "%s", filename);
    goto cancel;
  }

  guestfs_int_fadvise_sequential (fd);

  /* Receive the file in chunked encoding. */
  while ((r = receive_file_data (g, &buf)) > 0) {
    if (xwrite (fd, buf, r) == -1) {
      perrorf (g, "%s: write", filename);
      free (buf);
      close (fd);
      goto cancel;
    }
    free (buf);

    if (g->user_cancel) {
      close (fd);
      goto cancel;
    }
  }

  if (r == -1) {
    close (fd);
    return -1;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", filename);
    return -1;
  }

  return 0;

 cancel: ;
  /* Send cancellation message to daemon, then wait until it
   * cancels (just throwing away data).
   */
  XDR xdr;
  char fbuf[4];
  uint32_t flag = GUESTFS_CANCEL_FLAG;

  debug (g, "%s: waiting for daemon to acknowledge cancellation",
         __func__);

  xdrmem_create (&xdr, fbuf, sizeof fbuf, XDR_ENCODE);
  xdr_uint32_t (&xdr, &flag);
  xdr_destroy (&xdr);

  if (g->conn->ops->write_data (g, g->conn, fbuf, sizeof fbuf) == -1) {
    perrorf (g, _("write to daemon socket"));
    return -1;
  }

  while (receive_file_data (g, NULL) > 0)
    ;                           /* just discard it */

  return -1;
}