summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-02-04 16:33:53 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-02-04 16:33:53 -0500
commitd696346689e161ee8a5623182ed65ab119adb203 (patch)
tree3c55935d75f847a21c82c1ca7e400971f4f12fb2
parent0a3754f8b66fc50dafeb61711679fc85c1e38038 (diff)
downloadbfs-d696346689e161ee8a5623182ed65ab119adb203.tar.xz
Implement -[ac]?newer.
-rw-r--r--bfs.h1
-rw-r--r--color.c2
-rw-r--r--eval.c37
-rw-r--r--parse.c43
-rwxr-xr-xtests.sh12
5 files changed, 93 insertions, 2 deletions
diff --git a/bfs.h b/bfs.h
index 2a9ba2e..6c691b4 100644
--- a/bfs.h
+++ b/bfs.h
@@ -146,6 +146,7 @@ bool eval_false(const struct expr *expr, struct eval_state *state);
bool eval_access(const struct expr *expr, struct eval_state *state);
bool eval_acmtime(const struct expr *expr, struct eval_state *state);
+bool eval_acnewer(const struct expr *expr, struct eval_state *state);
bool eval_gid(const struct expr *expr, struct eval_state *state);
bool eval_uid(const struct expr *expr, struct eval_state *state);
diff --git a/color.c b/color.c
index 8e22340..d89be4f 100644
--- a/color.c
+++ b/color.c
@@ -318,7 +318,7 @@ void print_error(const struct color_table *colors, const char *path, int error)
if (color) {
print_esc(color, stderr);
}
- fprintf(stderr, "Error at %s: %s\n", path, strerror(error));
+ fprintf(stderr, "'%s': %s\n", path, strerror(error));
if (color) {
print_esc(colors->reset, stderr);
}
diff --git a/eval.c b/eval.c
index 2463d86..33da8e4 100644
--- a/eval.c
+++ b/eval.c
@@ -1,3 +1,14 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2015-2016 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
#include "bfs.h"
#include "bftw.h"
#include <dirent.h>
@@ -122,6 +133,32 @@ bool eval_acmtime(const struct expr *expr, struct eval_state *state) {
}
/**
+ * -[ac]?newer tests.
+ */
+bool eval_acnewer(const struct expr *expr, struct eval_state *state) {
+ const struct stat *statbuf = fill_statbuf(state);
+ if (!statbuf) {
+ return false;
+ }
+
+ const struct timespec *time;
+ switch (expr->timefield) {
+ case ATIME:
+ time = &statbuf->st_atim;
+ break;
+ case CTIME:
+ time = &statbuf->st_ctim;
+ break;
+ case MTIME:
+ time = &statbuf->st_mtim;
+ break;
+ }
+
+ return time->tv_sec > expr->reftime.tv_sec
+ || (time->tv_sec == expr->reftime.tv_sec && time->tv_nsec > expr->reftime.tv_nsec);
+}
+
+/**
* -gid test.
*/
bool eval_gid(const struct expr *expr, struct eval_state *state) {
diff --git a/parse.c b/parse.c
index 898b5df..da9ee9c 100644
--- a/parse.c
+++ b/parse.c
@@ -1,8 +1,23 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2015-2016 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
#include "bfs.h"
+#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
@@ -320,6 +335,28 @@ static struct expr *parse_acmtime(struct parser_state *state, const char *option
}
/**
+ * Parse -[ac]?newer.
+ */
+static struct expr *parse_acnewer(struct parser_state *state, const char *option, enum timefield field) {
+ struct expr *expr = parse_test_sdata(state, option, eval_acnewer);
+ if (!expr) {
+ return NULL;
+ }
+
+ struct stat sb;
+ if (fstatat(AT_FDCWD, expr->sdata, &sb, AT_SYMLINK_NOFOLLOW) != 0) {
+ print_error(NULL, expr->sdata, errno);
+ free_expr(expr);
+ return NULL;
+ }
+
+ expr->reftime = sb.st_mtim;
+ expr->timefield = field;
+
+ return expr;
+}
+
+/**
* "Parse" -daystart.
*/
static struct expr *parse_daystart(struct parser_state *state) {
@@ -426,10 +463,14 @@ static struct expr *parse_literal(struct parser_state *state) {
return parse_acmtime(state, arg, ATIME, MINUTES);
} else if (strcmp(arg, "-atime") == 0) {
return parse_acmtime(state, arg, ATIME, DAYS);
+ } else if (strcmp(arg, "-anewer") == 0) {
+ return parse_acnewer(state, arg, ATIME);
} else if (strcmp(arg, "-cmin") == 0) {
return parse_acmtime(state, arg, CTIME, MINUTES);
} else if (strcmp(arg, "-ctime") == 0) {
return parse_acmtime(state, arg, CTIME, DAYS);
+ } else if (strcmp(arg, "-cnewer") == 0) {
+ return parse_acnewer(state, arg, CTIME);
} else if (strcmp(arg, "-color") == 0) {
state->cl->color = true;
return new_option(state, arg);
@@ -468,6 +509,8 @@ static struct expr *parse_literal(struct parser_state *state) {
return parse_acmtime(state, arg, MTIME, DAYS);
} else if (strcmp(arg, "-name") == 0) {
return parse_test_sdata(state, arg, eval_name);
+ } else if (strcmp(arg, "-newer") == 0) {
+ return parse_acnewer(state, arg, MTIME);
} else if (strcmp(arg, "-path") == 0 || strcmp(arg, "-wholename") == 0) {
return parse_test_sdata(state, arg, eval_path);
} else if (strcmp(arg, "-print") == 0) {
diff --git a/tests.sh b/tests.sh
index 23a9aba..a45af5f 100755
--- a/tests.sh
+++ b/tests.sh
@@ -124,7 +124,17 @@ function test_0017() {
find_diff "$1" -uid -10000
}
-for i in {1..17}; do
+function test_0018() {
+ basic_structure "$1"
+ find_diff "$1" -newer "$1/e/f"
+}
+
+function test_0019() {
+ basic_structure "$1"
+ find_diff "$1" -cnewer "$1/e/f"
+}
+
+for i in {1..19}; do
dir="$(mktemp -d "${TMPDIR:-/tmp}"/bfs.XXXXXXXXXX)"
test="test_$(printf '%04d' $i)"
"$test" "$dir"