X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fcopy-acl.c;h=b4ebf7e8a8c7763eb271df20017f2228338848e4;hb=fa1db0dd22768f09a507674a30beb5b8a87bb35f;hp=eefbff768b8653638c3b56ff2ea6867fa3a6a504;hpb=fb3917caac20bdcf09b53c1f8d43d0676e5db8b2;p=gnulib.git diff --git a/lib/copy-acl.c b/lib/copy-acl.c index eefbff768..b4ebf7e8a 100644 --- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -1,6 +1,6 @@ /* copy-acl.c - copy access control list from one file to another file - Copyright (C) 2002-2003, 2005-2008 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2013 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 @@ -15,154 +15,18 @@ 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. */ + Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */ #include #include "acl.h" -#include "acl-internal.h" +#include - -/* 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. - Return -2 and set errno for an error relating to the source file. - Return -1 and set errno for an error relating to the destination file. */ - -static int -qcopy_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 - /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ - /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ - - 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 - 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); - if (ret != 0) - { - int saved_errno = errno; - - if (ACL_NOT_WELL_SUPPORTED (errno)) - { - int n = acl_entries (acl); - - acl_free (acl); - /* On most hosts with MODE_INSIDE_ACL an ACL is trivial if n == 3, - and it cannot be less than 3. - 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 * MODE_INSIDE_ACL) - { - 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); - } - 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; - -#elif 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) - return -2; - - ret = qset_acl (dst_name, dest_desc, mode); - if (ret != 0) - return -1; - - if (aclp) - { - ret = (dest_desc < 0 - ? acl_set (dst_name, aclp) - : facl_set (dest_desc, aclp)); - if (ret != 0) - { - int saved_errno = errno; - - acl_free (aclp); - errno = saved_errno; - return -1; - } - acl_free (aclp); - } - - return 0; - -#else - - return qset_acl (dst_name, dest_desc, mode); - -#endif -} +#include "quote.h" +#include "error.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) /* Copy access control lists from one file to another. If SOURCE_DESC is @@ -172,24 +36,26 @@ qcopy_acl (const char *src_name, int source_desc, const char *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. */ + Return 0 if successful, otherwise output a diagnostic and return a + negative error code. */ int copy_acl (const char *src_name, int source_desc, const char *dst_name, - int dest_desc, mode_t mode) + int dest_desc, mode_t mode) { int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); switch (ret) { case -2: error (0, errno, "%s", quote (src_name)); - return -1; + break; case -1: error (0, errno, _("preserving permissions for %s"), quote (dst_name)); - return -1; + break; default: - return 0; + break; } + return ret; }