summaryrefslogtreecommitdiffstats
path: root/src/opt.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2022-11-09 11:14:12 -0500
committerTavian Barnes <tavianator@tavianator.com>2022-11-09 12:08:20 -0500
commitb41dca52762c5188638236ae81b9f4597bb29ac9 (patch)
tree4d503f6dcee1b1ed15ef61df3c8ccb9b92533546 /src/opt.c
parentdd6808539013061a3113e45c7267430e56749f2c (diff)
downloadbfs-b41dca52762c5188638236ae81b9f4597bb29ac9.tar.xz
pwcache: Fill the user/group caches lazily
Iterating all the users/groups can be expensive, especially with NSS. Android has so many that it doesn't even return them all from get{pw,gr}ent() for performance reasons, leading to incorrect behaviour of -user/-group/etc.
Diffstat (limited to 'src/opt.c')
-rw-r--r--src/opt.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/opt.c b/src/opt.c
index cece337..fa2e66c 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -48,6 +48,7 @@
#include "expr.h"
#include "pwcache.h"
#include <assert.h>
+#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -789,12 +790,13 @@ static void infer_icmp_facts(struct opt_state *state, const struct bfs_expr *exp
static void infer_gid_facts(struct opt_state *state, const struct bfs_expr *expr) {
infer_icmp_facts(state, expr, GID_RANGE);
- const struct bfs_groups *groups = bfs_ctx_groups(state->ctx);
struct range *range = &state->facts_when_true.ranges[GID_RANGE];
- if (groups && range->min == range->max) {
+ if (range->min == range->max) {
gid_t gid = range->min;
- bool nogroup = !bfs_getgrgid(groups, gid);
- constrain_pred(&state->facts_when_true.preds[NOGROUP_PRED], nogroup);
+ bool nogroup = !bfs_getgrgid(state->ctx->groups, gid);
+ if (errno == 0) {
+ constrain_pred(&state->facts_when_true.preds[NOGROUP_PRED], nogroup);
+ }
}
}
@@ -802,12 +804,13 @@ static void infer_gid_facts(struct opt_state *state, const struct bfs_expr *expr
static void infer_uid_facts(struct opt_state *state, const struct bfs_expr *expr) {
infer_icmp_facts(state, expr, UID_RANGE);
- const struct bfs_users *users = bfs_ctx_users(state->ctx);
struct range *range = &state->facts_when_true.ranges[UID_RANGE];
- if (users && range->min == range->max) {
+ if (range->min == range->max) {
uid_t uid = range->min;
- bool nouser = !bfs_getpwuid(users, uid);
- constrain_pred(&state->facts_when_true.preds[NOUSER_PRED], nouser);
+ bool nouser = !bfs_getpwuid(state->ctx->users, uid);
+ if (errno == 0) {
+ constrain_pred(&state->facts_when_true.preds[NOUSER_PRED], nouser);
+ }
}
}