diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-02-04 16:33:53 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-02-04 16:33:53 -0500 |
commit | d696346689e161ee8a5623182ed65ab119adb203 (patch) | |
tree | 3c55935d75f847a21c82c1ca7e400971f4f12fb2 | |
parent | 0a3754f8b66fc50dafeb61711679fc85c1e38038 (diff) | |
download | bfs-d696346689e161ee8a5623182ed65ab119adb203.tar.xz |
Implement -[ac]?newer.
-rw-r--r-- | bfs.h | 1 | ||||
-rw-r--r-- | color.c | 2 | ||||
-rw-r--r-- | eval.c | 37 | ||||
-rw-r--r-- | parse.c | 43 | ||||
-rwxr-xr-x | tests.sh | 12 |
5 files changed, 93 insertions, 2 deletions
@@ -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); @@ -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); } @@ -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) { @@ -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) { @@ -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" |