diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-02-04 14:32:39 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-02-04 14:32:39 -0500 |
commit | 0a3754f8b66fc50dafeb61711679fc85c1e38038 (patch) | |
tree | 6a79b031b35df2726871c80910b5669fe4ef81e2 | |
parent | bff3576bedf7337d2cd7bd8f106519b38d128535 (diff) | |
download | bfs-0a3754f8b66fc50dafeb61711679fc85c1e38038.tar.xz |
Implements -daystart.
-rw-r--r-- | bfs.h | 9 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | parse.c | 46 |
3 files changed, 48 insertions, 9 deletions
@@ -63,9 +63,6 @@ struct cmdline { /** The command line expression. */ struct expr *expr; - - /** The current time. */ - struct timespec now; }; /** @@ -109,14 +106,20 @@ struct expr { struct expr *rhs; /** The function that evaluates this expression. */ eval_fn *eval; + /** The optional comparison flag. */ enum cmpflag cmp; + + /** The optional reference time. */ + struct timespec reftime; /** The optional time field. */ enum timefield timefield; /** The optional time unit. */ enum timeunit timeunit; + /** Optional integer data for this expression. */ int idata; + /** Optional string data for this expression. */ const char *sdata; }; @@ -108,7 +108,7 @@ bool eval_acmtime(const struct expr *expr, struct eval_state *state) { break; } - time_t diff = timespec_diff(&state->cl->now, time); + time_t diff = timespec_diff(&expr->reftime, time); switch (expr->timeunit) { case MINUTES: diff /= 60; @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> /** @@ -127,6 +128,9 @@ struct parser_state { bool warn; /** Whether any non-option arguments have been encountered. */ bool non_option_seen; + + /** The current time. */ + struct timespec now; }; /** @@ -308,6 +312,7 @@ static struct expr *parse_test_sdata(struct parser_state *state, const char *tes static struct expr *parse_acmtime(struct parser_state *state, const char *option, enum timefield field, enum timeunit unit) { struct expr *expr = parse_test_icmp(state, option, eval_acmtime); if (expr) { + expr->reftime = state->now; expr->timefield = field; expr->timeunit = unit; } @@ -315,6 +320,35 @@ static struct expr *parse_acmtime(struct parser_state *state, const char *option } /** + * "Parse" -daystart. + */ +static struct expr *parse_daystart(struct parser_state *state) { + // Should be called before localtime_r() according to POSIX.1-2004 + tzset(); + + struct tm tm; + if (!localtime_r(&state->now.tv_sec, &tm)) { + perror("localtime_r()"); + return NULL; + } + + tm.tm_sec = 0; + tm.tm_min = 0; + tm.tm_hour = 0; + ++tm.tm_mday; + time_t time = mktime(&tm); + if (time == -1) { + perror("mktime()"); + return NULL; + } + + state->now.tv_sec = time; + state->now.tv_nsec = 0; + + return new_positional_option(state); +} + +/** * Parse -{min,max}depth N. */ static struct expr *parse_depth(struct parser_state *state, const char *option, int *depth) { @@ -402,6 +436,8 @@ static struct expr *parse_literal(struct parser_state *state) { } else if (strcmp(arg, "-nocolor") == 0) { state->cl->color = false; return new_option(state, arg); + } else if (strcmp(arg, "-daystart") == 0) { + return parse_daystart(state); } else if (strcmp(arg, "-delete") == 0) { state->cl->flags |= BFTW_DEPTH; return new_action(state, eval_delete); @@ -681,11 +717,6 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { cl->flags = BFTW_RECOVER; cl->expr = &expr_true; - if (clock_gettime(CLOCK_REALTIME, &cl->now) != 0) { - perror("clock_gettime()"); - goto fail; - } - struct parser_state state = { .cl = cl, .argv = argv, @@ -695,6 +726,11 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { .non_option_seen = false, }; + if (clock_gettime(CLOCK_REALTIME, &state.now) != 0) { + perror("clock_gettime()"); + goto fail; + } + if (skip_paths(&state)) { cl->expr = parse_expr(&state); if (!cl->expr) { |