From a3c1c3ed54d9d595feb1df38e775af3d6ff9facd Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 5 May 2019 23:16:01 -0400 Subject: color: Don't stat() if we don't need to --- color.c | 70 ++++++++++++++++++++++++++---------------- eval.c | 8 +---- tests.sh | 10 ++++++ tests/test_color_L_no_stat.out | 20 ++++++++++++ tests/test_color_no_stat.out | 20 ++++++++++++ 5 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 tests/test_color_L_no_stat.out create mode 100644 tests/test_color_no_stat.out 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 -- cgit v1.2.3