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.
This commit is contained in:
parent
cc41938ae0
commit
6c52e9b93b
14 changed files with 936 additions and 920 deletions
|
@ -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
|
||||
|
|
280
lib/get-permissions.c
Normal file
280
lib/get-permissions.c
Normal file
|
@ -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;
|
||||
|
||||
}
|
|
@ -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
|
||||
## begin gnulib module qcopy-acl
|
||||
|
||||
libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c qset-acl.c
|
||||
libgnu_a_SOURCES += qcopy-acl.c
|
||||
|
||||
EXTRA_DIST += acl-internal.h acl.h acl_entries.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += acl_entries.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>."
|
||||
|
|
531
lib/qcopy-acl.c
531
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;
|
||||
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_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);
|
||||
ret = get_permissions (src_name, source_desc, mode, &ctx);
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
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';
|
||||
|
||||
int done_setacl = 0;
|
||||
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;
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
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];
|
||||
static int
|
||||
context_aclv_from_mode (struct permission_context *ctx)
|
||||
{
|
||||
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;
|
||||
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 ();
|
||||
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;
|
||||
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 */
|
||||
|
||||
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);
|
||||
|
||||
return ret;
|
||||
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 */
|
||||
|
||||
struct acl entries[4];
|
||||
static int
|
||||
context_acl_from_mode (struct permission_context *ctx)
|
||||
{
|
||||
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;
|
||||
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 ();
|
||||
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
|
||||
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;
|
||||
}
|
|
@ -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
|
||||
|
|
24
m4/acl.m4
24
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
23
nt/gnulib.mk
23
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
|
||||
## begin gnulib module qcopy-acl
|
||||
|
||||
libgnu_a_SOURCES += acl-errno-valid.c acl-internal.c qcopy-acl.c
|
||||
libgnu_a_SOURCES += qcopy-acl.c
|
||||
|
||||
EXTRA_DIST += acl-internal.h acl.h acl_entries.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += acl_entries.c
|
||||
|
||||
## end gnulib module qacl
|
||||
## end gnulib module qcopy-acl
|
||||
|
||||
## begin gnulib module readlink
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue