changeset 10108:bf329a08180c

Split off copy_acl function to separate file.
author Bruno Haible <bruno@clisp.org>
date Fri, 23 May 2008 00:13:07 +0200
parents 0f973047765d
children 29794e333189
files ChangeLog lib/acl.c lib/copy-acl.c m4/acl.m4 modules/acl
diffstat 5 files changed, 180 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-05-22  Bruno Haible  <bruno@clisp.org>
+
+	Split off copy_acl function to separate file.
+	* lib/copy-acl.c: New file, extracted from lib/acl.c.
+	* lib/acl.c (copy_acl): Moved function to separate file.
+	* m4/acl.m4 (gl_FUNC_ACL): Remove unconditional AC_LIBOBJs.
+	* modules/acl (Files): Add lib/copy-acl.c.
+	(Makefiles.am): Augment lib_SOURCES.
+
 2008-05-22  Bruno Haible  <bruno@clisp.org>
 
 	* modules/copy-file-tests: New file.
--- a/lib/acl.c
+++ b/lib/acl.c
@@ -1,6 +1,6 @@
 /* acl.c - access control lists
 
-   Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2002-2003, 2005-2008 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
@@ -37,149 +37,6 @@
     return chmod (name, mode);
 }
 
-/* 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
-   DST_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, otherwise output a diagnostic and return -1.  */
-
-int
-copy_acl (const char *src_name, int source_desc, const char *dst_name,
-	  int dest_desc, mode_t mode)
-{
-  int ret;
-
-#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
-  /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
-
-  acl_t acl;
-  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_NOT_WELL_SUPPORTED (errno))
-	return set_acl (dst_name, dest_desc, mode);
-      else
-        {
-	  error (0, errno, "%s", quote (src_name));
-	  return -1;
-	}
-    }
-
-  if (HAVE_ACL_SET_FD && dest_desc != -1)
-    ret = acl_set_fd (dest_desc, acl);
-  else
-    ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
-  if (ret != 0)
-    {
-      int saved_errno = errno;
-
-      if (ACL_NOT_WELL_SUPPORTED (errno))
-        {
-	  int n = acl_entries (acl);
-
-	  acl_free (acl);
-	  /* On most hosts an ACL is trivial if n == 3, and it cannot be
-	     less than 3.  On IRIX 6.5 it is also trivial if n == -1.
-	     For simplicity and safety, assume the ACL is trivial if n <= 3.
-	     Also see file-has-acl.c for some of the other possibilities;
-	     it's not clear whether that complexity is needed here.  */
-	  if (n <= 3)
-	    {
-	      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
-		saved_errno = errno;
-	      else
-		return 0;
-	    }
-	  else
-	    chmod_or_fchmod (dst_name, dest_desc, mode);
-	}
-      else
-	{
-	  acl_free (acl);
-	  chmod_or_fchmod (dst_name, dest_desc, mode);
-	}
-      error (0, saved_errno, _("preserving permissions for %s"),
-	     quote (dst_name));
-      return -1;
-    }
-  else
-    acl_free (acl);
-
-  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
-    {
-      /* We did not call chmod so far, so the special bits have not yet
-         been set.  */
-
-      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
-	{
-	  error (0, errno, _("preserving permissions for %s"),
-		 quote (dst_name));
-	  return -1;
-	}
-    }
-
-  if (S_ISDIR (mode))
-    {
-      acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
-      if (acl == NULL)
-	{
-	  error (0, errno, "%s", quote (src_name));
-	  return -1;
-	}
-
-      if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
-	{
-	  error (0, errno, _("preserving permissions for %s"),
-		 quote (dst_name));
-	  acl_free (acl);
-	  return -1;
-	}
-      else
-        acl_free (acl);
-    }
-  return 0;
-
-#else
-
-# if USE_ACL && defined ACL_NO_TRIVIAL
-  /* Solaris 10 NFSv4 ACLs.  */
-  acl_t *aclp = NULL;
-  ret = (source_desc < 0
-	 ? acl_get (src_name, ACL_NO_TRIVIAL, &aclp)
-	 : facl_get (source_desc, ACL_NO_TRIVIAL, &aclp));
-  if (ret != 0 && errno != ENOSYS)
-    {
-      error (0, errno, "%s", quote (src_name));
-      return ret;
-    }
-# endif
-
-  ret = qset_acl (dst_name, dest_desc, mode);
-  if (ret != 0)
-    error (0, errno, _("preserving permissions for %s"), quote (dst_name));
-
-# if USE_ACL && defined ACL_NO_TRIVIAL
-  if (ret == 0 && aclp)
-    {
-      ret = (dest_desc < 0
-	     ? acl_set (dst_name, aclp)
-	     : facl_set (dest_desc, aclp));
-      if (ret != 0)
-	error (0, errno, _("preserving permissions for %s"), quote (dst_name));
-      acl_free (aclp);
-    }
-# endif
-
-  return ret;
-#endif
-}
-
 /* 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
new file mode 100644
--- /dev/null
+++ b/lib/copy-acl.c
@@ -0,0 +1,167 @@
+/* copy-acl.c - copy access control list from one file to another file
+
+   Copyright (C) 2002-2003, 2005-2008 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 and Andreas Gruenbacher.  */
+
+#include <config.h>
+
+#include "acl.h"
+
+#include "acl-internal.h"
+
+/* 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
+   DST_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, otherwise output a diagnostic and return -1.  */
+
+int
+copy_acl (const char *src_name, int source_desc, const char *dst_name,
+	  int dest_desc, mode_t mode)
+{
+  int ret;
+
+#if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
+  /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
+
+  acl_t acl;
+  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_NOT_WELL_SUPPORTED (errno))
+	return set_acl (dst_name, dest_desc, mode);
+      else
+        {
+	  error (0, errno, "%s", quote (src_name));
+	  return -1;
+	}
+    }
+
+  if (HAVE_ACL_SET_FD && dest_desc != -1)
+    ret = acl_set_fd (dest_desc, acl);
+  else
+    ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
+  if (ret != 0)
+    {
+      int saved_errno = errno;
+
+      if (ACL_NOT_WELL_SUPPORTED (errno))
+        {
+	  int n = acl_entries (acl);
+
+	  acl_free (acl);
+	  /* On most hosts an ACL is trivial if n == 3, and it cannot be
+	     less than 3.  On IRIX 6.5 it is also trivial if n == -1.
+	     For simplicity and safety, assume the ACL is trivial if n <= 3.
+	     Also see file-has-acl.c for some of the other possibilities;
+	     it's not clear whether that complexity is needed here.  */
+	  if (n <= 3)
+	    {
+	      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
+		saved_errno = errno;
+	      else
+		return 0;
+	    }
+	  else
+	    chmod_or_fchmod (dst_name, dest_desc, mode);
+	}
+      else
+	{
+	  acl_free (acl);
+	  chmod_or_fchmod (dst_name, dest_desc, mode);
+	}
+      error (0, saved_errno, _("preserving permissions for %s"),
+	     quote (dst_name));
+      return -1;
+    }
+  else
+    acl_free (acl);
+
+  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
+    {
+      /* We did not call chmod so far, so the special bits have not yet
+         been set.  */
+
+      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
+	{
+	  error (0, errno, _("preserving permissions for %s"),
+		 quote (dst_name));
+	  return -1;
+	}
+    }
+
+  if (S_ISDIR (mode))
+    {
+      acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
+      if (acl == NULL)
+	{
+	  error (0, errno, "%s", quote (src_name));
+	  return -1;
+	}
+
+      if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
+	{
+	  error (0, errno, _("preserving permissions for %s"),
+		 quote (dst_name));
+	  acl_free (acl);
+	  return -1;
+	}
+      else
+        acl_free (acl);
+    }
+  return 0;
+
+#else
+
+# if USE_ACL && defined ACL_NO_TRIVIAL
+  /* Solaris 10 NFSv4 ACLs.  */
+  acl_t *aclp = NULL;
+  ret = (source_desc < 0
+	 ? acl_get (src_name, ACL_NO_TRIVIAL, &aclp)
+	 : facl_get (source_desc, ACL_NO_TRIVIAL, &aclp));
+  if (ret != 0 && errno != ENOSYS)
+    {
+      error (0, errno, "%s", quote (src_name));
+      return ret;
+    }
+# endif
+
+  ret = qset_acl (dst_name, dest_desc, mode);
+  if (ret != 0)
+    error (0, errno, _("preserving permissions for %s"), quote (dst_name));
+
+# if USE_ACL && defined ACL_NO_TRIVIAL
+  if (ret == 0 && aclp)
+    {
+      ret = (dest_desc < 0
+	     ? acl_set (dst_name, aclp)
+	     : facl_set (dest_desc, aclp));
+      if (ret != 0)
+	error (0, errno, _("preserving permissions for %s"), quote (dst_name));
+      acl_free (aclp);
+    }
+# endif
+
+  return ret;
+#endif
+}
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,5 +1,5 @@
 # acl.m4 - check for access control list (ACL) primitives
-# serial 2
+# serial 3
 
 # Copyright (C) 2002, 2004-2008 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -10,9 +10,6 @@
 
 AC_DEFUN([gl_FUNC_ACL],
 [
-  AC_LIBOBJ([acl])
-  AC_LIBOBJ([file-has-acl])
-
   AC_ARG_ENABLE([acl],
     AS_HELP_STRING([--disable-acl], [do not support ACLs]),
     , [enable_acl=auto])
--- a/modules/acl
+++ b/modules/acl
@@ -6,6 +6,7 @@
 lib/acl.c
 lib/acl-internal.h
 lib/acl_entries.c
+lib/copy-acl.c
 lib/file-has-acl.c
 m4/acl.m4
 
@@ -19,6 +20,7 @@
 gl_FUNC_ACL
 
 Makefile.am:
+lib_SOURCES += acl.c copy-acl.c file-has-acl.c
 
 Include:
 "acl.h"