* m4/acl.m4 (gl_FUNC_ACL): Check if acl_get_file_at(),
acl_set_file_at(), acl_delete_def_file_at(), acl_extended_file_at() are
available.
* lib/acl-internal.h: Define HAVE_ACL_*_AT macros and shims for those
functions.
* lib/file-has-acl.c (fdfile_has_aclinfo): Use acl_extended_file_at()
when available.
* lib/get-permissions.c (get_permissions): Likewise for
acl_get_file_at().
* lib/set-permissions.c (set_acls): Likewise for acl_set_file_at() and
acl_delete_def_file_at().
---
 lib/acl-internal.h    | 28 ++++++++++++++++++++++++++++
 lib/file-has-acl.c    |  8 +++++++-
 lib/get-permissions.c |  6 +++++-
 lib/set-permissions.c | 18 +++++++++++++++---
 m4/acl.m4             |  6 ++++--
 5 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index 36be1f657d..d4012ab4f6 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -25,6 +25,7 @@
 #include "acl.h"
 
 #include <stdlib.h>
+#include <fcntl.h>
 
 /* All systems define the ACL related API in <sys/acl.h>.  */
 #if HAVE_SYS_ACL_H
@@ -83,6 +84,33 @@ _GL_INLINE_HEADER_BEGIN
 #   define acl_get_fd(fd) (NULL)
 #  endif
 
+/* Linux (libacl >= 2.4.0) */
+#  ifdef HAVE_ACL_GET_FILE_AT
+/* acl_get_file_at takes four arguments.  */
+#  else
+#   define HAVE_ACL_GET_FILE_AT false
+#   undef acl_get_file_at
+#   define acl_get_file_at(dirfd, path_p, at_flags, type) (NULL)
+#  endif
+
+/* Linux (libacl >= 2.4.0) */
+#  ifdef HAVE_ACL_SET_FILE_AT
+/* acl_set_file_at takes five arguments.  */
+#  else
+#   define HAVE_ACL_SET_FILE_AT false
+#   undef acl_set_file_at
+#   define acl_set_file_at(dirfd, path_p, at_flags, type, acl) (NULL)
+#  endif
+
+/* Linux (libacl >= 2.4.0) */
+#  ifdef HAVE_ACL_DELETE_DEF_FILE_AT
+/* acl_delete_def_file_at takes three arguments.  */
+#  else
+#   define HAVE_ACL_DELETE_DEF_FILE_AT false
+#   undef acl_delete_def_file_at
+#   define acl_delete_def_file_at(dirfd, path_p, at_flags) (NULL)
+#  endif
+
 /* POSIX 1003.1e (draft 17) */
 #  ifdef HAVE_ACL_SET_FD
 /* acl_set_fd takes two arguments.  */
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 8b9bb0468f..7c125b3a84 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -524,7 +524,13 @@ fdfile_has_aclinfo (MAYBE_UNUSED int fd,
     /* Linux, FreeBSD, NetBSD >= 10, Mac OS X, Cygwin >= 2.5 */
     int ret;
 
-#   if HAVE_ACL_EXTENDED_FILE /* Linux */
+#   if HAVE_ACL_EXTENDED_FILE_AT /* Linux (libacl >= 2.4.0) */
+      ret = (fd < 0
+            ? acl_extended_file_at (AT_FDCWD, name,
+                                    (flags & ACL_SYMLINK_FOLLOW)
+                                    ? 0 : AT_SYMLINK_NOFOLLOW)
+            : acl_extended_file_at (fd, "", AT_EMPTY_PATH));
+#   elif HAVE_ACL_EXTENDED_FILE /* Linux (libacl < 2.4.0) */
       /* On Linux, acl_extended_file is an optimized function: It only
          makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
          ACL_TYPE_DEFAULT.  */
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index 3d744c1cf6..8648e0bba5 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -55,7 +55,11 @@ get_permissions (_GL_UNUSED const char *name, _GL_UNUSED int 
desc, mode_t mode,
 
   if (S_ISDIR (mode))
     {
-      ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT);
+      if (HAVE_ACL_GET_FILE_AT && desc != -1)
+       ctx->default_acl = acl_get_file_at (desc, "", AT_EMPTY_PATH,
+                                           ACL_TYPE_DEFAULT);
+      else
+       ctx->default_acl = acl_get_file (name, ACL_TYPE_DEFAULT);
       if (ctx->default_acl == NULL)
         return -1;
     }
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index e17a1e376d..cbe2b8369c 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -523,10 +523,22 @@ set_acls (struct permission_context *ctx, const char 
*name, int desc,
                 {
                   if (! from_mode && ctx->default_acl &&
                       acl_default_nontrivial (ctx->default_acl))
-                    ret = acl_set_file (name, ACL_TYPE_DEFAULT,
-                                        ctx->default_acl);
+                   {
+                     if (HAVE_ACL_SET_FILE_AT && desc != -1)
+                       ret = acl_set_file_at (desc, "", AT_EMPTY_PATH,
+                                              ACL_TYPE_DEFAULT,
+                                              ctx->default_acl);
+                     else
+                       ret = acl_set_file (name, ACL_TYPE_DEFAULT,
+                                           ctx->default_acl);
+                   }
                   else
-                    ret = acl_delete_def_file (name);
+                   {
+                     if (HAVE_ACL_DELETE_DEF_FILE_AT && desc != -1)
+                       ret = acl_delete_def_file_at (desc, "", AT_EMPTY_PATH);
+                     else
+                       ret = acl_delete_def_file (name);
+                   }
                 }
             }
         }
diff --git a/m4/acl.m4 b/m4/acl.m4
index 897882e140..bb87c56dc7 100644
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -44,10 +44,12 @@ AC_DEFUN_ONCE([gl_FUNC_ACL],
              LIB_ACL=$ac_cv_search_acl_get_file
            fi
            AC_CHECK_FUNCS(
-             [acl_get_file acl_get_fd acl_set_file acl_set_fd \
+             [acl_get_file acl_get_file_at acl_get_fd \
+             acl_set_file acl_set_file_at acl_set_fd \
+             acl_delete_def_file acl_delete_def_file_at \
+              acl_extended_file acl_extended_file_at \
               acl_get_link_np \
               acl_free acl_from_mode acl_from_text \
-              acl_delete_def_file acl_extended_file \
               acl_delete_fd_np acl_delete_file_np \
               acl_copy_ext_native acl_create_entry_np \
               acl_to_short_text acl_free_text])
-- 
2.56.0


Reply via email to