From d2e44433024a93cef7e6f6d572f2b9d81b3bc9b6 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 23 May 2008 00:13:07 +0200 Subject: [PATCH] Split off copy_acl function to separate file. --- ChangeLog | 9 ++++ lib/acl.c | 145 +------------------------------------------------ lib/copy-acl.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ m4/acl.m4 | 5 +- modules/acl | 2 + 5 files changed, 180 insertions(+), 148 deletions(-) create mode 100644 lib/copy-acl.c diff --git a/ChangeLog b/ChangeLog index 2d7f14905..1c11e4a75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2008-05-22 Bruno Haible + 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 + * modules/copy-file-tests: New file. * tests/test-copy-file.sh: New file. * tests/test-copy-file.c: New file. diff --git a/lib/acl.c b/lib/acl.c index b40e43a17..10499a0bb 100644 --- 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 @@ chmod_or_fchmod (const char *name, int desc, mode_t mode) 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 diff --git a/lib/copy-acl.c b/lib/copy-acl.c new file mode 100644 index 000000000..f5a879db3 --- /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 . + + Written by Paul Eggert and Andreas Gruenbacher. */ + +#include + +#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 +} diff --git a/m4/acl.m4 b/m4/acl.m4 index 7b7cb640c..2916a0057 100644 --- 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]) diff --git a/modules/acl b/modules/acl index 03a221799..9a7f27755 100644 --- a/modules/acl +++ b/modules/acl @@ -6,6 +6,7 @@ lib/acl.h 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 @@ configure.ac: gl_FUNC_ACL Makefile.am: +lib_SOURCES += acl.c copy-acl.c file-has-acl.c Include: "acl.h" -- 2.11.0