From unknown Sun Aug 17 22:01:40 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#20666 <20666@debbugs.gnu.org> To: bug#20666 <20666@debbugs.gnu.org> Subject: Status: [GNULIB v2 0/2] Improved acl handling Reply-To: bug#20666 <20666@debbugs.gnu.org> Date: Mon, 18 Aug 2025 05:01:40 +0000 retitle 20666 [GNULIB v2 0/2] Improved acl handling reassign 20666 coreutils submitter 20666 Andreas Gruenbacher severity 20666 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Tue May 26 16:54:21 2015 Received: (at submit) by debbugs.gnu.org; 26 May 2015 20:54:21 +0000 Received: from localhost ([127.0.0.1]:57458 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxLrh-0002yf-0J for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:21 -0400 Received: from eggs.gnu.org ([208.118.235.92]:38247) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxLrf-0002yR-6o for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxLrZ-0000BE-3m for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:14 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,FREEMAIL_FROM, T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:48910) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrZ-0000BA-0T for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51716) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrX-0003Ra-RT for bug-coreutils@gnu.org; Tue, 26 May 2015 16:54:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxLrW-00009f-Sd for bug-coreutils@gnu.org; Tue, 26 May 2015 16:54:11 -0400 Received: from mail-wi0-x22b.google.com ([2a00:1450:400c:c05::22b]:37692) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrR-00006K-Mw; Tue, 26 May 2015 16:54:05 -0400 Received: by wifw1 with SMTP id w1so45399090wif.0; Tue, 26 May 2015 13:54:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id; bh=jvfzqJSE5N5oEVJVFRmOs0iQxmeiZ8dhpLcJ1bkuOqk=; b=h5bpF/zJavhkOhP8tN3JFrnu+adB5Jtl8W34x40iAsQXhD1gp9V0+alyWClAQaYtuY gGhKj5gEFUitd5hrcxHfbtwDoeKkkA3tChPi1hOSs+fI9l5FuknXjVO4Z+YTUauSShD8 VCfG+sVdfghJ5W8i/pKgl1t/P3yi+ZWsrrRi61OE6wOS2o481Rm+Xa6folDALyTydGG5 VW8fRjBhEclxoUeRCK0PGzmwLyvZQRl5b6TzmydBUP29kyssjCuYLOZFnlposC3cj+Rw z1UuZjvqR+5GN3MKIoSRvuv/by7HUUhlQJay7zJ3o5bxvtqzB/8XkNBdUu+LBv9/n9e7 Jlww== X-Received: by 10.194.100.42 with SMTP id ev10mr24538152wjb.50.1432673644366; Tue, 26 May 2015 13:54:04 -0700 (PDT) Received: from nuc.lan (80-110-112-232.cgn.dynamic.surfer.at. [80.110.112.232]) by mx.google.com with ESMTPSA id g14sm23488545wjs.47.2015.05.26.13.54.02 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 May 2015 13:54:03 -0700 (PDT) From: Andreas Gruenbacher To: bug-gnulib@gnu.org, bug-coreutils@gnu.org Subject: [GNULIB v2 0/2] Improved acl handling Date: Tue, 26 May 2015 22:53:55 +0200 Message-Id: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> X-Mailer: git-send-email 2.4.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) Hello, these are the remaining two gnulib patches from the patch set originally posted on 12 April. These patches (and the richacl patches on top) are also available here: https://github.com/andreas-gruenbacher/gnulib https://github.com/andreas-gruenbacher/coreutils On the coreutils side, all that's needed is a gnulib update. Thanks, Andreas Andreas Gruenbacher (2): file-has-acl: Split feature tests again qacl: Reimplement qset_acl and qcopy_acl ChangeLog | 9 + lib/acl-internal.c | 30 ++ lib/acl-internal.h | 57 +++- lib/file-has-acl.c | 15 +- lib/get-permissions.c | 280 +++++++++++++++++ lib/qcopy-acl.c | 531 +------------------------------- lib/qset-acl.c | 639 +------------------------------------- lib/set-permissions.c | 833 ++++++++++++++++++++++++++++++++++++++++++++++++++ m4/acl.m4 | 24 +- modules/qacl | 4 +- 10 files changed, 1233 insertions(+), 1189 deletions(-) create mode 100644 lib/get-permissions.c create mode 100644 lib/set-permissions.c -- 2.4.0 From debbugs-submit-bounces@debbugs.gnu.org Tue May 26 16:55:08 2015 Received: (at submit) by debbugs.gnu.org; 26 May 2015 20:55:08 +0000 Received: from localhost ([127.0.0.1]:57464 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxLsI-0002zj-Gf for submit@debbugs.gnu.org; Tue, 26 May 2015 16:55:08 -0400 Received: from eggs.gnu.org ([208.118.235.92]:38710) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxLsC-0002zR-13 for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxLrz-0000RK-6w for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:46 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,FREEMAIL_FROM, T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:51451) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrz-0000R8-1T for submit@debbugs.gnu.org; Tue, 26 May 2015 16:54:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51994) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrp-00040t-0A for bug-coreutils@gnu.org; Tue, 26 May 2015 16:54:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxLri-0000GN-GI for bug-coreutils@gnu.org; Tue, 26 May 2015 16:54:28 -0400 Received: from mail-wi0-x230.google.com ([2a00:1450:400c:c05::230]:38217) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxLrU-00007j-1w; Tue, 26 May 2015 16:54:08 -0400 Received: by wizo1 with SMTP id o1so4142078wiz.1; Tue, 26 May 2015 13:54:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; bh=GDjpzvCqlVDlGnEd7DSnFmuZlyHWQmo3Fg7DGuYMZjE=; b=KSP/3nIk7/966JzNV6EyyKB5fmFdqD20utmLeUXh7Id3FFkus2St2UOKnyBqNtisrp efLQTRlzIYTUTGI9hAZ8isMBUsNYp7DzmIDm3WU3hS7iLKBJmTuUwLSMdlZcvPfivO65 0bIYfklfUom6RrwdTmF3VS3WdJk79XLkr1YnJRANIFUJNq1jIbLsuHhPCS96idxFzJoa xCTuPuBdZ9tpN40DJcF4A9W3xJJgV9gSp7VnPT4/RCc/JJlMpmE3fOCqxUKeq3qky6Ma mr0/g+R+D/UwA2jwtheeZr+buo+vjDOuMlydMHS+L9s2FJzGOJr9UTIqsdtBd0Uznx7l VtKA== X-Received: by 10.180.218.137 with SMTP id pg9mr43707411wic.79.1432673647298; Tue, 26 May 2015 13:54:07 -0700 (PDT) Received: from nuc.lan (80-110-112-232.cgn.dynamic.surfer.at. [80.110.112.232]) by mx.google.com with ESMTPSA id g14sm23488545wjs.47.2015.05.26.13.54.05 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 May 2015 13:54:06 -0700 (PDT) From: Andreas Gruenbacher To: bug-gnulib@gnu.org, bug-coreutils@gnu.org Subject: [GNULIB v2 2/2] qacl: Reimplement qset_acl and qcopy_acl Date: Tue, 26 May 2015 22:53:57 +0200 Message-Id: <1432673637-19777-3-git-send-email-andreas.gruenbacher@gmail.com> X-Mailer: git-send-email 2.4.0 In-Reply-To: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> References: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) Implement get_permissions and set_permissions primitives for getting all the permissions of a file, storing them, and later setting them. (In the minimal case, the permissions consist only of a file mode.) Reimplement qset_acl and qcopy_acl based on these new primitives: this avoids code duplication and makes error handling more consistent. The Solaris and Cygwin code still uses duplicate code paths for setting a file mode while making sure that no acls exist and setting an explicit acl; this is no worse than before, but could be cleaned up. The AIX code still doesn't read ACLs, it only makes sure that acls don't get in the way when setting a file mode. * lib/acl-internal.h (struct permission_context): New data structure. (get_permissions, set_permissions, free_permission_context): Declare. * lib/acl-internal.c (free_permission_context): New helper function. * lib/get-permissions.c (get_permissions): New helper function split off from qcopy_acl. * lib/set-permissions.c: (set_acls_from_mode): On Solaris, Cygwin, and AIX, set a file's permissions based only on a file mode. (acl_from_mode, context_acl_from_mode, context_aclv_from_mode): All other platforms construct a temporary acl from the file mode and set that acl in the same way as setting an acl read from the source file. This should help avoid code duplication and inconsistent / buggy behavior. (set_acls): New helper function Split off from qcopy_acl. (chmod_or_fchmod): Moved here from qset-acl.c. (set_permissions): New helper function. * lib/qcopy-acl.c (qcopy_acl): Rewrite using get_permissions and set_permissions. * lib/qset-acl.c (qset_acl): Rewrite using set_permissions. * modules/qacl: Add get-permissions.c and set-permissions.c. --- lib/acl-internal.c | 30 ++ lib/acl-internal.h | 57 +++- lib/get-permissions.c | 280 +++++++++++++++++ lib/qcopy-acl.c | 531 +------------------------------- lib/qset-acl.c | 639 +------------------------------------- lib/set-permissions.c | 833 ++++++++++++++++++++++++++++++++++++++++++++++++++ modules/qacl | 4 +- 7 files changed, 1206 insertions(+), 1168 deletions(-) create mode 100644 lib/get-permissions.c create mode 100644 lib/set-permissions.c diff --git a/lib/acl-internal.c b/lib/acl-internal.c index d9bd446..1c03c84 100644 --- a/lib/acl-internal.c +++ b/lib/acl-internal.c @@ -467,3 +467,33 @@ acl_nontrivial (int count, struct acl *entries) } #endif + +void free_permission_context (struct permission_context *ctx) +{ +#ifdef USE_ACL +# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ + if (ctx->acl) + acl_free (ctx->acl); +# if !HAVE_ACL_TYPE_EXTENDED + if (ctx->default_acl) + acl_free (ctx->default_acl); +# endif + +# elif defined GETACL /* Solaris, Cygwin */ + free (ctx->entries); +# ifdef ACE_GETACL + free (ctx->ace_entries); +# endif + +# elif HAVE_GETACL /* HP-UX */ + +# if HAVE_ACLV_H +# endif + +# elif HAVE_STATACL /* older AIX */ + +# elif HAVE_ACLSORT /* NonStop Kernel */ + +# endif +#endif +} diff --git a/lib/acl-internal.h b/lib/acl-internal.h index 9b9fae2..11fdea1 100644 --- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -133,12 +133,9 @@ rpl_acl_set_fd (int fd, acl_t acl) # define acl_from_mode(mode) (NULL) # endif -/* Set to 1 if a file's mode is implicit by the ACL. - Set to 0 if a file's mode is stored independently from the ACL. */ +/* Set to 0 if a file's mode is stored independently from the ACL. */ # if (HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP) || defined __sgi /* Mac OS X, IRIX */ # define MODE_INSIDE_ACL 0 -# else -# define MODE_INSIDE_ACL 1 # endif /* Return the number of entries in ACL. @@ -164,12 +161,9 @@ extern int acl_access_nontrivial (acl_t); # elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ -/* Set to 1 if a file's mode is implicit by the ACL. - Set to 0 if a file's mode is stored independently from the ACL. */ +/* Set to 0 if a file's mode is stored independently from the ACL. */ # if defined __CYGWIN__ /* Cygwin */ # define MODE_INSIDE_ACL 0 -# else /* Solaris */ -# define MODE_INSIDE_ACL 1 # endif /* Return 1 if the given ACL is non-trivial. @@ -248,6 +242,53 @@ extern int acl_nontrivial (int count, struct acl *entries); # endif +/* Set to 1 if a file's mode is implicit by the ACL. */ +# ifndef MODE_INSIDE_ACL +# define MODE_INSIDE_ACL 1 +# endif + #endif +struct permission_context { + mode_t mode; +#ifdef USE_ACL +# if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ + acl_t acl; +# if !HAVE_ACL_TYPE_EXTENDED + acl_t default_acl; +# endif + bool acls_not_supported; + +# elif defined GETACL /* Solaris, Cygwin */ + int count; + aclent_t *entries; +# ifdef ACE_GETACL + int ace_count; + ace_t *ace_entries; +# endif + +# elif HAVE_GETACL /* HP-UX */ + struct acl_entry entries[NACLENTRIES]; + int count; +# if HAVE_ACLV_H + struct acl aclv_entries[NACLVENTRIES]; + int aclv_count; +# endif + +# elif HAVE_STATACL /* older AIX */ + union { struct acl a; char room[4096]; } u; + bool have_u; + +# elif HAVE_ACLSORT /* NonStop Kernel */ + struct acl entries[NACLENTRIES]; + int count; + +# endif +#endif +}; + +int get_permissions (const char *, int, mode_t, struct permission_context *); +int set_permissions (struct permission_context *, const char *, int); +void free_permission_context (struct permission_context *); + _GL_INLINE_HEADER_END diff --git a/lib/get-permissions.c b/lib/get-permissions.c new file mode 100644 index 0000000..ccee1f1 --- /dev/null +++ b/lib/get-permissions.c @@ -0,0 +1,280 @@ +/* get-permissions.c - get permissions of a file + + Copyright (C) 2002-2003, 2005-2015 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include +#include "acl.h" + +#include "acl-internal.h" + +/* Read the permissions of a file into CTX. If DESC is a valid file descriptor, + use file descriptor operations, else use filename based operations on NAME. + MODE is the file mode obtained from a previous stat call. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +get_permissions (const char *name, int desc, mode_t mode, + struct permission_context *ctx) +{ + memset (ctx, 0, sizeof(*ctx)); + ctx->mode = mode; + +#if USE_ACL && HAVE_ACL_GET_FILE + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64 */ + + if (HAVE_ACL_GET_FD && desc != -1) + ctx->acl = acl_get_fd (desc); + else + ctx->acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (ctx->acl == NULL) + return acl_errno_valid (errno) ? -1 : 0; + + /* With POSIX ACLs, a file cannot have "no" acl; a file without + extended permissions has a "minimal" acl which is equivalent to the + file mode. */ + + if (S_ISDIR (mode)) + { + ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT); + if (ctx->default_acl == NULL) + return -1; + } + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + if (HAVE_ACL_GET_FD && desc != -1) + ctx->acl = acl_get_fd (desc); + else + ctx->acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (ctx->acl == NULL) + return acl_errno_valid (errno) ? -1 : 0; + +# endif + +#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ +# 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). + There is an API + pathconf (name, _PC_ACL_ENABLED) + fpathconf (desc, _PC_ACL_ENABLED) + that allows to determine which of the two kinds of ACLs is supported + for the given file. But some file systems may implement this call + incorrectly, so better not use it. + When fetching the source ACL, we simply fetch both ACL types. + When setting the destination ACL, we try either ACL types, assuming + that the kernel will translate the ACL from one form to the other. + (See in + the description of ENOTSUP.) */ + for (;;) + { + int ret; + + if (desc != -1) + ret = facl (desc, ACE_GETACLCNT, 0, NULL); + else + ret = acl (name, ACE_GETACLCNT, 0, NULL); + if (ret < 0) + { + if (errno == ENOSYS || errno == EINVAL) + ret = 0; + else + return -1; + } + ctx->ace_count = ret; + + if (ctx->ace_count == 0) + break; + + ctx->ace_entries = (ace_t *) malloc (ctx->ace_count * sizeof (ace_t)); + if (ctx->ace_entries == NULL) + { + errno = ENOMEM; + return -1; + } + + if (desc != -1) + ret = facl (desc, ACE_GETACL, ctx->ace_count, ctx->ace_entries); + else + ret = acl (name, ACE_GETACL, ctx->ace_count, ctx->ace_entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EINVAL) + { + free (ctx->ace_entries); + ctx->ace_entries = NULL; + ctx->ace_count = 0; + break; + } + else + return -1; + } + if (ret <= ctx->ace_count) + { + ctx->ace_count = ret; + break; + } + /* Huh? The number of ACL entries has increased since the last call. + Repeat. */ + free (ctx->ace_entries); + ctx->ace_entries = NULL; + } +# endif + + for (;;) + { + int ret; + + if (desc != -1) + ret = facl (desc, GETACLCNT, 0, NULL); + else + ret = acl (name, GETACLCNT, 0, NULL); + if (ret < 0) + { + if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) + ret = 0; + else + return -1; + } + ctx->count = ret; + + if (ctx->count == 0) + break; + + ctx->entries = (aclent_t *) malloc (ctx->count * sizeof (aclent_t)); + if (ctx->entries == NULL) + { + errno = ENOMEM; + return -1; + } + + if (desc != -1) + ret = facl (desc, GETACL, ctx->count, ctx->entries); + else + ret = acl (name, GETACL, ctx->count, ctx->entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) + { + free (ctx->entries); + ctx->entries = NULL; + ctx->count = 0; + break; + } + else + return -1; + } + if (ret <= ctx->count) + { + ctx->count = ret; + break; + } + /* Huh? The number of ACL entries has increased since the last call. + Repeat. */ + free (ctx->entries); + ctx->entries = NULL; + } + +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + + int ret; + + if (desc != -1) + ret = fgetacl (desc, NACLENTRIES, ctx->entries); + else + ret = getacl (name, NACLENTRIES, ctx->entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + ret = 0; + else + return -1; + } + else if (ret > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->count = ret; + +# if HAVE_ACLV_H + ret = acl ((char *) name, ACL_GET, NACLVENTRIES, ctx->aclv_entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + ret = 0; + else + return -2; + } + else if (ret > NACLVENTRIES) + /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->aclv_count = ret; +# endif + +#elif USE_ACL && HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ + + /* TODO (see set_permissions). */ + +#elif USE_ACL && HAVE_STATACL /* older AIX */ + + if (desc != -1) + ret = fstatacl (desc, STX_NORMAL, &ctx->u.a, sizeof (ctx->u)); + else + ret = statacl (name, STX_NORMAL, &ctx->u.a, sizeof (ctx->u)); + if (ret == 0) + ctx->have_u = true; + +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + + int ret; + + ret = acl ((char *) name, ACL_GET, NACLENTRIES, ctx->entries); + if (ret < 0) + return -1; + else if (ret > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + ctx->count = ret; + +#endif + + return 0; + +} diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c index bc258ba..c450742 100644 --- a/lib/qcopy-acl.c +++ b/lib/qcopy-acl.c @@ -39,534 +39,13 @@ int qcopy_acl (const char *src_name, int source_desc, const char *dst_name, int dest_desc, mode_t mode) { -#if USE_ACL && HAVE_ACL_GET_FILE - /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ - /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ -# if !HAVE_ACL_TYPE_EXTENDED - /* Linux, FreeBSD, IRIX, Tru64 */ - - acl_t acl; - int ret; - - if (HAVE_ACL_GET_FD && source_desc != -1) - acl = acl_get_fd (source_desc); - else - acl = acl_get_file (src_name, ACL_TYPE_ACCESS); - if (acl == NULL) - { - if (! acl_errno_valid (errno)) - return qset_acl (dst_name, dest_desc, mode); - else - return -2; - } - - if (HAVE_ACL_SET_FD && dest_desc != -1) - ret = acl_set_fd (dest_desc, acl); - else - ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl); - if (ret != 0) - { - int saved_errno = errno; - - if (! acl_errno_valid (errno) && !acl_access_nontrivial (acl)) - { - acl_free (acl); - return chmod_or_fchmod (dst_name, dest_desc, mode); - } - else - { - acl_free (acl); - chmod_or_fchmod (dst_name, dest_desc, mode); - errno = saved_errno; - return -1; - } - } - else - acl_free (acl); - - if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) - { - /* 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. */ - - if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) - return -1; - } - - if (S_ISDIR (mode)) - { - acl = acl_get_file (src_name, ACL_TYPE_DEFAULT); - if (acl == NULL) - return -2; - - if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl)) - { - int saved_errno = errno; - - acl_free (acl); - errno = saved_errno; - return -1; - } - else - acl_free (acl); - } - return 0; - -# else /* HAVE_ACL_TYPE_EXTENDED */ - /* Mac OS X */ - - /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) - always return NULL / EINVAL. You have to use - acl_get_file (name, ACL_TYPE_EXTENDED) - or acl_get_fd (open (name, ...)) - to retrieve an ACL. - On the other hand, - acl_set_file (name, ACL_TYPE_ACCESS, acl) - and acl_set_file (name, ACL_TYPE_DEFAULT, acl) - have the same effect as - acl_set_file (name, ACL_TYPE_EXTENDED, acl): - Each of these calls sets the file's ACL. */ - - acl_t acl; + struct permission_context ctx; int ret; - if (HAVE_ACL_GET_FD && source_desc != -1) - acl = acl_get_fd (source_desc); - else - acl = acl_get_file (src_name, ACL_TYPE_EXTENDED); - if (acl == NULL) - { - if (!acl_errno_valid (errno)) - return qset_acl (dst_name, dest_desc, mode); - else - return -2; - } - - if (HAVE_ACL_SET_FD && dest_desc != -1) - ret = acl_set_fd (dest_desc, acl); - else - ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl); + ret = get_permissions (src_name, source_desc, mode, &ctx); if (ret != 0) - { - int saved_errno = errno; - - if (!acl_errno_valid (saved_errno) && !acl_extended_nontrivial (acl)) - { - acl_free (acl); - return chmod_or_fchmod (dst_name, dest_desc, mode); - } - else - { - acl_free (acl); - chmod_or_fchmod (dst_name, dest_desc, mode); - errno = saved_errno; - return -1; - } - } - else - acl_free (acl); - - /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ - return chmod_or_fchmod (dst_name, dest_desc, mode); - -# endif - -#elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ - - /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions - of Unixware. The acl() call returns the access and default ACL both - at once. */ -# ifdef ACE_GETACL - int ace_count; - ace_t *ace_entries; -# endif - int count; - aclent_t *entries; - int did_chmod; - int saved_errno; - int ret; - -# 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). - There is an API - pathconf (name, _PC_ACL_ENABLED) - fpathconf (desc, _PC_ACL_ENABLED) - that allows to determine which of the two kinds of ACLs is supported - for the given file. But some file systems may implement this call - incorrectly, so better not use it. - When fetching the source ACL, we simply fetch both ACL types. - When setting the destination ACL, we try either ACL types, assuming - that the kernel will translate the ACL from one form to the other. - (See in - the description of ENOTSUP.) */ - for (;;) - { - ace_count = (source_desc != -1 - ? facl (source_desc, ACE_GETACLCNT, 0, NULL) - : acl (src_name, ACE_GETACLCNT, 0, NULL)); - - if (ace_count < 0) - { - if (errno == ENOSYS || errno == EINVAL) - { - ace_count = 0; - ace_entries = NULL; - break; - } - else - return -2; - } - - if (ace_count == 0) - { - ace_entries = NULL; - break; - } - - ace_entries = (ace_t *) malloc (ace_count * sizeof (ace_t)); - if (ace_entries == NULL) - { - errno = ENOMEM; - return -2; - } - - ret = (source_desc != -1 - ? facl (source_desc, ACE_GETACL, ace_count, ace_entries) - : acl (src_name, ACE_GETACL, ace_count, ace_entries)); - if (ret < 0) - { - free (ace_entries); - if (errno == ENOSYS || errno == EINVAL) - { - ace_count = 0; - ace_entries = NULL; - break; - } - else - return -2; - } - if (ret == ace_count) - break; - /* Huh? The number of ACL entries changed since the last call. - Repeat. */ - } -# endif - - for (;;) - { - count = (source_desc != -1 - ? facl (source_desc, GETACLCNT, 0, NULL) - : acl (src_name, GETACLCNT, 0, NULL)); - - if (count < 0) - { - if (errno == ENOSYS || errno == ENOTSUP || errno == EOPNOTSUPP) - { - count = 0; - entries = NULL; - break; - } - else - return -2; - } - - if (count == 0) - { - entries = NULL; - break; - } - - entries = (aclent_t *) malloc (count * sizeof (aclent_t)); - if (entries == NULL) - { - errno = ENOMEM; - return -2; - } - - if ((source_desc != -1 - ? facl (source_desc, GETACL, count, entries) - : acl (src_name, GETACL, count, entries)) - == count) - break; - /* Huh? The number of ACL entries changed since the last call. - Repeat. */ - } - - /* Is there an ACL of either kind? */ -# ifdef ACE_GETACL - if (ace_count == 0) -# endif - if (count == 0) - return qset_acl (dst_name, dest_desc, mode); - - did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */ - saved_errno = 0; /* the first non-ignorable error code */ - - if (!MODE_INSIDE_ACL) - { - /* On Cygwin, it is necessary to call chmod before acl, because - chmod can change the contents of the ACL (in ways that don't - change the allowed accesses, but still visible). */ - if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) - saved_errno = errno; - did_chmod = 1; - } - - /* If both ace_entries and entries are available, try SETACL before - ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL - can. */ - - if (count > 0) - { - ret = (dest_desc != -1 - ? facl (dest_desc, SETACL, count, entries) - : acl (dst_name, SETACL, count, entries)); - if (ret < 0 && saved_errno == 0) - { - saved_errno = errno; - if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - && !acl_nontrivial (count, entries)) - saved_errno = 0; - } - else - did_chmod = 1; - } - free (entries); - -# ifdef ACE_GETACL - if (ace_count > 0) - { - ret = (dest_desc != -1 - ? facl (dest_desc, ACE_SETACL, ace_count, ace_entries) - : acl (dst_name, ACE_SETACL, ace_count, ace_entries)); - if (ret < 0 && saved_errno == 0) - { - saved_errno = errno; - if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) - && !acl_ace_nontrivial (ace_count, ace_entries)) - saved_errno = 0; - } - } - free (ace_entries); -# endif - - if (MODE_INSIDE_ACL - && did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0)) - { - /* 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. */ - - if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) - { - if (saved_errno == 0) - saved_errno = errno; - } - } - - if (saved_errno) - { - errno = saved_errno; - return -1; - } - return 0; - -#elif USE_ACL && HAVE_GETACL /* HP-UX */ - - struct acl_entry entries[NACLENTRIES]; - int count; -# if HAVE_ACLV_H - struct acl aclv_entries[NACLVENTRIES]; - int aclv_count; -# endif - int did_chmod; - int saved_errno; - int ret; - - count = (source_desc != -1 - ? fgetacl (source_desc, NACLENTRIES, entries) - : getacl (src_name, NACLENTRIES, entries)); - - if (count < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) - count = 0; - else - return -2; - } - else if (count > 0) - { - if (count > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - } - -# if HAVE_ACLV_H - aclv_count = acl ((char *) src_name, ACL_GET, NACLVENTRIES, aclv_entries); - - if (aclv_count < 0) - { - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - count = 0; - else - return -2; - } - else if (aclv_count > 0) - { - if (aclv_count > NACLVENTRIES) - /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - } -# endif - - if (count == 0) -# if HAVE_ACLV_H - if (aclv_count == 0) -# endif - return qset_acl (dst_name, dest_desc, mode); - - did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */ - saved_errno = 0; /* the first non-ignorable error code */ - - if (count > 0) - { - ret = (dest_desc != -1 - ? fsetacl (dest_desc, count, entries) - : setacl (dst_name, count, entries)); - if (ret < 0 && saved_errno == 0) - { - saved_errno = errno; - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP - && !acl_nontrivial (count, entries)) - saved_errno = 0; - } - else - did_chmod = 1; - } - -# if HAVE_ACLV_H - if (aclv_count > 0) - { - ret = acl ((char *) dst_name, ACL_SET, aclv_count, aclv_entries); - if (ret < 0 && saved_errno == 0) - { - saved_errno = errno; - if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) - { - if (!aclv_nontrivial (aclv_count, aclv_entries)) - saved_errno = 0; - } - } - else - did_chmod = 1; - } -# endif - - if (did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0)) - { - /* We did not call chmod so far, and special bits are to be set which - don't fit into ACLs. */ - - if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) - { - if (saved_errno == 0) - saved_errno = errno; - } - } - - if (saved_errno) - { - errno = saved_errno; - return -1; - } - return 0; - -#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */ - - /* TODO */ - -#elif USE_ACL && HAVE_STATACL /* older AIX */ - - union { struct acl a; char room[4096]; } u; - int ret; - - if ((source_desc != -1 - ? fstatacl (source_desc, STX_NORMAL, &u.a, sizeof (u)) - : statacl (src_name, STX_NORMAL, &u.a, sizeof (u))) - < 0) return -2; - - ret = (dest_desc != -1 - ? fchacl (dest_desc, &u.a, u.a.acl_len) - : chacl (dst_name, &u.a, u.a.acl_len)); - if (ret < 0) - { - int saved_errno = errno; - - chmod_or_fchmod (dst_name, dest_desc, mode); - errno = saved_errno; - return -1; - } - - /* No need to call chmod_or_fchmod at this point, since the mode bits - S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ - - return 0; - -#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ - - struct acl entries[NACLENTRIES]; - int count; - int ret; - - count = acl ((char *) src_name, ACL_GET, NACLENTRIES, entries); - - if (count < 0) - { - if (0) - count = 0; - else - return -2; - } - else if (count > 0) - { - if (count > NACLENTRIES) - /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ - abort (); - } - - if (count == 0) - return qset_acl (dst_name, dest_desc, mode); - - ret = acl ((char *) dst_name, ACL_SET, count, entries); - if (ret < 0) - { - int saved_errno = errno; - - if (0) - { - if (!acl_nontrivial (count, entries)) - return chmod_or_fchmod (dst_name, dest_desc, mode); - } - - chmod_or_fchmod (dst_name, dest_desc, mode); - errno = saved_errno; - return -1; - } - - if (mode & (S_ISUID | S_ISGID | S_ISVTX)) - { - /* 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 (dst_name, dest_desc, mode); - } - return 0; - -#else - - return qset_acl (dst_name, dest_desc, mode); - -#endif + ret = set_permissions (&ctx, dst_name, dest_desc); + free_permission_context (&ctx); + return ret; } diff --git a/lib/qset-acl.c b/lib/qset-acl.c index bb4b0b2..1ebec22 100644 --- a/lib/qset-acl.c +++ b/lib/qset-acl.c @@ -21,26 +21,12 @@ #define ACL_INTERNAL_INLINE _GL_EXTERN_INLINE +#include #include "acl.h" #include "acl-internal.h" -/* If DESC is a valid file descriptor use fchmod to change the - file's mode to MODE on systems that have fchmod. On systems - that don't have fchmod and if DESC is invalid, use chmod on - NAME instead. - Return 0 if successful. Return -1 and set errno upon failure. */ - -int -chmod_or_fchmod (const char *name, int desc, mode_t mode) -{ - if (HAVE_FCHMOD && desc != -1) - return fchmod (desc, mode); - else - return chmod (name, mode); -} - /* Set the access control lists of a file. If DESC is a valid file descriptor, use file descriptor operations where available, else use filename based operations on NAME. If access control lists are not @@ -52,625 +38,12 @@ chmod_or_fchmod (const char *name, int desc, mode_t mode) int qset_acl (char const *name, int desc, mode_t mode) { -#if USE_ACL -# if HAVE_ACL_GET_FILE - /* POSIX 1003.1e draft 17 (abandoned) specific version. */ - /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ -# if !HAVE_ACL_TYPE_EXTENDED - /* Linux, FreeBSD, IRIX, Tru64 */ - - /* We must also have acl_from_text and acl_delete_def_file. - (acl_delete_def_file could be emulated with acl_init followed - by acl_set_file, but acl_set_file with an empty acl is - unspecified.) */ - -# ifndef HAVE_ACL_FROM_TEXT -# error Must have acl_from_text (see POSIX 1003.1e draft 17). -# endif -# ifndef HAVE_ACL_DELETE_DEF_FILE -# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). -# endif - - acl_t acl; - int ret; - - if (HAVE_ACL_FROM_MODE) /* Linux */ - { - acl = acl_from_mode (mode); - if (!acl) - return -1; - } - else /* FreeBSD, IRIX, Tru64 */ - { - /* If we were to create the ACL using the functions acl_init(), - acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(), - acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we - would need to create a qualifier. I don't know how to do this. - So create it using acl_from_text(). */ - -# if HAVE_ACL_FREE_TEXT /* Tru64 */ - char acl_text[] = "u::---,g::---,o::---,"; -# else /* FreeBSD, IRIX */ - char acl_text[] = "u::---,g::---,o::---"; -# endif - - if (mode & S_IRUSR) acl_text[ 3] = 'r'; - if (mode & S_IWUSR) acl_text[ 4] = 'w'; - if (mode & S_IXUSR) acl_text[ 5] = 'x'; - if (mode & S_IRGRP) acl_text[10] = 'r'; - if (mode & S_IWGRP) acl_text[11] = 'w'; - if (mode & S_IXGRP) acl_text[12] = 'x'; - if (mode & S_IROTH) acl_text[17] = 'r'; - if (mode & S_IWOTH) acl_text[18] = 'w'; - if (mode & S_IXOTH) acl_text[19] = 'x'; - - acl = acl_from_text (acl_text); - if (!acl) - return -1; - } - if (HAVE_ACL_SET_FD && desc != -1) - ret = acl_set_fd (desc, acl); - else - ret = acl_set_file (name, ACL_TYPE_ACCESS, acl); - if (ret != 0) - { - int saved_errno = errno; - acl_free (acl); - if (! acl_errno_valid (errno)) - return chmod_or_fchmod (name, desc, mode); - errno = saved_errno; - return -1; - } - else - acl_free (acl); - - if (S_ISDIR (mode) && acl_delete_def_file (name)) - return -1; - - if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) - { - /* 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 /* HAVE_ACL_TYPE_EXTENDED */ - /* Mac OS X */ - - /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) - and acl_get_file (name, ACL_TYPE_DEFAULT) - always return NULL / EINVAL. You have to use - acl_get_file (name, ACL_TYPE_EXTENDED) - or acl_get_fd (open (name, ...)) - to retrieve an ACL. - On the other hand, - acl_set_file (name, ACL_TYPE_ACCESS, acl) - and acl_set_file (name, ACL_TYPE_DEFAULT, acl) - have the same effect as - acl_set_file (name, ACL_TYPE_EXTENDED, acl): - Each of these calls sets the file's ACL. */ - - acl_t acl; + struct permission_context ctx; int ret; - /* Remove the ACL if the file has ACLs. */ - if (HAVE_ACL_GET_FD && desc != -1) - acl = acl_get_fd (desc); - else - acl = acl_get_file (name, ACL_TYPE_EXTENDED); - if (acl) - { - acl_free (acl); - - acl = acl_init (0); - if (acl) - { - if (HAVE_ACL_SET_FD && desc != -1) - ret = acl_set_fd (desc, acl); - else - ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); - if (ret != 0) - { - int saved_errno = errno; - acl_free (acl); - if (! acl_errno_valid (saved_errno)) - return chmod_or_fchmod (name, desc, mode); - errno = saved_errno; - return -1; - } - acl_free (acl); - } - } - - /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ - return chmod_or_fchmod (name, desc, mode); -# endif - -# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ - - int done_setacl = 0; - -# 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). */ - - /* The flags in the ace_t structure changed in a binary incompatible way - when ACL_NO_TRIVIAL etc. were introduced in version 1.15. - How to distinguish the two conventions at runtime? - We fetch the existing ACL. In the old convention, usually three ACEs have - a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. - In the new convention, these values are not used. */ - int convention; - - { - /* Initially, try to read the entries into a stack-allocated buffer. - Use malloc if it does not fit. */ - enum - { - alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ - alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) - }; - ace_t buf[alloc_init]; - size_t alloc = alloc_init; - ace_t *entries = buf; - ace_t *malloced = NULL; - int count; - - for (;;) - { - count = (desc != -1 - ? facl (desc, ACE_GETACL, alloc, entries) - : acl (name, ACE_GETACL, alloc, entries)); - if (count < 0 && errno == ENOSPC) - { - /* Increase the size of the buffer. */ - free (malloced); - if (alloc > alloc_max / 2) - { - errno = ENOMEM; - return -1; - } - alloc = 2 * alloc; /* <= alloc_max */ - entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); - if (entries == NULL) - { - errno = ENOMEM; - return -1; - } - continue; - } - break; - } - - if (count <= 0) - convention = -1; - else - { - int i; - - convention = 0; - for (i = 0; i < count; i++) - if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) - { - convention = 1; - break; - } - } - free (malloced); - } - - if (convention >= 0) - { - ace_t entries[6]; - int count; - int ret; - - if (convention) - { - /* Running on Solaris 10. */ - 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 = 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 = 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. - 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 = 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 = 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, count, entries); - else - 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 - - if (!done_setacl) - { - 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 (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))) - { - /* 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; - -# elif HAVE_GETACL /* HP-UX */ - - struct stat statbuf; - int ret; - - if (desc != -1) - ret = fstat (desc, &statbuf); - else - ret = stat (name, &statbuf); - if (ret < 0) - return -1; - - { - 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 (ret < 0) - { - 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)) - { - /* 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; - -# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ - - acl_type_list_t types; - size_t types_size = sizeof (types); - acl_type_t type; - - if (aclx_gettypes (name, &types, &types_size) < 0 - || types.num_entries == 0) - return chmod_or_fchmod (name, desc, mode); - - /* XXX Do we need to clear all types of ACLs for the given file, or is it - sufficient to clear the first one? */ - type = types.entries[0]; - if (type.u64 == ACL_AIXC) - { - union { struct acl a; char room[128]; } u; - int ret; - - u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ - u.a.acl_mode = mode & ~(S_IXACL | 0777); - u.a.u_access = (mode >> 6) & 7; - u.a.g_access = (mode >> 3) & 7; - u.a.o_access = mode & 7; - - if (desc != -1) - ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.acl_len, mode); - else - ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.acl_len, mode); - if (!(ret < 0 && errno == ENOSYS)) - return ret; - } - else if (type.u64 == ACL_NFS4) - { - union { nfs4_acl_int_t a; char room[128]; } u; - nfs4_ace_int_t *ace; - int ret; - - u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION; - u.a.aclEntryN = 0; - ace = &u.a.aclEntry[0]; - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_OWNER; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0200 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0100 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_GROUP; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0020 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0010 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - { - ace->flags = ACE4_ID_SPECIAL; - ace->aceWho.special_whoid = ACE4_WHO_EVERYONE; - ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; - ace->aceFlags = 0; - ace->aceMask = - (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) - | (mode & 0002 - ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA - | ACE4_ADD_SUBDIRECTORY - : 0) - | (mode & 0001 ? ACE4_EXECUTE : 0); - ace->aceWhoString[0] = '\0'; - ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; - ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; - u.a.aclEntryN++; - } - u.a.aclLength = (char *) ace - (char *) &u.a; - - if (desc != -1) - ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.aclLength, mode); - else - ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, - type, &u.a, u.a.aclLength, mode); - if (!(ret < 0 && errno == ENOSYS)) - return ret; - } - - return chmod_or_fchmod (name, desc, mode); - -# elif HAVE_STATACL /* older AIX */ - - union { struct acl a; char room[128]; } u; - int ret; - - u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ - u.a.acl_mode = mode & ~(S_IXACL | 0777); - u.a.u_access = (mode >> 6) & 7; - u.a.g_access = (mode >> 3) & 7; - u.a.o_access = mode & 7; - - if (desc != -1) - ret = fchacl (desc, &u.a, u.a.acl_len); - else - ret = chacl (name, &u.a, u.a.acl_len); - - if (ret < 0 && errno == ENOSYS) - return chmod_or_fchmod (name, desc, mode); - + memset (&ctx, 0, sizeof ctx); + ctx.mode = mode; + ret = set_permissions (&ctx, name, desc); + free_permission_context (&ctx); return ret; - -# elif HAVE_ACLSORT /* NonStop Kernel */ - - struct acl entries[4]; - 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 = 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 (0) - return chmod_or_fchmod (name, desc, mode); - return -1; - } - - 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 /* Unknown flavor of ACLs */ - return chmod_or_fchmod (name, desc, mode); -# endif -#else /* !USE_ACL */ - return chmod_or_fchmod (name, desc, mode); -#endif } diff --git a/lib/set-permissions.c b/lib/set-permissions.c new file mode 100644 index 0000000..47cb91c --- /dev/null +++ b/lib/set-permissions.c @@ -0,0 +1,833 @@ +/* set-permissions.c - set permissions of a file + + Copyright (C) 2002-2003, 2005-2015 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ + +#include + +#include "acl.h" + +#include "acl-internal.h" + +#if USE_ACL +# if ! defined HAVE_ACL_FROM_MODE && defined HAVE_ACL_FROM_TEXT /* FreeBSD, IRIX, Tru64 */ +static acl_t +acl_from_mode (mode_t mode) +{ +# if HAVE_ACL_FREE_TEXT /* Tru64 */ + char acl_text[] = "u::---,g::---,o::---,"; +# else /* FreeBSD, IRIX */ + char acl_text[] = "u::---,g::---,o::---"; +# endif + + if (mode & S_IRUSR) acl_text[ 3] = 'r'; + if (mode & S_IWUSR) acl_text[ 4] = 'w'; + if (mode & S_IXUSR) acl_text[ 5] = 'x'; + if (mode & S_IRGRP) acl_text[10] = 'r'; + if (mode & S_IWGRP) acl_text[11] = 'w'; + if (mode & S_IXGRP) acl_text[12] = 'x'; + if (mode & S_IROTH) acl_text[17] = 'r'; + if (mode & S_IWOTH) acl_text[18] = 'w'; + if (mode & S_IXOTH) acl_text[19] = 'x'; + + return acl_from_text (acl_text); +} +# endif + +# if HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ +static int +set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) +{ +# 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). */ + + /* The flags in the ace_t structure changed in a binary incompatible way + when ACL_NO_TRIVIAL etc. were introduced in version 1.15. + How to distinguish the two conventions at runtime? + We fetch the existing ACL. In the old convention, usually three ACEs have + a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. + In the new convention, these values are not used. */ + int convention; + + { + /* Initially, try to read the entries into a stack-allocated buffer. + Use malloc if it does not fit. */ + enum + { + alloc_init = 4000 / sizeof (ace_t), /* >= 3 */ + alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t)) + }; + ace_t buf[alloc_init]; + size_t alloc = alloc_init; + ace_t *entries = buf; + ace_t *malloced = NULL; + int count; + + for (;;) + { + count = (desc != -1 + ? facl (desc, ACE_GETACL, alloc, entries) + : acl (name, ACE_GETACL, alloc, entries)); + if (count < 0 && errno == ENOSPC) + { + /* Increase the size of the buffer. */ + free (malloced); + if (alloc > alloc_max / 2) + { + errno = ENOMEM; + return -1; + } + alloc = 2 * alloc; /* <= alloc_max */ + entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t)); + if (entries == NULL) + { + errno = ENOMEM; + return -1; + } + continue; + } + break; + } + + if (count <= 0) + convention = -1; + else + { + int i; + + convention = 0; + for (i = 0; i < count; i++) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) + { + convention = 1; + break; + } + } + free (malloced); + } + + if (convention >= 0) + { + ace_t entries[6]; + int count; + int ret; + + if (convention) + { + /* Running on Solaris 10. */ + 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 = 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 = 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. + 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 = 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 = 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, count, entries); + else + ret = acl (name, ACE_SETACL, count, entries); + if (ret < 0 && errno != EINVAL && errno != ENOTSUP) + { + if (errno == ENOSYS) + { + *must_chmod = true; + return 0; + } + return -1; + } + if (ret == 0) + return 0; + } +# 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 (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) + { + *must_chmod = true; + return 0; + } + return -1; + } + } +} + +#elif HAVE_GETACL /* HP-UX */ +static int +context_acl_from_mode (struct permission_context *ctx, const char *name, int desc) +{ + struct stat statbuf; + int ret; + + if (desc != -1) + ret = fstat (desc, &statbuf); + else + ret = stat (name, &statbuf); + if (ret < 0) + return -1; + + ctx->entries[0].uid = statbuf.st_uid; + ctx->entries[0].gid = ACL_NSGROUP; + ctx->entries[0].mode = (mode >> 6) & 7; + ctx->entries[1].uid = ACL_NSUSER; + ctx->entries[1].gid = statbuf.st_gid; + ctx->entries[1].mode = (mode >> 3) & 7; + ctx->entries[2].uid = ACL_NSUSER; + ctx->entries[2].gid = ACL_NSGROUP; + ctx->entries[2].mode = mode & 7; + ctx->count = 3; + return 0; +} + +# if HAVE_ACLV_H /* HP-UX >= 11.11 */ +static int +context_aclv_from_mode (struct permission_context *ctx) +{ + int ret; + + ctx->aclv_entries[0].a_type = USER_OBJ; + ctx->aclv_entries[0].a_id = 0; /* irrelevant */ + ctx->aclv_entries[0].a_perm = (mode >> 6) & 7; + ctx->aclv_entries[1].a_type = GROUP_OBJ; + ctx->aclv_entries[1].a_id = 0; /* irrelevant */ + ctx->aclv_entries[1].a_perm = (mode >> 3) & 7; + ctx->aclv_entries[2].a_type = CLASS_OBJ; + ctx->aclv_entries[2].a_id = 0; + ctx->aclv_entries[2].a_perm = (mode >> 3) & 7; + ctx->aclv_entries[3].a_type = OTHER_OBJ; + ctx->aclv_entries[3].a_id = 0; + ctx->aclv_entries[3].a_perm = mode & 7; + ctx->aclv_count = 4; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + return ret; +} +#endif + +# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */ +static int +set_acls_from_mode (const char *name, int desc, mode_t mode, bool *must_chmod) +{ + acl_type_list_t types; + size_t types_size = sizeof (types); + acl_type_t type; + + if (aclx_gettypes (name, &types, &types_size) < 0 + || types.num_entries == 0) + { + *must_chmod = true; + return 0; + } + + /* XXX Do we need to clear all types of ACLs for the given file, or is it + sufficient to clear the first one? */ + type = types.entries[0]; + if (type.u64 == ACL_AIXC) + { + union { struct acl a; char room[128]; } u; + int ret; + + u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */ + u.a.acl_mode = mode & ~(S_IXACL | 0777); + u.a.u_access = (mode >> 6) & 7; + u.a.g_access = (mode >> 3) & 7; + u.a.o_access = mode & 7; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.acl_len, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + else if (type.u64 == ACL_NFS4) + { + union { nfs4_acl_int_t a; char room[128]; } u; + nfs4_ace_int_t *ace; + int ret; + + u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION; + u.a.aclEntryN = 0; + ace = &u.a.aclEntry[0]; + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_OWNER; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0200 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0100 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_GROUP; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0020 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0010 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + { + ace->flags = ACE4_ID_SPECIAL; + ace->aceWho.special_whoid = ACE4_WHO_EVERYONE; + ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE; + ace->aceFlags = 0; + ace->aceMask = + (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0) + | (mode & 0002 + ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA + | ACE4_ADD_SUBDIRECTORY + : 0) + | (mode & 0001 ? ACE4_EXECUTE : 0); + ace->aceWhoString[0] = '\0'; + ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace; + ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4]; + u.a.aclEntryN++; + } + u.a.aclLength = (char *) ace - (char *) &u.a; + + if (desc != -1) + ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + else + ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS, + type, &u.a, u.a.aclLength, mode); + if (!(ret < 0 && errno == ENOSYS)) + return ret; + } + + *must_chmod = true; + return 0; +} + +# elif HAVE_STATACL /* older AIX */ +static int +context_acl_from_mode (struct permission_context *ctx) +{ + ctx->u.a.acl_len = (char *) &ctx->u.a.acl_ext[0] - (char *) &ctx->u.a; /* no entries */ + ctx->u.a.acl_mode = ctx->mode & ~(S_IXACL | 0777); + ctx->u.a.u_access = (ctx->mode >> 6) & 7; + ctx->u.a.g_access = (ctx->mode >> 3) & 7; + ctx->u.a.o_access = ctx->mode & 7; + ctx->have_u = true; + return 0; +} + +# elif HAVE_ACLSORT /* NonStop Kernel */ +static int +context_acl_from_mode (struct permission_context *ctx) +{ + int ret; + + ctx->entries[0].a_type = USER_OBJ; + ctx->entries[0].a_id = 0; /* irrelevant */ + ctx->entries[0].a_perm = (mode >> 6) & 7; + ctx->entries[1].a_type = GROUP_OBJ; + ctx->entries[1].a_id = 0; /* irrelevant */ + ctx->entries[1].a_perm = (mode >> 3) & 7; + ctx->entries[2].a_type = CLASS_OBJ; + ctx->entries[2].a_id = 0; + ctx->entries[2].a_perm = (mode >> 3) & 7; + ctx->entries[3].a_type = OTHER_OBJ; + ctx->entries[3].a_id = 0; + ctx->entries[3].a_perm = mode & 7; + ctx->count = 4; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + return ret; +} +# endif + +static int +set_acls (struct permission_context *ctx, const char *name, int desc, + int from_mode, bool *must_chmod, bool *acls_set) +{ + int ret = 0; + +#if HAVE_ACL_GET_FILE + /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */ +# if !HAVE_ACL_TYPE_EXTENDED + /* Linux, FreeBSD, IRIX, Tru64 */ + +# ifndef HAVE_ACL_FROM_TEXT +# error Must have acl_from_text (see POSIX 1003.1e draft 17). +# endif +# ifndef HAVE_ACL_DELETE_DEF_FILE +# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). +# endif + + if (! ctx->acls_not_supported) + { + if (ret == 0 && from_mode) + { + if (ctx->acl) + acl_free (ctx->acl); + ctx->acl = acl_from_mode (ctx->mode); + if (ctx->acl == NULL) + ret = -1; + } + + if (ret == 0 && ctx->acl) + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, ctx->acl); + else + ret = acl_set_file (name, ACL_TYPE_ACCESS, ctx->acl); + if (ret != 0) + { + if (! acl_errno_valid (errno)) + { + ctx->acls_not_supported = true; + if (from_mode || acl_access_nontrivial (ctx->acl) == 0) + ret = 0; + } + } + else + { + *acls_set = true; + if (S_ISDIR(ctx->mode)) + { + if (! from_mode && ctx->default_acl) + ret = acl_set_file (name, ACL_TYPE_DEFAULT, + ctx->default_acl); + else + ret = acl_delete_def_file (name); + } + } + } + } + +# else /* HAVE_ACL_TYPE_EXTENDED */ + /* Mac OS X */ + + /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) + and acl_get_file (name, ACL_TYPE_DEFAULT) + always return NULL / EINVAL. You have to use + acl_get_file (name, ACL_TYPE_EXTENDED) + or acl_get_fd (open (name, ...)) + to retrieve an ACL. + On the other hand, + acl_set_file (name, ACL_TYPE_ACCESS, acl) + and acl_set_file (name, ACL_TYPE_DEFAULT, acl) + have the same effect as + acl_set_file (name, ACL_TYPE_EXTENDED, acl): + Each of these calls sets the file's ACL. */ + + if (ctx->acl == NULL) + { + acl_t acl; + + /* Remove ACLs if the file has ACLs. */ + if (HAVE_ACL_GET_FD && desc != -1) + acl = acl_get_fd (desc); + else + acl = acl_get_file (name, ACL_TYPE_EXTENDED); + if (acl) + { + acl_free (acl); + + acl = acl_init (acl); + if (acl) + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, acl); + else + ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); + acl_free (acl); + } + else + ret = -1; + } + } + else + { + if (HAVE_ACL_SET_FD && desc != -1) + ret = acl_set_fd (desc, acl); + else + ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); + if (ret != 0) + { + if (! acl_errno_valid (saved_errno) && ! acl_extended_nontrivial (acl)) + ret = 0; + } + } + *acls_set = true; + +# endif + +# elif defined GETACL /* Solaris, Cygwin, not HP-UX */ + + /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions + of Unixware. The acl() call returns the access and default ACL both + at once. */ + + /* If both ace_entries and entries are available, try SETACL before + ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL + can. */ + + if (from_mode) + return set_acls_from_mode (name, desc, ctx->mode, must_chmod); + + if (ret == 0 && ctx->count) + { + if (desc != -1) + ret = facl (desc, SETACL, count, entries); + else + ret = acl (name, SETACL, count, entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + && acl_nontrivial (count, entries) == 0) + ret = 0; + } + else + *acls_set = true; + } + +# ifdef ACE_GETACL + if (ret == 0 && ctx->ace_count) + { + if (desc != -1) + ret = facl (desc, ACE_SETACL, ace_count, ace_entries); + else + ret = acl (name, ACE_SETACL, ace_count, ace_entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EINVAL || errno == ENOTSUP) + && acl_ace_nontrivial (ace_count, ace_entries) == 0) + ret = 0; + } + else + *acls_set = true; + } +# endif + +#elif HAVE_GETACL /* HP-UX */ + + if (from_mode) + ret = context_acl_from_mode (ctx, name, desc); + + if (ret == 0 && ctx->count > 0) + { + if (desc != -1) + ret = fsetacl (desc, ctx->count, ctx->entries); + else + ret = setacl (name, ctx->count, ctx->entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP) + && (from_mode || !acl_nontrivial (ctx->count, ctx->entries, &source_statbuf))) + ret = 0; + } + else + *acls_set = true; + } + +# if HAVE_ACLV_H + if (from_mode) + ret = context_aclv_from_mode (ctx); + + if (ret == 0 && ctx->aclv_count > 0) + { + ret = acl ((char *) name, ACL_SET, ctx->aclv_count, ctx->aclv_entries); + if (ret < 0) + { + if ((errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL) + && (from_mode || !aclv_nontrivial (ctx->aclv_count, ctx->aclv_entries))) + ret = 0; + } + else + *acls_set = true; + } +# endif + +# elif HAVE_ACLX_GET && ACL_AIX_WIP /* AIX */ + + /* TODO: Implement setting ACLs once get_permissions() reads them. */ + + if (from_mode) + ret = set_acls_from_mode (name, desc, mode, must_chmod); + +# elif HAVE_STATACL /* older AIX */ + + if (from_mode) + ret = context_acl_from_mode (ctx); + + if (ret == 0 && ctx->have_u) + { + if (desc != -1) + ret = fchacl (desc, &u.a, u.a.acl_len); + else + ret = chacl (name, &u.a, u.a.acl_len); + if (ret < 0) + { + if (errno == ENOSYS && from_mode) + ret = 0; + } + else + *acls_set = true; + } + +# elif HAVE_ACLSORT /* NonStop Kernel */ + + if (from_mode) + ret = context_acl_from_mode (ctx); + + if (ret == 0 && ctx->count) + { + ret = acl ((char *) name, ACL_SET, ctx->count, ctx->entries); + if (ret != 0) + { + if (!acl_nontrivial (ctx->count, ctx->entries)) + ret = 0; + } + else + *acls_set = true; + } + +# else /* No ACLs */ + + /* Nothing to do. */ + +#endif + + return ret; +} +#endif + +/* If DESC is a valid file descriptor use fchmod to change the + file's mode to MODE on systems that have fchmod. On systems + that don't have fchmod and if DESC is invalid, use chmod on + NAME instead. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +chmod_or_fchmod (const char *name, int desc, mode_t mode) +{ + if (HAVE_FCHMOD && desc != -1) + return fchmod (desc, mode); + else + return chmod (name, mode); +} + +/* Set the permissions in CTX on a file. If DESC is a valid file descriptor, + use file descriptor operations, else use filename based operations on NAME. + If access control lists are not available, fchmod the target file to the + mode in CTX. Also sets the non-permission bits of the destination file + (S_ISUID, S_ISGID, S_ISVTX) to those from the mode in CTX if any are set. + Return 0 if successful. Return -1 and set errno upon failure. */ + +int +set_permissions (struct permission_context *ctx, const char *name, int desc) +{ + bool acls_set _GL_UNUSED = false; + bool early_chmod; + bool must_chmod = false; + int ret = 0; + +#if USE_ACL +# if HAVE_STATACL + /* older AIX */ + /* There is no need to call chmod_or_fchmod, since the mode + bits S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL. */ + + early_chmod = false; +# else + /* All other plaforms */ + /* On Cygwin, it is necessary to call chmod before acl, because + chmod can change the contents of the ACL (in ways that don't + change the allowed accesses, but still visible). */ + + early_chmod = (! MODE_INSIDE_ACL || (ctx->mode & (S_ISUID | S_ISGID | S_ISVTX))); +# endif +#else + /* No ACLs */ + + early_chmod = true; +#endif + + if (early_chmod) + { + ret = chmod_or_fchmod (name, desc, ctx->mode); + if (ret != 0) + return -1; + } + +#if USE_ACL + ret = set_acls (ctx, name, desc, false, &must_chmod, &acls_set); + if (! acls_set) + { + int saved_errno = ret ? errno : 0; + + /* If we can't set an acl which we expect to be able to set, try setting + the permissions to ctx->mode. Doe to possible inherited permissions, + we cannot simply chmod. */ + + acls_set = false; + ret = set_acls (ctx, name, desc, true, &must_chmod, &acls_set); + if (! acls_set) + must_chmod = true; + + if (saved_errno) + { + errno = saved_errno; + ret = -1; + } + } +#endif + + if (must_chmod && ! early_chmod) + { + int saved_errno = ret ? errno : 0; + + ret = chmod_or_fchmod (name, desc, ctx->mode); + + if (saved_errno) + { + errno = saved_errno; + ret = -1; + } + } + + return ret; +} diff --git a/modules/qacl b/modules/qacl index bc7382b..d91507b 100644 --- a/modules/qacl +++ b/modules/qacl @@ -7,8 +7,10 @@ lib/acl-internal.h lib/acl-errno-valid.c lib/acl_entries.c lib/acl-internal.c +lib/get-permissions.c lib/qcopy-acl.c lib/qset-acl.c +lib/set-permissions.c m4/acl.m4 Depends-on: @@ -21,7 +23,7 @@ configure.ac: gl_FUNC_ACL Makefile.am: -lib_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c +lib_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c get-permissions.c set-permissions.c Include: "acl.h" -- 2.4.0 From debbugs-submit-bounces@debbugs.gnu.org Tue May 26 17:05:20 2015 Received: (at control) by debbugs.gnu.org; 26 May 2015 21:05:20 +0000 Received: from localhost ([127.0.0.1]:57476 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxM2J-0003Ji-HB for submit@debbugs.gnu.org; Tue, 26 May 2015 17:05:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48900) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxM2H-0003JY-MQ for control@debbugs.gnu.org; Tue, 26 May 2015 17:05:18 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id B41248E4ED for ; Tue, 26 May 2015 21:05:15 +0000 (UTC) Received: from [10.3.113.99] (ovpn-113-99.phx2.redhat.com [10.3.113.99]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t4QL5FGk012744 for ; Tue, 26 May 2015 17:05:15 -0400 Message-ID: <5564E00A.1080602@redhat.com> Date: Tue, 26 May 2015 15:05:14 -0600 From: Eric Blake Organization: Red Hat, Inc. User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: GNU bug control Subject: Re: bug#20667: [GNULIB v2 1/2] file-has-acl: Split feature tests again References: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> <1432673637-19777-2-git-send-email-andreas.gruenbacher@gmail.com> In-Reply-To: <1432673637-19777-2-git-send-email-andreas.gruenbacher@gmail.com> OpenPGP: url=http://people.redhat.com/eblake/eblake.gpg Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="mI13cwwK6umEEFUTK75pDbKBCNAiqjbP4" X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Spam-Score: -5.0 (-----) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --mI13cwwK6umEEFUTK75pDbKBCNAiqjbP4 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable merge 20666 20667 thanks --=20 Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org --mI13cwwK6umEEFUTK75pDbKBCNAiqjbP4 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Public key at http://people.redhat.com/eblake/eblake.gpg Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBCAAGBQJVZOALAAoJEKeha0olJ0NqsK8H/jmkXAsshZR2pAr/yScaNt2l +kMWY7+Va90rSGRfvodZuh1T/t6CoApOr1GbHy+CTdD7PhlaW7DLee/kO13Wb9J4 bf4mjBRrjnUT9zOysUiD3PO/5sziTMLtNC15hLBXD6AGdn0RYYp3ereVDEagkM3W K4FWQyWDM9pTOD0TaOAv3r3etR/CKagFeMq7SBl/iZQCruRb8q/yh97LNRd33Ypn 9cFn/VNjQB10N+mCgbxuzKBlHca8yG/zLHH4OjPnG9RHNHVPVsq7Kq3+3ewiCbbZ ninAc2GfOld2+IZ7n5lKtAdx4jynTauFzo9HRvlNV0LrcOZWFReX0rahN3rYUAg= =ZTdC -----END PGP SIGNATURE----- --mI13cwwK6umEEFUTK75pDbKBCNAiqjbP4-- From debbugs-submit-bounces@debbugs.gnu.org Wed May 27 14:21:19 2015 Received: (at submit) by debbugs.gnu.org; 27 May 2015 18:21:19 +0000 Received: from localhost ([127.0.0.1]:58600 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yxfx8-0006uh-95 for submit@debbugs.gnu.org; Wed, 27 May 2015 14:21:18 -0400 Received: from eggs.gnu.org ([208.118.235.92]:49795) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yxfx5-0006uO-GO for submit@debbugs.gnu.org; Wed, 27 May 2015 14:21:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yxfwz-0002uw-Mu for submit@debbugs.gnu.org; Wed, 27 May 2015 14:21:10 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:43015) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yxfwz-0002uq-Jc for submit@debbugs.gnu.org; Wed, 27 May 2015 14:21:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35029) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yxfwy-0005C4-J4 for bug-coreutils@gnu.org; Wed, 27 May 2015 14:21:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Yxfwx-0002tx-NF for bug-coreutils@gnu.org; Wed, 27 May 2015 14:21:08 -0400 Received: from mail-oi0-x22b.google.com ([2607:f8b0:4003:c06::22b]:35992) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Yxfwv-0002t4-TP; Wed, 27 May 2015 14:21:05 -0400 Received: by oihb142 with SMTP id b142so14093790oih.3; Wed, 27 May 2015 11:21:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=6t2Awakdbs80sjHIaOrXg2jxkKCFCaD135ovKiyZ5gk=; b=gKvXQ4V5uYEoU+nKQylIdSGF7Pc+C9amfBj93q0+DYzhU/hgt/tzo9h89KPtC8mpV3 eZsZuZqxb4IsdLmcODrWqcUDkxXrn8m6jpwTpDIGJf+Un6+7HrLeGd+fTtgeK1T3EeJi p4o++S32FVAUl6BUE0wJCJy+Su0UhUmQZVBfZ0KkOBIEI6KjaeLJ15w/zw3hAs53ACGv wBkAThR3NAQ9L1+smnAY0VFsScR37xtysBlrSxcmypVhGiKxfK08NKelNzZOxrkrBlr7 pDKJ/26luykja01lHh6IPfHyWQ8GUDN2xlDxSjZ7GjlN1P1e4cGMaavQzfL8ZrOE70n0 ZOHQ== MIME-Version: 1.0 X-Received: by 10.60.132.208 with SMTP id ow16mr27619031oeb.66.1432750865310; Wed, 27 May 2015 11:21:05 -0700 (PDT) Received: by 10.182.143.72 with HTTP; Wed, 27 May 2015 11:21:05 -0700 (PDT) In-Reply-To: <556609A2.6020609@cs.ucla.edu> References: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> <1432673637-19777-2-git-send-email-andreas.gruenbacher@gmail.com> <556609A2.6020609@cs.ucla.edu> Date: Wed, 27 May 2015 20:21:05 +0200 Message-ID: Subject: Re: [GNULIB v2 1/2] file-has-acl: Split feature tests again From: =?UTF-8?Q?Andreas_Gr=C3=BCnbacher?= To: Paul Eggert Content-Type: text/plain; charset=UTF-8 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit Cc: bug-coreutils@gnu.org, bug-gnulib@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) Paul, 2015-05-27 20:14 GMT+02:00 Paul Eggert : > Simplest fix is to replace AC_CHECK_FUNCS_ONCE with AC_CHECK_FUNCS. thanks, I've fixed that on github. Andreas From debbugs-submit-bounces@debbugs.gnu.org Wed May 27 14:51:02 2015 Received: (at submit) by debbugs.gnu.org; 27 May 2015 18:51:04 +0000 Received: from localhost ([127.0.0.1]:58618 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxgPs-0007eG-MH for submit@debbugs.gnu.org; Wed, 27 May 2015 14:51:01 -0400 Received: from eggs.gnu.org ([208.118.235.92]:57186) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxgPp-0007e2-Fj for submit@debbugs.gnu.org; Wed, 27 May 2015 14:50:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxgPj-00048S-Ez for submit@debbugs.gnu.org; Wed, 27 May 2015 14:50:52 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:55487) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxgPj-00048O-C2 for submit@debbugs.gnu.org; Wed, 27 May 2015 14:50:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42448) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxgPi-0003vv-CO for bug-coreutils@gnu.org; Wed, 27 May 2015 14:50:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxgPc-00046O-7i for bug-coreutils@gnu.org; Wed, 27 May 2015 14:50:50 -0400 Received: from smtp.cs.ucla.edu ([131.179.128.62]:42103) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxgPc-000461-1J; Wed, 27 May 2015 14:50:44 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by smtp.cs.ucla.edu (Postfix) with ESMTP id 55112A60010; Wed, 27 May 2015 11:50:42 -0700 (PDT) X-Virus-Scanned: amavisd-new at smtp.cs.ucla.edu Received: from smtp.cs.ucla.edu ([127.0.0.1]) by localhost (smtp.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id m9EALGL7mGRR; Wed, 27 May 2015 11:50:41 -0700 (PDT) Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by smtp.cs.ucla.edu (Postfix) with ESMTPSA id B12ECA60002; Wed, 27 May 2015 11:50:41 -0700 (PDT) Message-ID: <55661201.6090309@cs.ucla.edu> Date: Wed, 27 May 2015 11:50:41 -0700 From: Paul Eggert Organization: UCLA Computer Science Department User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Andreas Gruenbacher , bug-gnulib@gnu.org, bug-coreutils@gnu.org Subject: Re: [GNULIB v2 2/2] qacl: Reimplement qset_acl and qcopy_acl References: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> <1432673637-19777-3-git-send-email-andreas.gruenbacher@gmail.com> In-Reply-To: <1432673637-19777-3-git-send-email-andreas.gruenbacher@gmail.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) On 05/26/2015 01:53 PM, Andreas Gruenbacher wrote: > --- > lib/acl-internal.c | 30 ++ This one is missing a patch to ChangeLog. Please put the commit message into the ChangeLog. Also, please put the string "Bug#20666" somewhere into the commit message body and the ChangeLog (they should be essentially identical). I forgot, the "Bug#20667" should also be put into the other commit message and ChangeLog. > +void free_permission_context (struct permission_context *ctx) Please put the function name in column 1, with the type in the previous line. > Makefile.am: > -lib_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c > +lib_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c get-permissions.c set-permissions.c > Please break it into two lines (OK to use \ at the end of the 1st line) so that it's not longer than 80 characters. Other than that, both patches look good to me; please install. And thanks. From debbugs-submit-bounces@debbugs.gnu.org Wed May 27 17:50:08 2015 Received: (at submit) by debbugs.gnu.org; 27 May 2015 21:50:09 +0000 Received: from localhost ([127.0.0.1]:58694 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxjDB-0003Se-MR for submit@debbugs.gnu.org; Wed, 27 May 2015 17:50:07 -0400 Received: from eggs.gnu.org ([208.118.235.92]:36601) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YxjD7-0003S4-LM for submit@debbugs.gnu.org; Wed, 27 May 2015 17:50:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxjD1-0007vo-0L for submit@debbugs.gnu.org; Wed, 27 May 2015 17:49:56 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAYES_40,FREEMAIL_FROM, T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:34356) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxjD0-0007ve-UQ for submit@debbugs.gnu.org; Wed, 27 May 2015 17:49:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50074) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxjCz-0006yu-UO for bug-coreutils@gnu.org; Wed, 27 May 2015 17:49:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxjCy-0007v3-U4 for bug-coreutils@gnu.org; Wed, 27 May 2015 17:49:53 -0400 Received: from mail-oi0-x22e.google.com ([2607:f8b0:4003:c06::22e]:33280) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxjCw-0007tj-3l; Wed, 27 May 2015 17:49:50 -0400 Received: by oiww2 with SMTP id w2so18385409oiw.0; Wed, 27 May 2015 14:49:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=Eq439xmlp2awdXhn7Qzm0Wan5eU+7weq7ZNLa9hUyI0=; b=g669ewnQkEoneTISQsD9aKjruts8jLhjE35JK5b6wLcXYdlNn0ZKKARkDNq5pNUxa3 amqIFnReJwYtWwyho9DAE9u2cXBekDRr757MEd7Aeu6hGJ9zSlNRYKoRyE0kTx89C8HE TasRIJcPA9C8nGKSbXC+UgH6a9zjbw54ikGHxfXia3aDDTKd2H6gefQjcsCITXwfkrpb AYrxSCcYxZC8UmQSLEVaDqMtYS11/YQv1bkza3iaxCOkW4b14veH4SAC8kEYqv0DWjrX Tz8HSTTFYaoqNCa1Dmh9zT1XlDWcsHhMJ8wSd7+qK6aiz82Hbs76rc1NapadxYXhSRJQ xV1w== MIME-Version: 1.0 X-Received: by 10.202.72.207 with SMTP id v198mr16323958oia.116.1432763387978; Wed, 27 May 2015 14:49:47 -0700 (PDT) Received: by 10.182.143.72 with HTTP; Wed, 27 May 2015 14:49:47 -0700 (PDT) In-Reply-To: <55661201.6090309@cs.ucla.edu> References: <1432673637-19777-1-git-send-email-andreas.gruenbacher@gmail.com> <1432673637-19777-3-git-send-email-andreas.gruenbacher@gmail.com> <55661201.6090309@cs.ucla.edu> Date: Wed, 27 May 2015 23:49:47 +0200 Message-ID: Subject: Re: [GNULIB v2 2/2] qacl: Reimplement qset_acl and qcopy_acl From: =?UTF-8?Q?Andreas_Gr=C3=BCnbacher?= To: Paul Eggert Content-Type: multipart/mixed; boundary=001a11c14e00c9d27f0517173873 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit Cc: bug-coreutils@gnu.org, bug-gnulib@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) --001a11c14e00c9d27f0517173873 Content-Type: text/plain; charset=UTF-8 Paul, requested changes made and pushed. I don't think I have commit access to coreutils, so could you please push the coreutils change to update gnulib (attached)? Thanks, Andreas --001a11c14e00c9d27f0517173873 Content-Type: text/x-diff; charset=US-ASCII; name="0001-build-updated-gnulib-acl-handling.patch" Content-Disposition: attachment; filename="0001-build-updated-gnulib-acl-handling.patch" Content-Transfer-Encoding: base64 X-Attachment-Id: f_ia7a9eab0 RnJvbSAwZjlkYjM2ZDY1OGI5Y2I4OTMzZjMzNDEwOWM2ZTBhOGE3MmM1MTYwIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBBbmRyZWFzIEdydWVuYmFjaGVyIDxhbmRyZWFzLmdydWVuYmFj aGVyQGdtYWlsLmNvbT4KRGF0ZTogU2F0LCAxMSBBcHIgMjAxNSAxNDo0OTo0OSArMDIwMApTdWJq ZWN0OiBbUEFUQ0hdIGJ1aWxkOiB1cGRhdGVkIGdudWxpYiBhY2wgaGFuZGxpbmcKClRoaXMgYnJp bmdzIGluIHRoZSBnbnVsaWIgYWNsIHNldHRpbmcgYW5kIGNvcGluZyByZXdyaXRlLgoKKiBnbnVs aWI6IFVwZGF0ZSB0byBsYXRlc3QuCi0tLQogZ251bGliIHwgMiArLQogMSBmaWxlIGNoYW5nZWQs IDEgaW5zZXJ0aW9uKCspLCAxIGRlbGV0aW9uKC0pCgpkaWZmIC0tZ2l0IGEvZ251bGliIGIvZ251 bGliCmluZGV4IDJhZWEyYzcuLjJkNWNlNDQgMTYwMDAwCi0tLSBhL2dudWxpYgorKysgYi9nbnVs aWIKQEAgLTEgKzEgQEAKLVN1YnByb2plY3QgY29tbWl0IDJhZWEyYzcyMzM1OWQ5NDU5ZmQwMWU3 YjQyOGY0NzY1NmM5Y2UxZTkKK1N1YnByb2plY3QgY29tbWl0IDJkNWNlNDQ1ZDYzMTA5YjM5OTk0 MDJlZmZiYzZmOGMxZGI0ZTg5MjAKLS0gCjIuNC4wCgo= --001a11c14e00c9d27f0517173873-- From debbugs-submit-bounces@debbugs.gnu.org Sat May 30 20:30:12 2015 Received: (at control) by debbugs.gnu.org; 31 May 2015 00:30:13 +0000 Received: from localhost ([127.0.0.1]:33835 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yyr8k-00074N-W2 for submit@debbugs.gnu.org; Sat, 30 May 2015 20:30:11 -0400 Received: from mail2.vodafone.ie ([213.233.128.44]:24323) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yyr8e-00073L-8H for control@debbugs.gnu.org; Sat, 30 May 2015 20:30:06 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: At4iALlUalVtT7M5/2dsb2JhbABcgxAjb4FcgWKJNrZzgwCBAUwBAQEBAQGBC0EBAwGDfAoqVA0CBSECEQI6BgICCA0IAQGILQGiBI9fhWuddYEhkVwMLxKBMwWmKo8kI4FHAQEIAgGCJT2CeAIBAg Received: from unknown (HELO localhost.localdomain) ([109.79.179.57]) by mail2.vodafone.ie with ESMTP; 31 May 2015 01:29:57 +0100 Message-ID: <556A5605.60604@draigBrady.com> Date: Sun, 31 May 2015 01:29:57 +0100 From: =?UTF-8?B?UMOhZHJhaWcgQnJhZHk=?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.6.0 MIME-Version: 1.0 To: GNU bug tracker automated control server Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has identified this incoming email as possible spam. The original message has been attached to this so you can view it (if it isn't spam) or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: forcemerge 20310 20311 20312 20666 20667 20696 close 20310 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [213.233.128.44 listed in list.dnswl.org] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has identified this incoming email as possible spam. The original message has been attached to this so you can view it (if it isn't spam) or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: forcemerge 20310 20311 20312 20666 20667 20696 close 20310 [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [213.233.128.44 listed in list.dnswl.org] 1.8 MISSING_SUBJECT Missing Subject: header 0.2 NO_SUBJECT Extra score for no subject forcemerge 20310 20311 20312 20666 20667 20696 close 20310 From unknown Sun Aug 17 22:01:40 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Sun, 28 Jun 2015 11:24:05 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator