Hi Bruno, Please review now. Ondrej --- lib/qcopy-acl.c | 36 ++++++++++++++++++++++++++++++++++- m4/xattr.m4 | 42 +++++++++++++++++++++++++++++++++++++++++ modules/acl | 1 + modules/acl-tests | 6 +++--- modules/copy-file | 1 + modules/copy-file-tests | 2 +- modules/qacl | 3 +++ modules/qcopy-acl | 3 +++ modules/supersede | 1 + modules/supersede-tests | 2 +- 10 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 m4/xattr.m4
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c index 883bcf7d58..44980b71a4 100644 --- a/lib/qcopy-acl.c +++ b/lib/qcopy-acl.c @@ -23,6 +23,20 @@ #include "acl-internal.h" +#if USE_XATTR + +# include <attr/libattr.h> + +/* Returns 1 if NAME is the name of an extended attribute that is related + to permissions, i.e. ACLs. Returns 0 otherwise. */ + +static int +is_attr_permissions (const char *name, struct error_context *ctx) +{ + return attr_copy_action (name, ctx) == 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 @@ -39,13 +53,33 @@ int qcopy_acl (const char *src_name, int source_desc, const char *dst_name, int dest_desc, mode_t mode) { - struct permission_context ctx; int ret; +#ifdef USE_XATTR + /* in case no ACLs present and also to set higher mode bits + we chmod before setting ACLs as doing it after could overwrite them + (especially true for NFSv4, posix ACL has that ugly "mask" hack that + nobody understands) */ + 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 + Functions attr_copy_* return 0 in case we copied something OR nothing + to copy */ + if (ret == 0) + ret = source_desc <= 0 || dest_desc <= 0 + ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) + : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, + is_attr_permissions, NULL); +#else + /* no XATTR, so we proceed the old dusty way */ + struct permission_context ctx; + ret = get_permissions (src_name, source_desc, mode, &ctx); if (ret != 0) return -2; ret = set_permissions (&ctx, dst_name, dest_desc); free_permission_context (&ctx); +#endif return ret; } diff --git a/m4/xattr.m4 b/m4/xattr.m4 new file mode 100644 index 0000000000..6efdfa475a --- /dev/null +++ b/m4/xattr.m4 @@ -0,0 +1,42 @@ +# 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. + +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 + if test $use_xattr = yes; then + AC_DEFINE_UNQUOTED([USE_XATTR], 1) + fi +]) diff --git a/modules/acl b/modules/acl index 1a3a14e6c2..7edfb1e77d 100644 --- a/modules/acl +++ b/modules/acl @@ -22,6 +22,7 @@ Include: Link: $(LIB_MBRTOWC) +$(LIB_XATTR) License: GPL diff --git a/modules/acl-tests b/modules/acl-tests index e4173fe9ae..1d8d84d299 100644 --- a/modules/acl-tests +++ b/modules/acl-tests @@ -25,6 +25,6 @@ TESTS += \ test-copy-acl.sh test-copy-acl-1.sh test-copy-acl-2.sh TESTS_ENVIRONMENT += USE_ACL=$(USE_ACL) check_PROGRAMS += test-set-mode-acl test-copy-acl test-sameacls -test_set_mode_acl_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ $(LIB_MBRTOWC) -test_copy_acl_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ $(LIB_MBRTOWC) -test_sameacls_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ $(LIB_MBRTOWC) +test_set_mode_acl_LDADD = $(LDADD) $(LIB_ACL) $(LIB_XATTR) @LIBINTL@ $(LIB_MBRTOWC) +test_copy_acl_LDADD = $(LDADD) $(LIB_ACL) $(LIB_XATTR) @LIBINTL@ $(LIB_MBRTOWC) +test_sameacls_LDADD = $(LDADD) $(LIB_ACL) $(LIB_XATTR) @LIBINTL@ $(LIB_MBRTOWC) diff --git a/modules/copy-file b/modules/copy-file index 6140c72fa1..0a86a15889 100644 --- a/modules/copy-file +++ b/modules/copy-file @@ -37,6 +37,7 @@ Include: Link: $(LIB_MBRTOWC) +$(LIB_XATTR) License: GPL diff --git a/modules/copy-file-tests b/modules/copy-file-tests index a0788755f1..dc598b24f3 100644 --- a/modules/copy-file-tests +++ b/modules/copy-file-tests @@ -18,4 +18,4 @@ Makefile.am: TESTS += test-copy-file.sh test-copy-file-1.sh test-copy-file-2.sh TESTS_ENVIRONMENT += USE_ACL=$(USE_ACL) check_PROGRAMS += test-copy-file -test_copy_file_LDADD = $(LDADD) $(LIB_ACL) $(LIB_CLOCK_GETTIME) @LIBINTL@ $(LIB_MBRTOWC) +test_copy_file_LDADD = $(LDADD) $(LIB_ACL) $(LIB_XATTR) $(LIB_CLOCK_GETTIME) @LIBINTL@ $(LIB_MBRTOWC) diff --git a/modules/qacl b/modules/qacl index 45753c7623..7cfd9f3fbc 100644 --- a/modules/qacl +++ b/modules/qacl @@ -15,6 +15,9 @@ Makefile.am: Include: +Link: +$(LIB_XATTR) + License: GPL diff --git a/modules/qcopy-acl b/modules/qcopy-acl index c0e5b6a8f8..dcd610464b 100644 --- a/modules/qcopy-acl +++ b/modules/qcopy-acl @@ -3,11 +3,13 @@ Copy access control list from one file to another. (Unportable.) Files: lib/qcopy-acl.c +m4/xattr.m4 Depends-on: acl-permissions configure.ac: +gl_FUNC_XATTR Makefile.am: lib_SOURCES += qcopy-acl.c @@ -17,6 +19,7 @@ Include: Link: $(LIB_ACL) +$(LIB_XATTR) License: GPL diff --git a/modules/supersede b/modules/supersede index 70f3fdc482..5c6ccafe5c 100644 --- a/modules/supersede +++ b/modules/supersede @@ -38,6 +38,7 @@ Link: $(LIB_GETRANDOM) $(LIB_CLOCK_GETTIME) $(LIBTHREAD) +$(LIB_XATTR) License: GPL diff --git a/modules/supersede-tests b/modules/supersede-tests index 7224d2e31e..dc01a63652 100644 --- a/modules/supersede-tests +++ b/modules/supersede-tests @@ -19,4 +19,4 @@ configure.ac: Makefile.am: TESTS += test-supersede check_PROGRAMS += test-supersede -test_supersede_LDADD = $(LDADD) $(LIB_ACL) $(LIB_CLOCK_GETTIME) $(LIB_GETRANDOM) $(LIBINTL) $(LIBTHREAD) +test_supersede_LDADD = $(LDADD) $(LIB_ACL) $(LIB_XATTR) $(LIB_CLOCK_GETTIME) $(LIB_GETRANDOM) $(LIBINTL) $(LIBTHREAD) -- 2.38.1