* src/ls.c (get_extended_info): A new function refactored
from gobble_file(). Also add a comment about possible
improved file_has_aclinfo() operation.
---
src/ls.c | 142 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 78 insertions(+), 64 deletions(-)
diff --git a/src/ls.c b/src/ls.c
index 3a0e29ec7..9ddb88423 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -3300,6 +3300,83 @@ has_capability_cache (char const *file, struct fileinfo
*f)
return b;
}
+/* Get the ACL, security context, and capability information needed for F.
+ FULL_NAME names the file; DO_DEREF says whether to follow symlinks. */
+static void
+get_extended_info (char const *full_name, struct fileinfo *f, bool do_deref)
+{
+ /* FIXME: file_has_aclinfo() conflates capability and acl xattr lookup
+ with security context attributes. Ideally we'd have separate
+ ACL_GET_{CAPABILITY,ACL} flags to lookup just the required items,
+ simplifying the logic here. */
+
+ enum filetype type = f->filetype;
+ bool check_acl = USE_ACL && format == long_format;
+ bool get_scontext = false;
+#if HAVE_SMACK || USE_SELINUX_SELINUX_H
+ get_scontext = (format == long_format) | print_scontext;
+#endif
+ bool check_capability = format_needs_capability & (type == normal);
+
+ if (type != arg_directory && (check_acl | get_scontext | check_capability))
+ {
+ struct aclinfo ai;
+ /* Without ACL support, request contexts to obtain the attribute
+ names needed for capability coloring too. */
+ int aclinfo_flags = ((do_deref ? ACL_SYMLINK_FOLLOW : 0)
+ | (get_scontext || (!USE_ACL && check_capability)
+ ? ACL_GET_SCONTEXT : 0)
+ | filetype_d_type[type]);
+ 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 long-winded diagnostic.
+
+ Similarly, ignore ENOENT which may happen on some versions
+ of cygwin when processing dangling symlinks for example.
+ Also if a file is removed while we're reading ACL info,
+ ACL_T_UNKNOWN is sufficient indication for that edge case. */
+ bool cannot_access_acl = n < 0
+ && (errno == EACCES
+ || ignorable_traversal_errno (errno));
+
+ f->acl_type = (!have_scontext && !have_acl
+ ? (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 && !cannot_access_acl)
+ error (0, errno, "%s", quotef (full_name));
+ else
+ {
+ /* When requesting security context information, don't make
+ ls fail just because the file (even a command line argument)
+ isn't on the right type of file system. I.e., a getfilecon
+ failure isn't in the same class as a stat failure. */
+ if (print_scontext && ai.scontext_err
+ && ! ignorable_traversal_errno (ai.scontext_err)
+ && (! (is_ENOTSUP (ai.scontext_err)
+ || ai.scontext_err == ENODATA)))
+ error (0, ai.scontext_err, "%s", quotef (full_name));
+ }
+
+ /* has_capability adds around 30% runtime to 'ls --color',
+ so call it only if really needed. Note capability coloring
+ is disabled in the default color config. */
+ if (check_capability && aclinfo_has_xattr (&ai, XATTR_NAME_CAPS))
+ f->has_capability = has_capability_cache (full_name, f);
+
+ f->scontext = ai.scontext;
+ ai.scontext = NULL;
+ aclinfo_free (&ai);
+ }
+}
+
static bool
needs_quoting (char const *name)
{
@@ -3484,70 +3561,7 @@ gobble_file (char const *name, enum filetype type, ino_t
inode,
if (type == directory && command_line_arg && !immediate_dirs)
f->filetype = type = arg_directory;
- bool check_acl = USE_ACL && format == long_format;
- bool get_scontext = false;
-#if HAVE_SMACK || USE_SELINUX_SELINUX_H
- get_scontext = (format == long_format) | print_scontext;
-#endif
- bool check_capability = format_needs_capability & (type == normal);
-
- if (type != arg_directory && (check_acl | get_scontext | check_capability))
- {
- struct aclinfo ai;
- /* Without ACL support, request contexts to obtain the attribute
- names needed for capability coloring too. */
- int aclinfo_flags = ((do_deref ? ACL_SYMLINK_FOLLOW : 0)
- | (get_scontext || (!USE_ACL && check_capability)
- ? ACL_GET_SCONTEXT : 0)
- | filetype_d_type[type]);
- 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 long-winded diagnostic.
-
- Similarly, ignore ENOENT which may happen on some versions
- of cygwin when processing dangling symlinks for example.
- Also if a file is removed while we're reading ACL info,
- ACL_T_UNKNOWN is sufficient indication for that edge case. */
- bool cannot_access_acl = n < 0
- && (errno == EACCES
- || ignorable_traversal_errno (errno));
-
- f->acl_type = (!have_scontext && !have_acl
- ? (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 && !cannot_access_acl)
- error (0, errno, "%s", quotef (full_name));
- else
- {
- /* When requesting security context information, don't make
- ls fail just because the file (even a command line argument)
- isn't on the right type of file system. I.e., a getfilecon
- failure isn't in the same class as a stat failure. */
- if (print_scontext && ai.scontext_err
- && ! ignorable_traversal_errno (ai.scontext_err)
- && (! (is_ENOTSUP (ai.scontext_err)
- || ai.scontext_err == ENODATA)))
- error (0, ai.scontext_err, "%s", quotef (full_name));
- }
-
- /* has_capability adds around 30% runtime to 'ls --color',
- so call it only if really needed. Note capability coloring
- is disabled in the default color config. */
- if (check_capability && aclinfo_has_xattr (&ai, XATTR_NAME_CAPS))
- f->has_capability = has_capability_cache (full_name, f);
-
- f->scontext = ai.scontext;
- ai.scontext = NULL;
- aclinfo_free (&ai);
- }
+ get_extended_info (full_name, f, do_deref);
if ((type == symbolic_link)
& ((format == long_format) | check_symlink_mode))
--
2.55.0