예제 #1
0
int
guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir)
{
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
  int fd;
  int r;
  char fdbuf[64];
  size_t buf_len = strlen (localpath) + 1;
  char buf[buf_len];
  const char *dirname, *basename;

  int remote_is_dir = guestfs_is_dir (g, remotedir);
  if (remote_is_dir == -1)
    return -1;

  if (!remote_is_dir) {
    error (g, _("target '%s' is not a directory"), remotedir);
    return -1;
  }

  if (split_path (g, buf, buf_len, localpath, &dirname, &basename) == -1)
    return -1;

  guestfs_int_cmd_add_arg (cmd, "tar");
  if (dirname) {
    guestfs_int_cmd_add_arg (cmd, "-C");
    guestfs_int_cmd_add_arg (cmd, dirname);
  }
  guestfs_int_cmd_add_arg (cmd, "-cf");
  guestfs_int_cmd_add_arg (cmd, "-");
  guestfs_int_cmd_add_arg (cmd, basename);

  r = guestfs_int_cmd_run_async (cmd, NULL, NULL, &fd, NULL);
  if (r == -1)
    return -1;

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

  r = guestfs_tar_in (g, fdbuf, remotedir);

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

  r = guestfs_int_cmd_wait (cmd);
  if (r == -1)
    return -1;
  if (!(WIFEXITED (r) && WEXITSTATUS (r) == 0))
    return -1;

  return 0;
}
예제 #2
0
파일: copy.c 프로젝트: msmhrt/libguestfs
int
run_copy_in (const char *cmd, size_t argc, char *argv[])
{
    if (argc < 2) {
        fprintf (stderr,
                 _("use 'copy-in <local> [<local>...] <remotedir>' to copy files into the image\n"));
        return -1;
    }

    /* Remote directory is always the last arg. */
    char *remote = argv[argc-1];

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

    int nr_locals = argc-1;

    int remote_is_dir = guestfs_is_dir (g, remote);
    if (remote_is_dir == -1) {
        free (remote);
        return -1;
    }

    if (!remote_is_dir) {
        fprintf (stderr, _("copy-in: target '%s' is not a directory\n"), remote);
        free (remote);
        return -1;
    }

    /* Upload each local one at a time using tar-in. */
    int i;
    for (i = 0; i < nr_locals; ++i) {
        struct fd_pid fdpid = make_tar_from_local (argv[i]);
        if (fdpid.fd == -1) {
            free (remote);
            return -1;
        }

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

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

        if (close (fdpid.fd) == -1) {
            perror ("close (tar-from-local subprocess)");
            r = -1;
        }

        int status;
        if (waitpid (fdpid.pid, &status, 0) == -1) {
            perror ("wait (tar-from-local 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_in (guestfs_h *g,
                      const char *localpath, const char *remotedir)
{
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
  int fd;
  int r;
  char fdbuf[64];
  size_t buf_len = strlen (localpath) + 1;
  CLEANUP_FREE char *buf = safe_malloc (g, buf_len);
  const char *dirname, *basename;
  struct stat statbuf;

  if (stat (localpath, &statbuf) == -1) {
    error (g, _("source '%s' does not exist (or cannot be read)"), localpath);
    return -1;
  }

  int remote_is_dir = guestfs_is_dir (g, remotedir);
  if (remote_is_dir == -1)
    return -1;

  if (!remote_is_dir) {
    error (g, _("target '%s' is not a directory"), remotedir);
    return -1;
  }

  if (split_path (g, buf, buf_len, localpath, &dirname, &basename) == -1)
    return -1;

  guestfs_int_cmd_add_arg (cmd, "tar");
  if (dirname) {
    guestfs_int_cmd_add_arg (cmd, "-C");
    guestfs_int_cmd_add_arg (cmd, dirname);
  }
  guestfs_int_cmd_add_arg (cmd, "-cf");
  guestfs_int_cmd_add_arg (cmd, "-");
  guestfs_int_cmd_add_arg (cmd, basename);

  guestfs_int_cmd_clear_capture_errors (cmd);

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

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

  r = guestfs_tar_in (g, fdbuf, remotedir);

  if (close (fd) == -1) {
    perrorf (g, "close (tar 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;
}
예제 #4
0
int
main (int argc, char *argv[])
{
    const char *src, *srcdir, *dest, *destdir;
    guestfs_h *destg;
    int fd[2];
    pthread_t srcthread;
    struct threaddata threaddata;
    int err;
    char fdname[128];
    struct timeval start_t, end_t;
    int64_t ms;

    if (argc != 5) {
        usage ();
        exit (EXIT_FAILURE);
    }

    src = argv[1];
    srcdir = argv[2];
    dest = argv[3];
    destdir = argv[4];

    /* Instead of downloading to local disk and uploading, we are going
     * to connect the source download and destination upload using a
     * pipe.  Create that pipe.
     */
    if (pipe (fd) == -1) {
        perror ("pipe");
        exit (EXIT_FAILURE);
    }

    /* We don't want the pipe to be passed to subprocesses. */
    if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) == -1 ||
            fcntl (fd[1], F_SETFD, FD_CLOEXEC) == -1) {
        perror ("fcntl");
        exit (EXIT_FAILURE);
    }

    /* The libguestfs API is synchronous, so if we want to use two
     * handles concurrently, then we have to have two threads.  In this
     * case the main thread (this one) is handling the destination
     * domain (uploading), and we create one more thread to handle the
     * source domain (downloading).
     */
    threaddata.src = src;
    threaddata.srcdir = srcdir;
    threaddata.fd = fd[1];
    threaddata.mainthread = pthread_self ();
    err = pthread_create (&srcthread, NULL, start_srcthread, &threaddata);
    if (err != 0) {
        fprintf (stderr, "pthread_create: %s\n", strerror (err));
        exit (EXIT_FAILURE);
    }

    /* Open the destination domain. */
    destg = guestfs_create ();
    if (!destg) {
        perror ("failed to create libguestfs handle");
        pthread_cancel (srcthread);
        exit (EXIT_FAILURE);
    }
    if (open_guest (destg, dest, 0) == -1) {
        pthread_cancel (srcthread);
        exit (EXIT_FAILURE);
    }

    gettimeofday (&start_t, NULL);

    /* Begin the upload. */
    snprintf (fdname, sizeof fdname, "/dev/fd/%d", fd[0]);
    if (guestfs_tar_in (destg, fdname, destdir) == -1) {
        pthread_cancel (srcthread);
        exit (EXIT_FAILURE);
    }

    /* Close our end of the pipe.  The other thread will close the
     * other side of the pipe.
     */
    close (fd[0]);

    /* Wait for the other thread to finish. */
    err = pthread_join (srcthread, NULL);
    if (err != 0) {
        fprintf (stderr, "pthread_join: %s\n", strerror (err));
        exit (EXIT_FAILURE);
    }

    /* Clean up. */
    if (guestfs_shutdown (destg) == -1)
        exit (EXIT_FAILURE);
    guestfs_close (destg);

    gettimeofday (&end_t, NULL);

    /* Print the elapsed time. */
    ms = timeval_diff (&start_t, &end_t);
    printf ("copy finished, elapsed time (excluding launch) was "
            "%" PRIi64 ".%03" PRIi64 " s\n",
            ms / 1000, ms % 1000);

    exit (EXIT_SUCCESS);
}