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.