From fdec663855a198029859c8b33bd98bafca5a35df Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 19 Nov 2010 13:40:13 +0100 Subject: [PATCH] API clean up (part 2), plus misc changes and improvements. - Rename regpkgs_dictionary to regpkgdb_dictionary to better describe what is is. - Change some funcs in plist.c to return a boolean rather than int. - Hide more internal funcs off the API. - Simplify xbps_repository_update_pkg() and remove its second arg. - Hide implementation details in xbps_repository_pool, now to iterate over the pool you have to use xbps_repository_pool_foreach and its struct repository_pool_index. - Introduce xbps_{init,end}, to initialize/destroy some stuff in the library. - Introduce xbps_dbg_printf to printf stuff for debugging purposes. - xbps-{bin,repo}: added -d arg to enable debugging output. - Before checking if a config file needs to be installed or such, check that package contains the "conf_files" array. - Remove obsolete dirs as well while updating packages. - If transaction dictionary is ready remove the "missing_deps" array. Bump XBPS_RELVER to 20101118. --HG-- rename : lib/regpkgs_dictionary.c => lib/regpkgdb_dictionary.c --- bin/xbps-bin/check.c | 5 +- bin/xbps-bin/install.c | 86 ++-- bin/xbps-bin/main.c | 44 +- bin/xbps-bin/xbps-bin.8 | 9 +- bin/xbps-dgraph/main.c | 1 + bin/xbps-repo/main.c | 68 ++- bin/xbps-repo/repository.c | 207 ++++----- bin/xbps-repo/xbps-repo.8 | 9 +- bin/xbps-uhelper/main.c | 7 +- include/xbps_api.h | 262 +++++------ include/xbps_api_impl.h | 74 +++- lib/Makefile | 4 +- lib/download.c | 6 +- lib/fexec.c | 8 +- lib/initend.c | 78 ++++ lib/package_config_files.c | 70 ++- lib/package_configure.c | 46 +- lib/package_orphans.c | 10 +- lib/package_purge.c | 55 ++- lib/package_register.c | 38 +- lib/package_remove.c | 65 ++- lib/package_remove_obsoletes.c | 51 +-- lib/package_requiredby.c | 24 +- lib/package_state.c | 33 +- lib/package_unpack.c | 148 ++++--- lib/plist.c | 94 ++-- ...kgs_dictionary.c => regpkgdb_dictionary.c} | 40 +- lib/repository.c | 39 +- lib/repository_finddeps.c | 155 ++++--- lib/repository_findpkg.c | 418 +++++++++++------- lib/repository_plist.c | 70 ++- lib/repository_pool.c | 89 +++- lib/sortdeps.c | 56 +-- 33 files changed, 1426 insertions(+), 943 deletions(-) create mode 100644 lib/initend.c rename lib/{regpkgs_dictionary.c => regpkgdb_dictionary.c} (76%) diff --git a/bin/xbps-bin/check.c b/bin/xbps-bin/check.c index 5824d669..f0a89da6 100644 --- a/bin/xbps-bin/check.c +++ b/bin/xbps-bin/check.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "defs.h" @@ -56,7 +57,7 @@ xbps_check_pkg_integrity_all(void) int rv = 0; size_t npkgs = 0, nbrokenpkgs = 0; - d = xbps_regpkgs_dictionary_init(); + d = xbps_regpkgdb_dictionary_get(); if (d == NULL) return ENODEV; @@ -82,7 +83,7 @@ out: if (iter) prop_object_iterator_release(iter); - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return rv; } diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index c92a444e..bdbe73c9 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "defs.h" @@ -102,9 +103,6 @@ download_package_list(prop_object_iterator_t iter) if (cachedir == NULL) return EINVAL; - /* Set default limit of global and per-host cached connections */ - xbps_fetch_set_cache_connection(0, 0); - while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); @@ -293,11 +291,14 @@ xbps_autoupdate_pkgs(bool yes) if (rv == ENOENT) { printf("No packages currently registered.\n"); return 0; - } else if (rv == ENOPKG) { + } else if (rv == ENXIO) { printf("All packages are up-to-date.\n"); return 0; + } else { + fprintf(stderr, "xbps-bin: unexpected error %s\n", + strerror(rv)); + return -1; } - return rv; } return xbps_exec_transaction(yes); @@ -337,15 +338,16 @@ xbps_install_new_pkg(const char *pkg) free(pkgname); return 0; } - rv = xbps_repository_install_pkg(pkgpatt, true); - if (rv == EAGAIN) { - fprintf(stderr, "xbps-bin: unable to locate '%s' in " - "repository pool.\n", pkg); - rv = 1; - } else if (rv != 0 && rv != ENOENT) { - fprintf(stderr, "xbps-bin: unexpected error: %s", - strerror(errno)); - rv = -1; + if ((rv = xbps_repository_install_pkg(pkgpatt)) != 0) { + if (rv == EAGAIN) { + fprintf(stderr, "xbps-bin: unable to locate '%s' in " + "repository pool.\n", pkg); + rv = -1; + } else { + fprintf(stderr, "xbps-bin: unexpected error: %s\n", + strerror(rv)); + rv = -1; + } } if (pkgmatch) @@ -358,28 +360,22 @@ xbps_install_new_pkg(const char *pkg) int xbps_update_pkg(const char *pkgname) { - prop_dictionary_t pkgd; int rv = 0; - pkgd = xbps_find_pkg_dict_installed(pkgname, false); - printf("Finding new '%s' package...\n", pkgname); - if (pkgd) { - rv = xbps_repository_update_pkg(pkgname, pkgd); - if (rv == EEXIST) { - printf("Package '%s' is up to date.\n", pkgname); - rv = 0; - } else if (rv == ENOENT) { - fprintf(stderr, "Package '%s' not found in " - "repository pool.\n", pkgname); - rv = 0; - } - prop_object_release(pkgd); - } else { + rv = xbps_repository_update_pkg(pkgname); + if (rv == EEXIST) + printf("Package '%s' is up to date.\n", pkgname); + else if (rv == ENOENT) + fprintf(stderr, "Package '%s' not found in " + "repository pool.\n", pkgname); + else if (rv == ENODEV) printf("Package '%s' not installed.\n", pkgname); - return 0; + else if (rv != 0) { + fprintf(stderr, "xbps-bin: unexpected error %s\n", + strerror(rv)); + return -1; } - - return rv; + return 0; } static int @@ -435,11 +431,10 @@ replace_packages(prop_dictionary_t trans_dict, prop_dictionary_t pkgd, prop_object_release(instd); version = xbps_get_pkg_version(pkgver); - rv = xbps_remove_pkg(reppkgn, version, false); - if (rv != 0) { + if ((rv = xbps_remove_pkg(reppkgn, version, false)) != 0) { fprintf(stderr, "xbps-bin: couldn't remove %s (%s)\n", reppkgn, strerror(rv)); - return rv; + return -1; } } prop_object_iterator_release(replaces_iter); @@ -552,8 +547,7 @@ exec_transaction(struct transaction *trans) printf("Replacing %s files (%s -> %s) ...\n", pkgname, instver, version); - rv = xbps_remove_pkg(pkgname, version, true); - if (rv != 0) { + if ((rv = xbps_remove_pkg(pkgname, version, true)) != 0) { fprintf(stderr, "xbps-bin: error " "replacing %s-%s (%s)\n", pkgname, instver, strerror(rv)); @@ -617,14 +611,15 @@ xbps_exec_transaction(bool yes) return rv; trans->dict = xbps_repository_get_transaction_dict(); - if (trans->dict == NULL) + if (trans->dict == NULL) { + rv = errno; goto out; - - /* - * Bail out if there are unresolved deps. - */ - array = prop_dictionary_get(trans->dict, "missing_deps"); - if (prop_array_count(array) > 0) { + } + if (rv == ENOENT) { + /* + * Bail out if there are unresolved deps. + */ + array = prop_dictionary_get(trans->dict, "missing_deps"); show_missing_deps(trans->dict); goto out; } @@ -644,9 +639,6 @@ xbps_exec_transaction(bool yes) trans->yes = yes; rv = exec_transaction(trans); - DPRINTF(("Dictionary AFTER transaction happened:\n")); - DPRINTF(("%s", prop_dictionary_externalize(trans->dict))); - out: if (trans->iter) prop_object_iterator_release(trans->iter); diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 982191d0..10dc33fa 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "defs.h" @@ -44,7 +45,7 @@ usage(void) " autoremove\n" " autoupdate\n" " check\t\t[|]\n" - " find-files\t\n" + " find-files\t\t\n" " install\t\t[|]\n" " list\t\t[state]\n" " list-manual\n" @@ -59,6 +60,7 @@ usage(void) " update\t\t\n" " Options shared by all targets:\n" " -c\t\t\n" + " -d\t\tDebug output\n" " -r\t\t\n" " -v\t\tShows verbose messages\n" " -V\t\tPrints the xbps release version\n" @@ -120,8 +122,7 @@ list_manual_packages(prop_object_t obj, void *arg, bool *loop_done) static void cleanup(int signum) { - xbps_regpkgs_dictionary_release(); - xbps_fetch_unset_cache_connection(); + xbps_end(); exit(signum); } @@ -132,15 +133,18 @@ main(int argc, char **argv) pkg_state_t pkgstate = 0; struct sigaction sa; int i = 0, c, flags = 0, rv = 0; - bool yes, purge; + bool yes, purge, with_debug; - yes = purge = false; + yes = purge = with_debug = false; - while ((c = getopt(argc, argv, "Vcfpr:vy")) != -1) { + while ((c = getopt(argc, argv, "Vcdfpr:vy")) != -1) { switch (c) { case 'c': xbps_set_cachedir(optarg); break; + case 'd': + with_debug = true; + break; case 'f': flags |= XBPS_FLAG_FORCE; break; @@ -184,9 +188,13 @@ main(int argc, char **argv) sigaction(SIGTERM, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); - if ((dict = xbps_regpkgs_dictionary_init()) == NULL) { - if (errno != ENOENT) { - rv = errno; + /* + * Initialize stuff for libxbps. + */ + xbps_init(with_debug); + + if ((dict = xbps_regpkgdb_dictionary_get()) == NULL) { + if (errno && errno != ENOENT) { fprintf(stderr, "E: couldn't initialize regpkgdb dict: %s\n", strerror(errno)); @@ -194,6 +202,15 @@ main(int argc, char **argv) } } + if ((rv = xbps_repository_pool_init()) != 0) { + if (rv != ENOENT) { + fprintf(stderr, + "E: couldn't initialize repository pool: %s\n", + strerror(rv)); + goto out; + } + } + if (strcasecmp(argv[0], "list") == 0) { /* Lists packages currently registered in database. */ if (argc < 1 || argc > 2) @@ -221,11 +238,8 @@ main(int argc, char **argv) } } - if (!xbps_callback_array_iter_in_dict(dict, "packages", - list_pkgs_in_dict, &pkgstate)) { - rv = errno; - goto out; - } + rv = xbps_callback_array_iter_in_dict(dict, "packages", + list_pkgs_in_dict, &pkgstate); } else if (strcasecmp(argv[0], "install") == 0) { /* Installs a binary package and required deps. */ @@ -361,7 +375,7 @@ main(int argc, char **argv) rv = xbps_callback_array_iter_in_dict(dict, "packages", list_manual_packages, NULL); - + } else if (strcasecmp(argv[0], "show-revdeps") == 0) { /* * Show reverse dependencies for a package. diff --git a/bin/xbps-bin/xbps-bin.8 b/bin/xbps-bin/xbps-bin.8 index 0c947a97..af2c7016 100644 --- a/bin/xbps-bin/xbps-bin.8 +++ b/bin/xbps-bin/xbps-bin.8 @@ -2,12 +2,12 @@ .\" Title: xbps-bin .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.75.2 -.\" Date: 31/10/2010 +.\" Date: 18/11/2010 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "XBPS\-BIN" "8" "31/10/2010" "\ \&" "\ \&" +.TH "XBPS\-BIN" "8" "18/11/2010" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -43,6 +43,11 @@ of \fI/blah/cachedir\fR\&. .RE .PP +\fB\-d\fR +.RS 4 +Enables extra debugging output to be shown to stderr. +.RE +.PP \fB\-f\fR .RS 4 Used currently in the diff --git a/bin/xbps-dgraph/main.c b/bin/xbps-dgraph/main.c index 2cbf6583..8ed92d9d 100644 --- a/bin/xbps-dgraph/main.c +++ b/bin/xbps-dgraph/main.c @@ -29,6 +29,7 @@ #include #include #include +#include #include diff --git a/bin/xbps-repo/main.c b/bin/xbps-repo/main.c index a02585e7..17963f78 100644 --- a/bin/xbps-repo/main.c +++ b/bin/xbps-repo/main.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2009 Juan Romero Pardines. + * Copyright (c) 2008-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "defs.h" @@ -66,19 +67,44 @@ usage(void) exit(EXIT_FAILURE); } +static int +repo_list_uri_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + (void)arg; + (void)done; + + printf("%s\n", rpi->rpi_uri); + return 0; +} + +static int +repo_search_pkgs_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + char *pattern = arg; + (void)done; + + printf("From %s repository ...\n", rpi->rpi_uri); + (void)xbps_callback_array_iter_in_dict(rpi->rpi_repod, + "packages", show_pkg_namedesc, pattern); + return 0; +} + int main(int argc, char **argv) { prop_dictionary_t pkgd; - struct repository_pool *rpool; char *root; int c, rv = 0; + bool with_debug = false; - while ((c = getopt(argc, argv, "Vcr:")) != -1) { + while ((c = getopt(argc, argv, "Vcdr:")) != -1) { switch (c) { case 'c': xbps_set_cachedir(optarg); break; + case 'd': + with_debug = true; + break; case 'r': /* To specify the root directory */ root = optarg; @@ -99,11 +125,14 @@ main(int argc, char **argv) if (argc < 1) usage(); - rv = xbps_repository_pool_init(); - if (rv != 0 && rv != ENOENT) { - fprintf(stderr, "E: cannot get repository list pool! %s\n", - strerror(rv)); - exit(EXIT_FAILURE); + xbps_init(with_debug); + + if ((rv = xbps_repository_pool_init()) != 0) { + if (rv != ENOENT) { + fprintf(stderr, "E: cannot get repository list pool! %s\n", + strerror(rv)); + exit(EXIT_FAILURE); + } } if (strcasecmp(argv[0], "add") == 0) { @@ -118,8 +147,7 @@ main(int argc, char **argv) if (argc != 1) usage(); - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) - printf("%s\n", rpool->rp_uri); + xbps_repository_pool_foreach(repo_list_uri_cb, NULL); } else if ((strcasecmp(argv[0], "rm") == 0) || (strcasecmp(argv[0], "remove") == 0)) { @@ -137,11 +165,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - printf("From %s repository ...\n", rpool->rp_uri); - (void)xbps_callback_array_iter_in_dict(rpool->rp_repod, - "packages", show_pkg_namedesc, argv[1]); - } + xbps_repository_pool_foreach(repo_search_pkgs_cb, argv[1]); } else if (strcasecmp(argv[0], "show") == 0) { /* Shows info about a binary package. */ @@ -179,9 +203,15 @@ main(int argc, char **argv) pkgd = xbps_repository_get_pkg_plist_dict(argv[1], XBPS_PKGFILES); if (pkgd == NULL) { - fprintf(stderr, - "E: couldn't read %s: %s.\n", XBPS_PKGFILES, - strerror(errno)); + if (errno != ENOENT) { + fprintf(stderr, "xbps-repo: unexpected " + "error '%s' searching for '%s'\n", + strerror(errno), argv[1]); + } else { + fprintf(stderr, + "Package '%s' not found in repository " + "pool.\n", argv[1]); + } rv = errno; goto out; } @@ -207,6 +237,6 @@ main(int argc, char **argv) } out: - xbps_repository_pool_release(); + xbps_end(); exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/bin/xbps-repo/repository.c b/bin/xbps-repo/repository.c index 51c6a580..e8bf243b 100644 --- a/bin/xbps-repo/repository.c +++ b/bin/xbps-repo/repository.c @@ -33,6 +33,7 @@ #include #include +#include "../xbps-bin/defs.h" #include "defs.h" #include "config.h" @@ -147,13 +148,15 @@ unregister_repository(const char *uri) if ((idxstr = sanitize_url(uri)) == NULL) return errno; - if ((rv = xbps_repository_unregister(idxstr)) != 0) { - if (rv == ENOENT) - fprintf(stderr, "Repository '%s' not actually " - "registered.\n", idxstr); - else - fprintf(stderr, "E: couldn't unregister " - "repository (%s)\n", strerror(rv)); + if ((rv = xbps_repository_unregister(idxstr)) == 0) + return 0; + + if (rv == ENOENT) { + fprintf(stderr, "Repository '%s' not actually " + "registered.\n", idxstr); + } else { + fprintf(stderr, "E: couldn't unregister " + "repository (%s)\n", strerror(rv)); } return rv; @@ -211,14 +214,13 @@ register_repository(const char *uri) if ((rpi = pkgindex_verify(plist, idxstr)) == NULL) goto out; - rv = xbps_repository_register(idxstr); - if (rv != 0 && rv != EEXIST) { - fprintf(stderr, "E: couldn't register repository (%s)\n", - strerror(rv)); - goto out; - } else if (rv == EEXIST) { - fprintf(stderr, "W: repository already registered.\n"); - rv = 0; + if ((rv = xbps_repository_register(idxstr)) != 0) { + if (rv == EEXIST) { + fprintf(stderr, "W: repository already registered.\n"); + } else { + fprintf(stderr, "E: couldn't register repository " + "(%s)\n", strerror(errno)); + } goto out; } @@ -234,110 +236,111 @@ out: return rv; } +static int +repo_show_pkg_info_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + prop_dictionary_t repo_pkgd, pkg_propsd; + const char *pkgname = arg; + char *url = NULL; + + repo_pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod, + "packages", pkgname); + if (repo_pkgd == NULL) + return errno; + + url = xbps_repository_get_path_from_pkg_dict(repo_pkgd, rpi->rpi_uri); + if (url == NULL) + return errno; + + printf("Fetching info from: %s\n", rpi->rpi_uri); + pkg_propsd = + xbps_repository_get_pkg_plist_dict_from_url(url, XBPS_PKGPROPS); + if (pkg_propsd == NULL) { + free(url); + return errno; + } + show_pkg_info_only_repo(repo_pkgd); + show_pkg_info(pkg_propsd); + prop_object_release(pkg_propsd); + *done = true; + return 0; +} + int show_pkg_info_from_repolist(const char *pkgname) { - struct repository_pool *rp; - prop_dictionary_t repo_pkgd, pkg_propsd; - int rv = 0; + return xbps_repository_pool_foreach(repo_show_pkg_info_cb, + __UNCONST(pkgname)); +} - SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) { - char *url = NULL; - repo_pkgd = xbps_find_pkg_in_dict_by_name(rp->rp_repod, - "packages", pkgname); - if (repo_pkgd == NULL) { - if (errno && errno != ENOENT) { - rv = errno; - break; - } - continue; - } - url = xbps_repository_get_path_from_pkg_dict(repo_pkgd, - rp->rp_uri); - if (url == NULL) { - rv = errno; - break; - } - printf("Fetching info from: %s\n", rp->rp_uri); - pkg_propsd = xbps_repository_get_pkg_plist_dict_from_url(url, - XBPS_PKGPROPS); - if (pkg_propsd == NULL) { - free(url); - rv = errno; - break; - } - show_pkg_info_only_repo(repo_pkgd); - show_pkg_info(pkg_propsd); - prop_object_release(pkg_propsd); - break; +static int +repo_show_pkg_deps_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + prop_dictionary_t pkgd; + const char *ver, *pkgname = arg; + + pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod, + "packages", pkgname); + if (pkgd == NULL) { + if (errno && errno != ENOENT) + return errno; + + return 0; } + prop_dictionary_get_cstring_nocopy(pkgd, "version", &ver); + printf("Repository %s [pkgver: %s]\n", rpi->rpi_uri, ver); + (void)xbps_callback_array_iter_in_dict(pkgd, + "run_depends", list_strings_sep_in_array, NULL); + *done = true; - return rv; + return 0; } int show_pkg_deps_from_repolist(const char *pkgname) { - struct repository_pool *rd; - prop_dictionary_t pkgd; - const char *ver; + return xbps_repository_pool_foreach(repo_show_pkg_deps_cb, + __UNCONST(pkgname)); +} + +static int +repo_sync_pkg_index_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + struct repoinfo *rp; + char *plist; int rv = 0; - SIMPLEQ_FOREACH(rd, &rp_queue, rp_entries) { - pkgd = xbps_find_pkg_in_dict_by_name(rd->rp_repod, - "packages", pkgname); - if (pkgd == NULL) { - if (errno != ENOENT) { - rv = errno; - break; - } - continue; - } - prop_dictionary_get_cstring_nocopy(pkgd, "version", &ver); - printf("Repository %s [pkgver: %s]\n", rd->rp_uri, ver); - (void)xbps_callback_array_iter_in_dict(pkgd, - "run_depends", list_strings_sep_in_array, NULL); - } + (void)arg; + (void)done; - return rv; + if (!xbps_check_is_repo_string_remote(rpi->rpi_uri)) + return 0; + + printf("Syncing package index from: %s\n", rpi->rpi_uri); + rv = xbps_repository_sync_pkg_index(rpi->rpi_uri); + if (rv == -1) { + fprintf(stderr, "E: returned: %s\n", xbps_fetch_error_string()); + return rv; + } else if (rv == 0) { + printf("Package index file is already up to date.\n"); + return 0; + } + if ((plist = xbps_get_pkg_index_plist(rpi->rpi_uri)) == NULL) + return EINVAL; + + if ((rp = pkgindex_verify(plist, rpi->rpi_uri)) == NULL) + return errno; + + printf("Updated package index at %s (v%s) with %ju packages.\n", + rpi->rpi_uri, rp->pkgidxver, rp->totalpkgs); + free(rp); + free(plist); + + return 0; } int repository_sync(void) { - struct repository_pool *rp; - char *plist; - int rv = 0; - - SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) { - struct repoinfo *rpi = NULL; - - if (!xbps_check_is_repo_string_remote(rp->rp_uri)) - continue; - - printf("Syncing package index from: %s\n", rp->rp_uri); - rv = xbps_repository_sync_pkg_index(rp->rp_uri); - if (rv == -1) { - fprintf(stderr, "E: returned: %s\n", - xbps_fetch_error_string()); - break; - } else if (rv == 0) { - printf("Package index file is already up to date.\n"); - continue; - } - if ((plist = xbps_get_pkg_index_plist(rp->rp_uri)) == NULL) { - rv = EINVAL; - break; - } - if ((rpi = pkgindex_verify(plist, rp->rp_uri)) == NULL) { - rv = errno; - break; - } - printf("Updated package index at %s (v%s) with %ju packages.\n", - rp->rp_uri, rpi->pkgidxver, rpi->totalpkgs); - free(rpi); - free(plist); - } - - return rv; + return xbps_repository_pool_foreach(repo_sync_pkg_index_cb, NULL); } diff --git a/bin/xbps-repo/xbps-repo.8 b/bin/xbps-repo/xbps-repo.8 index 6c1c9c96..bcf6e584 100644 --- a/bin/xbps-repo/xbps-repo.8 +++ b/bin/xbps-repo/xbps-repo.8 @@ -2,12 +2,12 @@ .\" Title: xbps-repo .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.75.2 -.\" Date: 05/03/2010 +.\" Date: 18/11/2010 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "XBPS\-REPO" "8" "05/03/2010" "\ \&" "\ \&" +.TH "XBPS\-REPO" "8" "18/11/2010" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -43,6 +43,11 @@ of \fI/blah/cachedir\fR\&. .RE .PP +\fB\-d\fR +.RS 4 +Enables extra debugging output to be shown to stderr. +.RE +.PP \fB\-r\fR \fIrootdir\fR .RS 4 Sets the diff --git a/bin/xbps-uhelper/main.c b/bin/xbps-uhelper/main.c index 1b4790d6..6aabb449 100644 --- a/bin/xbps-uhelper/main.c +++ b/bin/xbps-uhelper/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -131,6 +132,8 @@ main(int argc, char **argv) if (argc < 1) usage(); + xbps_init(false); + plist = xbps_xasprintf("%s/%s/%s", root, XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) { fprintf(stderr, @@ -314,8 +317,6 @@ main(int argc, char **argv) if (argc != 2) usage(); - xbps_fetch_set_cache_connection(0, 0); - for (i = 1; i < argc; i++) { rv = xbps_fetch_file(argv[i], ".", false, "v"); if (rv == -1) { @@ -332,5 +333,7 @@ main(int argc, char **argv) usage(); } + xbps_end(); + exit(EXIT_SUCCESS); } diff --git a/include/xbps_api.h b/include/xbps_api.h index ab4b3ca2..a84c59bc 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -31,10 +31,6 @@ #include #include -#include -#include - -#include #ifdef __cplusplus # define __BEGIN_DECLS extern "C" { @@ -44,7 +40,6 @@ # define __END_DECLS #endif - /** * @file include/xbps_api.h * @brief XBPS Library API header @@ -56,7 +51,7 @@ * @def XBPS_RELVER * Current library release date. */ -#define XBPS_RELVER "20101023:0.6.1" +#define XBPS_RELVER "20101118" /** * @def XBPS_META_PATH @@ -122,6 +117,30 @@ __BEGIN_DECLS +void xbps_dbg_printf(const char *, ...); +void xbps_dbg_printf_append(const char *, ...); + +/** @addtogroup initend */ +/*@{*/ + +/** + * Initialize the XBPS library with the following steps: + * + * - Sets default cache connections for libfetch. + * + * - Initializes the debug printfs. + * + * @param[in] debug If true, debugging output will be shown to stderr. + */ +void xbps_init(bool debug); + +/** + * Releases all resources used by the XBPS library. + */ +void xbps_end(void); + +/*@}*/ + /** @addtogroup configure */ /*@{*/ @@ -134,7 +153,7 @@ __BEGIN_DECLS * in unpacked state. * @param[in] update Set it to true if this package is being updated. * - * @return 0 on success, or an appropiate errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_configure_pkg(const char *pkgname, const char *version, @@ -144,7 +163,7 @@ int xbps_configure_pkg(const char *pkgname, /** * Configure (or force reconfiguration of) all packages. * - * @return 0 on success, or an appropiate errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_configure_all_pkgs(void); @@ -172,20 +191,6 @@ int xbps_cmpver(const char *pkg1, const char *pkg2); /** @addtogroup download */ /*@{*/ -/** - * @def XBPS_FETCH_CACHECONN - * - * Default (global) limit of cached connections used in libfetch. - */ -#define XBPS_FETCH_CACHECONN 6 - -/** - * @def XBPS_FETCH_CACHECONN_HOST - * - * Default (per host) limit of cached connections used in libfetch. - */ -#define XBPS_FETCH_CACHECONN_HOST 2 - /** * Download a file from a remote URL. * @@ -203,73 +208,15 @@ int xbps_fetch_file(const char *uri, bool refetch, const char *flags); -/** - * Sets the libfetch's cache connection limits. - * - * @param[in] global Number of global cached connections, if set to 0 - * by default it's set to XBPS_FETCH_CACHECONN. - * @param[in] per_host Number of per host cached connections, if set to 0 - * by default it's set to XBPS_FETCH_CACHECONN_HOST. - */ -void xbps_fetch_set_cache_connection(int global, int per_host); - -/** - * Destroys the libfetch's cache connection established. - */ -void xbps_fetch_unset_cache_connection(void); - /** * Returns last error string reported by xbps_fetch_file(). * * @return A string with the appropiate error message. - * @} */ const char *xbps_fetch_error_string(void); /*@}*/ -/** @addtogroup fexec */ -/*@{*/ - -/** - * Forks and executes a command in the current working directory - * with an arbitrary number of arguments. - * - * @param[in] arg Arguments passed to execvp(3) when forked, the last - * argument must be NULL. - * - * @return 0 on success, -1 on error and errno set appropiately. - */ -int xbps_file_exec(const char *arg, ...); - -/** - * Forks and executes a command in the current working directory - * with an arbitrary number of arguments. - * - * @param[in] arg Arguments passed to execvp(3) when forked, does not need - * to be terminated with a NULL argument. - * - * @return 0 on success, -1 on error and errno set appropiately. - */ -int xbps_file_exec_skipempty(const char *arg, ...); - -/** - * Forks and executes a command with an arbitrary number of arguments - * in a specified path. - * - * If uid==0 and /bin/sh (relative to path) exists, a chroot(2) call - * will be done, otherwise chdir(2) to path. - * - * @param[in] path Destination path to chroot(2) or chdir(2). - * @param[in] arg Arguments passed to execvp(3) when forked, the last - * argument must be NULL. - * - * @return 0 on success, -1 on error and errno set appropiately. - */ -int xbps_file_chdir_exec(const char *path, const char *arg, ...); - -/*@}*/ - /* From lib/humanize_number.c */ #define HN_DECIMAL 0x01 #define HN_NOSPACE 0x02 @@ -298,7 +245,7 @@ int xbps_mkpath(char *path, mode_t mode); * Finds all package orphans currently installed. * * @return A proplib array of dictionaries with all orphans found, - * on error NULL is returned and errno set appropiately. + * on error NULL is returned and errno is set appropiately. */ prop_array_t xbps_find_orphan_packages(void); @@ -336,7 +283,7 @@ bool xbps_add_obj_to_dict(prop_dictionary_t dict, * @param[in] array Proplib array to insert the object to. * @param[in] obj Proplib object to be inserted. * - * @return true on success, false otherwise and errno set appropiately. + * @return true on success, false otherwise and xbps_errno set appropiately. */ bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj); @@ -353,7 +300,7 @@ bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj); * @param[in] arg Argument to be passed to the function callback. * * @return 0 on success (all objects were processed), otherwise an - * errno value on error. + * errno value is set appropiately. */ int xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key, @@ -373,7 +320,7 @@ int xbps_callback_array_iter_in_dict(prop_dictionary_t dict, * @param[in] arg Argument to be passed to the function callback. * * @return 0 on success (all objects were processed), otherwise an - * errno value on error. + * errno value is set appropiately. */ int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, const char *key, @@ -447,8 +394,7 @@ prop_dictionary_t xbps_find_pkg_dict_installed(const char *str, * @param[in] array The proplib array where to look for. * @param[in] val The value of string to match. * - * @return true on success, false otherwise and errno set appropiately - * if there was an unexpected error. + * @return true on success, false otherwise and errno is set appropiately. */ bool xbps_find_string_in_array(prop_array_t array, const char *val); @@ -485,9 +431,9 @@ prop_dictionary_t xbps_get_pkg_dict_from_metadata_plist(const char *pkgn, * @param[in] pkgname Package name to look for. * @param[in] plist Path to a plist file. * - * @return 0 on success, or an errno value otherwise. + * @return true on success, false otherwise and errno is set appropiately. */ -int xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist); +bool xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist); /** * Removes the package's proplib dictionary matching \a pkgname, @@ -497,11 +443,11 @@ int xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist); * @param[in] key Key associated with the proplib array. * @param[in] pkgname Package name to look for. * - * @return 0 on success, or an errno value otherwise. + * @return true on success, false otherwise and errno is set appropiately. */ -int xbps_remove_pkg_from_dict(prop_dictionary_t dict, - const char *key, - const char *pkgname); +bool xbps_remove_pkg_from_dict(prop_dictionary_t dict, + const char *key, + const char *pkgname); /** * Removes a string from a proplib's array. @@ -509,9 +455,9 @@ int xbps_remove_pkg_from_dict(prop_dictionary_t dict, * @param[in] array Proplib array where to look for. * @param[in] str String to match in the array. * - * @return 0 on success, or an errno value otherwise. + * @return true on success, false otherwise and errno is set appropiately. */ -int xbps_remove_string_from_array(prop_array_t array, const char *str); +bool xbps_remove_string_from_array(prop_array_t array, const char *str); /*@}*/ @@ -525,7 +471,7 @@ int xbps_remove_string_from_array(prop_array_t array, const char *str); * @param[in] check_state Set it to true to check that package * is in XBPS_PKG_STATE_CONFIG_FILES state. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_purge_pkg(const char *pkgname, bool check_state); @@ -533,7 +479,7 @@ int xbps_purge_pkg(const char *pkgname, bool check_state); * Purge all installed packages. Packages that aren't in * XBPS_PKG_STATE_CONFIG_FILES state will be ignored. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_purge_all_pkgs(void); @@ -550,7 +496,7 @@ int xbps_purge_all_pkgs(void); * @param[in] automatic Set it to true to mark package that has been * installed by another package, and not explicitly. * - * @return 0 on success, an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_register_pkg(prop_dictionary_t pkg_dict, bool automatic); @@ -559,7 +505,7 @@ int xbps_register_pkg(prop_dictionary_t pkg_dict, bool automatic); * * @param[in] pkgname Package name. * - * @return 0 on success, an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_unregister_pkg(const char *pkgname); @@ -569,19 +515,20 @@ int xbps_unregister_pkg(const char *pkgname); /*@{*/ /** - * Initialize resources used by the registered packages database. + * Initialize resources used by the registered packages database dictionary + * and returns the internalized proplib dictionary. * * @note This function is reference counted, if the database has * been initialized previously, the counter will be increased by one * and dictionary stored in memory will be returned. * - * @warning Don't forget to always use xbps_regpkgs_dictionary_release() + * @warning Don't forget to always use xbps_regpkgdb_dictionary_release() * when its dictionary is no longer needed. * * @return A dictionary as shown above in the Detailed description * graph on success, or NULL otherwise and errno is set appropiately. */ -prop_dictionary_t xbps_regpkgs_dictionary_init(void); +prop_dictionary_t xbps_regpkgdb_dictionary_get(void); /** * Release resources used by the registered packages database. @@ -589,7 +536,7 @@ prop_dictionary_t xbps_regpkgs_dictionary_init(void); * @note This function is reference counted, if the database * is in use (its reference count number is not 0), won't be released. */ -void xbps_regpkgs_dictionary_release(void); +void xbps_regpkgdb_dictionary_release(void); /*@}*/ @@ -604,7 +551,7 @@ void xbps_regpkgs_dictionary_release(void); * @param[in] update If true, some steps will be skipped. See in the * detailed description above for more information. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_remove_pkg(const char *pkgname, const char *version, bool update); @@ -618,7 +565,7 @@ int xbps_remove_pkg(const char *pkgname, const char *version, bool update); * @param[in] key Key of the array object to match, valid values are: * files, dirs, links and conf_files. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key); @@ -632,7 +579,7 @@ int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key); * * @param[in] uri URI pointing to the repository. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_repository_register(const char *uri); @@ -641,7 +588,7 @@ int xbps_repository_register(const char *uri); * * @param[in] uri URI pointing to the repository. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_repository_unregister(const char *uri); @@ -651,20 +598,18 @@ int xbps_repository_unregister(const char *uri); /*@{*/ /** - * Finds a package by its name or by a pattern and enqueues it into + * Finds a package by a pattern and enqueues it into * the transaction dictionary for future use. The first repository in - * the queue that matched the requirement wins. + * the pool that matched the pattern wins. * * @note The function name might be misleading, but is correct because * if package is found, it will be marked as "going to be installed". * * @param pkg Package name or pattern to find. - * @param bypattern If true, a package pattern will be used in \a pkg. - * Otherwise \a pkg will be used as a package name. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ -int xbps_repository_install_pkg(const char *pkg, bool bypattern); +int xbps_repository_install_pkg(const char *pkgpattern); /** * Marks a package as "going to be updated" in the transaction dictionary. @@ -672,20 +617,17 @@ int xbps_repository_install_pkg(const char *pkg, bool bypattern); * is available the package dictionary will be enqueued. * * @param pkgname The package name to update. - * @param instpkg Installed package dictionary, as returned by - * xbps_find_pkg_dict_installed(). * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ -int xbps_repository_update_pkg(const char *pkgname, - prop_dictionary_t instpkg); +int xbps_repository_update_pkg(const char *pkgname); /** * Finds newer versions for all installed packages by looking at the * repository pool. If a newer version exists, package will be enqueued * into the transaction dictionary. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_repository_update_allpkgs(void); @@ -702,7 +644,7 @@ int xbps_repository_update_allpkgs(void); * xbps_repository_update_pkg() functions are not called previously. * * @return The transaction dictionary to install/update/replace - * a package list. NULL on failure and errno set appropiately. + * a package list. NULL on failure and errno is set appropiately. */ prop_dictionary_t xbps_repository_get_transaction_dict(void); @@ -722,7 +664,7 @@ prop_dictionary_t xbps_repository_get_transaction_dict(void); * @param[in] uri URI pointing to a repository. * * @return A string with the full path, NULL otherwise and errno - * set appropiately. + * is set appropiately. */ char *xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d, const char *uri); @@ -759,8 +701,9 @@ prop_dictionary_t xbps_repository_get_pkg_plist_dict(const char *pkgname, * @return An internalized proplib dictionary, otherwise NULL and * errno is set appropiately. */ -prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url, - const char *plistf); +prop_dictionary_t + xbps_repository_get_pkg_plist_dict_from_url(const char *url, + const char *plistf); /*@}*/ @@ -768,58 +711,39 @@ prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url, /*@{*/ /** - * @struct repository_pool xbps_api.h "xbps_api.h" - * @brief Repository pool structure + * @struct repository_pool_index xbps_api.h "xbps_api.h" + * @brief Repository pool dictionary structure * - * Repository object structure registered in the global simple queue - * \a rp_queue. The simple queue must be initialized through - * xbps_repository_pool_init(), and released with - * xbps_repository_pool_release() when it's no longer needed. + * Repository index object structure registered in a private simple queue. + * The structure contains a dictionary and the URI associated with the + * registered repository index. */ -struct repository_pool { +struct repository_pool_index { /** - * @var rp_entries + * @var rpi_repod * - * Structure that connects elements in the simple queue. - * For use with the SIMPLEQ macros. + * Internalized Proplib dictionary of the pkg-index plist file + * associated with repository. */ - SIMPLEQ_ENTRY(repository_pool) rp_entries; - /** - * @var rp_repod - * - * Proplib dictionary associated with repository. - */ - prop_dictionary_t rp_repod; + prop_dictionary_t rpi_repod; /** * @var rp_uri * * URI string associated with repository. */ - char *rp_uri; + char *rpi_uri; }; -/** - * @var rp_queue - * @brief Pointer to the head of global simple queue. - * - * A pointer to the head of the global simple queue to - * use after xbps_repository_pool_init() has been initialized - * successfully. - */ -SIMPLEQ_HEAD(repopool_queue, repository_pool); -struct repopool_queue rp_queue; /** - * Initializes the repository pool by creating a global simple queue - * \a rp_queue with all registered repositories in the database. + * Initializes the repository pool. * * Once it's initialized, access to the repositories can be done - * by the global simple queue \a rp_queue and the \a repository_pool - * structure. + * through the \a xbps_repository_pool_foreach() function. * * @note This function is reference counted, don't forget to call * xbps_repository_pool_release() when it's no longer needed. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_repository_pool_init(void); @@ -832,6 +756,24 @@ int xbps_repository_pool_init(void); */ void xbps_repository_pool_release(void); +/** + * Iterates over the repository pool and executes the \a fn function + * callback passing in the void * \a arg argument to it. The bool pointer + * argument can be used in the callbacks to stop immediately the loop if + * set to true, otherwise it will only be stopped if it returns a + * non-zero value. + * + * @param fn Function callback to execute for every repository registered in + * the pool. + * @param arg Opaque data passed in to the \a fn function callback for + * client data. + * + * @return 0 on success, otherwise an errno value. + */ +int xbps_repository_pool_foreach( + int (*fn)(struct repository_pool_index *, void *, bool *), + void *arg); + /*@}*/ /** @addtogroup reposync */ @@ -886,7 +828,7 @@ typedef enum pkg_state { * @param[in] pkgname Package name. * @param[out] state Package state returned. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state); @@ -897,7 +839,7 @@ int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state); * @param[in] dict Package dictionary. * @param[out] state Package state returned. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state); @@ -907,7 +849,7 @@ int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state); * @param[in] pkgname Package name. * @param[in] state Package state to be set. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state); @@ -917,7 +859,7 @@ int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state); * @param[in] dict Package dictionary. * @param[in] state Package state to be set. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state); @@ -931,7 +873,7 @@ int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state); * @param[in] trans_pkg_dict Package proplib dictionary as stored in the * \a packages array returned by the transaction dictionary. * - * @return 0 on success, or an errno value otherwise. + * @return 0 on success, otherwise an errno value. */ int xbps_unpack_binary_pkg(prop_dictionary_t trans_pkg_dict); diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index b8bc3cef..4629aab7 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -31,6 +31,9 @@ # define NDEBUG #endif #include +#include +#include + #include #define ARCHIVE_READ_BLOCKSIZE 10240 @@ -60,17 +63,47 @@ #define HIDDEN #endif +/** + * @def XBPS_FETCH_CACHECONN + * + * Default (global) limit of cached connections used in libfetch. + */ +#define XBPS_FETCH_CACHECONN 6 + +/** + * @def XBPS_FETCH_CACHECONN_HOST + * + * Default (per host) limit of cached connections used in libfetch. + */ +#define XBPS_FETCH_CACHECONN_HOST 2 + __BEGIN_DECLS + +/** + * @private + * Sets the libfetch's cache connection limits. + * + * @param[in] global Number of global cached connections, if set to 0 + * by default it's set to XBPS_FETCH_CACHECONN. + * @param[in] per_host Number of per host cached connections, if set to 0 + * by default it's set to XBPS_FETCH_CACHECONN_HOST. + */ +void HIDDEN xbps_fetch_set_cache_connection(int global, int per_host); + +/** + * Destroys the libfetch's cache connection established. + */ +void HIDDEN xbps_fetch_unset_cache_connection(void); + /** * @private * From lib/package_config_files.c */ int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t, + prop_dictionary_t, struct archive_entry *, - const char *, int *, bool *); - /** * @private * From lib/plist.c @@ -119,6 +152,43 @@ int HIDDEN xbps_sort_pkg_deps(prop_dictionary_t); */ char HIDDEN *xbps_get_remote_repo_string(const char *); +/** + * Forks and executes a command in the current working directory + * with an arbitrary number of arguments. + * + * @param[in] arg Arguments passed to execvp(3) when forked, the last + * argument must be NULL. + * + * @return 0 on success, -1 on error and errno set appropiately. + */ +int HIDDEN xbps_file_exec(const char *arg, ...); + +/** + * Forks and executes a command in the current working directory + * with an arbitrary number of arguments. + * + * @param[in] arg Arguments passed to execvp(3) when forked, does not need + * to be terminated with a NULL argument. + * + * @return 0 on success, -1 on error and errno set appropiately. + */ +int HIDDEN xbps_file_exec_skipempty(const char *arg, ...); + +/** + * Forks and executes a command with an arbitrary number of arguments + * in a specified path. + * + * If uid==0 and /bin/sh (relative to path) exists, a chroot(2) call + * will be done, otherwise chdir(2) to path. + * + * @param[in] path Destination path to chroot(2) or chdir(2). + * @param[in] arg Arguments passed to execvp(3) when forked, the last + * argument must be NULL. + * + * @return 0 on success, -1 on error and errno set appropiately. + */ +int HIDDEN xbps_file_chdir_exec(const char *path, const char *arg, ...); + __END_DECLS #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 8c56712a..6e1e4b93 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,10 +35,10 @@ LIBFETCH_GEN = fetch/ftperr.h fetch/httperr.h OBJS = package_configure.o package_config_files.o package_orphans.o OBJS += package_remove.o package_remove_obsoletes.o package_state.o OBJS += package_unpack.o package_requiredby.o package_register.o -OBJS += package_purge.o +OBJS += package_purge.o initend.o OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o OBJS += sortdeps.o util.o pkgmatch.o mkpath.o -OBJS += regpkgs_dictionary.o repository.o repository_finddeps.o +OBJS += regpkgdb_dictionary.o repository.o repository_finddeps.o OBJS += repository_findpkg.o repository_plist.o OBJS += repository_pool.o repository_sync_index.o OBJS += $(COMPAT_SRCS) diff --git a/lib/download.c b/lib/download.c index 81a36e6e..12659ce2 100644 --- a/lib/download.c +++ b/lib/download.c @@ -39,7 +39,9 @@ #include #include #include + #include +#include "xbps_api_impl.h" #include "fetch.h" /** @@ -191,7 +193,7 @@ xbps_fetch_error_string(void) return fetchLastErrString; } -void +void HIDDEN xbps_fetch_set_cache_connection(int global, int per_host) { if (global == 0) @@ -202,7 +204,7 @@ xbps_fetch_set_cache_connection(int global, int per_host) fetchConnectionCacheInit(global, per_host); } -void +void HIDDEN xbps_fetch_unset_cache_connection(void) { fetchConnectionCacheClose(); diff --git a/lib/fexec.c b/lib/fexec.c index 64695adb..1680fdfc 100644 --- a/lib/fexec.c +++ b/lib/fexec.c @@ -80,7 +80,7 @@ pfcexec(const char *path, const char *file, const char **argv) _exit(127); } - (void)execvp(file, __UNCONST(argv)); + (void)execv(file, __UNCONST(argv)); _exit(127); /* NOTREACHED */ case -1: @@ -138,7 +138,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap) return retval; } -int +int HIDDEN xbps_file_exec(const char *arg, ...) { va_list ap; @@ -151,7 +151,7 @@ xbps_file_exec(const char *arg, ...) return result; } -int +int HIDDEN xbps_file_exec_skipempty(const char *arg, ...) { va_list ap; @@ -164,7 +164,7 @@ xbps_file_exec_skipempty(const char *arg, ...) return result; } -int +int HIDDEN xbps_file_chdir_exec(const char *path, const char *arg, ...) { va_list ap; diff --git a/lib/initend.c b/lib/initend.c new file mode 100644 index 00000000..645ebf71 --- /dev/null +++ b/lib/initend.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2010 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include "xbps_api_impl.h" + +static bool with_debug; + +void +xbps_init(bool debug) +{ + xbps_fetch_set_cache_connection(XBPS_FETCH_CACHECONN, + XBPS_FETCH_CACHECONN_HOST); + with_debug = debug; +} + +void +xbps_end(void) +{ + xbps_regpkgdb_dictionary_release(); + xbps_repository_pool_release(); + xbps_fetch_unset_cache_connection(); +} + +void +xbps_dbg_printf(const char *fmt, ...) +{ + va_list ap; + + if (!with_debug) + return; + + va_start(ap, fmt); + fprintf(stderr, "[DEBUG] "); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +void +xbps_dbg_printf_append(const char *fmt, ...) +{ + va_list ap; + + if (!with_debug) + return; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} diff --git a/lib/package_config_files.c b/lib/package_config_files.c index 6cb5952d..1d5f3d90 100644 --- a/lib/package_config_files.c +++ b/lib/package_config_files.c @@ -33,32 +33,82 @@ #include #include "xbps_api_impl.h" +/* + * Returns 1 if entry is a configuration file, 0 if don't or -1 on error. + */ +static int +entry_is_conf_file(prop_dictionary_t propsd, struct archive_entry *entry) +{ + prop_object_t obj; + prop_object_iterator_t iter; + char *entrytmp, *cffile; + int rv = 0; + + iter = xbps_get_array_iter_from_dict(propsd, "conf_files"); + if (iter == NULL) + return -1; + + entrytmp = xbps_xasprintf(".%s", archive_entry_pathname(entry)); + if (entrytmp == NULL) { + rv = -1; + goto out; + } + + while ((obj = prop_object_iterator_next(iter))) { + cffile = xbps_xasprintf(".%s", + prop_string_cstring_nocopy(obj)); + if (cffile == NULL) { + rv = -1; + goto out; + } + if (strcmp(cffile, entrytmp) == 0) { + rv = 1; + free(cffile); + break; + } + free(cffile); + } + +out: + prop_object_iterator_release(iter); + if (entrytmp) + free(entrytmp); + + return rv; +} + int HIDDEN -xbps_config_file_from_archive_entry(prop_dictionary_t d, +xbps_config_file_from_archive_entry(prop_dictionary_t filesd, + prop_dictionary_t propsd, struct archive_entry *entry, - const char *pkgname, int *flags, bool *skip) { prop_dictionary_t forigd; prop_object_t obj, obj2; prop_object_iterator_t iter, iter2; - const char *cffile, *sha256_new = NULL; + const char *pkgname, *cffile, *sha256_new = NULL; char *buf, *sha256_cur = NULL, *sha256_orig = NULL; int rv = 0; bool install_new = false; - if (d == NULL) - return 0; + /* + * Check that current entry is really a configuration file. + */ + rv = entry_is_conf_file(propsd, entry); + if (rv == -1 || rv == 0) + return rv; - iter = xbps_get_array_iter_from_dict(d, "conf_files"); + rv = 0; + iter = xbps_get_array_iter_from_dict(filesd, "conf_files"); if (iter == NULL) - return 0; + return EINVAL; /* * Get original hash for the file from current * installed package. */ + prop_dictionary_get_cstring_nocopy(propsd, "pkgname", &pkgname); forigd = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES); if (forigd == NULL) { install_new = true; @@ -73,7 +123,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d, buf = xbps_xasprintf(".%s", cffile); if (buf == NULL) { prop_object_iterator_release(iter2); - rv = errno; + rv = ENOMEM; goto out; } if (strcmp(archive_entry_pathname(entry), buf) == 0) { @@ -104,7 +154,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d, buf = xbps_xasprintf(".%s", cffile); if (buf == NULL) { prop_object_iterator_release(iter); - return errno; + return ENOMEM; } if (strcmp(archive_entry_pathname(entry), buf)) { free(buf); @@ -180,7 +230,7 @@ xbps_config_file_from_archive_entry(prop_dictionary_t d, (strcmp(sha256_orig, sha256_new))) { buf = xbps_xasprintf(".%s.new", cffile); if (buf == NULL) { - rv = errno; + rv = ENOMEM; break; } printf("Keeping modified file %s.\n", cffile); diff --git a/lib/package_configure.c b/lib/package_configure.c index 101bf3fc..a60a87a6 100644 --- a/lib/package_configure.c +++ b/lib/package_configure.c @@ -57,7 +57,7 @@ xbps_configure_all_pkgs(void) const char *pkgname, *version; int rv = 0; - if ((d = xbps_regpkgs_dictionary_init()) == NULL) + if ((d = xbps_regpkgdb_dictionary_get()) == NULL) return errno; iter = xbps_get_array_iter_from_dict(d, "packages"); @@ -75,29 +75,30 @@ xbps_configure_all_pkgs(void) } prop_object_iterator_release(iter); out: - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return rv; } int -xbps_configure_pkg(const char *pkgname, const char *version, bool check_state, +xbps_configure_pkg(const char *pkgname, + const char *version, + bool check_state, bool update) { prop_dictionary_t pkgd; const char *lver, *rootdir = xbps_get_rootdir(); char *buf; - int rv = 0, flags = 0; + int rv = 0, flags = xbps_get_flags(); pkg_state_t state = 0; bool reconfigure = false; assert(pkgname != NULL); - flags = xbps_get_flags(); - if (check_state) { - if ((rv = xbps_get_pkg_state_installed(pkgname, &state)) != 0) - return rv; + rv = xbps_get_pkg_state_installed(pkgname, &state); + if (rv != 0) + return EINVAL; if (state == XBPS_PKG_STATE_INSTALLED) { if ((flags & XBPS_FLAG_FORCE) == 0) @@ -108,9 +109,6 @@ xbps_configure_pkg(const char *pkgname, const char *version, bool check_state, return EINVAL; pkgd = xbps_find_pkg_dict_installed(pkgname, false); - if (pkgd == NULL) - return errno; - prop_dictionary_get_cstring_nocopy(pkgd, "version", &lver); prop_object_release(pkgd); } else { @@ -123,20 +121,28 @@ xbps_configure_pkg(const char *pkgname, const char *version, bool check_state, buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", XBPS_META_PATH, pkgname); if (buf == NULL) - return errno; + return ENOMEM; if (chdir(rootdir) == -1) { + xbps_dbg_printf("%s: [configure] chdir to '%s' returned %s\n", + pkgname, rootdir, strerror(errno)); free(buf); - return errno; + return EINVAL; } - rv = xbps_file_exec(buf, "post", - pkgname, lver, update ? "yes" : "no", NULL); - if (rv != 0 && errno != ENOENT) { - free(buf); - fprintf(stderr, "%s: post INSTALL action " - "returned: %s\n", pkgname, strerror(errno)); - return rv; + if (access(buf, X_OK) == 0) { + if (xbps_file_exec(buf, "post", + pkgname, lver, update ? "yes" : "no", NULL) != 0) { + free(buf); + xbps_dbg_printf("%s: [configure] post INSTALL " + "action returned %s\n", pkgname, strerror(errno)); + return errno; + } + } else { + if (errno != ENOENT) { + free(buf); + return errno; + } } free(buf); diff --git a/lib/package_orphans.c b/lib/package_orphans.c index e9402f2b..fb946ed1 100644 --- a/lib/package_orphans.c +++ b/lib/package_orphans.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Juan Romero Pardines. + * Copyright (c) 2009-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,6 +30,8 @@ #include #include +#include "xbps_api_impl.h" +#include "queue.h" /** * @file lib/orphans.c @@ -147,7 +149,7 @@ cleanup(void) prop_object_release(orphan->dict); free(orphan); } - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); } prop_array_t @@ -158,7 +160,7 @@ xbps_find_orphan_packages(void) struct orphan_pkg *orphan; int rv = 0; - if ((dict = xbps_regpkgs_dictionary_init()) == NULL) + if ((dict = xbps_regpkgdb_dictionary_get()) == NULL) return NULL; /* * Find out all orphans by looking at the @@ -189,7 +191,7 @@ xbps_find_orphan_packages(void) prop_object_release(orphan->dict); free(orphan); } - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return array; } diff --git a/lib/package_purge.c b/lib/package_purge.c index f22daa09..4687d2f9 100644 --- a/lib/package_purge.c +++ b/lib/package_purge.c @@ -54,16 +54,14 @@ remove_pkg_metadata(const char *pkgname) struct dirent *dp; DIR *dirp; char *metadir, *path; - int flags = 0, rv = 0; + int rv = 0, flags = xbps_get_flags(); assert(pkgname != NULL); - flags = xbps_get_flags(); - metadir = xbps_xasprintf("%s/%s/metadata/%s", xbps_get_rootdir(), XBPS_META_PATH, pkgname); if (metadir == NULL) - return errno; + return ENOMEM; dirp = opendir(metadir); if (dirp == NULL) { @@ -80,7 +78,7 @@ remove_pkg_metadata(const char *pkgname) if (path == NULL) { (void)closedir(dirp); free(metadir); - return -1; + return ENOMEM; } if (unlink(path) == -1) { @@ -107,7 +105,7 @@ xbps_purge_all_pkgs(void) const char *pkgname; int rv = 0; - if ((d = xbps_regpkgs_dictionary_init()) == NULL) + if ((d = xbps_regpkgdb_dictionary_get()) == NULL) return errno; iter = xbps_get_array_iter_from_dict(d, "packages"); @@ -123,7 +121,7 @@ xbps_purge_all_pkgs(void) } prop_object_iterator_release(iter); out: - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return rv; } @@ -132,16 +130,15 @@ int xbps_purge_pkg(const char *pkgname, bool check_state) { prop_dictionary_t dict, pkgd; - int rv = 0, flags; + int rv = 0, flags = xbps_get_flags(); pkg_state_t state = 0; assert(pkgname != NULL); - flags = xbps_get_flags(); /* * Firstly let's get the pkg dictionary from regpkgdb. */ - if ((dict = xbps_regpkgs_dictionary_init()) == NULL) + if ((dict = xbps_regpkgdb_dictionary_get()) == NULL) return errno; pkgd = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname); @@ -157,37 +154,47 @@ xbps_purge_pkg(const char *pkgname, bool check_state) if ((rv = xbps_get_pkg_state_dictionary(pkgd, &state)) != 0) goto out; - if (state != XBPS_PKG_STATE_CONFIG_FILES) + if (state != XBPS_PKG_STATE_CONFIG_FILES) { + rv = EINVAL; goto out; + } } /* - * Remove unmodified configuration files. + * Remove unmodified configuration files and directories. */ dict = xbps_get_pkg_dict_from_metadata_plist(pkgname, XBPS_PKGFILES); if (dict == NULL) { rv = errno; goto out; } - if ((rv = xbps_remove_pkg_files(dict, "conf_files")) != 0) { - prop_object_release(dict); - goto out; + + if (prop_dictionary_get(dict, "conf_files")) { + if ((rv = xbps_remove_pkg_files(dict, "conf_files")) != 0) { + prop_object_release(dict); + goto out; + } + if ((rv = xbps_remove_pkg_files(dict, "dirs")) != 0) { + prop_object_release(dict); + goto out; + } } prop_object_release(dict); /* * Remove metadata dir and unregister package. */ - if ((rv = remove_pkg_metadata(pkgname)) == 0) { - if ((rv = xbps_unregister_pkg(pkgname)) == 0) { - if (flags & XBPS_FLAG_VERBOSE) { - printf("Package %s purged " - "successfully.\n", pkgname); - } - } - } + if ((rv = remove_pkg_metadata(pkgname)) != 0) + goto out; + + if ((rv = xbps_unregister_pkg(pkgname)) != 0) + goto out; + + if (flags & XBPS_FLAG_VERBOSE) + printf("Package %s purged successfully.\n", pkgname); out: - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); + return rv; } diff --git a/lib/package_register.c b/lib/package_register.c index b506a2a3..ca3501de 100644 --- a/lib/package_register.c +++ b/lib/package_register.c @@ -53,7 +53,7 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic) plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) - return EINVAL; + return ENOMEM; prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version); @@ -70,29 +70,24 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic) "packages", pkgname); if (pkgd == NULL) { rv = errno; - DPRINTF(("%s: find_pkg_in_dict_by_name failed: %s\n", - __func__, strerror(rv))); goto out; } if (!prop_dictionary_set_cstring_nocopy(pkgd, "version", version)) { prop_object_release(pkgd); - rv = errno; - DPRINTF(("%s: version obj not found!\n", __func__)); + rv = EINVAL; goto out; } if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgver", pkgver)) { prop_object_release(pkgd); - rv = errno; - DPRINTF(("%s: pkgver obj not found!\n", __func__)); + rv = EINVAL; goto out; } if (!prop_dictionary_set_cstring_nocopy(pkgd, "short_desc", desc)) { prop_object_release(pkgd); - rv = errno; - DPRINTF(("%s: short_desc obj not found!\n", __func__)); + rv = EINVAL; goto out; } if (!prop_dictionary_get_bool(pkgd, @@ -100,9 +95,7 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic) if (!prop_dictionary_set_bool(pkgd, "automatic-install", automatic)) { prop_object_release(pkgd); - rv = errno; - DPRINTF(("%s: autoinst obj not found!\n", - __func__)); + rv = EINVAL; goto out; } } @@ -114,24 +107,19 @@ xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic) array = prop_dictionary_get(dict, "packages"); if (array == NULL) { prop_object_release(pkgd); - rv = ENOENT; - DPRINTF(("%s: packages array obj not found!\n", - __func__)); + rv = EINVAL; goto out; } - rv = xbps_requiredby_pkg_add(array, pkgrd); - if (rv != 0) { - prop_object_release(pkgd); - DPRINTF(("%s: requiredby_pkg_add failed %d\n", - __func__, rv)); + if ((rv = xbps_requiredby_pkg_add(array, pkgrd)) != 0) goto out; - } } /* * Write plist file to storage. */ - if (!prop_dictionary_externalize_to_zfile(dict, plist)) + if (!prop_dictionary_externalize_to_zfile(dict, plist)) { rv = errno; + goto out; + } } else { free(plist); return ENOENT; @@ -154,9 +142,11 @@ xbps_unregister_pkg(const char *pkgname) plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) - return EINVAL; + return ENOMEM; + + if (!xbps_remove_pkg_dict_from_file(pkgname, plist)) + rv = errno; - rv = xbps_remove_pkg_dict_from_file(pkgname, plist); free(plist); return rv; diff --git a/lib/package_remove.c b/lib/package_remove.c index c8174d58..3b92496d 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -78,7 +78,7 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) prop_object_iterator_t iter; prop_object_t obj; const char *file, *sha256, *curobj = NULL; - char *dname = NULL, *path = NULL; + char *path = NULL; int flags = 0, rv = 0; assert(dict != NULL); @@ -87,12 +87,14 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) flags = xbps_get_flags(); array = prop_dictionary_get(dict, key); - if (array == NULL || prop_array_count(array) == 0) + if (array == NULL) + return EINVAL; + else if (prop_array_count(array) == 0) return 0; iter = xbps_get_array_iter_from_dict(dict, key); if (iter == NULL) - return errno; + return ENOMEM; if (strcmp(key, "files") == 0) curobj = "file"; @@ -107,9 +109,10 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) prop_dictionary_get_cstring_nocopy(obj, "file", &file); path = xbps_xasprintf("%s/%s", xbps_get_rootdir(), file); if (path == NULL) { - rv = errno; + rv = ENOMEM; break; } + if ((strcmp(key, "files") == 0) || (strcmp(key, "conf_files") == 0)) { /* @@ -163,25 +166,6 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) if (flags & XBPS_FLAG_VERBOSE) printf("Removed %s: %s\n", curobj, file); } - /* - * When purging a package, also remove the directory where - * the conf_files are living on. - */ - if (strcmp(key, "conf_files") == 0) { - dname = dirname(path); - if (rmdir(dname) == -1) { - if (errno != ENOTEMPTY) { - fprintf(stderr, - "WARNING: can't remove %s %s " - "(%s)\n", curobj, file, - strerror(errno)); - } - } else { - if (flags & XBPS_FLAG_VERBOSE) - printf("Removed empty directory: " - "%s\n", dname); - } - } free(path); } prop_object_iterator_release(iter); @@ -195,6 +179,7 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) prop_dictionary_t dict; char *buf; int rv = 0; + bool rmfile_exists = false; assert(pkgname != NULL); assert(version != NULL); @@ -208,24 +193,31 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname); if (buf == NULL) - return errno; + return ENOMEM; if (chdir(xbps_get_rootdir()) == -1) { free(buf); - return errno; + return EINVAL; } /* * Run the pre remove action. */ - rv = xbps_file_exec(buf, "pre", pkgname, version, - update ? "yes" : "no", NULL); - if (rv != 0 && errno != ENOENT) { - fprintf(stderr, - "%s: prerm action target error (%s)\n", pkgname, - strerror(errno)); - free(buf); - return rv; + if (access(buf, X_OK) == 0) { + rmfile_exists = true; + if (xbps_file_exec(buf, "pre", pkgname, version, + update ? "yes" : "no", NULL) != 0) { + fprintf(stderr, + "%s: prerm action target error (%s)\n", + pkgname, strerror(errno)); + free(buf); + return errno; + } + } else { + if (errno != ENOENT) { + free(buf); + return errno; + } } /* @@ -271,13 +263,13 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) * Execute the post REMOVE action if file exists and we aren't * updating the package. */ - rv = xbps_file_exec(buf, "post", pkgname, version, "no", NULL); - if (rv != 0 && errno != ENOENT) { + if (rmfile_exists && + (xbps_file_exec(buf, "post", pkgname, version, "no", NULL) != 0)) { fprintf(stderr, "%s: postrm action target error (%s)\n", pkgname, strerror(errno)); free(buf); - return rv; + return errno; } free(buf); @@ -293,5 +285,6 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) rv = xbps_set_pkg_state_installed(pkgname, XBPS_PKG_STATE_CONFIG_FILES); + return rv; } diff --git a/lib/package_remove_obsoletes.c b/lib/package_remove_obsoletes.c index 262da476..2c24b833 100644 --- a/lib/package_remove_obsoletes.c +++ b/lib/package_remove_obsoletes.c @@ -39,15 +39,15 @@ int HIDDEN xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd) { - prop_object_iterator_t iter, iter2 = NULL; - prop_object_t obj, obj2 = NULL; - prop_string_t oldstr = NULL, newstr = NULL; + prop_object_iterator_t iter, iter2; + prop_object_t obj, obj2; + prop_string_t oldstr, newstr; struct stat st; const char *array_str = "files"; - const char *oldhash = NULL; - char *dname = NULL, *file = NULL; + const char *oldhash; + char *file; int rv = 0; - bool found, dolinks = false; + bool found, dodirs = false, dolinks = false; again: iter = xbps_get_array_iter_from_dict(oldd, array_str); @@ -59,7 +59,7 @@ again: return errno; } /* - * Check for obsolete files, i.e files/links available in + * Check for obsolete files, i.e files/links/dirs available in * the old package list not found in new package list. */ while ((obj = prop_object_iterator_next(iter))) { @@ -89,7 +89,7 @@ again: rv = 0; continue; } - } else { + } else if (strcmp(array_str, "links") == 0) { /* * Only remove dangling symlinks. */ @@ -123,32 +123,18 @@ again: } /* - * Obsolete file found, remove it. + * Obsolete obj found, remove it. */ if (remove(file) == -1) { fprintf(stderr, - "WARNING: couldn't remove obsolete %s: %s\n", - dolinks ? "link" : "file", - prop_string_cstring_nocopy(oldstr)); + "WARNING: couldn't remove obsolete obj: %s (%s)\n", + prop_string_cstring_nocopy(oldstr), + strerror(errno)); free(file); continue; } - printf("Removed obsolete %s: %s\n", - dolinks ? "link" : "file", + printf("Removed obsolete obj: %s\n", prop_string_cstring_nocopy(oldstr)); - /* - * Try to remove the directory where the obsole file or link - * was currently living on. - */ - dname = dirname(file); - if (rmdir(dname) == -1) { - if (errno != 0 && errno != EEXIST && errno != ENOTEMPTY) - fprintf(stderr, - "WARNING: couldn't remove obsolete " - "directory %s: %s\n", dname, - strerror(errno)); - } - free(file); } if (!dolinks) { /* @@ -161,6 +147,17 @@ again: iter2 = NULL; goto again; } + if (!dodirs) { + /* + * Look for obsolete dirs. + */ + dodirs = true; + array_str = "dirs"; + prop_object_iterator_release(iter2); + prop_object_iterator_release(iter); + iter2 = NULL; + goto again; + } out: prop_object_iterator_release(iter2); diff --git a/lib/package_requiredby.c b/lib/package_requiredby.c index 73065d2d..e2faceb8 100644 --- a/lib/package_requiredby.c +++ b/lib/package_requiredby.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Juan Romero Pardines. + * Copyright (c) 2009-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ add_pkg_into_reqby(prop_dictionary_t pkgd, const char *reqname) if (reqstr == NULL) { if (alloc) prop_object_release(array); - return errno; + return ENOMEM; } if (!xbps_add_obj_to_array(array, reqstr)) { @@ -132,20 +132,27 @@ xbps_requiredby_pkg_remove(const char *pkgname) plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) - return EINVAL; + return ENOMEM; if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) { free(plist); + xbps_dbg_printf("[reqby-rm] cannot internalize " + "regpkgdb plist for '%s': %s\n", pkgname, strerror(errno)); return errno; } rv = xbps_callback_array_iter_in_dict(dict, "packages", remove_pkg_from_reqby, __UNCONST(pkgname)); - if (rv == 0) { - if (!prop_dictionary_externalize_to_zfile(dict, plist)) - rv = errno; + if (rv != 0) + goto out; + + if (!prop_dictionary_externalize_to_zfile(dict, plist)) { + xbps_dbg_printf("[reqby-rm] cannot externalize plist for " + "'%s': %s\n", pkgname, strerror(errno)); + rv = errno; } +out: prop_object_release(dict); free(plist); @@ -174,7 +181,7 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) while ((obj = prop_object_iterator_next(iter)) != NULL) { str = prop_string_cstring_nocopy(obj); if (str == NULL) { - rv = errno; + rv = EINVAL; goto out; } rdepname = xbps_get_pkgpattern_name(str); @@ -182,10 +189,11 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) rv = EINVAL; goto out; } + iter2 = prop_array_iterator(regar); if (iter2 == NULL) { - free(rdepname); rv = ENOMEM; + free(rdepname); goto out; } diff --git a/lib/package_state.c b/lib/package_state.c index e8c210dc..d2835908 100644 --- a/lib/package_state.c +++ b/lib/package_state.c @@ -66,11 +66,11 @@ set_new_state(prop_dictionary_t dict, pkg_state_t state) } if (!prop_dictionary_set_cstring_nocopy(dict, "state", state_str)) - return -1; + return EINVAL; if (prop_dictionary_get_cstring_nocopy(dict, "pkgname", &pkgname)) { - DPRINTF(("%s: changed pkg state to '%s'.\n", - pkgname, state_str)); + xbps_dbg_printf("%s: changed pkg state to '%s'\n", + pkgname, state_str); } return 0; @@ -153,30 +153,31 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state) plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) - return EINVAL; + return ENOMEM; if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) { dict = prop_dictionary_create(); if (dict == NULL) { - rv = errno; + rv = ENOMEM; goto out; } array = prop_array_create(); if (array == NULL) { - rv = errno; + rv = ENOMEM; goto out; } pkgd = prop_dictionary_create(); if (pkgd == NULL) { + rv = ENOMEM; prop_object_release(array); - rv = errno; goto out; } + if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgname", pkgname)) { + rv = EINVAL; prop_object_release(array); prop_object_release(pkgd); - rv = errno; goto out; } if ((rv = set_new_state(pkgd, state)) != 0) { @@ -185,14 +186,14 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state) goto out; } if (!xbps_add_obj_to_array(array, pkgd)) { + rv = EINVAL; prop_object_release(array); prop_object_release(pkgd); - rv = errno; goto out; } if (!xbps_add_obj_to_dict(dict, array, "packages")) { + rv = EINVAL; prop_object_release(array); - rv = errno; goto out; } @@ -204,20 +205,21 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state) rv = errno; goto out; } + newpkg = true; pkgd = prop_dictionary_create(); if (!prop_dictionary_set_cstring_nocopy(pkgd, "pkgname", pkgname)) { + rv = EINVAL; prop_object_release(pkgd); - rv = errno; goto out; } } array = prop_dictionary_get(dict, "packages"); if (array == NULL) { + rv = EINVAL; if (newpkg) prop_object_release(pkgd); - rv = errno; goto out; } if ((rv = set_new_state(pkgd, state)) != 0) { @@ -226,14 +228,17 @@ xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state) goto out; } if (newpkg && !xbps_add_obj_to_array(array, pkgd)) { + rv = EINVAL; prop_object_release(pkgd); - rv = errno; goto out; } } - if (!prop_dictionary_externalize_to_zfile(dict, plist)) + if (!prop_dictionary_externalize_to_zfile(dict, plist)) { rv = errno; + xbps_dbg_printf("[pkgstate] cannot write plist '%s': %s\n", + plist, strerror(errno)); + } out: if (dict) diff --git a/lib/package_unpack.c b/lib/package_unpack.c index af272eee..1b9d4f6a 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -91,10 +91,12 @@ set_extract_flags(int *flags, bool update) * the consumer. */ static int -unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, - const char *pkgname, const char *version) +unpack_archive_fini(struct archive *ar, + prop_dictionary_t pkg, + const char *pkgname, + const char *version) { - prop_dictionary_t filesd = NULL, old_filesd = NULL; + prop_dictionary_t propsd, filesd, old_filesd; struct archive_entry *entry; size_t entry_idx = 0; const char *rootdir, *entry_str, *transact; @@ -128,9 +130,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", XBPS_META_PATH, pkgname); if (buf == NULL) - return errno; + return ENOMEM; + if (unlink(buf) == -1) { - if (errno != ENOENT) { + if (errno && errno != ENOENT) { free(buf); return errno; } @@ -139,9 +142,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname); if (buf == NULL) - return errno; + return ENOMEM; + if (unlink(buf) == -1) { - if (errno != ENOENT) { + if (errno && errno != ENOENT) { free(buf); return errno; } @@ -161,16 +165,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, if (strcmp("./INSTALL", entry_str) == 0) { buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", XBPS_META_PATH, pkgname); - if (buf == NULL) - return errno; + if (buf == NULL) { + rv = ENOMEM; + goto out; + } archive_entry_set_pathname(entry, buf); - archive_entry_set_mode(entry, 0750); + archive_entry_set_perm(entry, 0750); if (archive_read_extract(ar, entry, lflags) != 0) { if ((rv = archive_errno(ar)) != EEXIST) { free(buf); - return rv; + goto out; } } @@ -181,7 +187,7 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, fprintf(stderr, "%s: preinst action target error %s\n", pkgname, strerror(errno)); - return rv; + goto out; } /* Pass to the next entry if successful */ free(buf); @@ -194,13 +200,18 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, } else if (strcmp("./REMOVE", entry_str) == 0) { buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname); - if (buf == NULL) - return errno; + if (buf == NULL) { + rv = ENOMEM; + goto out; + } + archive_entry_set_pathname(entry, buf); free(buf); - archive_entry_set_mode(entry, 0750); - if (archive_read_extract(ar, entry, lflags) != 0) - return archive_errno(ar); + archive_entry_set_perm(entry, 0750); + if (archive_read_extract(ar, entry, lflags) != 0) { + if ((rv = archive_errno(ar)) != EEXIST) + goto out; + } /* Pass to next entry if successful */ entry_idx++; @@ -213,8 +224,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, * all files are extracted. */ filesd = xbps_read_dict_from_archive_entry(ar, entry); - if (filesd == NULL) - return errno; + if (filesd == NULL) { + rv = errno; + goto out; + } /* Pass to next entry */ files_plist_found = true; @@ -222,36 +235,30 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, continue; } else if (strcmp("./props.plist", entry_str) == 0) { - buf = xbps_xasprintf(".%s/metadata/%s/props.plist", - XBPS_META_PATH, pkgname); - if (buf == NULL) - return errno; + buf = xbps_xasprintf(".%s/metadata/%s/%s", + XBPS_META_PATH, pkgname, XBPS_PKGPROPS); + if (buf == NULL) { + rv = ENOMEM; + goto out; + } + archive_entry_set_pathname(entry, buf); free(buf); if (archive_read_extract(ar, entry, lflags) != 0) return archive_errno(ar); + propsd = + xbps_get_pkg_dict_from_metadata_plist(pkgname, + XBPS_PKGPROPS); + if (propsd == NULL) { + rv = errno; + goto out; + } /* Pass to next entry if successful */ props_plist_found = true; entry_idx++; continue; - - } else { - /* - * Handle configuration files. - */ - if ((rv = xbps_config_file_from_archive_entry(filesd, - entry, pkgname, &lflags, &skip_entry)) != 0) { - prop_object_release(filesd); - return rv; - } - if (skip_entry) { - archive_read_data_skip(ar); - skip_entry = false; - entry_idx++; - continue; - } } /* @@ -266,12 +273,31 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, * This is not an XBPS binary package. */ if (entry_idx >= 3) - return ENOPKG; + return ENODEV; entry_idx++; continue; } + /* + * Handle configuration files. Check if current entry is + * a configuration file and take action if required. Skip + * packages that don't have the "conf_files" array in + * the XBPS_PKGPROPS dictionary. + */ + if (prop_dictionary_get(propsd, "conf_files")) { + if ((rv = xbps_config_file_from_archive_entry(filesd, + propsd, entry, &lflags, &skip_entry)) != 0) { + prop_object_release(filesd); + goto out; + } + if (skip_entry) { + archive_read_data_skip(ar); + skip_entry = false; + continue; + } + } + /* * Account for the following scenario (real example): * @@ -303,10 +329,10 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, */ if (archive_read_extract(ar, entry, lflags) != 0) { rv = archive_errno(ar); - if (rv != EEXIST) { + if (rv && rv != EEXIST) { fprintf(stderr, "ERROR: %s...exiting!\n", archive_error_string(ar)); - return rv;; + goto out; } else if (rv == EEXIST) { if (flags & XBPS_FLAG_VERBOSE) { fprintf(stderr, @@ -322,33 +348,33 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, } if ((rv = archive_errno(ar)) == 0) { - buf = xbps_xasprintf(".%s/metadata/%s/files.plist", - XBPS_META_PATH, pkgname); + buf = xbps_xasprintf(".%s/metadata/%s/%s", + XBPS_META_PATH, pkgname, XBPS_PKGFILES); if (buf == NULL) { prop_object_release(filesd); - return errno; + return ENOMEM; } /* * Check if files.plist exists and pkg is NOT marked as * preserve, in that case we need to check for obsolete files * and remove them if necessary. */ - if (!preserve && (access(buf, R_OK) == 0)) { + if (!preserve) { old_filesd = prop_dictionary_internalize_from_zfile(buf); - if (old_filesd == NULL) { + if (old_filesd) { + rv = xbps_remove_obsoletes(old_filesd, filesd); + if (rv != 0) { + prop_object_release(old_filesd); + prop_object_release(filesd); + free(buf); + return rv; + } + } else if (errno && errno != ENOENT) { prop_object_release(filesd); free(buf); return errno; } - rv = xbps_remove_obsoletes(old_filesd, filesd); - if (rv != 0) { - prop_object_release(old_filesd); - prop_object_release(filesd); - free(buf); - return rv; - } - prop_object_release(old_filesd); } /* * Now that all files were successfully unpacked, we @@ -362,8 +388,12 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg, } free(buf); } + +out: if (filesd) prop_object_release(filesd); + if (propsd) + prop_object_release(propsd); return rv; } @@ -388,6 +418,8 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg) if ((pkg_fd = open(binfile, O_RDONLY)) == -1) { rv = errno; + xbps_dbg_printf("cannot open '%s' for unpacking %s\n", + binfile, strerror(errno)); goto out; } @@ -403,9 +435,11 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg) archive_read_support_compression_all(ar); archive_read_support_format_tar(ar); - if ((rv = archive_read_open_fd(ar, pkg_fd, - ARCHIVE_READ_BLOCKSIZE)) != 0) + if (archive_read_open_fd(ar, pkg_fd, + ARCHIVE_READ_BLOCKSIZE) != 0) { + rv = errno; goto out; + } if ((rv = unpack_archive_fini(ar, pkg, pkgname, version)) != 0) goto out; diff --git a/lib/plist.c b/lib/plist.c index f9e2da23..175b18ee 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -51,6 +51,7 @@ xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj, if (!prop_dictionary_set(dict, key, obj)) { prop_object_release(dict); + errno = EINVAL; return false; } @@ -66,6 +67,7 @@ xbps_add_obj_to_array(prop_array_t array, prop_object_t obj) if (!prop_array_add(array, obj)) { prop_object_release(array); + errno = EINVAL; return false; } @@ -98,6 +100,7 @@ xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key, } prop_object_iterator_release(iter); + return rv; } @@ -116,8 +119,10 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, assert(fn != NULL); array = prop_dictionary_get(dict, key); - if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) + if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) { + xbps_dbg_printf("invalid key '%s' for dictionary", key); return EINVAL; + } if ((cnt = prop_array_count(array)) == 0) return 0; @@ -141,8 +146,11 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname) assert(pkgname != NULL); dict = prop_dictionary_internalize_from_zfile(plist); - if (dict == NULL) + if (dict == NULL) { + xbps_dbg_printf("cannot internalize %s for pkg %s: %s", + plist, pkgname, strerror(errno)); return NULL; + } obj = xbps_find_pkg_in_dict_by_name(dict, "packages", pkgname); if (obj == NULL) { @@ -162,7 +170,7 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern) prop_dictionary_t d, pkgd, rpkgd = NULL; pkg_state_t state = 0; - if ((d = xbps_regpkgs_dictionary_init()) == NULL) + if ((d = xbps_regpkgdb_dictionary_get()) == NULL) return NULL; if (bypattern) @@ -182,12 +190,14 @@ xbps_find_pkg_dict_installed(const char *str, bool bypattern) break; case XBPS_PKG_STATE_CONFIG_FILES: errno = ENOENT; + xbps_dbg_printf("'%s' installed but its state is " + "config-files\n",str); break; default: break; } out: - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return rpkgd; } @@ -213,8 +223,10 @@ xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, break; } prop_object_iterator_release(iter); - if (obj == NULL) + if (obj == NULL) { errno = ENOENT; + return NULL; + } return obj; } @@ -241,8 +253,10 @@ xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict, break; } prop_object_iterator_release(iter); - if (obj == NULL) + if (obj == NULL) { errno = ENOENT; + return NULL; + } return obj; } @@ -270,6 +284,7 @@ xbps_find_string_in_array(prop_array_t array, const char *val) } prop_object_iterator_release(iter); + return false; } @@ -282,8 +297,10 @@ xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key) assert(key != NULL); array = prop_dictionary_get(dict, key); - if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) + if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) { + errno = EINVAL; return NULL; + } return prop_array_iterator(array); } @@ -304,11 +321,16 @@ xbps_get_pkg_dict_from_metadata_plist(const char *pkgn, const char *plist) plistd = prop_dictionary_internalize_from_zfile(plistf); free(plistf); + if (plistd == NULL) { + xbps_dbg_printf("cannot read from plist file %s for %s: %s\n", + plist, pkgn, strerror(errno)); + return NULL; + } return plistd; } -int +bool xbps_remove_string_from_array(prop_array_t array, const char *str) { prop_object_t obj; @@ -321,7 +343,7 @@ xbps_remove_string_from_array(prop_array_t array, const char *str) iter = prop_array_iterator(array); if (iter == NULL) - return errno; + return false; while ((obj = prop_object_iterator_next(iter)) != NULL) { if (prop_string_equals_cstring(obj, str)) { @@ -331,16 +353,19 @@ xbps_remove_string_from_array(prop_array_t array, const char *str) idx++; } prop_object_iterator_release(iter); - if (found == false) - return ENOENT; + if (!found) { + errno = ENOENT; + return false; + } prop_array_remove(array, idx); - return 0; + return true; } -int -xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, +bool +xbps_remove_pkg_from_dict(prop_dictionary_t dict, + const char *key, const char *pkgname) { prop_array_t array; @@ -355,12 +380,16 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, assert(pkgname != NULL); array = prop_dictionary_get(dict, key); - if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) - return EINVAL; + if (array == NULL || prop_object_type(array) != PROP_TYPE_ARRAY) { + errno = EINVAL; + xbps_dbg_printf("invalid array type for key: %s pkgname: %s\n", + key, pkgname); + return false; + } iter = prop_array_iterator(array); if (iter == NULL) - return errno; + return false; /* Iterate over the array of dictionaries to find its index. */ while ((obj = prop_object_iterator_next(iter))) { @@ -372,41 +401,46 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, i++; } prop_object_iterator_release(iter); - if (found == true) + if (found) { prop_array_remove(array, i); - else - return ENOENT; + return true; + } - return 0; + errno = ENOENT; + + return false; } -int +bool xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist) { prop_dictionary_t pdict; - int rv = 0; assert(pkg != NULL); assert(plist != NULL); pdict = prop_dictionary_internalize_from_zfile(plist); - if (pdict == NULL) - return errno; + if (pdict == NULL) { + xbps_dbg_printf("'%s' cannot read from file %s: %s\n", + pkg, plist, strerror(errno)); + return false; + } - rv = xbps_remove_pkg_from_dict(pdict, "packages", pkg); - if (rv != 0) { + if (!xbps_remove_pkg_from_dict(pdict, "packages", pkg)) { prop_object_release(pdict); - return rv; + return false; } if (!prop_dictionary_externalize_to_zfile(pdict, plist)) { + xbps_dbg_printf("'%s' cannot write plist file %s: %s\n", + pkg, plist, strerror(errno)); prop_object_release(pdict); - return errno; + return false; } prop_object_release(pdict); - return 0; + return true; } /* diff --git a/lib/regpkgs_dictionary.c b/lib/regpkgdb_dictionary.c similarity index 76% rename from lib/regpkgs_dictionary.c rename to lib/regpkgdb_dictionary.c index 08b587e0..18fcdb4d 100644 --- a/lib/regpkgs_dictionary.c +++ b/lib/regpkgdb_dictionary.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2008-2009 Juan Romero Pardines. + * Copyright (c) 2008-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,7 +33,7 @@ #include "xbps_api_impl.h" /** - * @file lib/regpkgs_dictionary.c + * @file lib/regpkgdb_dictionary.c * @brief Package register database routines * @defgroup regpkgdb Package register database functions * @@ -57,43 +57,45 @@ * dictionary. */ -static prop_dictionary_t regpkgs_dict; -static size_t regpkgs_refcount; -static bool regpkgs_initialized; +static prop_dictionary_t regpkgdb_dict; +static size_t regpkgdb_refcount; +static bool regpkgdb_initialized; prop_dictionary_t -xbps_regpkgs_dictionary_init(void) +xbps_regpkgdb_dictionary_get(void) { char *plist; - if (regpkgs_initialized == false) { + if (regpkgdb_initialized == false) { plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) return NULL; - regpkgs_dict = prop_dictionary_internalize_from_zfile(plist); - if (regpkgs_dict == NULL) { + regpkgdb_dict = prop_dictionary_internalize_from_zfile(plist); + if (regpkgdb_dict == NULL) { free(plist); + xbps_dbg_printf("[regpkgdb] cannot internalize " + "regpkgdb_dict %s\n", strerror(errno)); return NULL; } free(plist); - regpkgs_initialized = true; - DPRINTF(("%s: initialized ok.\n", __func__)); + regpkgdb_initialized = true; + xbps_dbg_printf("%s: initialized ok.\n", __func__); } - regpkgs_refcount++; + regpkgdb_refcount++; - return regpkgs_dict; + return regpkgdb_dict; } void -xbps_regpkgs_dictionary_release(void) +xbps_regpkgdb_dictionary_release(void) { - if (--regpkgs_refcount > 0) + if (--regpkgdb_refcount > 0) return; - prop_object_release(regpkgs_dict); - regpkgs_dict = NULL; - regpkgs_initialized = false; - DPRINTF(("%s: released ok.\n", __func__)); + prop_object_release(regpkgdb_dict); + regpkgdb_dict = NULL; + regpkgdb_initialized = false; + xbps_dbg_printf("%s: released ok.\n", __func__); } diff --git a/lib/repository.c b/lib/repository.c index 4b86ffac..139ce5d1 100644 --- a/lib/repository.c +++ b/lib/repository.c @@ -69,6 +69,7 @@ xbps_repository_register(const char *uri) rv = errno; goto out; } + if (!prop_array_set_cstring_nocopy(array, 0, uri)) { rv = errno; goto out; @@ -78,6 +79,7 @@ xbps_repository_register(const char *uri) rv = errno; goto out; } + xbps_dbg_printf("Added repository into plist: %s\n", uri); } else { /* Append into the array, the plist file exists. */ array = prop_dictionary_get(dict, "repository-list"); @@ -97,14 +99,16 @@ xbps_repository_register(const char *uri) rv = errno; goto out; } + xbps_dbg_printf("Added repository into plist: %s\n", uri); } /* Write dictionary into plist file. */ if (!prop_dictionary_externalize_to_zfile(dict, plist)) { + rv = errno; + xbps_dbg_printf("%s: cannot externalize '%s' for '%s': %s\n", + __func__, plist, uri, strerror(errno)); if (obj) prop_object_release(obj); - rv = errno; - goto out; } out: @@ -142,14 +146,18 @@ xbps_repository_unregister(const char *uri) goto out; } - if ((rv = xbps_remove_string_from_array(array, uri)) == 0) { - /* Update plist file. */ - if (!prop_dictionary_externalize_to_zfile(dict, plist)) { - rv = errno; - goto out; - } + if (!xbps_remove_string_from_array(array, uri)) { + rv = errno; + goto out; } + /* Update plist file. */ + if (!prop_dictionary_externalize_to_zfile(dict, plist)) { + rv = errno; + goto out; + } + + xbps_dbg_printf("Removed repository from plist: %s\n", uri); /* * If it's a remote repository, also remove the stored XBPS_PKGINDEX * file and its directory. @@ -157,26 +165,27 @@ xbps_repository_unregister(const char *uri) if (xbps_check_is_repo_string_remote(uri)) { pkgindex = xbps_get_pkg_index_plist(uri); if (pkgindex == NULL) { - rv = EINVAL; + rv = errno; goto out; } + if (unlink(pkgindex) == -1) { + rv = errno; if (errno == ENOENT) { free(pkgindex); goto out; } - fprintf(stderr, "E: cannot remove pkgindex file at " - "%s: %s\n", pkgindex, strerror(errno)); + xbps_dbg_printf("%s cannot remove pkgindex file at " + "%s: %s\n", __func__, pkgindex, strerror(errno)); free(pkgindex); - rv = errno; goto out; } pkgindexdir = dirname(pkgindex); if (rmdir(pkgindexdir) == -1) { - fprintf(stderr, "E: cannot remove pkgindex dir at " - "%s: %s\n", pkgindexdir, strerror(errno)); - free(pkgindex); rv = errno; + xbps_dbg_printf("%s: cannot remove pkgindex dir at " + "%s: %s\n", __func__, pkgindexdir, strerror(errno)); + free(pkgindex); goto out; } free(pkgindex); diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index 06dd241a..a1bfa2b8 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -38,7 +38,7 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict, prop_dictionary_t dict; prop_array_t array; const char *pkgname, *pkgver; - int flags = xbps_get_flags(), rv = 0; + int rv = 0; pkg_state_t state = 0; assert(trans_dict != NULL); @@ -63,17 +63,18 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict, * Always set "not-installed" package state. Will be overwritten * to its correct state later. */ + xbps_dbg_printf_append("\n"); rv = xbps_set_pkg_state_dictionary(dict, XBPS_PKG_STATE_NOT_INSTALLED); if (rv != 0) { prop_object_release(dict); return rv; } + /* * Overwrite package state in dictionary if it was unpacked * previously. */ - rv = xbps_get_pkg_state_installed(pkgname, &state); - if (rv == 0) { + if ((rv = xbps_get_pkg_state_installed(pkgname, &state)) == 0) { if ((rv = xbps_set_pkg_state_dictionary(dict, state)) != 0) { prop_object_release(dict); return rv; @@ -97,9 +98,8 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict, prop_object_release(dict); return EINVAL; } - if (flags & XBPS_FLAG_VERBOSE) - printf("\n Added package '%s' into the transaction (%s).\n", - pkgver, repoloc); + xbps_dbg_printf("Added package '%s' into " + "the transaction (%s).\n", pkgver, repoloc); return 0; } @@ -152,8 +152,8 @@ add_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg) * if new dependency version is greater than current * one, store it. */ - DPRINTF(("Missing pkgdep name matched, curver: %s " - "newver: %s\n", curver, pkgver)); + xbps_dbg_printf("Missing pkgdep name matched, " + "curver: %s newver: %s\n", curver, pkgver); if (xbps_cmpver(curver, pkgver) <= 0) { add_pkgdep = false; free(curpkgnamedep); @@ -250,7 +250,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, pkg_state_t state = 0; const char *reqpkg, *reqvers, *pkg_queued, *repo_pkgver; char *pkgname; - int flags = xbps_get_flags(), rv = 0; + int rv = 0; iter = prop_array_iterator(pkg_rdeps_array); if (iter == NULL) @@ -266,26 +266,25 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, rv = EINVAL; break; } - if (flags & XBPS_FLAG_VERBOSE) { - if (originpkgn) - printf(" %s requires dependency '%s' " - "[direct]: ", originpkgn, reqpkg); - else - printf(" requires dependency '%s' " - "[indirect]: ", reqpkg); - } + if (originpkgn) + xbps_dbg_printf(" %s requires dependency '%s' " + "[direct]: ", originpkgn, reqpkg); + else + xbps_dbg_printf(" requires dependency '%s' " + "[indirect]: ", reqpkg); + /* * Check if required dep is satisfied and installed. */ rv = xbps_check_is_installed_pkg(reqpkg); if (rv == -1) { /* There was an error checking it... */ - DPRINTF(("Error matching reqdep %s\n", reqpkg)); + xbps_dbg_printf_append("error matching reqdep %s\n", + reqpkg); break; } else if (rv == 1) { /* Required pkg dependency is satisfied */ - if (flags & XBPS_FLAG_VERBOSE) - printf("satisfied and installed.\n"); + xbps_dbg_printf_append("satisfied and installed.\n"); rv = 0; continue; } @@ -318,8 +317,8 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, "pkgver", &pkg_queued); if (xbps_pkgpattern_match(pkg_queued, __UNCONST(reqpkg))) { - if (flags & XBPS_FLAG_VERBOSE) - printf("queued in the transaction.\n"); + xbps_dbg_printf_append( + "queued in the transaction.\n"); free(pkgname); continue; } @@ -340,19 +339,19 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, rv = add_missing_reqdep(trans_dict, reqpkg); if (rv != 0 && rv != EEXIST) { - DPRINTF(("add missing reqdep failed %s\n", - reqpkg)); + xbps_dbg_printf_append("add missing reqdep " + "failed %s\n", reqpkg); free(pkgname); break; } else if (rv == EEXIST) { - DPRINTF(("Missing dep %s already added.\n", - reqpkg)); + xbps_dbg_printf_append("missing dep %s " + "already added.\n", reqpkg); rv = 0; free(pkgname); continue; } else { - if (flags & XBPS_FLAG_VERBOSE) - printf("missing package in repository!\n"); + xbps_dbg_printf_append( + "missing package in repository!\n"); free(pkgname); continue; } @@ -401,9 +400,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, /* * Package is on repo, add it into the dictionary. */ - if ((rv = store_dependency(trans_dict, curpkgd, - repoloc)) != 0) { - DPRINTF(("store_dependency failed %s\n", reqpkg)); + rv = store_dependency(trans_dict, curpkgd, repoloc); + if (rv != 0) { + xbps_dbg_printf("store_dependency failed %s", + reqpkg); free(pkgname); break; } @@ -416,10 +416,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, if (rv == ENOENT) { rv = 0; } else if (rv == 0) { - DPRINTF(("Removed missing dep %s.\n", reqpkg)); + xbps_dbg_printf("Removed missing dep %s.\n", reqpkg); } else { - DPRINTF(("Removing missing dep %s returned %s\n", - reqpkg, strerror(rv))); + xbps_dbg_printf("Removing missing dep %s " + "returned %s\n", reqpkg, strerror(rv)); free(pkgname); break; } @@ -436,15 +436,15 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, /* * Iterate on required pkg to find more deps. */ - if (flags & XBPS_FLAG_VERBOSE) - printf(" Finding dependencies for '%s-%s' [%s]:\n", + xbps_dbg_printf_append("\n"); + xbps_dbg_printf("Finding dependencies for '%s-%s' [%s]:\n", pkgname, reqvers, originpkgn ? "direct" : "indirect"); free(pkgname); if ((rv = find_repo_deps(trans_dict, repo_dict, repoloc, NULL, curpkg_rdeps)) != 0) { - DPRINTF(("Error checking %s rundeps %s\n", - reqpkg, strerror(errno))); + xbps_dbg_printf("Error checking %s for rundeps: %s\n", + reqpkg, strerror(rv)); break; } } @@ -453,14 +453,34 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict, return rv; } +struct rpool_index_data { + prop_dictionary_t transd; + prop_array_t rdeps; + const char *pkgname; +}; + +static int +find_repo_deps_in_pool(struct repository_pool_index *rpi, void *arg, bool *done) +{ + struct rpool_index_data *rid = arg; + int rv; + + (void)done; + + rv = find_repo_deps(rid->transd, rpi->rpi_repod, rpi->rpi_uri, + rid->pkgname, rid->rdeps); + return rv; +} + + int HIDDEN xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict) { prop_array_t pkg_rdeps, missing_rdeps; - struct repository_pool *rpool; + struct rpool_index_data *rid; const char *pkgname, *pkgver; - int flags = xbps_get_flags(), rv = 0; + int rv = 0; assert(trans_dict != NULL); assert(repo_pkg_dict != NULL); @@ -469,31 +489,36 @@ xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict, if (pkg_rdeps == NULL) return 0; + rid = malloc(sizeof(struct rpool_index_data)); + if (rid == NULL) + return ENOMEM; + prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver); if ((rv = xbps_repository_pool_init()) != 0) - return rv; + goto out; - if (flags & XBPS_FLAG_VERBOSE) - printf(" Finding required dependencies for '%s':\n", pkgver); + xbps_dbg_printf("Finding required dependencies for '%s':\n", pkgver); /* * Iterate over the repository pool and find out if we have * all available binary packages. */ - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - /* - * This will find direct and indirect deps, - * if any of them is not there it will be added - * into the missing_deps array. - */ - if ((rv = find_repo_deps(trans_dict, rpool->rp_repod, - rpool->rp_uri, pkgname, pkg_rdeps)) != 0) { - DPRINTF(("Error '%s' while checking rundeps!\n", - strerror(rv))); - goto out; - } + rid->transd = trans_dict; + rid->rdeps = pkg_rdeps; + rid->pkgname = pkgname; + + /* + * This will find direct and indirect deps, + * if any of them is not there it will be added + * into the missing_deps array. + */ + rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid); + if (rv != 0) { + xbps_dbg_printf("Error '%s' while checking rundeps!\n", + strerror(errno)); + goto out; } /* @@ -507,16 +532,20 @@ xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict, * Iterate one more time, but this time with missing deps * that were found in previous pass. */ - DPRINTF(("Checking for missing deps in %s.\n", pkgname)); - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - if ((rv = find_repo_deps(trans_dict, rpool->rp_repod, - rpool->rp_uri, pkgname, missing_rdeps)) != 0) { - DPRINTF(("Error '%s' while checking for " - "missing rundeps!\n", strerror(rv))); - goto out; - } + rid->rdeps = missing_rdeps; + rid->pkgname = NULL; + + xbps_dbg_printf("Checking for missing deps in %s.\n", pkgname); + rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid); + if (rv != 0) { + xbps_dbg_printf("Error '%s' while checking for " + "missing rundeps!\n", strerror(errno)); + goto out; } out: + if (rid) + free(rid); + xbps_repository_pool_release(); return rv; diff --git a/lib/repository_findpkg.c b/lib/repository_findpkg.c index 50545d52..ef0144bf 100644 --- a/lib/repository_findpkg.c +++ b/lib/repository_findpkg.c @@ -56,6 +56,16 @@ static prop_dictionary_t trans_dict; static bool trans_dict_initialized; +/* + * This creates the transaction dictionary with two arrays, one for + * dependencies not yet sorted and another one for missing dependencies. + * + * Before returning the dictionary to the caller, package dependencies in + * the "unsorted_deps" array will be sorted and moved to another + * array called "packages". If there are no missing dependencies, the + * "missing_deps" array will be removed. + * + */ static int create_transaction_dictionary(void) { @@ -77,31 +87,31 @@ create_transaction_dictionary(void) unsorted = prop_array_create(); if (unsorted == NULL) { - rv = ENOMEM; - goto fail2; - } + rv = ENOMEM; + goto fail2; + } - if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) { - rv = EINVAL; - goto fail3; + if (!xbps_add_obj_to_dict(trans_dict, missing, "missing_deps")) { + rv = EINVAL; + goto fail3; } if (!xbps_add_obj_to_dict(trans_dict, unsorted, "unsorted_deps")) { - rv = EINVAL; - goto fail3; - } + rv = EINVAL; + goto fail3; + } trans_dict_initialized = true; - return rv; + return rv; fail3: - prop_object_release(unsorted); + prop_object_release(unsorted); fail2: - prop_object_release(missing); + prop_object_release(missing); fail: - prop_object_release(trans_dict); + prop_object_release(trans_dict); - return rv; + return rv; } static int @@ -115,7 +125,7 @@ compute_transaction_sizes(void) iter = xbps_get_array_iter_from_dict(trans_dict, "packages"); if (iter == NULL) - return -1; + return EINVAL; while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "trans-action", &tract); @@ -139,7 +149,7 @@ compute_transaction_sizes(void) */ if (!prop_dictionary_set_uint64(trans_dict, "total-installed-size", instsize)) { - rv = -1; + rv = EINVAL; goto out; } /* @@ -148,7 +158,7 @@ compute_transaction_sizes(void) */ if (!prop_dictionary_set_uint64(trans_dict, "total-download-size", dlsize)) { - rv = -1; + rv = EINVAL; goto out; } out: @@ -172,11 +182,14 @@ set_pkg_state(prop_dictionary_t pkgd, const char *pkgname) */ rv = xbps_get_pkg_state_installed(pkgname, &state); if (rv == 0) { + if (state == XBPS_PKG_STATE_INSTALLED) + return 0; + if ((rv = xbps_set_pkg_state_dictionary(pkgd, state)) != 0) return rv; - } else if (rv == ENOENT) + } else if (rv == ENOENT) rv = 0; - + return rv; } @@ -186,23 +199,23 @@ xbps_repository_get_transaction_dict(void) int rv = 0; if (trans_dict_initialized == false) { - errno = ENOENT; + errno = ENXIO; return NULL; } /* - * Sort package list if necessary. + * Sort package dependencies if necessary. */ if ((rv = xbps_sort_pkg_deps(trans_dict)) != 0) { + errno = rv; /* - * If there are missing deps (errno==ENOENT) + * If there are missing deps (ENOENT) * return the dictionary, the client should always * check if that's the case. */ - if (errno == ENOENT) + if (rv == ENOENT) return trans_dict; - errno = rv; return NULL; } @@ -213,6 +226,11 @@ xbps_repository_get_transaction_dict(void) if (compute_transaction_sizes() != 0) return NULL; + /* + * Remove the "missing_deps" array now that it's not needed. + */ + prop_dictionary_remove(trans_dict, "missing_deps"); + return trans_dict; } @@ -229,16 +247,13 @@ xbps_repository_update_allpkgs(void) /* * Prepare dictionary with all registered packages. */ - dict = xbps_regpkgs_dictionary_init(); + dict = xbps_regpkgdb_dictionary_get(); if (dict == NULL) - return ENOENT; - - if ((rv = xbps_repository_pool_init()) != 0) - goto out; + return errno; iter = xbps_get_array_iter_from_dict(dict, "packages"); if (iter == NULL) { - rv = EINVAL; + rv = errno; goto out; } @@ -248,40 +263,96 @@ xbps_repository_update_allpkgs(void) */ while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - rv = xbps_repository_update_pkg(pkgname, obj); - if (rv == ENOENT) - continue; - else if (rv == EEXIST) { - rv = 0; - continue; - } else if (rv != 0) - break; + if ((rv = xbps_repository_update_pkg(pkgname)) != 0) { + if (rv == ENOENT || rv == EEXIST) + continue; + xbps_dbg_printf("[update-all] '%s' returned: %s\n", + pkgname, strerror(rv)); + goto out; + } newpkg_found = true; } prop_object_iterator_release(iter); - if (rv != ENOENT && !newpkg_found) - rv = ENOPKG; + if (newpkg_found) + rv = 0; + else + rv = ENXIO; + out: - xbps_repository_pool_release(); - xbps_regpkgs_dictionary_release(); + xbps_regpkgdb_dictionary_release(); return rv; } -int -xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) +struct rpool_index_data { + prop_dictionary_t pkg_repod; + const char *pkgname; + const char *repo_uri; + bool newpkgfound; +}; + +static int +repo_find_updated_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done) { - prop_dictionary_t pkgrd = NULL; - prop_array_t unsorted; - struct repository_pool *rpool; + struct rpool_index_data *rid = arg; + prop_dictionary_t instpkgd; const char *repover, *instver; - int flags = xbps_get_flags(), rv = 0; - bool newpkg_found = false; + + /* + * Get the package dictionary from current repository. + * If it's not there, pass to the next repository. + */ + rid->pkg_repod = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod, + "packages", rid->pkgname); + if (rid->pkg_repod == NULL) { + if (errno && errno != ENOENT) + return errno; + + xbps_dbg_printf("Package '%s' not found in repository " + "'%s'.\n", rid->pkgname, rpi->rpi_uri); + } else { + /* + * Check if version in repository is greater than + * the version currently installed. + */ + instpkgd = xbps_find_pkg_dict_installed(rid->pkgname, false); + prop_dictionary_get_cstring_nocopy(instpkgd, + "version", &instver); + prop_dictionary_get_cstring_nocopy(rid->pkg_repod, + "version", &repover); + prop_object_release(instpkgd); + + if (xbps_cmpver(repover, instver) > 0) { + xbps_dbg_printf("Found '%s-%s' (installed: %s) " + "in repository '%s'.\n", rid->pkgname, repover, + instver, rpi->rpi_uri); + /* + * New package version found, exit from the loop. + */ + rid->newpkgfound = true; + rid->repo_uri = rpi->rpi_uri; + *done = true; + return 0; + } + xbps_dbg_printf("Skipping '%s-%s' (installed: %s) " + "from repository '%s'\n", rid->pkgname, repover, instver, + rpi->rpi_uri); + } + + return 0; +} + +int +xbps_repository_update_pkg(const char *pkgname) +{ + prop_array_t unsorted; + prop_dictionary_t pkgd; + struct rpool_index_data *rid; + int rv = 0; assert(pkgname != NULL); - assert(instpkg != NULL); /* * Prepare repository pool queue. @@ -289,51 +360,42 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) if ((rv = xbps_repository_pool_init()) != 0) return rv; - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - /* - * Get the package dictionary from current repository. - * If it's not there, pass to the next repository. - */ - pkgrd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod, - "packages", pkgname); - if (pkgrd == NULL) { - if (errno && errno != ENOENT) { - rv = errno; - goto out; - } - if (flags & XBPS_FLAG_VERBOSE) - printf("Package '%s' not found in repository " - "'%s'.\n", pkgname, rpool->rp_uri); - } else if (pkgrd != NULL) { - /* - * Check if version in repository is greater than - * the version currently installed. - */ - prop_dictionary_get_cstring_nocopy(instpkg, - "version", &instver); - prop_dictionary_get_cstring_nocopy(pkgrd, - "version", &repover); - if (xbps_cmpver(repover, instver) > 0) { - if (flags & XBPS_FLAG_VERBOSE) { - printf("Found '%s-%s' in repository " - "'%s'.\n", pkgname, repover, - rpool->rp_uri); - } - newpkg_found = true; - break; - } - if (flags & XBPS_FLAG_VERBOSE) - printf("Skipping '%s-%s' from repository " - "'%s'.\n", pkgname, repover, rpool->rp_uri); - continue; - } + rid = calloc(1, sizeof(struct rpool_index_data)); + if (rid == NULL) { + rv = errno; + goto out; } - if (!newpkg_found) { + + /* + * Check if package is not installed. + */ + pkgd = xbps_find_pkg_dict_installed(pkgname, false); + if (pkgd == NULL) { + rv = ENODEV; + goto out; + } + prop_object_release(pkgd); + + /* + * Find out if a new package version exists in repositories. + */ + rid->pkgname = pkgname; + rv = xbps_repository_pool_foreach(repo_find_updated_pkg_cb, rid); + if (rv != 0) + goto out; + + /* + * No new versions found in repository pool. + */ + if (rid->newpkgfound == false) { rv = EEXIST; goto out; } - if (pkgrd == NULL) { + /* + * Package couldn't be found in repository pool. + */ + if (rid->pkg_repod == NULL) { rv = ENOENT; goto out; } @@ -346,7 +408,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) /* * Set repository in pkg dictionary. */ - if (!prop_dictionary_set_cstring(pkgrd, "repository", rpool->rp_uri)) { + if (!prop_dictionary_set_cstring(rid->pkg_repod, + "repository", rid->repo_uri)) { rv = errno; goto out; } @@ -354,7 +417,8 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) /* * Construct the dependency chain for this package. */ - if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0) + rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod); + if (rv != 0) goto out; /* @@ -363,7 +427,7 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) */ unsorted = prop_dictionary_get(trans_dict, "unsorted_deps"); if (unsorted == NULL) { - rv = EINVAL; + rv = errno; goto out; } @@ -371,66 +435,96 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) * Always set "not-installed" package state. Will be overwritten * to its correct state later. */ - if ((rv = set_pkg_state(pkgrd, pkgname)) != 0) + if ((rv = set_pkg_state(rid->pkg_repod, pkgname)) != 0) goto out; - if (!prop_dictionary_set_cstring_nocopy(pkgrd, + /* + * Set trans-action obj in pkg dictionary to "update". + */ + if (!prop_dictionary_set_cstring_nocopy(rid->pkg_repod, "trans-action", "update")) { rv = errno; goto out; } - if (!prop_array_add(unsorted, pkgrd)) + /* + * Added package dictionary from repository into the "unsorted" + * array in the transaction dictionary. + */ + if (!prop_array_add(unsorted, rid->pkg_repod)) { rv = errno; + goto out; + } out: + if (rid) + free(rid); + xbps_repository_pool_release(); return rv; } -int -xbps_repository_install_pkg(const char *pkg, bool bypattern) +static int +repo_find_new_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done) { - prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL; + struct rpool_index_data *rid = arg; + const char *pkgver; + + /* + * Finds a package dictionary from a repository pkg-index dictionary. + */ + rid->pkg_repod = xbps_find_pkg_in_dict_by_pattern( + rpi->rpi_repod, "packages", rid->pkgname); + if (rid->pkg_repod == NULL) { + if (errno && errno != ENOENT) + return errno; + } else { + prop_dictionary_get_cstring_nocopy(rid->pkg_repod, + "pkgver", &pkgver); + xbps_dbg_printf("Found package '%s' from repository %s.\n", + pkgver, rpi->rpi_uri); + + rid->repo_uri = rpi->rpi_uri; + *done = true; + } + + return 0; +} + +int +xbps_repository_install_pkg(const char *pkg) +{ + prop_dictionary_t origin_pkgrd = NULL; prop_array_t unsorted; - struct repository_pool *rpool; - const char *pkgname, *pkgver; - int flags = xbps_get_flags(), rv = 0; + struct rpool_index_data *rid; + const char *pkgname; + int rv = 0; assert(pkg != NULL); if ((rv = xbps_repository_pool_init()) != 0) return rv; - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - /* - * Get the package dictionary from current repository. - * If it's not there, pass to the next repository. - */ - if (bypattern) - pkgrd = xbps_find_pkg_in_dict_by_pattern( - rpool->rp_repod, "packages", pkg); - else - pkgrd = xbps_find_pkg_in_dict_by_name( - rpool->rp_repod, "packages", pkg); - - if (pkgrd == NULL) { - if (errno && errno != ENOENT) { - rv = errno; - goto out; - } - } else if (pkgrd != NULL) { - if (flags & XBPS_FLAG_VERBOSE) { - prop_dictionary_get_cstring_nocopy(pkgrd, - "pkgver", &pkgver); - printf("Found package '%s' (%s).\n", - pkgver, rpool->rp_uri); - } - break; - } + rid = calloc(1, sizeof(struct rpool_index_data)); + if (rid == NULL) { + rv = errno; + goto out; } - if (pkgrd == NULL) { + + /* + * Get the package dictionary from current repository. + * If it's not there, pass to the next repository. + */ + rid->pkgname = pkg; + rv = xbps_repository_pool_foreach(repo_find_new_pkg_cb, rid); + if (rv != 0) + goto out; + + /* + * Package couldn't be found in repository pool... EAGAIN. + */ + if (rid->pkg_repod == NULL) { rv = EAGAIN; goto out; } @@ -438,44 +532,38 @@ xbps_repository_install_pkg(const char *pkg, bool bypattern) /* * Create the transaction dictionary. */ - if ((rv = create_transaction_dictionary()) != 0) + if ((rv = create_transaction_dictionary()) != 0) goto out; /* * Check that this pkg hasn't been added previously into * the transaction. */ - if (bypattern) { - if (xbps_find_pkg_in_dict_by_pattern(trans_dict, - "unsorted_deps", pkg)) - goto out; - } else { - if (xbps_find_pkg_in_dict_by_name(trans_dict, - "unsorted_deps", pkg)) - goto out; - } - /* - * Set repository in pkg dictionary. - */ - if (!prop_dictionary_set_cstring(pkgrd, "repository", rpool->rp_uri)) { - rv = errno; - goto out; - } - origin_pkgrd = prop_dictionary_copy(pkgrd); - - prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname); - - /* - * Prepare required package dependencies. - */ - if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0) + if (xbps_find_pkg_in_dict_by_pattern(trans_dict, + "unsorted_deps", pkg)) goto out; - if (flags & XBPS_FLAG_VERBOSE) - printf("\n"); + /* + * Set repository location in pkg dictionary. + */ + if (!prop_dictionary_set_cstring(rid->pkg_repod, + "repository", rid->repo_uri)) { + rv = EINVAL; + goto out; + } + origin_pkgrd = prop_dictionary_copy(rid->pkg_repod); + prop_dictionary_get_cstring_nocopy(rid->pkg_repod, "pkgname", &pkgname); /* - * Add required package dictionary into the unsorted deps dictionary, + * Prepare required package dependencies and add them into the + * "unsorted" array in transaction dictionary. + */ + rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod); + if (rv != 0) + goto out; + + /* + * Add required package dictionary into the unsorted array and * set package state as not yet installed. */ unsorted = prop_dictionary_get(trans_dict, "unsorted_deps"); @@ -486,15 +574,27 @@ xbps_repository_install_pkg(const char *pkg, bool bypattern) if ((rv = set_pkg_state(origin_pkgrd, pkgname)) != 0) goto out; + /* + * Set trans-action obj in pkg dictionary to "install". + */ if (!prop_dictionary_set_cstring_nocopy(origin_pkgrd, "trans-action", "install")) { + rv = EINVAL; + goto out; + } + /* + * Add the pkg dictionary from repository's index dictionary into + * the "unsorted" array in transaction dictionary. + */ + if (!prop_array_add(unsorted, origin_pkgrd)) { rv = errno; goto out; } - if (!prop_array_add(unsorted, origin_pkgrd)) - rv = errno; out: + if (rid) + free(rid); + if (origin_pkgrd) prop_object_release(origin_pkgrd); diff --git a/lib/repository_plist.c b/lib/repository_plist.c index 356a7a84..8cf315ec 100644 --- a/lib/repository_plist.c +++ b/lib/repository_plist.c @@ -221,12 +221,45 @@ xbps_repository_get_pkg_plist_dict_from_url(const char *url, const char *plistf) return plistd; } +struct rpool_index_data { + prop_dictionary_t plistd; + const char *plistf; + const char *pkgname; +}; + +static int +repo_find_pkg_plistd_cb(struct repository_pool_index *rpi, void *arg, bool *done) +{ + struct rpool_index_data *rid = arg; + prop_dictionary_t pkgd; + char *url; + + pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod, + "packages", rid->pkgname); + if (pkgd == NULL) { + if (errno != ENOENT) + return errno; + + return 0; + } + url = xbps_repository_get_path_from_pkg_dict(pkgd, rpi->rpi_uri); + if (url == NULL) + return EINVAL; + + rid->plistd = + xbps_repository_get_pkg_plist_dict_from_url(url, rid->plistf); + free(url); + if (prop_object_type(rid->plistd) == PROP_TYPE_DICTIONARY) + *done = true; + + return 0; +} + prop_dictionary_t xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf) { - prop_dictionary_t plistd = NULL, pkgd; - struct repository_pool *rpool; - char *url = NULL; + prop_dictionary_t plistd; + struct rpool_index_data *rid; int rv = 0; if ((rv = xbps_repository_pool_init()) != 0) { @@ -234,6 +267,10 @@ xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf) return NULL; } + rid = malloc(sizeof(struct rpool_index_data)); + if (rid == NULL) + goto out; + /* * Iterate over the the repository pool and search for a plist file * in the binary package named 'pkgname'. The plist file will be @@ -243,27 +280,12 @@ xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf) * This will work locally and remotely, thanks to libarchive and * libfetch! */ - SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { - pkgd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod, - "packages", pkgname); - if (pkgd == NULL) { - if (errno != ENOENT) - break; - continue; - } - url = xbps_repository_get_path_from_pkg_dict(pkgd, - rpool->rp_uri); - if (url == NULL) - break; - plistd = xbps_repository_get_pkg_plist_dict_from_url(url, - plistf); - if (plistd != NULL) { - free(url); - break; - } - free(url); - } - + rid->pkgname = pkgname; + rid->plistf = plistf; + rv = xbps_repository_pool_foreach(repo_find_pkg_plistd_cb, rid); + plistd = rid->plistd; + free(rid); +out: xbps_repository_pool_release(); if (plistd == NULL) errno = ENOENT; diff --git a/lib/repository_pool.c b/lib/repository_pool.c index f6b25a66..0b396499 100644 --- a/lib/repository_pool.c +++ b/lib/repository_pool.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Juan Romero Pardines. + * Copyright (c) 2009-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ #include #include "xbps_api_impl.h" +#include "queue.h" /** * @file lib/repository_pool.c @@ -38,6 +39,14 @@ * @defgroup repopool Repository pool init/fini functions */ +struct repository_pool { + SIMPLEQ_ENTRY(repository_pool) rp_entries; + struct repository_pool_index *rpi; +}; + +static SIMPLEQ_HEAD(rpool_head, repository_pool) rpool_queue = + SIMPLEQ_HEAD_INITIALIZER(rpool_queue); + static size_t repolist_refcnt; static bool repolist_initialized; @@ -58,19 +67,19 @@ xbps_repository_pool_init(void) return 0; } - SIMPLEQ_INIT(&rp_queue); - plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REPOLIST); if (plist == NULL) { - rv = EINVAL; + rv = errno; goto out; } dict = prop_dictionary_internalize_from_zfile(plist); if (dict == NULL) { - free(plist); rv = errno; + free(plist); + xbps_dbg_printf("%s: cannot internalize plist %s: %s\n", + __func__, plist, strerror(errno)); goto out; } free(plist); @@ -96,7 +105,7 @@ xbps_repository_pool_init(void) plist = xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj)); if (plist == NULL) { - rv = EINVAL; + rv = errno; goto out; } @@ -106,16 +115,26 @@ xbps_repository_pool_init(void) goto out; } - rpool->rp_uri = prop_string_cstring(obj); - if (rpool->rp_uri == NULL) { - free(rpool); - free(plist); + rpool->rpi = malloc(sizeof(struct repository_pool_index)); + if (rpool->rpi == NULL) { rv = errno; + free(rpool); goto out; } - rpool->rp_repod = prop_dictionary_internalize_from_zfile(plist); - if (rpool->rp_repod == NULL) { - free(rpool->rp_uri); + + rpool->rpi->rpi_uri = prop_string_cstring(obj); + if (rpool->rpi->rpi_uri == NULL) { + rv = errno; + free(rpool->rpi); + free(rpool); + free(plist); + goto out; + } + rpool->rpi->rpi_repod = + prop_dictionary_internalize_from_zfile(plist); + if (rpool->rpi->rpi_repod == NULL) { + free(rpool->rpi->rpi_uri); + free(rpool->rpi); free(rpool); free(plist); if (errno == ENOENT) { @@ -124,10 +143,14 @@ xbps_repository_pool_init(void) continue; } rv = errno; + xbps_dbg_printf("%s: cannot internalize plist %s: %s\n", + __func__, plist, strerror(errno)); goto out; } free(plist); - SIMPLEQ_INSERT_TAIL(&rp_queue, rpool, rp_entries); + xbps_dbg_printf("Registered repository '%s'\n", + rpool->rpi->rpi_uri); + SIMPLEQ_INSERT_TAIL(&rpool_queue, rpool, rp_entries); } if (ntotal - nmissing == 0) @@ -135,13 +158,13 @@ xbps_repository_pool_init(void) repolist_initialized = true; repolist_refcnt = 1; - DPRINTF(("%s: initialized ok.\n", __func__)); + xbps_dbg_printf("%s: initialized ok.\n", __func__); out: if (iter) prop_object_iterator_release(iter); if (dict) prop_object_release(dict); - if (rv != 0) + if (rv != 0) xbps_repository_pool_release(); return rv; @@ -156,13 +179,37 @@ xbps_repository_pool_release(void) if (--repolist_refcnt > 0) return; - while ((rpool = SIMPLEQ_FIRST(&rp_queue)) != NULL) { - SIMPLEQ_REMOVE(&rp_queue, rpool, repository_pool, rp_entries); - prop_object_release(rpool->rp_repod); - free(rpool->rp_uri); + while ((rpool = SIMPLEQ_FIRST(&rpool_queue)) != NULL) { + SIMPLEQ_REMOVE(&rpool_queue, rpool, repository_pool, rp_entries); + xbps_dbg_printf("Unregistered repository '%s'\n", + rpool->rpi->rpi_uri); + prop_object_release(rpool->rpi->rpi_repod); + free(rpool->rpi->rpi_uri); + free(rpool->rpi); free(rpool); } repolist_refcnt = 0; repolist_initialized = false; - DPRINTF(("%s: released ok.\n", __func__)); + xbps_dbg_printf("%s: released ok.\n", __func__); +} + +int +xbps_repository_pool_foreach( + int (*fn)(struct repository_pool_index *, void *, bool *), + void *arg) +{ + struct repository_pool *rpool; + int rv = 0; + bool done = false; + + if (!repolist_initialized) + return 0; + + SIMPLEQ_FOREACH(rpool, &rpool_queue, rp_entries) { + rv = (*fn)(rpool->rpi, arg, &done); + if (rv != 0 || done) + break; + } + + return rv; } diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 917de07f..d23d00a0 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Juan Romero Pardines. + * Copyright (c) 2009-2010 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ #include #include "xbps_api_impl.h" +#include "queue.h" struct sorted_dependency { SIMPLEQ_ENTRY(sorted_dependency) chain; @@ -44,20 +45,15 @@ find_sorteddep_by_name(const char *pkgname) { struct sorted_dependency *sdep = NULL; const char *curpkgname; - bool found = false; SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { prop_dictionary_get_cstring_nocopy(sdep->dict, "pkgname", &curpkgname); - if (strcmp(pkgname, curpkgname) == 0) { - found = true; - break; - } + if (strcmp(pkgname, curpkgname) == 0) + return sdep; } - if (!found) - return NULL; - return sdep; + return NULL; } int HIDDEN @@ -107,13 +103,14 @@ again: while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - DPRINTF(("Sorting package: %s\n", pkgver)); + xbps_dbg_printf("Sorting package '%s': ", pkgver); if (find_sorteddep_by_name(pkgname) != NULL) { - DPRINTF(("Skipping %s already queued.\n", pkgname)); + xbps_dbg_printf_append("skipping, already queued.\n", + pkgname); continue; } - sdep = malloc(sizeof(*sdep)); + sdep = malloc(sizeof(struct sorted_dependency)); if (sdep == NULL) { rv = ENOMEM; goto out; @@ -124,8 +121,8 @@ again: */ rundeps = prop_dictionary_get(obj, "run_depends"); if (rundeps == NULL || prop_array_count(rundeps) == 0) { - DPRINTF(("Adding %s (no rundeps) into the sorted " - "queue.\n", pkgver)); + xbps_dbg_printf_append("added (no rundeps) into " + "the sorted queue.\n"); sdep->dict = prop_dictionary_copy(obj); SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); cnt++; @@ -133,15 +130,18 @@ again: } iter2 = prop_array_iterator(rundeps); if (iter2 == NULL) { - free(sdep); rv = ENOMEM; + free(sdep); goto out; } + /* * Iterate over the run_depends array, and find out if they * were already added in the sorted list. */ - DPRINTF(("Checking %s run_depends for sorting...\n", pkgver)); + xbps_dbg_printf_append("\n"); + xbps_dbg_printf("Checking '%s' run depends for sorting...\n", + pkgver); while ((obj2 = prop_object_iterator_next(iter2)) != NULL) { str = prop_string_cstring_nocopy(obj2); if (str == NULL) { @@ -152,22 +152,22 @@ again: pkgnamedep = xbps_get_pkgpattern_name(str); if (pkgnamedep == NULL) { free(sdep); - rv = errno; + rv = EINVAL; goto out; } - DPRINTF(("Required dependency %s: ", str)); + xbps_dbg_printf(" Required dependency '%s': ", str); /* * If dependency is already satisfied or queued, * pass to the next one. */ if (xbps_check_is_installed_pkg(str)) { rundepscnt++; - DPRINTF(("installed.\n")); + xbps_dbg_printf_append("installed.\n"); } else if (find_sorteddep_by_name(pkgnamedep) != NULL) { - DPRINTF(("queued.\n")); + xbps_dbg_printf_append("queued.\n"); rundepscnt++; } else { - DPRINTF(("not installed or queued.\n")); + xbps_dbg_printf_append("not installed.\n"); } free(pkgnamedep); } @@ -175,23 +175,25 @@ again: /* Add dependency if all its required deps are already added */ if (prop_array_count(rundeps) == rundepscnt) { - DPRINTF(("Adding package %s to the sorted queue.\n", - pkgver)); sdep->dict = prop_dictionary_copy(obj); SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); + xbps_dbg_printf("Added package '%s' to the sorted " + "queue (all rundeps satisfied).\n\n", pkgver); rundepscnt = 0; cnt++; continue; } - DPRINTF(("Unsorted package %s has missing rundeps.\n", pkgver)); + xbps_dbg_printf("Unsorted package '%s' has missing " + "rundeps (missing %zu).\n\n", pkgver, + prop_array_count(rundeps) - rundepscnt); free(sdep); rundepscnt = 0; } /* Iterate until all deps are processed. */ if (cnt < ndeps) { - DPRINTF(("Missing required deps! cnt: %zu ndeps: %zu\n", - cnt, ndeps)); + xbps_dbg_printf("Missing required deps! queued: %zu " + "required: %zu.\n", cnt, ndeps); prop_object_iterator_reset(iter); goto again; } @@ -203,7 +205,7 @@ again: while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) { if (!prop_array_add(sorted, sdep->dict)) { free(sdep); - rv = errno; + rv = EINVAL; goto out; } SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain);