From 36cb1762dd647a6c9cbb0ab36993c83798c854f1 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 25 Dec 2018 18:08:43 -0500 Subject: stat: Provide a helper for getting human-readable field names And fix -newerXY if the Y time doesn't exist. --- eval.c | 25 ++---------------------- parse.c | 67 +++++++++++++++++++++++++++++------------------------------------ stat.c | 36 +++++++++++++++++++++++++++++++++++ stat.h | 5 +++++ 4 files changed, 73 insertions(+), 60 deletions(-) diff --git a/eval.c b/eval.c index f636173..fa2be65 100644 --- a/eval.c +++ b/eval.c @@ -215,32 +215,11 @@ bool eval_capable(const struct expr *expr, struct eval_state *state) { */ static const struct timespec *eval_stat_time(const struct bfs_stat *statbuf, enum bfs_stat_field field, const struct eval_state *state) { const struct timespec *ret = bfs_stat_time(statbuf, field); - if (!ret) { - const char *kind; - switch (field) { - case BFS_STAT_ATIME: - kind = "access"; - break; - case BFS_STAT_BTIME: - kind = "birth"; - break; - case BFS_STAT_CTIME: - kind = "change"; - break; - case BFS_STAT_MTIME: - kind = "modification"; - break; - default: - assert(false); - kind = "???"; - break; - } - - cfprintf(state->cmdline->cerr, "%{er}error: '%s': Couldn't get file %s time: %s%{rs}\n", state->ftwbuf->path, kind, strerror(errno)); + cfprintf(state->cmdline->cerr, "%{er}error: '%s': Couldn't get file %s time: %m%{rs}\n", + state->ftwbuf->path, bfs_stat_field_name(field)); *state->ret = EXIT_FAILURE; } - return ret; } diff --git a/parse.c b/parse.c index 54d1a88..524a80d 100644 --- a/parse.c +++ b/parse.c @@ -1518,6 +1518,22 @@ static struct expr *parse_lname(struct parser_state *state, int casefold, int ar return parse_fnmatch(state, expr, casefold); } +/** Get the bfs_stat_field for X/Y in -newerXY */ +static enum bfs_stat_field parse_newerxy_field(char c) { + switch (c) { + case 'a': + return BFS_STAT_ATIME; + case 'B': + return BFS_STAT_BTIME; + case 'c': + return BFS_STAT_CTIME; + case 'm': + return BFS_STAT_MTIME; + default: + return 0; + } +} + /** * Parse -newerXY. */ @@ -1535,21 +1551,8 @@ static struct expr *parse_newerxy(struct parser_state *state, int arg1, int arg2 goto fail; } - switch (arg[6]) { - case 'a': - expr->stat_field = BFS_STAT_ATIME; - break; - case 'c': - expr->stat_field = BFS_STAT_CTIME; - break; - case 'm': - expr->stat_field = BFS_STAT_MTIME; - break; - case 'B': - expr->stat_field = BFS_STAT_BTIME; - break; - - default: + expr->stat_field = parse_newerxy_field(arg[6]); + if (!expr->stat_field) { cfprintf(cerr, "%{er}error: %s: For -newerXY, X should be 'a', 'c', 'm', or 'B'.%{rs}\n", arg); goto fail; } @@ -1558,35 +1561,25 @@ static struct expr *parse_newerxy(struct parser_state *state, int arg1, int arg2 cfprintf(cerr, "%{er}error: %s: Explicit reference times ('t') are not supported.%{rs}\n", arg); goto fail; } else { + enum bfs_stat_field field = parse_newerxy_field(arg[7]); + if (!field) { + cfprintf(cerr, "%{er}error: %s: For -newerXY, Y should be 'a', 'c', 'm', 'B', or 't'.%{rs}\n", arg); + goto fail; + } + struct bfs_stat sb; if (stat_arg(state, expr, &sb) != 0) { goto fail; } - switch (arg[7]) { - case 'a': - expr->reftime = sb.atime; - break; - case 'c': - expr->reftime = sb.ctime; - break; - case 'm': - expr->reftime = sb.mtime; - break; - - case 'B': - if (sb.mask & BFS_STAT_BTIME) { - expr->reftime = sb.btime; - } else { - cfprintf(cerr, "%{er}error: '%s': Couldn't get file birth time.%{rs}\n", expr->sdata); - goto fail; - } - break; - - default: - cfprintf(cerr, "%{er}error: %s: For -newerXY, Y should be 'a', 'c', 'm', 'B', or 't'.%{rs}\n", arg); + const struct timespec *reftime = bfs_stat_time(&sb, field); + if (!reftime) { + cfprintf(cerr, "%{er}error: '%s': Couldn't get file %s: %m.%{rs}\n", + expr->sdata, bfs_stat_field_name(field)); goto fail; } + + expr->reftime = *reftime; } return expr; diff --git a/stat.c b/stat.c index c567873..e78e206 100644 --- a/stat.c +++ b/stat.c @@ -42,6 +42,42 @@ # define st_birthtim st_birthtimespec #endif +const char *bfs_stat_field_name(enum bfs_stat_field field) { + switch (field) { + case BFS_STAT_DEV: + return "device number"; + case BFS_STAT_INO: + return "inode nunmber"; + case BFS_STAT_TYPE: + return "type"; + case BFS_STAT_MODE: + return "mode"; + case BFS_STAT_NLINK: + return "link count"; + case BFS_STAT_GID: + return "group ID"; + case BFS_STAT_UID: + return "user ID"; + case BFS_STAT_SIZE: + return "size"; + case BFS_STAT_BLOCKS: + return "block count"; + case BFS_STAT_RDEV: + return "underlying device"; + case BFS_STAT_ATIME: + return "access time"; + case BFS_STAT_BTIME: + return "birth time"; + case BFS_STAT_CTIME: + return "change time"; + case BFS_STAT_MTIME: + return "modification time"; + } + + assert(false); + return "???"; +} + /** * Check if we should retry a failed stat() due to a potentially broken link. */ diff --git a/stat.h b/stat.h index 4bad74e..d9c9588 100644 --- a/stat.h +++ b/stat.h @@ -46,6 +46,11 @@ enum bfs_stat_field { BFS_STAT_MTIME = 1 << 13, }; +/** + * Get the human-readable name of a bfs_stat field. + */ +const char *bfs_stat_field_name(enum bfs_stat_field field); + /** * bfs_stat() flags. */ -- cgit v1.2.3