summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-02-01 17:41:55 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-02-02 10:35:52 -0500
commitb997ddf3df6535765f7eab0683eae4703933a703 (patch)
treef49da0ca0bb1d84d6a0eb4494dc52e1b911aaf74 /eval.c
parente641450d7d5dd86139b92fe6f69801b16dd3eeed (diff)
downloadbfs-b997ddf3df6535765f7eab0683eae4703933a703.tar.xz
Add -[acm]{min,time} support.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c141
1 files changed, 130 insertions, 11 deletions
diff --git a/eval.c b/eval.c
index 417bfc3..243546e 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
}
}