diff options
Diffstat (limited to 'ctx.c')
-rw-r--r-- | ctx.c | 311 |
1 files changed, 0 insertions, 311 deletions
@@ -1,311 +0,0 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2015-2022 Tavian Barnes <tavianator@tavianator.com> * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ - -#include "ctx.h" -#include "color.h" -#include "darray.h" -#include "diag.h" -#include "expr.h" -#include "mtab.h" -#include "pwcache.h" -#include "stat.h" -#include "trie.h" -#include <assert.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> - -const char *debug_flag_name(enum debug_flags flag) { - switch (flag) { - case DEBUG_COST: - return "cost"; - case DEBUG_EXEC: - return "exec"; - case DEBUG_OPT: - return "opt"; - case DEBUG_RATES: - return "rates"; - case DEBUG_SEARCH: - return "search"; - case DEBUG_STAT: - return "stat"; - case DEBUG_TREE: - return "tree"; - - case DEBUG_ALL: - break; - } - - assert(!"Unrecognized debug flag"); - return "???"; -} - -struct bfs_ctx *bfs_ctx_new(void) { - struct bfs_ctx *ctx = malloc(sizeof(*ctx)); - if (!ctx) { - return NULL; - } - - ctx->argv = NULL; - ctx->paths = NULL; - ctx->expr = NULL; - ctx->exclude = NULL; - - ctx->mindepth = 0; - ctx->maxdepth = INT_MAX; - ctx->flags = BFTW_RECOVER; - ctx->strategy = BFTW_BFS; - ctx->optlevel = 3; - ctx->debug = 0; - ctx->ignore_races = false; - ctx->posixly_correct = false; - ctx->status = false; - ctx->unique = false; - ctx->warn = false; - ctx->xargs_safe = false; - - ctx->colors = NULL; - ctx->colors_error = 0; - ctx->cout = NULL; - ctx->cerr = NULL; - - ctx->users = NULL; - ctx->users_error = 0; - ctx->groups = NULL; - ctx->groups_error = 0; - - ctx->mtab = NULL; - ctx->mtab_error = 0; - - trie_init(&ctx->files); - ctx->nfiles = 0; - - struct rlimit rl; - if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { - ctx->nofile_soft = rl.rlim_cur; - ctx->nofile_hard = rl.rlim_max; - } else { - ctx->nofile_soft = 1024; - ctx->nofile_hard = RLIM_INFINITY; - } - - return ctx; -} - -const struct bfs_users *bfs_ctx_users(const struct bfs_ctx *ctx) { - struct bfs_ctx *mut = (struct bfs_ctx *)ctx; - - if (mut->users_error) { - errno = mut->users_error; - } else if (!mut->users) { - mut->users = bfs_users_parse(); - if (!mut->users) { - mut->users_error = errno; - } - } - - return mut->users; -} - -const struct bfs_groups *bfs_ctx_groups(const struct bfs_ctx *ctx) { - struct bfs_ctx *mut = (struct bfs_ctx *)ctx; - - if (mut->groups_error) { - errno = mut->groups_error; - } else if (!mut->groups) { - mut->groups = bfs_groups_parse(); - if (!mut->groups) { - mut->groups_error = errno; - } - } - - return mut->groups; -} - -const struct bfs_mtab *bfs_ctx_mtab(const struct bfs_ctx *ctx) { - struct bfs_ctx *mut = (struct bfs_ctx *)ctx; - - if (mut->mtab_error) { - errno = mut->mtab_error; - } else if (!mut->mtab) { - mut->mtab = bfs_mtab_parse(); - if (!mut->mtab) { - mut->mtab_error = errno; - } - } - - return mut->mtab; -} - -/** - * An open file tracked by the bfs context. - */ -struct bfs_ctx_file { - /** The file itself. */ - CFILE *cfile; - /** The path to the file (for diagnostics). */ - const char *path; -}; - -CFILE *bfs_ctx_dedup(struct bfs_ctx *ctx, CFILE *cfile, const char *path) { - struct bfs_stat sb; - if (bfs_stat(fileno(cfile->file), NULL, 0, &sb) != 0) { - return NULL; - } - - bfs_file_id id; - bfs_stat_id(&sb, &id); - - struct trie_leaf *leaf = trie_insert_mem(&ctx->files, id, sizeof(id)); - if (!leaf) { - return NULL; - } - - struct bfs_ctx_file *ctx_file = leaf->value; - if (ctx_file) { - ctx_file->path = path; - return ctx_file->cfile; - } - - leaf->value = ctx_file = malloc(sizeof(*ctx_file)); - if (!ctx_file) { - trie_remove(&ctx->files, leaf); - return NULL; - } - - ctx_file->cfile = cfile; - ctx_file->path = path; - - if (cfile != ctx->cout && cfile != ctx->cerr) { - ++ctx->nfiles; - } - - return cfile; -} - -void bfs_ctx_flush(const struct bfs_ctx *ctx) { - // Before executing anything, flush all open streams. This ensures that - // - the user sees everything relevant before an -ok[dir] prompt - // - output from commands is interleaved consistently with bfs - // - executed commands can rely on I/O from other bfs actions - // - // We do not check errors here, but they will be caught at cleanup time - // with ferror(). - fflush(NULL); -} - -/** Flush a file and report any errors. */ -static int bfs_ctx_fflush(CFILE *cfile) { - int ret = 0, error = 0; - if (ferror(cfile->file)) { - ret = -1; - error = EIO; - } - if (fflush(cfile->file) != 0) { - ret = -1; - error = errno; - } - - errno = error; - return ret; -} - -/** Close a file tracked by the bfs context. */ -static int bfs_ctx_fclose(struct bfs_ctx *ctx, struct bfs_ctx_file *ctx_file) { - CFILE *cfile = ctx_file->cfile; - - if (cfile == ctx->cout) { - // Will be checked later - return 0; - } else if (cfile == ctx->cerr) { - // Writes to stderr are allowed to fail silently, unless the same file was used by - // -fprint, -fls, etc. - if (ctx_file->path) { - return bfs_ctx_fflush(cfile); - } else { - return 0; - } - } - - int ret = 0, error = 0; - if (ferror(cfile->file)) { - ret = -1; - error = EIO; - } - if (cfclose(cfile) != 0) { - ret = -1; - error = errno; - } - - errno = error; - return ret; -} - -int bfs_ctx_free(struct bfs_ctx *ctx) { - int ret = 0; - - if (ctx) { - CFILE *cout = ctx->cout; - CFILE *cerr = ctx->cerr; - - bfs_expr_free(ctx->exclude); - bfs_expr_free(ctx->expr); - - bfs_mtab_free(ctx->mtab); - - bfs_groups_free(ctx->groups); - bfs_users_free(ctx->users); - - struct trie_leaf *leaf; - while ((leaf = trie_first_leaf(&ctx->files))) { - struct bfs_ctx_file *ctx_file = leaf->value; - - if (bfs_ctx_fclose(ctx, ctx_file) != 0) { - if (cerr) { - bfs_error(ctx, "'%s': %m.\n", ctx_file->path); - } - ret = -1; - } - - free(ctx_file); - trie_remove(&ctx->files, leaf); - } - trie_destroy(&ctx->files); - - if (cout && bfs_ctx_fflush(cout) != 0) { - if (cerr) { - bfs_error(ctx, "standard output: %m.\n"); - } - ret = -1; - } - - cfclose(cout); - cfclose(cerr); - - free_colors(ctx->colors); - - for (size_t i = 0; i < darray_length(ctx->paths); ++i) { - free((char *)ctx->paths[i]); - } - darray_free(ctx->paths); - - free(ctx->argv); - free(ctx); - } - - return ret; -} |