diff options
Diffstat (limited to 'src')
42 files changed, 818 insertions, 736 deletions
diff --git a/src/Makefile b/src/Makefile index 4360c48..e2b40ba 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ libapk_soname := 3.12.0 libapk_so := $(obj)/libapk.so.$(libapk_soname) libapk.so.$(libapk_soname)-objs := \ adb.o adb_trust.o \ - common.o database.o package.o commit.o solver.o \ + common.o context.o database.o package.o commit.o solver.o \ version.o atom.o blob.o hash.o print.o \ io.o io_url.o io_gunzip.o io_archive.o @@ -60,7 +60,7 @@ endif # Apk utility progs-y += apk -apk-objs := apk.o help.o \ +apk-objs := apk.o applet.o \ app_add.o app_del.o app_fix.o app_update.o app_upgrade.o \ app_info.o app_list.o app_search.o app_manifest.o \ app_policy.o app_stats.o \ diff --git a/src/adb_trust.c b/src/adb_trust.c index 41c904f..4f08441 100644 --- a/src/adb_trust.c +++ b/src/adb_trust.c @@ -248,11 +248,11 @@ int adb_trust_verify_signature(struct adb_trust *trust, struct adb *db, struct a APK_OPT_GROUP(options_signing, "Signing", SIGNING_OPTIONS); -static int option_parse_signing(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) +static int option_parse_signing(void *ctx, struct apk_ctx *ac, int optch, const char *optarg) { switch (optch) { case OPT_SIGN_sign_key: - *apk_string_array_add(&dbopts->private_keys) = (char*) optarg; + *apk_string_array_add(&ac->private_keys) = (char*) optarg; break; default: return -ENOTSUP; @@ -34,9 +34,6 @@ #include "apk_print.h" #include "apk_io.h" -static struct list_head apk_applet_list; -#define foreach_applet(iter) list_for_each_entry(iter, &apk_applet_list, node) - #ifdef TEST_MODE static const char *test_installed_db = NULL; static const char *test_world = NULL; @@ -54,13 +51,12 @@ time_t time(time_t *tloc) } #endif -static void version(void) +static void version(struct apk_out *out) { - printf("apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".\n" + apk_out(out, "apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH "."); #ifdef TEST_MODE - "TEST MODE BUILD. NOT FOR PRODUCTION USE.\n" + apk_out(out, "TEST MODE BUILD. NOT FOR PRODUCTION USE."); #endif - ); } #define GLOBAL_OPTIONS(OPT) \ @@ -106,95 +102,96 @@ APK_OPT_GROUP2(optiondesc_global, "Global", GLOBAL_OPTIONS, TEST_OPTIONS); APK_OPT_GROUP(optiondesc_global, "Global", GLOBAL_OPTIONS); #endif -static int option_parse_global(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_global(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { + struct apk_out *out = &ac->out; switch (opt) { case OPT_GLOBAL_help: return -EINVAL; case OPT_GLOBAL_root: - dbopts->root = optarg; + ac->root = optarg; break; case OPT_GLOBAL_keys_dir: - dbopts->keys_dir = optarg; + ac->keys_dir = optarg; break; case OPT_GLOBAL_repositories_file: - dbopts->repositories_file = optarg; + ac->repositories_file = optarg; break; case OPT_GLOBAL_repository: - *apk_string_array_add(&dbopts->repository_list) = (char*) optarg; + *apk_string_array_add(&ac->repository_list) = (char*) optarg; break; case OPT_GLOBAL_quiet: - apk_verbosity--; + if (ac->out.verbosity) ac->out.verbosity--; break; case OPT_GLOBAL_verbose: - apk_verbosity++; + ac->out.verbosity++; break; case OPT_GLOBAL_version: - version(); + version(out); return -ESHUTDOWN; case OPT_GLOBAL_force: - dbopts->force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK + ac->force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK | APK_FORCE_BROKEN_WORLD | APK_FORCE_NON_REPOSITORY | APK_FORCE_BINARY_STDOUT; break; case OPT_GLOBAL_force_overwrite: - dbopts->force |= APK_FORCE_OVERWRITE; + ac->force |= APK_FORCE_OVERWRITE; break; case OPT_GLOBAL_force_old_apk: - dbopts->force |= APK_FORCE_OLD_APK; + ac->force |= APK_FORCE_OLD_APK; break; case OPT_GLOBAL_force_broken_world: - dbopts->force |= APK_FORCE_BROKEN_WORLD; + ac->force |= APK_FORCE_BROKEN_WORLD; break; case OPT_GLOBAL_force_refresh: - dbopts->force |= APK_FORCE_REFRESH; + ac->force |= APK_FORCE_REFRESH; break; case OPT_GLOBAL_force_non_repository: - dbopts->force |= APK_FORCE_NON_REPOSITORY; + ac->force |= APK_FORCE_NON_REPOSITORY; break; case OPT_GLOBAL_force_binary_stdout: - dbopts->force |= APK_FORCE_BINARY_STDOUT; + ac->force |= APK_FORCE_BINARY_STDOUT; break; case OPT_GLOBAL_interactive: - dbopts->flags |= APK_INTERACTIVE; + ac->flags |= APK_INTERACTIVE; break; case OPT_GLOBAL_progress: - dbopts->progress.out = stdout; + ac->progress.out = &ac->out; break; case OPT_GLOBAL_no_progress: - dbopts->progress.out = NULL; + ac->progress.out = NULL; break; case OPT_GLOBAL_progress_fd: - dbopts->progress.fd = atoi(optarg); + ac->progress.fd = atoi(optarg); break; case OPT_GLOBAL_allow_untrusted: - dbopts->flags |= APK_ALLOW_UNTRUSTED; + ac->flags |= APK_ALLOW_UNTRUSTED; break; case OPT_GLOBAL_purge: - dbopts->flags |= APK_PURGE; + ac->flags |= APK_PURGE; break; case OPT_GLOBAL_wait: - dbopts->lock_wait = atoi(optarg); + ac->lock_wait = atoi(optarg); break; case OPT_GLOBAL_no_network: - dbopts->flags |= APK_NO_NETWORK; + ac->flags |= APK_NO_NETWORK; break; case OPT_GLOBAL_no_cache: - dbopts->flags |= APK_NO_CACHE; + ac->flags |= APK_NO_CACHE; break; case OPT_GLOBAL_cache_dir: - dbopts->cache_dir = optarg; + ac->cache_dir = optarg; break; case OPT_GLOBAL_update_cache: /* Make it one minute, to avoid updating indexes twice * when doing self-upgrade's re-exec */ - dbopts->cache_max_age = 60; + ac->cache_max_age = 60; break; case OPT_GLOBAL_cache_max_age: - dbopts->cache_max_age = atoi(optarg) * 60; + ac->cache_max_age = atoi(optarg) * 60; break; case OPT_GLOBAL_arch: - dbopts->arch = optarg; + ac->arch = optarg; break; case OPT_GLOBAL_print_arch: puts(APK_DEFAULT_ARCH); @@ -231,28 +228,28 @@ const struct apk_option_group optgroup_global = { APK_OPT_GROUP(optiondesc_commit, "Commit", COMMIT_OPTIONS); -static int option_parse_commit(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_commit(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { switch (opt) { case OPT_COMMIT_simulate: - dbopts->flags |= APK_SIMULATE; + ac->flags |= APK_SIMULATE; break; case OPT_COMMIT_clean_protected: - dbopts->flags |= APK_CLEAN_PROTECTED; + ac->flags |= APK_CLEAN_PROTECTED; break; case OPT_COMMIT_overlay_from_stdin: - dbopts->flags |= APK_OVERLAY_FROM_STDIN; + ac->flags |= APK_OVERLAY_FROM_STDIN; break; case OPT_COMMIT_no_scripts: - dbopts->flags |= APK_NO_SCRIPTS; + ac->flags |= APK_NO_SCRIPTS; break; case OPT_COMMIT_no_commit_hooks: - dbopts->flags |= APK_NO_COMMIT_HOOKS; + ac->flags |= APK_NO_COMMIT_HOOKS; break; case OPT_COMMIT_initramfs_diskless_boot: - dbopts->open_flags |= APK_OPENF_CREATE; - dbopts->flags |= APK_NO_COMMIT_HOOKS; - dbopts->force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK + ac->open_flags |= APK_OPENF_CREATE; + ac->flags |= APK_NO_COMMIT_HOOKS; + ac->force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK | APK_FORCE_BROKEN_WORLD | APK_FORCE_NON_REPOSITORY; break; default: @@ -266,25 +263,13 @@ const struct apk_option_group optgroup_commit = { .parse = option_parse_commit, }; -static int usage(struct apk_applet *applet) +static int usage(struct apk_out *out, struct apk_applet *applet) { - version(); - apk_help(applet); + version(out); + apk_applet_help(applet, out); return 1; } -static struct apk_applet *find_applet(const char *name) -{ - struct apk_applet *a; - - foreach_applet(a) { - if (strcmp(name, a->name) == 0) - return a; - } - - return NULL; -} - static struct apk_applet *deduce_applet(int argc, char **argv) { struct apk_applet *a; @@ -298,19 +283,20 @@ static struct apk_applet *deduce_applet(int argc, char **argv) prog++; if (strncmp(prog, "apk_", 4) == 0) - return find_applet(prog + 4); + return apk_applet_find(prog + 4); for (i = 1; i < argc; i++) { if (argv[i][0] == '-') continue; - a = find_applet(argv[i]); + a = apk_applet_find(argv[i]); if (a) return a; } return NULL; } -static int parse_options(int argc, char **argv, struct apk_applet *applet, void *ctx, struct apk_db_options *dbopts) +static int parse_options(int argc, char **argv, struct apk_applet *applet, void *ctx, struct apk_ctx *ac) { + struct apk_out *out = &ac->out; const struct apk_option_group *default_optgroups[] = { &optgroup_global, NULL }; const struct apk_option_group *og, **optgroups = default_optgroups; struct option all_options[80], *opt; @@ -357,7 +343,7 @@ static int parse_options(int argc, char **argv, struct apk_applet *applet, void while ((p = getopt_long(argc, argv, short_options, all_options, NULL)) != -1) { if (p >= 64 && p < 128) p = short_option_val[p - 64]; og = optgroups[p >> 10]; - r = og->parse(ctx, dbopts, p & 0x3ff, optarg); + r = og->parse(ctx, ac, p & 0x3ff, optarg); if (r == 0) continue; if (r == -EINVAL) { help_requested = 1; @@ -367,7 +353,7 @@ static int parse_options(int argc, char **argv, struct apk_applet *applet, void } if (help_requested || r == -ENOTSUP) - return usage(applet); + return usage(out, applet); return 0; } @@ -391,66 +377,51 @@ static void init_openssl(void) #endif } -static void on_sigwinch(int s) -{ - apk_reset_screen_width(); -} - -static void setup_terminal(void) -{ - signal(SIGWINCH, on_sigwinch); - signal(SIGPIPE, SIG_IGN); -} - -static void setup_automatic_flags(struct apk_db_options *dbopts) +static void setup_automatic_flags(struct apk_ctx *ac) { const char *tmp; if ((tmp = getenv("APK_PROGRESS_CHAR")) != NULL) - dbopts->progress.progress_char = tmp; + ac->progress.progress_char = tmp; else if ((tmp = getenv("LANG")) != NULL && strstr(tmp, "UTF-8") != NULL) - dbopts->progress.progress_char = "\u2588"; + ac->progress.progress_char = "\u2588"; else - dbopts->progress.progress_char = "#"; + ac->progress.progress_char = "#"; if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO) || !isatty(STDIN_FILENO)) return; - dbopts->progress.out = stdout; - if (!(dbopts->flags & APK_SIMULATE) && + ac->progress.out = &ac->out; + if (!(ac->flags & APK_SIMULATE) && access("/etc/apk/interactive", F_OK) == 0) - dbopts->flags |= APK_INTERACTIVE; + ac->flags |= APK_INTERACTIVE; } -void apk_applet_register(struct apk_applet *applet) +static struct apk_ctx ctx; +static struct apk_database db; + +static void on_sigint(int s) { - list_init(&applet->node); - list_add_tail(&applet->node, &apk_applet_list); + apk_db_close(&db); + exit(128 + s); } -static void apk_applet_register_builtin(void) +static void on_sigwinch(int s) { - extern apk_init_func_t __start_initapplets[], __stop_initapplets[]; - apk_init_func_t *p; - - list_init(&apk_applet_list); - for (p = __start_initapplets; p < __stop_initapplets; p++) - (*p)(); + apk_out_reset(&ctx.out); } -static struct apk_database db; - -static void on_sigint(int s) +static void setup_terminal(void) { - apk_db_close(&db); - exit(128 + s); + signal(SIGWINCH, on_sigwinch); + signal(SIGPIPE, SIG_IGN); } int main(int argc, char **argv) { - void *ctx = NULL; - struct apk_db_options dbopts; + void *applet_ctx = NULL; + struct apk_out *out = &ctx.out; struct apk_string_array *args; struct apk_applet *applet; int r; @@ -466,33 +437,31 @@ int main(int argc, char **argv) apk_argv[argc] = NULL; apk_argv[argc+1] = NULL; - memset(&dbopts, 0, sizeof(dbopts)); - apk_string_array_init(&dbopts.repository_list); - apk_string_array_init(&dbopts.private_keys); + apk_ctx_init(&ctx); umask(0); setup_terminal(); applet = deduce_applet(argc, argv); if (applet != NULL) { if (applet->context_size != 0) - ctx = calloc(1, applet->context_size); - dbopts.open_flags = applet->open_flags; - dbopts.force |= applet->forced_force; + applet_ctx = calloc(1, applet->context_size); + ctx.open_flags = applet->open_flags; + ctx.force |= applet->forced_force; } init_openssl(); - setup_automatic_flags(&dbopts); + setup_automatic_flags(&ctx); fetchConnectionCacheInit(32, 4); - r = parse_options(argc, argv, applet, ctx, &dbopts); + r = parse_options(argc, argv, applet, applet_ctx, &ctx); if (r != 0) goto err; if (applet == NULL) { if (argc > 1) { - apk_error("'%s' is not an apk command. See 'apk --help'.", argv[1]); + apk_err(out, "'%s' is not an apk command. See 'apk --help'.", argv[1]); return 1; } - return usage(NULL); + return usage(out, NULL); } argc -= optind; @@ -506,15 +475,14 @@ int main(int argc, char **argv) signal(SIGINT, on_sigint); #ifdef TEST_MODE - dbopts.open_flags &= ~(APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE | APK_OPENF_CREATE); - dbopts.open_flags |= APK_OPENF_READ | APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; - dbopts.flags |= APK_SIMULATE; - dbopts.flags &= ~APK_INTERACTIVE; + ctx.open_flags &= ~(APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE | APK_OPENF_CREATE); + ctx.open_flags |= APK_OPENF_READ | APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; + ctx.flags |= APK_SIMULATE; + ctx.flags &= ~APK_INTERACTIVE; #endif - r = apk_db_open(&db, &dbopts); + r = apk_db_open(&db, &ctx); if (r != 0) { - apk_error("Failed to open apk database: %s", - apk_error_str(r)); + apk_err(out, "Failed to open apk database: %s", apk_error_str(r)); goto err; } @@ -544,12 +512,12 @@ int main(int argc, char **argv) } if (apk_db_index_read(&db, apk_istream_from_file(AT_FDCWD, name.ptr), repo) != 0) { - apk_error("Failed to open repository: " BLOB_FMT, BLOB_PRINTF(name)); + apk_err(out, "Failed to open repository: " BLOB_FMT, BLOB_PRINTF(name)); goto err; } if (repo != -2) { - if (!(db.flags & APK_NO_NETWORK)) + if (!(ctx.flags & APK_NO_NETWORK)) db.available_repos |= BIT(repo); db.repo_tags[repo_tag].allowed_repos |= BIT(repo); } @@ -559,7 +527,7 @@ int main(int argc, char **argv) apk_string_array_resize(&args, argc); memcpy(args->item, argv, argc * sizeof(*argv)); - r = applet->main(ctx, &db, args); + r = applet->main(applet_ctx, &db, args); apk_db_close(&db); #ifdef TEST_MODE @@ -569,11 +537,11 @@ int main(int argc, char **argv) err: if (r == -ESHUTDOWN) r = 0; - if (ctx) free(ctx); + if (applet_ctx) free(applet_ctx); fetchConnectionCacheClose(); + apk_ctx_free(&ctx); apk_string_array_free(&args); - apk_string_array_free(&dbopts.private_keys); free(apk_argv); if (r < 0) r = 250; diff --git a/src/apk_applet.h b/src/apk_applet.h index 8e59390..2f4518b 100644 --- a/src/apk_applet.h +++ b/src/apk_applet.h @@ -15,13 +15,6 @@ #include "apk_defines.h" #include "apk_database.h" -#if 0 -#define APK_OPT1n(_opt) "\xf0" _opt "\x00" -#define APK_OPT1R(_opt) "\xaf" "\xf0" _opt "\x00" -#define APK_OPT2n(_opt, _short) _short _opt "\x00" -#define APK_OPT2R(_opt, _short) "\xaf" _short _opt "\x00" -#endif - #define __APK_OPTAPPLET "\x00" #define __APK_OPTGROUP(_name) _name "\x00" #define __APK_OPT_ENUM(_enum,__desc) _enum, @@ -45,8 +38,7 @@ struct apk_option_group { const char *desc; - int (*parse)(void *ctx, struct apk_db_options *dbopts, - int opt, const char *optarg); + int (*parse)(void *ctx, struct apk_ctx *ac, int opt, const char *optarg); }; struct apk_applet { @@ -63,10 +55,13 @@ struct apk_applet { extern const struct apk_option_group optgroup_global, optgroup_commit, optgroup_signing; -void apk_help(struct apk_applet *applet); void apk_applet_register(struct apk_applet *); +void apk_applet_register_builtin(void); +struct apk_applet *apk_applet_find(const char *name); +void apk_applet_help(struct apk_applet *applet, struct apk_out *out); typedef void (*apk_init_func_t)(void); + #define APK_DEFINE_APPLET(x) \ static void __register_##x(void) { apk_applet_register(&x); } \ static apk_init_func_t __regfunc_##x __attribute__((__section__("initapplets"))) __attribute((used)) = __register_##x; diff --git a/src/apk_archive.h b/src/apk_archive.h index 708fd1a..fdce49e 100644 --- a/src/apk_archive.h +++ b/src/apk_archive.h @@ -12,6 +12,7 @@ #include <sys/types.h> #include "apk_blob.h" +#include "apk_print.h" #include "apk_io.h" #define APK_EXTRACTF_NO_CHOWN 0x0001 @@ -31,6 +32,7 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, const char *extract_name, const char *hardlink_name, struct apk_istream *is, apk_progress_cb cb, void *cb_ctx, - unsigned int extract_flags); + unsigned int extract_flags, + struct apk_out *out); #endif diff --git a/src/apk_context.h b/src/apk_context.h new file mode 100644 index 0000000..27f7c4d --- /dev/null +++ b/src/apk_context.h @@ -0,0 +1,51 @@ +/* apk_context.h - Alpine Package Keeper (APK) + * + * Copyright (C) 2020 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#ifndef APK_CONTEXT_H +#define APK_CONTEXT_H + +#include "apk_print.h" + +#define APK_SIMULATE BIT(0) +#define APK_CLEAN_PROTECTED BIT(1) +#define APK_RECURSIVE BIT(2) +#define APK_ALLOW_UNTRUSTED BIT(3) +#define APK_PURGE BIT(4) +#define APK_INTERACTIVE BIT(5) +#define APK_NO_NETWORK BIT(6) +#define APK_OVERLAY_FROM_STDIN BIT(7) +#define APK_NO_SCRIPTS BIT(8) +#define APK_NO_CACHE BIT(9) +#define APK_NO_COMMIT_HOOKS BIT(10) + +#define APK_FORCE_OVERWRITE BIT(0) +#define APK_FORCE_OLD_APK BIT(1) +#define APK_FORCE_BROKEN_WORLD BIT(2) +#define APK_FORCE_REFRESH BIT(3) +#define APK_FORCE_NON_REPOSITORY BIT(4) +#define APK_FORCE_BINARY_STDOUT BIT(5) + +struct apk_ctx { + unsigned int flags, force, lock_wait; + struct apk_out out; + struct apk_progress progress; + unsigned int cache_max_age; + unsigned long open_flags; + const char *root; + const char *arch; + const char *keys_dir; + const char *cache_dir; + const char *repositories_file; + struct apk_string_array *repository_list; + struct apk_string_array *private_keys; +}; + +void apk_ctx_init(struct apk_ctx *ac); +void apk_ctx_free(struct apk_ctx *ac); + +#endif diff --git a/src/apk_database.h b/src/apk_database.h index 20d9169..e43f7ae 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -16,32 +16,13 @@ #include "apk_archive.h" #include "apk_package.h" #include "apk_io.h" -#include "apk_print.h" +#include "apk_context.h" #include "apk_provider_data.h" #include "apk_solver_data.h" #include "adb.h" -#define APK_SIMULATE BIT(0) -#define APK_CLEAN_PROTECTED BIT(1) -#define APK_RECURSIVE BIT(2) -#define APK_ALLOW_UNTRUSTED BIT(3) -#define APK_PURGE BIT(4) -#define APK_INTERACTIVE BIT(5) -#define APK_NO_NETWORK BIT(6) -#define APK_OVERLAY_FROM_STDIN BIT(7) -#define APK_NO_SCRIPTS BIT(8) -#define APK_NO_CACHE BIT(9) -#define APK_NO_COMMIT_HOOKS BIT(10) - -#define APK_FORCE_OVERWRITE BIT(0) -#define APK_FORCE_OLD_APK BIT(1) -#define APK_FORCE_BROKEN_WORLD BIT(2) -#define APK_FORCE_REFRESH BIT(3) -#define APK_FORCE_NON_REPOSITORY BIT(4) -#define APK_FORCE_BINARY_STDOUT BIT(5) - struct apk_name; APK_ARRAY(apk_name_array, struct apk_name *); @@ -137,20 +118,6 @@ struct apk_repository { apk_blob_t description; }; -struct apk_db_options { - unsigned int flags, force, lock_wait; - struct apk_progress progress; - unsigned int cache_max_age; - unsigned long open_flags; - const char *root; - const char *arch; - const char *keys_dir; - const char *cache_dir; - const char *repositories_file; - struct apk_string_array *repository_list; - struct apk_string_array *private_keys; -}; - #define APK_REPOSITORY_CACHED 0 #define APK_REPOSITORY_FIRST_CONFIGURED 1 @@ -163,16 +130,14 @@ struct apk_repository_tag { }; struct apk_database { - unsigned int flags, force; - struct apk_progress progress; - char *root; + struct apk_ctx *ctx; int root_fd, lock_fd, cache_fd, keys_fd; unsigned num_repos, num_repo_tags; const char *cache_dir; char *cache_remount_dir, *root_proc_dir; unsigned long cache_remount_flags; apk_blob_t *arch; - unsigned int local_repos, available_repos, cache_max_age; + unsigned int local_repos, available_repos; unsigned int repo_update_errors, repo_update_counter; unsigned int pending_triggers; unsigned int extract_flags; @@ -245,7 +210,7 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db, APK_OPENF_NO_WORLD) void apk_db_init(struct apk_database *db); -int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts); +int apk_db_open(struct apk_database *db, struct apk_ctx *ctx); void apk_db_close(struct apk_database *db); int apk_db_write_config(struct apk_database *db); int apk_db_permanent(struct apk_database *db); @@ -254,7 +219,7 @@ int apk_db_fire_triggers(struct apk_database *db); int apk_db_run_script(struct apk_database *db, char *fn, char **argv); void apk_db_update_directory_permissions(struct apk_database *db); static inline time_t apk_db_url_since(struct apk_database *db, time_t since) { - return (db->force & APK_FORCE_REFRESH) ? APK_ISTREAM_FORCE_REFRESH : since; + return (db->ctx->force & APK_FORCE_REFRESH) ? APK_ISTREAM_FORCE_REFRESH : since; } struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg); diff --git a/src/apk_defines.h b/src/apk_defines.h index 7445e03..1bc8db0 100644 --- a/src/apk_defines.h +++ b/src/apk_defines.h @@ -68,9 +68,6 @@ static inline int IS_ERR_OR_NULL(const void *ptr) { return IS_ERR(ptr) || !ptr; #define ROUND_DOWN(x,a) ((x) & ~(a-1)) #define ROUND_UP(x,a) (((x)+(a)-1) & ~((a)-1)) -extern int apk_verbosity; -extern char **apk_argv; - /* default architecture for APK packages. */ #if defined(__x86_64__) #define APK_DEFAULT_ARCH "x86_64" diff --git a/src/apk_io.h b/src/apk_io.h index 2e70b53..adec003 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -147,7 +147,7 @@ struct apk_ostream *apk_ostream_to_fd(int fd); struct apk_ostream *apk_ostream_to_file(int atfd, const char *file, mode_t mode); struct apk_ostream *apk_ostream_to_file_gz(int atfd, const char *file, const char *tmpfile, mode_t mode); size_t apk_ostream_write_string(struct apk_ostream *ostream, const char *string); -static inline void apk_ostream_cancel(struct apk_ostream *os, int rc) { if (!os->rc) os->rc = rc; } +static inline int apk_ostream_cancel(struct apk_ostream *os, int rc) { if (!os->rc) os->rc = rc; return rc; } static inline ssize_t apk_ostream_write(struct apk_ostream *os, const void *buf, size_t size) { return os->ops->write(os, buf, size); diff --git a/src/apk_print.h b/src/apk_print.h index 0d001d8..ec766ed 100644 --- a/src/apk_print.h +++ b/src/apk_print.h @@ -12,6 +12,9 @@ #include "apk_blob.h" +const char *apk_error_str(int error); +const char *apk_get_human_size(off_t size, off_t *dest); + struct apk_url_print { const char *url; const char *pwmask; @@ -24,22 +27,28 @@ void apk_url_parse(struct apk_url_print *, const char *); #define URL_FMT "%.*s%s%s" #define URL_PRINTF(u) u.len_before_pw, u.url, u.pwmask, u.url_or_host -#define apk_error(args...) do { apk_log_err("ERROR: ", args); } while (0) -#define apk_warning(args...) do { if (apk_verbosity > 0) { apk_log_err("WARNING: ", args); } } while (0) -#define apk_message(args...) do { if (apk_verbosity > 0) { apk_log(NULL, args); } } while (0) +struct apk_out { + int verbosity; + unsigned int width, last_change; + FILE *out, *err; +}; -void apk_log(const char *prefix, const char *format, ...); -void apk_log_err(const char *prefix, const char *format, ...); -const char *apk_error_str(int error); +static inline int apk_out_verbosity(struct apk_out *out) { return out->verbosity; } -void apk_reset_screen_width(void); -int apk_get_screen_width(void); -const char *apk_get_human_size(off_t size, off_t *dest); +#define apk_err(out, args...) do { apk_out_fmt(out, "ERROR: ", args); } while (0) +#define apk_out(out, args...) do { apk_out_fmt(out, NULL, args); } while (0) +#define apk_warn(out, args...) do { if (apk_out_verbosity(out) >= 0) { apk_out_fmt(out, "WARNING: ", args); } } while (0) +#define apk_msg(out, args...) do { if (apk_out_verbosity(out) >= 1) { apk_out_fmt(out, NULL, args); } } while (0) +#define apk_dbg(out, args...) do { if (apk_out_verbosity(out) >= 2) { apk_out_fmt(out, NULL, args); } } while (0) +#define apk_dbg2(out, args...) do { if (apk_out_verbosity(out) >= 3) { apk_out_fmt(out, NULL, args); } } while (0) + +void apk_out_reset(struct apk_out *); +void apk_out_fmt(struct apk_out *, const char *prefix, const char *format, ...); struct apk_progress { - int fd; - FILE *out; - int last_bar, last_percent; + struct apk_out *out; + int fd, last_bar, last_percent; + unsigned int last_out_change; size_t last_done; const char *progress_char; }; @@ -47,8 +56,8 @@ struct apk_progress { void apk_print_progress(struct apk_progress *p, size_t done, size_t total); struct apk_indent { - int x; - int indent; + struct apk_out *out; + int x, indent; }; int apk_print_indented(struct apk_indent *i, apk_blob_t blob); diff --git a/src/app_adbdump.c b/src/app_adbdump.c index 6e42a55..75cf048 100644 --- a/src/app_adbdump.c +++ b/src/app_adbdump.c @@ -223,13 +223,14 @@ static int mmap_and_dump_adb(struct adb_trust *trust, int fd) static int adbdump_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; char **arg; int r; foreach_array_item(arg, args) { r = mmap_and_dump_adb(&db->trust, open(*arg, O_RDONLY)); if (r) { - apk_error("%s: %s", *arg, apk_error_str(r)); + apk_err(out, "%s: %s", *arg, apk_error_str(r)); return r; } } diff --git a/src/app_adbsign.c b/src/app_adbsign.c index 918948f..ddcf0c1 100644 --- a/src/app_adbsign.c +++ b/src/app_adbsign.c @@ -19,7 +19,7 @@ struct sign_ctx { APK_OPT_APPLET(option_desc, ADBSIGN_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int optch, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int optch, const char *optarg) { struct sign_ctx *ctx = (struct sign_ctx *) pctx; @@ -64,6 +64,7 @@ static int update_signatures(struct adb_xfrm *xfrm, struct adb_block *blk, struc static int adbsign_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct sign_ctx *ctx = pctx; char **arg; int r; @@ -75,7 +76,7 @@ static int adbsign_main(void *pctx, struct apk_database *db, struct apk_string_a adb_c_xfrm(&ctx->xfrm, update_signatures); apk_istream_close(ctx->xfrm.is); r = apk_ostream_close(ctx->xfrm.os); - if (r) apk_error("%s: %s", *arg, apk_error_str(r)); + if (r) apk_err(out, "%s: %s", *arg, apk_error_str(r)); } return 0; diff --git a/src/app_add.c b/src/app_add.c index 93b376c..1eedcc6 100644 --- a/src/app_add.c +++ b/src/app_add.c @@ -30,13 +30,13 @@ struct add_ctx { APK_OPT_APPLET(option_desc, ADD_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct add_ctx *actx = (struct add_ctx *) ctx; switch (opt) { case OPT_ADD_initdb: - dbopts->open_flags |= APK_OPENF_CREATE; + ac->open_flags |= APK_OPENF_CREATE; break; case OPT_ADD_latest: actx->solver_flags |= APK_SOLVERF_LATEST; @@ -63,17 +63,18 @@ static const struct apk_option_group optgroup_applet = { static int non_repository_check(struct apk_database *db) { - if (db->force & APK_FORCE_NON_REPOSITORY) + if (db->ctx->force & APK_FORCE_NON_REPOSITORY) return 0; if (apk_db_cache_active(db)) return 0; if (apk_db_permanent(db)) return 0; - apk_error("You tried to add a non-repository package to system, " - "but it would be lost on next reboot. Enable package caching " - "(apk cache --help) or use --force-non-repository " - "if you know what you are doing."); + apk_err(&db->ctx->out, + "You tried to add a non-repository package to system, " + "but it would be lost on next reboot. Enable package caching " + "(apk cache --help) or use --force-non-repository " + "if you know what you are doing."); return 1; } @@ -111,6 +112,7 @@ static struct apk_package *create_virtual_package(struct apk_database *db, struc static int add_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct add_ctx *actx = (struct add_ctx *) ctx; struct apk_package *virtpkg = NULL; struct apk_dependency virtdep; @@ -129,7 +131,7 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array if (APK_BLOB_IS_NULL(b) || virtdep.conflict || virtdep.result_mask != APK_DEPMASK_ANY || virtdep.version != &apk_atom_null) { - apk_error("%s: bad package specifier"); + apk_err(out, "%s: bad package specifier"); return -1; } if (virtdep.name->name[0] != '.' && non_repository_check(db)) @@ -137,7 +139,7 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array virtpkg = create_virtual_package(db, virtdep.name); if (!virtpkg) { - apk_error("Failed to allocate virtual meta package"); + apk_err(out, "Failed to allocate virtual meta package"); return -1; } @@ -156,11 +158,11 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array return -1; apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY_AND_GENERATE, - NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_pkg_read(db, *parg, &sctx, &pkg); apk_sign_ctx_free(&sctx); if (r != 0) { - apk_error("%s: %s", *parg, apk_error_str(r)); + apk_err(out, "%s: %s", *parg, apk_error_str(r)); return -1; } apk_dep_from_pkg(&dep, db, pkg); @@ -169,9 +171,9 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array apk_blob_pull_dep(&b, db, &dep); if (APK_BLOB_IS_NULL(b) || b.len > 0 || (virtpkg != NULL && dep.repository_tag)) { - apk_error("'%s' is not a valid %s dependency, format is %s", - *parg, virtpkg == NULL ? "world" : "child", - virtpkg == NULL ? "name(@tag)([<>~=]version)" : "name([<>~=]version)"); + apk_err(out, "'%s' is not a valid %s dependency, format is %s", + *parg, virtpkg == NULL ? "world" : "child", + virtpkg == NULL ? "name(@tag)([<>~=]version)" : "name([<>~=]version)"); return -1; } } diff --git a/src/app_audit.c b/src/app_audit.c index 9b410c5..acfca13 100644 --- a/src/app_audit.c +++ b/src/app_audit.c @@ -29,6 +29,7 @@ enum { }; struct audit_ctx { + int verbosity; unsigned mode : 1; unsigned recursive : 1; unsigned check_permissions : 1; @@ -44,9 +45,9 @@ struct audit_ctx { APK_OPT_APPLET(option_desc, AUDIT_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *applet_ctx, struct apk_ctx *ac, int opt, const char *optarg) { - struct audit_ctx *actx = (struct audit_ctx *) ctx; + struct audit_ctx *actx = (struct audit_ctx *) applet_ctx; switch (opt) { case OPT_AUDIT_backup: @@ -146,18 +147,19 @@ static int audit_directory(struct audit_ctx *actx, static void report_audit(struct audit_ctx *actx, char reason, apk_blob_t bfull, struct apk_package *pkg) { - if (!reason) - return; + int verbosity = actx->verbosity; + + if (!reason) return; if (actx->packages_only) { if (pkg == NULL || pkg->state_int != 0) return; pkg->state_int = 1; - if (apk_verbosity < 1) + if (verbosity < 1) printf("%s\n", pkg->name->name); else printf(PKG_VER_FMT "\n", PKG_VER_PRINTF(pkg)); - } else if (apk_verbosity < 1) { + } else if (verbosity < 1) { printf(BLOB_FMT "\n", BLOB_PRINTF(bfull)); } else printf("%c " BLOB_FMT "\n", reason, BLOB_PRINTF(bfull)); @@ -307,11 +309,13 @@ static int audit_missing_files(apk_hash_item item, void *pctx) static int audit_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct audit_tree_ctx atctx; struct audit_ctx *actx = (struct audit_ctx *) ctx; char **parg, *arg; int r = 0; + actx->verbosity = apk_out_verbosity(&db->ctx->out); atctx.db = db; atctx.actx = actx; atctx.pathlen = 0; @@ -323,7 +327,7 @@ static int audit_main(void *ctx, struct apk_database *db, struct apk_string_arra foreach_array_item(parg, args) { arg = *parg; if (arg[0] != '/') { - apk_warning("%s: relative path skipped.\n", arg); + apk_warn(out, "%s: relative path skipped.\n", arg); continue; } arg++; diff --git a/src/app_cache.c b/src/app_cache.c index 826ac1f..974690c 100644 --- a/src/app_cache.c +++ b/src/app_cache.c @@ -34,7 +34,7 @@ struct cache_ctx { APK_OPT_APPLET(option_desc, CACHE_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct cache_ctx *cctx = (struct cache_ctx *) ctx; @@ -69,16 +69,17 @@ static void progress_cb(void *ctx, size_t bytes_done) static int cache_download(struct cache_ctx *cctx, struct apk_database *db) { + struct apk_out *out = &db->ctx->out; struct apk_changeset changeset = {}; struct apk_change *change; struct apk_package *pkg; struct apk_repository *repo; - struct progress prog = { .prog = db->progress }; + struct progress prog = { .prog = db->ctx->progress }; int r, ret = 0; r = apk_solver_solve(db, cctx->solver_flags, db->world, &changeset); if (r < 0) { - apk_error("Unable to select packages. Run apk fix."); + apk_err(out, "Unable to select packages. Run apk fix."); return r; } @@ -100,7 +101,7 @@ static int cache_download(struct cache_ctx *cctx, struct apk_database *db) r = apk_cache_download(db, repo, pkg, APK_SIGN_VERIFY_IDENTITY, 0, progress_cb, &prog); if (r && r != -EALREADY) { - apk_error(PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); + apk_err(out, PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); ret++; } prog.done += pkg->size; @@ -111,6 +112,7 @@ static int cache_download(struct cache_ctx *cctx, struct apk_database *db) static void cache_clean_item(struct apk_database *db, int dirfd, const char *name, struct apk_package *pkg) { + struct apk_out *out = &db->ctx->out; char tmp[PATH_MAX]; apk_blob_t b; int i; @@ -118,7 +120,7 @@ static void cache_clean_item(struct apk_database *db, int dirfd, const char *nam if (strcmp(name, "installed") == 0) return; if (pkg) { - if ((db->flags & APK_PURGE) && pkg->ipkg == NULL) goto delete; + if ((db->ctx->flags & APK_PURGE) && pkg->ipkg == NULL) goto delete; if (pkg->repos & db->local_repos & ~BIT(APK_REPOSITORY_CACHED)) goto delete; if (pkg->ipkg == NULL && !(pkg->repos & ~BIT(APK_REPOSITORY_CACHED))) goto delete; return; @@ -132,9 +134,8 @@ static void cache_clean_item(struct apk_database *db, int dirfd, const char *nam } delete: - if (apk_verbosity >= 2) - apk_message("deleting %s", name); - if (!(db->flags & APK_SIMULATE)) { + apk_dbg(out, "deleting %s", name); + if (!(db->ctx->flags & APK_SIMULATE)) { if (unlinkat(dirfd, name, 0) < 0 && errno == EISDIR) unlinkat(dirfd, name, AT_REMOVEDIR); } @@ -147,6 +148,7 @@ static int cache_clean(struct apk_database *db) static int cache_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct cache_ctx *cctx = (struct cache_ctx *) ctx; char *arg; int r = 0, actions = 0; @@ -165,7 +167,7 @@ static int cache_main(void *ctx, struct apk_database *db, struct apk_string_arra return -EINVAL; if (!apk_db_cache_active(db)) { - apk_error("Package cache is not enabled.\n"); + apk_err(out, "Package cache is not enabled.\n"); r = 2; goto err; } diff --git a/src/app_convndx.c b/src/app_convndx.c index 924a1f6..393ca43 100644 --- a/src/app_convndx.c +++ b/src/app_convndx.c @@ -57,7 +57,7 @@ static int load_index(struct conv_ctx *ctx, struct apk_istream *is) if (IS_ERR_OR_NULL(is)) return is ? PTR_ERR(is) : -EINVAL; ctx->found = 0; - apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, ctx->db->keys_fd, ctx->db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, ctx->db->keys_fd, ctx->db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_tar_parse( apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx->sctx), load_apkindex, ctx, &ctx->db->id_cache); diff --git a/src/app_del.c b/src/app_del.c index aa7ab4f..390a99a 100644 --- a/src/app_del.c +++ b/src/app_del.c @@ -24,7 +24,7 @@ struct del_ctx { APK_OPT_APPLET(option_desc, DEL_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int opt, const char *optarg) { struct del_ctx *ctx = (struct del_ctx *) pctx; @@ -44,6 +44,7 @@ static const struct apk_option_group optgroup_applet = { }; struct not_deleted_ctx { + struct apk_out *out; struct apk_indent indent; struct apk_name *name; unsigned int matches; @@ -54,12 +55,13 @@ static void print_not_deleted_pkg(struct apk_package *pkg0, struct apk_dependenc struct apk_package *pkg, void *pctx) { struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; + struct apk_out *out = ctx->out; struct apk_dependency *d; struct apk_provider *p; if (pkg0->name != ctx->name) { if (!ctx->header) { - apk_message("World updated, but the following packages are not removed due to:"); + apk_msg(out, "World updated, but the following packages are not removed due to:"); ctx->header = 1; } if (!ctx->indent.indent) { @@ -83,10 +85,11 @@ static void print_not_deleted_pkg(struct apk_package *pkg0, struct apk_dependenc static void print_not_deleted_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { + struct apk_out *out = &db->ctx->out; struct not_deleted_ctx *ctx = (struct not_deleted_ctx *) pctx; struct apk_provider *p; - ctx->indent.indent = 0; + ctx->indent = (struct apk_indent) { .out = out }; ctx->name = name; ctx->matches = apk_foreach_genid() | APK_FOREACH_MARKED | APK_DEP_SATISFIES; foreach_array_item(p, name->providers) @@ -111,11 +114,12 @@ static void delete_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, static void delete_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { + struct apk_out *out = &db->ctx->out; struct del_ctx *ctx = (struct del_ctx *) pctx; struct apk_package *pkg; if (!name) { - apk_error("No such package: %s", match); + apk_err(out, "No such package: %s", match); ctx->errors++; return; } @@ -130,7 +134,7 @@ static void delete_name(struct apk_database *db, const char *match, static int del_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { struct del_ctx *ctx = (struct del_ctx *) pctx; - struct not_deleted_ctx ndctx = {}; + struct not_deleted_ctx ndctx = { .out = &db->ctx->out }; struct apk_changeset changeset = {}; struct apk_change *change; int r = 0; diff --git a/src/app_dot.c b/src/app_dot.c index ad9167c..15283fd 100644 --- a/src/app_dot.c +++ b/src/app_dot.c @@ -28,7 +28,7 @@ struct dot_ctx { APK_OPT_APPLET(option_desc, DOT_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int opt, const char *optarg) { struct dot_ctx *ctx = (struct dot_ctx *) pctx; @@ -38,7 +38,7 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op break; case OPT_DOT_installed: ctx->installed_only = 1; - dbopts->open_flags &= ~APK_OPENF_NO_INSTALLED; + ac->open_flags &= ~APK_OPENF_NO_INSTALLED; break; default: return -ENOTSUP; diff --git a/src/app_fetch.c b/src/app_fetch.c index c1498e7..9a4faab 100644 --- a/src/app_fetch.c +++ b/src/app_fetch.c @@ -76,13 +76,13 @@ static int cup(void) APK_OPT_APPLET(option_desc, FETCH_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct fetch_ctx *fctx = (struct fetch_ctx *) ctx; switch (opt) { case OPT_FETCH_simulate: - dbopts->flags |= APK_SIMULATE; + ac->flags |= APK_SIMULATE; break; case OPT_FETCH_recursive: fctx->flags |= FETCH_RECURSIVE; @@ -117,6 +117,7 @@ static int fetch_package(apk_hash_item item, void *pctx) { struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; struct apk_database *db = ctx->db; + struct apk_out *out = &db->ctx->out; struct apk_package *pkg = (struct apk_package *) item; struct apk_istream *is; struct apk_repository *repo; @@ -144,8 +145,8 @@ static int fetch_package(apk_hash_item item, void *pctx) return 0; } - apk_message("Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg)); - if (db->flags & APK_SIMULATE) + apk_msg(out, "Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg)); + if (db->ctx->flags & APK_SIMULATE) return 0; r = apk_repo_format_item(db, repo, pkg, &urlfd, url, sizeof(url)); @@ -194,7 +195,7 @@ static int fetch_package(apk_hash_item item, void *pctx) return 0; err: - apk_error(PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); + apk_err(out, PKG_VER_FMT ": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); ctx->errors++; return 0; } @@ -209,10 +210,12 @@ static void mark_package(struct fetch_ctx *ctx, struct apk_package *pkg) static void mark_error(struct fetch_ctx *ctx, const char *match, struct apk_name *name) { + struct apk_out *out = &ctx->db->ctx->out; + if (strchr(match, '*') != NULL) return; - apk_message("%s: unable to select package (or its dependencies)", name ? name->name : match); + apk_msg(out, "%s: unable to select package (or its dependencies)", name ? name->name : match); ctx->errors++; } @@ -276,6 +279,7 @@ static int purge_package(void *pctx, int dirfd, const char *filename) char tmp[PATH_MAX]; struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; struct apk_database *db = ctx->db; + struct apk_out *out = &db->ctx->out; struct apk_provider *p0; struct apk_name *name; apk_blob_t b = APK_BLOB_STR(filename), bname, bver; @@ -294,8 +298,8 @@ static int purge_package(void *pctx, int dirfd, const char *filename) break; } - apk_message("Purging %s", filename); - if (db->flags & APK_SIMULATE) + apk_msg(out, "Purging %s", filename); + if (db->ctx->flags & APK_SIMULATE) return 0; unlinkat(dirfd, filename, 0); @@ -304,21 +308,22 @@ static int purge_package(void *pctx, int dirfd, const char *filename) static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct fetch_ctx *ctx = (struct fetch_ctx *) pctx; ctx->db = db; - ctx->prog = db->progress; + ctx->prog = db->ctx->progress; if (ctx->flags & FETCH_STDOUT) { - ctx->prog.out = 0; - apk_verbosity = 0; + db->ctx->progress.out = 0; + db->ctx->out.verbosity = 0; } if (ctx->outdir_fd == 0) ctx->outdir_fd = AT_FDCWD; if ((args->num == 1) && (strcmp(args->item[0], "coffee") == 0)) { - if (db->force) return cup(); - apk_message("Go and fetch your own coffee."); + if (db->ctx->force) return cup(); + apk_msg(out, "Go and fetch your own coffee."); return 0; } @@ -335,7 +340,7 @@ static int fetch_main(void *pctx, struct apk_database *db, struct apk_string_arr apk_hash_foreach(&db->available.packages, fetch_package, ctx); /* Remove packages not matching download spec from the output directory */ - if (!ctx->errors && (db->flags & APK_PURGE) && + if (!ctx->errors && (db->ctx->flags & APK_PURGE) && !(ctx->flags & FETCH_STDOUT) && ctx->outdir_fd > 0) apk_dir_foreach_file(ctx->outdir_fd, purge_package, ctx); diff --git a/src/app_fix.c b/src/app_fix.c index ccd1e3c..311cfdd 100644 --- a/src/app_fix.c +++ b/src/app_fix.c @@ -31,7 +31,7 @@ struct fix_ctx { APK_OPT_APPLET(option_desc, FIX_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int opt, const char *optarg) { struct fix_ctx *ctx = (struct fix_ctx *) pctx; switch (opt) { @@ -76,10 +76,11 @@ static void mark_fix(struct fix_ctx *ctx, struct apk_name *name) static void set_solver_flags(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { + struct apk_out *out = &db->ctx->out; struct fix_ctx *ctx = pctx; if (!name) { - apk_error("Package '%s' not found", match); + apk_err(out, "Package '%s' not found", match); ctx->errors++; } else mark_fix(ctx, name); diff --git a/src/app_index.c b/src/app_index.c index 2a0a912..707bd94 100644 --- a/src/app_index.c +++ b/src/app_index.c @@ -20,6 +20,7 @@ #define APK_INDEXF_NO_WARNINGS 0x0001 struct counts { + struct apk_out *out; int unsatisfied; }; @@ -42,7 +43,7 @@ struct index_ctx { APK_OPT_APPLET(option_desc, INDEX_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct index_ctx *ictx = (struct index_ctx *) ctx; @@ -90,16 +91,15 @@ static int warn_if_no_providers(apk_hash_item item, void *ctx) { struct counts *counts = (struct counts *) ctx; struct apk_name *name = (struct apk_name *) item; + struct apk_out *out = counts->out; if (!name->is_dependency) return 0; if (name->providers->num) return 0; if (++counts->unsatisfied < 10) { - apk_warning("No provider for dependency '%s'", - name->name); + apk_warn(out, "No provider for dependency '%s'", name->name); } else if (counts->unsatisfied == 10) { - apk_warning("Too many unsatisfiable dependencies, " - "not reporting the rest."); + apk_warn(out, "Too many unsatisfiable dependencies, not reporting the rest."); } return 0; @@ -107,7 +107,8 @@ static int warn_if_no_providers(apk_hash_item item, void *ctx) static int index_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { - struct counts counts = {0}; + struct apk_out *out = &db->ctx->out; + struct counts counts = { .out = out }; struct apk_ostream *os; struct apk_file_info fi; int total, r, found, newpkgs = 0, errors = 0; @@ -117,9 +118,10 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra apk_blob_t *rewrite_arch = NULL; if (isatty(STDOUT_FILENO) && ictx->output == NULL && - !(db->force & APK_FORCE_BINARY_STDOUT)) { - apk_error("Will not write binary index to console. " - "Use --force-binary-stdout to override."); + !(db->ctx->force & APK_FORCE_BINARY_STDOUT)) { + apk_err(out, + "Will not write binary index to console. " + "Use --force-binary-stdout to override."); return -1; } @@ -127,7 +129,7 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra ictx->method = APK_SIGN_GENERATE; if ((r = index_read_file(db, ictx)) < 0) { - apk_error("%s: %s", ictx->index, apk_error_str(r)); + apk_err(out, "%s: %s", ictx->index, apk_error_str(r)); return r; } @@ -136,7 +138,7 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra foreach_array_item(parg, args) { if (apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi, &db->atoms) < 0) { - apk_warning("File '%s' is unaccessible", *parg); + apk_warn(out, "File '%s' is unaccessible", *parg); continue; } @@ -183,10 +185,10 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra if (!found) { struct apk_sign_ctx sctx; - apk_sign_ctx_init(&sctx, ictx->method, NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&sctx, ictx->method, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_pkg_read(db, *parg, &sctx, &pkg); if (r < 0) { - apk_error("%s: %s", *parg, apk_error_str(r)); + apk_err(out, "%s: %s", *parg, apk_error_str(r)); errors++; } else { newpkgs++; @@ -237,7 +239,7 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra apk_ostream_close(os); if (r < 0) { - apk_error("Index generation failed: %s", apk_error_str(r)); + apk_err(out, "Index generation failed: %s", apk_error_str(r)); return r; } @@ -247,11 +249,11 @@ static int index_main(void *ctx, struct apk_database *db, struct apk_string_arra } if (counts.unsatisfied != 0) - apk_warning("Total of %d unsatisfiable package " - "names. Your repository may be broken.", - counts.unsatisfied); - apk_message("Index has %d packages (of which %d are new)", - total, newpkgs); + apk_warn(out, + "Total of %d unsatisfiable package names. Your repository may be broken.", + counts.unsatisfied); + apk_msg(out, "Index has %d packages (of which %d are new)", + total, newpkgs); return 0; } diff --git a/src/app_info.c b/src/app_info.c index 8454f0f..8f02f30 100644 --- a/src/app_info.c +++ b/src/app_info.c @@ -23,6 +23,8 @@ struct info_ctx { int errors; }; +static int verbosity = 0; + /* These need to stay in sync with the function pointer array in * info_subaction() */ #define APK_INFO_DESC 0x01 @@ -40,18 +42,11 @@ struct info_ctx { static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity) { - int verbosity = apk_verbosity; - if (verbosity < minimal_verbosity) - verbosity = minimal_verbosity; - - if (pkg == NULL || verbosity < 1) - return; - + int v = min(verbosity, minimal_verbosity); + if (pkg == NULL || v < 1) return; printf("%s", pkg->name->name); - if (apk_verbosity > 1) - printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); - if (apk_verbosity > 2) - printf(" - %s", pkg->description); + if (v > 1) printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); + if (v > 2) printf(" - %s", pkg->description); printf("\n"); } @@ -89,6 +84,7 @@ static void info_exists(struct info_ctx *ctx, struct apk_database *db, static void info_who_owns(struct info_ctx *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct apk_package *pkg; struct apk_dependency_array *deps; struct apk_dependency dep; @@ -116,13 +112,13 @@ static void info_who_owns(struct info_ctx *ctx, struct apk_database *db, } if (pkg == NULL) { - apk_error(BLOB_FMT ": Could not find owner package", - BLOB_PRINTF(fn)); + apk_err(out, BLOB_FMT ": Could not find owner package", + BLOB_PRINTF(fn)); ctx->errors++; continue; } - if (apk_verbosity < 1) { + if (verbosity < 1) { dep = (struct apk_dependency) { .name = pkg->name, .version = &apk_atom_null, @@ -134,7 +130,7 @@ static void info_who_owns(struct info_ctx *ctx, struct apk_database *db, BLOB_PRINTF(fn), via, PKG_VER_PRINTF(pkg)); } } - if (apk_verbosity < 1 && deps->num != 0) { + if (verbosity < 1 && deps->num != 0) { os = apk_ostream_to_fd(STDOUT_FILENO); if (!IS_ERR_OR_NULL(os)) { apk_deps_write(db, deps, os, APK_BLOB_PTR_LEN(" ", 1)); @@ -147,7 +143,7 @@ static void info_who_owns(struct info_ctx *ctx, struct apk_database *db, static void info_print_description(struct apk_database *db, struct apk_package *pkg) { - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: %s", pkg->name->name, pkg->description); else printf(PKG_VER_FMT " description:\n%s\n", @@ -157,7 +153,7 @@ static void info_print_description(struct apk_database *db, struct apk_package * static void info_print_url(struct apk_database *db, struct apk_package *pkg) { - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: %s", pkg->name->name, pkg->url); else printf(PKG_VER_FMT " webpage:\n%s\n", @@ -167,7 +163,7 @@ static void info_print_url(struct apk_database *db, struct apk_package *pkg) static void info_print_license(struct apk_database *db, struct apk_package *pkg) { - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: " BLOB_FMT , pkg->name->name, BLOB_PRINTF(*pkg->license)); else printf(PKG_VER_FMT " license:\n" BLOB_FMT "\n", @@ -181,7 +177,7 @@ static void info_print_size(struct apk_database *db, struct apk_package *pkg) const char *size_unit; size_unit = apk_get_human_size(pkg->installed_size, &size); - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: %lld %s", pkg->name->name, (long long)size, size_unit); else @@ -193,12 +189,12 @@ static void info_print_dep_array(struct apk_database *db, struct apk_package *pk struct apk_dependency_array *deps, const char *dep_text) { struct apk_dependency *d; - apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n"); + apk_blob_t separator = APK_BLOB_STR(verbosity > 1 ? " " : "\n"); char buf[256]; - if (apk_verbosity == 1) + if (verbosity == 1) printf(PKG_VER_FMT " %s:\n", PKG_VER_PRINTF(pkg), dep_text); - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: ", pkg->name->name); foreach_array_item(d, deps) { apk_blob_t b = APK_BLOB_BUF(buf); @@ -221,14 +217,14 @@ static void info_print_provides(struct apk_database *db, struct apk_package *pkg static void print_rdep_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *pctx) { - printf(PKG_VER_FMT "%s", PKG_VER_PRINTF(pkg0), apk_verbosity > 1 ? " " : "\n"); + printf(PKG_VER_FMT "%s", PKG_VER_PRINTF(pkg0), verbosity > 1 ? " " : "\n"); } static void info_print_required_by(struct apk_database *db, struct apk_package *pkg) { - if (apk_verbosity == 1) + if (verbosity == 1) printf(PKG_VER_FMT " is required by:\n", PKG_VER_PRINTF(pkg)); - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: ", pkg->name->name); apk_pkg_foreach_reverse_dependency( pkg, @@ -244,12 +240,12 @@ static void info_print_install_if(struct apk_database *db, struct apk_package *p static void info_print_rinstall_if(struct apk_database *db, struct apk_package *pkg) { int i, j; - char *separator = apk_verbosity > 1 ? " " : "\n"; + char *separator = verbosity > 1 ? " " : "\n"; - if (apk_verbosity == 1) + if (verbosity == 1) printf(PKG_VER_FMT " affects auto-installation of:\n", PKG_VER_PRINTF(pkg)); - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: ", pkg->name->name); for (i = 0; i < pkg->name->rinstall_if->num; i++) { struct apk_name *name0; @@ -280,7 +276,7 @@ static void info_print_contents(struct apk_database *db, struct apk_package *pkg struct apk_db_file *file; struct hlist_node *dc, *dn, *fc, *fn; - if (apk_verbosity == 1) + if (verbosity == 1) printf(PKG_VER_FMT " contains:\n", PKG_VER_PRINTF(pkg)); @@ -288,7 +284,7 @@ static void info_print_contents(struct apk_database *db, struct apk_package *pkg pkg_dirs_list) { hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) { - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: ", pkg->name->name); printf(DIR_FILE_FMT "\n", DIR_FILE_PRINTF(diri->dir, file)); } @@ -300,12 +296,12 @@ static void info_print_triggers(struct apk_database *db, struct apk_package *pkg struct apk_installed_package *ipkg = pkg->ipkg; char **trigger; - if (apk_verbosity == 1) + if (verbosity == 1) printf(PKG_VER_FMT " triggers:\n", PKG_VER_PRINTF(pkg)); foreach_array_item(trigger, ipkg->triggers) { - if (apk_verbosity > 1) + if (verbosity > 1) printf("%s: trigger ", pkg->name->name); printf("%s\n", *trigger); } @@ -383,7 +379,7 @@ static void print_name_info(struct apk_database *db, const char *match, struct a APK_OPT_APPLET(option_desc, INFO_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int opt, const char *optarg) { struct info_ctx *ctx = (struct info_ctx *) pctx; @@ -391,11 +387,11 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op switch (opt) { case OPT_INFO_installed: ctx->action = info_exists; - dbopts->open_flags |= APK_OPENF_NO_REPOS; + ac->open_flags |= APK_OPENF_NO_REPOS; break; case OPT_INFO_who_owns: ctx->action = info_who_owns; - dbopts->open_flags |= APK_OPENF_NO_REPOS; + ac->open_flags |= APK_OPENF_NO_REPOS; break; case OPT_INFO_webpage: ctx->subaction_mask |= APK_INFO_URL; @@ -447,6 +443,7 @@ static int info_main(void *ctx, struct apk_database *db, struct apk_string_array struct info_ctx *ictx = (struct info_ctx *) ctx; struct apk_installed_package *ipkg; + verbosity = apk_out_verbosity(&db->ctx->out); ictx->db = db; if (ictx->subaction_mask == 0) ictx->subaction_mask = APK_INFO_DESC | APK_INFO_URL | APK_INFO_SIZE; diff --git a/src/app_list.c b/src/app_list.c index 5606df0..a7e05b8 100644 --- a/src/app_list.c +++ b/src/app_list.c @@ -18,6 +18,7 @@ #include "apk_print.h" struct list_ctx { + int verbosity; unsigned int installed : 1; unsigned int orphaned : 1; unsigned int available : 1; @@ -36,8 +37,7 @@ static int origin_matches(const struct list_ctx *ctx, const struct apk_package * if (pkg->origin == NULL) return 0; - foreach_array_item(pmatch, ctx->filters) - { + foreach_array_item(pmatch, ctx->filters) { if (apk_blob_compare(APK_BLOB_STR(*pmatch), *pkg->origin) == 0) return 1; } @@ -103,8 +103,7 @@ static void print_package(const struct apk_package *pkg, const struct list_ctx * if (pkg->ipkg) printf(" [installed]"); - else - { + else { const struct apk_package *u; u = is_upgradable(pkg->name, pkg); @@ -113,10 +112,9 @@ static void print_package(const struct apk_package *pkg, const struct list_ctx * } - if (apk_verbosity > 1) - { + if (ctx->verbosity > 1) { printf("\n %s\n", pkg->description); - if (apk_verbosity > 2) + if (ctx->verbosity > 2) printf(" <%s>\n", pkg->url); } @@ -147,8 +145,7 @@ static void iterate_providers(const struct apk_name *name, const struct list_ctx { struct apk_provider *p; - foreach_array_item(p, name->providers) - { + foreach_array_item(p, name->providers) { if (!ctx->match_providers && p->pkg->name != name) continue; @@ -162,19 +159,17 @@ static void iterate_providers(const struct apk_name *name, const struct list_ctx static void print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { struct list_ctx *ctx = pctx; + struct apk_name **pname; if (name == NULL) return; - if (ctx->match_depends) - { - struct apk_name **pname; - + if (ctx->match_depends) { foreach_array_item(pname, name->rdepends) iterate_providers(*pname, ctx); - } - else + } else { iterate_providers(name, ctx); + } } #define LIST_OPTIONS(OPT) \ @@ -188,7 +183,7 @@ static void print_result(struct apk_database *db, const char *match, struct apk_ APK_OPT_APPLET(option_desc, LIST_OPTIONS); -static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *pctx, struct apk_ctx *ac, int opt, const char *optarg) { struct list_ctx *ctx = pctx; @@ -235,6 +230,7 @@ static int list_main(void *pctx, struct apk_database *db, struct apk_string_arra { struct list_ctx *ctx = pctx; + ctx->verbosity = apk_out_verbosity(&db->ctx->out); ctx->filters = args; if (ctx->match_origin) diff --git a/src/app_manifest.c b/src/app_manifest.c index c2e20e8..9b9a2db 100644 --- a/src/app_manifest.c +++ b/src/app_manifest.c @@ -24,43 +24,50 @@ static char *csum_types[APK_CHECKSUM_SHA1 + 1] = { [APK_CHECKSUM_SHA1] = "sha1", }; -struct manifest_file_ctx { - const char *file; - struct apk_sign_ctx *sctx; -}; - static void process_package(struct apk_database *db, struct apk_package *pkg) { + struct apk_out *out = &db->ctx->out; struct apk_installed_package *ipkg = pkg->ipkg; struct apk_db_dir_instance *diri; struct apk_db_file *file; struct hlist_node *dc, *dn, *fc, *fn; + const char *prefix1 = "", *prefix2 = ""; char csum_buf[APK_BLOB_CHECKSUM_BUF]; if (ipkg == NULL) return; + if (apk_out_verbosity(out) > 1) { + prefix1 = pkg->name->name; + prefix2 = ": "; + } + hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs, pkg_dirs_list) { hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) { apk_blob_t csum_blob = APK_BLOB_BUF(csum_buf); - memset(csum_buf, '\0', sizeof(csum_buf)); apk_blob_push_hexdump(&csum_blob, APK_BLOB_CSUM(file->csum)); - if (apk_verbosity > 1) - printf("%s: ", pkg->name->name); - - printf("%s:%s " DIR_FILE_FMT "\n", csum_types[file->csum.type], csum_buf, DIR_FILE_PRINTF(diri->dir, file)); - } + apk_out(out, "%s%s%s:%s " DIR_FILE_FMT, + prefix1, prefix2, + csum_types[file->csum.type], csum_buf, + DIR_FILE_PRINTF(diri->dir, file)); + } } } -static int read_file_entry(void *ctx, const struct apk_file_info *ae, - struct apk_istream *is) +struct manifest_file_ctx { + struct apk_out *out; + struct apk_sign_ctx *sctx; + const char *prefix1, *prefix2; +}; + +static int read_file_entry(void *ctx, const struct apk_file_info *ae, struct apk_istream *is) { struct manifest_file_ctx *mctx = ctx; + struct apk_out *out = mctx->out; char csum_buf[APK_BLOB_CHECKSUM_BUF]; apk_blob_t csum_blob = APK_BLOB_BUF(csum_buf); int r; @@ -78,34 +85,43 @@ static int read_file_entry(void *ctx, const struct apk_file_info *ae, memset(csum_buf, '\0', sizeof(csum_buf)); apk_blob_push_hexdump(&csum_blob, APK_BLOB_CSUM(ae->csum)); - if (apk_verbosity > 1) - printf("%s: ", mctx->file); - - printf("%s:%s %s\n", csum_types[ae->csum.type], csum_buf, ae->name); + apk_out(out, "%s%s%s:%s %s\n", + mctx->prefix1, mctx->prefix2, + csum_types[ae->csum.type], csum_buf, ae->name); return 0; } static void process_file(struct apk_database *db, const char *match) { + struct apk_out *out = &db->ctx->out; struct apk_sign_ctx sctx; - struct manifest_file_ctx ctx = {match, &sctx}; + struct manifest_file_ctx ctx = { + .out = out, + .sctx = &sctx, + .prefix1 = "", + .prefix2 = "", + }; int r; - apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + if (apk_out_verbosity(out) > 1) { + ctx.prefix1 = match; + ctx.prefix2 = ": "; + } + + apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_tar_parse( apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, match), apk_sign_ctx_mpart_cb, &sctx), read_file_entry, &ctx, &db->id_cache); apk_sign_ctx_free(&sctx); - if (r < 0) apk_error("%s: %s", match, apk_error_str(r)); + if (r < 0) apk_err(out, "%s: %s", match, apk_error_str(r)); } static void process_match(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { struct apk_provider *p; - if (name == NULL) - { + if (name == NULL) { process_file(db, match); return; } @@ -114,7 +130,7 @@ static void process_match(struct apk_database *db, const char *match, struct apk process_package(db, p->pkg); } -static int manifest_main(void *ctx, struct apk_database *db, struct apk_string_array *args) +static int manifest_main(void *applet_ctx, struct apk_database *db, struct apk_string_array *args) { apk_name_foreach_matching(db, args, apk_foreach_genid(), process_match, NULL); return 0; diff --git a/src/app_mkndx.c b/src/app_mkndx.c index d3c6143..beb4144 100644 --- a/src/app_mkndx.c +++ b/src/app_mkndx.c @@ -44,7 +44,7 @@ struct mkndx_ctx { APK_OPT_APPLET(option_desc, MKNDX_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int optch, const char *optarg) { struct mkndx_ctx *ictx = ctx; @@ -188,6 +188,7 @@ static int mkndx_parse_v2_tar(void *pctx, const struct apk_file_info *ae, struct static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct adb odb, tmpdb; struct adb_obj oroot, opkgs, ndx, tmpl; struct apk_file_info fi; @@ -198,7 +199,7 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr time_t index_mtime = 0; if (ctx->output == NULL) { - apk_error("Please specify --output FILE"); + apk_err(out, "Please specify --output FILE"); return -1; } @@ -215,7 +216,7 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr r = adb_m_map(&odb, open(ctx->index, O_RDONLY), ADB_SCHEMA_INDEX, &db->trust); if (r) { - apk_error("%s: %s", ctx->index, apk_error_str(r)); + apk_err(out, "%s: %s", ctx->index, apk_error_str(r)); return r; } adb_ro_obj(adb_r_rootobj(&odb, &oroot, &schema_index), ADBI_NDX_PACKAGES, &opkgs); @@ -225,7 +226,7 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr r = apk_fileinfo_get(AT_FDCWD, *parg, APK_CHECKSUM_NONE, &fi, 0); if (r < 0) { err_pkg: - apk_error("%s: %s", *parg, apk_error_str(r)); + apk_err(out, "%s: %s", *parg, apk_error_str(r)); errors++; continue; } @@ -273,7 +274,7 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr } if (!found) { do_file: - apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&ctx->sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_tar_parse( apk_istream_gunzip_mpart(apk_istream_from_file(AT_FDCWD, *parg), apk_sign_ctx_mpart_cb, &ctx->sctx), mkndx_parse_v2_tar, ctx, &db->id_cache); @@ -283,7 +284,7 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr } } if (errors) { - apk_error("%d errors, not creating index", errors); + apk_err(out, "%d errors, not creating index", errors); return -1; } @@ -300,19 +301,18 @@ static int mkndx_main(void *pctx, struct apk_database *db, struct apk_string_arr adb_free(&odb); if (r == 0) - apk_message("Index has %d packages (of which %d are new)", - numpkgs, newpkgs); + apk_msg(out, "Index has %d packages (of which %d are new)", numpkgs, newpkgs); else - apk_error("Index creation failed: %s", apk_error_str(r)); + apk_err(out, "Index creation failed: %s", apk_error_str(r)); #if 0 apk_hash_foreach(&db->available.names, warn_if_no_providers, &counts); if (counts.unsatisfied != 0) - apk_warning("Total of %d unsatisfiable package " - "names. Your repository may be broken.", - counts.unsatisfied); + apk_warn(out, + "Total of %d unsatisfiable package names. Your repository may be broken.", + counts.unsatisfied); #endif return r; diff --git a/src/app_policy.c b/src/app_policy.c index 954eb9d..91e97d0 100644 --- a/src/app_policy.c +++ b/src/app_policy.c @@ -17,6 +17,7 @@ extern const char * const apk_installed_file; static void print_policy(struct apk_database *db, const char *match, struct apk_name *name, void *ctx) { + struct apk_out *out = &db->ctx->out; struct apk_provider *p; struct apk_repository *repo; int i, j, num = 0; @@ -41,17 +42,17 @@ zlib1g policy: if (p->pkg->name != name) continue; if (num++ == 0) - printf("%s policy:\n", name->name); - printf(" " BLOB_FMT ":\n", BLOB_PRINTF(*p->version)); + apk_out(out, "%s policy:", name->name); + apk_out(out, " " BLOB_FMT ":", BLOB_PRINTF(*p->version)); if (p->pkg->ipkg != NULL) - printf(" %s\n", apk_installed_file); + apk_out(out, " %s", apk_installed_file); for (i = 0; i < db->num_repos; i++) { repo = &db->repos[i]; if (!(BIT(i) & p->pkg->repos)) continue; for (j = 0; j < db->num_repo_tags; j++) { if (db->repo_tags[j].allowed_repos & p->pkg->repos) - printf(" "BLOB_FMT"%s%s\n", + apk_out(out, " "BLOB_FMT"%s%s", BLOB_PRINTF(db->repo_tags[j].tag), j == 0 ? "" : " ", repo->url); diff --git a/src/app_search.c b/src/app_search.c index 866bb7a..11b7108 100644 --- a/src/app_search.c +++ b/src/app_search.c @@ -18,6 +18,7 @@ struct search_ctx { void (*print_result)(struct search_ctx *ctx, struct apk_package *pkg); void (*print_package)(struct search_ctx *ctx, struct apk_package *pkg); + int verbosity; int show_all : 1; int search_exact : 1; int search_description : 1; @@ -38,9 +39,9 @@ static void print_package_name(struct search_ctx *ctx, struct apk_package *pkg) { if (!unique_match(pkg)) return; printf("%s", pkg->name->name); - if (apk_verbosity > 0) + if (ctx->verbosity > 0) printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); - if (apk_verbosity > 1) + if (ctx->verbosity > 1) printf(" - %s", pkg->description); printf("\n"); } @@ -52,7 +53,7 @@ static void print_origin_name(struct search_ctx *ctx, struct apk_package *pkg) printf(BLOB_FMT, BLOB_PRINTF(*pkg->origin)); else printf("%s", pkg->name->name); - if (apk_verbosity > 0) + if (ctx->verbosity > 0) printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); printf("\n"); } @@ -65,7 +66,7 @@ static void print_rdep_pkg(struct apk_package *pkg0, struct apk_dependency *dep0 static void print_rdepends(struct search_ctx *ctx, struct apk_package *pkg) { - if (apk_verbosity > 0) { + if (ctx->verbosity > 0) { ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES; printf(PKG_VER_FMT " is required by:\n", PKG_VER_PRINTF(pkg)); } @@ -82,7 +83,7 @@ static void print_rdepends(struct search_ctx *ctx, struct apk_package *pkg) APK_OPT_APPLET(option_desc, SEARCH_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct search_ctx *ictx = (struct search_ctx *) ctx; @@ -176,6 +177,7 @@ static int search_main(void *pctx, struct apk_database *db, struct apk_string_ar struct search_ctx *ctx = (struct search_ctx *) pctx; char *tmp, **pmatch; + ctx->verbosity = apk_out_verbosity(&db->ctx->out); ctx->filter = args; ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES; if (ctx->print_package == NULL) diff --git a/src/app_update.c b/src/app_update.c index 70b7460..4fa24f8 100644 --- a/src/app_update.c +++ b/src/app_update.c @@ -16,11 +16,12 @@ static int update_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct apk_repository *repo; int i; char buf[32] = "OK:"; - if (apk_verbosity < 1) + if (apk_out_verbosity(out) < 1) return db->repo_update_errors; for (i = 0; i < db->num_repos; i++) { @@ -29,15 +30,15 @@ static int update_main(void *ctx, struct apk_database *db, struct apk_string_arr if (APK_BLOB_IS_NULL(repo->description)) continue; - apk_message(BLOB_FMT " [%s]", - BLOB_PRINTF(repo->description), - db->repos[i].url); + apk_msg(out, BLOB_FMT " [%s]", + BLOB_PRINTF(repo->description), + db->repos[i].url); } if (db->repo_update_errors != 0) snprintf(buf, sizeof(buf), "%d errors;", db->repo_update_errors); - apk_message("%s %d distinct packages available", buf, + apk_msg(out, "%s %d distinct packages available", buf, db->available.packages.num_items); return db->repo_update_errors; diff --git a/src/app_upgrade.c b/src/app_upgrade.c index 2c35d63..6d63b50 100644 --- a/src/app_upgrade.c +++ b/src/app_upgrade.c @@ -16,6 +16,8 @@ #include "apk_print.h" #include "apk_solver.h" +extern char **apk_argv; + struct upgrade_ctx { unsigned short solver_flags; int no_self_upgrade : 1; @@ -35,7 +37,7 @@ struct upgrade_ctx { APK_OPT_APPLET(option_desc, UPGRADE_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx; @@ -71,6 +73,7 @@ static const struct apk_option_group optgroup_applet = { int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags, unsigned int self_upgrade_only) { + struct apk_out *out = &db->ctx->out; struct apk_name *name; struct apk_package *pkg; struct apk_provider *p0; @@ -102,7 +105,7 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags, un r = apk_solver_solve(db, 0, db->world, &changeset); if (r != 0) { - apk_warning("Failed to perform initial self-upgrade, continuing with full upgrade."); + apk_warn(out, "Failed to perform initial self-upgrade, continuing with full upgrade."); r = 0; goto ret; } @@ -110,24 +113,24 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags, un if (changeset.num_total_changes == 0) goto ret; - if (!self_upgrade_only && db->flags & APK_SIMULATE) { - apk_warning("This simulation is not reliable as apk-tools upgrade is available."); + if (!self_upgrade_only && db->ctx->flags & APK_SIMULATE) { + apk_warn(out, "This simulation is not reliable as apk-tools upgrade is available."); goto ret; } - apk_message("Upgrading critical system libraries and apk-tools:"); + apk_msg(out, "Upgrading critical system libraries and apk-tools:"); apk_solver_commit_changeset(db, &changeset, db->world); if (self_upgrade_only) goto ret; apk_db_close(db); + apk_msg(out, "Continuing the upgrade transaction with new apk-tools:"); - apk_message("Continuing the upgrade transaction with new apk-tools:"); for (r = 0; apk_argv[r] != NULL; r++) ; apk_argv[r] = "--no-self-upgrade"; execvp(apk_argv[0], apk_argv); - apk_error("PANIC! Failed to re-execute new apk-tools!"); + apk_err(out, "PANIC! Failed to re-execute new apk-tools!"); exit(1); ret: @@ -138,10 +141,11 @@ ret: static void set_upgrade_for_name(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { + struct apk_out *out = &db->ctx->out; struct upgrade_ctx *uctx = (struct upgrade_ctx *) pctx; if (!name) { - apk_error("Package '%s' not found", match); + apk_err(out, "Package '%s' not found", match); uctx->errors++; return; } @@ -151,6 +155,7 @@ static void set_upgrade_for_name(struct apk_database *db, const char *match, str static int upgrade_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx; unsigned short solver_flags; struct apk_dependency *dep; @@ -159,8 +164,9 @@ static int upgrade_main(void *ctx, struct apk_database *db, struct apk_string_ar int r = 0; if (apk_db_check_world(db, db->world) != 0) { - apk_error("Not continuing with upgrade due to missing repository tags. " - "Use --force-broken-world to override."); + apk_err(out, + "Not continuing with upgrade due to missing repository tags. " + "Use --force-broken-world to override."); return -1; } diff --git a/src/app_verify.c b/src/app_verify.c index 8f78d82..0a18ea6 100644 --- a/src/app_verify.c +++ b/src/app_verify.c @@ -17,6 +17,7 @@ static int verify_main(void *ctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct apk_sign_ctx sctx; char **parg; int r, ok, rc = 0; @@ -28,13 +29,13 @@ static int verify_main(void *ctx, struct apk_database *db, struct apk_string_arr apk_sign_ctx_mpart_cb, &sctx), apk_sign_ctx_verify_tar, &sctx, &db->id_cache); ok = sctx.control_verified && sctx.data_verified; - if (apk_verbosity >= 1) - apk_message("%s: %d - %s", *parg, r, + if (apk_out_verbosity(out) >= 1) + apk_msg(out, "%s: %d - %s", *parg, r, r < 0 ? apk_error_str(r) : ok ? "OK" : !sctx.control_verified ? "UNTRUSTED" : "FAILED"); else if (!ok) - printf("%s\n", *parg); + apk_out(out, "%s", *parg); if (!ok) rc++; diff --git a/src/app_version.c b/src/app_version.c index d5d9c88..0e17493 100644 --- a/src/app_version.c +++ b/src/app_version.c @@ -22,6 +22,7 @@ struct ver_ctx { static int ver_indexes(struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct apk_repository *repo; int i; @@ -31,9 +32,9 @@ static int ver_indexes(struct apk_database *db, struct apk_string_array *args) if (APK_BLOB_IS_NULL(repo->description)) continue; - printf(BLOB_FMT " [%s]\n", - BLOB_PRINTF(repo->description), - db->repos[i].url); + apk_out(out, BLOB_FMT " [%s]", + BLOB_PRINTF(repo->description), + db->repos[i].url); } return 0; @@ -41,25 +42,26 @@ static int ver_indexes(struct apk_database *db, struct apk_string_array *args) static int ver_test(struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; int r; if (args->num != 2) return 1; r = apk_version_compare(args->item[0], args->item[1]); - printf("%s\n", apk_version_op_string(r)); + apk_out(out, "%s", apk_version_op_string(r)); return 0; } static int ver_validate(struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; char **parg; int errors = 0; foreach_array_item(parg, args) { if (!apk_version_validate(APK_BLOB_STR(*parg))) { - if (apk_verbosity > 0) - printf("%s\n", *parg); + apk_msg(out, "%s", *parg); errors++; } } @@ -75,7 +77,7 @@ static int ver_validate(struct apk_database *db, struct apk_string_array *args) APK_OPT_APPLET(option_desc, VERSION_OPTIONS); -static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg) +static int option_parse_applet(void *ctx, struct apk_ctx *ac, int opt, const char *optarg) { struct ver_ctx *ictx = (struct ver_ctx *) ctx; switch (opt) { @@ -84,7 +86,7 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt break; case OPT_VERSION_check: ictx->action = ver_validate; - dbopts->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; + ac->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; break; case OPT_VERSION_indexes: ictx->action = ver_indexes; @@ -94,7 +96,7 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt break; case OPT_VERSION_test: ictx->action = ver_test; - dbopts->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; + ac->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; break; default: return -ENOTSUP; @@ -109,6 +111,7 @@ static const struct apk_option_group optgroup_applet = { static void ver_print_package_status(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) { + struct apk_out *out = &db->ctx->out; struct ver_ctx *ctx = (struct ver_ctx *) pctx; struct apk_package *pkg; struct apk_provider *p0; @@ -149,8 +152,8 @@ static void ver_print_package_status(struct apk_database *db, const char *match, opstr = apk_version_op_string(r); if ((ctx->limchars != NULL) && (strchr(ctx->limchars, *opstr) == NULL)) return; - if (apk_verbosity <= 0) { - printf("%s\n", pkg->name->name); + if (apk_out_verbosity(out) <= 0) { + apk_out(out, "%s", pkg->name->name); return; } @@ -163,7 +166,7 @@ static void ver_print_package_status(struct apk_database *db, const char *match, } snprintf(pkgname, sizeof(pkgname), PKG_VER_FMT, PKG_VER_PRINTF(pkg)); - printf("%-40s%s " BLOB_FMT " " BLOB_FMT "\n", + apk_out(out, "%-40s%s " BLOB_FMT " " BLOB_FMT, pkgname, opstr, BLOB_PRINTF(*latest), BLOB_PRINTF(db->repo_tags[tag].tag)); @@ -171,20 +174,20 @@ static void ver_print_package_status(struct apk_database *db, const char *match, static int ver_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; struct ver_ctx *ctx = (struct ver_ctx *) pctx; if (ctx->limchars) { if (strlen(ctx->limchars) == 0) ctx->limchars = NULL; - } else if (args->num == 0 && apk_verbosity == 1) { + } else if (args->num == 0 && apk_out_verbosity(out) == 1) { ctx->limchars = "<"; } if (ctx->action != NULL) return ctx->action(db, args); - if (apk_verbosity > 0) - printf("%-42sAvailable:\n", "Installed:"); + apk_msg(out, "%-42s%s", "Installed:", "Available:"); apk_name_foreach_matching( db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), diff --git a/src/app_vertest.c b/src/app_vertest.c index 54d5f10..e6b3cae 100644 --- a/src/app_vertest.c +++ b/src/app_vertest.c @@ -16,6 +16,7 @@ static int vertest_main(void *pctx, struct apk_database *db, struct apk_string_array *args) { + struct apk_out *out = &db->ctx->out; apk_blob_t arg, ver, op, space = APK_BLOB_STRLIT(" "); char **parg; int errors = 0; @@ -35,8 +36,7 @@ static int vertest_main(void *pctx, struct apk_database *db, struct apk_string_a ok = apk_version_validate(arg); } if (!ok) { - if (apk_verbosity > 0) - printf("%s\n", *parg); + apk_msg(out, "%s", *parg); errors++; } } diff --git a/src/help.c b/src/applet.c index 3034da2..1d47662 100644 --- a/src/help.c +++ b/src/applet.c @@ -10,6 +10,37 @@ #include "apk_applet.h" #include "apk_print.h" +static struct list_head apk_applet_list; + +#define apk_applet_foreach(iter) list_for_each_entry(iter, &apk_applet_list, node) + +void apk_applet_register(struct apk_applet *applet) +{ + list_init(&applet->node); + list_add_tail(&applet->node, &apk_applet_list); +} + +void apk_applet_register_builtin(void) +{ + extern apk_init_func_t __start_initapplets[], __stop_initapplets[]; + apk_init_func_t *p; + + list_init(&apk_applet_list); + for (p = __start_initapplets; p < __stop_initapplets; p++) + (*p)(); +} + +struct apk_applet *apk_applet_find(const char *name) +{ + struct apk_applet *a; + + apk_applet_foreach(a) { + if (strcmp(name, a->name) == 0) + return a; + } + return NULL; +} + static inline int is_group(struct apk_applet *applet, const char *topic) { if (!applet) return strcasecmp(topic, "apk") == 0; @@ -19,7 +50,7 @@ static inline int is_group(struct apk_applet *applet, const char *topic) return 0; } -void apk_help(struct apk_applet *applet) +void apk_applet_help(struct apk_applet *applet, struct apk_out *out) { #include "help.h" @@ -31,16 +62,15 @@ void apk_help(struct apk_applet *applet) uncompress((unsigned char*) buf, &len, compressed_help, sizeof compressed_help); for (ptr = buf; *ptr && ptr < &buf[len]; ptr = msg + strlen(msg) + 1) { msg = ptr + strlen(ptr) + 1; - if (is_group(applet, ptr)) { fputc('\n', stdout); fwrite(msg, strlen(msg), 1, stdout); num++; } } - if (num == 0) apk_error("Help not found"); + if (num == 0) apk_err(out, "Help not found"); #else fputc('\n', stdout); - apk_error("This apk-tools has been built without help"); + apk_err(out, "This apk-tools has been built without help"); #endif } diff --git a/src/commit.c b/src/commit.c index 6cc60b7..640c135 100644 --- a/src/commit.c +++ b/src/commit.c @@ -28,6 +28,7 @@ static inline int pkg_available(struct apk_database *db, struct apk_package *pkg static int print_change(struct apk_database *db, struct apk_change *change, int cur, int total) { + struct apk_out *out = &db->ctx->out; struct apk_name *name; struct apk_package *oldpkg = change->old_pkg; struct apk_package *newpkg = change->new_pkg; @@ -73,18 +74,18 @@ static int print_change(struct apk_database *db, struct apk_change *change, return FALSE; if (oneversion) { - apk_message("%s %s %s" BLOB_FMT " (" BLOB_FMT ")", - status, msg, - name->name, - BLOB_PRINTF(db->repo_tags[change->new_repository_tag].tag), - BLOB_PRINTF(*oneversion)); + apk_msg(out, "%s %s %s" BLOB_FMT " (" BLOB_FMT ")", + status, msg, + name->name, + BLOB_PRINTF(db->repo_tags[change->new_repository_tag].tag), + BLOB_PRINTF(*oneversion)); } else { - apk_message("%s %s %s" BLOB_FMT " (" BLOB_FMT " -> " BLOB_FMT ")", - status, msg, - name->name, - BLOB_PRINTF(db->repo_tags[change->new_repository_tag].tag), - BLOB_PRINTF(*oldpkg->version), - BLOB_PRINTF(*newpkg->version)); + apk_msg(out, "%s %s %s" BLOB_FMT " (" BLOB_FMT " -> " BLOB_FMT ")", + status, msg, + name->name, + BLOB_PRINTF(db->repo_tags[change->new_repository_tag].tag), + BLOB_PRINTF(*oldpkg->version), + BLOB_PRINTF(*newpkg->version)); } return TRUE; } @@ -126,13 +127,13 @@ static void progress_cb(void *ctx, size_t installed_bytes) prog->total.bytes + prog->total.packages); } -static int dump_packages(struct apk_changeset *changeset, +static int dump_packages(struct apk_out *out, struct apk_changeset *changeset, int (*cmp)(struct apk_change *change), const char *msg) { struct apk_change *change; struct apk_name *name; - struct apk_indent indent = { .indent = 2 }; + struct apk_indent indent = { .out = out, .indent = 2 }; int match = 0; foreach_array_item(change, changeset->changes) { @@ -231,17 +232,18 @@ static int run_commit_hook(void *ctx, int dirfd, const char *file) static char *const commit_hook_str[] = { "pre-commit", "post-commit" }; struct apk_commit_hook *hook = (struct apk_commit_hook *) ctx; struct apk_database *db = hook->db; + struct apk_out *out = &db->ctx->out; char fn[PATH_MAX], *argv[] = { fn, (char *) commit_hook_str[hook->type], NULL }; if (file[0] == '.') return 0; - if ((db->flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0) return 0; + if ((db->ctx->flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0) return 0; snprintf(fn, sizeof(fn), "etc/apk/commit_hooks.d" "/%s", file); - if ((db->flags & APK_NO_COMMIT_HOOKS) != 0) { - apk_message("Skipping: %s %s", fn, commit_hook_str[hook->type]); + if ((db->ctx->flags & APK_NO_COMMIT_HOOKS) != 0) { + apk_msg(out, "Skipping: %s %s", fn, commit_hook_str[hook->type]); return 0; } - if (apk_verbosity >= 2) apk_message("Executing: %s %s", fn, commit_hook_str[hook->type]); + apk_dbg(out, "Executing: %s %s", fn, commit_hook_str[hook->type]); if (apk_db_run_script(db, fn, argv) < 0 && hook->type == PRE_COMMIT_HOOK) return -2; @@ -260,7 +262,8 @@ int apk_solver_commit_changeset(struct apk_database *db, struct apk_changeset *changeset, struct apk_dependency_array *world) { - struct progress prog = { .prog = db->progress }; + struct apk_out *out = &db->ctx->out; + struct progress prog = { .prog = db->ctx->progress }; struct apk_change *change; char buf[32]; const char *size_unit; @@ -269,8 +272,8 @@ int apk_solver_commit_changeset(struct apk_database *db, assert(world); if (apk_db_check_world(db, world) != 0) { - apk_error("Not committing changes due to missing repository tags. " - "Use --force-broken-world to override."); + apk_err(out, "Not committing changes due to missing repository tags. " + "Use --force-broken-world to override."); return -1; } @@ -287,18 +290,18 @@ int apk_solver_commit_changeset(struct apk_database *db, } size_unit = apk_get_human_size(llabs(size_diff), &humanized); - if ((apk_verbosity > 1 || (db->flags & APK_INTERACTIVE)) && - !(db->flags & APK_SIMULATE)) { - r = dump_packages(changeset, cmp_remove, + if ((apk_out_verbosity(out) > 1 || (db->ctx->flags & APK_INTERACTIVE)) && + !(db->ctx->flags & APK_SIMULATE)) { + r = dump_packages(out, changeset, cmp_remove, "The following packages will be REMOVED"); - r += dump_packages(changeset, cmp_downgrade, + r += dump_packages(out, changeset, cmp_downgrade, "The following packages will be DOWNGRADED"); - if (r || (db->flags & APK_INTERACTIVE) || apk_verbosity > 2) { - r += dump_packages(changeset, cmp_new, + if (r || (db->ctx->flags & APK_INTERACTIVE) || apk_out_verbosity(out) > 2) { + r += dump_packages(out, changeset, cmp_new, "The following NEW packages will be installed"); - r += dump_packages(changeset, cmp_upgrade, + r += dump_packages(out, changeset, cmp_upgrade, "The following packages will be upgraded"); - r += dump_packages(changeset, cmp_reinstall, + r += dump_packages(out, changeset, cmp_reinstall, "The following packages will be reinstalled"); printf("After this operation, %lld %s of %s.\n", (long long)humanized, @@ -307,7 +310,7 @@ int apk_solver_commit_changeset(struct apk_database *db, "disk space will be freed" : "additional disk space will be used"); } - if (r > 0 && (db->flags & APK_INTERACTIVE)) { + if (r > 0 && (db->ctx->flags & APK_INTERACTIVE)) { printf("Do you want to continue [Y/n]? "); fflush(stdout); r = fgetc(stdin); @@ -328,7 +331,7 @@ int apk_solver_commit_changeset(struct apk_database *db, prog.pkg = change->new_pkg; progress_cb(&prog, 0); - if (!(db->flags & APK_SIMULATE) && + if (!(db->ctx->flags & APK_SIMULATE) && ((change->old_pkg != change->new_pkg) || (change->reinstall && pkg_available(db, change->new_pkg)))) { r = apk_db_install_pkg(db, change->old_pkg, change->new_pkg, @@ -357,18 +360,18 @@ all_done: errors > 1 ? "s" : ""); else strcpy(buf, "OK:"); - if (apk_verbosity > 1) { - apk_message("%s %d packages, %d dirs, %d files, %zu MiB", - buf, - db->installed.stats.packages, - db->installed.stats.dirs, - db->installed.stats.files, - db->installed.stats.bytes / (1024 * 1024)); + if (apk_out_verbosity(out) > 1) { + apk_msg(out, "%s %d packages, %d dirs, %d files, %zu MiB", + buf, + db->installed.stats.packages, + db->installed.stats.dirs, + db->installed.stats.files, + db->installed.stats.bytes / (1024 * 1024)); } else { - apk_message("%s %zu MiB in %d packages", - buf, - db->installed.stats.bytes / (1024 * 1024), - db->installed.stats.packages); + apk_msg(out, "%s %zu MiB in %d packages", + buf, + db->installed.stats.bytes / (1024 * 1024), + db->installed.stats.packages); } } return errors; @@ -599,6 +602,7 @@ void apk_solver_print_errors(struct apk_database *db, struct apk_changeset *changeset, struct apk_dependency_array *world) { + struct apk_out *out = &db->ctx->out; struct print_state ps; struct apk_change *change; struct apk_dependency *p; @@ -640,7 +644,7 @@ void apk_solver_print_errors(struct apk_database *db, * any other selected version. or all of them with -v. */ - apk_error("unable to select packages:"); + apk_err(out, "unable to select packages:"); /* Construct information about names */ foreach_array_item(change, changeset->changes) { @@ -655,6 +659,7 @@ void apk_solver_print_errors(struct apk_database *db, /* Analyze is package, and missing names referred to */ ps = (struct print_state) { + .i.out = out, .db = db, .world = world, }; @@ -675,12 +680,13 @@ int apk_solver_commit(struct apk_database *db, unsigned short solver_flags, struct apk_dependency_array *world) { + struct apk_out *out = &db->ctx->out; struct apk_changeset changeset = {}; int r; if (apk_db_check_world(db, world) != 0) { - apk_error("Not committing changes due to missing repository tags. " - "Use --force-broken-world to override."); + apk_err(out, "Not committing changes due to missing repository tags. " + "Use --force-broken-world to override."); return -1; } diff --git a/src/context.c b/src/context.c new file mode 100644 index 0000000..f7b745c --- /dev/null +++ b/src/context.c @@ -0,0 +1,27 @@ +/* context.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org> + * Copyright (C) 2008-2020 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +#include "apk_context.h" + +void apk_ctx_init(struct apk_ctx *ac) +{ + memset(ac, 0, sizeof *ac); + apk_string_array_init(&ac->repository_list); + apk_string_array_init(&ac->private_keys); + apk_out_reset(&ac->out); + ac->out.out = stdout; + ac->out.err = stderr; + ac->out.verbosity = 1; +} + +void apk_ctx_free(struct apk_ctx *ac) +{ + apk_string_array_free(&ac->repository_list); + apk_string_array_free(&ac->private_keys); +} diff --git a/src/database.c b/src/database.c index 946155d..f31e840 100644 --- a/src/database.c +++ b/src/database.c @@ -47,10 +47,7 @@ enum { APK_DIR_REMOVE }; -int apk_verbosity = 1; - -static apk_blob_t tmpprefix = { .len=8, .ptr = ".apknew." }; - +static apk_blob_t tmpprefix = APK_BLOB_STRLIT(".apknew."); static const char * const apkindex_tar_gz = "APKINDEX.tar.gz"; static const char * const apk_static_cache_dir = "var/cache/apk"; static const char * const apk_world_file = "etc/apk/world"; @@ -242,7 +239,7 @@ static void apk_db_dir_prepare(struct apk_database *db, struct apk_db_dir *dir, (st.st_mode & 07777) == (dir->mode & 07777) && st.st_uid == dir->uid && st.st_gid == dir->gid; } else if (newmode) { - if (!(db->flags & APK_SIMULATE)) + if (!(db->ctx->flags & APK_SIMULATE)) mkdirat(db->root_fd, dir->name, newmode); dir->created = 1; dir->update_permissions = 1; @@ -257,7 +254,7 @@ void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir, int rmdir if (dir->namelen != 0) { if (rmdir_mode == APK_DIR_REMOVE) { dir->modified = 1; - if (!(db->flags & APK_SIMULATE) && + if (!(db->ctx->flags & APK_SIMULATE) && unlinkat(db->root_fd, dir->name, AT_REMOVEDIR) != 0) ; } @@ -609,6 +606,7 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, struct apk_package *pkg, int verify, int autoupdate, apk_progress_cb cb, void *cb_ctx) { + struct apk_out *out = &db->ctx->out; struct stat st = {0}; struct apk_url_print urlp; struct apk_istream *is; @@ -629,18 +627,18 @@ int apk_cache_download(struct apk_database *db, struct apk_repository *repo, r = apk_repo_format_real_url(db->arch, repo, pkg, url, sizeof(url), &urlp); if (r < 0) return r; - if (autoupdate && !(db->force & APK_FORCE_REFRESH)) { + if (autoupdate && !(db->ctx->force & APK_FORCE_REFRESH)) { if (fstatat(db->cache_fd, cacheitem, &st, 0) == 0 && - now - st.st_mtime <= db->cache_max_age) + now - st.st_mtime <= db->ctx->cache_max_age) return -EALREADY; } - apk_message("fetch " URL_FMT, URL_PRINTF(urlp)); + apk_msg(out, "fetch " URL_FMT, URL_PRINTF(urlp)); - if (db->flags & APK_SIMULATE) return 0; + if (db->ctx->flags & APK_SIMULATE) return 0; if (cb) cb(cb_ctx, 0); if (verify != APK_SIGN_NONE) { - apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); is = apk_istream_from_url(url, apk_db_url_since(db, st.st_mtime)); is = apk_istream_tee(is, db->cache_fd, tmpcacheitem, !autoupdate, cb, cb_ctx); is = apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &sctx); @@ -747,6 +745,7 @@ err: int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) { + struct apk_out *out = &db->ctx->out; struct apk_package *pkg = NULL; struct apk_installed_package *ipkg = NULL; struct apk_db_dir_instance *diri = NULL; @@ -782,7 +781,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) } if (apk_db_pkg_add(db, pkg) == NULL) { - apk_error("Installed database load failed"); + apk_err(out, "Installed database load failed"); return -1; } pkg = NULL; @@ -870,13 +869,13 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) case 's': ipkg->broken_script = 1; break; case 'x': ipkg->broken_xattr = 1; break; default: - if (!(db->force & APK_FORCE_OLD_APK)) + if (!(db->ctx->force & APK_FORCE_OLD_APK)) goto old_apk_tools; } } break; default: - if (r != 0 && !(db->force & APK_FORCE_OLD_APK)) + if (r != 0 && !(db->ctx->force & APK_FORCE_OLD_APK)) goto old_apk_tools; /* Installed. So mark the package as installable. */ pkg->filename = NULL; @@ -888,10 +887,10 @@ int apk_db_index_read(struct apk_database *db, struct apk_istream *is, int repo) return 0; old_apk_tools: /* Installed db should not have unsupported fields */ - apk_error("This apk-tools is too old to handle installed packages"); + apk_err(out, "This apk-tools is too old to handle installed packages"); goto err; bad_entry: - apk_error("FDB format error (line %d, entry '%c')", lineno, field); + apk_err(out, "FDB format error (line %d, entry '%c')", lineno, field); err: apk_istream_close(is); return -1; @@ -928,8 +927,9 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { pkg = ipkg->pkg; r = apk_pkg_write_index_entry(pkg, os); - if (r < 0) + if (r < 0) { return r; + } if (ipkg->replaces->num) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:")); @@ -1192,7 +1192,7 @@ static int write_index_entry(apk_hash_item item, void *ctx) return r; if (apk_ostream_write(iwctx->os, "\n", 1) != 1) - return -EIO; + return apk_ostream_cancel(iwctx->os, -EIO); iwctx->count++; return 0; @@ -1390,6 +1390,7 @@ static void mark_in_cache(struct apk_database *db, int dirfd, const char *name, static int add_repos_from_file(void *ctx, int dirfd, const char *file) { struct apk_database *db = (struct apk_database *) ctx; + struct apk_out *out = &db->ctx->out; apk_blob_t blob; if (dirfd != AT_FDCWD && dirfd != db->root_fd) { @@ -1401,8 +1402,8 @@ static int add_repos_from_file(void *ctx, int dirfd, const char *file) blob = apk_blob_from_file(dirfd, file); if (APK_BLOB_IS_NULL(blob)) { if (dirfd != AT_FDCWD) return 0; - apk_error("failed to read repositories: %s", file); - apk_message("NOTE: --repositories-file is relative to the startup directory since apk 2.12.0_rc2"); + apk_err(out, "failed to read repositories: %s", file); + apk_msg(out, "NOTE: --repositories-file is relative to the startup directory since apk 2.12.0_rc2"); return -ENOENT; } @@ -1507,8 +1508,9 @@ void apk_db_init(struct apk_database *db) db->root_fd = -1; } -int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) +int apk_db_open(struct apk_database *db, struct apk_ctx *ac) { + struct apk_out *out = &ac->out; const char *msg = NULL; struct statfs stfs; apk_blob_t blob; @@ -1517,31 +1519,31 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_default_acl_dir = apk_db_acl_atomize(db, 0755, 0, 0, NULL); apk_default_acl_file = apk_db_acl_atomize(db, 0644, 0, 0, NULL); - if (dbopts->flags & APK_SIMULATE) { - dbopts->open_flags &= ~(APK_OPENF_CREATE | APK_OPENF_WRITE); - dbopts->open_flags |= APK_OPENF_READ; - } - if (dbopts->open_flags == 0) { + db->ctx = ac; + if (ac->open_flags == 0) { msg = "Invalid open flags (internal error)"; r = -1; goto ret_r; } - db->flags = dbopts->flags; - db->force = dbopts->force; - if ((dbopts->open_flags & APK_OPENF_WRITE) && - !(dbopts->open_flags & APK_OPENF_NO_AUTOUPDATE) && - !(dbopts->flags & APK_NO_NETWORK)) + if (ac->flags & APK_SIMULATE) { + ac->open_flags &= ~(APK_OPENF_CREATE | APK_OPENF_WRITE); + ac->open_flags |= APK_OPENF_READ; + } + if ((ac->open_flags & APK_OPENF_WRITE) && + !(ac->open_flags & APK_OPENF_NO_AUTOUPDATE) && + !(ac->flags & APK_NO_NETWORK)) db->autoupdate = 1; - if (!dbopts->cache_dir) dbopts->cache_dir = "etc/apk/cache"; + if (!ac->cache_dir) ac->cache_dir = "etc/apk/cache"; + if (!ac->keys_dir) ac->keys_dir = "etc/apk/keys"; + if (!ac->root) ac->root = "/"; + if (!ac->cache_max_age) ac->cache_max_age = 4*60*60; /* 4 hours default */ - apk_db_setup_repositories(db, dbopts->cache_dir); + apk_db_setup_repositories(db, ac->cache_dir); - db->cache_max_age = dbopts->cache_max_age ?: 4*60*60; /* 4 hours default */ - db->root = strdup(dbopts->root ?: "/"); - db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY | O_CLOEXEC); - if (db->root_fd < 0 && (dbopts->open_flags & APK_OPENF_CREATE)) { - mkdirat(AT_FDCWD, db->root, 0755); - db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY | O_CLOEXEC); + db->root_fd = openat(AT_FDCWD, db->ctx->root, O_RDONLY | O_CLOEXEC); + if (db->root_fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) { + mkdirat(AT_FDCWD, db->ctx->root, 0755); + db->root_fd = openat(AT_FDCWD, db->ctx->root, O_RDONLY | O_CLOEXEC); } if (db->root_fd < 0) { msg = "Unable to open root"; @@ -1551,8 +1553,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) stfs.f_type == TMPFS_MAGIC) db->permanent = 0; - if (dbopts->root && dbopts->arch) { - db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(dbopts->arch)); + if (ac->root && ac->arch) { + db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(ac->arch)); write_arch = TRUE; } else { apk_blob_t arch; @@ -1568,11 +1570,11 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_id_cache_init(&db->id_cache, db->root_fd); - if (dbopts->open_flags & APK_OPENF_WRITE) { + if (ac->open_flags & APK_OPENF_WRITE) { db->lock_fd = openat(db->root_fd, apk_lock_file, O_CREAT | O_RDWR | O_CLOEXEC, 0600); if (db->lock_fd < 0 && errno == ENOENT && - (dbopts->open_flags & APK_OPENF_CREATE)) { + (ac->open_flags & APK_OPENF_CREATE)) { r = apk_db_create(db); if (r != 0) { msg = "Unable to create database"; @@ -1584,16 +1586,16 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) if (db->lock_fd < 0 || flock(db->lock_fd, LOCK_EX | LOCK_NB) < 0) { msg = "Unable to lock database"; - if (dbopts->lock_wait) { + if (ac->lock_wait) { struct sigaction sa, old_sa; - apk_message("Waiting for repository lock"); + apk_msg(out, "Waiting for repository lock"); memset(&sa, 0, sizeof sa); sa.sa_handler = handle_alarm; sa.sa_flags = SA_ONESHOT; sigaction(SIGALRM, &sa, &old_sa); - alarm(dbopts->lock_wait); + alarm(ac->lock_wait); if (flock(db->lock_fd, LOCK_EX) < 0) goto ret_errno; @@ -1606,7 +1608,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_blob_to_file(db->root_fd, apk_arch_file, *db->arch, APK_BTF_ADD_EOL); /* mount /proc */ - if (asprintf(&db->root_proc_dir, "%s/proc", db->root) == -1) + if (asprintf(&db->root_proc_dir, "%s/proc", db->ctx->root) == -1) goto ret_errno; if (statfs(db->root_proc_dir, &stfs) != 0) { if (errno == ENOENT) mkdir(db->root_proc_dir, 0555); @@ -1628,21 +1630,21 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) add_protected_paths_from_file, db); /* figure out where to have the cache */ - fd = openat(db->root_fd, dbopts->cache_dir, O_RDONLY | O_CLOEXEC); + fd = openat(db->root_fd, ac->cache_dir, O_RDONLY | O_CLOEXEC); if (fd >= 0 && fstatfs(fd, &stfs) == 0) { - db->cache_dir = dbopts->cache_dir; + db->cache_dir = ac->cache_dir; db->cache_fd = fd; db->cache_remount_flags = map_statfs_flags(stfs.f_flags); - if ((dbopts->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) && + if ((ac->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) && (db->cache_remount_flags & MS_RDONLY) != 0) { /* remount cache read/write */ db->cache_remount_dir = find_mountpoint(db->root_fd, db->cache_dir); if (db->cache_remount_dir == NULL) { - apk_warning("Unable to find cache directory mount point"); + apk_warn(out, "Unable to find cache directory mount point"); } else if (mount(0, db->cache_remount_dir, 0, MS_REMOUNT | (db->cache_remount_flags & ~MS_RDONLY), 0) != 0) { free(db->cache_remount_dir); db->cache_remount_dir = NULL; - apk_error("Unable to remount cache read/write"); + apk_err(out, "Unable to remount cache read/write"); r = EROFS; goto ret_r; } @@ -1659,53 +1661,51 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) } } - db->keys_fd = openat(db->root_fd, - dbopts->keys_dir ?: "etc/apk/keys", - O_RDONLY | O_CLOEXEC); + db->keys_fd = openat(db->root_fd, ac->keys_dir, O_RDONLY | O_CLOEXEC); - r = adb_trust_init(&db->trust, dup(db->keys_fd), dbopts->private_keys); + r = adb_trust_init(&db->trust, dup(db->keys_fd), ac->private_keys); if (r) { msg = "Unable to read trusted keys"; goto ret_r; } - if (db->flags & APK_OVERLAY_FROM_STDIN) { - db->flags &= ~APK_OVERLAY_FROM_STDIN; + if (db->ctx->flags & APK_OVERLAY_FROM_STDIN) { + db->ctx->flags &= ~APK_OVERLAY_FROM_STDIN; apk_db_read_overlay(db, apk_istream_from_fd(STDIN_FILENO)); } - r = apk_db_read_state(db, dbopts->open_flags); - if (r == -ENOENT && (dbopts->open_flags & APK_OPENF_CREATE)) { + r = apk_db_read_state(db, ac->open_flags); + if (r == -ENOENT && (ac->open_flags & APK_OPENF_CREATE)) { r = apk_db_create(db); if (r != 0) { msg = "Unable to create database"; goto ret_r; } - r = apk_db_read_state(db, dbopts->open_flags); + r = apk_db_read_state(db, ac->open_flags); } if (r != 0) { msg = "Unable to read database state"; goto ret_r; } - if (!(dbopts->open_flags & APK_OPENF_NO_INSTALLED_REPO)) { + if (!(ac->open_flags & APK_OPENF_NO_INSTALLED_REPO)) { if (apk_db_cache_active(db)) { apk_db_index_read(db, apk_istream_from_file(db->cache_fd, "installed"), -2); } } - if (!(dbopts->open_flags & APK_OPENF_NO_SYS_REPOS)) { + if (!(ac->open_flags & APK_OPENF_NO_SYS_REPOS)) { char **repo; - foreach_array_item(repo, dbopts->repository_list) + foreach_array_item(repo, ac->repository_list) apk_db_add_repository(db, APK_BLOB_STR(*repo)); - if (dbopts->repositories_file == NULL) { + if (ac->repositories_file == NULL) { add_repos_from_file(db, db->root_fd, "etc/apk/repositories"); apk_dir_foreach_file(openat(db->root_fd, "etc/apk/repositories.d", O_RDONLY | O_CLOEXEC), add_repos_from_file, db); } else { - add_repos_from_file(db, AT_FDCWD, dbopts->repositories_file); + add_repos_from_file(db, AT_FDCWD, ac->repositories_file); } if (db->repo_update_counter) @@ -1714,16 +1714,15 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_hash_foreach(&db->available.names, apk_db_name_rdepends, db); } - if (apk_db_cache_active(db) && (dbopts->open_flags & (APK_OPENF_NO_REPOS|APK_OPENF_NO_INSTALLED)) == 0) + if (apk_db_cache_active(db) && (ac->open_flags & (APK_OPENF_NO_REPOS|APK_OPENF_NO_INSTALLED)) == 0) apk_db_cache_foreach_item(db, mark_in_cache); db->open_complete = 1; if (db->compat_newfeatures) { - apk_warning("This apk-tools is OLD! Some packages %s.", - db->compat_notinstallable ? - "are not installable" : - "might not function properly"); + apk_warn(out, + "This apk-tools is OLD! Some packages %s.", + db->compat_notinstallable ? "are not installable" : "might not function properly"); } return 0; @@ -1732,7 +1731,7 @@ ret_errno: r = -errno; ret_r: if (msg != NULL) - apk_error("%s: %s", msg, strerror(-r)); + apk_err(out, "%s: %s", msg, strerror(-r)); apk_db_close(db); return r; @@ -1745,14 +1744,15 @@ struct write_ctx { int apk_db_write_config(struct apk_database *db) { + struct apk_out *out = &db->ctx->out; struct apk_ostream *os; int r; - if ((db->flags & APK_SIMULATE) || db->root == NULL) + if ((db->ctx->flags & APK_SIMULATE) || db->ctx->root == NULL) return 0; if (db->lock_fd == 0) { - apk_error("Refusing to write db without write lock!"); + apk_err(out, "Refusing to write db without write lock!"); return -1; } @@ -1837,16 +1837,10 @@ void apk_db_close(struct apk_database *db) adb_trust_free(&db->trust); - if (db->keys_fd) - close(db->keys_fd); - if (db->cache_fd) - close(db->cache_fd); - if (db->root_fd) - close(db->root_fd); - if (db->lock_fd) - close(db->lock_fd); - if (db->root != NULL) - free(db->root); + if (db->keys_fd) close(db->keys_fd); + if (db->cache_fd) close(db->cache_fd); + if (db->root_fd) close(db->root_fd); + if (db->lock_fd) close(db->lock_fd); } int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag) @@ -1927,6 +1921,7 @@ int apk_db_fire_triggers(struct apk_database *db) int apk_db_run_script(struct apk_database *db, char *fn, char **argv) { + struct apk_out *out = &db->ctx->out; int status; pid_t pid; static char * const environment[] = { @@ -1936,7 +1931,7 @@ int apk_db_run_script(struct apk_database *db, char *fn, char **argv) pid = fork(); if (pid == -1) { - apk_error("%s: fork: %s", basename(fn), strerror(errno)); + apk_err(out, "%s: fork: %s", basename(fn), strerror(errno)); return -2; } if (pid == 0) { @@ -1947,7 +1942,7 @@ int apk_db_run_script(struct apk_database *db, char *fn, char **argv) } waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - apk_error("%s: script exited with error %d", basename(fn), WEXITSTATUS(status)); + apk_err(out, "%s: script exited with error %d", basename(fn), WEXITSTATUS(status)); return -1; } return 0; @@ -1998,7 +1993,7 @@ void apk_db_update_directory_permissions(struct apk_database *db) int apk_db_cache_active(struct apk_database *db) { - return db->cache_dir != apk_static_cache_dir; + return db->ctx->cache_dir != apk_static_cache_dir; } struct foreach_cache_item_ctx { @@ -2052,10 +2047,11 @@ int apk_db_permanent(struct apk_database *db) int apk_db_check_world(struct apk_database *db, struct apk_dependency_array *world) { + struct apk_out *out = &db->ctx->out; struct apk_dependency *dep; int bad = 0, tag; - if (db->force & APK_FORCE_BROKEN_WORLD) + if (db->ctx->force & APK_FORCE_BROKEN_WORLD) return 0; foreach_array_item(dep, world) { @@ -2064,8 +2060,8 @@ int apk_db_check_world(struct apk_database *db, struct apk_dependency_array *wor continue; if (tag < 0) tag = 0; - apk_warning("The repository tag for world dependency '%s" BLOB_FMT "' does not exist", - dep->name->name, BLOB_PRINTF(db->repo_tags[tag].tag)); + apk_warn(out, "The repository tag for world dependency '%s" BLOB_FMT "' does not exist", + dep->name->name, BLOB_PRINTF(db->repo_tags[tag].tag)); bad++; } @@ -2138,14 +2134,15 @@ struct apk_repository *apk_db_select_repo(struct apk_database *db, static int apk_repository_update(struct apk_database *db, struct apk_repository *repo) { + struct apk_out *out = &db->ctx->out; struct apk_url_print urlp; - int r, verify = (db->flags & APK_ALLOW_UNTRUSTED) ? APK_SIGN_NONE : APK_SIGN_VERIFY; + int r, verify = (db->ctx->flags & APK_ALLOW_UNTRUSTED) ? APK_SIGN_NONE : APK_SIGN_VERIFY; r = apk_cache_download(db, repo, NULL, verify, 1, NULL, NULL); if (r == -EALREADY) return 0; if (r != 0) { apk_url_parse(&urlp, repo->url); - apk_error(URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r)); + apk_err(out, URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r)); db->repo_update_errors++; } else { db->repo_update_counter++; @@ -2196,7 +2193,7 @@ static int load_index(struct apk_database *db, struct apk_istream *is, ctx.db = db; ctx.repo = repo; ctx.found = 0; - apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_tar_parse(apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx), load_apkindex, &ctx, &db->id_cache); apk_sign_ctx_free(&ctx.sctx); @@ -2221,6 +2218,7 @@ int apk_db_index_read_file(struct apk_database *db, const char *file, int repo) int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository) { struct apk_database *db = _db.db; + struct apk_out *out = &db->ctx->out; struct apk_repository *repo; struct apk_url_print urlp; apk_blob_t brepo, btag; @@ -2262,11 +2260,11 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository) apk_blob_checksum(brepo, apk_checksum_default(), &repo->csum); if (apk_url_local_file(repo->url) == NULL) { - if (!(db->flags & APK_NO_NETWORK)) + if (!(db->ctx->flags & APK_NO_NETWORK)) db->available_repos |= BIT(repo_num); - if (db->flags & APK_NO_CACHE) { + if (db->ctx->flags & APK_NO_CACHE) { r = apk_repo_format_real_url(db->arch, repo, NULL, buf, sizeof(buf), &urlp); - if (r == 0) apk_message("fetch " URL_FMT, URL_PRINTF(urlp)); + if (r == 0) apk_msg(out, "fetch " URL_FMT, URL_PRINTF(urlp)); } else { if (db->autoupdate) apk_repository_update(db, repo); r = apk_repo_format_cache_index(APK_BLOB_BUF(buf), repo); @@ -2282,7 +2280,7 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository) if (r != 0) { apk_url_parse(&urlp, repo->url); - apk_warning("Ignoring " URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r)); + apk_warn(out, "Ignoring " URL_FMT ": %s", URL_PRINTF(urlp), apk_error_str(r)); db->available_repos &= ~BIT(repo_num); r = 0; } else { @@ -2394,6 +2392,7 @@ static int apk_db_install_archive_entry(void *_ctx, static const char dot1[] = "/./", dot2[] = "/../"; struct install_ctx *ctx = (struct install_ctx *) _ctx; struct apk_database *db = ctx->db; + struct apk_out *out = &db->ctx->out; struct apk_package *pkg = ctx->pkg, *opkg; struct apk_dependency *dep; struct apk_installed_package *ipkg = pkg->ipkg; @@ -2437,8 +2436,8 @@ static int apk_db_install_archive_entry(void *_ctx, strncmp(ae->name, &dot1[1], 2) == 0 || strncmp(ae->name, &dot2[1], 3) == 0 || strstr(ae->name, dot1) || strstr(ae->name, dot2)) { - apk_warning(PKG_VER_FMT": ignoring malicious file %s", - PKG_VER_PRINTF(pkg), ae->name); + apk_warn(out, PKG_VER_FMT": ignoring malicious file %s", + PKG_VER_PRINTF(pkg), ae->name); ipkg->broken_files = 1; return 0; } @@ -2458,8 +2457,8 @@ static int apk_db_install_archive_entry(void *_ctx, diri = ctx->diri = find_diri(ipkg, bdir, diri, &ctx->file_diri_node); if (diri == NULL) { if (!APK_BLOB_IS_NULL(bdir)) { - apk_error(PKG_VER_FMT": "BLOB_FMT": no dirent in archive", - PKG_VER_PRINTF(pkg), BLOB_PRINTF(name)); + apk_err(out, PKG_VER_FMT": "BLOB_FMT": no dirent in archive", + PKG_VER_PRINTF(pkg), BLOB_PRINTF(name)); ipkg->broken_files = 1; return 0; } @@ -2493,8 +2492,8 @@ static int apk_db_install_archive_entry(void *_ctx, } while (0); if (!link_target_file) { - apk_error(PKG_VER_FMT": "BLOB_FMT": no hard link target (%s) in archive", - PKG_VER_PRINTF(pkg), BLOB_PRINTF(name), ae->link_target); + apk_err(out, PKG_VER_FMT": "BLOB_FMT": no hard link target (%s) in archive", + PKG_VER_PRINTF(pkg), BLOB_PRINTF(name), ae->link_target); ipkg->broken_files = 1; return 0; } @@ -2539,14 +2538,14 @@ static int apk_db_install_archive_entry(void *_ctx, if (pkg_prio >= 0) break; - if (!(db->force & APK_FORCE_OVERWRITE)) { - apk_error(PKG_VER_FMT": trying to overwrite %s owned by "PKG_VER_FMT".", - PKG_VER_PRINTF(pkg), ae->name, PKG_VER_PRINTF(opkg)); + if (!(db->ctx->force & APK_FORCE_OVERWRITE)) { + apk_err(out, PKG_VER_FMT": trying to overwrite %s owned by "PKG_VER_FMT".", + PKG_VER_PRINTF(pkg), ae->name, PKG_VER_PRINTF(opkg)); ipkg->broken_files = 1; return 0; } - apk_warning(PKG_VER_FMT": overwriting %s owned by "PKG_VER_FMT".", - PKG_VER_PRINTF(pkg), ae->name, PKG_VER_PRINTF(opkg)); + apk_warn(out, PKG_VER_FMT": overwriting %s owned by "PKG_VER_FMT".", + PKG_VER_PRINTF(pkg), ae->name, PKG_VER_PRINTF(opkg)); } while (0); } @@ -2555,8 +2554,7 @@ static int apk_db_install_archive_entry(void *_ctx, file = apk_db_file_new(diri, bfile, &ctx->file_diri_node); } - if (apk_verbosity >= 3) - apk_message("%s", ae->name); + apk_dbg2(out, "%s", ae->name); /* Extract the file with temporary name */ file->acl = apk_db_acl_atomize(db, ae->mode, ae->uid, ae->gid, &ae->xattr_csum); @@ -2564,7 +2562,7 @@ static int apk_db_install_archive_entry(void *_ctx, db->root_fd, ae, format_tmpname(pkg, file, tmpname_file), format_tmpname(pkg, link_target_file, tmpname_link_target), - is, extract_cb, ctx, db->extract_flags); + is, extract_cb, ctx, db->extract_flags, out); switch (r) { case 0: @@ -2575,9 +2573,10 @@ static int apk_db_install_archive_entry(void *_ctx, memcpy(&file->csum, &ae->csum, sizeof file->csum); /* only warn once per package */ if (file->csum.type == APK_CHECKSUM_NONE && !ctx->missing_checksum) { - apk_warning(PKG_VER_FMT": support for packages without embedded " - "checksums will be dropped in apk-tools 3.", - PKG_VER_PRINTF(pkg)); + apk_warn(out, + PKG_VER_FMT": support for packages without embedded " + "checksums will be dropped in apk-tools 3.", + PKG_VER_PRINTF(pkg)); ipkg->broken_files = 1; ctx->missing_checksum = 1; } @@ -2592,8 +2591,7 @@ static int apk_db_install_archive_entry(void *_ctx, break; } } else { - if (apk_verbosity >= 3) - apk_message("%s (dir)", ae->name); + apk_dbg2(out, "%s (dir)", ae->name); if (name.ptr[name.len-1] == '/') name.len--; @@ -2614,6 +2612,7 @@ static void apk_db_purge_pkg(struct apk_database *db, struct apk_installed_package *ipkg, int is_installed) { + struct apk_out *out = &db->ctx->out; struct apk_db_dir_instance *diri; struct apk_db_file *file; struct apk_db_file_hash_key key; @@ -2637,13 +2636,12 @@ static void apk_db_purge_pkg(struct apk_database *db, }; hash = apk_blob_hash_seed(key.filename, diri->dir->hash); if ((diri->dir->protect_mode == APK_PROTECT_NONE) || - (db->flags & APK_PURGE) || + (db->ctx->flags & APK_PURGE) || (file->csum.type != APK_CHECKSUM_NONE && apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi, &db->atoms) == 0 && apk_checksum_compare(&file->csum, &fi.csum) == 0)) unlinkat(db->root_fd, name, 0); - if (apk_verbosity >= 3) - apk_message("%s", name); + apk_dbg2(out, "%s", name); __hlist_del(fc, &diri->owned_files.first); if (is_installed) { apk_hash_delete_hashed(&db->installed.files, APK_BLOB_BUF(&key), hash); @@ -2659,6 +2657,7 @@ static void apk_db_purge_pkg(struct apk_database *db, static void apk_db_migrate_files(struct apk_database *db, struct apk_installed_package *ipkg) { + struct apk_out *out = &db->ctx->out; struct apk_db_dir_instance *diri; struct apk_db_dir *dir; struct apk_db_file *file, *ofile; @@ -2715,7 +2714,7 @@ static void apk_db_migrate_files(struct apk_database *db, apk_fileinfo_get(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi, &db->atoms); - if ((db->flags & APK_CLEAN_PROTECTED) || + if ((db->ctx->flags & APK_CLEAN_PROTECTED) || (file->csum.type != APK_CHECKSUM_NONE && apk_checksum_compare(&file->csum, &fi.csum) == 0)) { unlinkat(db->root_fd, tmpname, 0); @@ -2725,9 +2724,9 @@ static void apk_db_migrate_files(struct apk_database *db, DIR_FILE_PRINTF(diri->dir, file)); if (renameat(db->root_fd, tmpname, db->root_fd, name) != 0) { - apk_error(PKG_VER_FMT": failed to rename %s to %s.", - PKG_VER_PRINTF(ipkg->pkg), - tmpname, name); + apk_err(out, PKG_VER_FMT": failed to rename %s to %s.", + PKG_VER_PRINTF(ipkg->pkg), + tmpname, name); ipkg->broken_files = 1; } } @@ -2736,8 +2735,8 @@ static void apk_db_migrate_files(struct apk_database *db, /* Overwrite the old file */ if (renameat(db->root_fd, tmpname, db->root_fd, name) != 0) { - apk_error(PKG_VER_FMT": failed to rename %s to %s.", - PKG_VER_PRINTF(ipkg->pkg), tmpname, name); + apk_err(out, PKG_VER_FMT": failed to rename %s to %s.", + PKG_VER_PRINTF(ipkg->pkg), tmpname, name); ipkg->broken_files = 1; } } @@ -2763,6 +2762,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, int upgrade, apk_progress_cb cb, void *cb_ctx, char **script_args) { + struct apk_out *out = &db->ctx->out; struct install_ctx ctx; struct apk_istream *is = NULL, *cache_is; struct apk_repository *repo; @@ -2807,8 +2807,8 @@ static int apk_db_unpack_pkg(struct apk_database *db, if (!IS_ERR_OR_NULL(cache_is)) is = cache_is; else - apk_warning(PKG_VER_FMT": unable to cache: %s", - PKG_VER_PRINTF(pkg), apk_error_str(errno)); + apk_warn(out, PKG_VER_FMT": unable to cache: %s", + PKG_VER_PRINTF(pkg), apk_error_str(errno)); } ctx = (struct install_ctx) { @@ -2821,7 +2821,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, .cb = cb, .cb_ctx = cb_ctx, }; - apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd, db->flags & APK_ALLOW_UNTRUSTED); + apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd, db->ctx->flags & APK_ALLOW_UNTRUSTED); r = apk_tar_parse(apk_istream_gunzip_mpart(is, apk_sign_ctx_mpart_cb, &ctx.sctx), apk_db_install_archive_entry, &ctx, &db->id_cache); apk_sign_ctx_free(&ctx.sctx); @@ -2839,7 +2839,7 @@ static int apk_db_unpack_pkg(struct apk_database *db, apk_db_run_pending_script(&ctx); return 0; err_msg: - apk_error(PKG_VER_FMT": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); + apk_err(out, PKG_VER_FMT": %s", PKG_VER_PRINTF(pkg), apk_error_str(r)); return r; } diff --git a/src/io_archive.c b/src/io_archive.c index 79cfd74..de4741e 100644 --- a/src/io_archive.c +++ b/src/io_archive.c @@ -336,7 +336,8 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, const char *extract_name, const char *link_target, struct apk_istream *is, apk_progress_cb cb, void *cb_ctx, - unsigned int apk_extract_flags) + unsigned int apk_extract_flags, + struct apk_out *out) { struct apk_xattr *xattr; const char *fn = extract_name ?: ae->name; @@ -380,15 +381,15 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, break; } if (ret) { - apk_error("Failed to create %s: %s", ae->name, strerror(-ret)); + apk_err(out, "Failed to create %s: %s", ae->name, strerror(-ret)); return ret; } if (!(apk_extract_flags & APK_EXTRACTF_NO_CHOWN)) { r = fchownat(atfd, fn, ae->uid, ae->gid, atflags); if (r < 0) { - apk_error("Failed to set ownership on %s: %s", - fn, strerror(errno)); + apk_err(out, "Failed to set ownership on %s: %s", + fn, strerror(errno)); if (!ret) ret = -errno; } @@ -396,9 +397,8 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, if (ae->mode & 07000) { r = fchmodat(atfd, fn, ae->mode & 07777, atflags); if (r < 0) { - apk_error("Failed to set file permissions " - "on %s: %s", - fn, strerror(errno)); + apk_err(out, "Failed to set file permissions on %s: %s", + fn, strerror(errno)); if (!ret) ret = -errno; } } @@ -421,8 +421,8 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, } if (r) { if (r != -ENOTSUP) - apk_error("Failed to set xattrs on %s: %s", - fn, strerror(-r)); + apk_err(out, "Failed to set xattrs on %s: %s", + fn, strerror(-r)); if (!ret) ret = r; } } @@ -435,7 +435,7 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae, times[0].tv_nsec = times[1].tv_nsec = 0; r = utimensat(atfd, fn, times, atflags); if (r < 0) { - apk_error("Failed to preserve modification time on %s: %s", + apk_err(out, "Failed to preserve modification time on %s: %s", fn, strerror(errno)); if (!ret || ret == -ENOTSUP) ret = -errno; } diff --git a/src/lua-apk.c b/src/lua-apk.c index 6cd0208..10d34eb 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -140,7 +140,7 @@ static int get_boolean_field(lua_State *L, int index, const char *key) return value; } -static int get_dbopts(lua_State *L, int i, struct apk_db_options *o) +static int get_ctx(lua_State *L, int i, struct apk_ctx *o) { struct flagmap *f; o->root = (char *)get_opt_string_field(L, i, "root", NULL); @@ -165,14 +165,14 @@ static struct apk_database *checkdb(lua_State *L, int index) static int Papk_db_open(lua_State *L) { - struct apk_db_options opts; + struct apk_ctx opts; struct apk_database *db; int r; memset(&opts, 0, sizeof(opts)); apk_string_array_init(&opts.repository_list); if (lua_istable(L, 1)) - get_dbopts(L, 1, &opts); + get_ctx(L, 1, &opts); else opts.open_flags |= APK_OPENF_READ; diff --git a/src/meson.build b/src/meson.build index f2b8cc9..4f3d435 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,6 +7,7 @@ libapk_src = [ 'blob.c', 'commit.c', 'common.c', + 'context.c', 'database.c', 'hash.c', 'io.c', @@ -63,7 +64,7 @@ apk_src = [ 'app_verify.c', 'app_version.c', 'app_vertest.c', - 'help.c', + 'applet.c', ] if lua_bin.found() diff --git a/src/package.c b/src/package.c index 8376275..b63fae0 100644 --- a/src/package.c +++ b/src/package.c @@ -908,8 +908,9 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae, while (!APK_BLOB_IS_NULL(l = apk_istream_get_delim(is, token))) read_info_line(ctx, l); } else if (strcmp(ae->name, ".INSTALL") == 0) { - apk_warning("Package '%s-%s' contains deprecated .INSTALL", - pkg->name->name, pkg->version); + apk_warn(&ri->db->ctx->out, + "Package '%s-%s' contains deprecated .INSTALL", + pkg->name->name, pkg->version); } return 0; @@ -1004,6 +1005,7 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg, struct apk_database *db, unsigned int type, char **argv) { + struct apk_out *out = &db->ctx->out; struct apk_package *pkg = ipkg->pkg; char fn[PATH_MAX]; int fd, root_fd = db->root_fd; @@ -1018,10 +1020,10 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg, PKG_VER_PRINTF(pkg), apk_script_types[type]); - if ((db->flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0) + if ((db->ctx->flags & (APK_NO_SCRIPTS | APK_SIMULATE)) != 0) return; - apk_message("Executing %s", &fn[15]); + apk_msg(out, "Executing %s", &fn[15]); fd = openat(root_fd, fn, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0755); if (fd < 0) { mkdirat(root_fd, "var/cache/misc", 0755); @@ -1043,7 +1045,7 @@ void apk_ipkg_run_script(struct apk_installed_package *ipkg, goto cleanup; err_log: - apk_error("%s: failed to execute: %s", &fn[15], apk_error_str(errno)); + apk_err(out, "%s: failed to execute: %s", &fn[15], apk_error_str(errno)); err: ipkg->broken_script = 1; cleanup: @@ -1063,6 +1065,7 @@ static int parse_index_line(void *ctx, apk_blob_t line) struct apk_package *apk_pkg_parse_index_entry(struct apk_database *db, apk_blob_t blob) { + struct apk_out *out = &db->ctx->out; struct read_info_ctx ctx; ctx.pkg = apk_pkg_new(); @@ -1075,8 +1078,7 @@ struct apk_package *apk_pkg_parse_index_entry(struct apk_database *db, apk_blob_ if (ctx.pkg->name == NULL) { apk_pkg_free(ctx.pkg); - apk_error("Failed to parse index entry: " BLOB_FMT, - BLOB_PRINTF(blob)); + apk_err(out, "Failed to parse index entry: " BLOB_FMT, BLOB_PRINTF(blob)); ctx.pkg = NULL; } @@ -1143,18 +1145,15 @@ int apk_pkg_write_index_entry(struct apk_package *info, } apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); - if (APK_BLOB_IS_NULL(bbuf)) { - apk_error("Metadata for package " PKG_VER_FMT " is too long.", - PKG_VER_PRINTF(info)); - return -ENOBUFS; - } + if (APK_BLOB_IS_NULL(bbuf)) + return apk_ostream_cancel(os, -ENOBUFS); bbuf = apk_blob_pushed(APK_BLOB_BUF(buf), bbuf); if (apk_ostream_write(os, bbuf.ptr, bbuf.len) != bbuf.len || write_depends(os, "D:", info->depends) || write_depends(os, "p:", info->provides) || write_depends(os, "i:", info->install_if)) - return -EIO; + return apk_ostream_cancel(os, -EIO); return 0; } diff --git a/src/print.c b/src/print.c index 84c8ed1..829f7f5 100644 --- a/src/print.c +++ b/src/print.c @@ -19,43 +19,125 @@ #include "apk_defines.h" #include "apk_print.h" -static int apk_screen_width = 0; -static int apk_progress_force = 1; -static const char *apk_size_units[] = {"B", "KiB", "MiB", "GiB", "TiB"}; - -void apk_reset_screen_width(void) -{ - apk_screen_width = 0; - apk_progress_force = 1; -} - -int apk_get_screen_width(void) +const char *apk_error_str(int error) { - struct winsize w; - - if (apk_screen_width == 0) { - apk_screen_width = 50; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0 && - w.ws_col > 25) - apk_screen_width = w.ws_col; + if (error < 0) + error = -error; + switch (error) { + case ENOKEY: + return "UNTRUSTED signature"; + case EKEYREJECTED: + return "BAD signature"; + case EIO: + return "IO ERROR"; + case EBADMSG: + return "BAD archive"; + case ENOMSG: + return "archive does not contain expected data"; + case ENOPKG: + return "could not find a repo which provides this package (check repositories file and run 'apk update')"; + case ECONNABORTED: + return "network connection aborted"; + case ECONNREFUSED: + return "could not connect to server (check repositories file)"; + case ENETUNREACH: + return "network error (check Internet connection and firewall)"; + case ENXIO: + return "DNS lookup error"; + case EREMOTEIO: + return "remote server returned error (try 'apk update')"; + case ETIMEDOUT: + return "operation timed out"; + case EAGAIN: + return "temporary error (try again later)"; + case EAPKBADURL: + return "invalid URL (check your repositories file)"; + case EAPKSTALEINDEX: + return "package mentioned in index not found (try 'apk update')"; + case EAPKFORMAT: + return "package file format error"; + case EAPKDEPFORMAT: + return "package dependency format error"; + default: + return strerror(error); } - - return apk_screen_width; } const char *apk_get_human_size(off_t size, off_t *dest) { + static const char *size_units[] = {"B", "KiB", "MiB", "GiB", "TiB"}; size_t i; off_t s; assert(size >= 0); - for (i = 0, s = size; s >= 10000 && - i < ARRAY_SIZE(apk_size_units); i++) + for (i = 0, s = size; s >= 10000 && i < ARRAY_SIZE(size_units); i++) s /= 1024; if (dest) *dest = s; - return apk_size_units[min(i, ARRAY_SIZE(apk_size_units) - 1)]; + return size_units[min(i, ARRAY_SIZE(size_units) - 1)]; +} + +void apk_url_parse(struct apk_url_print *urlp, const char *url) +{ + const char *authority, *path_or_host, *pw; + + *urlp = (struct apk_url_print) { + .url = "", + .pwmask = "", + .url_or_host = url, + }; + + if (!(authority = strstr(url, "://"))) return; + authority += 3; + path_or_host = strpbrk(authority, "/@"); + if (!path_or_host || *path_or_host == '/') return; + pw = strpbrk(authority, "@:"); + if (!pw || *pw == '@') return; + *urlp = (struct apk_url_print) { + .url = url, + .pwmask = "*", + .url_or_host = path_or_host, + .len_before_pw = pw - url + 1, + }; +} + +void apk_out_reset(struct apk_out *out) +{ + out->width = 0; + out->last_change++; +} + +static int apk_out_get_width(struct apk_out *out) +{ + struct winsize w; + + if (out->width == 0) { + out->width = 50; + if (ioctl(fileno(out->out), TIOCGWINSZ, &w) == 0 && + w.ws_col > 25) + out->width = w.ws_col; + } + + return out->width; +} + +static void log_internal(FILE *dest, const char *prefix, const char *format, va_list va) +{ + if (dest != stdout) fflush(stdout); + if (prefix != NULL) fprintf(dest, "%s", prefix); + vfprintf(dest, format, va); + fprintf(dest, "\n"); + fflush(dest); +} + +void apk_out_fmt(struct apk_out *out, const char *prefix, const char *format, ...) +{ + va_list va; + va_start(va, format); + log_internal(prefix ? out->err : out->out, prefix, format, va); + out->last_change++; + va_end(va); } void apk_print_progress(struct apk_progress *p, size_t done, size_t total) @@ -64,31 +146,31 @@ void apk_print_progress(struct apk_progress *p, size_t done, size_t total) int bar = 0; char buf[64]; /* enough for petabytes... */ int i, percent = 0; - FILE *out = p->out; - - if (p->last_done == done && !apk_progress_force) - return; + FILE *out; + if (p->last_done == done && (!p->out || p->last_out_change == p->out->last_change)) return; if (p->fd != 0) { i = snprintf(buf, sizeof(buf), "%zu/%zu\n", done, total); write(p->fd, buf, i); } p->last_done = done; + if (!p->out) return; + out = p->out->out; if (!out) return; - bar_width = apk_get_screen_width() - 6; + bar_width = apk_out_get_width(p->out) - 6; if (total > 0) { bar = muldiv(bar_width, done, total); percent = muldiv(100, done, total); } - if (bar == p->last_bar && percent == p->last_percent && !apk_progress_force) + if (bar == p->last_bar && percent == p->last_percent && p->last_out_change == p->out->last_change) return; p->last_bar = bar; p->last_percent = percent; - apk_progress_force = 0; + p->last_out_change = p->out->last_change; fprintf(out, "\e7%3i%% ", percent); @@ -103,13 +185,14 @@ void apk_print_progress(struct apk_progress *p, size_t done, size_t total) int apk_print_indented(struct apk_indent *i, apk_blob_t blob) { + FILE *out = i->out->out; if (i->x <= i->indent) - i->x += printf("%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); - else if (i->x + blob.len + 1 >= apk_get_screen_width()) - i->x = printf("\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; + i->x += fprintf(out, "%*s" BLOB_FMT, i->indent - i->x, "", BLOB_PRINTF(blob)); + else if (i->x + blob.len + 1 >= apk_out_get_width(i->out)) + i->x = fprintf(out, "\n%*s" BLOB_FMT, i->indent, "", BLOB_PRINTF(blob)) - 1; else - i->x += printf(" " BLOB_FMT, BLOB_PRINTF(blob)); - apk_progress_force = 1; + i->x += fprintf(out, " " BLOB_FMT, BLOB_PRINTF(blob)); + i->out->last_change++; return 0; } @@ -130,99 +213,3 @@ void apk_print_indented_fmt(struct apk_indent *i, const char *fmt, ...) apk_print_indented(i, APK_BLOB_PTR_LEN(tmp, n)); va_end(va); } - -const char *apk_error_str(int error) -{ - if (error < 0) - error = -error; - switch (error) { - case ENOKEY: - return "UNTRUSTED signature"; - case EKEYREJECTED: - return "BAD signature"; - case EIO: - return "IO ERROR"; - case EBADMSG: - return "BAD archive"; - case ENOMSG: - return "archive does not contain expected data"; - case ENOPKG: - return "could not find a repo which provides this package (check repositories file and run 'apk update')"; - case ECONNABORTED: - return "network connection aborted"; - case ECONNREFUSED: - return "could not connect to server (check repositories file)"; - case ENETUNREACH: - return "network error (check Internet connection and firewall)"; - case ENXIO: - return "DNS lookup error"; - case EREMOTEIO: - return "remote server returned error (try 'apk update')"; - case ETIMEDOUT: - return "operation timed out"; - case EAGAIN: - return "temporary error (try again later)"; - case EAPKBADURL: - return "invalid URL (check your repositories file)"; - case EAPKSTALEINDEX: - return "package mentioned in index not found (try 'apk update')"; - case EAPKFORMAT: - return "package file format error"; - case EAPKDEPFORMAT: - return "package dependency format error"; - default: - return strerror(error); - } -} - -static void log_internal(FILE *dest, const char *prefix, const char *format, va_list va) -{ - if (dest != stdout) - fflush(stdout); - if (prefix != NULL) - fprintf(dest, "%s", prefix); - vfprintf(dest, format, va); - fprintf(dest, "\n"); - fflush(dest); - apk_progress_force = 1; -} - -void apk_log(const char *prefix, const char *format, ...) -{ - va_list va; - va_start(va, format); - log_internal(stdout, prefix, format, va); - va_end(va); -} - -void apk_log_err(const char *prefix, const char *format, ...) -{ - va_list va; - va_start(va, format); - log_internal(stderr, prefix, format, va); - va_end(va); -} - -void apk_url_parse(struct apk_url_print *urlp, const char *url) -{ - const char *authority, *path_or_host, *pw; - - *urlp = (struct apk_url_print) { - .url = "", - .pwmask = "", - .url_or_host = url, - }; - - if (!(authority = strstr(url, "://"))) return; - authority += 3; - path_or_host = strpbrk(authority, "/@"); - if (!path_or_host || *path_or_host == '/') return; - pw = strpbrk(authority, "@:"); - if (!pw || *pw == '@') return; - *urlp = (struct apk_url_print) { - .url = url, - .pwmask = "*", - .url_or_host = path_or_host, - .len_before_pw = pw - url + 1, - }; -} diff --git a/src/solver.c b/src/solver.c index be9240a..faa20b0 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1097,7 +1097,7 @@ restart: generate_changeset(ss, world); - if (ss->errors && (db->force & APK_FORCE_BROKEN_WORLD)) { + if (ss->errors && (db->ctx->force & APK_FORCE_BROKEN_WORLD)) { foreach_array_item(d, world) { name = d->name; pkg = name->ss.chosen.pkg; |