Hi All!
rsync-3.0.6 with fileflags.diff under FreeBSD 8.0-RC1: if there is a file
with uchg or schg flag in source directory and it's hard-linked (usual
case for /usr/bin), then rsync cannot create the link in destination
directory. Error message: rsync: link "/tmp/s/a" => b failed:
Operation
not permitted (1)
The problem is that it's not allowed to link a *chg'ed file. Following
patch tries to remove the flag, link the file and then restore the file
(actually, the code is similar to code in the do_unlink function).
Regards
Anatoli Klassen
Test case:
# mkdir s d
# touch s/a
# ln s/a s/b
# chflags uchg s/a
# rsync -v --hard-links --archive --fileflags --force-change s/ d/
sending incremental file list
./
b
a => b
sent 102 bytes received 43 bytes 290.00 bytes/sec
total size is 0 speedup is 0.00
# ll *
d:
total 0
-rw-r--r-- 2 root wheel schg 0B Oct 1 15:50 a
-rw-r--r-- 2 root wheel schg 0B Oct 1 15:50 b
s:
total 0
-rw-r--r-- 2 root wheel schg 0B Oct 1 15:50 a
-rw-r--r-- 2 root wheel schg 0B Oct 1 15:50 b
The patch:
--- orig/syscall.c 2009-09-29 15:34:03.293118000 +0200
+++ syscall.c 2009-09-29 16:11:29.400671306 +0200
@@ -82,7 +82,23 @@
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
- return link(fname1, fname2);
+ if (link(fname1, fname2) == 0)
+ return 0;
+#ifdef SUPPORT_FORCE_CHANGE
+ if (force_change && errno == EPERM) {
+ STRUCT_STAT st;
+
+ if (x_lstat(fname1, &st, NULL) == 0
+ && make_mutable(fname1, st.st_mode, st.st_flags,
force_change) > 0) {
+ int ret = link(fname1, fname2);
+ undo_make_mutable(fname1, st.st_flags);
+ if (ret == 0)
+ return 0;
+ }
+ errno = EPERM;
+ }
+#endif
+ return -1;
}
#endif