diff options
Diffstat (limited to 'src/fix.c')
-rw-r--r-- | src/fix.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/fix.c b/src/fix.c new file mode 100644 index 0000000..3086428 --- /dev/null +++ b/src/fix.c @@ -0,0 +1,113 @@ +/* fix.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org> + * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * 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 <errno.h> +#include <stdio.h> +#include "apk_applet.h" +#include "apk_database.h" +#include "apk_state.h" + +struct fix_ctx { + unsigned int reinstall : 1; +}; + +static int fix_parse(void *pctx, int optch, int optindex, const char *optarg) +{ + struct fix_ctx *ctx = (struct fix_ctx *) pctx; + switch (optch) { + case 'u': + apk_flags |= APK_UPGRADE; + break; + case 'r': + ctx->reinstall = 1; + break; + default: + return -1; + } + return 0; +} + +static int fix_main(void *pctx, int argc, char **argv) +{ + struct fix_ctx *ctx = (struct fix_ctx *) pctx; + struct apk_database db; + struct apk_state *state = NULL; + struct apk_name *name; + int r, i, j; + + r = apk_db_open(&db, apk_root, APK_OPENF_WRITE); + if (r != 0) + return r; + + state = apk_state_new(&db); + if (state == NULL) + goto err; + + for (i = 0; i < argc; i++) { + name = apk_db_get_name(&db, APK_BLOB_STR(argv[i])); + if (name == NULL) + goto err; + + for (j = 0; j < name->pkgs->num; j++) { + if (apk_pkg_get_state(name->pkgs->item[j]) == APK_PKG_INSTALLED) + break; + } + if (j >= name->pkgs->num) { + apk_error("Package '%s' is not installed", name->name); + goto err; + } + + if (ctx->reinstall) + name->flags |= APK_NAME_REINSTALL; + } + + for (i = 0; i < argc; i++) { + struct apk_dependency dep; + + r = apk_dep_from_blob(&dep, &db, APK_BLOB_STR(argv[i])); + if (r != 0) + goto err; + + r = apk_state_lock_dependency(state, &dep); + if (r != 0) { + if (!(apk_flags & APK_FORCE)) + goto err; + } + } + r = apk_state_commit(state, &db); +err: + if (r != 0 && i < argc) + apk_error("Error while processing '%s'", argv[i]); + if (state != NULL) + apk_state_unref(state); + apk_db_close(&db); + return r; +} + +static struct apk_option fix_options[] = { + { 'u', "upgrade", "Upgrade package if possible" }, + { 'r', "reinstall", "Reinstall the package" }, +}; + +static struct apk_applet apk_fix = { + .name = "fix", + .help = "Repair package or upgrade it without modifying main " + "dependencies.", + .arguments = "PACKAGE...", + .context_size = sizeof(struct fix_ctx), + .num_options = ARRAY_SIZE(fix_options), + .options = fix_options, + .parse = fix_parse, + .main = fix_main, +}; + +APK_DEFINE_APPLET(apk_fix); + |