summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-05-05 23:16:01 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-05-05 23:16:01 -0400
commita3c1c3ed54d9d595feb1df38e775af3d6ff9facd (patch)
tree4d7347b1cc073be521cb8f0d6e5b36ab5e091021
parentdf7d960b0d7e1f9bd8aa58654760e41b6282f78a (diff)
downloadbfs-a3c1c3ed54d9d595feb1df38e775af3d6ff9facd.tar.xz
color: Don't stat() if we don't need to
-rw-r--r--color.c70
-rw-r--r--eval.c8
-rwxr-xr-xtests.sh10
-rw-r--r--tests/test_color_L_no_stat.out20
-rw-r--r--tests/test_color_no_stat.out20
5 files changed, 95 insertions, 33 deletions
diff --git a/color.c b/color.c
index cf507fd..fd9949e 100644
--- a/color.c
+++ b/color.c
@@ -551,28 +551,32 @@ static bool is_link_broken(const struct BFTW *ftwbuf) {
/** Get the color for a file. */
static const char *file_color(const struct colors *colors, const char *filename, const struct BFTW *ftwbuf, enum bfs_stat_flag flags) {
- const struct bfs_stat *sb = bftw_stat(ftwbuf, flags);
- if (!sb) {
- if (colors->missing) {
- return colors->missing;
- } else {
- return colors->orphan;
- }
+ enum bftw_typeflag typeflag = bftw_typeflag(ftwbuf, flags);
+ if (typeflag == BFTW_ERROR) {
+ goto error;
}
+ const struct bfs_stat *statbuf = NULL;
const char *color = NULL;
- switch (sb->mode & S_IFMT) {
- case S_IFREG:
- if (colors->setuid && (sb->mode & 04000)) {
+ switch (typeflag) {
+ case BFTW_REG:
+ if (colors->setuid || colors->setgid || colors->executable || colors->multi_hard) {
+ statbuf = bftw_stat(ftwbuf, flags);
+ if (!statbuf) {
+ goto error;
+ }
+ }
+
+ if (colors->setuid && (statbuf->mode & 04000)) {
color = colors->setuid;
- } else if (colors->setgid && (sb->mode & 02000)) {
+ } else if (colors->setgid && (statbuf->mode & 02000)) {
color = colors->setgid;
} else if (colors->capable && bfs_check_capabilities(ftwbuf)) {
color = colors->capable;
- } else if (colors->executable && (sb->mode & 00111)) {
+ } else if (colors->executable && (statbuf->mode & 00111)) {
color = colors->executable;
- } else if (colors->multi_hard && sb->nlink > 1) {
+ } else if (colors->multi_hard && statbuf->nlink > 1) {
color = colors->multi_hard;
}
@@ -586,12 +590,19 @@ static const char *file_color(const struct colors *colors, const char *filename,
break;
- case S_IFDIR:
- if (colors->sticky_other_writable && (sb->mode & 01002) == 01002) {
+ case BFTW_DIR:
+ if (colors->sticky_other_writable || colors->other_writable || colors->sticky) {
+ statbuf = bftw_stat(ftwbuf, flags);
+ if (!statbuf) {
+ goto error;
+ }
+ }
+
+ if (colors->sticky_other_writable && (statbuf->mode & 01002) == 01002) {
color = colors->sticky_other_writable;
- } else if (colors->other_writable && (sb->mode & 00002)) {
+ } else if (colors->other_writable && (statbuf->mode & 00002)) {
color = colors->other_writable;
- } else if (colors->sticky && (sb->mode & 01000)) {
+ } else if (colors->sticky && (statbuf->mode & 01000)) {
color = colors->sticky;
} else {
color = colors->directory;
@@ -599,7 +610,7 @@ static const char *file_color(const struct colors *colors, const char *filename,
break;
- case S_IFLNK:
+ case BFTW_LNK:
if (colors->orphan && is_link_broken(ftwbuf)) {
color = colors->orphan;
} else {
@@ -607,24 +618,24 @@ static const char *file_color(const struct colors *colors, const char *filename,
}
break;
- case S_IFBLK:
+ case BFTW_BLK:
color = colors->blockdev;
break;
- case S_IFCHR:
+ case BFTW_CHR:
color = colors->chardev;
break;
- case S_IFIFO:
+ case BFTW_FIFO:
color = colors->pipe;
break;
- case S_IFSOCK:
+ case BFTW_SOCK:
color = colors->socket;
break;
-
-#ifdef S_IFDOOR
- case S_IFDOOR:
+ case BFTW_DOOR:
color = colors->door;
break;
-#endif
+
+ default:
+ break;
}
if (!color) {
@@ -632,6 +643,13 @@ static const char *file_color(const struct colors *colors, const char *filename,
}
return color;
+
+error:
+ if (colors->missing) {
+ return colors->missing;
+ } else {
+ return colors->orphan;
+ }
}
/** Print a fixed-length string. */
diff --git a/eval.c b/eval.c
index 0c4f9a9..7a9a1aa 100644
--- a/eval.c
+++ b/eval.c
@@ -700,15 +700,9 @@ error:
* -f?print action.
*/
bool eval_fprint(const struct expr *expr, struct eval_state *state) {
- CFILE *cfile = expr->cfile;
- if (cfile->colors) {
- eval_stat(state);
- }
-
- if (cfprintf(cfile, "%pP\n", state->ftwbuf) < 0) {
+ if (cfprintf(expr->cfile, "%pP\n", state->ftwbuf) < 0) {
eval_report_error(state);
}
-
return true;
}
diff --git a/tests.sh b/tests.sh
index 8716639..b9d0a89 100755
--- a/tests.sh
+++ b/tests.sh
@@ -610,6 +610,8 @@ bfs_tests=(
test_color_ext_override
test_color_ext_underride
test_color_missing_colon
+ test_color_no_stat
+ test_color_L_no_stat
test_execdir_plus
@@ -2056,6 +2058,14 @@ function test_color_missing_colon() {
LS_COLORS="*.txt=01" bfs_diff rainbow -color
}
+function test_color_no_stat() {
+ LS_COLORS="mh=0:ex=0:sg=0:su=0:st=0:ow=0:tw=0:*.txt=01:" bfs_diff rainbow -color
+}
+
+function test_color_L_no_stat() {
+ LS_COLORS="mh=0:ex=0:sg=0:su=0:st=0:ow=0:tw=0:*.txt=01:" bfs_diff -L rainbow -color
+}
+
function test_deep() {
closefrom 4
diff --git a/tests/test_color_L_no_stat.out b/tests/test_color_L_no_stat.out
new file mode 100644
index 0000000..c0bb1be
--- /dev/null
+++ b/tests/test_color_L_no_stat.out
@@ -0,0 +1,20 @@
+rainbow
+rainbow/chardev_link
+rainbow/ow
+rainbow/sticky
+rainbow/sticky_ow
+rainbow/socket
+rainbow/broken
+rainbow/file.txt
+rainbow/link.txt
+rainbow/pipe
+rainbow/exec.sh
+rainbow/file.dat
+rainbow/mh1
+rainbow/mh2
+rainbow/sgid
+rainbow/star.gz
+rainbow/star.tar
+rainbow/star.tar.gz
+rainbow/sugid
+rainbow/suid
diff --git a/tests/test_color_no_stat.out b/tests/test_color_no_stat.out
new file mode 100644
index 0000000..1fc5324
--- /dev/null
+++ b/tests/test_color_no_stat.out
@@ -0,0 +1,20 @@
+rainbow
+rainbow/ow
+rainbow/sticky
+rainbow/sticky_ow
+rainbow/socket
+rainbow/broken
+rainbow/chardev_link
+rainbow/link.txt
+rainbow/file.txt
+rainbow/pipe
+rainbow/exec.sh
+rainbow/file.dat
+rainbow/mh1
+rainbow/mh2
+rainbow/sgid
+rainbow/star.gz
+rainbow/star.tar
+rainbow/star.tar.gz
+rainbow/sugid
+rainbow/suid