Commit 6c52e9b9 authored by Paul Eggert's avatar Paul Eggert

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.
parent cc41938a
......@@ -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
......
......@@ -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 @@
\catcode\count255=#1\relax
\advance\count255 by 1
\repeat
}
% @documentencoding sets the definition of non-ASCII characters
......
......@@ -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
}
......@@ -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
/* 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;
}
......@@ -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
......
......@@ -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>."
......
......@@ -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)
{