Hi!

Using rsync under FreeBSD with hard links and files having schg set result in EPERM "Operation not permitted". This behavior can be observed if rsyncing /usr/bin/.

The patch fileflags.diff tries to deal with this situation but changes the flags of the parent directory only. It doesn't change the flags of the files itself.

do_link() in syscall.c has to be fixed. The attached syscall-do_link.c.txt contains the complete function do_link(). patch-syscall.c.txt is a patch which have the be applied after fileflags.diff.

Please have a look at the changes.

What is the "official" way of asking for inclusion in the rsync distribution? Reporting a bug via bugzilla?

        Best regards
                Franz
#ifdef HAVE_LINK
int do_link(const char *fname1, const char *fname2)
{
        if (dry_run) return 0;
        RETURN_ERROR_IF_RO_OR_LO;
        if (link(fname1, fname2) == 0)
                return 0;

#ifdef SUPPORT_FORCE_CHANGE
        if (force_change && (errno == EPERM || errno == EACCES)) {
                char parent[MAXPATHLEN];
                int parent_flags;
                int saved_errno = errno;
                int file_flags = make_mutable(fname1, NULL, NO_FFLAGS, 
force_change);
                if (file_flags) {
                        int ret = link(fname1, fname2);
                        undo_make_mutable(fname1, file_flags);
                        if (ret == 0)
                                return 0;
                }
                parent_flags = make_parentdir_mutable(fname2, force_change, 
parent, sizeof parent);
                if (parent_flags) {
                        int ret = link(fname1, fname2);
                        undo_make_mutable(parent, parent_flags);
                        if (ret == 0)
                                return 0;
                }
                errno = saved_errno;
        }
#endif

        return -1;
}
#endif
--- syscall.c.orig      2012-05-07 16:30:28.000000000 +0200
+++ syscall.c   2012-05-07 16:30:44.000000000 +0200
@@ -114,8 +114,16 @@
 #ifdef SUPPORT_FORCE_CHANGE
        if (force_change && (errno == EPERM || errno == EACCES)) {
                char parent[MAXPATHLEN];
+               int parent_flags;
                int saved_errno = errno;
-               int parent_flags = make_parentdir_mutable(fname2, force_change, 
parent, sizeof parent);
+               int file_flags = make_mutable(fname1, NULL, NO_FFLAGS, 
force_change);
+               if (file_flags) {
+                       int ret = link(fname1, fname2);
+                       undo_make_mutable(fname1, file_flags);
+                       if (ret == 0)
+                               return 0;
+               }
+               parent_flags = make_parentdir_mutable(fname2, force_change, 
parent, sizeof parent);
                if (parent_flags) {
                        int ret = link(fname1, fname2);
                        undo_make_mutable(parent, parent_flags);
-- 
Please use reply-all for most replies to avoid omitting the mailing list.
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to