Lukáš Zaoral wrote: > My bad, I wrongly assumed that S_ISLNK implies (f)stat and vice versa > which, apparently, does not hold.
Yes, this comment "assume that the stat buffer was obtained through stat()." made the code look like an obvious bug. It requires a 4x4 matrix, to convince oneself that your patch was indeed correct. I'm committing this followup. 2026-11-03 Bruno Haible <[email protected]> file-has-acl: Remove restriction. Based on a patch by Lukáš Zaoral <[email protected]> in <https://lists.gnu.org/archive/html/bug-gnulib/2026-11/msg00024.html>. * lib/file-has-acl.c (file_has_acl): Revert comment change. Use flag ACL_SYMLINK_FOLLOW if needed or if it does not matter. diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 4a70d4cf0f..f4c0789816 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -972,17 +972,26 @@ fdfile_has_aclinfo (MAYBE_UNUSED int fd, and -1 (setting errno) on error. Note callers can determine if ACLs are not supported as errno is set in that case also. SB must be set to the stat buffer of NAME, - obtained through stat(), fstat(), or lstat(). - In the case that SB was obtained through lstat(), the caller must guarantee - that !S_ISLNK (SB->st_mode). (In order to support S_ISLNK (SB->st_mode), - this function would need a flags parameter, where the caller would need - to pass either 0 or ACL_SYMLINK_FOLLOW.) */ + obtained through stat(), fstat(), or lstat(). */ int file_has_acl (char const *name, struct stat const *sb) { - int flags = IFTODT (sb->st_mode); + int flags = 0; + /* Whether to set ACL_SYMLINK_FOLLOW, is tricky: + SB provenance | NAME type | S_ISLNK (SB->st_mode) | use ACL_SYMLINK_FOLLOW? + --------------+-----------+-----------------------+------------------------ + stat, fstat | !symlink | false | does not matter + stat, fstat | symlink | false | yes + lstat | !symlink | false | does not matter + lstat | symlink | true | no + --------------+-----------+-----------------------+------------------------ + */ + if (!S_ISLNK (sb->st_mode)) + flags |= ACL_SYMLINK_FOLLOW; + flags |= IFTODT (sb->st_mode); if (!S_ISDIR (sb->st_mode)) flags |= _GL_DT_NOTDIR; + struct aclinfo ai; int r = file_has_aclinfo (name, &ai, flags); aclinfo_free (&ai);
