From fc63f1b33fb438e8f7690db9bd84e3c69fe86b51 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 9 Nov 2022 11:35:53 -0500 Subject: ctx: Flush the user/group caches when executing commands This fixes (admittedly uncommon) commands like $ bfs -nouser -exec add-missing-user.sh {} \; --- src/ctx.c | 5 +++++ src/pwcache.c | 46 ++++++++++++++++++++++------------------------ src/pwcache.h | 16 ++++++++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/ctx.c b/src/ctx.c index 8d80691..4b373a1 100644 --- a/src/ctx.c +++ b/src/ctx.c @@ -186,6 +186,11 @@ void bfs_ctx_flush(const struct bfs_ctx *ctx) { // We do not check errors here, but they will be caught at cleanup time // with ferror(). fflush(NULL); + + // Flush the user/group caches, in case the executed command edits the + // user/group tables + bfs_users_flush(ctx->users); + bfs_groups_flush(ctx->groups); } /** Flush a file and report any errors. */ diff --git a/src/pwcache.c b/src/pwcache.c index 7071f59..868ec8f 100644 --- a/src/pwcache.c +++ b/src/pwcache.c @@ -64,6 +64,16 @@ static void *bfs_getent(struct trie_leaf *leaf, bfs_getent_fn *fn, const void *k } } +/** Flush a single cache. */ +static void bfs_pwcache_flush(struct trie *trie) { + TRIE_FOR_EACH(trie, leaf) { + if (leaf->value != MISSING) { + free(leaf->value); + } + trie_remove(trie, leaf); + } +} + struct bfs_users { /** Initial buffer size for getpw*_r(). */ size_t bufsize; @@ -123,22 +133,16 @@ const struct passwd *bfs_getpwuid(struct bfs_users *users, uid_t uid) { return bfs_getent(leaf, bfs_getpwuid_impl, &uid, sizeof(struct passwd), users->bufsize); } +void bfs_users_flush(struct bfs_users *users) { + bfs_pwcache_flush(&users->by_name); + bfs_pwcache_flush(&users->by_uid); +} + void bfs_users_free(struct bfs_users *users) { if (users) { - TRIE_FOR_EACH(&users->by_uid, leaf) { - if (leaf->value != MISSING) { - free(leaf->value); - } - } + bfs_users_flush(users); trie_destroy(&users->by_uid); - - TRIE_FOR_EACH(&users->by_name, leaf) { - if (leaf->value != MISSING) { - free(leaf->value); - } - } trie_destroy(&users->by_name); - free(users); } } @@ -202,22 +206,16 @@ const struct group *bfs_getgrgid(struct bfs_groups *groups, gid_t gid) { return bfs_getent(leaf, bfs_getgrgid_impl, &gid, sizeof(struct group), groups->bufsize); } +void bfs_groups_flush(struct bfs_groups *groups) { + bfs_pwcache_flush(&groups->by_name); + bfs_pwcache_flush(&groups->by_gid); +} + void bfs_groups_free(struct bfs_groups *groups) { if (groups) { - TRIE_FOR_EACH(&groups->by_gid, leaf) { - if (leaf->value != MISSING) { - free(leaf->value); - } - } + bfs_groups_flush(groups); trie_destroy(&groups->by_gid); - - TRIE_FOR_EACH(&groups->by_name, leaf) { - if (leaf->value != MISSING) { - free(leaf->value); - } - } trie_destroy(&groups->by_name); - free(groups); } } diff --git a/src/pwcache.h b/src/pwcache.h index 6ae8bea..f1ca0bf 100644 --- a/src/pwcache.h +++ b/src/pwcache.h @@ -63,6 +63,14 @@ const struct passwd *bfs_getpwnam(struct bfs_users *users, const char *name); */ const struct passwd *bfs_getpwuid(struct bfs_users *users, uid_t uid); +/** + * Flush a user cache. + * + * @param users + * The cache to flush. + */ +void bfs_users_flush(struct bfs_users *users); + /** * Free a user cache. * @@ -110,6 +118,14 @@ const struct group *bfs_getgrnam(struct bfs_groups *groups, const char *name); */ const struct group *bfs_getgrgid(struct bfs_groups *groups, gid_t gid); +/** + * Flush a group cache. + * + * @param groups + * The cache to flush. + */ +void bfs_groups_flush(struct bfs_groups *groups); + /** * Free a group cache. * -- cgit v1.2.3