summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-02-04 14:32:39 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-02-04 14:32:39 -0500
commit0a3754f8b66fc50dafeb61711679fc85c1e38038 (patch)
tree6a79b031b35df2726871c80910b5669fe4ef81e2
parentbff3576bedf7337d2cd7bd8f106519b38d128535 (diff)
downloadbfs-0a3754f8b66fc50dafeb61711679fc85c1e38038.tar.xz
Implements -daystart.
-rw-r--r--bfs.h9
-rw-r--r--eval.c2
-rw-r--r--parse.c46
3 files changed, 48 insertions, 9 deletions
diff --git a/bfs.h b/bfs.h
index bf33a33..2a9ba2e 100644
--- a/bfs.h
+++ b/bfs.h
@@ -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;
};
diff --git a/eval.c b/eval.c
index 258857c..2463d86 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/parse.c b/parse.c
index 4f6f987..898b5df 100644
--- a/parse.c
+++ b/parse.c
@@ -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) {