bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

add limited support for Solaris 10 ZFS-style ACLs to gnulib


From: Paul Eggert
Subject: add limited support for Solaris 10 ZFS-style ACLs to gnulib
Date: Mon, 19 Mar 2007 15:01:47 -0700
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Sun has seriously rethought ACLs for Solaris 10 and ZFS.  I installed
this first step at supporting them in gnulib; it's just enough to get
GNU 'ls' to work.  I have tested this on Solaris 8, Solaris 10, and
Debian stable; I haven't tested it on a Linux system supporting ACLs.

2007-03-19  Paul Eggert  <address@hidden>

        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.

Index: lib/acl-internal.h
===================================================================
RCS file: lib/acl-internal.h
diff -N lib/acl-internal.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/acl-internal.h  19 Mar 2007 21:58:54 -0000
@@ -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
Index: lib/acl_entries.c
===================================================================
RCS file: lib/acl_entries.c
diff -N lib/acl_entries.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/acl_entries.c   19 Mar 2007 21:58:54 -0000
@@ -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;
+}
Index: lib/file-has-acl.c
===================================================================
RCS file: lib/file-has-acl.c
diff -N lib/file-has-acl.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/file-has-acl.c  19 Mar 2007 21:58:54 -0000
@@ -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;
+}
Index: lib/acl.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/acl.c,v
retrieving revision 1.11
diff -u -p -r1.11 acl.c
--- lib/acl.c   4 Mar 2007 19:07:51 -0000       1.11
+++ lib/acl.c   19 Mar 2007 21:58:54 -0000
@@ -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 d
     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
Index: m4/acl.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/acl.m4,v
retrieving revision 1.9
diff -u -p -r1.9 acl.m4
--- m4/acl.m4   12 Dec 2006 15:30:05 -0000      1.9
+++ m4/acl.m4   19 Mar 2007 21:58:54 -0000
@@ -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.])
 ])
Index: modules/acl
===================================================================
RCS file: /cvsroot/gnulib/gnulib/modules/acl,v
retrieving revision 1.10
diff -u -p -r1.10 acl
--- modules/acl 1 Feb 2007 01:52:34 -0000       1.10
+++ modules/acl 19 Mar 2007 21:58:54 -0000
@@ -4,11 +4,15 @@ Access control lists of files.  (Unporta
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]