Пример #1
0
static void *
start_srcthread (void *arg)
{
    struct threaddata *threaddata = arg;
    guestfs_h *srcg;
    char fdname[128];

    /* Open the source domain. */
    srcg = guestfs_create ();
    if (!srcg) {
        perror ("failed to create libguestfs handle");
        pthread_cancel (threaddata->mainthread);
        exit (EXIT_FAILURE);
    }
    if (open_guest (srcg, threaddata->src, 1) == -1) {
        pthread_cancel (threaddata->mainthread);
        exit (EXIT_FAILURE);
    }

    /* Begin the download. */
    snprintf (fdname, sizeof fdname, "/dev/fd/%d", threaddata->fd);
    if (guestfs_tar_out (srcg, threaddata->srcdir, fdname) == -1) {
        pthread_cancel (threaddata->mainthread);
        exit (EXIT_FAILURE);
    }

    /* Close the pipe; this will cause the receiver to finish the upload. */
    if (close (threaddata->fd) == -1) {
        pthread_cancel (threaddata->mainthread);
        exit (EXIT_FAILURE);
    }

    /* Clean up. */
    guestfs_close (srcg);

    return NULL;
}
Пример #2
0
int
run_copy_out (const char *cmd, size_t argc, char *argv[])
{
    if (argc < 2) {
        fprintf (stderr,
                 _("use 'copy-out <remote> [<remote>...] <localdir>' to copy files out of the image\n"));
        return -1;
    }

    /* Local directory is always the last arg. */
    const char *local = argv[argc-1];
    int nr_remotes = argc-1;

    struct stat statbuf;
    if (stat (local, &statbuf) == -1 ||
            ! (S_ISDIR (statbuf.st_mode))) {
        fprintf (stderr, _("copy-out: target '%s' is not a directory\n"), local);
        return -1;
    }

    /* Download each remote one at a time using tar-out. */
    int i, r;
    for (i = 0; i < nr_remotes; ++i) {
        char *remote = argv[i];

        /* Allow win:... prefix on remotes. */
        remote = win_prefix (remote);
        if (remote == NULL)
            return -1;

        /* If the remote is a file, download it.  If it's a directory,
         * create the directory in local first before using tar-out.
         */
        r = guestfs_is_file (g, remote);
        if (r == -1) {
            free (remote);
            return -1;
        }
        if (r == 1) {               /* is file */
            char buf[PATH_MAX];
            const char *basename;
            if (split_path (buf, sizeof buf, remote, NULL, &basename) == -1) {
                free (remote);
                return -1;
            }

            char filename[PATH_MAX];
            snprintf (filename, sizeof filename, "%s/%s", local, basename);
            if (guestfs_download (g, remote, filename) == -1) {
                free (remote);
                return -1;
            }
        }
        else {                      /* not a regular file */
            r = guestfs_is_dir (g, remote);
            if (r == -1) {
                free (remote);
                return -1;
            }

            if (r == 0) {
                fprintf (stderr, _("copy-out: '%s' is not a file or directory\n"),
                         remote);
                free (remote);
                return -1;
            }

            char buf[PATH_MAX];
            const char *basename;
            if (split_path (buf, sizeof buf, remote, NULL, &basename) == -1) {
                free (remote);
                return -1;
            }

            struct fd_pid fdpid = make_tar_output (local, basename);
            if (fdpid.fd == -1) {
                free (remote);
                return -1;
            }

            char fdbuf[64];
            snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fdpid.fd);

            int r = guestfs_tar_out (g, remote, fdbuf);

            if (close (fdpid.fd) == -1) {
                perror ("close (tar-output subprocess)");
                free (remote);
                r = -1;
            }

            int status;
            if (waitpid (fdpid.pid, &status, 0) == -1) {
                perror ("wait (tar-output subprocess)");
                free (remote);
                return -1;
            }
            if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0)) {
                free (remote);
                return -1;
            }

            if (r == -1) {
                free (remote);
                return -1;
            }
        }

        free (remote);
    }

    return 0;
}
Пример #3
0
int
guestfs_impl_copy_out (guestfs_h *g,
                       const char *remotepath, const char *localdir)
{
  struct stat statbuf;
  int r;

  if (stat (localdir, &statbuf) == -1 ||
      ! (S_ISDIR (statbuf.st_mode))) {
    error (g, _("target '%s' is not a directory"), localdir);
    return -1;
  }

  /* If the remote is a file, download it.  If it's a directory,
   * create the directory in localdir first before using tar-out.
   */
  r = guestfs_is_file (g, remotepath);
  if (r == -1)
    return -1;

  if (r == 1) {               /* is file */
    CLEANUP_FREE char *filename = NULL;
    size_t buf_len = strlen (remotepath) + 1;
    CLEANUP_FREE char *buf = safe_malloc (g, buf_len);
    const char *basename;

    if (split_path (g, buf, buf_len, remotepath, NULL, &basename) == -1)
      return -1;

    if (asprintf (&filename, "%s/%s", localdir, basename) == -1) {
      perrorf (g, "asprintf");
      return -1;
    }
    if (guestfs_download (g, remotepath, filename) == -1)
      return -1;
  } else {                    /* not a regular file */
    CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
    struct copy_out_child_data data;
    char fdbuf[64];
    int fd;

    r = guestfs_is_dir (g, remotepath);
    if (r == -1)
      return -1;

    if (r == 0) {
      error (g, _("'%s' is not a file or directory"), remotepath);
      return -1;
    }

    size_t buf_len = strlen (remotepath) + 1;
    CLEANUP_FREE char *buf = safe_malloc (g, buf_len);
    const char *basename;
    if (split_path (g, buf, buf_len, remotepath, NULL, &basename) == -1)
      return -1;

    /* RHBZ#845522: If remotepath == "/" then basename would be an empty
     * string.  Replace it with "." so that make_tar_output writes
     * to "localdir/."
     */
    if (STREQ (basename, ""))
      basename = ".";

    data.localdir = localdir;
    data.basename = basename;

    guestfs_int_cmd_set_child_callback (cmd, &child_setup, &data);

    guestfs_int_cmd_add_arg (cmd, "tar");
    guestfs_int_cmd_add_arg (cmd, "-xf");
    guestfs_int_cmd_add_arg (cmd, "-");

    guestfs_int_cmd_clear_capture_errors (cmd);

    fd = guestfs_int_cmd_pipe_run (cmd, "w");
    if (fd == -1)
      return -1;

    snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fd);

    r = guestfs_tar_out (g, remotepath, fdbuf);

    if (close (fd) == -1) {
      perrorf (g, "close (tar-output subprocess)");
      return -1;
    }

    r = guestfs_int_cmd_pipe_wait (cmd);
    if (r == -1)
      return -1;
    if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
      CLEANUP_FREE char *errors = guestfs_int_cmd_get_pipe_errors (cmd);
      if (errors == NULL)
        return -1;
      error (g, "tar subprocess failed: %s", errors);
      return -1;
    }
  }

  return 0;
}