Commit 354713d2 authored by Timo Teräs's avatar Timo Teräs

rename apk_db_options to apk_ctx, rework logging

makes apk_verbosity non-global

fixes #10682
parent 7a7eca86
......@@ -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 \
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
/* 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
......@@ -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)