summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-01-02 22:12:36 -0500
committerTavian Barnes <tavianator@tavianator.com>2019-01-02 22:17:08 -0500
commit28c787b0dcbae9e6c7dfc0013bdaff25d0a2f009 (patch)
treed8c49d80fe896aff24af78db7530f67aa245eb2b
parent29a49f5d150911428a35943be8d9fc226865eb1b (diff)
downloadbfs-28c787b0dcbae9e6c7dfc0013bdaff25d0a2f009.tar.xz
color: Fix more incompatibilities with GNU ls
-rw-r--r--RELEASES.md7
-rw-r--r--color.c31
-rwxr-xr-xtests.sh83
-rw-r--r--tests/test_color.out15
-rw-r--r--tests/test_color_ext.out15
-rw-r--r--tests/test_color_ext0.out15
-rw-r--r--tests/test_color_mh.out15
-rw-r--r--tests/test_color_mh0.out15
-rw-r--r--tests/test_color_mi.out15
-rw-r--r--tests/test_color_missing_colon.out15
-rw-r--r--tests/test_color_or.out15
-rw-r--r--tests/test_color_or0_mi.out15
-rw-r--r--tests/test_color_or_mi.out15
-rw-r--r--tests/test_color_or_mi0.out15
-rw-r--r--tests/test_colors.out12
15 files changed, 267 insertions, 31 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 2275cf8..f8f3c3c 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -15,7 +15,12 @@ New features:
Fixes:
-- Extension colors from `LS_COLORS` are now case-insensitive like GNU `ls`
+- `LS_COLORS` handling has been improved:
+ - Extension colors are now case-insensitive like GNU `ls`
+ - `or` (orphan) and `mi` (missing) files are now treated differently
+ - Default colors can be unset with `di=00` or similar
+ - Specific colors fall back to more general colors when unspecified in more places
+ - `LS_COLORS` no longer needs a trailing colon
- `-ls`/`-fls` now prints the major/minor numbers for device nodes
- `-exec ;` is rejected rather than segfaulting
- `bfs` now builds on old Linux versions that require `-lrt` for POSIX timers
diff --git a/color.c b/color.c
index 5807184..a877ff7 100644
--- a/color.c
+++ b/color.c
@@ -184,25 +184,20 @@ struct colors *parse_colors(const char *ls_colors) {
}
char *start = colors->data;
- char *end;
+ size_t colon;
struct ext_color *ext;
- for (end = strchr(start, ':'); *start && end; start = end + 1, end = strchr(start, ':')) {
+ for (colon = strcspn(start, ":"); *start; start += colon + 1, colon = strcspn(start, ":")) {
+ start[colon] = '\0';
+
char *equals = strchr(start, '=');
if (!equals) {
continue;
}
-
*equals = '\0';
- *end = '\0';
const char *key = start;
const char *value = equals + 1;
- // Ignore all-zero values
- if (strspn(value, "0") == strlen(value)) {
- continue;
- }
-
if (key[0] == '*') {
ext = malloc(sizeof(struct ext_color));
if (ext) {
@@ -213,6 +208,11 @@ struct colors *parse_colors(const char *ls_colors) {
colors->ext_list = ext;
}
} else {
+ // All-zero values should be treated like NULL, to fall
+ // back on any other relevant coloring for that file
+ if (strcmp(key, "rs") != 0 && strspn(value, "0") == strlen(value)) {
+ value = NULL;
+ }
set_color(colors, key, value);
}
}
@@ -307,7 +307,11 @@ static const char *ext_color(const struct colors *colors, const char *filename)
static const char *file_color(const struct colors *colors, const char *filename, const struct BFTW *ftwbuf) {
const struct bfs_stat *sb = ftwbuf->statbuf;
if (!sb) {
- return colors->orphan;
+ if (colors->missing) {
+ return colors->missing;
+ } else {
+ return colors->orphan;
+ }
}
const char *color = NULL;
@@ -318,7 +322,7 @@ static const char *file_color(const struct colors *colors, const char *filename,
color = colors->setuid;
} else if (sb->mode & S_ISGID) {
color = colors->setgid;
- } else if (bfs_check_capabilities(ftwbuf)) {
+ } else if (colors->capable && bfs_check_capabilities(ftwbuf)) {
color = colors->capable;
} else if (sb->mode & 0111) {
color = colors->exec;
@@ -356,9 +360,8 @@ static const char *file_color(const struct colors *colors, const char *filename,
break;
case S_IFLNK:
- if (xfaccessat(ftwbuf->at_fd, ftwbuf->at_path, F_OK) == 0) {
- color = colors->link;
- } else {
+ color = colors->link;
+ if (colors->orphan && xfaccessat(ftwbuf->at_fd, ftwbuf->at_path, F_OK) != 0) {
color = colors->orphan;
}
break;
diff --git a/tests.sh b/tests.sh
index 0e86904..0b2678d 100755
--- a/tests.sh
+++ b/tests.sh
@@ -53,7 +53,9 @@ function installp() {
# Like a mythical touch -p
function touchp() {
- installp -m644 /dev/null "$1"
+ for arg; do
+ installp -m644 /dev/null "$arg"
+ done
}
# Creates a simple file+directory structure for tests
@@ -164,6 +166,29 @@ function make_deep() {
}
make_deep "$TMP/deep"
+# Creates a directory structure with many different types, and therefore colors
+function make_rainbow() {
+ touchp "$1/file.txt"
+ touchp "$1/file.dat"
+ ln -s file.txt "$1/link.txt"
+ touchp "$1/mh1"
+ ln "$1/mh1" "$1/mh2"
+ mkfifo "$1/pipe"
+ # XXX: block
+ # XXX: chardev
+ ln -s nowhere "$1/broken"
+ # XXX: socket
+ touchp "$1"/s{u,g,ug}id
+ chmod u+s "$1"/su{,g}id
+ chmod g+s "$1"/s{u,}gid
+ mkdir "$1/ow" "$1"/sticky{,_ow}
+ chmod o+w "$1"/*ow
+ chmod +t "$1"/sticky*
+ touchp "$1"/exec.sh
+ chmod +x "$1"/exec.sh
+}
+make_rainbow "$TMP/rainbow"
+
# Creates a scratch directory that tests can modify
function make_scratch() {
mkdir -p "$1"
@@ -582,7 +607,17 @@ bfs_tests=(
# Primaries
- test_colors
+ test_color
+ test_color_mh
+ test_color_mh0
+ test_color_or
+ test_color_mi
+ test_color_or_mi
+ test_color_or0_mi
+ test_color_or_mi0
+ test_color_ext
+ test_color_ext0
+ test_color_missing_colon
test_execdir_plus
@@ -1741,8 +1776,48 @@ function test_precedence() {
bfs_diff basic \( -name foo -type d -o -name bar -a -type f \) -print , \! -empty -type f -print
}
-function test_colors() {
- LS_COLORS= bfs_diff links -color
+function test_color() {
+ LS_COLORS= bfs_diff rainbow -color
+}
+
+function test_color_mh() {
+ LS_COLORS="mh=01:" bfs_diff rainbow -color
+}
+
+function test_color_mh0() {
+ LS_COLORS="mh=00:" bfs_diff rainbow -color
+}
+
+function test_color_or() {
+ LS_COLORS="or=01:" bfs_diff rainbow -color
+}
+
+function test_color_mi() {
+ LS_COLORS="mi=01:" bfs_diff rainbow -color
+}
+
+function test_color_or_mi() {
+ LS_COLORS="or=01;31:mi=01;33:" bfs_diff rainbow -color
+}
+
+function test_color_or0_mi() {
+ LS_COLORS="or=00:mi=01;33:" bfs_diff rainbow -color
+}
+
+function test_color_or_mi0() {
+ LS_COLORS="or=01;31:mi=00:" bfs_diff rainbow -color
+}
+
+function test_color_ext() {
+ LS_COLORS="*.txt=01:" bfs_diff rainbow -color
+}
+
+function test_color_ext0() {
+ LS_COLORS="*.txt=00:" bfs_diff rainbow -color
+}
+
+function test_color_missing_colon() {
+ LS_COLORS="*.txt=01" bfs_diff rainbow -color
}
function test_deep() {
diff --git a/tests/test_color.out b/tests/test_color.out
new file mode 100644
index 0000000..e267da8
--- /dev/null
+++ b/tests/test_color.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_ext.out b/tests/test_color_ext.out
new file mode 100644
index 0000000..d2e2a70
--- /dev/null
+++ b/tests/test_color_ext.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/file.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_ext0.out b/tests/test_color_ext0.out
new file mode 100644
index 0000000..3bc8dc1
--- /dev/null
+++ b/tests/test_color_ext0.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/file.txt
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_mh.out b/tests/test_color_mh.out
new file mode 100644
index 0000000..600451e
--- /dev/null
+++ b/tests/test_color_mh.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/mh1
+rainbow/mh2
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
diff --git a/tests/test_color_mh0.out b/tests/test_color_mh0.out
new file mode 100644
index 0000000..e267da8
--- /dev/null
+++ b/tests/test_color_mh0.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_mi.out b/tests/test_color_mi.out
new file mode 100644
index 0000000..e267da8
--- /dev/null
+++ b/tests/test_color_mi.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_missing_colon.out b/tests/test_color_missing_colon.out
new file mode 100644
index 0000000..d2e2a70
--- /dev/null
+++ b/tests/test_color_missing_colon.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/file.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/broken
+rainbow/pipe
+rainbow/file.dat
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_or.out b/tests/test_color_or.out
new file mode 100644
index 0000000..6e94bc6
--- /dev/null
+++ b/tests/test_color_or.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/broken
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_or0_mi.out b/tests/test_color_or0_mi.out
new file mode 100644
index 0000000..cafa798
--- /dev/null
+++ b/tests/test_color_or0_mi.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/exec.sh
+rainbow/broken
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_or_mi.out b/tests/test_color_or_mi.out
new file mode 100644
index 0000000..7e57688
--- /dev/null
+++ b/tests/test_color_or_mi.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/broken
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_color_or_mi0.out b/tests/test_color_or_mi0.out
new file mode 100644
index 0000000..7e57688
--- /dev/null
+++ b/tests/test_color_or_mi0.out
@@ -0,0 +1,15 @@
+rainbow
+rainbow/broken
+rainbow/exec.sh
+rainbow/link.txt
+rainbow/sticky_ow
+rainbow/sgid
+rainbow/ow
+rainbow/sugid
+rainbow/suid
+rainbow/sticky
+rainbow/pipe
+rainbow/file.dat
+rainbow/file.txt
+rainbow/mh1
+rainbow/mh2
diff --git a/tests/test_colors.out b/tests/test_colors.out
deleted file mode 100644
index dbdeafa..0000000
--- a/tests/test_colors.out
+++ /dev/null
@@ -1,12 +0,0 @@
-links
-links/deeply
-links/skip
-links/symlink
-links/broken
-links/notdir
-links/file
-links/hardlink
-links/deeply/nested
-links/deeply/nested/dir
-links/deeply/nested/link
-links/deeply/nested/file