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.