EA.diff   [plain text]


--- src/create.c.orig	2007-06-01 03:17:10.000000000 -0700
+++ src/create.c	2008-08-18 19:10:08.000000000 -0700
@@ -26,6 +26,15 @@
 #include "common.h"
 #include <hash.h>
 
+#ifdef __APPLE__
+#include <copyfile.h>
+#include <libgen.h>
+#include <paths.h>
+
+int copyfile_on = 0;
+char *copyfile_fname = NULL;
+#endif
+
 struct link
   {
     dev_t dev;
@@ -1485,9 +1494,18 @@
   if (interactive_option && !confirm ("add", p))
     return;
 
+  if (copyfile_on)
+  {
+    assign_string (&st->orig_file_name, copyfile_fname);
+    assign_string (&st->file_name,
+                   safer_name_suffix (copyfile_fname, false, absolute_names_option));
+  }
+  else
+  {
   assign_string (&st->orig_file_name, p);
   assign_string (&st->file_name,
                  safer_name_suffix (p, false, absolute_names_option));
+  }
 
   transform_name (&st->file_name);
 
@@ -1777,6 +1795,40 @@
 dump_file (const char *p, int top_level, dev_t parent_device)
 {
   struct tar_stat_info st;
+
+#ifdef __APPLE__
+	if (!getenv(COPYFILE_DISABLE_VAR) && !strncmp(basename(p), "._", 2)) {
+		return;
+	}
+
+  if (!getenv(COPYFILE_DISABLE_VAR) && strncmp(basename(p), "._", 2))
+  {
+	char *tmpdir = getenv("TMPDIR"), *md_p;
+	asprintf(&md_p, "%s/tar.md.XXXXXXXX", tmpdir ? tmpdir : _PATH_TMP);
+	asprintf(&copyfile_fname, "%s/._%s", dirname(p), basename(p));
+
+	if (copyfile(p, NULL, 0, COPYFILE_CHECK | COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR))
+	{
+	    copyfile_on = 1;
+	    tar_stat_init (&st);
+
+	    if(mktemp(md_p))
+	    {
+		if (copyfile(p, md_p, 0, COPYFILE_PACK | COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR) == 0)
+			dump_file0 (&st, md_p, top_level, parent_device);
+		else
+			WARN((0, 0, "copyfile pack (%s) failed: %s", p, strerror(errno)));
+	    }
+
+	    tar_stat_destroy (&st);
+	    unlink(md_p);
+	    free(copyfile_fname);
+	    copyfile_on = 0;
+	}
+	free(md_p);
+  }
+#endif
+
   tar_stat_init (&st);
   dump_file0 (&st, p, top_level, parent_device);
   if (listed_incremental_option)
--- src/extract.c.orig	2007-06-08 01:14:42.000000000 -0700
+++ src/extract.c	2008-08-18 19:10:08.000000000 -0700
@@ -27,6 +27,19 @@
 
 #include "common.h"
 
+#ifdef __APPLE__
+#include <libgen.h>
+#include <sys/queue.h>
+#include <copyfile.h>
+struct copyfile_list_entry_t {
+    char *src;
+    char *dst;
+    char *tmp;
+    LIST_ENTRY(copyfile_list_entry_t) link;
+} *cle;
+extern LIST_HEAD(copyfile_list_t, copyfile_list_entry_t) copyfile_list;
+#endif
+
 static bool we_are_root;	/* true if our effective uid == 0 */
 static mode_t newdir_umask;	/* umask when creating new directories */
 static mode_t current_umask;	/* current umask (which is set to 0 if -p) */
@@ -1200,6 +1213,9 @@
 {
   char typeflag;
   tar_extractor_t fun;
+#ifdef __APPLE__
+  struct copyfile_list_entry_t *cle = NULL;
+#endif
 
   set_next_block_after (current_header);
   decode_header (current_header, &current_stat_info, &current_format, 1);
@@ -1240,7 +1256,31 @@
 
   if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun))
     {
-      if (fun && (*fun) (current_stat_info.file_name, typeflag)
+#ifdef __APPLE__
+		if (strncmp(basename(current_stat_info.file_name), "._", 2) == 0) {
+			if ((cle = calloc(1, sizeof(struct copyfile_list_entry_t))) == NULL)
+				goto err;
+			if ((cle->src = strdup(current_stat_info.file_name)) == NULL)
+				goto err;
+			if (asprintf(&cle->tmp, "%s.XXX", current_stat_info.file_name) == -1)
+				goto err;
+			if (mktemp(cle->tmp) == NULL)
+				goto err;
+			if (asprintf(&cle->dst, "%s/%s", dirname(current_stat_info.file_name), basename(current_stat_info.file_name) + 2) != -1)
+				LIST_INSERT_HEAD(&copyfile_list, cle, link);
+			else {
+err:
+				if (cle->src) free(cle->src);
+				if (cle->dst) free(cle->dst);
+				if (cle->tmp) free(cle->tmp);
+				if (cle) {
+					free(cle);
+					cle = NULL;
+				}
+			}
+		}
+#endif
+      if (fun && (*fun) (cle ? cle->tmp : current_stat_info.file_name, typeflag)
 	  && backup_option)
 	undo_last_backup ();
     }
--- src/list.c.orig	2007-06-08 01:14:42.000000000 -0700
+++ src/list.c	2008-08-18 19:10:08.000000000 -0700
@@ -23,6 +23,19 @@
 #include <inttostr.h>
 #include <quotearg.h>
 
+#ifdef __APPLE__
+#include <copyfile.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+struct copyfile_list_entry_t {
+    char *src;
+    char *dst;
+    char *tmp;
+    LIST_ENTRY(copyfile_list_entry_t) link;
+} *cle;
+LIST_HEAD(copyfile_list_t, copyfile_list_entry_t) copyfile_list;
+#endif
+
 #include "common.h"
 
 #define max(a, b) ((a) < (b) ? (b) : (a))
@@ -68,6 +81,12 @@
   enum read_header prev_status;
   struct timespec mtime;
 
+#ifdef __APPLE__
+  int disable_copyfile = (getenv(COPYFILE_DISABLE_VAR) != NULL);
+  struct copyfile_list_entry_t *cle;
+  LIST_INIT(&copyfile_list);
+#endif
+
   base64_init ();
   name_gather ();
 
@@ -195,6 +214,28 @@
     }
   while (!all_names_found (&current_stat_info));
 
+#ifdef __APPLE__
+      LIST_FOREACH(cle, &copyfile_list, link)
+	{
+	  if(!disable_copyfile && copyfile(cle->tmp, cle->dst, 0, COPYFILE_UNPACK | COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR) == 0)
+	    {
+	      unlink(cle->tmp);
+	    }
+	  else
+	    {
+	      if (!disable_copyfile)
+		{
+		  WARN((0, 0, "copyfile unpack (%s) failed: %s", cle->dst, strerror(errno)));
+		}
+	      rename(cle->tmp, cle->src);
+	    }
+
+	  free(cle->tmp);
+	  free(cle->dst);
+	  free(cle->src);
+	}
+#endif
+
   close_archive ();
   names_notfound ();		/* print names not found */
 }
--- lib/version-etc.c.orig	2008-08-18 19:17:17.000000000 -0700
+++ lib/version-etc.c	2008-08-18 19:19:10.000000000 -0700
@@ -74,6 +74,8 @@
 "),
 	 stream);
 
+  fputs (_("Modified to support extended attributes.\n"), stream);
+
   switch (n_authors)
     {
     case 0: