recipes: Remove two C file dependencies which are not actually used in the POD.
[libguestfs.git] / fish / copy.c
index 789e430..c1c1b47 100644 (file)
@@ -1,5 +1,5 @@
 /* guestfish - the filesystem interactive shell
- * Copyright (C) 2010 Red Hat Inc.
+ * Copyright (C) 2010-2011 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
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <assert.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 
 static int make_tar_from_local (const char *local);
 static int make_tar_output (const char *local, const char *basename);
-static int split_path (char *buf, size_t buf_size, const char *path, char **dirname, char **basename);
+static int split_path (char *buf, size_t buf_size, const char *path, const char **dirname, const char **basename);
 
 int
-do_copy_in (const char *cmd, int argc, char *argv[])
+run_copy_in (const char *cmd, size_t argc, char *argv[])
 {
   if (argc < 2) {
     fprintf (stderr,
@@ -43,15 +43,24 @@ do_copy_in (const char *cmd, int argc, char *argv[])
   }
 
   /* Remote directory is always the last arg. */
-  const char *remote = argv[argc-1];
+  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)
+  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;
   }
 
@@ -59,8 +68,10 @@ do_copy_in (const char *cmd, int argc, char *argv[])
   int i;
   for (i = 0; i < nr_locals; ++i) {
     int fd = make_tar_from_local (argv[i]);
-    if (fd == -1)
+    if (fd == -1) {
+      free (remote);
       return -1;
+    }
 
     char fdbuf[64];
     snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fd);
@@ -75,15 +86,22 @@ do_copy_in (const char *cmd, int argc, char *argv[])
     int status;
     if (wait (&status) == -1) {
       perror ("wait (tar-from-local subprocess)");
+      free (remote);
       return -1;
     }
-    if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0))
+    if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0)) {
+      free (remote);
       return -1;
+    }
 
-    if (r == -1)
+    if (r == -1) {
+      free (remote);
       return -1;
+    }
   }
 
+  free (remote);
+
   return 0;
 }
 
@@ -119,7 +137,7 @@ make_tar_from_local (const char *local)
   close (fd[1]);
 
   char buf[PATH_MAX];
-  char *dirname, *basename;
+  const char *dirname, *basename;
   if (split_path (buf, sizeof buf, local, &dirname, &basename) == -1)
     _exit (EXIT_FAILURE);
 
@@ -132,7 +150,7 @@ make_tar_from_local (const char *local)
  */
 static int
 split_path (char *buf, size_t buf_size,
-            const char *path, char **dirname, char **basename)
+            const char *path, const char **dirname, const char **basename)
 {
   size_t len = strlen (path);
   if (len == 0 || len > buf_size - 1) {
@@ -148,11 +166,14 @@ split_path (char *buf, size_t buf_size,
   }
 
   char *p = strrchr (buf, '/');
-  if (p && p > buf) {
+  if (p && p > buf) {           /* "foo/bar" */
     *p = '\0';
     p++;
     if (dirname) *dirname = buf;
     if (basename) *basename = p;
+  } else if (p && p == buf) {   /* "/foo" */
+    if (dirname) *dirname = "/";
+    if (basename) *basename = buf+1;
   } else {
     if (dirname) *dirname = NULL;
     if (basename) *basename = buf;
@@ -174,7 +195,7 @@ tar_create (const char *dir, const char *path)
 }
 
 int
-do_copy_out (const char *cmd, int argc, char *argv[])
+run_copy_out (const char *cmd, size_t argc, char *argv[])
 {
   if (argc < 2) {
     fprintf (stderr,
@@ -189,71 +210,99 @@ do_copy_out (const char *cmd, int argc, char *argv[])
   struct stat statbuf;
   if (stat (local, &statbuf) == -1 ||
       ! (S_ISDIR (statbuf.st_mode))) {
-    fprintf (stderr, _("copy-in: target '%s' is not a directory\n"), local);
+    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, argv[i]);
-    if (r == -1)
+    r = guestfs_is_file (g, remote);
+    if (r == -1) {
+      free (remote);
       return -1;
+    }
     if (r == 1) {               /* is file */
       char buf[PATH_MAX];
-      char *basename;
-      if (split_path (buf, sizeof buf, argv[i], NULL, &basename) == -1)
+      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, argv[i], filename) == -1)
+      if (guestfs_download (g, remote, filename) == -1) {
+        free (remote);
         return -1;
+      }
     }
     else {                      /* not a regular file */
-      r = guestfs_is_dir (g, argv[i]);
-      if (r == -1)
+      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"),
-                 argv[i]);
+                 remote);
+        free (remote);
         return -1;
       }
 
       char buf[PATH_MAX];
-      char *basename;
-      if (split_path (buf, sizeof buf, argv[i], NULL, &basename) == -1)
+      const char *basename;
+      if (split_path (buf, sizeof buf, remote, NULL, &basename) == -1) {
+        free (remote);
         return -1;
+      }
 
       int fd = make_tar_output (local, basename);
-      if (fd == -1)
+      if (fd == -1) {
+        free (remote);
         return -1;
+      }
 
       char fdbuf[64];
       snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fd);
 
-      int r = guestfs_tar_out (g, argv[i], fdbuf);
+      int r = guestfs_tar_out (g, remote, fdbuf);
 
       if (close (fd) == -1) {
         perror ("close (tar-output subprocess)");
+        free (remote);
         r = -1;
       }
 
       int status;
       if (wait (&status) == -1) {
         perror ("wait (tar-output subprocess)");
+        free (remote);
         return -1;
       }
-      if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0))
+      if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0)) {
+        free (remote);
         return -1;
+      }
 
-      if (r == -1)
+      if (r == -1) {
+        free (remote);
         return -1;
+      }
     }
+
+    free (remote);
   }
 
   return 0;