2008-04-17 14:09:13 +00:00
|
|
|
/* apk.c - Alpine Package Keeper (APK)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
|
2011-09-13 08:53:01 +00:00
|
|
|
* Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi>
|
2008-04-17 14:09:13 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2009-06-25 12:14:07 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
2008-04-17 14:09:13 +00:00
|
|
|
* under the terms of the GNU General Public License version 2 as published
|
|
|
|
* by the Free Software Foundation. See http://www.gnu.org/ for details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2008-04-22 08:16:26 +00:00
|
|
|
#include <fcntl.h>
|
2009-01-13 12:09:45 +00:00
|
|
|
#include <ctype.h>
|
2010-06-30 13:53:56 +00:00
|
|
|
#include <errno.h>
|
2020-05-04 18:45:11 +00:00
|
|
|
#include <assert.h>
|
2011-07-22 09:08:35 +00:00
|
|
|
#include <signal.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
#include <stdarg.h>
|
2008-04-21 16:30:10 +00:00
|
|
|
#include <stdlib.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
#include <string.h>
|
2008-04-21 16:30:10 +00:00
|
|
|
#include <getopt.h>
|
2011-03-16 13:22:05 +00:00
|
|
|
#include <unistd.h>
|
2008-04-21 16:30:10 +00:00
|
|
|
#include <sys/stat.h>
|
2008-04-17 14:09:13 +00:00
|
|
|
|
2010-06-30 13:53:56 +00:00
|
|
|
#include <openssl/crypto.h>
|
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
2009-07-08 13:19:06 +00:00
|
|
|
#include <openssl/engine.h>
|
2010-06-30 13:53:56 +00:00
|
|
|
#endif
|
2009-07-08 13:19:06 +00:00
|
|
|
|
2014-10-08 07:10:45 +00:00
|
|
|
#include <fetch.h>
|
|
|
|
|
2008-04-17 14:09:13 +00:00
|
|
|
#include "apk_defines.h"
|
2009-08-06 11:25:03 +00:00
|
|
|
#include "apk_database.h"
|
2008-04-17 14:09:13 +00:00
|
|
|
#include "apk_applet.h"
|
2009-06-25 12:14:07 +00:00
|
|
|
#include "apk_blob.h"
|
2010-03-05 08:13:25 +00:00
|
|
|
#include "apk_print.h"
|
2012-02-23 20:02:11 +00:00
|
|
|
#include "apk_io.h"
|
2008-04-21 16:30:10 +00:00
|
|
|
|
2014-05-12 16:42:32 +00:00
|
|
|
static struct list_head apk_applet_list;
|
|
|
|
#define foreach_applet(iter) list_for_each_entry(iter, &apk_applet_list, node)
|
|
|
|
|
2014-12-08 06:30:35 +00:00
|
|
|
#ifdef TEST_MODE
|
|
|
|
static const char *test_installed_db = NULL;
|
|
|
|
static const char *test_world = NULL;
|
|
|
|
static struct apk_string_array *test_repos;
|
|
|
|
#endif
|
|
|
|
|
2011-01-01 13:48:10 +00:00
|
|
|
char **apk_argv;
|
|
|
|
|
2019-06-03 13:18:29 +00:00
|
|
|
#ifdef TEST_MODE
|
2020-02-04 08:31:10 +00:00
|
|
|
time_t time(time_t *tloc)
|
|
|
|
{
|
|
|
|
const time_t val = 1559567666;
|
|
|
|
if (tloc) *tloc = val;
|
|
|
|
return val;
|
2019-06-03 13:18:29 +00:00
|
|
|
}
|
2020-02-04 08:31:10 +00:00
|
|
|
#endif
|
2019-06-03 13:18:29 +00:00
|
|
|
|
2014-10-08 12:29:27 +00:00
|
|
|
static void version(void)
|
|
|
|
{
|
|
|
|
printf("apk-tools " APK_VERSION ", compiled for " APK_DEFAULT_ARCH ".\n"
|
|
|
|
#ifdef TEST_MODE
|
|
|
|
"TEST MODE BUILD. NOT FOR PRODUCTION USE.\n"
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct apk_repository_list *apk_repository_new(const char *url)
|
|
|
|
{
|
|
|
|
struct apk_repository_list *r = calloc(1, sizeof(struct apk_repository_list));
|
|
|
|
if (r) {
|
|
|
|
r->url = url;
|
|
|
|
list_init(&r->list);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
enum {
|
|
|
|
OPT_GLOBAL_allow_untrusted,
|
|
|
|
OPT_GLOBAL_arch,
|
|
|
|
OPT_GLOBAL_cache_dir,
|
|
|
|
OPT_GLOBAL_cache_max_age,
|
|
|
|
OPT_GLOBAL_force,
|
|
|
|
OPT_GLOBAL_force_binary_stdout,
|
|
|
|
OPT_GLOBAL_force_broken_world,
|
|
|
|
OPT_GLOBAL_force_non_repository,
|
|
|
|
OPT_GLOBAL_force_old_apk,
|
|
|
|
OPT_GLOBAL_force_overwrite,
|
|
|
|
OPT_GLOBAL_force_refresh,
|
|
|
|
OPT_GLOBAL_help,
|
|
|
|
OPT_GLOBAL_interactive,
|
|
|
|
OPT_GLOBAL_keys_dir,
|
|
|
|
OPT_GLOBAL_no_cache,
|
|
|
|
OPT_GLOBAL_no_network,
|
|
|
|
OPT_GLOBAL_no_progress,
|
|
|
|
OPT_GLOBAL_print_arch,
|
|
|
|
OPT_GLOBAL_progress,
|
|
|
|
OPT_GLOBAL_progress_fd,
|
|
|
|
OPT_GLOBAL_purge,
|
|
|
|
OPT_GLOBAL_quiet,
|
|
|
|
OPT_GLOBAL_repositories_file,
|
|
|
|
OPT_GLOBAL_repository,
|
|
|
|
OPT_GLOBAL_root,
|
|
|
|
OPT_GLOBAL_update_cache,
|
|
|
|
OPT_GLOBAL_verbose,
|
|
|
|
OPT_GLOBAL_version,
|
|
|
|
OPT_GLOBAL_wait,
|
|
|
|
#ifdef TEST_MODE
|
|
|
|
OPT_GLOBAL_test_instdb,
|
|
|
|
OPT_GLOBAL_test_repo,
|
|
|
|
OPT_GLOBAL_test_world,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char optiondesc_global[] =
|
|
|
|
APK_OPTGROUP("Global")
|
|
|
|
APK_OPT1n("allow-untrusted")
|
|
|
|
APK_OPT1R("arch")
|
|
|
|
APK_OPT1R("cache-dir")
|
|
|
|
APK_OPT1R("cache-max-age")
|
|
|
|
APK_OPT2n("force", "f")
|
|
|
|
APK_OPT1n("force-binary-stdout")
|
|
|
|
APK_OPT1n("force-broken-world")
|
|
|
|
APK_OPT1n("force-non-repository")
|
|
|
|
APK_OPT1n("force-old-apk")
|
|
|
|
APK_OPT1n("force-overwrite")
|
|
|
|
APK_OPT1n("force-refresh")
|
|
|
|
APK_OPT2n("help", "h")
|
|
|
|
APK_OPT2n("interactive", "i")
|
|
|
|
APK_OPT1R("keys-dir")
|
|
|
|
APK_OPT1n("no-cache")
|
|
|
|
APK_OPT1n("no-network")
|
|
|
|
APK_OPT1n("no-progress")
|
|
|
|
APK_OPT1n("print-arch")
|
|
|
|
APK_OPT1n("progress")
|
|
|
|
APK_OPT1R("progress-fd")
|
|
|
|
APK_OPT1n("purge")
|
|
|
|
APK_OPT2n("quiet", "q")
|
|
|
|
APK_OPT1R("repositories-file")
|
|
|
|
APK_OPT2R("repository", "X")
|
|
|
|
APK_OPT2R("root", "p")
|
|
|
|
APK_OPT2n("update-cache", "U")
|
|
|
|
APK_OPT2n("verbose", "v")
|
|
|
|
APK_OPT2n("version", "V")
|
|
|
|
APK_OPT1R("wait")
|
|
|
|
#ifdef TEST_MODE
|
|
|
|
APK_OPT1R("test-instdb")
|
|
|
|
APK_OPT1R("test-repo")
|
|
|
|
APK_OPT1R("test-world")
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
|
|
|
|
static int option_parse_global(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
|
2014-10-08 12:29:27 +00:00
|
|
|
{
|
|
|
|
struct apk_repository_list *repo;
|
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
switch (opt) {
|
|
|
|
case OPT_GLOBAL_help:
|
|
|
|
return -EINVAL;
|
|
|
|
case OPT_GLOBAL_root:
|
2014-10-08 12:29:27 +00:00
|
|
|
dbopts->root = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_keys_dir:
|
2014-10-08 12:29:27 +00:00
|
|
|
dbopts->keys_dir = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_repositories_file:
|
2014-10-08 12:29:27 +00:00
|
|
|
dbopts->repositories_file = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_repository:
|
2014-10-08 12:29:27 +00:00
|
|
|
repo = apk_repository_new(optarg);
|
|
|
|
if (repo) list_add(&repo->list, &dbopts->repository_list);
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_quiet:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_verbosity--;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_verbose:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_verbosity++;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_version:
|
2014-10-08 12:29:27 +00:00
|
|
|
version();
|
|
|
|
return -ESHUTDOWN;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK
|
|
|
|
| APK_FORCE_BROKEN_WORLD | APK_FORCE_NON_REPOSITORY
|
|
|
|
| APK_FORCE_BINARY_STDOUT;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_overwrite:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_OVERWRITE;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_old_apk:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_OLD_APK;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_broken_world:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_BROKEN_WORLD;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_refresh:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_REFRESH;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_non_repository:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_NON_REPOSITORY;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_force_binary_stdout:
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_force |= APK_FORCE_BINARY_STDOUT;
|
2014-10-08 12:29:27 +00:00
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_interactive:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_INTERACTIVE;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_progress:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_PROGRESS;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_no_progress:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags &= ~APK_PROGRESS;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_progress_fd:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_progress_fd = atoi(optarg);
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_allow_untrusted:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_ALLOW_UNTRUSTED;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_purge:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_PURGE;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_wait:
|
2014-10-08 12:29:27 +00:00
|
|
|
dbopts->lock_wait = atoi(optarg);
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_no_network:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_NO_NETWORK;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_no_cache:
|
2015-12-07 10:41:13 +00:00
|
|
|
apk_flags |= APK_NO_CACHE;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_cache_dir:
|
2017-02-27 09:12:42 +00:00
|
|
|
dbopts->cache_dir = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_update_cache:
|
2018-01-04 07:46:03 +00:00
|
|
|
/* Make it one minute, to avoid updating indexes twice
|
|
|
|
* when doing self-upgrade's re-exec */
|
|
|
|
dbopts->cache_max_age = 60;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_cache_max_age:
|
2018-01-04 07:46:03 +00:00
|
|
|
dbopts->cache_max_age = atoi(optarg) * 60;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_arch:
|
2014-10-08 12:29:27 +00:00
|
|
|
dbopts->arch = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_print_arch:
|
2014-10-08 12:29:27 +00:00
|
|
|
puts(APK_DEFAULT_ARCH);
|
|
|
|
return -ESHUTDOWN;
|
|
|
|
#ifdef TEST_MODE
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_test_repo:
|
2014-10-08 12:29:27 +00:00
|
|
|
*apk_string_array_add(&test_repos) = (char*) optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_test_instdb:
|
2014-10-08 12:29:27 +00:00
|
|
|
test_installed_db = optarg;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_GLOBAL_test_world:
|
2014-10-08 12:29:27 +00:00
|
|
|
test_world = optarg;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct apk_option_group optgroup_global = {
|
2020-05-04 18:45:11 +00:00
|
|
|
.desc = optiondesc_global,
|
2014-10-08 12:29:27 +00:00
|
|
|
.parse = option_parse_global,
|
|
|
|
};
|
2008-04-17 14:09:13 +00:00
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
enum {
|
|
|
|
OPT_COMMIT_clean_protected,
|
|
|
|
OPT_COMMIT_initramfs_diskless_boot,
|
|
|
|
OPT_COMMIT_no_commit_hooks,
|
|
|
|
OPT_COMMIT_no_scripts,
|
|
|
|
OPT_COMMIT_overlay_from_stdin,
|
|
|
|
OPT_COMMIT_simulate,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char optiondesc_commit[] =
|
|
|
|
APK_OPTGROUP("commit")
|
|
|
|
APK_OPT1n("clean-protected")
|
|
|
|
APK_OPT1n("initramfs-diskless-boot")
|
|
|
|
APK_OPT1n("no-commit-hooks")
|
|
|
|
APK_OPT1n("no-scripts")
|
|
|
|
APK_OPT1n("overlay-from-stdin")
|
|
|
|
APK_OPT2n("simulate", "s");
|
|
|
|
|
|
|
|
static int option_parse_commit(void *ctx, struct apk_db_options *dbopts, int opt, const char *optarg)
|
2014-01-06 09:51:17 +00:00
|
|
|
{
|
2020-05-04 18:45:11 +00:00
|
|
|
switch (opt) {
|
|
|
|
case OPT_COMMIT_simulate:
|
2018-11-15 10:03:51 +00:00
|
|
|
apk_flags |= APK_SIMULATE;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_COMMIT_clean_protected:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_CLEAN_PROTECTED;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_COMMIT_overlay_from_stdin:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_OVERLAY_FROM_STDIN;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_COMMIT_no_scripts:
|
2014-10-08 12:29:27 +00:00
|
|
|
apk_flags |= APK_NO_SCRIPTS;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_COMMIT_no_commit_hooks:
|
2017-12-29 20:10:44 +00:00
|
|
|
apk_flags |= APK_NO_COMMIT_HOOKS;
|
|
|
|
break;
|
2020-05-04 18:45:11 +00:00
|
|
|
case OPT_COMMIT_initramfs_diskless_boot:
|
2018-01-03 09:31:34 +00:00
|
|
|
dbopts->open_flags |= APK_OPENF_CREATE;
|
2018-01-03 13:17:11 +00:00
|
|
|
apk_flags |= APK_NO_COMMIT_HOOKS;
|
|
|
|
apk_force |= APK_FORCE_OVERWRITE | APK_FORCE_OLD_APK
|
|
|
|
| APK_FORCE_BROKEN_WORLD | APK_FORCE_NON_REPOSITORY;
|
2018-01-03 09:31:34 +00:00
|
|
|
break;
|
2014-10-08 12:29:27 +00:00
|
|
|
default:
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
2014-01-06 09:51:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-10-08 12:29:27 +00:00
|
|
|
const struct apk_option_group optgroup_commit = {
|
2020-05-04 18:45:11 +00:00
|
|
|
.desc = optiondesc_commit,
|
2014-10-08 12:29:27 +00:00
|
|
|
.parse = option_parse_commit,
|
|
|
|
};
|
|
|
|
|
2009-06-25 12:14:07 +00:00
|
|
|
static int usage(struct apk_applet *applet)
|
|
|
|
{
|
2009-06-19 13:40:37 +00:00
|
|
|
version();
|
2020-04-24 08:49:14 +00:00
|
|
|
apk_help(applet);
|
2008-04-17 14:09:13 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-04-21 16:30:10 +00:00
|
|
|
static struct apk_applet *find_applet(const char *name)
|
|
|
|
{
|
2014-05-12 16:42:32 +00:00
|
|
|
struct apk_applet *a;
|
2008-04-21 16:30:10 +00:00
|
|
|
|
2014-05-12 16:42:32 +00:00
|
|
|
foreach_applet(a) {
|
|
|
|
if (strcmp(name, a->name) == 0)
|
|
|
|
return a;
|
2008-04-21 16:30:10 +00:00
|
|
|
}
|
2009-06-25 12:14:07 +00:00
|
|
|
|
2008-04-21 16:30:10 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
static struct apk_applet *deduce_applet(int argc, char **argv)
|
2008-04-17 14:09:13 +00:00
|
|
|
{
|
2009-01-13 12:09:45 +00:00
|
|
|
struct apk_applet *a;
|
2008-04-21 16:30:10 +00:00
|
|
|
const char *prog;
|
2009-01-13 12:09:45 +00:00
|
|
|
int i;
|
2008-04-17 14:09:13 +00:00
|
|
|
|
|
|
|
prog = strrchr(argv[0], '/');
|
|
|
|
if (prog == NULL)
|
|
|
|
prog = argv[0];
|
|
|
|
else
|
|
|
|
prog++;
|
|
|
|
|
2008-04-21 16:30:10 +00:00
|
|
|
if (strncmp(prog, "apk_", 4) == 0)
|
2009-01-13 12:09:45 +00:00
|
|
|
return find_applet(prog + 4);
|
|
|
|
|
|
|
|
for (i = 1; i < argc; i++) {
|
2020-05-04 18:45:11 +00:00
|
|
|
if (argv[i][0] == '-') continue;
|
2009-01-13 12:09:45 +00:00
|
|
|
a = find_applet(argv[i]);
|
2020-05-04 18:45:11 +00:00
|
|
|
if (a) return a;
|
2009-01-13 12:09:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
static int parse_options(int argc, char **argv, struct apk_applet *applet, void *ctx, struct apk_db_options *dbopts)
|
2009-06-25 12:14:07 +00:00
|
|
|
{
|
2020-05-04 18:45:11 +00:00
|
|
|
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;
|
|
|
|
char short_options[256], *sopt;
|
|
|
|
unsigned short short_option_val[64];
|
|
|
|
int r, p, help_requested = 0, num_short;
|
|
|
|
|
|
|
|
memset(short_option_val, 0, sizeof short_option_val);
|
2009-06-25 12:14:07 +00:00
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
if (applet && applet->optgroups[0]) optgroups = applet->optgroups;
|
|
|
|
|
|
|
|
for (p = 0, opt = &all_options[0], sopt = short_options; (og = optgroups[p]) != 0; p++) {
|
|
|
|
assert(opt < &all_options[ARRAY_SIZE(all_options)]);
|
|
|
|
assert(sopt < &short_options[sizeof short_options]);
|
|
|
|
const char *d = og->desc + strlen(og->desc) + 1;
|
|
|
|
for (r = 0; *d; r++) {
|
|
|
|
opt->val = (p << 10) + r;
|
|
|
|
opt->flag = 0;
|
|
|
|
opt->has_arg = no_argument;
|
|
|
|
if ((unsigned char)*d == 0xaf) {
|
|
|
|
opt->has_arg = required_argument;
|
|
|
|
d++;
|
|
|
|
}
|
|
|
|
num_short = 1;
|
|
|
|
if ((unsigned char)*d >= 0xf0)
|
|
|
|
num_short = *d++ & 0x0f;
|
|
|
|
for (; num_short > 0; num_short--) {
|
|
|
|
assert(*d >= 64 && *d < 128);
|
|
|
|
short_option_val[*d - 64] = opt->val;
|
|
|
|
*sopt++ = *d++;
|
|
|
|
if (opt->has_arg != no_argument)
|
|
|
|
*sopt++ = ':';
|
|
|
|
}
|
|
|
|
opt->name = d;
|
|
|
|
opt++;
|
|
|
|
d += strlen(d) + 1;
|
|
|
|
}
|
2009-06-25 12:14:07 +00:00
|
|
|
}
|
2020-05-04 18:45:11 +00:00
|
|
|
opt->name = 0;
|
|
|
|
*sopt = 0;
|
|
|
|
|
|
|
|
r = 0;
|
|
|
|
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);
|
|
|
|
if (r == 0) continue;
|
|
|
|
if (r == -EINVAL) {
|
|
|
|
help_requested = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (r != -ENOTSUP) return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (help_requested || r == -ENOTSUP)
|
|
|
|
return usage(applet);
|
|
|
|
|
|
|
|
if (applet == NULL) {
|
|
|
|
if (argc > 1) {
|
|
|
|
apk_error("'%s' is not an apk command. See 'apk --help'.", argv[1]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return usage(NULL);
|
|
|
|
}
|
|
|
|
return 0;
|
2009-06-25 12:14:07 +00:00
|
|
|
}
|
2009-01-13 12:09:45 +00:00
|
|
|
|
2009-07-08 13:19:06 +00:00
|
|
|
static void fini_openssl(void)
|
|
|
|
{
|
|
|
|
EVP_cleanup();
|
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
|
|
|
ENGINE_cleanup();
|
|
|
|
#endif
|
|
|
|
CRYPTO_cleanup_all_ex_data();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_openssl(void)
|
|
|
|
{
|
|
|
|
atexit(fini_openssl);
|
|
|
|
OpenSSL_add_all_algorithms();
|
|
|
|
#ifndef OPENSSL_NO_ENGINE
|
|
|
|
ENGINE_load_builtin_engines();
|
2009-07-13 11:28:52 +00:00
|
|
|
ENGINE_register_all_complete();
|
2009-07-08 13:19:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-07-22 09:08:35 +00:00
|
|
|
static void on_sigwinch(int s)
|
2011-03-19 13:20:47 +00:00
|
|
|
{
|
2011-07-22 09:08:35 +00:00
|
|
|
apk_reset_screen_width();
|
|
|
|
}
|
2011-03-19 13:20:47 +00:00
|
|
|
|
2011-07-22 09:08:35 +00:00
|
|
|
static void setup_terminal(void)
|
|
|
|
{
|
|
|
|
signal(SIGWINCH, on_sigwinch);
|
2012-09-20 12:12:15 +00:00
|
|
|
signal(SIGPIPE, SIG_IGN);
|
2011-03-19 13:20:47 +00:00
|
|
|
}
|
|
|
|
|
2012-02-24 06:47:19 +00:00
|
|
|
static void setup_automatic_flags(void)
|
|
|
|
{
|
|
|
|
if (!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO) ||
|
|
|
|
!isatty(STDIN_FILENO))
|
|
|
|
return;
|
|
|
|
|
|
|
|
apk_flags |= APK_PROGRESS;
|
|
|
|
if (!(apk_flags & APK_SIMULATE) &&
|
|
|
|
access("/etc/apk/interactive", F_OK) == 0)
|
|
|
|
apk_flags |= APK_INTERACTIVE;
|
|
|
|
}
|
|
|
|
|
2014-05-12 16:42:32 +00:00
|
|
|
void apk_applet_register(struct apk_applet *applet)
|
|
|
|
{
|
|
|
|
list_init(&applet->node);
|
|
|
|
list_add_tail(&applet->node, &apk_applet_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static 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)();
|
|
|
|
}
|
|
|
|
|
2017-04-17 12:54:24 +00:00
|
|
|
static struct apk_database db;
|
|
|
|
|
|
|
|
static void on_sigint(int s)
|
|
|
|
{
|
|
|
|
apk_db_close(&db);
|
|
|
|
exit(128 + s);
|
|
|
|
}
|
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
void *ctx = NULL;
|
2009-08-06 11:25:03 +00:00
|
|
|
struct apk_db_options dbopts;
|
2013-06-18 10:01:51 +00:00
|
|
|
struct apk_string_array *args;
|
2020-05-04 18:45:11 +00:00
|
|
|
struct apk_applet *applet;
|
|
|
|
int r;
|
2012-02-23 20:02:11 +00:00
|
|
|
|
2018-01-03 07:30:12 +00:00
|
|
|
apk_string_array_init(&args);
|
2014-12-08 06:30:35 +00:00
|
|
|
#ifdef TEST_MODE
|
2012-02-23 20:02:11 +00:00
|
|
|
apk_string_array_init(&test_repos);
|
|
|
|
#endif
|
2014-05-12 16:42:32 +00:00
|
|
|
apk_applet_register_builtin();
|
|
|
|
|
2011-09-14 08:07:45 +00:00
|
|
|
apk_argv = malloc(sizeof(char*[argc+2]));
|
2011-01-01 13:48:10 +00:00
|
|
|
memcpy(apk_argv, argv, sizeof(char*[argc]));
|
|
|
|
apk_argv[argc] = NULL;
|
2011-09-14 08:07:45 +00:00
|
|
|
apk_argv[argc+1] = NULL;
|
2011-01-01 13:48:10 +00:00
|
|
|
|
2009-08-06 11:25:03 +00:00
|
|
|
memset(&dbopts, 0, sizeof(dbopts));
|
|
|
|
list_init(&dbopts.repository_list);
|
2010-12-14 17:51:16 +00:00
|
|
|
apk_atom_init();
|
2009-01-13 12:09:45 +00:00
|
|
|
umask(0);
|
2011-03-19 13:20:47 +00:00
|
|
|
setup_terminal();
|
2011-03-16 13:22:05 +00:00
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
applet = deduce_applet(argc, argv);
|
2009-01-17 08:51:52 +00:00
|
|
|
if (applet != NULL) {
|
|
|
|
if (applet->context_size != 0)
|
|
|
|
ctx = calloc(1, applet->context_size);
|
2009-08-06 11:25:03 +00:00
|
|
|
dbopts.open_flags = applet->open_flags;
|
|
|
|
apk_flags |= applet->forced_flags;
|
2018-01-04 07:46:03 +00:00
|
|
|
apk_force |= applet->forced_force;
|
2009-01-13 12:09:45 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 13:19:06 +00:00
|
|
|
init_openssl();
|
2013-06-19 09:25:26 +00:00
|
|
|
setup_automatic_flags();
|
2018-01-04 09:08:30 +00:00
|
|
|
fetchConnectionCacheInit(32, 4);
|
2009-07-08 13:19:06 +00:00
|
|
|
|
2020-05-04 18:45:11 +00:00
|
|
|
r = parse_options(argc, argv, applet, ctx, &dbopts);
|
|
|
|
if (r != 0) goto err;
|
2009-01-17 08:51:52 +00:00
|
|
|
|
2009-01-13 12:09:45 +00:00
|
|
|
argc -= optind;
|
|
|
|
argv += optind;
|
|
|
|
if (argc >= 1 && strcmp(argv[0], applet->name) == 0) {
|
2008-04-21 16:30:10 +00:00
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
}
|
|
|
|
|
2017-04-28 10:28:32 +00:00
|
|
|
apk_db_init(&db);
|
2017-04-17 12:54:24 +00:00
|
|
|
signal(SIGINT, on_sigint);
|
2017-04-28 10:28:32 +00:00
|
|
|
|
2012-02-23 20:02:11 +00:00
|
|
|
#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;
|
|
|
|
apk_flags |= APK_SIMULATE;
|
|
|
|
apk_flags &= ~APK_INTERACTIVE;
|
|
|
|
#endif
|
2010-03-06 19:22:01 +00:00
|
|
|
r = apk_db_open(&db, &dbopts);
|
2009-08-06 11:25:03 +00:00
|
|
|
if (r != 0) {
|
|
|
|
apk_error("Failed to open apk database: %s",
|
|
|
|
apk_error_str(r));
|
2012-02-17 08:02:44 +00:00
|
|
|
goto err;
|
2009-08-06 11:25:03 +00:00
|
|
|
}
|
|
|
|
|
2012-02-23 20:02:11 +00:00
|
|
|
#ifdef TEST_MODE
|
|
|
|
if (test_world != NULL) {
|
|
|
|
apk_blob_t b = APK_BLOB_STR(test_world);
|
|
|
|
apk_blob_pull_deps(&b, &db, &db.world);
|
|
|
|
}
|
|
|
|
if (test_installed_db != NULL) {
|
2020-01-11 01:23:22 +00:00
|
|
|
apk_db_index_read(&db, apk_istream_from_file(AT_FDCWD, test_installed_db), -1);
|
2012-02-23 20:02:11 +00:00
|
|
|
}
|
2020-05-04 18:45:11 +00:00
|
|
|
for (int i = 0; i < test_repos->num; i++) {
|
2012-02-24 06:42:40 +00:00
|
|
|
apk_blob_t spec = APK_BLOB_STR(test_repos->item[i]), name, tag;
|
2013-05-30 05:46:30 +00:00
|
|
|
int repo_tag = 0, repo = APK_REPOSITORY_FIRST_CONFIGURED + i;
|
2012-02-24 06:42:40 +00:00
|
|
|
|
2014-05-19 08:48:36 +00:00
|
|
|
if (spec.ptr[0] == '!') {
|
|
|
|
/* cache's installed repository */
|
|
|
|
spec.ptr++;
|
|
|
|
spec.len--;
|
|
|
|
repo = -2;
|
|
|
|
}
|
|
|
|
|
2012-02-24 06:42:40 +00:00
|
|
|
if (apk_blob_split(spec, APK_BLOB_STR(":"), &tag, &name)) {
|
|
|
|
repo_tag = apk_db_get_tag_id(&db, tag);
|
|
|
|
} else {
|
|
|
|
name = spec;
|
2012-02-23 20:02:11 +00:00
|
|
|
}
|
2012-02-24 06:42:40 +00:00
|
|
|
|
2020-01-11 01:23:22 +00:00
|
|
|
if (apk_db_index_read(&db, apk_istream_from_file(AT_FDCWD, name.ptr), repo) != 0) {
|
2014-05-19 08:48:36 +00:00
|
|
|
apk_error("Failed to open repository: " BLOB_FMT, BLOB_PRINTF(name));
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (repo != -2) {
|
2013-05-30 05:46:30 +00:00
|
|
|
if (!(apk_flags & APK_NO_NETWORK))
|
|
|
|
db.available_repos |= BIT(repo);
|
|
|
|
db.repo_tags[repo_tag].allowed_repos |= BIT(repo);
|
2012-02-23 20:02:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-18 10:01:51 +00:00
|
|
|
apk_string_array_resize(&args, argc);
|
|
|
|
memcpy(args->item, argv, argc * sizeof(*argv));
|
|
|
|
|
|
|
|
r = applet->main(ctx, &db, args);
|
2009-08-06 11:25:03 +00:00
|
|
|
apk_db_close(&db);
|
|
|
|
|
2018-02-20 22:20:15 +00:00
|
|
|
#ifdef TEST_MODE
|
|
|
|
/* in test mode, we need to always exit 0 since xargs dies otherwise */
|
|
|
|
r = 0;
|
|
|
|
#endif
|
|
|
|
|
2019-06-05 06:56:13 +00:00
|
|
|
err:
|
2020-05-04 18:45:11 +00:00
|
|
|
if (r == -ESHUTDOWN) r = 0;
|
|
|
|
if (ctx) free(ctx);
|
2014-10-08 07:10:45 +00:00
|
|
|
|
|
|
|
fetchConnectionCacheClose();
|
2018-01-03 07:30:12 +00:00
|
|
|
apk_string_array_free(&args);
|
|
|
|
free(apk_argv);
|
|
|
|
|
2018-09-05 07:21:22 +00:00
|
|
|
if (r < 0) r = 250;
|
|
|
|
if (r > 99) r = 99;
|
2009-06-29 08:22:55 +00:00
|
|
|
return r;
|
2008-04-17 14:09:13 +00:00
|
|
|
}
|