diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-02-01 17:41:55 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-02-02 10:35:52 -0500 |
commit | b997ddf3df6535765f7eab0683eae4703933a703 (patch) | |
tree | f49da0ca0bb1d84d6a0eb4494dc52e1b911aaf74 /eval.c | |
parent | e641450d7d5dd86139b92fe6f69801b16dd3eeed (diff) | |
download | bfs-b997ddf3df6535765f7eab0683eae4703933a703.tar.xz |
Add -[acm]{min,time} support.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 141 |
1 files changed, 130 insertions, 11 deletions
@@ -8,6 +8,7 @@ #include <string.h> #include <sys/resource.h> #include <sys/stat.h> +#include <time.h> #include <unistd.h> struct eval_state { @@ -24,17 +25,57 @@ struct eval_state { /** * Perform a stat() call if necessary. */ -static void fill_statbuf(eval_state *state) { +static const struct stat *fill_statbuf(eval_state *state) { struct BFTW *ftwbuf = state->ftwbuf; - if (ftwbuf->statbuf) { - return; + if (!ftwbuf->statbuf) { + if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) { + ftwbuf->statbuf = &state->statbuf; + } else { + perror("fstatat()"); + } } + return ftwbuf->statbuf; +} - if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) { - ftwbuf->statbuf = &state->statbuf; - } else { - perror("fstatat()"); +/** + * Get the difference (in seconds) between two struct timespecs. + */ +static time_t timespec_diff(const struct timespec *lhs, const struct timespec *rhs) { + time_t ret = lhs->tv_sec - rhs->tv_sec; + if (lhs->tv_nsec < rhs->tv_nsec) { + --ret; + } + return ret; +} + +/** + * Convert a second count to minutes. + */ +static time_t to_minutes(time_t seconds) { + return seconds/60; +} + +/** + * Convert a second count to days. + */ +static time_t to_days(time_t seconds) { + return seconds/60/60/24; +} + +/** + * Perform a comparison. + */ +static bool do_cmp(const expression *expr, int n) { + switch (expr->cmp) { + case CMP_EXACT: + return n == expr->idata; + case CMP_LESS: + return n < expr->idata; + case CMP_GREATER: + return n > expr->idata; } + + return false; } /** @@ -52,7 +93,7 @@ bool eval_false(const expression *expr, eval_state *state) { } /** - * -executable, -readable, -writable action. + * -executable, -readable, -writable tests. */ bool eval_access(const expression *expr, eval_state *state) { struct BFTW *ftwbuf = state->ftwbuf; @@ -60,6 +101,84 @@ bool eval_access(const expression *expr, eval_state *state) { } /** + * -amin test. + */ +bool eval_amin(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_atim); + return do_cmp(expr, to_minutes(diff)); +} + +/** + * -atime test. + */ +bool eval_atime(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_atim); + return do_cmp(expr, to_days(diff)); +} + +/** + * -cmin test. + */ +bool eval_cmin(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_ctim); + return do_cmp(expr, to_minutes(diff)); +} + +/** + * -ctime test. + */ +bool eval_ctime(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_ctim); + return do_cmp(expr, to_days(diff)); +} + +/** + * -mmin test. + */ +bool eval_mmin(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_mtim); + return do_cmp(expr, to_minutes(diff)); +} + +/** + * -mtime test. + */ +bool eval_mtime(const expression *expr, eval_state *state) { + const struct stat *statbuf = fill_statbuf(state); + if (!statbuf) { + return false; + } + + time_t diff = timespec_diff(&state->cl->now, &statbuf->st_mtim); + return do_cmp(expr, to_days(diff)); +} + +/** * -delete action. */ bool eval_delete(const expression *expr, eval_state *state) { @@ -111,9 +230,9 @@ bool eval_empty(const expression *expr, eval_state *state) { closedir(dir); } else { - fill_statbuf(state); - if (ftwbuf->statbuf) { - ret = ftwbuf->statbuf->st_size == 0; + const struct stat *statbuf = fill_statbuf(state); + if (statbuf) { + ret = statbuf->st_size == 0; } } |