summaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c56
1 files changed, 35 insertions, 21 deletions
diff --git a/src/eval.c b/src/eval.c
index 0b5992e..9789b5d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -5,10 +5,11 @@
* Implementation of all the primary expressions.
*/
-#include "prelude.h"
#include "eval.h"
+
#include "atomic.h"
#include "bar.h"
+#include "bfs.h"
#include "bfstd.h"
#include "bftw.h"
#include "color.h"
@@ -27,11 +28,13 @@
#include "stat.h"
#include "trie.h"
#include "xregex.h"
+
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <grp.h>
#include <pwd.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -53,6 +56,8 @@ struct bfs_eval {
enum bftw_action action;
/** The bfs_eval() return value. */
int *ret;
+ /** The number of errors that have occurred. */
+ size_t *nerrors;
/** Whether to quit immediately. */
bool quit;
};
@@ -60,12 +65,18 @@ struct bfs_eval {
/**
* Print an error message.
*/
-attr(printf(2, 3))
+_printf(2, 3)
static void eval_error(struct bfs_eval *state, const char *format, ...) {
+ const struct bfs_ctx *ctx = state->ctx;
+
+ ++*state->nerrors;
+ if (ctx->ignore_errors) {
+ return;
+ }
+
// By POSIX, any errors should be accompanied by a non-zero exit status
*state->ret = EXIT_FAILURE;
- const struct bfs_ctx *ctx = state->ctx;
CFILE *cerr = ctx->cerr;
bfs_error(ctx, "%pP: ", state->ftwbuf);
@@ -269,10 +280,10 @@ bool eval_time(const struct bfs_expr *expr, struct bfs_eval *state) {
switch (expr->time_unit) {
case BFS_DAYS:
diff /= 60 * 24;
- fallthru;
+ _fallthrough;
case BFS_MINUTES:
diff /= 60;
- fallthru;
+ _fallthrough;
case BFS_SECONDS:
break;
}
@@ -1014,25 +1025,23 @@ bool eval_xtype(const struct bfs_expr *expr, struct bfs_eval *state) {
}
}
-#if _POSIX_MONOTONIC_CLOCK > 0
-# define BFS_CLOCK CLOCK_MONOTONIC
-#elif _POSIX_TIMERS > 0
-# define BFS_CLOCK CLOCK_REALTIME
-#endif
-
/**
- * Call clock_gettime(), if available.
+ * clock_gettime() wrapper.
*/
static int eval_gettime(struct bfs_eval *state, struct timespec *ts) {
-#ifdef BFS_CLOCK
- int ret = clock_gettime(BFS_CLOCK, ts);
+ clockid_t clock = CLOCK_REALTIME;
+
+#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
+ if (sysoption(MONOTONIC_CLOCK) > 0) {
+ clock = CLOCK_MONOTONIC;
+ }
+#endif
+
+ int ret = clock_gettime(clock, ts);
if (ret != 0) {
bfs_warning(state->ctx, "%pP: clock_gettime(): %s.\n", state->ftwbuf, errstr());
}
return ret;
-#else
- return -1;
-#endif
}
/**
@@ -1382,8 +1391,6 @@ struct callback_args {
struct bfs_bar *bar;
/** The time of the last status update. */
struct timespec last_status;
- /** SIGINFO hook. */
- struct sighook *info_hook;
/** Flag set by SIGINFO hook. */
atomic bool info_flag;
@@ -1393,6 +1400,8 @@ struct callback_args {
/** The set of seen files. */
struct trie *seen;
+ /** The number of errors that have occurred. */
+ size_t nerrors;
/** Eventual return value from bfs_eval(). */
int ret;
};
@@ -1411,6 +1420,7 @@ static enum bftw_action eval_callback(const struct BFTW *ftwbuf, void *ptr) {
state.ctx = ctx;
state.action = BFTW_CONTINUE;
state.ret = &args->ret;
+ state.nerrors = &args->nerrors;
state.quit = false;
// Check whether SIGINFO was delivered and show/hide the bar
@@ -1672,7 +1682,7 @@ int bfs_eval(struct bfs_ctx *ctx) {
#else
int siginfo = SIGUSR1;
#endif
- args.info_hook = sighook(siginfo, eval_siginfo, &args, SH_CONTINUE);
+ struct sighook *info_hook = sighook(siginfo, eval_siginfo, &args, SH_CONTINUE);
struct trie seen;
if (ctx->unique) {
@@ -1741,8 +1751,12 @@ int bfs_eval(struct bfs_ctx *ctx) {
trie_destroy(&seen);
}
- sigunhook(args.info_hook);
+ sigunhook(info_hook);
bfs_bar_hide(args.bar);
+ if (ctx->ignore_errors && args.nerrors > 0) {
+ bfs_warning(ctx, "Suppressed errors: %zu\n", args.nerrors);
+ }
+
return args.ret;
}