summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2015-05-27 17:46:15 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2015-05-27 17:55:06 -0700
commit6c52e9b93b68795d1876718d8f3c1d57bf7f6d91 (patch)
treeb2d93b1121c05cfffa59df9325139cdf56eed6c0
parentcc41938ae0f5694d657f360f19dd9ac166271db2 (diff)
Merge from gnulib
This incorporates: 2015-05-27 qacl: Reimplement qset_acl and qcopy_acl (Bug#20666) 2015-05-27 file-has-acl: Split feature tests again (Bug#20667) 2015-05-27 string: fix build failure on BSD/OSX with FORTIFY_SOURCE 2015-05-26 stdio: limit __gnu_printf__ witness to gcc 4.4+ 2015-05-26 inttypes: force correct mingw PRIdMAX even without <stdio.h> 2015-05-26 stdio: fix probe on mingw under gcc 5.1 * admin/merge-gnulib (GNULIB_MODULES): Replace qacl with qcopy-acl, since we don't need the rest of qacl. * doc/misc/texinfo.tex, lib/acl-internal.c, lib/acl-internal.h: * lib/inttypes.in.h, lib/qcopy-acl.c, lib/qset-acl.c: * lib/string.in.h, m4/acl.m4, m4/stdio_h.m4: Get latest versions from gnulib. * lib/get-permissions.c, lib/set-permissions.c: New files. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * nt/gnulib.mk: Merge lib/gnulib.mk changes by hand.
-rwxr-xr-xadmin/merge-gnulib2
-rw-r--r--doc/misc/texinfo.tex3
-rw-r--r--lib/acl-internal.c31
-rw-r--r--lib/acl-internal.h57
-rw-r--r--lib/get-permissions.c280
-rw-r--r--lib/gnulib.mk23
-rw-r--r--lib/inttypes.in.h4
-rw-r--r--lib/qcopy-acl.c531
-rw-r--r--lib/set-permissions.c (renamed from lib/qset-acl.c)805
-rw-r--r--lib/string.in.h21
-rw-r--r--m4/acl.m424
-rw-r--r--m4/gnulib-comp.m48
-rw-r--r--m4/stdio_h.m420
-rw-r--r--nt/gnulib.mk23
14 files changed, 924 insertions, 908 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index e63422b0d5..e7910a642c 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -34,7 +34,7 @@ GNULIB_MODULES='
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
intprops largefile lstat
manywarnings memrchr mkostemp mktime
- pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat
+ pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
sig2str socklen stat-time stdalign stddef stdio
stpcpy strftime strtoimax strtoumax symlink sys_stat
sys_time time time_r timer-time timespec-add timespec-sub
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index 152e985348..4b4856469a 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,7 +3,7 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2015-05-06.11}
+\def\texinfoversion{2015-05-26.15}
%
% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
@@ -8954,7 +8954,6 @@ directory should work if nowhere else does.}
\catcode\count255=#1\relax
\advance\count255 by 1
\repeat
-
}
% @documentencoding sets the definition of non-ASCII characters
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index d9bd4461ea..1a2f8c44bf 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -467,3 +467,34 @@ 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 9b9fae2e9e..11fdea1404 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 0000000000..ccee1f1410
--- /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 <http://www.gnu.org/licenses/>.
+
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
+
+#include <config.h>
+
+#include <string.h>
+#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 <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view>
+ 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/gnulib.mk b/lib/gnulib.mk
index bec0d3bb19..95f2f8b48a 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -42,6 +42,17 @@ HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
## end gnulib module absolute-header
+## begin gnulib module acl-permissions
+
+libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c \
+ get-permissions.c set-permissions.c
+
+EXTRA_DIST += acl-internal.h acl.h acl_entries.c
+
+EXTRA_libgnu_a_SOURCES += acl_entries.c
+
+## end gnulib module acl-permissions
+
## begin gnulib module alloca-opt
BUILT_SOURCES += $(ALLOCA_H)
@@ -696,15 +707,11 @@ EXTRA_libgnu_a_SOURCES += putenv.c
## end gnulib module putenv
-## begin gnulib module qacl
-
-libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c
+## begin gnulib module qcopy-acl
-EXTRA_DIST += acl-internal.h acl.h acl_entries.c
-
-EXTRA_libgnu_a_SOURCES += acl_entries.c
+libgnu_a_SOURCES += qcopy-acl.c
-## end gnulib module qacl
+## end gnulib module qcopy-acl
## begin gnulib module readlink
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index 13a72bee90..78846f6968 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -51,6 +51,10 @@
#endif
/* Get CHAR_BIT. */
#include <limits.h>
+/* On mingw, __USE_MINGW_ANSI_STDIO only works if <stdio.h> is also included */
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# include <stdio.h>
+#endif
#if !(INT_MIN == INT32_MIN && INT_MAX == INT32_MAX)
# error "This file assumes that 'int' has exactly 32 bits. Please report your platform and compiler to <bug-gnulib@gnu.org>."
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index bc258ba560..c450742471 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 <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view>
- 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/set-permissions.c
index bb4b0b261a..47cb91ca16 100644
--- a/lib/qset-acl.c
+++ b/lib/set-permissions.c
@@ -1,4 +1,4 @@
-/* qset-acl.c - set access control list equivalent to a mode
+/* set-permissions.c - set permissions of a file
Copyright (C) 2002-2003, 2005-2015 Free Software Foundation, Inc.
@@ -15,182 +15,43 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
- Written by Paul Eggert and Andreas Gruenbacher, and Bruno Haible. */
+ Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
#include <config.h>
-#define ACL_INTERNAL_INLINE _GL_EXTERN_INLINE
-
#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
- available, fchmod the target file to MODE. Also sets the
- non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX)
- to those from MODE if any are set.
- Return 0 if successful. Return -1 and set errno upon failure. */
-
-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;
- 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);
+# 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
-# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
-
- int done_setacl = 0;
+ 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). */
@@ -365,53 +226,53 @@ qset_acl (char const *name, int desc, mode_t mode)
if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
{
if (errno == ENOSYS)
- return chmod_or_fchmod (name, desc, mode);
+ {
+ *must_chmod = true;
+ return 0;
+ }
return -1;
}
if (ret == 0)
- done_setacl = 1;
+ return 0;
}
# 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;
+ {
+ 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;
-# elif HAVE_GETACL /* HP-UX */
+ 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;
@@ -422,87 +283,60 @@ qset_acl (char const *name, int desc, mode_t mode)
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;
+ 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 */
- {
- 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;
- }
+static int
+context_aclv_from_mode (struct permission_context *ctx)
+{
+ int ret;
- 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
- }
+ 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;
- 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;
+ 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)
- return chmod_or_fchmod (name, desc, mode);
+ {
+ *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? */
@@ -599,78 +433,401 @@ qset_acl (char const *name, int desc, mode_t mode)
return ret;
}
- return chmod_or_fchmod (name, desc, mode);
+ *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;
+}
- union { struct acl a; char room[128]; } u;
+# elif HAVE_ACLSORT /* NonStop Kernel */
+static int
+context_acl_from_mode (struct permission_context *ctx)
+{
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;
+ 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;
- if (desc != -1)
- ret = fchacl (desc, &u.a, u.a.acl_len);
+ 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
- ret = chacl (name, &u.a, u.a.acl_len);
+ {
+ 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;
- if (ret < 0 && errno == ENOSYS)
- return chmod_or_fchmod (name, desc, mode);
+# endif
- return ret;
+# elif defined GETACL /* Solaris, Cygwin, not HP-UX */
-# elif HAVE_ACLSORT /* NonStop Kernel */
+ /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
+ of Unixware. The acl() call returns the access and default ACL both
+ at once. */
- struct acl entries[4];
- int ret;
+ /* If both ace_entries and entries are available, try SETACL before
+ ACE_SETACL, because SETACL cannot fail with ENOTSUP whereas ACE_SETACL
+ can. */
- 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;
+ if (from_mode)
+ return set_acls_from_mode (name, desc, ctx->mode, must_chmod);
- ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries);
- if (ret > 0)
- abort ();
- if (ret < 0)
+ if (ret == 0 && ctx->count)
{
- if (0)
- return chmod_or_fchmod (name, desc, mode);
- return -1;
+ 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;
}
- ret = acl ((char *) name, ACL_SET,
- sizeof (entries) / sizeof (struct acl), entries);
- if (ret < 0)
+# ifdef ACE_GETACL
+ if (ret == 0 && ctx->ace_count)
{
- if (0)
- return chmod_or_fchmod (name, desc, mode);
- return -1;
+ 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 (mode & (S_ISUID | S_ISGID | S_ISVTX))
+ if (from_mode)
+ ret = context_acl_from_mode (ctx, name, desc);
+
+ if (ret == 0 && ctx->count > 0)
{
- /* We did not call chmod so far, so the special bits have not yet
- been set. */
- return chmod_or_fchmod (name, desc, mode);
+ 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;
}
- return 0;
-# else /* Unknown flavor of ACLs */
- return chmod_or_fchmod (name, desc, mode);
+# 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 /* !USE_ACL */
- return chmod_or_fchmod (name, desc, mode);
+#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/lib/string.in.h b/lib/string.in.h
index ebd727eda1..2abd6bc0e1 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -15,16 +15,32 @@
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. */
-#ifndef _@GUARD_PREFIX@_STRING_H
-
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@
+#if defined _GL_ALREADY_INCLUDING_STRING_H
+/* Special invocation convention:
+ - On OS X/NetBSD we have a sequence of nested includes
+ <string.h> -> <strings.h> -> "string.h"
+ In this situation system _chk variants due to -D_FORTIFY_SOURCE
+ might be used after any replacements defined here. */
+
+#@INCLUDE_NEXT@ @NEXT_STRING_H@
+
+#else
+/* Normal invocation convention. */
+
+#ifndef _@GUARD_PREFIX@_STRING_H
+
+#define _GL_ALREADY_INCLUDING_STRING_H
+
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_STRING_H@
+#undef _GL_ALREADY_INCLUDING_STRING_H
+
#ifndef _@GUARD_PREFIX@_STRING_H
#define _@GUARD_PREFIX@_STRING_H
@@ -1027,3 +1043,4 @@ _GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - "
#endif /* _@GUARD_PREFIX@_STRING_H */
#endif /* _@GUARD_PREFIX@_STRING_H */
+#endif
diff --git a/m4/acl.m4 b/m4/acl.m4
index b8f4660f7e..5da6a43ab6 100644
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,5 +1,5 @@
# acl.m4 - check for access control list (ACL) primitives
-# serial 19
+# serial 20
# Copyright (C) 2002, 2004-2015 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
@@ -181,26 +181,12 @@ AC_DEFUN([gl_FILE_HAS_ACL],
[
AC_REQUIRE([gl_FUNC_ACL_ARG])
if test "$enable_acl" != no; then
- AC_CACHE_CHECK([for getxattr with XATTR_NAME_POSIX_ACL macros],
- [gl_cv_getxattr_with_posix_acls],
- [gl_cv_getxattr_with_posix_acls=no
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM(
- [[#include <sys/types.h>
- #include <sys/xattr.h>
- #include <linux/xattr.h>
- ]],
- [[ssize_t a = getxattr (".", XATTR_NAME_POSIX_ACL_ACCESS, 0, 0);
- ssize_t b = getxattr (".", XATTR_NAME_POSIX_ACL_DEFAULT, 0, 0);
- return a < 0 || b < 0;
- ]])],
- [gl_cv_getxattr_with_posix_acls=yes])])
+ AC_CHECK_HEADERS([linux/xattr.h])
+ AC_CHECK_HEADERS([sys/xattr.h],
+ [AC_CHECK_FUNCS([getxattr])])
fi
- if test "$gl_cv_getxattr_with_posix_acls" = yes; then
+ if test "$ac_cv_header_sys_xattr_h,$ac_cv_func_getxattr" = yes,yes; then
LIB_HAS_ACL=
- AC_DEFINE([GETXATTR_WITH_POSIX_ACLS], 1,
- [Define to 1 if getxattr works with XATTR_NAME_POSIX_ACL_ACCESS
- and XATTR_NAME_POSIX_ACL_DEFAULT.])
else
dnl Set gl_need_lib_has_acl to a nonempty value, so that any
dnl later gl_FUNC_ACL call will set LIB_HAS_ACL=$LIB_ACL.
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 06636cfe76..0425d02241 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -39,6 +39,7 @@ AC_DEFUN([gl_EARLY],
m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable
AC_REQUIRE([gl_PROG_AR_RANLIB])
# Code from module absolute-header:
+ # Code from module acl-permissions:
# Code from module alloca-opt:
# Code from module allocator:
# Code from module at-internal:
@@ -105,7 +106,7 @@ AC_DEFUN([gl_EARLY],
# Code from module pselect:
# Code from module pthread_sigmask:
# Code from module putenv:
- # Code from module qacl:
+ # Code from module qcopy-acl:
# Code from module readlink:
# Code from module readlinkat:
# Code from module root-uid:
@@ -172,6 +173,7 @@ AC_DEFUN([gl_INIT],
m4_pushdef([gl_LIBSOURCES_DIR], [])
gl_COMMON
gl_source_base='lib'
+ gl_FUNC_ACL
gl_FUNC_ALLOCA
gl_BYTESWAP
AC_CHECK_FUNCS_ONCE([readlinkat])
@@ -317,7 +319,6 @@ AC_DEFUN([gl_INIT],
gl_PREREQ_PUTENV
fi
gl_STDLIB_MODULE_INDICATOR([putenv])
- gl_FUNC_ACL
gl_FUNC_READLINK
if test $HAVE_READLINK = 0 || test $REPLACE_READLINK = 1; then
AC_LIBOBJ([readlink])
@@ -865,6 +866,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/fsync.c
lib/ftoastr.c
lib/ftoastr.h
+ lib/get-permissions.c
lib/getdtablesize.c
lib/getgroups.c
lib/getloadavg.c
@@ -895,11 +897,11 @@ AC_DEFUN([gl_FILE_LIST], [
lib/pthread_sigmask.c
lib/putenv.c
lib/qcopy-acl.c
- lib/qset-acl.c
lib/readlink.c
lib/readlinkat.c
lib/root-uid.h
lib/secure_getenv.c
+ lib/set-permissions.c
lib/sha1.c
lib/sha1.h
lib/sha256.c
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index e0c4bde1f8..f60cc2156e 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 44
+# stdio_h.m4 serial 46
dnl Copyright (C) 2007-2015 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -15,15 +15,21 @@ AC_DEFUN([gl_STDIO_H],
dnl Determine whether __USE_MINGW_ANSI_STDIO makes printf and
dnl inttypes.h behave like gnu instead of system; we must give our
dnl printf wrapper the right attribute to match.
- AC_CACHE_CHECK([whether inttypes macros match system or gnu printf],
+ AC_CACHE_CHECK([which flavor of printf attribute matches inttypes macros],
[gl_cv_func_printf_attribute_flavor],
- [AC_EGREP_CPP([findme .(ll|j)d. findme],
- [#define __STDC_FORMAT_MACROS 1
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #define __STDC_FORMAT_MACROS 1
#include <stdio.h>
#include <inttypes.h>
- findme PRIdMAX findme
- ], [gl_cv_func_printf_attribute_flavor=gnu],
- [gl_cv_func_printf_attribute_flavor=system])])
+ /* For non-mingw systems, compilation will trivially succeed.
+ For mingw, compilation will succeed for older mingw (system
+ printf, "I64d") and fail for newer mingw (gnu printf, "lld"). */
+ #if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+ extern char PRIdMAX_probe[sizeof PRIdMAX == sizeof "I64d" ? 1 : -1];
+ #endif
+ ]])], [gl_cv_func_printf_attribute_flavor=system],
+ [gl_cv_func_printf_attribute_flavor=gnu])])
if test "$gl_cv_func_printf_attribute_flavor" = gnu; then
AC_DEFINE([GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU], [1],
[Define to 1 if printf and friends should be labeled with
diff --git a/nt/gnulib.mk b/nt/gnulib.mk
index 26a9ea9ad5..cab20d911b 100644
--- a/nt/gnulib.mk
+++ b/nt/gnulib.mk
@@ -43,7 +43,7 @@
# the same distribution terms as the rest of that program.
#
# Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
MOSTLYCLEANFILES += core *.stackdump
@@ -64,6 +64,17 @@ HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
## end gnulib module absolute-header
+## begin gnulib module acl-permissions
+
+libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c \
+ get-permissions.c set-permissions.c
+
+EXTRA_DIST += acl-internal.h acl.h acl_entries.c
+
+EXTRA_libgnu_a_SOURCES += acl_entries.c
+
+## end gnulib module acl-permissions
+
## begin gnulib module alloca-opt
BUILT_SOURCES += $(ALLOCA_H)
@@ -521,15 +532,11 @@ EXTRA_libgnu_a_SOURCES += putenv.c
## end gnulib module putenv
-## begin gnulib module qacl
-
-libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c
+## begin gnulib module qcopy-acl
-EXTRA_DIST += acl-internal.h acl.h acl_entries.c
-
-EXTRA_libgnu_a_SOURCES += acl_entries.c
+libgnu_a_SOURCES += qcopy-acl.c
-## end gnulib module qacl
+## end gnulib module qcopy-acl
## begin gnulib module readlink