summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2025-07-03 12:54:12 -0400
committerTavian Barnes <tavianator@tavianator.com>2025-07-04 08:22:35 -0400
commit2598b0d3e62d8b689937444ace194dcc51c34d12 (patch)
tree973c8e58b17f6077fa0483c10af03e14641d1375
parent34556d2ebad8f3fcb69520c4a980c8fbe3e47c1d (diff)
downloadbfs-2598b0d3e62d8b689937444ace194dcc51c34d12.tar.xz
color: Add support for dataless files
Link: https://developer.apple.com/documentation/technotes/tn3150-getting-ready-for-data-less-files
-rw-r--r--src/color.c62
-rw-r--r--tests/bfs/color_bsd_fail.sh4
2 files changed, 49 insertions, 17 deletions
diff --git a/src/color.c b/src/color.c
index fa79808..11dff2a 100644
--- a/src/color.c
+++ b/src/color.c
@@ -103,6 +103,8 @@ struct colors {
struct esc_seq *pipe;
struct esc_seq *socket;
+ struct esc_seq *dataless;
+
/** A mapping from color names (fi, di, ln, etc.) to struct fields. */
struct trie names;
@@ -630,7 +632,7 @@ static int parse_bsd_ls_colors(struct colors *colors, const char *lscolors) {
};
// Please refer to https://man.freebsd.org/cgi/man.cgi?ls(1)#ENVIRONMENT
- char complete_colors[] = "exfxcxdxbxegedabagacad";
+ char complete_colors[] = "exfxcxdxbxegedabagacadah";
size_t max = strlen(complete_colors);
size_t len = strnlen(lscolors, max + 1);
@@ -652,6 +654,7 @@ static int parse_bsd_ls_colors(struct colors *colors, const char *lscolors) {
&colors->setgid,
&colors->sticky_other_writable,
&colors->other_writable,
+ &colors->dataless,
};
dchar *value = dstralloc(0);
@@ -755,6 +758,8 @@ struct colors *parse_colors(void) {
fail = fail || init_esc(colors, "pi", "33", &colors->pipe);
fail = fail || init_esc(colors, "so", "01;35", &colors->socket);
+ colors->dataless = NULL;
+
if (fail) {
goto fail;
}
@@ -1042,6 +1047,34 @@ static bool cpath_is_broken(const struct cpath *cpath) {
}
}
+/** Check if we need a statbuf to colorize a file. */
+static bool must_stat(const struct colors *colors, enum bfs_type type) {
+ switch (type) {
+ case BFS_REG:
+ if (colors->setuid || colors->setgid || colors->executable || colors->multi_hard) {
+ return true;
+ }
+
+#ifdef ST_DATALESS
+ if (colors->dataless) {
+ return true;
+ }
+#endif
+
+ return false;
+
+ case BFS_DIR:
+ if (colors->sticky_other_writable || colors->other_writable || colors->sticky) {
+ return true;
+ }
+
+ return false;
+
+ default:
+ return false;
+ }
+}
+
/** Get the color for a file. */
static const struct esc_seq *file_color(const struct colors *colors, const struct cpath *cpath) {
enum bfs_type type;
@@ -1056,17 +1089,17 @@ static const struct esc_seq *file_color(const struct colors *colors, const struc
}
const struct bfs_stat *statbuf = NULL;
+ if (must_stat(colors, type)) {
+ statbuf = cpath_stat(cpath);
+ if (!statbuf) {
+ goto error;
+ }
+ }
+
const struct esc_seq *color = NULL;
switch (type) {
case BFS_REG:
- if (colors->setuid || colors->setgid || colors->executable || colors->multi_hard) {
- statbuf = cpath_stat(cpath);
- if (!statbuf) {
- goto error;
- }
- }
-
if (colors->setuid && (statbuf->mode & 04000)) {
color = colors->setuid;
} else if (colors->setgid && (statbuf->mode & 02000)) {
@@ -1079,6 +1112,12 @@ static const struct esc_seq *file_color(const struct colors *colors, const struc
color = colors->multi_hard;
}
+#ifdef SF_DATALESS
+ if (!color && colors->dataless && (statbuf->attrs & SF_DATALESS)) {
+ color = colors->dataless;
+ }
+#endif
+
if (!color) {
const char *name = cpath->path + cpath->nameoff;
size_t namelen = cpath->valid - cpath->nameoff;
@@ -1092,13 +1131,6 @@ static const struct esc_seq *file_color(const struct colors *colors, const struc
break;
case BFS_DIR:
- if (colors->sticky_other_writable || colors->other_writable || colors->sticky) {
- statbuf = cpath_stat(cpath);
- if (!statbuf) {
- goto error;
- }
- }
-
if (colors->sticky_other_writable && (statbuf->mode & 01002) == 01002) {
color = colors->sticky_other_writable;
} else if (colors->other_writable && (statbuf->mode & 00002)) {
diff --git a/tests/bfs/color_bsd_fail.sh b/tests/bfs/color_bsd_fail.sh
index 94e1209..541190c 100644
--- a/tests/bfs/color_bsd_fail.sh
+++ b/tests/bfs/color_bsd_fail.sh
@@ -1,2 +1,2 @@
-# LSCOLORS can be at most 22 characters long (11 color pairs); this one has 24.
-! LSCOLORS="exfxcxdxbxegedabagacadeB" invoke_bfs rainbow -color
+# LSCOLORS can be at most 24 characters long (12 color pairs); this one has 25.
+! LSCOLORS="exfxcxdxbxegedabagacadeahB" invoke_bfs rainbow -color