From 508f119bc9d0f78fbec4b7ae2777758bc53bdf08 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Wed, 27 Jul 2011 17:13:54 +0200 Subject: [PATCH] Moved install transaction code to libxbps, see NEWS file. --- NEWS | 11 + bin/xbps-bin/check.c | 8 +- bin/xbps-bin/defs.h | 38 ++- bin/xbps-bin/fetch.c | 13 +- bin/xbps-bin/find-files.c | 2 +- bin/xbps-bin/install.c | 443 ++++++++------------------- bin/xbps-bin/main.c | 82 +++-- bin/xbps-bin/question.c | 4 +- bin/xbps-bin/remove.c | 14 +- bin/xbps-bin/show-deps.c | 4 +- bin/xbps-repo/defs.h | 2 +- bin/xbps-repo/index.c | 2 +- bin/xbps-repo/main.c | 30 +- bin/xbps-uhelper/main.c | 26 +- etc/xbps-conf.plist | 6 +- include/xbps_api.h | 582 ++++++++++++++++++++++-------------- lib/Makefile | 2 +- lib/download.c | 38 +-- lib/initend.c | 76 ++++- lib/package_configure.c | 32 +- lib/package_orphans.c | 4 +- lib/package_purge.c | 4 +- lib/package_register.c | 6 +- lib/package_remove.c | 4 +- lib/package_requiredby.c | 2 +- lib/package_state.c | 2 +- lib/package_unpack.c | 66 ++-- lib/plist.c | 2 +- lib/plist_find.c | 2 +- lib/regpkgdb_dictionary.c | 2 +- lib/repository_findpkg.c | 2 +- lib/repository_pool.c | 4 +- lib/repository_sync_index.c | 2 +- lib/transaction_commit.c | 360 ++++++++++++++++++++++ lib/util.c | 4 +- 35 files changed, 1146 insertions(+), 735 deletions(-) create mode 100644 lib/transaction_commit.c diff --git a/NEWS b/NEWS index 17b08544..bcdd2d5e 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,16 @@ xbps-0.10.0 (???): + * Moved install transaction code to libxbps. The API has been extended + with xbps_transaction_commit() which expects the transaction dictionary + as its argument. This function will execute transaction tasks, like + removing, updating, installing and configuring packages as defined + in the transaction dictionary. + + * The 'cachedir' option in configuration file now can be changed to + be relative to the rootdir if the first character is not '/'. The + -c flag in xbps-bin(8) still expects a full path and if set, overrides + the setting in configuration file. + * xbps-bin(8): the 'show', 'show-deps' and 'show-revdeps' targets now work with virtual packages. diff --git a/bin/xbps-bin/check.c b/bin/xbps-bin/check.c index ce9adcaa..6086db70 100644 --- a/bin/xbps-bin/check.c +++ b/bin/xbps-bin/check.c @@ -51,7 +51,7 @@ */ int -xbps_check_pkg_integrity_all(void) +check_pkg_integrity_all(void) { const struct xbps_handle *xhp; prop_object_t obj; @@ -71,7 +71,7 @@ xbps_check_pkg_integrity_all(void) prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "version", &version); printf("Checking %s-%s ...\n", pkgname, version); - if ((rv = xbps_check_pkg_integrity(pkgname)) != 0) + if ((rv = check_pkg_integrity(pkgname)) != 0) nbrokenpkgs++; npkgs++; } @@ -86,9 +86,9 @@ out: } int -xbps_check_pkg_integrity(const char *pkgname) +check_pkg_integrity(const char *pkgname) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t pkgd, propsd = NULL, filesd = NULL; prop_array_t array; prop_object_t obj; diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index e6bf6354..837a79eb 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -32,26 +32,38 @@ #include -int xbps_install_new_pkg(const char *); -int xbps_update_pkg(const char *); -int xbps_autoupdate_pkgs(bool, bool); -int xbps_autoremove_pkgs(bool, bool); -int xbps_exec_transaction(bool, bool); -int xbps_remove_installed_pkgs(int, char **, bool, bool, bool, bool); -int xbps_check_pkg_integrity(const char *); -int xbps_check_pkg_integrity_all(void); -int xbps_show_pkg_deps(const char *); -int xbps_show_pkg_reverse_deps(const char *); +/* from install.c */ +int install_new_pkg(const char *); +int update_pkg(const char *); +int autoupdate_pkgs(bool, bool); +int autoremove_pkgs(bool, bool); +int exec_transaction(bool, bool); +void transaction_cb(struct xbps_transaction_cb_data *); +void transaction_err_cb(struct xbps_transaction_cb_data *); + +int remove_installed_pkgs(int, char **, bool, bool, bool, bool); + +/* from check.c */ +int check_pkg_integrity(const char *); +int check_pkg_integrity_all(void); + +/* from show-deps.c */ +int show_pkg_deps(const char *); +int show_pkg_reverse_deps(const char *); + +/* from show-info-files.c */ int show_pkg_info_from_metadir(const char *); int show_pkg_files_from_metadir(const char *); + +/* from find-files.c */ int find_files_in_packages(const char *); /* from question.c */ -bool xbps_yesno(const char *, ...); -bool xbps_noyes(const char *, ...); +bool yesno(const char *, ...); +bool noyes(const char *, ...); /* from fetch.c */ -void fetch_file_progress_cb(void *); +void fetch_file_progress_cb(struct xbps_fetch_cb_data *); /* From util.c */ int show_pkg_files(prop_dictionary_t); diff --git a/bin/xbps-bin/fetch.c b/bin/xbps-bin/fetch.c index 03d2afdd..cb6e40fe 100644 --- a/bin/xbps-bin/fetch.c +++ b/bin/xbps-bin/fetch.c @@ -52,7 +52,7 @@ struct xferstat { * Compute and display ETA */ static const char * -stat_eta(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) +stat_eta(struct xbps_fetch_cb_data *xfpd, struct xferstat *xsp) { static char str[16]; long elapsed, eta; @@ -92,7 +92,7 @@ compare_double(const double a, const double b) * Compute and display transfer rate */ static const char * -stat_bps(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) +stat_bps(struct xbps_fetch_cb_data *xfpd, struct xferstat *xsp) { static char str[16]; char size[8]; @@ -115,7 +115,7 @@ stat_bps(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) * Update the stats display */ static void -stat_display(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) +stat_display(struct xbps_fetch_cb_data *xfpd, struct xferstat *xsp) { struct timeval now; char totsize[8], recvsize[8]; @@ -152,7 +152,7 @@ stat_start(struct xferstat *xsp) * Update the transfer statistics */ static void -stat_update(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) +stat_update(struct xbps_fetch_cb_data *xfpd, struct xferstat *xsp) { xfpd->file_dloaded += xfpd->file_offset; stat_display(xfpd, xsp); @@ -162,7 +162,7 @@ stat_update(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) * Finalize the transfer statistics */ static void -stat_end(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) +stat_end(struct xbps_fetch_cb_data *xfpd, struct xferstat *xsp) { char size[8]; @@ -173,9 +173,8 @@ stat_end(struct xbps_fetch_progress_data *xfpd, struct xferstat *xsp) } void -fetch_file_progress_cb(void *data) +fetch_file_progress_cb(struct xbps_fetch_cb_data *xfpd) { - struct xbps_fetch_progress_data *xfpd = data; static struct xferstat xs; if (xfpd->cb_start) diff --git a/bin/xbps-bin/find-files.c b/bin/xbps-bin/find-files.c index 2422231c..7ef90f22 100644 --- a/bin/xbps-bin/find-files.c +++ b/bin/xbps-bin/find-files.c @@ -71,7 +71,7 @@ match_files_by_pattern(prop_dictionary_t pkg_filesd, prop_dictionary_keysym_t ke int find_files_in_packages(const char *pattern) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t pkg_filesd; prop_array_t files_keys; DIR *dirp; diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index e8d856be..c85586ec 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -39,10 +39,8 @@ #include "../xbps-repo/defs.h" struct transaction { - prop_dictionary_t dict; + prop_dictionary_t d; prop_object_iterator_t iter; - bool yes; - bool only_show; uint32_t inst_pkgcnt; uint32_t up_pkgcnt; uint32_t cf_pkgcnt; @@ -66,118 +64,40 @@ show_missing_deps(prop_array_t a) } static int -check_binpkg_hash(const char *path, - const char *filename, - const char *sha256) +show_binpkgs_url(prop_object_iterator_t iter) { - int rv; - - printf("Checking %s integrity... ", filename); - rv = xbps_file_hash_check(path, sha256); - if (rv != 0 && rv != ERANGE) { - xbps_error_printf("\nxbps-bin: unexpected error: %s\n", - strerror(rv)); - return rv; - } else if (rv == ERANGE) { - printf("hash mismatch!\n"); - xbps_warn_printf("Package '%s' has wrong checksum, removing " - "and refetching it again...\n", filename); - (void)remove(path); - return rv; - } - printf("OK.\n"); - - return 0; -} - -static int -download_package_list(prop_object_iterator_t iter, bool only_show) -{ - const struct xbps_handle *xhp; prop_object_t obj; - const char *pkgver, *repoloc, *filename, *sha256, *trans; + const char *repoloc, *trans; char *binfile; - int rv = 0; - bool cksum; - xhp = xbps_handle_get(); -again: while ((obj = prop_object_iterator_next(iter)) != NULL) { prop_dictionary_get_cstring_nocopy(obj, "transaction", &trans); if ((strcmp(trans, "remove") == 0) || (strcmp(trans, "configure") == 0)) continue; - cksum = false; - prop_dictionary_get_bool(obj, "checksum_ok", &cksum); - if (cksum == true) - continue; - if (!prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc)) continue; - prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - prop_dictionary_get_cstring_nocopy(obj, "filename", &filename); - prop_dictionary_get_cstring_nocopy(obj, - "filename-sha256", &sha256); + + /* ignore pkgs from local repositories */ + if (!xbps_check_is_repository_uri_remote(repoloc)) + continue; binfile = xbps_path_from_repository_uri(obj, repoloc); if (binfile == NULL) return errno; /* - * If downloaded package is in cachedir, check its hash - * and refetch the binpkg again if didn't match. + * If downloaded package is in cachedir, ignore it. */ if (access(binfile, R_OK) == 0) { - rv = check_binpkg_hash(binfile, filename, sha256); - free(binfile); - if (rv != 0 && rv != ERANGE) { - return rv; - } else if (rv == ERANGE) { - break; - } - prop_dictionary_set_bool(obj, "checksum_ok", true); - continue; - } - if (only_show) { - printf("%s\n", binfile); free(binfile); continue; } - if (xbps_mkpath(xhp->cachedir, 0755) == -1) { - xbps_error_printf("xbps-bin: cannot mkdir cachedir " - "`%s': %s.\n", xhp->cachedir, strerror(errno)); - free(binfile); - return errno; - } - printf("Downloading %s binary package ...\n", pkgver); - rv = xbps_fetch_file(binfile, xhp->cachedir, false, NULL); - if (rv == -1) { - xbps_error_printf("xbps-bin: couldn't download `%s'\n", - filename); - xbps_error_printf("xbps-bin: %s returned: `%s'\n", - repoloc, xbps_fetch_error_string()); - free(binfile); - return -1; - } + printf("%s\n", binfile); free(binfile); - binfile = xbps_path_from_repository_uri(obj, repoloc); - if (binfile == NULL) - return errno; - - rv = check_binpkg_hash(binfile, filename, sha256); - free(binfile); - if (rv != 0 && rv != ERANGE) { - return rv; - } else if (rv == ERANGE) { - break; - } - prop_dictionary_set_bool(obj, "checksum_ok", true); } prop_object_iterator_reset(iter); - if (rv == ERANGE) - goto again; - return 0; } @@ -207,28 +127,28 @@ show_transaction_sizes(struct transaction *trans) /* * Show the list of packages that will be installed. */ - if (prop_dictionary_get_uint32(trans->dict, "total-install-pkgs", + if (prop_dictionary_get_uint32(trans->d, "total-install-pkgs", &trans->inst_pkgcnt)) { printf("%u package%s will be installed:\n\n", trans->inst_pkgcnt, trans->inst_pkgcnt == 1 ? "" : "s"); show_package_list(trans->iter, "install"); printf("\n\n"); } - if (prop_dictionary_get_uint32(trans->dict, "total-update-pkgs", + if (prop_dictionary_get_uint32(trans->d, "total-update-pkgs", &trans->up_pkgcnt)) { printf("%u package%s will be updated:\n\n", trans->up_pkgcnt, trans->up_pkgcnt == 1 ? "" : "s"); show_package_list(trans->iter, "update"); printf("\n\n"); } - if (prop_dictionary_get_uint32(trans->dict, "total-configure-pkgs", + if (prop_dictionary_get_uint32(trans->d, "total-configure-pkgs", &trans->cf_pkgcnt)) { printf("%u package%s will be configured:\n\n", trans->cf_pkgcnt, trans->cf_pkgcnt == 1 ? "" : "s"); show_package_list(trans->iter, "configure"); printf("\n\n"); } - if (prop_dictionary_get_uint32(trans->dict, "total-remove-pkgs", + if (prop_dictionary_get_uint32(trans->d, "total-remove-pkgs", &trans->rm_pkgcnt)) { printf("%u package%s will be removed:\n\n", trans->rm_pkgcnt, trans->rm_pkgcnt == 1 ? "" : "s"); @@ -239,8 +159,8 @@ show_transaction_sizes(struct transaction *trans) /* * Show total download/installed size for all required packages. */ - prop_dictionary_get_uint64(trans->dict, "total-download-size", &dlsize); - prop_dictionary_get_uint64(trans->dict, "total-installed-size", + prop_dictionary_get_uint64(trans->d, "total-download-size", &dlsize); + prop_dictionary_get_uint64(trans->d, "total-installed-size", &instsize); if (xbps_humanize_number(size, (int64_t)dlsize) == -1) { xbps_error_printf("xbps-bin: error: humanize_number returns " @@ -259,7 +179,7 @@ show_transaction_sizes(struct transaction *trans) } int -xbps_autoupdate_pkgs(bool yes, bool show_download_pkglist_url) +autoupdate_pkgs(bool yes, bool show_download_pkglist_url) { int rv = 0; @@ -282,11 +202,11 @@ xbps_autoupdate_pkgs(bool yes, bool show_download_pkglist_url) } } - return xbps_exec_transaction(yes, show_download_pkglist_url); + return exec_transaction(yes, show_download_pkglist_url); } int -xbps_install_new_pkg(const char *pkg) +install_new_pkg(const char *pkg) { prop_dictionary_t pkgd; char *pkgname = NULL, *pkgpatt = NULL; @@ -343,7 +263,7 @@ out: } int -xbps_update_pkg(const char *pkgname) +update_pkg(const char *pkgname) { int rv = 0; @@ -363,219 +283,99 @@ xbps_update_pkg(const char *pkgname) return 0; } -static int -exec_transaction(struct transaction *trans) +void +transaction_cb(struct xbps_transaction_cb_data *xtcd) { - prop_dictionary_t instpkgd; - prop_object_t obj; - const char *pkgname, *version, *pkgver, *instver, *filen, *tract; - int rv = 0; - bool update, preserve; - pkg_state_t state; - - /* - * Only show the URLs to download the binary packages. - */ - if (trans->only_show) - return download_package_list(trans->iter, true); - /* - * Show download/installed size for the transaction. - */ - if ((rv = show_transaction_sizes(trans)) != 0) - return rv; - /* - * Ask interactively (if -y not set). - */ - if (trans->yes == false) { - if (xbps_noyes("Do you want to continue?") == false) { - printf("Aborting!\n"); - return 0; - } - } - /* - * Download binary packages (if they come from a remote repository) - * and check its SHA256 hash. - */ - printf("[*] Downloading/integrity check ...\n"); - if ((rv = download_package_list(trans->iter, false)) != 0) - return rv; - /* - * Remove packages to be replaced. - */ - if (trans->rm_pkgcnt) { - printf("\n[*] Removing packages to be replaced ...\n"); - while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "transaction", - &tract); - if (strcmp(tract, "remove")) - continue; - - prop_dictionary_get_cstring_nocopy(obj, "pkgname", - &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", - &version); - prop_dictionary_get_cstring_nocopy(obj, "pkgver", - &pkgver); - update = false; - prop_dictionary_get_bool(obj, "remove-and-update", - &update); - - /* Remove and purge packages that shall be replaced */ - printf("Removing `%s' package ...\n", pkgver); - rv = xbps_remove_pkg(pkgname, version, update); - if (rv != 0) { - xbps_error_printf("xbps-bin: failed to " - "remove `%s': %s\n", pkgver, strerror(rv)); - return rv; - } - if (!update) - continue; - printf("Purging `%s' package...\n", pkgver); - if ((rv = xbps_purge_pkg(pkgname, false)) != 0) { - xbps_error_printf("xbps-bin: failed to " - "purge `%s': %s\n", pkgver, strerror(rv)); - return rv; - } - } - prop_object_iterator_reset(trans->iter); - } - /* - * Configure pending packages. - */ - if (trans->cf_pkgcnt) { - printf("\n[*] Reconfigure unpacked packages ...\n"); - while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "transaction", - &tract); - if (strcmp(tract, "configure")) - continue; - prop_dictionary_get_cstring_nocopy(obj, "pkgname", - &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", - &version); - prop_dictionary_get_cstring_nocopy(obj, "pkgver", - &pkgver); - rv = xbps_configure_pkg(pkgname, version, false, false); - if (rv != 0) { - xbps_error_printf("xbps-bin: failed to " - "configure `%s': %s\n", pkgver, strerror(rv)); - return rv; - } - } - prop_object_iterator_reset(trans->iter); - } - /* - * Install or update packages in transaction. - */ - printf("\n[*] Unpacking packages to be installed/updated ...\n"); - while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract); - /* Match only packages to be installed or updated */ - if ((strcmp(tract, "remove") == 0) || - (strcmp(tract, "configure") == 0)) - continue; - preserve = false; - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); - prop_dictionary_get_cstring_nocopy(obj, "filename", &filen); - prop_dictionary_get_bool(obj, "preserve", &preserve); - /* - * If dependency is already unpacked skip this phase. - */ - state = 0; - if (xbps_pkg_state_dictionary(obj, &state) != 0) - return EINVAL; - if (state == XBPS_PKG_STATE_UNPACKED) - continue; - - if (strcmp(tract, "update") == 0) { - /* Update a package */ - instpkgd = xbps_find_pkg_dict_installed(pkgname, false); - if (instpkgd == NULL) { - xbps_error_printf("xbps-bin: error: unable to " - "find %s installed dict!\n", pkgname); - return EINVAL; - } - prop_dictionary_get_cstring_nocopy(instpkgd, - "version", &instver); - prop_object_release(instpkgd); - if (preserve) - printf("Conserving %s-%s files, installing new " - "version ...\n", pkgname, instver); - else - printf("Replacing %s files (%s -> %s) ...\n", - pkgname, instver, version); - - if ((rv = xbps_remove_pkg(pkgname, version, true)) != 0) { - xbps_error_printf("xbps-bin: error " - "replacing %s-%s (%s)\n", pkgname, - instver, strerror(rv)); - return rv; - } - } - /* - * Unpack binary package. - */ - printf("Unpacking `%s' (from ../%s) ...\n", pkgver, filen); - if ((rv = xbps_unpack_binary_pkg(obj)) != 0) { - xbps_error_printf("xbps-bin: error unpacking %s " - "(%s)\n", pkgver, strerror(rv)); - return rv; - } - /* - * Register binary package. - */ - if ((rv = xbps_register_pkg(obj)) != 0) { - xbps_error_printf("xbps-bin: error registering %s " - "(%s)\n", pkgver, strerror(rv)); - return rv; - } - } - prop_object_iterator_reset(trans->iter); - /* - * Configure all unpacked packages. - */ - printf("\n[*] Configuring packages installed/updated ...\n"); - while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { - prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract); - if ((strcmp(tract, "remove") == 0) || - (strcmp(tract, "configure") == 0)) - continue; - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - update = false; - if (strcmp(tract, "update") == 0) - update = true; - rv = xbps_configure_pkg(pkgname, version, false, update); - if (rv != 0) { - xbps_error_printf("xbps-bin: error configuring " - "package %s (%s)\n", pkgname, strerror(rv)); - return rv; - } - trans->cf_pkgcnt++; + if (xtcd->desc != NULL && xtcd->pkgver == NULL) { + printf("\n%s ...\n", xtcd->desc); + return; } - printf("\nxbps-bin: %u installed, %u updated, " - "%u configured, %u removed.\n", trans->inst_pkgcnt, - trans->up_pkgcnt, trans->cf_pkgcnt, trans->rm_pkgcnt); + switch (xtcd->state) { + case XBPS_TRANS_STATE_DOWNLOAD: + printf("Downloading `%s' (from %s) ...\n", + xtcd->pkgver, xtcd->binpkg_repourl); + break; + case XBPS_TRANS_STATE_VERIFY: + printf("Checking `%s' integrity ...\n", xtcd->binpkg_fname); + break; + case XBPS_TRANS_STATE_REMOVE: + printf("Removing `%s' ...\n", xtcd->pkgver); + break; + case XBPS_TRANS_STATE_PURGE: + printf("Purging `%s' ...\n", xtcd->pkgver); + break; + case XBPS_TRANS_STATE_CONFIGURE: + printf("Configuring `%s' ...\n", xtcd->pkgver); + break; + case XBPS_TRANS_STATE_REGISTER: + case XBPS_TRANS_STATE_INSTALL: + break; + case XBPS_TRANS_STATE_UPDATE: + printf("Updating `%s' ...\n", xtcd->pkgver); + break; + case XBPS_TRANS_STATE_UNPACK: + printf("Unpacking `%s' (from ../%s) ...\n", + xtcd->pkgver, xtcd->binpkg_fname); + break; + default: + xbps_dbg_printf("%s: unknown transaction state %d %s\n", + xtcd->pkgver, xtcd->state, xtcd->desc); + break; + } +} - return 0; +void +transaction_err_cb(struct xbps_transaction_cb_data *xtcd) +{ + const char *state_descr = NULL; + + switch (xtcd->state) { + case XBPS_TRANS_STATE_DOWNLOAD: + state_descr = "failed to download binary package"; + break; + case XBPS_TRANS_STATE_VERIFY: + state_descr = "failed to verify binary package SHA256"; + break; + case XBPS_TRANS_STATE_REMOVE: + state_descr = "failed to remove package"; + break; + case XBPS_TRANS_STATE_PURGE: + state_descr = "failed to purge package"; + break; + case XBPS_TRANS_STATE_CONFIGURE: + state_descr = "failed to configure package"; + break; + case XBPS_TRANS_STATE_UPDATE: + state_descr = "failed to update package"; + break; + case XBPS_TRANS_STATE_UNPACK: + state_descr = "failed to unpack binary package"; + break; + case XBPS_TRANS_STATE_REGISTER: + state_descr = "failed to register package"; + break; + default: + state_descr = "unknown transaction state"; + break; + } + + xbps_error_printf("%s: %s: %s\n", + xtcd->pkgver, state_descr, strerror(xtcd->err)); } int -xbps_exec_transaction(bool yes, bool show_download_pkglist_url) +exec_transaction(bool yes, bool show_download_urls) { struct transaction *trans; prop_array_t array; int rv = 0; - trans = calloc(1, sizeof(struct transaction)); + trans = calloc(1, sizeof(*trans)); if (trans == NULL) - return errno; + return ENOMEM; - trans->dict = xbps_transaction_prepare(); - if (trans->dict == NULL) { + if ((trans->d = xbps_transaction_prepare()) == NULL) { if (errno == ENODEV) { /* missing packages */ array = xbps_transaction_missingdeps_get(); @@ -583,33 +383,54 @@ xbps_exec_transaction(bool yes, bool show_download_pkglist_url) rv = errno; goto out; } - rv = errno; xbps_dbg_printf("Empty transaction dictionary: %s\n", strerror(errno)); - goto out; + return errno; } xbps_dbg_printf("Dictionary before transaction happens:\n"); - xbps_dbg_printf_append("%s", prop_dictionary_externalize(trans->dict)); + xbps_dbg_printf_append("%s", prop_dictionary_externalize(trans->d)); - /* - * It's time to run the transaction! - */ - trans->iter = xbps_array_iter_from_dict(trans->dict, "packages"); + trans->iter = xbps_array_iter_from_dict(trans->d, "packages"); if (trans->iter == NULL) { rv = errno; xbps_error_printf("xbps-bin: error allocating array mem! (%s)\n", strerror(errno)); goto out; } - - trans->yes = yes; - trans->only_show = show_download_pkglist_url; - rv = exec_transaction(trans); + /* + * Only show URLs to download binary packages. + */ + if (show_download_urls) { + rv = show_binpkgs_url(trans->iter); + goto out; + } + /* + * Show download/installed size for the transaction. + */ + if ((rv = show_transaction_sizes(trans)) != 0) + goto out; + /* + * Ask interactively (if -y not set). + */ + if (!yes && !noyes("Do you want to continue?")) { + printf("Aborting!\n"); + goto out; + } + /* + * It's time to run the transaction! + */ + rv = xbps_transaction_commit(trans->d); + if (rv == 0) { + printf("\nxbps-bin: %u installed, %u updated, " + "%u configured, %u removed.\n", trans->inst_pkgcnt, + trans->up_pkgcnt, trans->cf_pkgcnt + trans->inst_pkgcnt, + trans->rm_pkgcnt); + } out: if (trans->iter) prop_object_iterator_release(trans->iter); - if (trans->dict) - prop_object_release(trans->dict); + if (trans->d) + prop_object_release(trans->d); if (trans) free(trans); diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index a902c149..d118f333 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -46,7 +46,7 @@ struct list_pkgver_cb { static void __attribute__((noreturn)) usage(void) { - xbps_end(); + xbps_end(xbps_handle_get()); fprintf(stderr, "Usage: xbps-bin [options] [target] [arguments]\n" "See xbps-bin(8) for more information.\n"); @@ -145,15 +145,15 @@ show_orphans(void) static void __attribute__((noreturn)) cleanup(int signum) { - xbps_end(); + struct xbps_handle *xhp = xbps_handle_get(); + + xbps_end(xhp); exit(signum); } static void -unpack_progress_cb_verbose(void *data) +unpack_progress_cb_verbose(struct xbps_unpack_cb_data *xpd) { - struct xbps_unpack_progress_data *xpd = data; - if (xpd->entry == NULL || xpd->entry_is_metadata) return; else if (xpd->entry_size <= 0) @@ -165,10 +165,8 @@ unpack_progress_cb_verbose(void *data) } static void -unpack_progress_cb(void *data) +unpack_progress_cb(struct xbps_unpack_cb_data *xpd) { - struct xbps_unpack_progress_data *xpd = data; - if (xpd->entry == NULL || xpd->entry_is_metadata) return; else if (xpd->entry_size <= 0) @@ -181,20 +179,17 @@ unpack_progress_cb(void *data) int main(int argc, char **argv) { - const struct xbps_handle *xhp; - struct xbps_handle xh; - struct xbps_unpack_progress_data xupd; - struct xbps_fetch_progress_data xfpd; + struct xbps_handle *xhp; struct list_pkgver_cb lpc; struct sigaction sa; const char *rootdir, *cachedir, *conffile; int i , c, flags, rv; - bool yes, purge, with_debug, force_rm_with_deps, recursive_rm; + bool yes, purge, debug, force_rm_with_deps, recursive_rm; bool install_auto, install_manual, show_download_pkglist_url; rootdir = cachedir = conffile = NULL; flags = rv = 0; - yes = purge = force_rm_with_deps = recursive_rm = with_debug = false; + yes = purge = force_rm_with_deps = recursive_rm = debug = false; install_auto = install_manual = show_download_pkglist_url = false; while ((c = getopt(argc, argv, "AC:c:dDFfMpRr:Vvy")) != -1) { @@ -209,7 +204,7 @@ main(int argc, char **argv) cachedir = optarg; break; case 'd': - with_debug = true; + debug = true; break; case 'D': show_download_pkglist_url = true; @@ -273,28 +268,31 @@ main(int argc, char **argv) /* * Initialize stuff for libxbps. */ - memset(&xh, 0, sizeof(xh)); - xh.with_debug = with_debug; - xh.xbps_fetch_cb = fetch_file_progress_cb; - xh.xfpd = &xfpd; + xhp = xbps_handle_alloc(); + if (xhp == NULL) { + xbps_error_printf("xbps-bin: failed to allocate resources.\n"); + exit(EXIT_FAILURE); + } + xhp->debug = debug; + xhp->xbps_transaction_cb = transaction_cb; + xhp->xbps_transaction_err_cb = transaction_err_cb; + xhp->xbps_fetch_cb = fetch_file_progress_cb; if (flags & XBPS_FLAG_VERBOSE) - xh.xbps_unpack_cb = unpack_progress_cb_verbose; + xhp->xbps_unpack_cb = unpack_progress_cb_verbose; else - xh.xbps_unpack_cb = unpack_progress_cb; - xh.xupd = &xupd; - xh.rootdir = rootdir; - xh.cachedir = cachedir; - xh.flags = flags; - xh.conffile = conffile; - xh.install_reason_manual = install_manual; - xh.install_reason_auto = install_auto; + xhp->xbps_unpack_cb = unpack_progress_cb; + xhp->rootdir = rootdir; + xhp->cachedir = cachedir; + xhp->flags = flags; + xhp->conffile = conffile; + xhp->install_reason_manual = install_manual; + xhp->install_reason_auto = install_auto; - if ((rv = xbps_init(&xh)) != 0) { + if ((rv = xbps_init(xhp)) != 0) { xbps_error_printf("xbps-bin: couldn't initialize library: %s\n", strerror(errno)); exit(EXIT_FAILURE); } - xhp = xbps_handle_get(); if (strcasecmp(argv[0], "list") == 0) { /* Lists packages currently registered in database. */ @@ -337,10 +335,10 @@ main(int argc, char **argv) usage(); for (i = 1; i < argc; i++) - if ((rv = xbps_install_new_pkg(argv[i])) != 0) + if ((rv = install_new_pkg(argv[i])) != 0) goto out; - rv = xbps_exec_transaction(yes, show_download_pkglist_url); + rv = exec_transaction(yes, show_download_pkglist_url); } else if (strcasecmp(argv[0], "update") == 0) { /* Update an installed package. */ @@ -348,17 +346,17 @@ main(int argc, char **argv) usage(); for (i = 1; i < argc; i++) - if ((rv = xbps_update_pkg(argv[i])) != 0) + if ((rv = update_pkg(argv[i])) != 0) goto out; - rv = xbps_exec_transaction(yes, show_download_pkglist_url); + rv = exec_transaction(yes, show_download_pkglist_url); } else if (strcasecmp(argv[0], "remove") == 0) { /* Removes a binary package. */ if (argc < 2) usage(); - rv = xbps_remove_installed_pkgs(argc, argv, yes, purge, + rv = remove_installed_pkgs(argc, argv, yes, purge, force_rm_with_deps, recursive_rm); } else if (strcasecmp(argv[0], "show") == 0) { @@ -389,9 +387,9 @@ main(int argc, char **argv) usage(); if (strcasecmp(argv[1], "all") == 0) - rv = xbps_check_pkg_integrity_all(); + rv = check_pkg_integrity_all(); else - rv = xbps_check_pkg_integrity(argv[1]); + rv = check_pkg_integrity(argv[1]); } else if (strcasecmp(argv[0], "autoupdate") == 0) { /* @@ -400,7 +398,7 @@ main(int argc, char **argv) if (argc != 1) usage(); - rv = xbps_autoupdate_pkgs(yes, show_download_pkglist_url); + rv = autoupdate_pkgs(yes, show_download_pkglist_url); } else if (strcasecmp(argv[0], "show-orphans") == 0) { /* @@ -421,7 +419,7 @@ main(int argc, char **argv) if (argc != 1) usage(); - rv = xbps_autoremove_pkgs(yes, purge); + rv = autoremove_pkgs(yes, purge); } else if (strcasecmp(argv[0], "purge") == 0) { /* @@ -454,7 +452,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - rv = xbps_show_pkg_deps(argv[1]); + rv = show_pkg_deps(argv[1]); } else if (strcasecmp(argv[0], "list-manual") == 0) { /* @@ -474,7 +472,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - rv = xbps_show_pkg_reverse_deps(argv[1]); + rv = show_pkg_reverse_deps(argv[1]); } else if (strcasecmp(argv[0], "find-files") == 0) { /* @@ -491,6 +489,6 @@ main(int argc, char **argv) } out: - xbps_end(); + xbps_end(xhp); exit(rv); } diff --git a/bin/xbps-bin/question.c b/bin/xbps-bin/question.c index 80c977db..6d85a6fc 100644 --- a/bin/xbps-bin/question.c +++ b/bin/xbps-bin/question.c @@ -84,7 +84,7 @@ question(bool preset, const char *fmt, va_list ap) } bool -xbps_yesno(const char *fmt, ...) +yesno(const char *fmt, ...) { va_list ap; bool res; @@ -97,7 +97,7 @@ xbps_yesno(const char *fmt, ...) } bool -xbps_noyes(const char *fmt, ...) +noyes(const char *fmt, ...) { va_list ap; bool res; diff --git a/bin/xbps-bin/remove.c b/bin/xbps-bin/remove.c index d2a82b50..a23699da 100644 --- a/bin/xbps-bin/remove.c +++ b/bin/xbps-bin/remove.c @@ -61,7 +61,7 @@ pkg_remove_and_purge(const char *pkgname, const char *version, bool purge) } int -xbps_autoremove_pkgs(bool yes, bool purge) +autoremove_pkgs(bool yes, bool purge) { prop_array_t orphans = NULL; prop_object_t obj = NULL; @@ -98,7 +98,7 @@ xbps_autoremove_pkgs(bool yes, bool purge) prop_object_iterator_reset(iter); printf("\n\n"); - if (!yes && !xbps_noyes("Do you want to continue?")) { + if (!yes && !noyes("Do you want to continue?")) { printf("Cancelled!\n"); goto out; } @@ -120,12 +120,8 @@ out: } int -xbps_remove_installed_pkgs(int argc, - char **argv, - bool yes, - bool purge, - bool force_rm_with_deps, - bool recursive_rm) +remove_installed_pkgs(int argc, char **argv, bool yes, bool purge, + bool force_rm_with_deps, bool recursive_rm) { prop_array_t sorted_pkgs, orphans, reqby, orphans_user = NULL; prop_dictionary_t dict; @@ -219,7 +215,7 @@ xbps_remove_installed_pkgs(int argc, prop_array_count(sorted_pkgs) == 1 ? "" : "s", purge ? " and purged" : ""); - if (!yes && !xbps_noyes("Do you want to continue?")) { + if (!yes && !noyes("Do you want to continue?")) { printf("Cancelling!\n"); prop_object_release(sorted_pkgs); return 0; diff --git a/bin/xbps-bin/show-deps.c b/bin/xbps-bin/show-deps.c index 82d9ecb0..1610b4b2 100644 --- a/bin/xbps-bin/show-deps.c +++ b/bin/xbps-bin/show-deps.c @@ -35,7 +35,7 @@ #include "../xbps-repo/defs.h" int -xbps_show_pkg_deps(const char *pkgname) +show_pkg_deps(const char *pkgname) { prop_dictionary_t propsd; int rv = 0; @@ -60,7 +60,7 @@ xbps_show_pkg_deps(const char *pkgname) } int -xbps_show_pkg_reverse_deps(const char *pkgname) +show_pkg_reverse_deps(const char *pkgname) { prop_dictionary_t pkgd; int rv = 0; diff --git a/bin/xbps-repo/defs.h b/bin/xbps-repo/defs.h index 6af83c09..997da115 100644 --- a/bin/xbps-repo/defs.h +++ b/bin/xbps-repo/defs.h @@ -31,7 +31,7 @@ #endif /* From index.c */ -int xbps_repo_genindex(const char *); +int repo_genindex(const char *); /* From repository.c */ int show_pkg_info_from_repolist(const char *); int show_pkg_deps_from_repolist(const char *); diff --git a/bin/xbps-repo/index.c b/bin/xbps-repo/index.c index 0379a7ad..92744c48 100644 --- a/bin/xbps-repo/index.c +++ b/bin/xbps-repo/index.c @@ -316,7 +316,7 @@ out: } int -xbps_repo_genindex(const char *pkgdir) +repo_genindex(const char *pkgdir) { prop_dictionary_t idxdict = NULL; struct dirent *dp; diff --git a/bin/xbps-repo/main.c b/bin/xbps-repo/main.c index 5d61dc06..95a01689 100644 --- a/bin/xbps-repo/main.c +++ b/bin/xbps-repo/main.c @@ -41,7 +41,9 @@ static void __attribute__((noreturn)) usage(void) { - xbps_end(); + struct xbps_handle *xhp = xbps_handle_get(); + + xbps_end(xhp); fprintf(stderr, "Usage: xbps-repo [options] [action] [arguments]\n" "See xbps-repo(8) for more information.\n"); @@ -85,8 +87,7 @@ repo_search_pkgs_cb(struct repository_pool_index *rpi, void *arg, bool *done) int main(int argc, char **argv) { - struct xbps_handle xh; - struct xbps_fetch_progress_data xfpd; + struct xbps_handle *xhp; prop_dictionary_t pkgd; const char *rootdir, *cachedir, *conffile; int c, rv = 0; @@ -127,15 +128,18 @@ main(int argc, char **argv) /* * Initialize XBPS subsystems. */ - memset(&xh, 0, sizeof(xh)); - xh.with_debug = debug; - xh.xbps_fetch_cb = fetch_file_progress_cb; - xh.xfpd = &xfpd; - xh.rootdir = rootdir; - xh.cachedir = cachedir; - xh.conffile = conffile; + xhp = xbps_handle_alloc(); + if (xhp == NULL) { + xbps_error_printf("xbps-repo: failed to allocate resources.\n"); + exit(EXIT_FAILURE); + } + xhp->debug = debug; + xhp->xbps_fetch_cb = fetch_file_progress_cb; + xhp->rootdir = rootdir; + xhp->cachedir = cachedir; + xhp->conffile = conffile; - if ((rv = xbps_init(&xh)) != 0) { + if ((rv = xbps_init(xhp)) != 0) { xbps_error_printf("xbps-repo: couldn't initialize library: %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -224,7 +228,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - rv = xbps_repo_genindex(argv[1]); + rv = repo_genindex(argv[1]); } else if (strcasecmp(argv[0], "sync") == 0) { /* Syncs the pkg index for all registered remote repos */ @@ -238,6 +242,6 @@ main(int argc, char **argv) } out: - xbps_end(); + xbps_end(xhp); exit(rv ? EXIT_FAILURE : EXIT_SUCCESS); } diff --git a/bin/xbps-uhelper/main.c b/bin/xbps-uhelper/main.c index cd43b613..d0013bb2 100644 --- a/bin/xbps-uhelper/main.c +++ b/bin/xbps-uhelper/main.c @@ -60,7 +60,7 @@ write_plist_file(prop_dictionary_t dict, const char *file) static void __attribute__((noreturn)) usage(void) { - xbps_end(); + xbps_end(xbps_handle_get()); fprintf(stderr, "usage: xbps-uhelper [options] [action] [args]\n" @@ -109,8 +109,7 @@ usage(void) int main(int argc, char **argv) { - struct xbps_handle xh; - struct xbps_fetch_progress_data xfpd; + struct xbps_handle *xhp; prop_dictionary_t dict; const char *version, *rootdir = NULL, *conffile = NULL; char *plist, *pkgname, *pkgver, *in_chroot_env, *hash; @@ -147,14 +146,17 @@ main(int argc, char **argv) /* * Initialize the callbacks and debug in libxbps. */ - memset(&xh, 0, sizeof(xh)); - xh.with_debug = debug; - xh.xbps_fetch_cb = fetch_file_progress_cb; - xh.xfpd = &xfpd; - xh.rootdir = rootdir; - xh.conffile = conffile; + xhp = xbps_handle_alloc(); + if (xhp == NULL) { + xbps_error_printf("xbps-uhelper: failed to allocate resources\n"); + exit(EXIT_FAILURE); + } + xhp->debug = debug; + xhp->xbps_fetch_cb = fetch_file_progress_cb; + xhp->rootdir = rootdir; + xhp->conffile = conffile; - if ((rv = xbps_init(&xh)) != 0) { + if ((rv = xbps_init(xhp)) != 0) { xbps_error_printf("xbps-uhelper: failed to " "initialize libxbps.\n"); exit(EXIT_FAILURE); @@ -163,7 +165,7 @@ main(int argc, char **argv) plist = xbps_xasprintf("%s/%s/%s", rootdir, XBPS_META_PATH, XBPS_REGPKGDB); if (plist == NULL) { - xbps_end(); + xbps_end(xhp); exit(EXIT_FAILURE); } @@ -372,7 +374,7 @@ main(int argc, char **argv) usage(); } - xbps_end(); + xbps_end(xhp); exit(EXIT_SUCCESS); } diff --git a/etc/xbps-conf.plist b/etc/xbps-conf.plist index 516d7689..7e1c49ef 100644 --- a/etc/xbps-conf.plist +++ b/etc/xbps-conf.plist @@ -6,9 +6,11 @@ root-directory / - + cache-directory - /var/cache/xbps + var/cache/xbps fetch-cache-connections diff --git a/include/xbps_api.h b/include/xbps_api.h index 4686a06e..162d6ad7 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -55,7 +55,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.2" -#define XBPS_API_VERSION "20110725" +#define XBPS_API_VERSION "20110727" #define XBPS_VERSION "0.10.0" /** @@ -142,201 +142,90 @@ void xbps_warn_printf(const char *, ...); /*@{*/ /** - * @struct xbps_handle xbps_api.h "xbps_api.h" - * @brief Generic XBPS structure handler for initialization. + * @enum trans_state_t * - * This structure sets some global properties for libxbps, to set some - * function callbacks and data to the fetch and unpack functions, - * the root and cache directory, flags, etc. + * Integer representing the transaction state. Possible values: + * + * XBPS_TRANS_STATE_UKKNOWN: unknown, transaction hasn't been + * prepared or some unknown error ocurred. + * XBPS_TRANS_STATE_DOWNLOAD: a binary package is being downloaded. + * XBPS_TRANS_STATE_VERIFY: a binary package is being verified. + * XBPS_TRANS_STATE_REMOVE: a package is being removed. + * XBPS_TRANS_STATE_PURGE: a package is being purged. + * XBPS_TRANS_STATE_REPLACE: a package is being replaced. + * XBPS_TRANS_STATE_INSTALL: a package is being installed. + * XBPS_TRANS_STATE_UPDATE: a package is being updated. + * XBPS_TRANS_STATE_UNPACK: a package is being unpacked. + * XBPS_TRANS_STATE_CONFIGURE: a package is being configured. + * XBPS_TRANS_STATE_REGISTER: a package is being registered. */ -struct xbps_handle { +typedef enum trans_state { + XBPS_TRANS_STATE_UNKNOWN = 0, + XBPS_TRANS_STATE_DOWNLOAD, + XBPS_TRANS_STATE_VERIFY, + XBPS_TRANS_STATE_REMOVE, + XBPS_TRANS_STATE_PURGE, + XBPS_TRANS_STATE_REPLACE, + XBPS_TRANS_STATE_INSTALL, + XBPS_TRANS_STATE_UPDATE, + XBPS_TRANS_STATE_UNPACK, + XBPS_TRANS_STATE_CONFIGURE, + XBPS_TRANS_STATE_REGISTER +} trans_state_t; + +/** + * @struct xbps_transaction_cb_data xbps_api.h "xbps_api.h" + * @brief Structure to be passed as argument to the transaction + * function callbacks. + */ +struct xbps_transaction_cb_data { /** - * @private conf_dictionary + * @var state * - * Internalized proplib dictionary from conffile member. - * Used internally by xbps_init(). + * Transaction's state (read-only). */ - prop_dictionary_t conf_dictionary; + trans_state_t state; /** - * @var regpkgdb_dictionary. + * @var desc * - * Internalized proplib dictionary with the registed package database - * stored in XBPS_META_PATH/XBPS_REGPKGDB. + * Transaction's string description (read-only). */ - prop_dictionary_t regpkgdb_dictionary; + const char *desc; /** - * @var xbps_unpack_cb + * @var pkgver * - * Pointer to the supplied function callback to be used in - * xbps_unpack_binary_pkg(). + * Transaction's current pkgname/version string (read-only). */ - void (*xbps_unpack_cb)(void *); + const char *pkgver; /** - * @var xupd + * @var binpkg_fname * - * Pointer to a xbps_unpack_progress_data structure to be passed - * as argument to the \a xbps_unpack_cb function callback. + * Binary package's filename (read-only). */ - struct xbps_unpack_progress_data *xupd; + const char *binpkg_fname; /** - * @var xbps_fetch_cb + * @var binpkg_repourl * - * Pointer to the supplied function callback to be used in - * xbps_fetch_file(). + * Binary package's repository URL (read-only). */ - void (*xbps_fetch_cb)(void *); + const char *binpkg_repourl; /** - * @var xfpd + * @var err * - * Pointer to a xbps_fetch_progress_data structure to be passed - * as argument to the \a xbps_fetch_cb function callback. + * Transaction error value (read-only). */ - struct xbps_fetch_progress_data *xfpd; + int err; /** - * @private fetch_timeout + * @var cookie * - * Unsigned integer to specify libfetch's timeout limit. - * If not set, it defaults to 30 (in seconds). This is set internally - * by the API from a setting in configuration file. + * Pointer to user supplied data. */ - uint16_t fetch_timeout; - /** - * @var flags - * - * Flags to be set globally, possible values: - * - XBPS_FLAG_VERBOSE - * - XBPS_FLAG_FORCE - */ - int flags; - /** - * @var rootdir - * - * Root directory for all operations in XBPS. If NULL, - * by default it's set to /. - */ - const char *rootdir; - /** - * @var cachedir - * - * Cache directory to store downloaded binary packages. - * If NULL default value in \a XBPS_CACHE_PATH is used. - */ - const char *cachedir; - /** - * @var conffile - * - * Full path to the XBPS_CONF_PLIST configuration file. - */ - const char *conffile; - /** - * @var with_debug - * - * Set to true to enable debugging messages to stderr. - */ - bool with_debug; - /** - * @var install_reason_auto - * - * Set to true to make installed or updated target package - * (and its dependencies) marked with automatic installation, - * thus it will be found as orphan if no packages are depending - * on it. - */ - bool install_reason_auto; - /** - * @var install_reason_manual - * - * Set to true to make installed or updated target package - * (and its dependencies) marked with manual installation, thus - * it will never will be found as orphan. - */ - bool install_reason_manual; + void *cookie; }; /** - * Initialize the XBPS library with the following steps: - * - * - Set function callbacks for fetching and unpacking. - * - Set root directory (if not set, defaults to /). - * - Set cache directory (if not set, defaults to XBPS_CACHE_PATH). - * - Set global flags. - * - Set default cache connections for libfetch. - * - Initialize the debug printfs. - * - Internalize the proplib dictionary in config file. - * - Internalize the regpkgdb dictionary (if available). - * - * @param[in] xh Pointer to an xbps_handle structure. It's - * assumed that this pointer is not NULL. - * - * @return 0 on success, an errno value otherwise. - */ -int xbps_init(struct xbps_handle *xh); - -/** - * Releases all resources used by the XBPS library. - */ -void xbps_end(void); - -/** - * Returns a pointer to the xbps_handle structure set by xbps_init(). - */ -const struct xbps_handle *xbps_handle_get(void); - -/*@}*/ - -/** @addtogroup configure */ -/*@{*/ - -/** - * Configure (or force reconfiguration of) a package. - * - * @param[in] pkgname Package name to configure. - * @param[in] version Package version (optional). - * @param[in] check_state Set it to true to check that package is - * in unpacked state. - * @param[in] update Set it to true if this package is being updated. - * - * @return 0 on success, otherwise an errno value. - */ -int xbps_configure_pkg(const char *pkgname, - const char *version, - bool check_state, - bool update); - -/** - * Configure (or force reconfiguration of) all packages. - * - * @return 0 on success, otherwise an errno value. - */ -int xbps_configure_packages(void); - -/*@}*/ - -/** - * @ingroup vermatch - * - * Compares package version strings. - * - * The package version is defined by: - * ${VERSION}[_${REVISION}]. - * - * ${VERSION} supersedes ${REVISION}. - * - * @param[in] pkg1 a package version string. - * @param[in] pkg2 a package version string. - * - * @return -1, 0 or 1 depending if pkg1 is less than, equal to or - * greater than pkg2. - */ -int xbps_cmpver(const char *pkg1, const char *pkg2); - - -/** @addtogroup download */ -/*@{*/ - -/** - * @struct xbps_fetch_progress_data xbps_api.h "xbps_api.h" - * @brief Structure to be passed to the fetch progress function callback. + * @struct xbps_fetch_cb_data xbps_api.h "xbps_api.h" + * @brief Structure to be passed to the fetch function callback. * * This structure is passed as argument to the fetch progress function * callback and its members will be updated when there's any progress. @@ -344,7 +233,7 @@ int xbps_cmpver(const char *pkg1, const char *pkg2); * xbps_unpack_binary_pkg() and shouldn't be modified in the passed * function callback. */ -struct xbps_fetch_progress_data { +struct xbps_fetch_cb_data { /** * @var file_size * @@ -400,6 +289,298 @@ struct xbps_fetch_progress_data { void *cookie; }; +/** + * @struct xbps_unpack_cb_data xbps_api.h "xbps_api.h" + * @brief Structure to be passed to the unpack function callback. + * + * This structure is passed as argument to the unpack progress function + * callback and its members will be updated when there's any progress. + * All members in this struct are set internally by xbps_unpack_binary_pkg() + * and should be used in read-only mode in the function callback. + * The \a cookie member can be used to pass user supplied data. + */ +struct xbps_unpack_cb_data { + /** + * @var entry + * + * Entry pathname string (set internally, read only). + */ + const char *entry; + /** + * @var entry_size + * + * Entry file size (set internally, read only). + */ + int64_t entry_size; + /** + * @var entry_extract_count + * + * Total number of extracted entries (set internally, read only). + */ + ssize_t entry_extract_count; + /** + * @var entry_total_count + * + * Total number of entries in package (set internally, read only). + */ + ssize_t entry_total_count; + /** + * @var entry_is_metadata + * + * If true "entry" is a package metadata file (set internally, + * read only). + */ + bool entry_is_metadata; + /** + * @var entry_is_conf + * + * If true "entry" is a configuration file (set internally, + * read only). + */ + bool entry_is_conf; + /** + * @var cookie + * + * Pointer to private user data. + */ + void *cookie; +}; + +/** + * @struct xbps_handle xbps_api.h "xbps_api.h" + * @brief Generic XBPS structure handler for initialization. + * + * This structure sets some global properties for libxbps, to set some + * function callbacks and data to the fetch, transaction and unpack functions, + * the root and cache directory, flags, etc. + */ +struct xbps_handle { + /** + * @private conf_dictionary + * + * Internalized proplib dictionary from conffile member. + * Used internally by xbps_init(). + */ + prop_dictionary_t conf_dictionary; + /** + * @var regpkgdb_dictionary. + * + * Internalized proplib dictionary with the registed package database + * stored in XBPS_META_PATH/XBPS_REGPKGDB. + */ + prop_dictionary_t regpkgdb_dictionary; + /** + * @var xbps_transaction_cb + * + * Pointer to the supplifed function callback to be used + * in a transaction. + */ + void (*xbps_transaction_cb)(struct xbps_transaction_cb_data *); + /** + * @var xbps_transaction_err_cb + * + * Pointer the the supplied function callback to be used in + * a transaction when an error happens. + */ + void (*xbps_transaction_err_cb)(struct xbps_transaction_cb_data *); + /** + * @var xtcd + * + * Pointer to a xbps_transaction_cb_data structure, to be passed as + * argument to the \a xbps_transaction_cb and + * \a xbps_transaction_err_cb function callbacks. + */ + struct xbps_transaction_cb_data *xtcd; + /** + * @var xbps_unpack_cb + * + * Pointer to the supplied function callback to be used in + * xbps_unpack_binary_pkg(). + */ + void (*xbps_unpack_cb)(struct xbps_unpack_cb_data *); + /** + * @var xucd + * + * Pointer to a xbps_unpack_cb_data structure to be passed + * as argument to the \a xbps_unpack_cb function callback. + */ + struct xbps_unpack_cb_data *xucd; + /** + * @var xbps_fetch_cb + * + * Pointer to the supplied function callback to be used in + * xbps_fetch_file(). + */ + void (*xbps_fetch_cb)(struct xbps_fetch_cb_data *); + /** + * @var xfcd + * + * Pointer to a xbps_fetch_cb_data structure to be passed + * as argument to the \a xbps_fetch_cb function callback. + */ + struct xbps_fetch_cb_data *xfcd; + /** + * @private fetch_timeout + * + * Unsigned integer to specify libfetch's timeout limit. + * If not set, it defaults to 30 (in seconds). This is set internally + * by the API from a setting in configuration file. + */ + uint16_t fetch_timeout; + /** + * @var flags + * + * Flags to be set globally, possible values: + * - XBPS_FLAG_VERBOSE + * - XBPS_FLAG_FORCE + */ + int flags; + /** + * @var rootdir + * + * Root directory for all operations in XBPS. If NULL, + * by default it's set to /. + */ + const char *rootdir; + /** + * @var cachedir + * + * Cache directory to store downloaded binary packages. + * If NULL default value in \a XBPS_CACHE_PATH is used. + */ + const char *cachedir; + /** + * @private pstring_cachedir + * + * Used internally by xbps_init(), do not use it. + */ + prop_string_t pstring_cachedir; + /** + * @var conffile + * + * Full path to the XBPS_CONF_PLIST configuration file. + */ + const char *conffile; + /** + * @var debug + * + * Set to true to enable debugging messages to stderr. + */ + bool debug; + /** + * @var install_reason_auto + * + * Set to true to make installed or updated target package + * (and its dependencies) marked with automatic installation, + * thus it will be found as orphan if no packages are depending + * on it. + */ + bool install_reason_auto; + /** + * @var install_reason_manual + * + * Set to true to make installed or updated target package + * (and its dependencies) marked with manual installation, thus + * it will never will be found as orphan. + */ + bool install_reason_manual; +}; + +/** + * Initialize the XBPS library with the following steps: + * + * - Set function callbacks for fetching and unpacking. + * - Set root directory (if not set, defaults to /). + * - Set cache directory (if not set, defaults to XBPS_CACHE_PATH). + * - Set global flags. + * - Set default cache connections for libfetch. + * - Initialize the debug printfs. + * - Internalize the proplib dictionary in config file. + * - Internalize the regpkgdb dictionary (if available). + * + * @param[in] xhp Pointer to an xbps_handle structure, as returned by + * \a xbps_handle_alloc(). + * @note It's assumed that \a xhp is a valid pointer. + * + * @return 0 on success, an errno value otherwise. + */ +int xbps_init(struct xbps_handle *xhp); + +/** + * Releases all resources used by libxbps. + * + * @param[in] xhp Pointer to an xbps_handle structure, as returned + * by \a xbps_handle_alloc(). + * @note It's assumed that \a xhp is a valid pointer. + */ +void xbps_end(struct xbps_handle *xhp); + +/** + * Allocated an xbps_handle structure. + * + * @return A pointer to the allocated xbps_handle structure, NULL + * otherwise. + */ +struct xbps_handle *xbps_handle_alloc(void); + +/** + * Returns a pointer to the xbps_handle structure set by xbps_init(). + */ +struct xbps_handle *xbps_handle_get(void); + +/*@}*/ + +/** @addtogroup configure */ +/*@{*/ + +/** + * Configure (or force reconfiguration of) a package. + * + * @param[in] pkgname Package name to configure. + * @param[in] version Package version (optional). + * @param[in] check_state Set it to true to check that package is + * in unpacked state. + * @param[in] update Set it to true if this package is being updated. + * + * @return 0 on success, otherwise an errno value. + */ +int xbps_configure_pkg(const char *pkgname, + const char *version, + bool check_state, + bool update); + +/** + * Configure (or force reconfiguration of) all packages. + * + * @return 0 on success, otherwise an errno value. + */ +int xbps_configure_packages(void); + +/*@}*/ + +/** + * @ingroup vermatch + * + * Compares package version strings. + * + * The package version is defined by: + * ${VERSION}[_${REVISION}]. + * + * ${VERSION} supersedes ${REVISION}. + * + * @param[in] pkg1 a package version string. + * @param[in] pkg2 a package version string. + * + * @return -1, 0 or 1 depending if pkg1 is less than, equal to or + * greater than pkg2. + */ +int xbps_cmpver(const char *pkg1, const char *pkg2); + + +/** @addtogroup download */ +/*@{*/ + + /** * Download a file from a remote URL. * @@ -944,6 +1125,16 @@ int xbps_repository_update_packages(void); */ prop_dictionary_t xbps_transaction_prepare(void); +/** + * Commit a transaction. The transaction dictionary contains all steps + * to be executed in the transaction, as returned by xbps_transaction_prepare(). + * + * @param[in] transd The transaction dictionary. + * + * @return 0 on success, otherwise an errno value. + */ +int xbps_transaction_commit(prop_dictionary_t transd); + /** * Returns the missing deps array if xbps_repository_install_pkg() * or xbps_repository_update_pkg() failed to find required packages @@ -1157,55 +1348,6 @@ int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state); /** @addtogroup unpack */ /*@{*/ -/** - * @struct xbps_unpack_progress_data xbps_api.h "xbps_api.h" - * @brief Structure to be passed to the unpacking progress function callback. - * - * This structure is passed as argument to the unpack progress function - * callback and its members will be updated when there's any progress. - * All members in this struct are set internally by xbps_unpack_binary_pkg() - * and should be used in read-only mode in the function callback. - */ -struct xbps_unpack_progress_data { - /** - * @var entry - * - * Entry pathname string (set internally, read only). - */ - const char *entry; - /** - * @var entry_size - * - * Entry file size (set internally, read only). - */ - int64_t entry_size; - /** - * @var entry_extract_count - * - * Total number of extracted entries (set internally, read only). - */ - ssize_t entry_extract_count; - /** - * @var entry_total_count - * - * Total number of entries in package (set internally, read only). - */ - ssize_t entry_total_count; - /** - * @var entry_is_metadata - * - * If true "entry" is a package metadata file (set internally, - * read only). - */ - bool entry_is_metadata; - /** - * @var entry_is_conf - * - * If true "entry" is a configuration file (set internally, - * read only). - */ - bool entry_is_conf; -}; /** * Unpacks a binary package into specified root directory. diff --git a/lib/Makefile b/lib/Makefile index c80c3515..9dee0ae2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -40,7 +40,7 @@ endif 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 package_replaces.o +OBJS += package_purge.o package_replaces.o transaction_commit.o OBJS += transaction_dictionary.o transaction_sortdeps.o OBJS += download.o fexec.o humanize_number.o plist.o OBJS += plist_archive_entry.o plist_find.o plist_match.o plist_remove.o diff --git a/lib/download.c b/lib/download.c index 5c231334..5495fa85 100644 --- a/lib/download.c +++ b/lib/download.c @@ -90,7 +90,7 @@ xbps_fetch_file(const char *uri, bool refetch, const char *flags) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; struct stat st; struct url *url = NULL; struct url_stat url_st; @@ -263,15 +263,15 @@ xbps_fetch_file(const char *uri, * and let the user know that the transfer is going to start * immediately. */ - if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfpd != NULL) { - xhp->xfpd->file_name = filename; - xhp->xfpd->file_size = url_st.size; - xhp->xfpd->file_offset = url->offset; - xhp->xfpd->file_dloaded = -1; - xhp->xfpd->cb_start = true; - xhp->xfpd->cb_update = false; - xhp->xfpd->cb_end = false; - xhp->xbps_fetch_cb(xhp->xfpd); + if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfcd != NULL) { + xhp->xfcd->file_name = filename; + xhp->xfcd->file_size = url_st.size; + xhp->xfcd->file_offset = url->offset; + xhp->xfcd->file_dloaded = -1; + xhp->xfcd->cb_start = true; + xhp->xfcd->cb_update = false; + xhp->xfcd->cb_end = false; + xhp->xbps_fetch_cb(xhp->xfcd); } /* * Start fetching requested file. @@ -289,11 +289,11 @@ xbps_fetch_file(const char *uri, * we are sucking more bytes from it. */ if (xhp != NULL && xhp->xbps_fetch_cb != NULL && - xhp->xfpd != NULL) { - xhp->xfpd->file_dloaded = bytes_dload; - xhp->xfpd->cb_start = false; - xhp->xfpd->cb_update = true; - xhp->xbps_fetch_cb(xhp->xfpd); + xhp->xfcd != NULL) { + xhp->xfcd->file_dloaded = bytes_dload; + xhp->xfcd->cb_start = false; + xhp->xfcd->cb_update = true; + xhp->xbps_fetch_cb(xhp->xfcd); } } @@ -301,10 +301,10 @@ xbps_fetch_file(const char *uri, * Let the fetch progress callback know that the file * has been fetched. */ - if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfpd != NULL) { - xhp->xfpd->cb_update = false; - xhp->xfpd->cb_end = true; - xhp->xbps_fetch_cb(xhp->xfpd); + if (xhp != NULL && xhp->xbps_fetch_cb != NULL && xhp->xfcd != NULL) { + xhp->xfcd->cb_update = false; + xhp->xfcd->cb_end = true; + xhp->xbps_fetch_cb(xhp->xfcd); } if (bytes_read == -1) { xbps_error_printf("IO error while fetching %s: %s\n", filename, diff --git a/lib/initend.c b/lib/initend.c index 03bcb5c4..15269d51 100644 --- a/lib/initend.c +++ b/lib/initend.c @@ -52,7 +52,7 @@ xbps_init(struct xbps_handle *xh) assert(xh != NULL); xhp = xh; - debug = xhp->with_debug; + debug = xhp->debug; /* If conffile not set, defaults to XBPS_CONF_PATH */ if (xhp->conffile == NULL) @@ -67,7 +67,7 @@ xbps_init(struct xbps_handle *xh) if (errno != ENOENT) { xbps_dbg_printf("%s: cannot internalize conf " "dictionary: %s\n", strerror(errno)); - xbps_end(); + xbps_end(xh); return errno; } xbps_dbg_printf("%s: conf_dictionary not internalized.\n", @@ -101,9 +101,22 @@ xbps_init(struct xbps_handle *xh) } } if (xhp->cachedir == NULL) { - if (conf_cachedir != NULL) - xhp->cachedir = conf_cachedir; - else { + if (conf_cachedir != NULL) { + if (conf_cachedir[0] == '/') { + /* full path */ + xhp->cachedir = conf_cachedir; + } else { + /* relative to rootdir */ + xhp->pstring_cachedir = + prop_string_create_cstring(xhp->rootdir); + prop_string_append_cstring( + xhp->pstring_cachedir, "/"); + prop_string_append_cstring( + xhp->pstring_cachedir, conf_cachedir); + xhp->cachedir = prop_string_cstring_nocopy( + xhp->pstring_cachedir); + } + } else { /* If cachedir not set, defaults to XBPS_CACHE_PATH */ xhp->cachedir = XBPS_CACHE_PATH; } @@ -130,7 +143,7 @@ xbps_init(struct xbps_handle *xh) if (rv != ENOENT) { xbps_dbg_printf("%s: couldn't initialize " "regpkgdb: %s\n", strerror(rv)); - xbps_end(); + xbps_end(xh); return rv; } } @@ -139,27 +152,68 @@ xbps_init(struct xbps_handle *xh) } void -xbps_end(void) +xbps_end(struct xbps_handle *xh) { xbps_regpkgdb_dictionary_release(); xbps_repository_pool_release(); xbps_fetch_unset_cache_connection(); - if (xhp == NULL) + if (xh == NULL) return; - if (prop_object_type(xhp->conf_dictionary) == PROP_TYPE_DICTIONARY) - prop_object_release(xhp->conf_dictionary); + if (prop_object_type(xh->conf_dictionary) == PROP_TYPE_DICTIONARY) + prop_object_release(xh->conf_dictionary); + if (prop_object_type(xh->pstring_cachedir) == PROP_TYPE_STRING) + prop_object_release(xh->pstring_cachedir); + if (xh->xfcd != NULL) + free(xh->xfcd); + if (xh->xucd != NULL) + free(xh->xucd); + if (xh->xtcd != NULL) + free(xh->xtcd); + + free(xh); + xh = NULL; xhp = NULL; } -const struct xbps_handle * +struct xbps_handle * xbps_handle_get(void) { assert(xhp != NULL); return xhp; } +struct xbps_handle * +xbps_handle_alloc(void) +{ + struct xbps_handle *xh; + + xh = calloc(1, sizeof(struct xbps_handle)); + if (xh == NULL) + return NULL; + xh->xtcd = calloc(1, sizeof(struct xbps_transaction_cb_data)); + if (xh->xtcd == NULL) { + free(xh); + return NULL; + } + xh->xucd = calloc(1, sizeof(struct xbps_unpack_cb_data)); + if (xh->xucd == NULL) { + free(xh->xtcd); + free(xh); + return NULL; + } + xh->xfcd = calloc(1, sizeof(struct xbps_fetch_cb_data)); + if (xh->xfcd == NULL) { + free(xh->xucd); + free(xh->xtcd); + free(xh); + return NULL; + } + + return xh; +} + static void common_printf(FILE *f, const char *msg, const char *fmt, va_list ap) { diff --git a/lib/package_configure.c b/lib/package_configure.c index 65ddc0e3..a66da546 100644 --- a/lib/package_configure.c +++ b/lib/package_configure.c @@ -50,7 +50,7 @@ int xbps_configure_packages(void) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_object_t obj; prop_object_iterator_t iter; const char *pkgname, *version; @@ -79,13 +79,12 @@ xbps_configure_pkg(const char *pkgname, bool check_state, bool update) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t pkgd; const char *lver; char *buf, *pkgver; int rv = 0; pkg_state_t state = 0; - bool reconfigure = false; assert(pkgname != NULL); xhp = xbps_handle_get(); @@ -98,8 +97,6 @@ xbps_configure_pkg(const char *pkgname, if (state == XBPS_PKG_STATE_INSTALLED) { if ((xhp->flags & XBPS_FLAG_FORCE) == 0) return 0; - - reconfigure = true; } else if (state != XBPS_PKG_STATE_UNPACKED) return EINVAL; @@ -110,18 +107,31 @@ xbps_configure_pkg(const char *pkgname, lver = version; } - xbps_printf("%sonfiguring package `%s-%s' ...\n", - reconfigure ? "Rec" : "C", pkgname, lver); + pkgver = xbps_xasprintf("%s-%s", pkgname, lver); + if (pkgver == NULL) + return ENOMEM; + + if (xhp->xbps_transaction_cb) { + xhp->xtcd->desc = NULL; + xhp->xtcd->binpkg_fname = NULL; + xhp->xtcd->binpkg_repourl = NULL; + xhp->xtcd->state = XBPS_TRANS_STATE_CONFIGURE; + xhp->xtcd->pkgver = pkgver; + xhp->xbps_transaction_cb(xhp->xtcd); + } buf = xbps_xasprintf(".%s/metadata/%s/INSTALL", XBPS_META_PATH, pkgname); - if (buf == NULL) + if (buf == NULL) { + free(pkgver); return ENOMEM; + } if (chdir(xhp->rootdir) == -1) { xbps_dbg_printf("%s: [configure] chdir to '%s' returned %s\n", pkgname, xhp->rootdir, strerror(errno)); free(buf); + free(pkgver); return EINVAL; } @@ -129,6 +139,7 @@ xbps_configure_pkg(const char *pkgname, if (xbps_file_exec(buf, "post", pkgname, lver, update ? "yes" : "no", NULL) != 0) { free(buf); + free(pkgver); xbps_error_printf("%s: post install script error: %s\n", pkgname, strerror(errno)); return errno; @@ -136,14 +147,11 @@ xbps_configure_pkg(const char *pkgname, } else { if (errno != ENOENT) { free(buf); + free(pkgver); return errno; } } free(buf); - pkgver = xbps_xasprintf("%s-%s", pkgname, lver); - if (pkgver == NULL) - return ENOMEM; - rv = xbps_set_pkg_state_installed(pkgname, lver, pkgver, XBPS_PKG_STATE_INSTALLED); free(pkgver); diff --git a/lib/package_orphans.c b/lib/package_orphans.c index 6d9f7480..da5b6927 100644 --- a/lib/package_orphans.c +++ b/lib/package_orphans.c @@ -147,6 +147,7 @@ find_orphan_pkg(prop_object_t obj, void *arg, bool *loop_done) break; } } + free(pkgdepname); } prop_object_iterator_release(iter); @@ -161,7 +162,7 @@ find_orphan_pkg(prop_object_t obj, void *arg, bool *loop_done) prop_array_t xbps_find_pkg_orphans(prop_array_t orphans_user) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_array_t array = NULL; struct orphan_data od; int rv = 0; @@ -186,5 +187,6 @@ xbps_find_pkg_orphans(prop_array_t orphans_user) return NULL; } array = prop_array_copy(od.array); + prop_object_release(od.array); return array; } diff --git a/lib/package_purge.c b/lib/package_purge.c index 784873e6..8ac81f28 100644 --- a/lib/package_purge.c +++ b/lib/package_purge.c @@ -95,7 +95,7 @@ remove_pkg_metadata(const char *pkgname, const char *rootdir) int xbps_purge_packages(void) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_object_t obj; prop_object_iterator_t iter; const char *pkgname; @@ -118,7 +118,7 @@ xbps_purge_packages(void) int xbps_purge_pkg(const char *pkgname, bool check_state) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t dict, pkgd; const char *version; char *buf; diff --git a/lib/package_register.c b/lib/package_register.c index 67ea5107..39152df1 100644 --- a/lib/package_register.c +++ b/lib/package_register.c @@ -42,13 +42,13 @@ int xbps_register_pkg(prop_dictionary_t pkgrd) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t dict, pkgd; prop_array_t array, provides = NULL; const char *pkgname, *version, *desc, *pkgver; char *plist; int rv = 0; - bool autoinst; + bool autoinst = false; xhp = xbps_handle_get(); plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir, @@ -149,7 +149,7 @@ out: int xbps_unregister_pkg(const char *pkgname) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; char *plist; int rv = 0; diff --git a/lib/package_remove.c b/lib/package_remove.c index 6780f2f0..e6bf430b 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -73,7 +73,7 @@ int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_array_t array; prop_object_iterator_t iter; prop_object_t obj; @@ -172,7 +172,7 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) int xbps_remove_pkg(const char *pkgname, const char *version, bool update) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t dict; const char *pkgver; char *buf; diff --git a/lib/package_requiredby.c b/lib/package_requiredby.c index 9de83a42..b87f758a 100644 --- a/lib/package_requiredby.c +++ b/lib/package_requiredby.c @@ -102,7 +102,7 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done) int HIDDEN xbps_requiredby_pkg_remove(const char *pkgname) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t dict; char *plist; int rv = 0; diff --git a/lib/package_state.c b/lib/package_state.c index 8f686e7b..59575e55 100644 --- a/lib/package_state.c +++ b/lib/package_state.c @@ -164,7 +164,7 @@ xbps_set_pkg_state_installed(const char *pkgname, const char *pkgver, pkg_state_t state) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t dict = NULL, pkgd; prop_array_t array; char *plist; diff --git a/lib/package_unpack.c b/lib/package_unpack.c index 335722c1..5270dad6 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -152,8 +152,8 @@ remove_metafile(const char *file, const char *pkgname, const char *version) */ #define RUN_PROGRESS_CB() \ do { \ - if (xhp != NULL && xhp->xbps_unpack_cb != NULL && xhp->xupd != NULL) \ - (*xhp->xbps_unpack_cb)(xhp->xupd); \ + if (xhp != NULL && xhp->xbps_unpack_cb != NULL && xhp->xucd != NULL) \ + (*xhp->xbps_unpack_cb)(xhp->xucd); \ } while (0) static int @@ -161,7 +161,7 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar, const char *pkgname, const char *version, - const struct xbps_handle *xhp) + struct xbps_handle *xhp) { prop_dictionary_t propsd = NULL, filesd = NULL, old_filesd = NULL; prop_array_t array; @@ -211,11 +211,11 @@ unpack_archive(prop_dictionary_t pkg_repod, entry_pname = archive_entry_pathname(entry); set_extract_flags(&flags, update); if (xhp != NULL && xhp->xbps_unpack_cb != NULL && - xhp->xupd != NULL) { - xhp->xupd->entry = entry_pname; - xhp->xupd->entry_size = archive_entry_size(entry); - xhp->xupd->entry_is_metadata = false; - xhp->xupd->entry_is_conf = false; + xhp->xucd != NULL) { + xhp->xucd->entry = entry_pname; + xhp->xucd->entry_size = archive_entry_size(entry); + xhp->xucd->entry_is_metadata = false; + xhp->xucd->entry_is_conf = false; } if (strcmp("./INSTALL", entry_pname) == 0) { @@ -245,9 +245,9 @@ unpack_archive(prop_dictionary_t pkg_repod, goto out; } nmetadata++; - if (xhp->xupd != NULL) { - xhp->xupd->entry_is_metadata = true; - xhp->xupd->entry_extract_count++; + if (xhp->xucd != NULL) { + xhp->xucd->entry_is_metadata = true; + xhp->xucd->entry_extract_count++; } RUN_PROGRESS_CB(); continue; @@ -259,9 +259,9 @@ unpack_archive(prop_dictionary_t pkg_repod, goto out; nmetadata++; - if (xhp->xupd != NULL) { - xhp->xupd->entry_is_metadata = true; - xhp->xupd->entry_extract_count++; + if (xhp->xucd != NULL) { + xhp->xucd->entry_is_metadata = true; + xhp->xucd->entry_extract_count++; } RUN_PROGRESS_CB(); continue; @@ -278,9 +278,9 @@ unpack_archive(prop_dictionary_t pkg_repod, goto out; } nmetadata++; - if (xhp->xupd != NULL) { - xhp->xupd->entry_is_metadata = true; - xhp->xupd->entry_extract_count++; + if (xhp->xucd != NULL) { + xhp->xucd->entry_is_metadata = true; + xhp->xucd->entry_extract_count++; } RUN_PROGRESS_CB(); continue; @@ -298,9 +298,9 @@ unpack_archive(prop_dictionary_t pkg_repod, goto out; } nmetadata++; - if (xhp->xupd != NULL) { - xhp->xupd->entry_is_metadata = true; - xhp->xupd->entry_extract_count++; + if (xhp->xucd != NULL) { + xhp->xucd->entry_is_metadata = true; + xhp->xucd->entry_extract_count++; } RUN_PROGRESS_CB(); continue; @@ -329,16 +329,16 @@ unpack_archive(prop_dictionary_t pkg_repod, * Compute total entries in progress data, if set. * total_entries = metadata + files + conf_files + links. */ - if (xhp->xupd != NULL) { - xhp->xupd->entry_total_count = nmetadata; + if (xhp->xucd != NULL) { + xhp->xucd->entry_total_count = nmetadata; array = prop_dictionary_get(filesd, "files"); - xhp->xupd->entry_total_count += + xhp->xucd->entry_total_count += (ssize_t)prop_array_count(array); array = prop_dictionary_get(filesd, "conf_files"); - xhp->xupd->entry_total_count += + xhp->xucd->entry_total_count += (ssize_t)prop_array_count(array); array = prop_dictionary_get(filesd, "links"); - xhp->xupd->entry_total_count += + xhp->xucd->entry_total_count += (ssize_t)prop_array_count(array); } @@ -353,8 +353,8 @@ unpack_archive(prop_dictionary_t pkg_repod, /* error */ goto out; } else if (rv == 1) { - if (xhp->xupd != NULL) - xhp->xupd->entry_is_conf = true; + if (xhp->xucd != NULL) + xhp->xucd->entry_is_conf = true; rv = xbps_entry_install_conf_file(filesd, entry, entry_pname, pkgname, version); @@ -396,8 +396,8 @@ unpack_archive(prop_dictionary_t pkg_repod, continue; } } - if (xhp->xupd != NULL) - xhp->xupd->entry_extract_count++; + if (xhp->xucd != NULL) + xhp->xucd->entry_extract_count++; RUN_PROGRESS_CB(); } @@ -462,7 +462,7 @@ out: int xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; struct archive *ar; const char *pkgname, *version, *repoloc, *pkgver; char *bpkg; @@ -503,9 +503,9 @@ xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod) * Set extract progress callback if specified. */ xhp = xbps_handle_get(); - if (xhp != NULL && xhp->xbps_unpack_cb != NULL && xhp->xupd != NULL) { - xhp->xupd->entry_extract_count = 0; - xhp->xupd->entry_total_count = 0; + if (xhp != NULL && xhp->xbps_unpack_cb != NULL && xhp->xucd != NULL) { + xhp->xucd->entry_extract_count = 0; + xhp->xucd->entry_total_count = 0; } /* * Extract archive files. diff --git a/lib/plist.c b/lib/plist.c index 1939b6bd..141f020e 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -186,7 +186,7 @@ prop_dictionary_t xbps_dictionary_from_metadata_plist(const char *pkgname, const char *plist) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t pkgd, plistd = NULL; const char *rpkgname; char *plistf; diff --git a/lib/plist_find.c b/lib/plist_find.c index a66eef84..0a631789 100644 --- a/lib/plist_find.c +++ b/lib/plist_find.c @@ -322,7 +322,7 @@ xbps_find_pkg_dict_from_plist_by_pattern(const char *plist, static prop_dictionary_t find_pkgd_installed(const char *str, bool bypattern, bool virtual) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_dictionary_t pkgd, rpkgd = NULL; pkg_state_t state = 0; diff --git a/lib/regpkgdb_dictionary.c b/lib/regpkgdb_dictionary.c index 13e78046..c70eead3 100644 --- a/lib/regpkgdb_dictionary.c +++ b/lib/regpkgdb_dictionary.c @@ -90,7 +90,7 @@ xbps_regpkgdb_dictionary_init(struct xbps_handle *xhp) void HIDDEN xbps_regpkgdb_dictionary_release(void) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; if (!regpkgdb_initialized) return; diff --git a/lib/repository_findpkg.c b/lib/repository_findpkg.c index b5de52b1..72cfcc28 100644 --- a/lib/repository_findpkg.c +++ b/lib/repository_findpkg.c @@ -176,7 +176,7 @@ out: int xbps_repository_update_packages(void) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_object_t obj; prop_object_iterator_t iter; const char *pkgname; diff --git a/lib/repository_pool.c b/lib/repository_pool.c index e4683ca3..22bd7727 100644 --- a/lib/repository_pool.c +++ b/lib/repository_pool.c @@ -56,7 +56,7 @@ static bool repolist_initialized; int HIDDEN xbps_repository_pool_init(void) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; prop_array_t array; prop_object_t obj; prop_object_iterator_t iter = NULL; @@ -258,7 +258,7 @@ xbps_repository_pool_foreach( xbps_dbg_printf("%s: couldn't initialize " "repository pool: %s\n", __func__, strerror(rv)); } - xbps_end(); + xbps_end(xbps_handle_get()); return rv; } diff --git a/lib/repository_sync_index.c b/lib/repository_sync_index.c index d86a8e4d..e4064673 100644 --- a/lib/repository_sync_index.c +++ b/lib/repository_sync_index.c @@ -83,7 +83,7 @@ xbps_get_remote_repo_string(const char *uri) int xbps_repository_sync_pkg_index(const char *uri) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; struct url *url = NULL; struct utsname un; struct stat st; diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c new file mode 100644 index 00000000..40da331a --- /dev/null +++ b/lib/transaction_commit.c @@ -0,0 +1,360 @@ +/*- + * Copyright (c) 2009-2011 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 +#include +#include + +#include "xbps_api_impl.h" + +#define RUN_TRANS_CB(s, d, p, bf, burl) \ +do { \ + if (xhp->xbps_transaction_cb != NULL) { \ + xhp->xtcd->state = s; \ + xhp->xtcd->desc = d; \ + xhp->xtcd->pkgver = p; \ + xhp->xtcd->binpkg_fname = bf; \ + xhp->xtcd->binpkg_repourl = burl; \ + (*xhp->xbps_transaction_cb)(xhp->xtcd); \ + } \ +} while (0) + +#define RUN_TRANS_ERR_CB(s, p, r) \ +do { \ + if (xhp->xbps_transaction_err_cb != NULL) { \ + xhp->xtcd->state = s; \ + xhp->xtcd->pkgver = p; \ + xhp->xtcd->err = r; \ + (*xhp->xbps_transaction_err_cb)(xhp->xtcd); \ + } \ +} while (0) + +static int +check_binpkgs_hash(struct xbps_handle *xhp, prop_object_iterator_t iter) +{ + prop_object_t obj; + const char *pkgver, *repoloc, *filename, *sha256, *trans; + char *binfile; + int rv = 0; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", &trans); + if ((strcmp(trans, "remove") == 0) || + (strcmp(trans, "configure") == 0)) + continue; + + prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); + assert(repoloc != NULL); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); + assert(pkgver != NULL); + prop_dictionary_get_cstring_nocopy(obj, "filename", &filename); + assert(filename != NULL); + prop_dictionary_get_cstring_nocopy(obj, + "filename-sha256", &sha256); + assert(sha256 != NULL); + + binfile = xbps_path_from_repository_uri(obj, repoloc); + if (binfile == NULL) { + rv = EINVAL; + break; + } + RUN_TRANS_CB(XBPS_TRANS_STATE_VERIFY, + NULL, pkgver, filename, repoloc); + rv = xbps_file_hash_check(binfile, sha256); + if (rv != 0) { + free(binfile); + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_VERIFY, pkgver, rv); + break; + } + free(binfile); + } + prop_object_iterator_reset(iter); + + return rv; +} + +static int +download_binpkgs(struct xbps_handle *xhp, prop_object_iterator_t iter) +{ + prop_object_t obj; + const char *pkgver, *repoloc, *filename, *trans; + char *binfile; + int rv = 0; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", &trans); + if ((strcmp(trans, "remove") == 0) || + (strcmp(trans, "configure") == 0)) + continue; + + prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc); + assert(repoloc != NULL); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); + assert(pkgver != NULL); + prop_dictionary_get_cstring_nocopy(obj, "filename", &filename); + assert(filename != NULL); + + binfile = xbps_path_from_repository_uri(obj, repoloc); + if (binfile == NULL) { + rv = EINVAL; + break; + } + /* + * If downloaded package is in cachedir continue. + */ + if (access(binfile, R_OK) == 0) { + free(binfile); + continue; + } + /* + * Create cachedir. + */ + if (xbps_mkpath(xhp->cachedir, 0755) == -1) { + xbps_error_printf("xbps-bin: cannot mkdir cachedir " + "`%s': %s.\n", xhp->cachedir, strerror(errno)); + free(binfile); + rv = errno; + break; + } + RUN_TRANS_CB(XBPS_TRANS_STATE_DOWNLOAD, + NULL, pkgver, filename, repoloc); + /* + * Fetch binary package. + */ + rv = xbps_fetch_file(binfile, xhp->cachedir, false, NULL); + if (rv == -1) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_DOWNLOAD, pkgver, errno); + free(binfile); + break; + } + rv = 0; + free(binfile); + } + prop_object_iterator_reset(iter); + + return rv; +} + +int +xbps_transaction_commit(prop_dictionary_t transd) +{ + struct xbps_handle *xhp; + prop_object_t obj; + prop_object_iterator_t iter; + const char *pkgname, *version, *pkgver, *filen, *tract; + int rv = 0; + bool update, preserve; + pkg_state_t state; + + assert(transd != NULL); + + xhp = xbps_handle_get(); + iter = xbps_array_iter_from_dict(transd, "packages"); + if (iter == NULL) + return EINVAL; + /* + * Download binary packages (if they come from a remote repository). + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_DOWNLOAD, + "[*] Downloading binary packages", NULL, NULL, NULL); + if ((rv = download_binpkgs(xhp, iter)) != 0) + goto out; + + /* + * Check SHA256 hashes for binary packages in transaction. + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_VERIFY, + "[*] Verifying binary package integrity", NULL, NULL, NULL); + if ((rv = check_binpkgs_hash(xhp, iter)) != 0) + goto out; + + /* + * Remove packages to be replaced. + */ + if (prop_dictionary_get(transd, "total-remove-pkgs")) { + RUN_TRANS_CB(XBPS_TRANS_STATE_REPLACE, + "[*] Removing packages to be replaced", NULL, NULL, NULL); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", + &tract); + if (strcmp(tract, "remove")) + continue; + + prop_dictionary_get_cstring_nocopy(obj, "pkgname", + &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", + &version); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", + &pkgver); + update = false; + prop_dictionary_get_bool(obj, "remove-and-update", + &update); + + /* Remove and purge packages that shall be replaced */ + RUN_TRANS_CB(XBPS_TRANS_STATE_REMOVE, + NULL, pkgver, NULL, NULL); + rv = xbps_remove_pkg(pkgname, version, update); + if (rv != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_REMOVE, + pkgver, rv); + goto out; + } + if (!update) + continue; + + RUN_TRANS_CB(XBPS_TRANS_STATE_PURGE, + NULL, pkgver, NULL, NULL); + if ((rv = xbps_purge_pkg(pkgname, false)) != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_PURGE, + pkgver, rv); + goto out; + } + } + prop_object_iterator_reset(iter); + } + /* + * Configure pending packages. + */ + if (prop_dictionary_get(transd, "total-configure-pkgs")) { + RUN_TRANS_CB(XBPS_TRANS_STATE_CONFIGURE, + "[*] Reconfigure unpacked packages", NULL, NULL, NULL); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", + &tract); + if (strcmp(tract, "configure")) + continue; + prop_dictionary_get_cstring_nocopy(obj, "pkgname", + &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", + &version); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", + &pkgver); + + rv = xbps_configure_pkg(pkgname, version, false, false); + if (rv != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_CONFIGURE, + pkgver, rv); + goto out; + } + } + prop_object_iterator_reset(iter); + } + /* + * Install or update packages in transaction. + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_INSTALL, + "[*] Unpacking packages to be installed/updated", NULL, NULL, NULL); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract); + /* Match only packages to be installed or updated */ + if ((strcmp(tract, "remove") == 0) || + (strcmp(tract, "configure") == 0)) + continue; + + preserve = false; + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); + prop_dictionary_get_cstring_nocopy(obj, "filename", &filen); + prop_dictionary_get_bool(obj, "preserve", &preserve); + /* + * If dependency is already unpacked skip this phase. + */ + state = 0; + if (xbps_pkg_state_dictionary(obj, &state) != 0) { + rv = EINVAL; + goto out; + } + if (state == XBPS_PKG_STATE_UNPACKED) + continue; + + if (strcmp(tract, "update") == 0) { + /* Update a package, execute pre-remove action if found */ + RUN_TRANS_CB(XBPS_TRANS_STATE_UPDATE, + NULL, pkgver, filen, NULL); + if ((rv = xbps_remove_pkg(pkgname, version, true)) != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_UPDATE, + pkgver, rv); + goto out; + } + } + /* + * Unpack binary package. + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_UNPACK, NULL, pkgver, filen, NULL); + if ((rv = xbps_unpack_binary_pkg(obj)) != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_UNPACK, pkgver, rv); + goto out; + } + /* + * Register binary package. + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_REGISTER, + NULL, pkgver, filen, NULL); + if ((rv = xbps_register_pkg(obj)) != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_REGISTER, pkgver, rv); + goto out; + } + } + prop_object_iterator_reset(iter); + + /* + * Configure all unpacked packages. + */ + RUN_TRANS_CB(XBPS_TRANS_STATE_CONFIGURE, + "[*] Configuring packages installed/updated", NULL, NULL, NULL); + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract); + if ((strcmp(tract, "remove") == 0) || + (strcmp(tract, "configure") == 0)) + continue; + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + update = false; + if (strcmp(tract, "update") == 0) + update = true; + + rv = xbps_configure_pkg(pkgname, version, false, update); + if (rv != 0) { + RUN_TRANS_ERR_CB(XBPS_TRANS_STATE_CONFIGURE, pkgver, rv); + goto out; + } + } + +out: + prop_object_iterator_release(iter); + + return rv; +} diff --git a/lib/util.c b/lib/util.c index a34bbdc9..dfe45667 100644 --- a/lib/util.c +++ b/lib/util.c @@ -203,7 +203,7 @@ xbps_pkgpattern_version(const char *pkg) static char * get_pkg_index_remote_plist(const char *uri) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; char *uri_fixed, *repodir; assert(uri != NULL); @@ -243,7 +243,7 @@ xbps_pkg_index_plist(const char *uri) char * xbps_path_from_repository_uri(prop_dictionary_t pkg_repod, const char *repoloc) { - const struct xbps_handle *xhp; + struct xbps_handle *xhp; const char *filen, *arch; char *lbinpkg = NULL;