The following patch is aiming to improve & simplify ACL handling in copy-acl.c Changes/Benefits: * we no longer try to decode ACLs, instead we just copy the whole xattr with ACLs making the code simpler and faster * side effect is support for NFSv4 acls Disadvantages: * it pulls in dependency on libattr. We still need dependency on libacl because of set-acl.c which would have to be cared of separately. The idea I have here is to confirm if it's safe to replace set_acl() with chmod_or_fchmod() at least in Linux. It probably has something to do with ACL inheritance. Anyhow - with this patch copy_acl() does NOT honor inherited ACLs. It copies ACLs to dest file exactly - i.e. the same way the old code worked. * we can't do any ACLs conversions, but these are not (AFAIK) being done anyway in the old code (the old code only worked with Posix)
The goal is for "cp -p" to preserve ACLs regardless of the type. I tried to experiment with variety of filesystems (posix and nfs) and it seems to me to work exactly the way the old code worked (plus handy support for NFSv4). Ondrej --- lib/copy-acl.c | 31 ++++++++++++++++++++++++++++++- m4/xattr.m4 | 43 +++++++++++++++++++++++++++++++++++++++++++ modules/acl | 1 + 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 m4/xattr.m4 diff --git a/lib/copy-acl.c b/lib/copy-acl.c index 5fc42b7f6..341d1f605 100644 --- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -29,6 +29,20 @@ #define _(msgid) gettext (msgid) +#if USE_XATTR + +# include <attr/libattr.h> + +static int +copy_attr_permissions (const char *name, struct error_context *ctx) +{ + int action = attr_copy_action (name, ctx); + return action == ATTR_ACTION_PERMISSIONS; +} + +#endif /* USE_XATTR */ + + /* 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 @@ -43,7 +57,22 @@ int copy_acl (const char *src_name, int source_desc, const char *dst_name, int dest_desc, mode_t mode) { - int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); + int ret; +#ifdef USE_XATTR + ret = chmod_or_fchmod (dst_name, dest_desc, mode); + /* Rather than fiddling with acls one by one, we just copy the whole ACL xattrs + * (Posix or NFSv4). Of course, that won't address ACLs conversion + * (i.e. posix <-> nfs4) but we can't do it anyway, so for now, we don't care + */ + if(ret == 0) + ret = source_desc <= 0 && dest_desc <= 0 + ? attr_copy_file (src_name, dst_name, copy_attr_permissions, NULL) + : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, copy_attr_permissions, NULL); +#else + /* no XATTR, so we proceed the old dusty way */ + ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); +#endif + switch (ret) { case -2: diff --git a/m4/xattr.m4 b/m4/xattr.m4 new file mode 100644 index 000000000..5f9248939 --- /dev/null +++ b/m4/xattr.m4 @@ -0,0 +1,43 @@ +# xattr.m4 - check for Extended Attributes (Linux) +# serial 4 + +# Copyright (C) 2003-2021 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. + +# Originally written by Andreas Gruenbacher. + +AC_DEFUN([gl_FUNC_XATTR], +[ + AC_ARG_ENABLE([xattr], + AS_HELP_STRING([--disable-xattr], + [do not support extended attributes]), + [use_xattr=$enableval], [use_xattr=yes]) + + LIB_XATTR= + AC_SUBST([LIB_XATTR]) + + if test "$use_xattr" = "yes"; then + AC_CHECK_HEADERS([attr/error_context.h attr/libattr.h]) + use_xattr=no + if test $ac_cv_header_attr_libattr_h = yes \ + && test $ac_cv_header_attr_error_context_h = yes; then + xattr_saved_LIBS=$LIBS + AC_SEARCH_LIBS([attr_copy_file], [attr], + [test "$ac_cv_search_attr_copy_file" = "none required" || + LIB_XATTR=$ac_cv_search_attr_copy_file]) + AC_CHECK_FUNCS([attr_copy_file]) + LIBS=$xattr_saved_LIBS + if test $ac_cv_func_attr_copy_file = yes; then + use_xattr=yes + fi + fi + if test $use_xattr = no; then + AC_MSG_WARN([libattr development library was not found or not usable.]) + AC_MSG_WARN([AC_PACKAGE_NAME will be built without xattr support.]) + fi + fi + AC_DEFINE_UNQUOTED([USE_XATTR], [`test $use_xattr != yes; echo $?`], + [Define if you want extended attribute support.]) +]) diff --git a/modules/acl b/modules/acl index 1a3a14e6c..ca2239823 100644 --- a/modules/acl +++ b/modules/acl @@ -4,6 +4,7 @@ Access control lists of files, with diagnostics. (Unportable.) Files: lib/copy-acl.c lib/set-acl.c +m4/xattr.m4 Depends-on: error -- 2.38.1