Rsync may set bogus permissions if --perms is not specified and ACLs are
enabled. This happens if the destination directory was not created by
Cygwin itself. Testcase:
$ cygcheck -f /bin/cygwin1.dll
cygwin-1.7.7-1
$ cygcheck -f /bin/rsync.exe
rsync-3.0.7-1
$ umask
0022
$ cmd /c 'mkdir C:\test'
$ cd /cygdrive/c/test
$ echo test >source
$ rsync -vvv source dest
...
got ACL-based default perms 5070 for directory . <<---rwx---
...
$ ls -l
-rw-r--r--+ 1 someone none 5 2010-11-25 19:50 source
----r-----+ 1 someone none 5 2010-11-25 19:50 dest
$ cat dest
cat: dest: Permission denied
For some (security?) reason rsync (without --perms) does not rely on
permissions set by open(., O_CREAT, .). The permissions are set later
based on the default ACL of the parent dir.
The problem is that the rsync function acls.c:rsync_acl_get_perms()
expects that the default ACL has an "other" entry and that the "mask"
entry has only 3 rwx-bits.
The default ACL returned by Cygwin does not contain an "other" entry in
this case. The default "mask" is 0777 (OK or Cygwin bug?):
$ getfacl .
# file: .
# owner: someone
# group: none
user::rwx
group::---
group:root:rwx
group:SYSTEM:rwx
group:users:rwx
mask:rwx
other:---
default:user::rwx
default:group:root:rwx
default:group:SYSTEM:rwx
default:group:users:rwx
#default:other:... <<--- missing, expected by rsync
default:mask:rwx <<--- Cygwin returns 0777, rsync expects <= 07
With the above default ACL the function rsync_acl_get_perms() returns:
(07 << 6) + ((uchar)0777 << 3) + 0200/*NO_ENTRY*/ = 05070
This is interpreted as ---rwx--- which results in a file not readable by
the user.
The attached patch should fix this.
--
Christian Franke
--- rsync-3.0.7.orig/acls.c 2009-04-11 01:09:39.000000000 +0200
+++ rsync-3.0.7/acls.c 2010-11-25 15:37:45.859375000 +0100
@@ -122,12 +122,13 @@
}
/* Extracts and returns the permission bits from the ACL. This cannot be
- * called on an rsync_acl that has NO_ENTRY in any spot but the mask. */
+ * called on an rsync_acl that has NO_ENTRY in user_obj. */
static int rsync_acl_get_perms(const rsync_acl *racl)
{
return (racl->user_obj << 6)
- + ((racl->mask_obj != NO_ENTRY ? racl->mask_obj : racl->group_obj) << 3)
- + racl->other_obj;
+ | (((racl->mask_obj != NO_ENTRY ? racl->mask_obj
+ : racl->group_obj != NO_ENTRY ? racl->group_obj : 0) & 7) << 3)
+ | ((racl->other_obj != NO_ENTRY ? racl->other_obj : 0) & 7);
}
/* Removes the permission-bit entries from the ACL because these
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple