Extended Attributes and Tiger’s Rsync

It’s been a while, but never fear I’ve got a nice shiny new bug for you today.

Rsync can in some cases not handle the -E and -‍-delete functions very well when combined together. Because Apple chose to implement resource forks in rsync using their you-beaut-gee-whiz ._ files, when the resource fork doesn’t exist for the file, or indeed the file doesn’t exist at all in the source directory rsync happily attempts to unlink the corresponding ._ file. On an HFS+ volume, clearly this is going to fail, as it doesn’t exist (incidentally on a UFS, Xsan, FAT, etc volume, it’d work just fine, but rsync is still broken).

A Patch

Due to my extreme generosity, or alternatively in an attempt to get away from some software with a name that rhymes with typo, I’ve whipped up a quick fix to this problem. It may not be the best way to fix it, but it works, and it even removes the resource fork from a file if the resource fork should be deleted, but not the file itself. How’s that for slick?

(Yeah, pasting it into a website isn’t all that slick, but I’m too lazy to upload it as a file right now, so tough luck. And WordPress seems to have stuck \ characters before the quote characters. They shouldn’t be there.)

--- rsync-2.6.3/syscall.c	2005-10-11 14:44:42.000000000 +1000
+++ rsync-2.6.3/syscall.c	2005-10-11 15:47:06.000000000 +1000
@@ -53,6 +53,31 @@
 {
 	if (dry_run) return 0;
 	RETURN_ERROR_IF_RO_OR_LO;
+#ifdef EA_SUPPORT
+	if (extended_attributes
+		&& !strncmp(basename(fname), "._", 2)) {
+		int retval;
+		retval = unlink(fname);
+		if (retval == -1 && errno == ENOENT) {
+			char ftemp[MAXPATHLEN+17];
+			if (snprintf(ftemp, MAXPATHLEN+17, "%s/%s/..namedfork/rsrc", 
+					dirname(fname), basename(fname)+2) >= MAXPATHLEN+17)
+			{
+				errno = ENOENT;
+				return -1;
+			}
+			fprintf(stderr, "%s", ftemp);
+			retval = truncate(ftemp, 0);
+			if (retval == -1 && errno == ENOENT) {
+				return 0;
+			} else {
+				return retval;
+			}
+		} else {
+			return retval;
+		}
+	}
+#endif
 	return unlink(fname);
 }
 

For reference the bug is Radar 4295233.

Comments are closed.