ls: suppress "Permission denied" errors on NFS

NFS (on Linux 6.12 at least) was seen to return EACCES
from listxattr() for files without read access.
We started using listxattr() in coreutils 9.4.

* src/ls.c (gobble_file): Map EACCES from file_has_aclinfo()
to '?', rather than displaying the error.
* doc/coreutils.texi (ls invocation): Document the '?' flag.
* NEWS: Mention the bug fix.
Addresses https://bugs.gnu.org/74692
This commit is contained in:
Pádraig Brady
2025-01-08 21:46:05 +00:00
parent 6b9e601a97
commit b58e321c8d
3 changed files with 21 additions and 2 deletions

6
NEWS
View File

@@ -15,6 +15,12 @@ GNU coreutils NEWS -*- outline -*-
first and last characters, and single quotes in the string.
[bug introduced in coreutils-8.26]
ls -l may now mark files with a '?' character after the mode bits
if it is unable to read alternate access method details, which may
happen on NFS with files without read permission.
Previously ls would have output "Permission denied" errors.
[bug introduced in coreutils-9.4]
mv works again with macFUSE file systems. Previously it would
have exited with a "Function not implemented" error.
[bug introduced in coreutils-8.28]

View File

@@ -8084,6 +8084,10 @@ with a security context, but no other alternate access method.
A file with any other combination of alternate access methods
is marked with a @samp{+} character.
@command{ls} uses a @samp{?} character to indicate it is unable to determine
whether alternate access methods apply to the file, which may happen for
example with some NFS setups with files without read permission.
@item -n
@itemx --numeric-uid-gid
@opindex -n

View File

@@ -199,6 +199,7 @@ static char const d_type_filetype[UCHAR_MAX + 1] =
enum acl_type
{
ACL_T_NONE,
ACL_T_UNKNOWN,
ACL_T_LSM_CONTEXT_ONLY,
ACL_T_YES
};
@@ -3518,14 +3519,20 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
int n = file_has_aclinfo_cache (full_name, f, &ai, aclinfo_flags);
bool have_acl = 0 < n;
bool have_scontext = !ai.scontext_err;
/* Let the user know via '?' if errno is EACCES, which can
happen with Linux kernel 6.12 on an NFS file system.
That's better than a longwinded diagnostic. */
bool cannot_access_acl = n < 0 && errno == EACCES;
f->acl_type = (!have_scontext && !have_acl
? ACL_T_NONE
? (cannot_access_acl ? ACL_T_UNKNOWN : ACL_T_NONE)
: (have_scontext && !have_acl
? ACL_T_LSM_CONTEXT_ONLY
: ACL_T_YES));
any_has_acl |= f->acl_type != ACL_T_NONE;
if (format == long_format && n < 0)
if (format == long_format && n < 0 && !cannot_access_acl)
error (0, ai.u.err, "%s", quotef (full_name));
else
{
@@ -4302,6 +4309,8 @@ print_long_format (const struct fileinfo *f)
modebuf[10] = '.';
else if (f->acl_type == ACL_T_YES)
modebuf[10] = '+';
else if (f->acl_type == ACL_T_UNKNOWN)
modebuf[10] = '?';
switch (time_type)
{