summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--lib/acl-internal.h90
-rw-r--r--lib/acl.c155
-rw-r--r--lib/acl_entries.c39
-rw-r--r--lib/file-has-acl.c87
-rw-r--r--m4/acl.m426
-rw-r--r--modules/acl4
7 files changed, 264 insertions, 159 deletions
diff --git a/ChangeLog b/ChangeLog
index 2a15f8d75d..2c8bd84525 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2007-03-19 Paul Eggert <eggert@cs.ucla.edu>
+
+ Add limited support for Solaris 10 ZFS-style ACLs: just enough to
+ handle file_has_acl.
+ * lib/acl-internal.h, lib/acl_entries.c, lib/file-has-acl.c: New files.
+ * lib/acl.c: Move header inclusions and related macro defns into
+ lib/acl-internal.h.
+ (S_ISLNK): Remove defn, since that's now done for us.
+ (file_has_acl): Move to lib/file-has-acl.c.
+ Call acl_trivial if available. This is the crucial part of the fix.
+ (acl_entries): Move to lib/acl_entries.c. Now extern, since it's
+ shared within the library. Rewrite a bit, partly to make it compatible
+ with the GNU coding style.
+ * m4/acl.m4 (AC_FUNC_ACL): Add AC_LIBOBJ([file-has-acl]).
+ Remove unnecessary double-quotes.
+ Don't test for acl_to_text; the build will catch that.
+ Replace acl_entries if it doesn't exist and it is needed.
+ Check for -lsec and acl_trivial (as used on Solaris 10).
+ * modules/acl (Files): Add lib/acl-internal.h, lib/acl_entries.c,
+ lib/file-has-acl.c.
+ (Depends-on): Add sys_stat, for S_ISLNK.
+
2007-03-19 Ben Pfaff <blp@gnu.org>
* doc/gnulib.texi: Fix typos.
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
new file mode 100644
index 0000000000..c37a7c19e7
--- /dev/null
+++ b/lib/acl-internal.h
@@ -0,0 +1,90 @@
+/* Internal implementation of access control lists.
+
+ Copyright (C) 2002, 2003, 2005, 2006, 2007 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 2, 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Written by Paul Eggert and Andreas Gruenbacher. */
+
+#include <config.h>
+
+#include "acl.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#ifdef HAVE_ACL_LIBACL_H
+# include <acl/libacl.h>
+#endif
+
+#include "error.h"
+#include "quote.h"
+
+#include <errno.h>
+#ifndef ENOSYS
+# define ENOSYS (-1)
+#endif
+#ifndef ENOTSUP
+# define ENOTSUP (-1)
+#endif
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define _(Text) Text
+#endif
+
+#ifndef HAVE_FCHMOD
+# define HAVE_FCHMOD false
+# define fchmod(fd, mode) (-1)
+#endif
+
+#ifndef MIN_ACL_ENTRIES
+# define MIN_ACL_ENTRIES 4
+#endif
+
+/* POSIX 1003.1e (draft 17) */
+#ifndef HAVE_ACL_GET_FD
+# define HAVE_ACL_GET_FD false
+# define acl_get_fd(fd) (NULL)
+#endif
+
+/* POSIX 1003.1e (draft 17) */
+#ifndef HAVE_ACL_SET_FD
+# define HAVE_ACL_SET_FD false
+# define acl_set_fd(fd, acl) (-1)
+#endif
+
+/* Linux-specific */
+#ifndef HAVE_ACL_EXTENDED_FILE
+# define HAVE_ACL_EXTENDED_FILE false
+# define acl_extended_file(name) (-1)
+#endif
+
+/* Linux-specific */
+#ifndef HAVE_ACL_FROM_MODE
+# define HAVE_ACL_FROM_MODE false
+# define acl_from_mode(mode) (NULL)
+#endif
+
+#define ACL_NOT_WELL_SUPPORTED(Errno) \
+ (Errno == ENOTSUP || Errno == ENOSYS || Errno == EINVAL)
+
+/* Define a replacement for acl_entries if needed. */
+#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE && !HAVE_ACL_ENTRIES
+# define acl_entries rpl_acl_entries
+int acl_entries (acl_t);
+#endif
diff --git a/lib/acl.c b/lib/acl.c
index 81fc470c13..84c595ab24 100644
--- a/lib/acl.c
+++ b/lib/acl.c
@@ -22,97 +22,7 @@
#include "acl.h"
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef S_ISLNK
-# define S_ISLNK(Mode) 0
-#endif
-
-#ifdef HAVE_ACL_LIBACL_H
-# include <acl/libacl.h>
-#endif
-
-#include "error.h"
-#include "quote.h"
-
-#include <errno.h>
-#ifndef ENOSYS
-# define ENOSYS (-1)
-#endif
-#ifndef ENOTSUP
-# define ENOTSUP (-1)
-#endif
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(Text) gettext (Text)
-#else
-# define _(Text) Text
-#endif
-
-#ifndef HAVE_FCHMOD
-# define HAVE_FCHMOD false
-# define fchmod(fd, mode) (-1)
-#endif
-
-/* POSIX 1003.1e (draft 17) */
-#ifndef HAVE_ACL_GET_FD
-# define HAVE_ACL_GET_FD false
-# define acl_get_fd(fd) (NULL)
-#endif
-
-/* POSIX 1003.1e (draft 17) */
-#ifndef HAVE_ACL_SET_FD
-# define HAVE_ACL_SET_FD false
-# define acl_set_fd(fd, acl) (-1)
-#endif
-
-/* Linux-specific */
-#ifndef HAVE_ACL_EXTENDED_FILE
-# define HAVE_ACL_EXTENDED_FILE false
-# define acl_extended_file(name) (-1)
-#endif
-
-/* Linux-specific */
-#ifndef HAVE_ACL_FROM_MODE
-# define HAVE_ACL_FROM_MODE false
-# define acl_from_mode(mode) (NULL)
-#endif
-
-#define ACL_NOT_WELL_SUPPORTED(Errno) \
- (Errno == ENOTSUP || Errno == ENOSYS || Errno == EINVAL)
-
-/* We detect the presence of POSIX 1003.1e (draft 17 -- abandoned) support
- by checking for HAVE_ACL_GET_FILE, HAVE_ACL_SET_FILE, and HAVE_ACL_FREE.
- Systems that have acl_get_file, acl_set_file, and acl_free must also
- have acl_to_text, acl_from_text, and acl_delete_def_file (all defined
- in the draft); systems that don't would hit #error statements here. */
-
-#if USE_ACL && HAVE_ACL_GET_FILE && !HAVE_ACL_ENTRIES
-# ifndef HAVE_ACL_TO_TEXT
-# error Must have acl_to_text (see POSIX 1003.1e draft 17).
-# endif
-
-/* Return the number of entries in ACL. Linux implements acl_entries
- as a more efficient extension than using this workaround. */
-
-static int
-acl_entries (acl_t acl)
-{
- char *text = acl_to_text (acl, NULL), *t;
- int entries;
- if (text == NULL)
- return -1;
- for (entries = 0, t = text; ; t++, entries++) {
- t = strchr (t, '\n');
- if (t == NULL)
- break;
- }
- acl_free (text);
- return entries;
-}
-#endif
+#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 fchown. On systems
@@ -128,69 +38,6 @@ chmod_or_fchmod (const char *name, int desc, mode_t mode)
return chmod (name, mode);
}
-/* Return 1 if NAME has a nontrivial access control list, 0 if
- NAME only has no or a base access control list, and -1 on
- error. SB must be set to the stat buffer of FILE. */
-
-int
-file_has_acl (char const *name, struct stat const *sb)
-{
-#if USE_ACL && HAVE_ACL && defined GETACLCNT
- /* This implementation should work on recent-enough versions of HP-UX,
- Solaris, and Unixware. */
-
-# ifndef MIN_ACL_ENTRIES
-# define MIN_ACL_ENTRIES 4
-# endif
-
- if (! S_ISLNK (sb->st_mode))
- {
- int n = acl (name, GETACLCNT, 0, NULL);
- return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
- }
-#elif USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE
- /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
-
- if (! S_ISLNK (sb->st_mode))
- {
- int ret;
-
- if (HAVE_ACL_EXTENDED_FILE)
- ret = acl_extended_file (name);
- else
- {
- acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
- if (acl)
- {
- ret = (3 < acl_entries (acl));
- acl_free (acl);
- if (ret == 0 && S_ISDIR (sb->st_mode))
- {
- acl = acl_get_file (name, ACL_TYPE_DEFAULT);
- if (acl)
- {
- ret = (0 < acl_entries (acl));
- acl_free (acl);
- }
- else
- ret = -1;
- }
- }
- else
- ret = -1;
- }
- if (ret < 0)
- return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
- return ret;
- }
-#endif
-
- /* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
- source/lib/sysacls.c file for fix-related ideas. */
-
- return 0;
-}
-
/* Copy access control lists from one file to another. If SOURCE_DESC is
a valid file descriptor, use file descriptor operations, else use
filename based operations on SRC_NAME. Likewise for DEST_DESC and
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
new file mode 100644
index 0000000000..25c8bb8250
--- /dev/null
+++ b/lib/acl_entries.c
@@ -0,0 +1,39 @@
+/* Return the number of entries in an ACL.
+
+ Copyright (C) 2002, 2003, 2005, 2006, 2007 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 2, 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Written by Paul Eggert and Andreas Gruenbacher. */
+
+#include <config.h>
+
+#include "acl-internal.h"
+
+/* Return the number of entries in ACL. */
+
+int
+acl_entries (acl_t acl)
+{
+ char *t;
+ int entries = 0;
+ char *text = acl_to_text (acl, NULL);
+ if (! text)
+ return -1;
+ for (t = text; *t; t++)
+ entries += (*t == '\n');
+ acl_free (text);
+ return entries;
+}
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
new file mode 100644
index 0000000000..218f52ec86
--- /dev/null
+++ b/lib/file-has-acl.c
@@ -0,0 +1,87 @@
+/* Test whether a file has a nontrivial access control list.
+
+ Copyright (C) 2002, 2003, 2005, 2006, 2007 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 2, 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, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Written by Paul Eggert and Andreas Gruenbacher. */
+
+#include <config.h>
+
+#include "acl.h"
+
+#include "acl-internal.h"
+
+/* Return 1 if NAME has a nontrivial access control list, 0 if NAME
+ only has no or a base access control list, and -1 (setting errno)
+ on error. SB must be set to the stat buffer of FILE. */
+
+int
+file_has_acl (char const *name, struct stat const *sb)
+{
+ if (! S_ISLNK (sb->st_mode))
+ {
+#if USE_ACL && HAVE_ACL_TRIVIAL
+
+ /* Solaris 10, which also has NFSv4 and ZFS style ACLs. */
+ return acl_trivial (name);
+
+#elif USE_ACL && HAVE_ACL && defined GETACLCNT
+
+ /* Solaris 2.5 through Solaris 9, and contemporaneous versions of
+ HP-UX and Unixware. */
+ int n = acl (name, GETACLCNT, 0, NULL);
+ return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
+
+#elif USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE
+
+ /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
+ int ret;
+
+ if (HAVE_ACL_EXTENDED_FILE)
+ ret = acl_extended_file (name);
+ else
+ {
+ acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
+ if (acl)
+ {
+ ret = (3 < acl_entries (acl));
+ acl_free (acl);
+ if (ret == 0 && S_ISDIR (sb->st_mode))
+ {
+ acl = acl_get_file (name, ACL_TYPE_DEFAULT);
+ if (acl)
+ {
+ ret = (0 < acl_entries (acl));
+ acl_free (acl);
+ }
+ else
+ ret = -1;
+ }
+ }
+ else
+ ret = -1;
+ }
+ if (ret < 0)
+ return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
+ return ret;
+#endif
+ }
+
+ /* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
+ source/lib/sysacls.c file for fix-related ideas. */
+
+ return 0;
+}
diff --git a/m4/acl.m4 b/m4/acl.m4
index c5c6e34468..6e6bd086b6 100644
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,6 +1,6 @@
# acl.m4 - check for access control list (ACL) primitives
-# Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -10,6 +10,7 @@
AC_DEFUN([AC_FUNC_ACL],
[
AC_LIBOBJ([acl])
+ AC_LIBOBJ([file-has-acl])
dnl Prerequisites of lib/acl.c.
AC_CHECK_HEADERS(sys/acl.h)
@@ -21,18 +22,33 @@ AC_DEFUN([AC_FUNC_ACL],
AC_SUBST(LIB_ACL)
AC_CHECK_HEADERS(acl/libacl.h)
AC_CHECK_FUNCS(acl_get_file acl_get_fd acl_set_file acl_set_fd \
- acl_free acl_from_mode acl_from_text acl_to_text \
- acl_delete_def_file acl_entries acl_extended_file)
- if test "$ac_cv_header_sys_acl_h" = yes; then
+ acl_free acl_from_mode acl_from_text \
+ acl_delete_def_file acl_extended_file)
+ if test $ac_cv_header_sys_acl_h = yes; then
use_acl=1
- if test "$ac_cv_func_acl_get_file" = yes; then
+ if test $ac_cv_func_acl_get_file = yes; then
# If we detect the acl_get_file bug, disable ACL support altogether.
gl_ACL_GET_FILE( , [use_acl=0])
fi
else
use_acl=0
fi
+ if test $use_acl = 1 &&
+ test $ac_cv_func_acl_get_file = yes &&
+ test $ac_cv_func_acl_free = yes; then
+ AC_REPLACE_FUNCS([acl_entries])
+ fi
LIBS="$ac_save_LIBS"
+ if test $use_acl = 1; then
+ ac_save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([acl_trivial], [sec],
+ [AC_DEFINE([HAVE_ACL_TRIVIAL], 1,
+ [Define to 1 if you have the `acl_trivial' function.])
+ test "$ac_cv_search_acl_trivial" = "none required" ||
+ LIB_ACL_TRIVIAL="$ac_cv_search_acl_trivial"])
+ AC_SUBST([LIB_ACL_TRIVIAL])
+ LIBS="$ac_save_LIBS"
+ fi
AC_DEFINE_UNQUOTED(USE_ACL, $use_acl,
[Define if you want access control list support.])
])
diff --git a/modules/acl b/modules/acl
index 969511535c..3211f307a3 100644
--- a/modules/acl
+++ b/modules/acl
@@ -4,11 +4,15 @@ Access control lists of files. (Unportable.)
Files:
lib/acl.h
lib/acl.c
+lib/acl-internal.h
+lib/acl_entries.c
+lib/file-has-acl.c
m4/acl.m4
Depends-on:
error
quote
+sys_stat
configure.ac:
AC_FUNC_ACL