Hello, Thank you for the explanation and for the patch! My bad, I wrongly assumed that S_ISLNK implies (f)stat and vice versa which, apparently, does not hold.
Regard, Lukas > On 3. 11. 2026, at 14:45, Bruno Haible <[email protected]> wrote: > > Hi, > > Lukáš Zaoral wrote: >> file_has_aclinfo always calls lgetxattr unless ACL_SYMLINK_FOLLOW is >> set. > > ... and the documentation of file_has_acl states that SB was > "obtained through stat() or lstat()". > > But file_has_acl does not receive the information whether to call getxattr > or lgetxattr. That is the main problem, and your patch does not fix it: > it makes a guess. And that guess is correct in one case but wrong in > the other case. > > Instead, the correct fix would be to add to file_has_acl a flags > argument, that would be either 0 (in the case lstat() was used) > or ACL_SYMLINK_FOLLOW (in the case stat() or fstat() was used). > > But this is a backwards-incompatible change, and it would cause > compilation errors in GNU emacs and GNU tar. Therefore I don't > want to do it. Instead, I'm merely applying the attached documentation > change that adds a restriction to file_has_acl. I have verified that > - The only packages that use or used file_has_acl are > GNU coreutils, GNU emacs, GNU tar. > - GNU coreutils does not use file_has_acl any more, it now uses > file_has_aclinfo. > - GNU emacs and GNU tar satisfy the restriction. > > So, the only package that does not satisfy the restriction is the > GNU coreutils from two years ago, which is exactly your case. > > For this case I would recommend that you apply a patch like this, > locally for the coreutils package only. > > diff --git a/lib/acl.h b/lib/acl.h > index 4ac25fe226..74ccb09306 100644 > --- a/lib/acl.h > +++ b/lib/acl.h > @@ -77,7 +77,7 @@ struct aclinfo > }; > > bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; > -int file_has_acl (char const *, struct stat const *); > +int file_has_acl (char const *, struct stat const *, int); > int file_has_aclinfo (char const *restrict, struct aclinfo *restrict, int); > int fdfile_has_aclinfo (int, char const *restrict, > struct aclinfo *restrict, int); > diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c > index 4a70d4cf0f..f9d8efed3d 100644 > --- a/lib/file-has-acl.c > +++ b/lib/file-has-acl.c > @@ -973,14 +973,12 @@ fdfile_has_aclinfo (MAYBE_UNUSED int fd, > 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.) */ > + FLAGS must be ACL_SYMLINK_FOLLOW in the stat(), fstat() cases, or > + 0 in the lstat() case. */ > int > -file_has_acl (char const *name, struct stat const *sb) > +file_has_acl (char const *name, struct stat const *sb, int flags) > { > - int flags = IFTODT (sb->st_mode); > + flags |= IFTODT (sb->st_mode); > if (!S_ISDIR (sb->st_mode)) > flags |= _GL_DT_NOTDIR; > struct aclinfo ai; > > > Bruno > > <0001-file-has-acl-Document-restriction.patch>
