Blame SOURCES/0013-daemon-tar-Use-a-temporary-file-to-pass-excludes-to-.patch

022f11
From a9492cf1a031ddcec9d2e6f879731bc49122e7e1 Mon Sep 17 00:00:00 2001
022f11
From: "Richard W.M. Jones" <rjones@redhat.com>
022f11
Date: Thu, 29 Aug 2013 13:26:51 +0100
022f11
Subject: [PATCH] daemon: tar: Use a temporary file to pass excludes to tar
022f11
 command (RHBZ#1001875).
022f11
022f11
Use tar -X option instead of tar --exclude=... option.
022f11
022f11
(cherry picked from commit 91c162586cc2170ea224016307016153f3d081b5)
022f11
---
022f11
 daemon/tar.c | 78 +++++++++++++++++++++++++++++++++++-------------------------
022f11
 1 file changed, 46 insertions(+), 32 deletions(-)
022f11
022f11
diff --git a/daemon/tar.c b/daemon/tar.c
022f11
index 51f82f8..da19de7 100644
022f11
--- a/daemon/tar.c
022f11
+++ b/daemon/tar.c
022f11
@@ -239,41 +239,60 @@ do_txz_in (const char *dir)
022f11
   return do_tar_in (dir, "xz");
022f11
 }
022f11
 
022f11
-/* Turn list 'excludes' into list of " --excludes=..." strings, all
022f11
- * properly quoted.  Caller must free the returned string.
022f11
+/* Turn list 'excludes' into a temporary file, and return a string
022f11
+ * containing the temporary file name.  Caller must unlink the file
022f11
+ * and free the string.
022f11
  */
022f11
 static char *
022f11
-make_excludes_args (char *const *excludes)
022f11
+make_exclude_from_file (char *const *excludes)
022f11
 {
022f11
-  DECLARE_STRINGSBUF (strings);
022f11
   size_t i;
022f11
-  char *s, *ret;
022f11
+  int fd;
022f11
+  char template[] = "/tmp/excludesXXXXXX";
022f11
+  char *ret;
022f11
+
022f11
+  fd = mkstemp (template);
022f11
+  if (fd == -1) {
022f11
+    reply_with_perror ("mkstemp");
022f11
+    return NULL;
022f11
+  }
022f11
 
022f11
   for (i = 0; excludes[i] != NULL; ++i) {
022f11
-    if (asprintf_nowarn (&s, " --exclude=%Q", excludes[i]) == -1) {
022f11
-      reply_with_perror ("asprintf");
022f11
-      free_stringslen (strings.argv, strings.size);
022f11
-      return NULL;
022f11
+    if (strchr (excludes[i], '\n')) {
022f11
+      reply_with_error ("tar-out: excludes file patterns cannot contain \\n character");
022f11
+      goto error;
022f11
     }
022f11
-    if (add_string_nodup (&strings, s) == -1) {
022f11
-      free (s);
022f11
-      return NULL;
022f11
+
022f11
+    if (xwrite (fd, excludes[i], strlen (excludes[i])) == -1 ||
022f11
+        xwrite (fd, "\n", 1) == -1) {
022f11
+      reply_with_perror ("write");
022f11
+      goto error;
022f11
     }
022f11
-  }
022f11
 
022f11
-  if (end_stringsbuf (&strings) == -1)
022f11
-    return NULL;
022f11
+    if (verbose)
022f11
+      fprintf (stderr, "tar-out: adding excludes pattern '%s'\n", excludes[i]);
022f11
+  }
022f11
 
022f11
-  ret = concat_strings (strings.argv);
022f11
-  if (!ret) {
022f11
-    reply_with_perror ("concat");
022f11
-    free_stringslen (strings.argv, strings.size);
022f11
-    return NULL;
022f11
+  if (close (fd) == -1) {
022f11
+    reply_with_perror ("close");
022f11
+    fd = -1;
022f11
+    goto error;
022f11
   }
022f11
+  fd = -1;
022f11
 
022f11
-  free_stringslen (strings.argv, strings.size);
022f11
+  ret = strdup (template);
022f11
+  if (ret == NULL) {
022f11
+    reply_with_perror ("strdup");
022f11
+    goto error;
022f11
+  }
022f11
 
022f11
   return ret;
022f11
+
022f11
+ error:
022f11
+  if (fd >= 0)
022f11
+    close (fd);
022f11
+  unlink (template);
022f11
+  return NULL;
022f11
 }
022f11
 
022f11
 /* Has one FileOut parameter. */
022f11
@@ -287,7 +306,7 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
022f11
   const char *filter;
022f11
   int r;
022f11
   FILE *fp;
022f11
-  CLEANUP_FREE char *excludes_args = NULL;
022f11
+  CLEANUP_UNLINK_FREE char *exclude_from_file = NULL;
022f11
   CLEANUP_FREE char *cmd = NULL;
022f11
   char buffer[GUESTFS_MAX_CHUNK_SIZE];
022f11
 
022f11
@@ -313,15 +332,9 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
022f11
     numericowner = 0;
022f11
 
022f11
   if ((optargs_bitmask & GUESTFS_TAR_OUT_EXCLUDES_BITMASK)) {
022f11
-    excludes_args = make_excludes_args (excludes);
022f11
-    if (!excludes_args)
022f11
-      return -1;
022f11
-  } else {
022f11
-    excludes_args = strdup ("");
022f11
-    if (excludes_args == NULL) {
022f11
-      reply_with_perror ("strdup");
022f11
+    exclude_from_file = make_exclude_from_file (excludes);
022f11
+    if (!exclude_from_file)
022f11
       return -1;
022f11
-    }
022f11
   }
022f11
 
022f11
   /* Check the filename exists and is a directory (RHBZ#908322). */
022f11
@@ -342,11 +355,12 @@ do_tar_out (const char *dir, const char *compress, int numericowner,
022f11
   }
022f11
 
022f11
   /* "tar -C /sysroot%s -cf - ." but we have to quote the dir. */
022f11
-  if (asprintf_nowarn (&cmd, "%s -C %Q%s%s%s -cf - .",
022f11
+  if (asprintf_nowarn (&cmd, "%s -C %Q%s%s%s%s -cf - .",
022f11
                        str_tar,
022f11
                        buf, filter,
022f11
                        numericowner ? " --numeric-owner" : "",
022f11
-                       excludes_args) == -1) {
022f11
+                       exclude_from_file ? " -X " : "",
022f11
+                       exclude_from_file ? exclude_from_file : "") == -1) {
022f11
     reply_with_perror ("asprintf");
022f11
     return -1;
022f11
   }
022f11
-- 
022f11
1.8.3.1
022f11