X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fset-mode-acl.c;h=d0fc6f8762bb067d517cf1e5e72914bd1b026a1c;hb=2408f02086a20c0a02241cd4a1cf11f126a95fe3;hp=f24ed0f27a584d9972c94c40588448fd617c7104;hpb=8c4874e600742f95ad38fbd6f518a3005ac4283c;p=gnulib.git diff --git a/lib/set-mode-acl.c b/lib/set-mode-acl.c index f24ed0f27..d0fc6f876 100644 --- a/lib/set-mode-acl.c +++ b/lib/set-mode-acl.c @@ -1,6 +1,6 @@ /* set-mode-acl.c - set access control list equivalent to a mode - Copyright (C) 2002-2003, 2005-2010 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,7 +57,7 @@ qset_acl (char const *name, int desc, mode_t mode) # if HAVE_ACL_GET_FILE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ -# if MODE_INSIDE_ACL +# if !HAVE_ACL_TYPE_EXTENDED /* Linux, FreeBSD, IRIX, Tru64 */ /* We must also have acl_from_text and acl_delete_def_file. @@ -132,21 +132,17 @@ qset_acl (char const *name, int desc, mode_t mode) if (S_ISDIR (mode) && acl_delete_def_file (name)) return -1; - if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) { - /* We did not call chmod so far, so the special bits have not yet - been set. */ + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ return chmod_or_fchmod (name, desc, mode); } return 0; -# else /* !MODE_INSIDE_ACL */ +# else /* HAVE_ACL_TYPE_EXTENDED */ /* MacOS X */ -# if !HAVE_ACL_TYPE_EXTENDED -# error Must have ACL_TYPE_EXTENDED -# endif - /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS) and acl_get_file (name, ACL_TYPE_DEFAULT) always return NULL / EINVAL. You have to use @@ -203,54 +199,9 @@ qset_acl (char const *name, int desc, mode_t mode) # elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ -# if defined ACL_NO_TRIVIAL - /* Solaris 10 (newer version), which has additional API declared in - (acl_t) and implemented in libsec (acl_set, acl_trivial, - acl_fromtext, ...). */ - - acl_t *aclp; - char acl_text[] = "user::---,group::---,mask:---,other:---"; - int ret; - int saved_errno; - - if (mode & S_IRUSR) acl_text[ 6] = 'r'; - if (mode & S_IWUSR) acl_text[ 7] = 'w'; - if (mode & S_IXUSR) acl_text[ 8] = 'x'; - if (mode & S_IRGRP) acl_text[17] = acl_text[26] = 'r'; - if (mode & S_IWGRP) acl_text[18] = acl_text[27] = 'w'; - if (mode & S_IXGRP) acl_text[19] = acl_text[28] = 'x'; - if (mode & S_IROTH) acl_text[36] = 'r'; - if (mode & S_IWOTH) acl_text[37] = 'w'; - if (mode & S_IXOTH) acl_text[38] = 'x'; - - if (acl_fromtext (acl_text, &aclp) != 0) - { - errno = ENOMEM; - return -1; - } - - ret = (desc < 0 ? acl_set (name, aclp) : facl_set (desc, aclp)); - saved_errno = errno; - acl_free (aclp); - if (ret < 0) - { - if (saved_errno == ENOSYS || saved_errno == EOPNOTSUPP) - return chmod_or_fchmod (name, desc, mode); - errno = saved_errno; - return -1; - } + int done_setacl = 0; - if (mode & (S_ISUID | S_ISGID | S_ISVTX)) - { - /* We did not call chmod so far, so the special bits have not yet - been set. */ - return chmod_or_fchmod (name, desc, mode); - } - return 0; - -# else /* Solaris, Cygwin, general case */ - -# ifdef ACE_GETACL +# ifdef ACE_GETACL /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 file systems (whereas the other ones are used in UFS file systems). */ @@ -292,7 +243,7 @@ qset_acl (char const *name, int desc, mode_t mode) convention = 0; for (i = 0; i < count; i++) - if (entries[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_OTHER)) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) { convention = 1; break; @@ -308,90 +259,145 @@ qset_acl (char const *name, int desc, mode_t mode) if (convention >= 0) { - ace_t entries[3]; + ace_t entries[6]; + int count; int ret; if (convention) { /* Running on Solaris 10. */ - entries[0].a_type = ALLOW; - entries[0].a_flags = ACE_OWNER; + entries[0].a_type = OLD_ALLOW; + entries[0].a_flags = OLD_ACE_OWNER; entries[0].a_who = 0; /* irrelevant */ entries[0].a_access_mask = (mode >> 6) & 7; - entries[1].a_type = ALLOW; - entries[1].a_flags = ACE_GROUP; + entries[1].a_type = OLD_ALLOW; + entries[1].a_flags = OLD_ACE_GROUP; entries[1].a_who = 0; /* irrelevant */ entries[1].a_access_mask = (mode >> 3) & 7; - entries[2].a_type = ALLOW; - entries[2].a_flags = ACE_OTHER; + entries[2].a_type = OLD_ALLOW; + entries[2].a_flags = OLD_ACE_OTHER; entries[2].a_who = 0; entries[2].a_access_mask = mode & 7; + count = 3; } else { - /* Running on Solaris 10 (newer version) or Solaris 11. */ - entries[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + /* Running on Solaris 10 (newer version) or Solaris 11. + The details here were found through "/bin/ls -lvd somefiles". */ + entries[0].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; entries[0].a_flags = NEW_ACE_OWNER; entries[0].a_who = 0; /* irrelevant */ - entries[0].a_access_mask = - (mode & 0400 ? NEW_ACE_READ_DATA : 0) - | (mode & 0200 ? NEW_ACE_WRITE_DATA : 0) - | (mode & 0100 ? NEW_ACE_EXECUTE : 0); - entries[1].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - entries[1].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[0].a_access_mask = 0; + entries[1].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[1].a_flags = NEW_ACE_OWNER; entries[1].a_who = 0; /* irrelevant */ - entries[1].a_access_mask = - (mode & 0040 ? NEW_ACE_READ_DATA : 0) - | (mode & 0020 ? NEW_ACE_WRITE_DATA : 0) - | (mode & 0010 ? NEW_ACE_EXECUTE : 0); - entries[2].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; - entries[2].a_flags = ACE_EVERYONE; - entries[2].a_who = 0; - entries[2].a_access_mask = - (mode & 0004 ? NEW_ACE_READ_DATA : 0) - | (mode & 0002 ? NEW_ACE_WRITE_DATA : 0) - | (mode & 0001 ? NEW_ACE_EXECUTE : 0); + entries[1].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + if (mode & 0400) + entries[1].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[0].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0200) + entries[1].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[0].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0100) + entries[1].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[0].a_access_mask |= NEW_ACE_EXECUTE; + entries[2].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[2].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[2].a_who = 0; /* irrelevant */ + entries[2].a_access_mask = 0; + entries[3].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[3].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP; + entries[3].a_who = 0; /* irrelevant */ + entries[3].a_access_mask = 0; + if (mode & 0040) + entries[3].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[2].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0020) + entries[3].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[2].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0010) + entries[3].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[2].a_access_mask |= NEW_ACE_EXECUTE; + entries[4].a_type = NEW_ACE_ACCESS_DENIED_ACE_TYPE; + entries[4].a_flags = NEW_ACE_EVERYONE; + entries[4].a_who = 0; + entries[4].a_access_mask = NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER; + entries[5].a_type = NEW_ACE_ACCESS_ALLOWED_ACE_TYPE; + entries[5].a_flags = NEW_ACE_EVERYONE; + entries[5].a_who = 0; + entries[5].a_access_mask = NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE; + if (mode & 0004) + entries[5].a_access_mask |= NEW_ACE_READ_DATA; + else + entries[4].a_access_mask |= NEW_ACE_READ_DATA; + if (mode & 0002) + entries[5].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + else + entries[4].a_access_mask |= NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA; + if (mode & 0001) + entries[5].a_access_mask |= NEW_ACE_EXECUTE; + else + entries[4].a_access_mask |= NEW_ACE_EXECUTE; + count = 6; } if (desc != -1) - ret = facl (desc, ACE_SETACL, - sizeof (entries) / sizeof (ace_t), entries); + ret = facl (desc, ACE_SETACL, count, entries); else - ret = acl (name, ACE_SETACL, - sizeof (entries) / sizeof (ace_t), entries); + ret = acl (name, ACE_SETACL, count, entries); if (ret < 0 && errno != EINVAL && errno != ENOTSUP) { if (errno == ENOSYS) return chmod_or_fchmod (name, desc, mode); return -1; } + if (ret == 0) + done_setacl = 1; } -# endif +# endif - { - aclent_t entries[3]; - int ret; - - entries[0].a_type = USER_OBJ; - entries[0].a_id = 0; /* irrelevant */ - entries[0].a_perm = (mode >> 6) & 7; - entries[1].a_type = GROUP_OBJ; - entries[1].a_id = 0; /* irrelevant */ - entries[1].a_perm = (mode >> 3) & 7; - entries[2].a_type = OTHER_OBJ; - entries[2].a_id = 0; - entries[2].a_perm = mode & 7; + if (!done_setacl) + { + aclent_t entries[3]; + int ret; - if (desc != -1) - ret = facl (desc, SETACL, sizeof (entries) / sizeof (aclent_t), entries); - else - ret = acl (name, SETACL, sizeof (entries) / sizeof (aclent_t), entries); - if (ret < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP) - return chmod_or_fchmod (name, desc, mode); - return -1; - } - } + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = OTHER_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = mode & 7; + + if (desc != -1) + ret = facl (desc, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + else + ret = acl (name, SETACL, + sizeof (entries) / sizeof (aclent_t), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + } if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) { @@ -401,12 +407,9 @@ qset_acl (char const *name, int desc, mode_t mode) } return 0; -# endif - # elif HAVE_GETACL /* HP-UX */ struct stat statbuf; - struct acl_entry entries[3]; int ret; if (desc != -1) @@ -416,25 +419,68 @@ qset_acl (char const *name, int desc, mode_t mode) if (ret < 0) return -1; - entries[0].uid = statbuf.st_uid; - entries[0].gid = ACL_NSGROUP; - entries[0].mode = (mode >> 6) & 7; - entries[1].uid = ACL_NSUSER; - entries[1].gid = statbuf.st_gid; - entries[1].mode = (mode >> 3) & 7; - entries[2].uid = ACL_NSUSER; - entries[2].gid = ACL_NSGROUP; - entries[2].mode = mode & 7; + { + struct acl_entry entries[3]; + + entries[0].uid = statbuf.st_uid; + entries[0].gid = ACL_NSGROUP; + entries[0].mode = (mode >> 6) & 7; + entries[1].uid = ACL_NSUSER; + entries[1].gid = statbuf.st_gid; + entries[1].mode = (mode >> 3) & 7; + entries[2].uid = ACL_NSUSER; + entries[2].gid = ACL_NSGROUP; + entries[2].mode = mode & 7; - if (desc != -1) - ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), entries); - else - ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), entries); + if (desc != -1) + ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), entries); + else + ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), entries); + } if (ret < 0) { - if (errno == ENOSYS || errno == EOPNOTSUPP) - return chmod_or_fchmod (name, desc, mode); - return -1; + if (!(errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)) + return -1; + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ + { + struct acl entries[4]; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = CLASS_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = (mode >> 3) & 7; + entries[3].a_type = OTHER_OBJ; + entries[3].a_id = 0; + entries[3].a_perm = mode & 7; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + ret = acl ((char *) name, ACL_SET, + sizeof (entries) / sizeof (struct acl), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + } +# else + return chmod_or_fchmod (name, desc, mode); +# endif } if (mode & (S_ISUID | S_ISGID | S_ISVTX))