Sending the other proposed patch fixing the NFSv4 acl detection on Fedora39. It's bit longer, but I think should be better. Please review.
--- lib/file-has-acl.c | 60 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index b31a2ea252..27da1c0607 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -121,6 +121,30 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) return 0; } + +/* Return 1 if ATTR is found in the xattr list given by BUF */ +int have_xattr (char const *attr, char *buf, ssize_t buflen) +{ + char const *key = buf; + /* Loop over the list of zero terminated strings with the + attribute keys. Use the remaining buffer length to determine + the end of the list. */ + while (buflen > 0) { + int keylen; + + if (strcmp (key, attr) == 0) + { + /* we don't expect this function will be called again + so we free the buffer so caller does not have to */ + free (buf); + return 1; + } + keylen = strlen (key) + 1; + buflen -= keylen; + key += keylen; + } + return 0; +} #endif /* Return 1 if NAME has a nontrivial access control list, @@ -139,25 +163,37 @@ file_has_acl (char const *name, struct stat const *sb) # if GETXATTR_WITH_POSIX_ACLS - ssize_t ret; + ssize_t ret, buflen; + char *attrlist; int initial_errno = errno; - ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0); - if (ret < 0 && errno == ENODATA) - ret = 0; - else if (ret > 0) + ret = listxattr (name, NULL, 0); + if (ret <= 0) + return ret; + attrlist = malloc (ret); + if (attrlist == NULL) + return -1; + buflen = listxattr (name, attrlist, ret); + if (buflen == -1) + { + free (attrlist); + return - acl_errno_valid (errno); + } + + if(have_xattr (XATTR_NAME_POSIX_ACL_ACCESS, attrlist, buflen)) return 1; + else + ret = 0; - if (ret == 0 && S_ISDIR (sb->st_mode)) + if (S_ISDIR (sb->st_mode)) { - ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0); - if (ret < 0 && errno == ENODATA) - ret = 0; - else if (ret > 0) + if (have_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, attrlist, buflen)) return 1; + else + ret = 0; } - if (ret < 0) + if (have_xattr (XATTR_NAME_NFSV4_ACL, attrlist, buflen)) { /* Check for NFSv4 ACLs. The max length of a trivial ACL is 6 words for owner, 6 for group, 7 for everyone, @@ -186,6 +222,8 @@ file_has_acl (char const *name, struct stat const *sb) errno = initial_errno; } } + else + free (attrlist); if (ret < 0) return - acl_errno_valid (errno); return ret; -- 2.40.1