diff --git a/bin/xbps-bin/check.c b/bin/xbps-bin/check.c index 2f765ca3..dc397a2f 100644 --- a/bin/xbps-bin/check.c +++ b/bin/xbps-bin/check.c @@ -110,7 +110,7 @@ xbps_check_pkg_integrity(const char *pkgname) assert(pkgname != NULL); - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) { printf("Package %s is not installed.\n", pkgname); return 0; diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index ffc60722..470af70f 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -37,22 +37,11 @@ struct transaction { prop_dictionary_t dict; prop_object_iterator_t iter; bool yes; + size_t inst_pkgcnt; + size_t up_pkgcnt; + size_t cf_pkgcnt; }; -static int exec_transaction(struct transaction *); -static void show_missing_deps(prop_dictionary_t); -static int show_missing_dep_cb(prop_object_t, void *, bool *); -static void show_package_list(prop_object_iterator_t, const char *); - -static void -show_missing_deps(prop_dictionary_t d) -{ - fprintf(stderr, - "xbps-bin: unable to locate some required packages:\n"); - (void)xbps_callback_array_iter_in_dict(d, "missing_deps", - show_missing_dep_cb, NULL); -} - static int show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) { @@ -69,6 +58,15 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) return 0; } +static void +show_missing_deps(prop_dictionary_t d) +{ + fprintf(stderr, + "xbps-bin: unable to locate some required packages:\n"); + (void)xbps_callback_array_iter_in_dict(d, "missing_deps", + show_missing_dep_cb, NULL); +} + static bool check_binpkg_hash(const char *path, const char *filename, const char *sha256) @@ -125,7 +123,7 @@ download_package_list(prop_object_iterator_t iter) /* * If package is in a local repository, check its hash - * and pass no next one. + * and pass to next one. */ if (!xbps_check_is_repo_string_remote(repoloc)) { if (!check_binpkg_hash(lbinfile, filename, sha256)) { @@ -167,11 +165,12 @@ download_package_list(prop_object_iterator_t iter) rv = xbps_fetch_file(binfile, cachedir, false, NULL); free(binfile); if (rv == -1) { - fprintf(stderr, "xbps-bin: couldn't download %s " - "from %s (%s)\n", filename, repoloc, - xbps_fetch_error_string()); + fprintf(stderr, "xbps-bin: couldn't download `%s'\n", + filename); + fprintf(stderr, "xbps-bin: %s returned: `%s'\n", + repoloc, xbps_fetch_error_string()); free(lbinfile); - return errno; + return -1; } if (!check_binpkg_hash(lbinfile, filename, sha256)) { fprintf(stderr, "W: removing wrong %s file ...\n", @@ -221,66 +220,62 @@ show_package_list(prop_object_iterator_t iter, const char *match) } static int -show_transaction_sizes(prop_object_iterator_t iter) +show_transaction_sizes(struct transaction *trans) { prop_object_t obj; - uint64_t tsize = 0, dlsize = 0, instsize = 0; + uint64_t dlsize = 0, instsize = 0; const char *tract; char size[64]; bool trans_inst, trans_up, trans_conf; trans_inst = trans_up = trans_conf = false; - while ((obj = prop_object_iterator_next(iter)) != NULL) { - if (!prop_dictionary_get_uint64(obj, "filename-size", &tsize)) - return errno; - - dlsize += tsize; - tsize = 0; - if (!prop_dictionary_get_uint64(obj, "installed_size", &tsize)) - return errno; - - instsize += tsize; - tsize = 0; - } - prop_object_iterator_reset(iter); - - while ((obj = prop_object_iterator_next(iter))) { + while ((obj = prop_object_iterator_next(trans->iter))) { if (!prop_dictionary_get_cstring_nocopy(obj, "trans-action", &tract)) return errno; - if (strcmp(tract, "install") == 0) + if (strcmp(tract, "install") == 0) { + trans->inst_pkgcnt++; trans_inst = true; - else if (strcmp(tract, "update") == 0) + } else if (strcmp(tract, "update") == 0) { + trans->up_pkgcnt++; trans_up = true; - else if (strcmp(tract, "configure") == 0) + } else if (strcmp(tract, "configure") == 0) { + trans->cf_pkgcnt++; trans_conf = true; + } } - prop_object_iterator_reset(iter); + prop_object_iterator_reset(trans->iter); /* * Show the list of packages that will be installed. */ if (trans_inst) { printf("The following packages will be installed:\n\n"); - show_package_list(iter, "install"); + show_package_list(trans->iter, "install"); printf("\n\n"); } if (trans_up) { printf("The following packages will be updated:\n\n"); - show_package_list(iter, "update"); + show_package_list(trans->iter, "update"); printf("\n\n"); } if (trans_conf) { printf("The following packages will be configured:\n\n"); - show_package_list(iter, "configure"); + show_package_list(trans->iter, "configure"); printf("\n\n"); } /* * Show total download/installed size for all required packages. */ + if (!prop_dictionary_get_uint64(trans->dict, + "total-download-size", &dlsize)) + return errno; + if (!prop_dictionary_get_uint64(trans->dict, + "total-installed-size", &instsize)) + return errno; if (xbps_humanize_number(size, 5, (int64_t)dlsize, "", HN_AUTOSCALE, HN_B|HN_DECIMAL|HN_NOSPACE) == -1) { fprintf(stderr, "xbps-bin: error: humanize_number returns " @@ -334,14 +329,14 @@ pkgname_from_pkgmatch(const char *pkg) * * XXX REALLY FIX THIS CRAP! I haven't found much easier ways... */ - if ((version = xbps_get_pkgdep_version(pkg))) { + if ((version = xbps_get_pkgpattern_version(pkg))) { while (*version) { if (!isdigit((unsigned char)*version)) { version++; continue; } if (xbps_cmpver("0", version) <= 0) - return xbps_get_pkgdep_name(pkg); + return xbps_get_pkgpattern_name(pkg); } } if ((version = xbps_get_pkg_version(pkg))) { @@ -394,7 +389,7 @@ xbps_install_new_pkg(const char *pkg) /* * Find a package in a repository and prepare for installation. */ - if ((pkgd = xbps_find_pkg_installed_from_plist(pkgname))) { + if ((pkgd = xbps_find_pkg_dict_installed(pkgname, false))) { printf("Package '%s' is already installed.\n", pkgname); prop_object_release(pkgd); if (pkgmatch) @@ -424,7 +419,7 @@ xbps_update_pkg(const char *pkgname) prop_dictionary_t pkgd; int rv = 0; - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); printf("Finding new '%s' package...\n", pkgname); if (pkgd) { rv = xbps_repository_update_pkg(pkgname, pkgd); @@ -445,70 +440,12 @@ xbps_update_pkg(const char *pkgname) return rv; } -int -xbps_exec_transaction(bool yes) -{ - struct transaction *trans; - prop_array_t array; - int rv = 0; - - trans = calloc(1, sizeof(struct transaction)); - if (trans == NULL) - goto out; - - trans->dict = xbps_repository_get_transaction_dict(); - if (trans->dict == NULL) - goto out; - - /* - * Bail out if there are unresolved deps. - */ - array = prop_dictionary_get(trans->dict, "missing_deps"); - if (prop_array_count(array) > 0) { - show_missing_deps(trans->dict); - goto out; - } - - DPRINTF(("%s", prop_dictionary_externalize(trans->dict))); - - /* - * Sort the package transaction dictionary. - */ - if ((rv = xbps_sort_pkg_deps(trans->dict)) != 0) { - fprintf(stderr, "xbps-bin: error while sorting " - "packages: %s\n", strerror(rv)); - goto out; - } - - /* - * It's time to run the transaction! - */ - trans->iter = xbps_get_array_iter_from_dict(trans->dict, "packages"); - if (trans->iter == NULL) { - fprintf(stderr, "xbps-bin: error allocating array mem! (%s)\n", - strerror(errno)); - goto out; - } - - trans->yes = yes; - rv = exec_transaction(trans); - -out: - if (trans->iter) - prop_object_iterator_release(trans->iter); - if (trans->dict) - prop_object_release(trans->dict); - if (trans) - free(trans); - return rv; -} - static int replace_packages(prop_object_iterator_t iter, const char *pkgver) { prop_dictionary_t instd; prop_object_t obj; - const char *reppkgn, *version; + const char *pattern, *reppkgn, *reppkgver, *version; int rv = 0; /* @@ -516,16 +453,23 @@ replace_packages(prop_object_iterator_t iter, const char *pkgver) * them before upgrading or installing new one. */ while ((obj = prop_object_iterator_next(iter))) { - reppkgn = prop_string_cstring_nocopy(obj); - if (reppkgn == NULL) + pattern = prop_string_cstring_nocopy(obj); + if (pattern == NULL) return errno; - instd = xbps_find_pkg_installed_from_plist(reppkgn); + /* + * If pattern matches an installed package, replace it. + */ + instd = xbps_find_pkg_dict_installed(pattern, true); if (instd == NULL) continue; - printf("Replacing package '%s' with '%s' ...\n", - reppkgn, pkgver); + prop_dictionary_get_cstring_nocopy(instd, "pkgname", &reppkgn); + prop_dictionary_get_cstring_nocopy(instd, "pkgver", &reppkgver); + printf("Replacing package '%s' with '%s' " + "(matched by '%s')...\n", reppkgver, pkgver, pattern); + prop_object_release(instd); + version = xbps_get_pkg_version(pkgver); if ((rv = xbps_remove_pkg(reppkgn, version, false)) != 0) { fprintf(stderr, "xbps-bin: couldn't remove %s (%s)\n", @@ -562,8 +506,7 @@ exec_transaction(struct transaction *trans) /* * Show download/installed size for the transaction. */ - rv = show_transaction_sizes(trans->iter); - if (rv != 0) + if ((rv = show_transaction_sizes(trans)) != 0) return rv; /* @@ -580,12 +523,14 @@ exec_transaction(struct transaction *trans) * Download binary packages (if they come from a remote repository) * and check its SHA256 hash. */ + printf("[1/3] Downloading/integrity check\n\n"); if ((rv = download_package_list(trans->iter)) != 0) return rv; /* * Iterate over the transaction dictionary. */ + printf("\n[2/3] Unpacking\n\n"); while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { if (!prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) @@ -631,7 +576,7 @@ exec_transaction(struct transaction *trans) } if (strcmp(tract, "update") == 0) { - instpkgd = xbps_find_pkg_installed_from_plist(pkgname); + instpkgd = xbps_find_pkg_dict_installed(pkgname, false); if (instpkgd == NULL) { fprintf(stderr, "xbps-bin: error: unable to " "find %s installed dict!\n", pkgname); @@ -648,27 +593,24 @@ exec_transaction(struct transaction *trans) /* * If package is marked as 'essential' remove old * requiredby entries and overwrite pkg files; otherwise - * remove old package and install new one. + * remove old package and install new one. This + * is all handled internally in xbps_remove_pkg() + * and xbps_unpack_binary_pkg(). */ - if (essential) { - rv = xbps_requiredby_pkg_remove(pkgname); - if (rv != 0) { - fprintf(stderr, "xbps-bin: error: " - "couldn't remove reqby" - " entries for %s-%s (%s)\n", - pkgname, instver, strerror(rv)); - return rv; - } - } else { - printf("Removing %s-%s ...\n", - pkgname, instver); - rv = xbps_remove_pkg(pkgname, version, true); - if (rv != 0) { - fprintf(stderr, "xbps-bin: error " - "removing %s-%s (%s)\n", - pkgname, instver, strerror(rv)); - return rv; - } + if (essential) + printf("Replacing %s-%s with %s-%s ...\n", + pkgname, instver, pkgname, version); + else + printf("Removing %s-%s before installing new " + "version ...\n", pkgname, instver); + + rv = xbps_remove_pkg(pkgname, version, true); + if (rv != 0) { + fprintf(stderr, "xbps-bin: error " + "%s %s-%s (%s)\n", essential ? + "replacing" : "removing", pkgname, + instver, strerror(rv)); + return rv; } } /* @@ -694,6 +636,7 @@ exec_transaction(struct transaction *trans) /* * Configure all unpacked packages. */ + printf("\n[3/3] Configuring\n\n"); while ((obj = prop_object_iterator_next(trans->iter)) != NULL) { if (!prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname)) @@ -713,7 +656,60 @@ exec_transaction(struct transaction *trans) "package %s (%s)\n", pkgname, strerror(rv)); return rv; } + trans->cf_pkgcnt++; } + printf("\nxbps-bin: %zu installed, %zu updated, " + "%zu configured.\n", trans->inst_pkgcnt, trans->up_pkgcnt, + trans->cf_pkgcnt); return 0; } + +int +xbps_exec_transaction(bool yes) +{ + struct transaction *trans; + prop_array_t array; + int rv = 0; + + trans = calloc(1, sizeof(struct transaction)); + if (trans == NULL) + goto out; + + trans->dict = xbps_repository_get_transaction_dict(); + if (trans->dict == NULL) + goto out; + + /* + * Bail out if there are unresolved deps. + */ + array = prop_dictionary_get(trans->dict, "missing_deps"); + if (prop_array_count(array) > 0) { + show_missing_deps(trans->dict); + goto out; + } + + DPRINTF(("%s", prop_dictionary_externalize(trans->dict))); + + /* + * It's time to run the transaction! + */ + trans->iter = xbps_get_array_iter_from_dict(trans->dict, "packages"); + if (trans->iter == NULL) { + fprintf(stderr, "xbps-bin: error allocating array mem! (%s)\n", + strerror(errno)); + goto out; + } + + trans->yes = yes; + rv = exec_transaction(trans); + +out: + if (trans->iter) + prop_object_iterator_release(trans->iter); + if (trans->dict) + prop_object_release(trans->dict); + if (trans) + free(trans); + return rv; +} diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index aecf7063..b810718e 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -34,10 +34,6 @@ #include "defs.h" #include "../xbps-repo/defs.h" -static void cleanup(int); -static void usage(void); -static int list_pkgs_in_dict(prop_object_t, void *, bool *); - static void usage(void) { @@ -109,6 +105,14 @@ list_manual_packages(prop_object_t obj, void *arg, bool *loop_done) return 0; } + +static void +cleanup(int signum) +{ + xbps_regpkgs_dictionary_release(); + exit(signum); +} + int main(int argc, char **argv) { @@ -332,10 +336,3 @@ main(int argc, char **argv) out: cleanup(rv); } - -static void -cleanup(int signum) -{ - xbps_regpkgs_dictionary_release(); - exit(signum); -} diff --git a/bin/xbps-bin/remove.c b/bin/xbps-bin/remove.c index d19c87b5..bf5dea0f 100644 --- a/bin/xbps-bin/remove.c +++ b/bin/xbps-bin/remove.c @@ -130,7 +130,7 @@ xbps_remove_installed_pkgs(int argc, char **argv, bool force) * First check if package is required by other packages. */ for (i = 1; i < argc; i++) { - dict = xbps_find_pkg_installed_from_plist(argv[i]); + dict = xbps_find_pkg_dict_installed(argv[i], false); if (dict == NULL) { printf("Package %s is not installed.\n", argv[i]); continue; @@ -155,7 +155,7 @@ xbps_remove_installed_pkgs(int argc, char **argv, bool force) */ printf("The following packages will be removed:\n\n"); for (i = 1; i < argc; i++) { - dict = xbps_find_pkg_installed_from_plist(argv[i]); + dict = xbps_find_pkg_dict_installed(argv[i], false); if (dict == NULL) continue; prop_dictionary_get_cstring_nocopy(dict, "version", &version); @@ -180,7 +180,7 @@ xbps_remove_installed_pkgs(int argc, char **argv, bool force) printf("Forcing removal!\n"); for (i = 1; i < argc; i++) { - dict = xbps_find_pkg_installed_from_plist(argv[i]); + dict = xbps_find_pkg_dict_installed(argv[i], false); if (dict == NULL) continue; prop_dictionary_get_cstring_nocopy(dict, "version", &version); diff --git a/bin/xbps-bin/show-deps.c b/bin/xbps-bin/show-deps.c index fe8cbf10..d6ff2f33 100644 --- a/bin/xbps-bin/show-deps.c +++ b/bin/xbps-bin/show-deps.c @@ -42,7 +42,7 @@ xbps_show_pkg_deps(const char *pkgname) assert(pkgname != NULL); - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) { printf("Package %s is not installed.\n", pkgname); return 0; @@ -79,7 +79,7 @@ xbps_show_pkg_reverse_deps(const char *pkgname) prop_dictionary_t pkgd; int rv = 0; - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) { printf("Package %s is not installed.\n", pkgname); return 0; diff --git a/bin/xbps-repo/main.c b/bin/xbps-repo/main.c index f3160683..0f14ec2a 100644 --- a/bin/xbps-repo/main.c +++ b/bin/xbps-repo/main.c @@ -34,8 +34,6 @@ #include #include "defs.h" -static void usage(void); - static void usage(void) { @@ -122,7 +120,7 @@ main(int argc, char **argv) if (argc != 1) usage(); - SIMPLEQ_FOREACH(rpool, &repopool_queue, chain) + SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) printf("%s\n", rpool->rp_uri); } else if ((strcasecmp(argv[0], "rm") == 0) || @@ -141,7 +139,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - SIMPLEQ_FOREACH(rpool, &repopool_queue, chain) { + 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]); diff --git a/bin/xbps-repo/repository.c b/bin/xbps-repo/repository.c index 1d16ad96..a6c66cdd 100644 --- a/bin/xbps-repo/repository.c +++ b/bin/xbps-repo/repository.c @@ -222,7 +222,7 @@ show_pkg_info_from_repolist(const char *pkgname) prop_dictionary_t repo_pkgd, pkg_propsd; int rv = 0; - SIMPLEQ_FOREACH(rp, &repopool_queue, chain) { + SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) { char *url = NULL; repo_pkgd = xbps_find_pkg_in_dict_by_name(rp->rp_repod, "packages", pkgname); @@ -264,7 +264,7 @@ show_pkg_deps_from_repolist(const char *pkgname) const char *ver; int rv = 0; - SIMPLEQ_FOREACH(rd, &repopool_queue, chain) { + SIMPLEQ_FOREACH(rd, &rp_queue, rp_entries) { pkgd = xbps_find_pkg_in_dict_by_name(rd->rp_repod, "packages", pkgname); if (pkgd == NULL) { @@ -294,7 +294,7 @@ repository_sync(void) char *plist; int rv = 0; - SIMPLEQ_FOREACH(rp, &repopool_queue, chain) { + SIMPLEQ_FOREACH(rp, &rp_queue, rp_entries) { if (!xbps_check_is_repo_string_remote(rp->rp_uri)) continue; diff --git a/bin/xbps-repo/util.c b/bin/xbps-repo/util.c index ca900ded..411f476b 100644 --- a/bin/xbps-repo/util.c +++ b/bin/xbps-repo/util.c @@ -191,7 +191,7 @@ show_pkg_namedesc(prop_object_t obj, void *arg, bool *loop_done) prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); prop_dictionary_get_cstring_nocopy(obj, "short_desc", &desc); - if (xbps_pkgdep_match(pkgver, pattern) == 1) + if (xbps_pkgpattern_match(pkgver, pattern) == 1) printf(" %s - %s\n", pkgver, desc); else if (strcmp(pkgname, pattern) == 0) printf(" %s - %s\n", pkgver, desc); diff --git a/bin/xbps-uhelper/main.c b/bin/xbps-uhelper/main.c index 4a18417a..6dc2f835 100644 --- a/bin/xbps-uhelper/main.c +++ b/bin/xbps-uhelper/main.c @@ -273,7 +273,7 @@ main(int argc, char **argv) if (argc != 2) usage(); - pkgname = xbps_get_pkgdep_name(argv[1]); + pkgname = xbps_get_pkgpattern_name(argv[1]); if (pkgname == NULL) exit(EXIT_FAILURE); @@ -285,7 +285,7 @@ main(int argc, char **argv) if (argc != 3) usage(); - exit(xbps_pkgdep_match(argv[1], argv[2])); + exit(xbps_pkgpattern_match(argv[1], argv[2])); } else if (strcasecmp(argv[0], "cmpver") == 0) { /* Compare two version strings, installed vs required */ diff --git a/include/sha256.h b/include/sha256.h index c93b8633..24926096 100644 --- a/include/sha256.h +++ b/include/sha256.h @@ -44,8 +44,8 @@ typedef struct _SHA256_CTX { uint8_t buffer[SHA256_BLOCK_LENGTH]; } SHA256_CTX; -int XBPS_SHA256_Init(SHA256_CTX *); -int XBPS_SHA256_Update(SHA256_CTX *, const uint8_t *, size_t); -char *XBPS_SHA256_End(SHA256_CTX *, uint8_t *); +int HIDDEN XBPS_SHA256_Init(SHA256_CTX *); +int HIDDEN XBPS_SHA256_Update(SHA256_CTX *, const uint8_t *, size_t); +char HIDDEN *XBPS_SHA256_End(SHA256_CTX *, uint8_t *); #endif /* !_SHA2_DIGEST_H_ */ diff --git a/include/xbps_api.h b/include/xbps_api.h index 1c4de6b9..f5f04a06 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -21,6 +21,7 @@ * 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. + *- */ #ifndef _XBPS_API_H_ @@ -30,43 +31,140 @@ #include #include #include +/** + * @cond + */ #ifndef DEBUG # define NDEBUG #endif #include - +/** + * @endcond + */ #include #include #include -/* Current release version */ -#define XBPS_RELVER "20100118" +__BEGIN_DECLS -/* Default root PATH for xbps to store metadata info. */ +/** + * @mainpage The X Binary Package System Library API + * @section intro_sec Introduction + * + * XBPS is a new binary package system designed and implemented from + * scratch, by Juan Romero Pardines. This document describes + * the API used by the XBPS Library, that is the base to implement + * a package manager frontend, such as is implemented in the xbps-bin(8) + * and xbps-repo(8) command line interfaces. + * + * XBPS uses extensively NetBSD's proplib, a library that provides an + * abstract interface for creating and manipulating property lists. + * Property lists have object types for boolean values, opaque data, numbers, + * and strings. Structure is provided by the array and dictionary collection + * types. Property lists can be passed across protection boundaries by + * translating them to an external representation. This external representation + * is an XML document whose format is described by the following DTD: + * + * http://www.apple.com/DTDs/PropertyList-1.0.dtd + * + * NetBSD's proplib has been used because it's fast, extensible, and easy + * to use. These are the three facts I mentioned: + * + *
    + *
  • Fast because proplib uses an ultra optimized + * red-black tree implementation to store and find all its objects, + * the same implementation has been used in commercial projects by + * Apple Inc.
  • + * + *
  • Extensible because you don't have to worry about + * ABI problems with its objects, arrays and dictionaries can be extended + * without such problems.
  • + * + *
  • Easy to use (and learn) because it has a superb documentation + * available in the form of manual pages.
  • + *
+ * + * Not to mention that its arrays and dictionaries can be externalized to + * files (known as plists) and always are written atomically. You + * have the whole file or don't have it at all. + * + * @file include/xbps_api.h + * @brief XBPS Library API header + * + * This header documents the full API for the XBPS Library. + */ + +/** + * @def XBPS_RELVER + * Current library release date. + */ +#define XBPS_RELVER "20100121" + +/** + * @def XBPS_META_PATH + * Default root PATH store metadata info. + */ #define XBPS_META_PATH "/var/db/xbps" -/* Default cache PATH for xbps to store downloaded binpkgs. */ +/** + * @def XBPS_CACHE_PATH + * Default cache PATH to store downloaded binpkgs. + */ #define XBPS_CACHE_PATH "/var/cache/xbps" -/* Filename for the repositories plist file. */ +/** + * @def XBPS_REPOLIST + * Filename for the repositories plist file. + */ #define XBPS_REPOLIST "repositories.plist" -/* Filename of the package index plist for a repository. */ -#define XBPS_PKGINDEX "pkg-index.plist" - -/* Filename of the packages register. */ +/** + * @def XBPS_REGPKGDB + * Filename of the packages register database. + */ #define XBPS_REGPKGDB "regpkgdb.plist" -/* Package metadata files. */ +/** + * @def XBPS_PKGPROPS + * Package metadata properties file. + */ #define XBPS_PKGPROPS "props.plist" + +/** + * @def XBPS_PKGFILES + * Package metadata files properties file. + */ #define XBPS_PKGFILES "files.plist" -/* Current version of the package index format. */ +/** + * @def XBPS_PKGINDEX + * Filename of the package index plist for a repository. + */ +#define XBPS_PKGINDEX "pkg-index.plist" + +/** + * @def XBPS_PKGINDEX_VERSION + * Current version of the package index format. + */ #define XBPS_PKGINDEX_VERSION "1.1" +/** + * @def XBPS_FLAG_VERBOSE + * Verbose flag used in xbps_unpack_binary_pkg() (for now). + * Must be set through the xbps_set_flags() function. + */ #define XBPS_FLAG_VERBOSE 0x00000001 + +/** + * @def XBPS_FLAG_FORCE + * Force flag used in xbps_configure_pkg() (for now). + * Must be set through the xbps_set_flags() function. + */ #define XBPS_FLAG_FORCE 0x00000002 +/** + * @cond + */ #define ARCHIVE_READ_BLOCKSIZE 10240 #define EXTRACT_FLAGS ARCHIVE_EXTRACT_SECURE_NODOTDOT | \ @@ -86,36 +184,144 @@ #define DPRINTF(x) #endif +/* + * By default all public functions have default visibility, unless + * gcc >= 4.x and the HIDDEN definition is used. + */ #if __GNUC__ >= 4 -#define SYMEXPORT __attribute__ ((visibility("default"))) +#define HIDDEN __attribute__ ((visibility("hidden"))) #else -#define SYMEXPORT +#define HIDDEN #endif +/** + * @endcond + */ -__BEGIN_DECLS +/** + * @private + * From lib/config_files.c + */ +int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t, + struct archive_entry *, + const char *, + int *, + bool *); -/* From lib/config_files.c */ -int xbps_config_file_from_archive_entry(prop_dictionary_t, - struct archive_entry *, - const char *, - int *, - bool *); +/** + * @ingroup 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, or an appropiate errno value otherwise. + */ +int xbps_configure_pkg(const char *pkgname, + const char *version, + bool check_state, + bool update); -/* From lib/configure.c */ -int SYMEXPORT xbps_configure_pkg(const char *, const char *, bool, bool); -int SYMEXPORT xbps_configure_all_pkgs(void); +/** + * @ingroup configure + * + * Configure (or force reconfiguration of) all packages. + * + * @return 0 on success, or an appropiate errno value otherwise. + */ +int xbps_configure_all_pkgs(void); -/* from lib/cmpver.c */ -int SYMEXPORT xbps_cmpver(const char *, const char *); +/** + * @ingroup vermatch + * + * Compares package version strings. + * + * The package version is defined by: + * ${VERSION}[_${PKGREVISION}][-${EPOCH}]. + * + * ${EPOCH} supersedes ${VERSION} supersedes ${PKGREVISION}. + * + * @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); -/* From lib/download.c */ -int SYMEXPORT xbps_fetch_file(const char *, const char *, bool, const char *); -const char SYMEXPORT *xbps_fetch_error_string(void); +/** + * @ingroup download + * + * Download a file from a remote URL. + * + * @param[in] uri Remote URI string. + * @param[in] outputdir Directory string to store downloaded file. + * @param[in] refetch If true and local/remote size/mtime do not match, + * fetch the file from scratch. + * @param[in] flags Flags passed to libfetch's fetchXget(). + * + * @return -1 on error, 0 if not downloaded (because local/remote size/mtime + * do not match) and 1 if downloaded successfully. + **/ +int xbps_fetch_file(const char *uri, + const char *outputdir, + bool refetch, + const char *flags); -/* From lib/fexec.c */ -int SYMEXPORT xbps_file_exec(const char *, ...); -int SYMEXPORT xbps_file_exec_skipempty(const char *, ...); -int SYMEXPORT xbps_file_chdir_exec(const char *, const char *, ...); +/** + * @ingroup download + * + * Returns last error string reported by xbps_fetch_file(). + * + * @return A string with the appropiate error message. + */ +const char *xbps_fetch_error_string(void); + +/** + * @ingroup 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, ...); + +/** + * @ingroup 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, 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, ...); + +/** + * @ingroup fexec + * + * 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 @@ -125,121 +331,652 @@ int SYMEXPORT xbps_file_chdir_exec(const char *, const char *, ...); #define HN_GETSCALE 0x10 #define HN_AUTOSCALE 0x20 -int SYMEXPORT xbps_humanize_number(char *, size_t, int64_t, const char *, - int, int); +int xbps_humanize_number(char *, size_t, int64_t, const char *, int, int); -/* From lib/mkpath.c */ -int SYMEXPORT xbps_mkpath(char *, mode_t); +/** + * @ingroup dircreate + * + * Creates a directory (and required components if necessary). + * + * @param[in] path Path for final directory. + * @param[in] mode Mode for final directory (0755 if not specified). + * + * @return 0 on success, -1 on error and errno set appropiately. + */ +int xbps_mkpath(char *path, mode_t mode); -/* From lib/orphans.c */ -prop_array_t SYMEXPORT xbps_find_orphan_packages(void); +/** + * @ingroup pkg_orphans + * + * 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. + */ +prop_array_t xbps_find_orphan_packages(void); -/* From lib/pkgmatch.c */ -int SYMEXPORT xbps_pkgdep_match(const char *, char *); +/** + * @ingroup vermatch + * + * Package pattern matching. + * + * @param[in] instpkg Package/version string of an installed package. + * @param[in] pattern Pattern required for \a instpkg to match. + * + * @return 1 if \a instpkg is matched against \a pattern, 0 if no match. + */ +int xbps_pkgpattern_match(const char *instpkg, char *pattern); -/* From lib/plist.c */ -bool SYMEXPORT xbps_add_obj_to_dict(prop_dictionary_t, prop_object_t, - const char *); -bool SYMEXPORT xbps_add_obj_to_array(prop_array_t, prop_object_t); +/** + * @ingroup plist + * + * Adds a proplib object into a proplib dictionary with specified key. + * + * @param[in] dict Proplib dictionary to insert the object to. + * @param[in] obj Proplib object to be inserted. + * @param[in] key Key associated with \a obj. + * + * @return true on success, false otherwise and errno set appropiately. + */ +bool xbps_add_obj_to_dict(prop_dictionary_t dict, + prop_object_t obj, + const char *key); -int SYMEXPORT xbps_callback_array_iter_in_dict(prop_dictionary_t, - const char *, +/** + * @ingroup plist + * + * Adds a proplib object into a proplib array. + * + * @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. + */ +bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj); + +/** + * @ingroup plist + * + * Executes a function callback into the array associated with key \a key, + * contained in a proplib dictionary. + * + * @param[in] dict Proplib dictionary where the array resides. + * @param[in] key Key associated with array. + * @param[in] fn Function callback to run on every + * object in the array. While running the function callback, the third + * parameter (a pointer to a boolean) can be set to true to stop + * immediately the loop. + * @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. + */ +int xbps_callback_array_iter_in_dict(prop_dictionary_t dict, + const char *key, int (*fn)(prop_object_t, void *, bool *), - void *); -int SYMEXPORT xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t, - const char *, + void *arg); + +/** + * @ingroup plist + * + * Executes a function callback (in reverse order) into the array + * associated with key \a key, contained in a proplib dictionary. + * + * @param[in] dict Proplib dictionary where the array resides. + * @param[in] key Key associated with array. + * @param[in] fn Function callback to run on every + * object in the array. While running the function callback, the third + * parameter (a pointer to a boolean) can be set to true to stop + * immediately the loop. + * @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. + */ +int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, + const char *key, int (*fn)(prop_object_t, void *, bool *), - void *); + void *arg); -prop_dictionary_t SYMEXPORT - xbps_find_pkg_in_dict_by_name(prop_dictionary_t, - const char *, const char *); -prop_dictionary_t SYMEXPORT - xbps_find_pkg_in_dict_by_pkgmatch(prop_dictionary_t, - const char *, const char *); -prop_dictionary_t SYMEXPORT xbps_find_pkg_from_plist(const char *, - const char *); -prop_dictionary_t SYMEXPORT - xbps_find_pkg_installed_from_plist(const char *); -bool SYMEXPORT xbps_find_string_in_array(prop_array_t, const char *); +/** + * @ingroup plist + * + * Finds the proplib's dictionary associated with a package, by looking + * it via its name in a proplib dictionary. + * + * @param[in] dict Proplib dictionary to look for the package dictionary. + * @param[in] key Key associated with the array that stores package's dictionary. + * @param[in] pkgname Package name to look for. + * + * @return The package's proplib dictionary on success, NULL otherwise and + * errno is set appropiately. + */ +prop_dictionary_t xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, + const char *key, + const char *pkgname); -prop_object_iterator_t SYMEXPORT - xbps_get_array_iter_from_dict(prop_dictionary_t, const char *); +/** + * @ingroup plist + * + * Finds the proplib's dictionary associated with a package, by looking + * at it via a package pattern in a proplib dictionary. + * + * @param[in] dict Proplib dictionary to look for the package dictionary. + * @param[in] key Key associated with the array storing the package's dictionary. + * @param[in] pattern Package pattern to match. + * + * @return The package's proplib dictionary on success, NULL otherwise + * and errno is set appropiately. + */ +prop_dictionary_t xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict, + const char *key, + const char *pattern); -prop_dictionary_t SYMEXPORT - xbps_read_dict_from_archive_entry(struct archive *, - struct archive_entry *); +/** + * @ingroup plist + * + * Finds the package's proplib dictionary by looking at it in + * a plist file. + * + * @param[in] plist Path to a plist file. + * @param[in] pkgname Package name to look for. + * + * @return The package's proplib dictionary on success, NULL otherwise and + * errno is set appropiately. + */ +prop_dictionary_t xbps_find_pkg_from_plist(const char *plist, + const char *pkgname); -int SYMEXPORT xbps_remove_pkg_dict_from_file(const char *, const char *); -int SYMEXPORT - xbps_remove_pkg_from_dict(prop_dictionary_t, const char *, - const char *); -int SYMEXPORT xbps_remove_string_from_array(prop_array_t, const char *); +/** + * @ingroup plist + * + * Finds a package's dictionary searching in the registered packages + * database by using a package name or a package pattern. + * + * @param[in] str Package name or package pattern. + * @param[in] bypattern Set it to true to find the package dictionary + * by using a package pattern. If false, \a str is assumed to be a package name. + * + * @return The package's dictionary on success, NULL otherwise and + * errno is set appropiately. + */ +prop_dictionary_t xbps_find_pkg_dict_installed(const char *str, + bool bypattern); -/* From lib/purge.c */ -int SYMEXPORT xbps_purge_pkg(const char *, bool); -int SYMEXPORT xbps_purge_all_pkgs(void); +/** + * @ingroup plist + * + * Finds a string matching an object in a proplib array. + * + * @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. + */ +bool xbps_find_string_in_array(prop_array_t array, const char *val); -/* From lib/register.c */ -int SYMEXPORT xbps_register_pkg(prop_dictionary_t, bool); -int SYMEXPORT xbps_unregister_pkg(const char *); +/** + * @ingroup plist + * + * Gets a proplib object iterator associated with an array, contained + * in a proplib dictionary matching a key. + * + * @param[in] dict Proplib dictionary where to look for the array. + * @param[in] key Key associated with the array. + * + * @return A proplib object iterator on success, NULL otherwise and + * errno is set appropiately. + */ +prop_object_iterator_t xbps_get_array_iter_from_dict(prop_dictionary_t dict, + const char *key); -/* From lib/regpkgs_dictionary.c */ -prop_dictionary_t SYMEXPORT xbps_regpkgs_dictionary_init(void); -void SYMEXPORT xbps_regpkgs_dictionary_release(void); +/** + * @ingroup plist + * + * Finds a proplib dictionary in an archive, matching a specific + * entry on it. + * + * @param[in] ar Pointer to an archive object, as returned by libarchive. + * @param[in] entry Pointer to an archive entry object, as returned by libarchive. + * + * @return The proplib dictionary associated with entry, NULL otherwise + * and errno is set appropiately. + */ +prop_dictionary_t xbps_read_dict_from_archive_entry(struct archive *ar, + struct archive_entry *entry); -/* From lib/remove.c */ -int SYMEXPORT xbps_remove_pkg(const char *, const char *, bool); -int SYMEXPORT xbps_remove_pkg_files(prop_dictionary_t, const char *); +/** + * @ingroup plist + * + * Removes the package's proplib dictionary matching \a pkgname + * in a plist file. + * + * @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. + */ +int xbps_remove_pkg_dict_from_file(const char *pkgname, const char *plist); -/* From lib/remove_obsoletes.c */ -int xbps_remove_obsoletes(prop_dictionary_t, prop_dictionary_t); +/** + * @ingroup plist + * + * Removes the package's proplib dictionary matching \a pkgname, + * in an array with key \a key stored in a proplib dictionary. + * + * @param[in] dict Proplib dictionary storing the proplib array. + * @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. + */ +int xbps_remove_pkg_from_dict(prop_dictionary_t dict, + const char *key, + const char *pkgname); -/* From lib/repository.c */ -int SYMEXPORT xbps_repository_register(const char *); -int SYMEXPORT xbps_repository_unregister(const char *); +/** + * @ingroup plist + * + * Removes a string from a proplib's array. + * + * @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. + */ +int xbps_remove_string_from_array(prop_array_t array, const char *str); -/* From lib/repository_finddeps.c */ -int SYMEXPORT xbps_repository_find_pkg_deps(prop_dictionary_t, - prop_dictionary_t); +/** + * @ingroup purge + * + * Purge an installed package. + * + * @param[in] pkgname Package name to match. + * @param[in] check_state Set it to true to check that package + * is in config-files state. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_purge_pkg(const char *pkgname, bool check_state); -/* From lib/repository_findpkg.c */ -int SYMEXPORT xbps_repository_install_pkg(const char *, bool); -int SYMEXPORT xbps_repository_update_pkg(const char *, prop_dictionary_t); -int SYMEXPORT xbps_repository_update_allpkgs(void); -prop_dictionary_t SYMEXPORT xbps_repository_get_transaction_dict(void); +/** + * @ingroup purge + * + * Purge all installed packages. Packages that aren't in + * config-files state will be ignored. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_purge_all_pkgs(void); -/* From lib/repository_plist.c */ -char SYMEXPORT *xbps_repository_get_path_from_pkg_dict(prop_dictionary_t, - const char *); -prop_dictionary_t SYMEXPORT - xbps_repository_get_pkg_plist_dict(const char *, const char *); -prop_dictionary_t SYMEXPORT - xbps_repository_get_pkg_plist_dict_from_url(const char *, const char *); +/** + * @ingroup pkg_register + * + * Register a package into the installed packages database. + * + * @param[in] pkgrd Package proplib dictionary returned by a transaction. + * @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. + */ +int xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic); -/* From lib/repository_pool.c */ +/** + * @ingroup pkg_register + * + * Unregister a package from the package database. + * + * @param[in] pkgname Package name to match. + * + * @return 0 on success, an errno value otherwise. + */ +int xbps_unregister_pkg(const char *pkgname); + +/** + * @ingroup regpkgdb + * + * Initialize resources used by the installed packages database. + * + * @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() + * once that you don't this data to release resources if possible. + * + * @return A proplib dictionary with all packages registered currently + * on success, NULL otherwise and errno is set appropiately. + */ +prop_dictionary_t xbps_regpkgs_dictionary_init(void); + +/** + * @ingroup regpkgdb + * + * Release resources used by the installed packages database. + * + * @note This function is reference counted, if the database + * is in use by other callers it won't be released. + */ +void xbps_regpkgs_dictionary_release(void); + +/** + * @ingroup pkg_remove + * + * Remove an installed package. + * + * @param[in] pkgname Package name to match. + * @param[in] version Package version associated. + * @param[in] update If true, and depending if \a pkgname is an + * essential package, some steps will be skipped. See in the + * detailed description section for more information. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_remove_pkg(const char *pkgname, const char *version, bool update); + +/** + * @ingroup pkg_remove + * + * Remove files defined in a proplib array as specified by \a key + * of an installed package. + * + * @param[in] dict Proplib dictionary internalized from package's + * "files.plist" metadata plist file. + * @param[in] key Key where the object files reside on, valid values are: + * "files", "dirs", "links" and "conf_files". + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key); + +/** + * @private + * From lib/remove_obsoletes.c + */ +int HIDDEN xbps_remove_obsoletes(prop_dictionary_t, prop_dictionary_t); + +/** + * @ingroup repo_register + * + * Registers a repository into the database. + * + * @param[in] uri URI pointing to the repository. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_repository_register(const char *uri); + +/** + * @ingroup repo_register + * + * Unregisters a repository from the database. + * + * @param[in] uri URI pointing to the repository. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_repository_unregister(const char *uri); + +/** + * @private + */ +int HIDDEN xbps_repository_find_pkg_deps(prop_dictionary_t, + prop_dictionary_t); + +/** + * @ingroup repo_pkgs + * + * Finds a package by its name or by a pattern and enqueues it into + * the transaction dictionary for future use. The first repository in + * the queue that matched the requirement 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. + */ +int xbps_repository_install_pkg(const char *pkg, bool bypattern); + +/** + * @ingroup repo_pkgs + * + * Marks a package as "going to be updated" in the transaction dictionary. + * All repositories in the pool will be used, and if a newer version + * 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_installed_from_plist(). + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_repository_update_pkg(const char *pkgname, + prop_dictionary_t instpkg); + +/** + * @ingroup repo_pkgs + * + * 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. + */ +int xbps_repository_update_allpkgs(void); + +/** + * @ingroup repo_pkgs + * + * Returns the transaction proplib dictionary with properties for + * all operations previously done. + * + * @note This function won't return anything useful in the proplib + * dictionary, if either of xbps_repository_install_pkg() or + * xbps_repository_update_pkg() functions are not called previously. + * + * @return The transaction dictionary to install/update/replace + * a package list. + */ +prop_dictionary_t xbps_repository_get_transaction_dict(void); + +/** + * @ingroup repo_plist + * + * Returns a malloc(3)ed URI string pointing to a binary package file, + * either from a local or remote repository. + * + * @note The caller is responsible to free(3) the returned buffer. + * + * @param[in] d Package proplib dictionary as returned by the + * transaction dictionary, aka xbps_repository_get_transaction_dict(). + * @param[in] uri URI pointing to a repository. + * + * @return A string with the full path, NULL otherwise and errno + * set appropiately. + */ +char *xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d, + const char *uri); + +/** + * @ingroup repo_plist + * + * Iterate over the the repository pool and search for a plist file + * in the binary package named 'pkgname'. The plist file will be + * internalized to a proplib dictionary. + * + * The first repository that has it wins and the loop is stopped. + * This will work locally and remotely, thanks to libarchive and + * libfetch! + * + * @param[in] pkgname Package name to match. + * @param[in] plistf Plist file name to match. + * + * @return An internalized proplib dictionary, otherwise NULL and + * errno is set appropiately. + * + * @note if NULL is returned and errno is ENOENT, that means that + * binary package file has been found but the plist file could not + * be found. + */ +prop_dictionary_t xbps_repository_get_pkg_plist_dict(const char *pkgname, + const char *plistf); + +/** + * @ingroup repo_plist + * + * Finds a plist file in a binary package file stored local or + * remotely as specified in the URL. + * + * @param[in] url URL to binary package file. + * @param[in] plistf Plist file name to match. + * + * @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); + +/** + * @ingroup repopool + * + * @struct repository_pool xbps_api.h "xbps_api.h" + * @brief Repository pool 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. + */ struct repository_pool { - SIMPLEQ_ENTRY(repository_pool) chain; + /** + * @var rp_entries + * + * Structure that connects elements in the simple queue. + * For use with the SIMPLEQ macros. + */ + SIMPLEQ_ENTRY(repository_pool) rp_entries; + /** + * @var rp_repod + * + * Proplib dictionary associated with repository. + */ prop_dictionary_t rp_repod; + /** + * @var rp_uri + * + * URI string associated with repository. + */ char *rp_uri; }; -SYMEXPORT SIMPLEQ_HEAD(, repository_pool) repopool_queue; +/** + * @ingroup repopool + * + * @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; -int SYMEXPORT xbps_repository_pool_init(void); -void SYMEXPORT xbps_repository_pool_release(void); +/** + * @ingroup repopool + * + * Initializes the repository pool by creating a global simple queue + * \a rp_queue with all registered repositories in the database. + * + * 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. + * + * @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. + */ +int xbps_repository_pool_init(void); -/* From lib/repository_sync_index.c */ -int SYMEXPORT xbps_repository_sync_pkg_index(const char *); -char SYMEXPORT *xbps_get_remote_repo_string(const char *); +/** + * @ingroup repopool + * + * Releases the repository pool with all registered repositories + * in the database. + * + * @note This function is reference counted, it won't be released until + * its reference counter is 0. + */ +void xbps_repository_pool_release(void); -/* From lib/requiredby.c */ -int SYMEXPORT xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t); -int SYMEXPORT xbps_requiredby_pkg_remove(const char *); +/** + * @ingroup reposync + * + * Syncs the package index file for a remote repository as specified + * by the \a uri argument (if necessary). + * + * @param[in] uri URI to a remote repository. + * + * @return -1 on error (errno is set appropiately), 0 if transfer was + * not necessary (local/remote size/mtime matched) or 1 if + * downloaded successfully. + */ +int xbps_repository_sync_pkg_index(const char *uri); -/* From lib/sortdeps.c */ -int SYMEXPORT xbps_sort_pkg_deps(prop_dictionary_t); +/** + * @ingroup reposync + * + * Returns a malloc(3)ed string with the local directory name for + * the package cache directory pointing to a remote URI repository. + * + * @note The caller is responsible to free(3) the returned buffer, + * @param[in] uri URI to a remote repository. + * + * @return A buffer with the transformed string, NULL otherwise and + * errno is set appropiately. + */ +char *xbps_get_remote_repo_string(const char *uri); -/* From lib/state.c */ +/** + * @private + * From lib/requiredby.c + */ +int HIDDEN xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t); +int HIDDEN xbps_requiredby_pkg_remove(const char *); + +/** + * @private + * From lib/sortdeps.c + */ +int HIDDEN xbps_sort_pkg_deps(prop_dictionary_t); + +/** + * @ingroup pkgstates + * + * @enum pkg_state_t + * + * Integer representing a state on which a package may be. Possible + * values for this are: + * + * XBPS_PKG_STATE_UNPACKED: Package has been unpacked correctly + * but has not been configured due to unknown reasons. + * + * XBPS_PKG_STATE_INSTALLED: Package has been installed successfully. + * + * XBPS_PKG_STATE_BROKEN: not yet used. + * + * XBPS_PKG_STATE_CONFIG_FILES: Package has been removed but not + * yet purged. + * + * XBPS_PKG_STATE_NOT_INSTALLED: Package going to be installed in + * a transaction dictionary but that has not been yet unpacked. + */ typedef enum pkg_state { XBPS_PKG_STATE_UNPACKED = 1, XBPS_PKG_STATE_INSTALLED, @@ -248,38 +985,313 @@ typedef enum pkg_state { XBPS_PKG_STATE_NOT_INSTALLED } pkg_state_t; -int SYMEXPORT xbps_get_pkg_state_installed(const char *, pkg_state_t *); -int SYMEXPORT xbps_get_pkg_state_dictionary(prop_dictionary_t, pkg_state_t *); -int SYMEXPORT xbps_set_pkg_state_installed(const char *, pkg_state_t); -int SYMEXPORT xbps_set_pkg_state_dictionary(prop_dictionary_t, pkg_state_t); +/** + * @ingroup pkgstates + * + * Gets package state from package \a pkgname, and sets its state + * into \a state. + * + * @param[in] pkgname Package name. + * @param[out] state Package state returned. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state); -/* From lib/unpack.c */ -int SYMEXPORT xbps_unpack_binary_pkg(prop_dictionary_t); +/** + * @ingroup pkgstates + * + * Gets package state from a package dictionary \a dict, and sets its + * state into \a state. + * + * @param[in] dict Package dictionary. + * @param[out] state Package state returned. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state); -/* From lib/util.c */ -char SYMEXPORT *xbps_xasprintf(const char *, ...); -char SYMEXPORT *xbps_get_file_hash(const char *); -int SYMEXPORT xbps_check_file_hash(const char *, const char *); -int SYMEXPORT xbps_check_is_installed_pkg(const char *); -bool SYMEXPORT xbps_check_is_installed_pkgname(const char *); -bool SYMEXPORT xbps_check_is_repo_string_remote(const char *); -char SYMEXPORT *xbps_get_binpkg_local_path(prop_dictionary_t, const char *); -char SYMEXPORT *xbps_get_pkg_index_plist(const char *); -char SYMEXPORT *xbps_get_pkg_name(const char *); -char SYMEXPORT *xbps_get_pkgdep_name(const char *); -const char SYMEXPORT *xbps_get_pkg_version(const char *); -const char SYMEXPORT *xbps_get_pkgdep_version(const char *); -const char SYMEXPORT *xbps_get_pkg_revision(const char *); -const char SYMEXPORT *xbps_get_pkgver_from_dict(prop_dictionary_t); -bool SYMEXPORT xbps_pkg_has_rundeps(prop_dictionary_t); -void SYMEXPORT xbps_set_rootdir(const char *); -const char SYMEXPORT *xbps_get_rootdir(void); -void SYMEXPORT xbps_set_cachedir(const char *); -const char SYMEXPORT *xbps_get_cachedir(void); -void SYMEXPORT xbps_set_flags(int); -int SYMEXPORT xbps_get_flags(void); -bool SYMEXPORT xbps_yesno(const char *, ...); -bool SYMEXPORT xbps_noyes(const char *, ...); +/** + * @ingroup pkgstates + * + * Sets package state \a state in package \a pkgname. + * + * @param[in] pkgname Package name. + * @param[in] state Package state to be set. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state); + +/** + * @ingroup pkgstates + * + * Sets package state \a state in package dictionary \a dict. + * + * @param[in] dict Package dictionary. + * @param[in] state Package state to be set. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state); + +/** + * @ingroup unpack + * + * Unpacks a binary package into specified root directory. + * + * @param[in] dict Package proplib dictionary as returned by a transaction. + * + * @return 0 on success, or an errno value otherwise. + */ +int xbps_unpack_binary_pkg(prop_dictionary_t dict); + +/** + * @ingroup util + * + * Returns a string by concatenating its variable argument list + * as specified by the format string \a fmt. + * + * @param[in] fmt Format string, see printf(3). + * @return A pointer to a malloc(3)ed string, NULL otherwise and errno + * is set appropiately. The pointer should be free(3)d when it's + * no longer needed. + */ +char *xbps_xasprintf(const char *fmt, ...); + +/** + * @ingroup util + * + * Returns a string with the sha256 hash for the file specified + * by \a file. + * + * @param[in] file Path to a file. + * @return A pointer to a malloc(3)ed string, NULL otherwise and errno + * is set appropiately. The pointer should be free(3)d when it's no + * longer needed. + */ +char *xbps_get_file_hash(const char *file); + +/** + * @ingroup util + * + * Compares the sha256 hash of the file \a file with the sha256 + * string specified by \a sha256. + * + * @param[in] file Path to a file. + * @param[in] sha256 SHA256 hash to compare. + * + * @return 0 if \a file and \a sha256 have the same hash, ERANGE + * if it differs, or any other errno value on error. + */ +int xbps_check_file_hash(const char *file, const char *sha256); + +/** + * @ingroup util + * + * Checks if a package is currently installed by matching a package + * pattern string. + * + * @param[in] pkg Package pattern used to find the package. + * + * @return -1 on error (errno set appropiately), 0 if package pattern + * didn't match installed package, 1 if \a pkg pattern fully + * matched installed package. + */ +int xbps_check_is_installed_pkg(const char *pkg); + +/** + * @ingroup util + * + * Checks if package \a pkgname is currently installed. + * + * @param[in] pkgname Package name. + * + * @return True if \a pkgname is installed, false otherwise. + */ +bool xbps_check_is_installed_pkgname(const char *pkgname); + +/** + * @ingroup util + * + * Checks if the URI specified by \a uri is remote or local. + * + * @param[in] uri URI string. + * + * @return true if URI is remote, false if local. + */ +bool xbps_check_is_repo_string_remote(const char *uri); + +/** + * @ingroup util + * + * Gets the full path to a binary package file as returned by a + * package transaction dictionary \a pkgd, by looking at the + * repository location \a repoloc. + * + * @param[in] pkgd Package dictionary stored in a transaction dictionary. + * @param[in] repoloc Repository location as returned by the object + * repository in the package dictionary of a transaction + * dictionary. + * + * @return A pointer to a malloc(3)ed string, NULL otherwise and + * errno is set appropiately. The pointer should be free(3)d when it's + * no longer needed. + */ +char *xbps_get_binpkg_local_path(prop_dictionary_t pkgd, const char *repoloc); + +/** + * @ingroup util + * + * Gets the full path to a repository package index plist file, as + * specified by \a uri. + * + * @param[in] uri Repository URI. + * + * @return A pointer to a malloc(3)d string, NULL otherwise and + * errno is set appropiately. The pointer should be free(3)d when it's + * no longer needed. + */ +char *xbps_get_pkg_index_plist(const char *uri); + +/** + * @ingroup util + * + * Gets the name of a package string. Package strings are composed + * by a @/@ pair and separated by the minus + * sign, i.e foo-2.0. + * + * @param[in] pkg Package string. + * + * @return A pointer to a malloc(3)d string, NULL otherwise and + * errno is set appropiately. The pointer should be free(3)d when it's + * no longer needed. + */ +char *xbps_get_pkg_name(const char *pkg); + +/** + * @ingroup util + * + * Gets a the package name of a package pattern string specified by + * the \a pattern argument. + * + * @param[in] pattern A package pattern. Package patterns are composed + * by looking at '><=' to split components, i.e foo>=2.0, + * blah<1.0, blob==2.0, etc. + * + * @return A pointer to a malloc(3)ed string with the package name, + * NULL otherwise and errno is set appropiately. The pointer should be + * free(3)d when it's no longer needed. + */ +char *xbps_get_pkgpattern_name(const char *pattern); + +/** + * @ingroup util + * + * Gets the package version in a package string, i.e foo-2.0. + * + * @param[in] pkg Package string. + * + * @return A string with the version string, NULL if it couldn't + * find the version component. + */ +const char *xbps_get_pkg_version(const char *pkg); + +/** + * @ingroup util + * + * Gets the package version of a package pattern string specified by + * the \a pattern argument. + * + * @param[in] pattern A package pattern. The same rules in + * xbps_get_pkgpattern_name() apply here. + * + * @return A string with the pattern version, NULL otherwise and + * errno is set appropiately. + */ +const char *xbps_get_pkgpattern_version(const char *pattern); + +/** + * @ingroup util + * + * Gets the package version revision in a package string. + * + * @param[in] pkg Package string, i.e foo-2.0_1. + * + * @return A string with the revision number, NULL if it couldn't + * find the revision component. + */ +const char *xbps_get_pkg_revision(const char *pkg); + +/** + * @ingroup util + * + * Checks if a package has run dependencies. + * + * @param[in] dict Package dictionary. + * + * @return True if package has run dependencies, false otherwise. + */ +bool xbps_pkg_has_rundeps(prop_dictionary_t dict); + +/** + * @ingroup util + * + * Sets the global root directory. + * + * @param[in] path Destination directory. + */ +void xbps_set_rootdir(const char *path); + +/** + * @ingroup util + * + * Gets the global root directory. + * + * @return A string with full path to the root directory. + */ +const char *xbps_get_rootdir(void); + +/** + * @ingroup util + * + * Sets globally the cache directory to store downloaded binary + * packages. Any full path without rootdir is valid. + * + * @param[in] cachedir Directory to be set. + */ +void xbps_set_cachedir(const char *cachedir); + +/** + * @ingroup util + * + * Gets the cache directory currently used to store downloaded + * binary packages. + * + * @return The path to a directory. + */ +const char *xbps_get_cachedir(void); + +/** + * @ingroup util + * + * Sets the flag specified in \a flags for internal use. + * + * @param[in] flags Flags to be set globally. + */ +void xbps_set_flags(int flags); + +/** + * @ingroup util + * + * Gets the flags currently set internally. + * + * @return An integer with flags + */ +int xbps_get_flags(void); + +bool xbps_yesno(const char *, ...); +bool xbps_noyes(const char *, ...); __END_DECLS diff --git a/lib/Makefile b/lib/Makefile index e5a918d7..a7e10431 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,6 +12,7 @@ LIBFETCH_OBJS = fetch/common.o fetch/fetch.o fetch/file.o LIBFETCH_OBJS += fetch/ftp.o fetch/http.o LIBFETCH_CPPFLAGS = -DFTP_COMBINE_CWDS -DNETBSD -DINET6 -DWITH_SSL LIBFETCH_CFLAGS = -Wno-unused-macros -Wno-conversion -Wno-stack-protector +LIBFETCH_SHLIBCFLAGS = -fvisibility=hidden LIBFETCH_INCS = fetch/common.h LIBFETCH_GEN = fetch/ftperr.h fetch/httperr.h @@ -37,7 +38,7 @@ fetch/httperr.h: fetch/http.errors $(LIBFETCH_OBJS): %.o: %.c $(LIBFETCH_INCS) $(LIBFETCH_GEN) @echo " [CC]\t\t$@" @$(CC) $(CPPFLAGS) $(LIBFETCH_CPPFLAGS) $(CFLAGS) \ - $(LIBFETCH_CFLAGS) $(SHAREDLIB_CFLAGS) -c $< -o $@ + $(LIBFETCH_CFLAGS) $(LIBFETCH_SHLIBCFLAGS) -c $< -o $@ $(OBJS): %.o: %.c @echo " [CC]\t\t$@" diff --git a/lib/cmpver.c b/lib/cmpver.c index 4f47420a..5fd9ede9 100644 --- a/lib/cmpver.c +++ b/lib/cmpver.c @@ -223,7 +223,7 @@ get_component(const char *position, version_component *component) * of the version should conform to the porting guidelines. It can contain * multiple components, separated by a period, including letters. */ -int SYMEXPORT +int xbps_cmpver(const char *pkg1, const char *pkg2) { const char *v1, *v2, *ve1, *ve2; diff --git a/lib/config_files.c b/lib/config_files.c index 01e8d652..d6d8a4cb 100644 --- a/lib/config_files.c +++ b/lib/config_files.c @@ -32,7 +32,7 @@ #include -int +int HIDDEN xbps_config_file_from_archive_entry(prop_dictionary_t d, struct archive_entry *entry, const char *pkgname, diff --git a/lib/configure.c b/lib/configure.c index f469137b..e009b5ff 100644 --- a/lib/configure.c +++ b/lib/configure.c @@ -28,12 +28,25 @@ #include #include +/** + * @file lib/configure.c + * @brief Package configuration routines + * @defgroup configure Package configuration functions + * + * Configure a package or all packages. Only packages in unpacked + * state will be processed (unless overriden). Package configuration steps: + * + * 1- Its post-install target in the INSTALL script will be executed. + * + * 2- Its state will be changed to installed if previous step + * ran successful. + * + * If the \a XBPS_FLAG_FORCE is set through xbps_set_flags(), the package + * (or packages) will be reconfigured even if its state is installed. + */ #include -/* - * Configure all packages currently in unpacked state. - */ -int SYMEXPORT +int xbps_configure_all_pkgs(void) { prop_dictionary_t d; @@ -78,12 +91,7 @@ out: return rv; } -/* - * Configure a package that is in unpacked state. This runs the - * post INSTALL action if required and updates package state to - * to installed. - */ -int SYMEXPORT +int xbps_configure_pkg(const char *pkgname, const char *version, bool check_state, bool update) { @@ -111,7 +119,7 @@ xbps_configure_pkg(const char *pkgname, const char *version, bool check_state, } else if (state != XBPS_PKG_STATE_UNPACKED) return EINVAL; - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) return errno; diff --git a/lib/download.c b/lib/download.c index 88a2e04d..e8ee9205 100644 --- a/lib/download.c +++ b/lib/download.c @@ -42,6 +42,13 @@ #include #include "fetch.h" +/** + * @file lib/download.c + * @brief Download routines + * @defgroup download Internal download functions + * + * These functions allow you to download files. + */ struct xferstat { struct timeval start; struct timeval last; @@ -164,7 +171,7 @@ stat_end(struct xferstat *xsp) fprintf(stderr, "\033[K\n"); } -const char SYMEXPORT * +const char * xbps_fetch_error_string(void) { return fetchLastErrString; @@ -183,11 +190,7 @@ print_time(time_t *t) } #endif -/* - * Returns -1 on error, 0 if not download (because local/remote - * size and/or mtime match) and 1 if downloaded successfully. - */ -int SYMEXPORT +int xbps_fetch_file(const char *uri, const char *outputdir, bool refetch, const char *flags) { diff --git a/lib/fexec.c b/lib/fexec.c index 04819825..8c483e3c 100644 --- a/lib/fexec.c +++ b/lib/fexec.c @@ -36,15 +36,16 @@ #include -static int vfcexec(const char *, int, const char *, va_list); -static int pfcexec(const char *, const char *, const char **); - -/* - * Fork, then if /bin/sh exists change root directory to - * path; otherwise just change current working directory. - * Execute the command and arguments in the argv array. - * wait for the command to finish, then return the exit status. +/** + * @file lib/fexec.c + * @brief Generic file execution routines + * @defgroup fexec File execution functions + * + * These functions will fork and execute a program in cwd (current working + * directory), destination directory or changing root directory to + * destination directory and passing an arbitrary number of arguments to it. */ + static int pfcexec(const char *path, const char *file, const char **argv) { @@ -128,7 +129,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap) return retval; } -int SYMEXPORT +int xbps_file_exec(const char *arg, ...) { va_list ap; @@ -141,7 +142,7 @@ xbps_file_exec(const char *arg, ...) return result; } -int SYMEXPORT +int xbps_file_exec_skipempty(const char *arg, ...) { va_list ap; @@ -154,7 +155,7 @@ xbps_file_exec_skipempty(const char *arg, ...) return result; } -int SYMEXPORT +int xbps_file_chdir_exec(const char *path, const char *arg, ...) { va_list ap; diff --git a/lib/humanize_number.c b/lib/humanize_number.c index 7781b1c2..5e3dc19a 100644 --- a/lib/humanize_number.c +++ b/lib/humanize_number.c @@ -39,7 +39,7 @@ #include -int SYMEXPORT +int xbps_humanize_number(char *buf, size_t len, int64_t bytes, const char *suffix, int scale, int flags) { diff --git a/lib/mkpath.c b/lib/mkpath.c index 5774447a..968778b7 100644 --- a/lib/mkpath.c +++ b/lib/mkpath.c @@ -37,11 +37,13 @@ #include #include -/* - * mkpath -- create directories. - * path - path - * mode - file mode of terminal directory + +/** + * @file lib/mkpath.c + * @brief Generic directory creation routines + * @defgroup dircreate Generic directory creation functions */ + int xbps_mkpath(char *path, mode_t mode) { diff --git a/lib/orphans.c b/lib/orphans.c index 52f56f74..ce717da8 100644 --- a/lib/orphans.c +++ b/lib/orphans.c @@ -31,6 +31,12 @@ #include +/** + * @file lib/orphans.c + * @brief Package orphans handling routines + * @defgroup pkg_orphans Package orphans handling functions + */ + struct orphan_pkg { SIMPLEQ_ENTRY(orphan_pkg) chain; prop_dictionary_t dict; @@ -128,7 +134,7 @@ cleanup(void) xbps_regpkgs_dictionary_release(); } -prop_array_t SYMEXPORT +prop_array_t xbps_find_orphan_packages(void) { prop_array_t array; diff --git a/lib/pkgmatch.c b/lib/pkgmatch.c index cacf3909..ce70e556 100644 --- a/lib/pkgmatch.c +++ b/lib/pkgmatch.c @@ -27,6 +27,12 @@ #include +/** + * @file lib/pkgmatch.c + * @brief Package version matching routines + * @defgroup vermatch Package version matching functions + */ + static int csh_match(const char *pattern, const char *string, int flags) { @@ -106,8 +112,8 @@ csh_match(const char *pattern, const char *string, int flags) return ret; } -int SYMEXPORT -xbps_pkgdep_match(const char *instpkg, char *pattern) +int +xbps_pkgpattern_match(const char *instpkg, char *pattern) { const char *fname = instpkg; char basefname[PATH_MAX], condchar = '\0', *condition; diff --git a/lib/plist.c b/lib/plist.c index 6c5fa5ef..4f1977bd 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -31,7 +31,15 @@ #include -bool SYMEXPORT +/** + * @file lib/plist.c + * @brief PropertyList generic routines + * @defgroup plist PropertyList generic functions + * + * These functions manipulate plist files and objects shared by almost + * all library functions. + */ +bool xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj, const char *key) { @@ -48,7 +56,7 @@ xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj, return true; } -bool SYMEXPORT +bool xbps_add_obj_to_array(prop_array_t array, prop_object_t obj) { assert(array != NULL); @@ -63,7 +71,7 @@ xbps_add_obj_to_array(prop_array_t array, prop_object_t obj) return true; } -int SYMEXPORT +int xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key, int (*fn)(prop_object_t, void *, bool *), void *arg) @@ -91,7 +99,7 @@ xbps_callback_array_iter_in_dict(prop_dictionary_t dict, const char *key, return rv; } -int SYMEXPORT +int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, const char *key, int (*fn)(prop_object_t, void *, bool *), void *arg) { @@ -122,7 +130,7 @@ xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, return rv; } -prop_dictionary_t SYMEXPORT +prop_dictionary_t xbps_find_pkg_from_plist(const char *plist, const char *pkgname) { prop_dictionary_t dict, obj, res; @@ -146,8 +154,8 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname) return res; } -prop_dictionary_t SYMEXPORT -xbps_find_pkg_installed_from_plist(const char *pkgname) +prop_dictionary_t +xbps_find_pkg_dict_installed(const char *str, bool bypattern) { prop_dictionary_t d, pkgd; pkg_state_t state = 0; @@ -155,7 +163,10 @@ xbps_find_pkg_installed_from_plist(const char *pkgname) if ((d = xbps_regpkgs_dictionary_init()) == NULL) return NULL; - pkgd = xbps_find_pkg_in_dict_by_name(d, "packages", pkgname); + if (bypattern) + pkgd = xbps_find_pkg_in_dict_by_pattern(d, "packages", str); + else + pkgd = xbps_find_pkg_in_dict_by_name(d, "packages", str); if (pkgd == NULL) goto fail; @@ -178,8 +189,9 @@ fail: return NULL; } -prop_dictionary_t SYMEXPORT -xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, const char *key, +prop_dictionary_t +xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, + const char *key, const char *pkgname) { prop_object_iterator_t iter; @@ -207,9 +219,10 @@ xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, const char *key, return obj; } -prop_dictionary_t SYMEXPORT -xbps_find_pkg_in_dict_by_pkgmatch(prop_dictionary_t dict, const char *key, - const char *pkgmatch) +prop_dictionary_t +xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict, + const char *key, + const char *pattern) { prop_object_iterator_t iter; prop_object_t obj = NULL; @@ -226,7 +239,7 @@ xbps_find_pkg_in_dict_by_pkgmatch(prop_dictionary_t dict, const char *key, if (!prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) break; - if (xbps_pkgdep_match(pkgver, __UNCONST(pkgmatch))) + if (xbps_pkgpattern_match(pkgver, __UNCONST(pattern))) break; } prop_object_iterator_release(iter); @@ -236,7 +249,7 @@ xbps_find_pkg_in_dict_by_pkgmatch(prop_dictionary_t dict, const char *key, return obj; } -bool SYMEXPORT +bool xbps_find_string_in_array(prop_array_t array, const char *val) { prop_object_iterator_t iter; @@ -262,7 +275,7 @@ xbps_find_string_in_array(prop_array_t array, const char *val) return false; } -prop_object_iterator_t SYMEXPORT +prop_object_iterator_t xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key) { prop_array_t array; @@ -277,7 +290,7 @@ xbps_get_array_iter_from_dict(prop_dictionary_t dict, const char *key) return prop_array_iterator(array); } -int SYMEXPORT +int xbps_remove_string_from_array(prop_array_t array, const char *str) { prop_object_t obj; @@ -308,7 +321,7 @@ xbps_remove_string_from_array(prop_array_t array, const char *str) return 0; } -int SYMEXPORT +int xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, const char *pkgname) { @@ -353,7 +366,7 @@ xbps_remove_pkg_from_dict(prop_dictionary_t dict, const char *key, return 0; } -int SYMEXPORT +int xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist) { prop_dictionary_t pdict; @@ -382,7 +395,7 @@ xbps_remove_pkg_dict_from_file(const char *pkg, const char *plist) return 0; } -prop_dictionary_t SYMEXPORT +prop_dictionary_t xbps_read_dict_from_archive_entry(struct archive *ar, struct archive_entry *entry) { diff --git a/lib/purge.c b/lib/purge.c index 129c3ac0..9b7d5e7e 100644 --- a/lib/purge.c +++ b/lib/purge.c @@ -31,9 +31,77 @@ #include -static int remove_pkg_metadata(const char *); +/** + * @file lib/purge.c + * @brief Package purging routines + * @defgroup purge Package purging functions + * + * These functions will purge an specified package or all packages. + * Only packages in config-files state will be processed + * (unless overriden). Package purging steps: + * + * 1- Its post-remove target specified in the REMOVE script + * will be executed. + * + * 2- Unmodified configuration files and directories containing them + * will be removed (if empty). + * + * 3- Its metadata directory and all its files will be removed. + * + * 4- It will be unregistered from the installed packages database with + * xbps_unregister_pkg(). + */ -int SYMEXPORT +static int +remove_pkg_metadata(const char *pkgname) +{ + struct dirent *dp; + DIR *dirp; + char *metadir, *path; + int flags = 0, rv = 0; + + 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; + + dirp = opendir(metadir); + if (dirp == NULL) { + free(metadir); + return errno; + } + + while ((dp = readdir(dirp)) != NULL) { + if ((strcmp(dp->d_name, ".") == 0) || + (strcmp(dp->d_name, "..") == 0)) + continue; + + path = xbps_xasprintf("%s/%s", metadir, dp->d_name); + if (path == NULL) { + (void)closedir(dirp); + free(metadir); + return -1; + } + + if ((rv = unlink(path)) == -1) { + if (flags & XBPS_FLAG_VERBOSE) + printf("WARNING: can't remove %s (%s)\n", + pkgname, strerror(errno)); + } + free(path); + } + (void)closedir(dirp); + rv = rmdir(metadir); + free(metadir); + + return rv; +} + +int xbps_purge_all_pkgs(void) { @@ -73,12 +141,7 @@ out: return rv; } -/* - * Purge a package that is currently in "config-files" state. - * This removes configuration files if they weren't modified, - * removes metadata files and fully unregisters the package. - */ -int SYMEXPORT +int xbps_purge_pkg(const char *pkgname, bool check_state) { prop_dictionary_t dict; @@ -129,59 +192,13 @@ xbps_purge_pkg(const char *pkgname, bool check_state) * Remove metadata dir and unregister package. */ if ((rv = remove_pkg_metadata(pkgname)) == 0) { - if ((rv = xbps_unregister_pkg(pkgname)) == 0) - printf("Package %s has been purged successfully.\n", - pkgname); + if ((rv = xbps_unregister_pkg(pkgname)) == 0) { + if (flags & XBPS_FLAG_VERBOSE) { + printf("Package %s purged " + "successfully.\n", pkgname); + } + } } return rv; } - -static int -remove_pkg_metadata(const char *pkgname) -{ - struct dirent *dp; - DIR *dirp; - char *metadir, *path; - int flags = 0, rv = 0; - - 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; - - dirp = opendir(metadir); - if (dirp == NULL) { - free(metadir); - return errno; - } - - while ((dp = readdir(dirp)) != NULL) { - if ((strcmp(dp->d_name, ".") == 0) || - (strcmp(dp->d_name, "..") == 0)) - continue; - - path = xbps_xasprintf("%s/%s", metadir, dp->d_name); - if (path == NULL) { - (void)closedir(dirp); - free(metadir); - return -1; - } - - if ((rv = unlink(path)) == -1) { - if (flags & XBPS_FLAG_VERBOSE) - printf("WARNING: can't remove %s (%s)\n", - pkgname, strerror(errno)); - } - free(path); - } - (void)closedir(dirp); - rv = rmdir(metadir); - free(metadir); - - return rv; -} diff --git a/lib/register.c b/lib/register.c index d24b5fb2..649a2010 100644 --- a/lib/register.c +++ b/lib/register.c @@ -30,7 +30,16 @@ #include -int SYMEXPORT +/** + * @file lib/register.c + * @brief Package (un)registration routines + * @defgroup pkg_register Package (un)registration functions + * + * Register and unregister packages into/from the installed + * packages database. + */ + +int xbps_register_pkg(prop_dictionary_t pkgrd, bool automatic) { prop_dictionary_t dict, pkgd; @@ -129,7 +138,7 @@ out: return rv; } -int SYMEXPORT +int xbps_unregister_pkg(const char *pkgname) { char *plist; diff --git a/lib/regpkgs_dictionary.c b/lib/regpkgs_dictionary.c index 1b819514..c262fa4d 100644 --- a/lib/regpkgs_dictionary.c +++ b/lib/regpkgs_dictionary.c @@ -31,11 +31,22 @@ #include +/** + * @file lib/regpkgs_dictionary.c + * @brief Installed packages database init/fini routines + * @defgroup regpkgdb Installed packages database init/fini functions + * + * These functions will initialize the installed packages database, + * internalizing/externalizing the plist dictionary. Every initialization + * must be followed by a finalization if its data is not necessary, because + * the functions are reference counted. + */ + static prop_dictionary_t regpkgs_dict; static size_t regpkgs_refcount; static bool regpkgs_initialized; -prop_dictionary_t SYMEXPORT +prop_dictionary_t xbps_regpkgs_dictionary_init(void) { char *plist; @@ -60,7 +71,7 @@ xbps_regpkgs_dictionary_init(void) return regpkgs_dict; } -void SYMEXPORT +void xbps_regpkgs_dictionary_release(void) { if (--regpkgs_refcount > 0) diff --git a/lib/remove.c b/lib/remove.c index eb19e9f5..ffce3299 100644 --- a/lib/remove.c +++ b/lib/remove.c @@ -32,7 +32,38 @@ #include -int SYMEXPORT +/** + * @file lib/remove.c + * @brief Package removal routines + * @defgroup pkg_remove Package removal functions + * + * These functions will remove a package or only a subset of its + * files. Package removal steps: + * + * 1) Its pre-remove target specified in the REMOVE script + * will be executed. + * + * 2) Its files, dirs and links will be removed. Modified files (not + * matching its sha256 hash) will always be preserved. + * + * 3) Its post-remove target specified in the REMOVE script + * will be executed. + * + * 4) Its requiredby objects will be removed from the installed packages + * database. + * + * 5) Its state will be changed to config-files. + * + * If a package is going to be updated and it's an essential package, + * only steps 1 and 4 will be executed. + * + * If a package is going to be updated and it's NOT an essential + * package, only steps 1, 2 and 4 will be executed. + * + * If a package is going to be removed, all steps will be executed. + */ + +int xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) { prop_array_t array; @@ -135,14 +166,14 @@ xbps_remove_pkg_files(prop_dictionary_t dict, const char *key) return rv; } -int SYMEXPORT +int xbps_remove_pkg(const char *pkgname, const char *version, bool update) { - prop_dictionary_t dict; + prop_dictionary_t dict, pkgd; const char *rootdir = xbps_get_rootdir(); char *path, *buf; int rv = 0; - bool prepostf = false; + bool essential = false, prepostf = false; assert(pkgname != NULL); assert(version != NULL); @@ -150,9 +181,12 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) /* * Check if pkg is installed before anything else. */ - if (xbps_check_is_installed_pkgname(pkgname) == false) + if ((pkgd = xbps_find_pkg_dict_installed(pkgname, false)) == NULL) return ENOENT; + prop_dictionary_get_bool(pkgd, "essential", &essential); + prop_object_release(pkgd); + if (strcmp(rootdir, "") == 0) rootdir = "/"; @@ -183,6 +217,15 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) } } + /* + * If updating an essential package, we just need to execute + * the current pre-remove action target, unregister its requiredby + * entries and continue. Its files will be overwritten later in + * the unpack phase. + */ + if (essential && update) + return xbps_requiredby_pkg_remove(pkgname); + /* * Remove links, files and dirs. */ diff --git a/lib/remove_obsoletes.c b/lib/remove_obsoletes.c index c8ad975a..fcc90fe5 100644 --- a/lib/remove_obsoletes.c +++ b/lib/remove_obsoletes.c @@ -31,7 +31,7 @@ #include -int +int HIDDEN xbps_remove_obsoletes(prop_dictionary_t oldd, prop_dictionary_t newd) { prop_object_iterator_t iter, iter2; diff --git a/lib/repository.c b/lib/repository.c index a7c47b46..07077239 100644 --- a/lib/repository.c +++ b/lib/repository.c @@ -30,7 +30,13 @@ #include -int SYMEXPORT +/** + * @file lib/repository.c + * @brief Repository (un)registration routines + * @defgroup repo_register Repository (un)registration functions + */ + +int xbps_repository_register(const char *uri) { prop_dictionary_t dict; @@ -106,7 +112,7 @@ out: return rv; } -int SYMEXPORT +int xbps_repository_unregister(const char *uri) { prop_dictionary_t dict; diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index d2541834..9e3ab639 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -30,11 +30,6 @@ #include -static int add_missing_reqdep(prop_dictionary_t, const char *); -static int remove_missing_reqdep(prop_dictionary_t, const char *); -static int find_repo_deps(prop_dictionary_t, prop_dictionary_t, - const char *, prop_array_t); - static int store_dependency(prop_dictionary_t master, prop_dictionary_t depd, const char *repoloc) @@ -135,14 +130,14 @@ add_missing_reqdep(prop_dictionary_t master, const char *reqpkg) assert(prop_object_type(obj) == PROP_TYPE_STRING); curdep = prop_string_cstring_nocopy(obj); - curver = xbps_get_pkgdep_version(curdep); - pkgver = xbps_get_pkgdep_version(reqpkg); + curver = xbps_get_pkgpattern_version(curdep); + pkgver = xbps_get_pkgpattern_version(reqpkg); if (curver == NULL || pkgver == NULL) goto out; - curpkgnamedep = xbps_get_pkgdep_name(curdep); + curpkgnamedep = xbps_get_pkgpattern_name(curdep); if (curpkgnamedep == NULL) goto out; - pkgnamedep = xbps_get_pkgdep_name(reqpkg); + pkgnamedep = xbps_get_pkgpattern_name(reqpkg); if (pkgnamedep == NULL) { free(curpkgnamedep); goto out; @@ -207,12 +202,12 @@ remove_missing_reqdep(prop_dictionary_t master, const char *reqpkg) char *curpkgnamedep, *reqpkgname; curdep = prop_string_cstring_nocopy(obj); - curpkgnamedep = xbps_get_pkgdep_name(curdep); + curpkgnamedep = xbps_get_pkgpattern_name(curdep); if (curpkgnamedep == NULL) { rv = errno; goto out; } - reqpkgname = xbps_get_pkgdep_name(reqpkg); + reqpkgname = xbps_get_pkgpattern_name(reqpkg); if (reqpkgname == NULL) { free(curpkgnamedep); rv = errno; @@ -239,72 +234,6 @@ out: return rv; } -int SYMEXPORT -xbps_repository_find_pkg_deps(prop_dictionary_t master, prop_dictionary_t pkg) -{ - prop_array_t pkg_rdeps, missing_rdeps; - struct repository_pool *rpool; - const char *pkgname; - int rv = 0; - - assert(master != NULL); - assert(pkg != NULL); - - pkg_rdeps = prop_dictionary_get(pkg, "run_depends"); - if (pkg_rdeps == NULL) - return 0; - - if (!prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname)) - return errno; - - if ((rv = xbps_repository_pool_init()) != 0) - return rv; - - DPRINTF(("Checking rundeps for %s.\n", pkgname)); - /* - * Iterate over the repository pool and find out if we have - * all available binary packages. - */ - SIMPLEQ_FOREACH(rpool, &repopool_queue, chain) { - /* - * 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(master, rpool->rp_repod, - rpool->rp_uri, pkg_rdeps)) != 0) { - DPRINTF(("Error '%s' while checking rundeps!\n", - strerror(rv))); - goto out; - } - } - - /* - * If there are no missing deps, there's nothing to do. - */ - missing_rdeps = prop_dictionary_get(master, "missing_deps"); - if (prop_array_count(missing_rdeps) == 0) - goto out; - - /* - * 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, &repopool_queue, chain) { - if ((rv = find_repo_deps(master, rpool->rp_repod, - rpool->rp_uri, missing_rdeps)) != 0) { - DPRINTF(("Error '%s' while checking for " - "missing rundeps!\n", strerror(rv))); - goto out; - } - } -out: - xbps_repository_pool_release(); - - return rv; -} - static int find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, const char *repoloc, prop_array_t array) @@ -347,12 +276,12 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, continue; } DPRINTF(("Dependency %s not installed.\n", reqpkg)); - pkgname = xbps_get_pkgdep_name(reqpkg); + pkgname = xbps_get_pkgpattern_name(reqpkg); if (pkgname == NULL) { rv = EINVAL; break; } - reqvers = xbps_get_pkgdep_version(reqpkg); + reqvers = xbps_get_pkgpattern_version(reqpkg); if (reqvers == NULL) { free(pkgname); rv = EINVAL; @@ -379,7 +308,8 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, rv = errno; break; } - if (xbps_pkgdep_match(pkg_queued, __UNCONST(reqpkg))) { + if (xbps_pkgpattern_match(pkg_queued, + __UNCONST(reqpkg))) { DPRINTF(("Dependency %s already queued.\n", pkgname)); free(pkgname); @@ -429,7 +359,7 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, rv = errno; break; } - if (xbps_pkgdep_match(repo_pkgver, __UNCONST(reqpkg)) < 1) { + if (xbps_pkgpattern_match(repo_pkgver, __UNCONST(reqpkg)) < 1) { free(pkgname); continue; } @@ -440,7 +370,7 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, * an install. Packages that were unpacked previously * will be marked as pending to be configured. */ - tmpd = xbps_find_pkg_installed_from_plist(pkgname); + tmpd = xbps_find_pkg_dict_installed(pkgname, false); if (tmpd == NULL) { if (errno && errno != ENOENT) { free(pkgname); @@ -512,3 +442,69 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, return rv; } + +int HIDDEN +xbps_repository_find_pkg_deps(prop_dictionary_t master, prop_dictionary_t pkg) +{ + prop_array_t pkg_rdeps, missing_rdeps; + struct repository_pool *rpool; + const char *pkgname; + int rv = 0; + + assert(master != NULL); + assert(pkg != NULL); + + pkg_rdeps = prop_dictionary_get(pkg, "run_depends"); + if (pkg_rdeps == NULL) + return 0; + + if (!prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname)) + return errno; + + if ((rv = xbps_repository_pool_init()) != 0) + return rv; + + DPRINTF(("Checking rundeps for %s.\n", pkgname)); + /* + * 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(master, rpool->rp_repod, + rpool->rp_uri, pkg_rdeps)) != 0) { + DPRINTF(("Error '%s' while checking rundeps!\n", + strerror(rv))); + goto out; + } + } + + /* + * If there are no missing deps, there's nothing to do. + */ + missing_rdeps = prop_dictionary_get(master, "missing_deps"); + if (prop_array_count(missing_rdeps) == 0) + goto out; + + /* + * 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(master, rpool->rp_repod, + rpool->rp_uri, missing_rdeps)) != 0) { + DPRINTF(("Error '%s' while checking for " + "missing rundeps!\n", strerror(rv))); + goto out; + } + } +out: + xbps_repository_pool_release(); + + return rv; +} diff --git a/lib/repository_findpkg.c b/lib/repository_findpkg.c index acf0fa00..d837443d 100644 --- a/lib/repository_findpkg.c +++ b/lib/repository_findpkg.c @@ -31,11 +31,15 @@ #include +/** + * @file lib/repository_findpkg.c + * @brief Repository packages transaction handling routines + * @defgroup repo_pkgs Repository packages transaction handling functions + */ + static prop_dictionary_t trans_dict; static bool trans_dict_initialized; -static int set_pkg_state(prop_dictionary_t, const char *); - static int create_transaction_dictionary(void) { @@ -84,16 +88,123 @@ fail: return rv; } -prop_dictionary_t SYMEXPORT +static int +compute_transaction_sizes(void) +{ + prop_object_iterator_t iter; + prop_object_t obj; + uint64_t tsize = 0, dlsize = 0, instsize = 0; + int rv = 0; + const char *tract; + + iter = xbps_get_array_iter_from_dict(trans_dict, "packages"); + if (iter == NULL) + return -1; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + if (!prop_dictionary_get_cstring_nocopy(obj, + "trans-action", &tract)) { + rv = -1; + goto out; + } + /* + * Skip pkgs that need to be configured. + */ + if (strcmp(tract, "configure") == 0) + continue; + + if (!prop_dictionary_get_uint64(obj, + "filename-size", &tsize)) { + rv = -1; + goto out; + } + dlsize += tsize; + tsize = 0; + if (!prop_dictionary_get_uint64(obj, + "installed_size", &tsize)) { + rv = -1; + goto out; + } + instsize += tsize; + tsize = 0; + } + + /* + * Add object in transaction dictionary with total installed + * size that it will take. + */ + if (!prop_dictionary_set_uint64(trans_dict, + "total-installed-size", instsize)) { + rv = -1; + goto out; + } + /* + * Add object in transaction dictionary with total download + * size that needs to be sucked in. + */ + if (!prop_dictionary_set_uint64(trans_dict, + "total-download-size", dlsize)) { + rv = -1; + goto out; + } +out: + prop_object_iterator_release(iter); + + return rv; +} + +static int +set_pkg_state(prop_dictionary_t pkgd, const char *pkgname) +{ + pkg_state_t state = 0; + int rv = 0; + + rv = xbps_set_pkg_state_dictionary(pkgd, XBPS_PKG_STATE_NOT_INSTALLED); + if (rv != 0) + 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_set_pkg_state_dictionary(pkgd, state)) != 0) + return rv; + } else if (rv == ENOENT) + rv = 0; + + return rv; +} + +prop_dictionary_t xbps_repository_get_transaction_dict(void) { - if (trans_dict_initialized == false) + int rv = 0; + + if (trans_dict_initialized == false) { + errno = ENOENT; + return NULL; + } + + /* + * Sort package list if necessary. + */ + if ((rv = xbps_sort_pkg_deps(trans_dict)) != 0) { + errno = rv; + return NULL; + } + + /* + * Add total transaction installed/download sizes + * to the transaction dictionary. + */ + if (compute_transaction_sizes() != 0) return NULL; return trans_dict; } -int SYMEXPORT +int xbps_repository_update_allpkgs(void) { prop_dictionary_t dict; @@ -110,10 +221,7 @@ xbps_repository_update_allpkgs(void) if (dict == NULL) return ENOENT; - /* - * Prepare simpleq with all registered repositories. - */ - if ((rv = xbps_repository_pool_init()) != 0) + if ((rv = xbps_repository_pool_init()) != 0) goto out; iter = xbps_get_array_iter_from_dict(dict, "packages"); @@ -154,7 +262,7 @@ out: return rv; } -int SYMEXPORT +int xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) { prop_dictionary_t pkgrd = NULL; @@ -173,7 +281,7 @@ xbps_repository_update_pkg(const char *pkgname, prop_dictionary_t instpkg) if ((rv = xbps_repository_pool_init()) != 0) return rv; - SIMPLEQ_FOREACH(rpool, &repopool_queue, chain) { + SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { /* * Get the package dictionary from current repository. * If it's not there, pass to the next repository. @@ -274,31 +382,8 @@ out: return rv; } -static int -set_pkg_state(prop_dictionary_t pkgd, const char *pkgname) -{ - pkg_state_t state = 0; - int rv = 0; - - rv = xbps_set_pkg_state_dictionary(pkgd, XBPS_PKG_STATE_NOT_INSTALLED); - if (rv != 0) - 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_set_pkg_state_dictionary(pkgd, state)) != 0) - return rv; - } else if (rv == ENOENT) - rv = 0; - - return rv; -} - -int SYMEXPORT -xbps_repository_install_pkg(const char *pkg, bool by_pkgmatch) +int +xbps_repository_install_pkg(const char *pkg, bool bypattern) { prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL; prop_array_t unsorted; @@ -311,13 +396,13 @@ xbps_repository_install_pkg(const char *pkg, bool by_pkgmatch) if ((rv = xbps_repository_pool_init()) != 0) return rv; - SIMPLEQ_FOREACH(rpool, &repopool_queue, chain) { + 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 (by_pkgmatch) - pkgrd = xbps_find_pkg_in_dict_by_pkgmatch( + if (bypattern) + pkgrd = xbps_find_pkg_in_dict_by_pattern( rpool->rp_repod, "packages", pkg); else pkgrd = xbps_find_pkg_in_dict_by_name( @@ -346,8 +431,8 @@ xbps_repository_install_pkg(const char *pkg, bool by_pkgmatch) * Check that this pkg hasn't been added previously into * the transaction. */ - if (by_pkgmatch) { - if (xbps_find_pkg_in_dict_by_pkgmatch(trans_dict, + if (bypattern) { + if (xbps_find_pkg_in_dict_by_pattern(trans_dict, "unsorted_deps", pkg)) goto out; } else { diff --git a/lib/repository_plist.c b/lib/repository_plist.c index f797fa2d..05b9d028 100644 --- a/lib/repository_plist.c +++ b/lib/repository_plist.c @@ -34,6 +34,12 @@ #include #include "fetch.h" +/** + * @file lib/repository_plist.c + * @brief Repository plist file handling routines + * @defgroup repo_plist Repository plist file handling functions + */ + struct fetch_archive { struct url *url; struct fetchIO *fetch; @@ -151,7 +157,7 @@ binpkg_in_cachedir(prop_dictionary_t d, const char *uri) return NULL; } -char SYMEXPORT * +char * xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d, const char *uri) { const char *arch, *filen; @@ -169,7 +175,7 @@ xbps_repository_get_path_from_pkg_dict(prop_dictionary_t d, const char *uri) return xbps_xasprintf("%s/%s/%s", uri, arch, filen); } -prop_dictionary_t SYMEXPORT +prop_dictionary_t xbps_repository_get_pkg_plist_dict_from_url(const char *url, const char *plistf) { prop_dictionary_t plistd = NULL; @@ -216,7 +222,7 @@ xbps_repository_get_pkg_plist_dict_from_url(const char *url, const char *plistf) return plistd; } -prop_dictionary_t SYMEXPORT +prop_dictionary_t xbps_repository_get_pkg_plist_dict(const char *pkgname, const char *plistf) { prop_dictionary_t plistd = NULL, pkgd; @@ -238,7 +244,7 @@ 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, &repopool_queue, chain) { + SIMPLEQ_FOREACH(rpool, &rp_queue, rp_entries) { pkgd = xbps_find_pkg_in_dict_by_name(rpool->rp_repod, "packages", pkgname); if (pkgd == NULL) { diff --git a/lib/repository_pool.c b/lib/repository_pool.c index 7a8e87ee..0340db39 100644 --- a/lib/repository_pool.c +++ b/lib/repository_pool.c @@ -31,10 +31,16 @@ #include +/** + * @file lib/repository_pool.c + * @brief Repository pool init/fini routines + * @defgroup repopool Repository pool init/fini functions + */ + static size_t repolist_refcnt; static bool repolist_initialized; -int SYMEXPORT +int xbps_repository_pool_init(void) { prop_dictionary_t dict = NULL; @@ -51,7 +57,7 @@ xbps_repository_pool_init(void) return 0; } - SIMPLEQ_INIT(&repopool_queue); + SIMPLEQ_INIT(&rp_queue); plist = xbps_xasprintf("%s/%s/%s", xbps_get_rootdir(), XBPS_META_PATH, XBPS_REPOLIST); @@ -120,7 +126,7 @@ xbps_repository_pool_init(void) goto out; } free(plist); - SIMPLEQ_INSERT_TAIL(&repopool_queue, rpool, chain); + SIMPLEQ_INSERT_TAIL(&rp_queue, rpool, rp_entries); } if (ntotal - nmissing == 0) @@ -141,7 +147,7 @@ out: } -void SYMEXPORT +void xbps_repository_pool_release(void) { struct repository_pool *rpool; @@ -149,8 +155,8 @@ xbps_repository_pool_release(void) if (--repolist_refcnt > 0) return; - while ((rpool = SIMPLEQ_FIRST(&repopool_queue)) != NULL) { - SIMPLEQ_REMOVE(&repopool_queue, rpool, repository_pool, chain); + 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); free(rpool); diff --git a/lib/repository_sync_index.c b/lib/repository_sync_index.c index a1fcc7ff..d7a2cb8e 100644 --- a/lib/repository_sync_index.c +++ b/lib/repository_sync_index.c @@ -33,7 +33,13 @@ #include #include "fetch.h" -char SYMEXPORT * +/** + * @file lib/repository_sync_index.c + * @brief Repository package index synchronization routines + * @defgroup reposync Repository package index synchronization functions + */ + +char * xbps_get_remote_repo_string(const char *uri) { struct url *url; @@ -71,7 +77,7 @@ xbps_get_remote_repo_string(const char *uri) * Returns -1 on error, 0 if transfer was not necessary (local/remote * size and/or mtime match) and 1 if downloaded successfully. */ -int SYMEXPORT +int xbps_repository_sync_pkg_index(const char *uri) { struct url *url = NULL; diff --git a/lib/requiredby.c b/lib/requiredby.c index 6a3087c8..8ca1816a 100644 --- a/lib/requiredby.c +++ b/lib/requiredby.c @@ -121,7 +121,7 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done) return 0; } -int SYMEXPORT +int HIDDEN xbps_requiredby_pkg_remove(const char *pkgname) { prop_dictionary_t dict; @@ -151,7 +151,7 @@ xbps_requiredby_pkg_remove(const char *pkgname) return rv; } -int SYMEXPORT +int HIDDEN xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) { prop_array_t rdeps; @@ -178,7 +178,7 @@ xbps_requiredby_pkg_add(prop_array_t regar, prop_dictionary_t pkg) rv = errno; goto out; } - rdepname = xbps_get_pkgdep_name(str); + rdepname = xbps_get_pkgpattern_name(str); if (rdepname == NULL) { rv = EINVAL; goto out; diff --git a/lib/sha256.c b/lib/sha256.c index 2f2f38b5..e474c68f 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -87,6 +87,11 @@ static void SHA256_Transform(SHA256_CTX *, const uint32_t*); static int SHA256_Final(uint8_t *, SHA256_CTX *); +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char sha2_hex_digits[] = "0123456789abcdef"; /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ /* Hash constant words K for SHA-256: */ @@ -122,7 +127,7 @@ static const uint32_t sha256_initial_hash_value[8] = { }; /*** SHA-256: *********************************************************/ -int +int HIDDEN XBPS_SHA256_Init(SHA256_CTX *context) { if (context == NULL) @@ -297,7 +302,7 @@ SHA256_Transform(SHA256_CTX *context, const uint32_t *data) #endif /* SHA2_UNROLL_TRANSFORM */ -int +int HIDDEN XBPS_SHA256_Update(SHA256_CTX *context, const uint8_t *data, size_t len) { unsigned int freespace, usedspace; @@ -434,13 +439,7 @@ SHA256_Final(uint8_t digest[], SHA256_CTX *context) return SHA224_256_Final(digest, context, SHA256_DIGEST_LENGTH); } -/* - * Constant used by SHA256/384/512_End() functions for converting the - * digest to a readable hexadecimal character string: - */ -static const char sha2_hex_digits[] = "0123456789abcdef"; - -char * +char HIDDEN * XBPS_SHA256_End(SHA256_CTX *ctx, uint8_t *buffer) { uint8_t digest[SHA256_DIGEST_LENGTH], *d = digest; diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 73c3e08b..1c1dddef 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -59,7 +59,7 @@ find_sorteddep_by_name(const char *pkgname) return sdep; } -int SYMEXPORT +int HIDDEN xbps_sort_pkg_deps(prop_dictionary_t chaindeps) { prop_array_t sorted, unsorted, rundeps; @@ -149,7 +149,7 @@ again: rv = EINVAL; goto out; } - pkgnamedep = xbps_get_pkgdep_name(str); + pkgnamedep = xbps_get_pkgpattern_name(str); if (pkgnamedep == NULL) { free(sdep); rv = errno; diff --git a/lib/state.c b/lib/state.c index 64566f3f..66551297 100644 --- a/lib/state.c +++ b/lib/state.c @@ -31,6 +31,12 @@ #include +/** + * @file lib/state.c + * @brief Package state handling routines + * @defgroup pkgstates Package state handling functions + */ + static int set_new_state(prop_dictionary_t dict, pkg_state_t state) { @@ -96,14 +102,14 @@ get_state(prop_dictionary_t dict) return state; } -int SYMEXPORT +int xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state) { prop_dictionary_t pkgd; assert(pkgname != NULL); - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) return errno; @@ -114,7 +120,7 @@ xbps_get_pkg_state_installed(const char *pkgname, pkg_state_t *state) return 0; } -int SYMEXPORT +int xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state) { assert(dict != NULL); @@ -125,7 +131,7 @@ xbps_get_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t *state) return 0; } -int SYMEXPORT +int xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state) { assert(dict != NULL); @@ -133,7 +139,7 @@ xbps_set_pkg_state_dictionary(prop_dictionary_t dict, pkg_state_t state) return set_new_state(dict, state); } -int SYMEXPORT +int xbps_set_pkg_state_installed(const char *pkgname, pkg_state_t state) { prop_dictionary_t dict = NULL, pkgd; diff --git a/lib/unpack.c b/lib/unpack.c index 6d4a297e..1df9a17e 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -32,74 +32,11 @@ #include -static int unpack_archive_fini(struct archive *, prop_dictionary_t); -static void set_extract_flags(int *); - -int SYMEXPORT -xbps_unpack_binary_pkg(prop_dictionary_t pkg) -{ - const char *pkgname, *repoloc; - struct archive *ar = NULL; - char *binfile = NULL; - int pkg_fd, rv = 0; - - assert(pkg != NULL); - - if (!prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname)) - return errno; - if (!prop_dictionary_get_cstring_nocopy(pkg, "repository", &repoloc)) - return errno; - binfile = xbps_get_binpkg_local_path(pkg, repoloc); - if (binfile == NULL) - return EINVAL; - - if ((pkg_fd = open(binfile, O_RDONLY)) == -1) { - rv = errno; - goto out; - } - - ar = archive_read_new(); - if (ar == NULL) { - rv = errno; - goto out; - } - - /* - * Enable support for tar format and all compression methods. - */ - 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) - goto out; - - if ((rv = unpack_archive_fini(ar, pkg)) == 0) { - /* - * If installation of package was successful, make sure - * its files are written in storage (if possible). - */ - if (fsync(pkg_fd) == -1) { - rv = errno; - goto out; - } - /* - * Set package state to unpacked. - */ - rv = xbps_set_pkg_state_installed(pkgname, - XBPS_PKG_STATE_UNPACKED); - } - -out: - if (ar) - archive_read_finish(ar); - if (pkg_fd != -1) - (void)close(pkg_fd); - if (binfile) - free(binfile); - - return rv; -} +/** + * @file lib/unpack.c + * @brief Binary package file unpacking routines + * @defgroup unpack Binary package file unpacking functions + */ static void set_extract_flags(int *flags) @@ -154,30 +91,6 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg) if (xbps_check_is_installed_pkgname(pkgname)) update = true; - /* - * If we are updating an essential package, we have to run the - * pre-remove stage by the current package, because later some - * files could be removed. - */ - if (update && essential) { - buf = xbps_xasprintf(".%s/metadata/%s/REMOVE", - XBPS_META_PATH, pkgname); - if (buf == NULL) - return errno; - if (access(buf, R_OK|X_OK) == 0) { - if ((rv = xbps_file_chdir_exec(rootdir, buf, "pre", - pkgname, version, "yes", NULL)) != 0) { - fprintf(stderr, "%s: prerm action target error" - "(%s) while updating!\n", - pkgname, strerror(errno)); - free(buf); - return rv; - } - } - free(buf); - buf = NULL; - } - /* * Process the archive files. */ @@ -401,3 +314,69 @@ unpack_archive_fini(struct archive *ar, prop_dictionary_t pkg) return rv; } + +int +xbps_unpack_binary_pkg(prop_dictionary_t pkg) +{ + const char *pkgname, *repoloc; + struct archive *ar = NULL; + char *binfile = NULL; + int pkg_fd, rv = 0; + + assert(pkg != NULL); + + if (!prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname)) + return errno; + if (!prop_dictionary_get_cstring_nocopy(pkg, "repository", &repoloc)) + return errno; + binfile = xbps_get_binpkg_local_path(pkg, repoloc); + if (binfile == NULL) + return EINVAL; + + if ((pkg_fd = open(binfile, O_RDONLY)) == -1) { + rv = errno; + goto out; + } + + ar = archive_read_new(); + if (ar == NULL) { + rv = errno; + goto out; + } + + /* + * Enable support for tar format and all compression methods. + */ + 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) + goto out; + + if ((rv = unpack_archive_fini(ar, pkg)) == 0) { + /* + * If installation of package was successful, make sure + * its files are written in storage (if possible). + */ + if (fsync(pkg_fd) == -1) { + rv = errno; + goto out; + } + /* + * Set package state to unpacked. + */ + rv = xbps_set_pkg_state_installed(pkgname, + XBPS_PKG_STATE_UNPACKED); + } + +out: + if (ar) + archive_read_finish(ar); + if (pkg_fd != -1) + (void)close(pkg_fd); + if (binfile) + free(binfile); + + return rv; +} diff --git a/lib/util.c b/lib/util.c index 8bceddda..72077625 100644 --- a/lib/util.c +++ b/lib/util.c @@ -38,13 +38,17 @@ #include #include "sha256.h" -static bool question(bool, const char *, va_list); +/** + * @file lib/util.c + * @brief Utility routines + * @defgroup util Utility functions + */ static const char *rootdir; static const char *cachedir; static int flags; -char SYMEXPORT * +char * xbps_get_file_hash(const char *file) { SHA256_CTX ctx; @@ -65,12 +69,12 @@ xbps_get_file_hash(const char *file) return hash; } -int SYMEXPORT -xbps_check_file_hash(const char *path, const char *sha256) +int +xbps_check_file_hash(const char *file, const char *sha256) { char *res; - res = xbps_get_file_hash(path); + res = xbps_get_file_hash(file); if (res == NULL) return errno; @@ -83,7 +87,7 @@ xbps_check_file_hash(const char *path, const char *sha256) return 0; } -bool SYMEXPORT +bool xbps_check_is_repo_string_remote(const char *uri) { assert(uri != NULL); @@ -96,7 +100,20 @@ xbps_check_is_repo_string_remote(const char *uri) return false; } -int SYMEXPORT +static const char * +xbps_get_pkgver_from_dict(prop_dictionary_t d) +{ + const char *pkgver; + + assert(d != NULL); + + if (!prop_dictionary_get_cstring_nocopy(d, "pkgver", &pkgver)) + return NULL; + + return pkgver; +} + +int xbps_check_is_installed_pkg(const char *pkg) { prop_dictionary_t dict; @@ -107,11 +124,11 @@ xbps_check_is_installed_pkg(const char *pkg) assert(pkg != NULL); - pkgname = xbps_get_pkgdep_name(pkg); + pkgname = xbps_get_pkgpattern_name(pkg); if (pkgname == NULL) return -1; - dict = xbps_find_pkg_installed_from_plist(pkgname); + dict = xbps_find_pkg_dict_installed(pkgname, false); if (dict == NULL) { free(pkgname); if (errno == ENOENT) { @@ -144,20 +161,20 @@ xbps_check_is_installed_pkg(const char *pkg) return -1; } - rv = xbps_pkgdep_match(instpkgver, __UNCONST(pkg)); + rv = xbps_pkgpattern_match(instpkgver, __UNCONST(pkg)); prop_object_release(dict); return rv; } -bool SYMEXPORT +bool xbps_check_is_installed_pkgname(const char *pkgname) { prop_dictionary_t pkgd; assert(pkgname != NULL); - pkgd = xbps_find_pkg_installed_from_plist(pkgname); + pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd) { prop_object_release(pkgd); return true; @@ -166,7 +183,7 @@ xbps_check_is_installed_pkgname(const char *pkgname) return false; } -const char SYMEXPORT * +const char * xbps_get_pkg_version(const char *pkg) { const char *tmp; @@ -181,7 +198,7 @@ xbps_get_pkg_version(const char *pkg) return tmp + 1; /* skip first '-' */ } -const char SYMEXPORT * +const char * xbps_get_pkg_revision(const char *pkg) { const char *tmp; @@ -196,7 +213,7 @@ xbps_get_pkg_revision(const char *pkg) return tmp + 1; /* skip first '_' */ } -char SYMEXPORT * +char * xbps_get_pkg_name(const char *pkg) { const char *tmp; @@ -219,8 +236,8 @@ xbps_get_pkg_name(const char *pkg) return pkgname; } -char SYMEXPORT * -xbps_get_pkgdep_name(const char *pkg) +char * +xbps_get_pkgpattern_name(const char *pkg) { char *res, *pkgname; size_t len; @@ -242,8 +259,8 @@ xbps_get_pkgdep_name(const char *pkg) return pkgname; } -const char SYMEXPORT * -xbps_get_pkgdep_version(const char *pkg) +const char * +xbps_get_pkgpattern_version(const char *pkg) { char *res; @@ -256,19 +273,6 @@ xbps_get_pkgdep_version(const char *pkg) return res; } -const char SYMEXPORT * -xbps_get_pkgver_from_dict(prop_dictionary_t d) -{ - const char *pkgver; - - assert(d != NULL); - - if (!prop_dictionary_get_cstring_nocopy(d, "pkgver", &pkgver)) - return NULL; - - return pkgver; -} - static char * get_pkg_index_remote_plist(const char *uri) { @@ -288,7 +292,7 @@ get_pkg_index_remote_plist(const char *uri) return repodir; } -char SYMEXPORT * +char * xbps_get_pkg_index_plist(const char *uri) { struct utsname un; @@ -304,14 +308,14 @@ xbps_get_pkg_index_plist(const char *uri) return xbps_xasprintf("%s/%s/%s", uri, un.machine, XBPS_PKGINDEX); } -char SYMEXPORT * -xbps_get_binpkg_local_path(prop_dictionary_t pkg, const char *repoloc) +char * +xbps_get_binpkg_local_path(prop_dictionary_t pkgd, const char *repoloc) { const char *filen, *arch, *cdir; - if (!prop_dictionary_get_cstring_nocopy(pkg, "filename", &filen)) + if (!prop_dictionary_get_cstring_nocopy(pkgd, "filename", &filen)) return NULL; - if (!prop_dictionary_get_cstring_nocopy(pkg, "architecture", &arch)) + if (!prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch)) return NULL; cdir = xbps_get_cachedir(); if (cdir == NULL) @@ -325,7 +329,7 @@ xbps_get_binpkg_local_path(prop_dictionary_t pkg, const char *repoloc) return xbps_xasprintf("%s/%s", cdir, filen); } -bool SYMEXPORT +bool xbps_pkg_has_rundeps(prop_dictionary_t pkg) { prop_array_t array; @@ -338,14 +342,14 @@ xbps_pkg_has_rundeps(prop_dictionary_t pkg) return false; } -void SYMEXPORT +void xbps_set_rootdir(const char *dir) { assert(dir != NULL); rootdir = dir; } -const char SYMEXPORT * +const char * xbps_get_rootdir(void) { if (rootdir == NULL) @@ -354,7 +358,7 @@ xbps_get_rootdir(void) return rootdir; } -void SYMEXPORT +void xbps_set_cachedir(const char *dir) { static char res[PATH_MAX]; @@ -371,7 +375,7 @@ xbps_set_cachedir(const char *dir) cachedir = res; } -const char SYMEXPORT * +const char * xbps_get_cachedir(void) { static char res[PATH_MAX]; @@ -388,19 +392,19 @@ xbps_get_cachedir(void) return cachedir; } -void SYMEXPORT +void xbps_set_flags(int lflags) { flags = lflags; } -int SYMEXPORT +int xbps_get_flags(void) { return flags; } -char SYMEXPORT * +char * xbps_xasprintf(const char *fmt, ...) { va_list ap; @@ -414,32 +418,6 @@ xbps_xasprintf(const char *fmt, ...) return buf; } -bool SYMEXPORT -xbps_yesno(const char *fmt, ...) -{ - va_list ap; - bool res; - - va_start(ap, fmt); - res = question(1, fmt, ap); - va_end(ap); - - return res; -} - -bool SYMEXPORT -xbps_noyes(const char *fmt, ...) -{ - va_list ap; - bool res; - - va_start(ap, fmt); - res = question(0, fmt, ap); - va_end(ap); - - return res; -} - static char * strtrim(char *str) { @@ -489,3 +467,29 @@ question(bool preset, const char *fmt, va_list ap) } return false; } + +bool +xbps_yesno(const char *fmt, ...) +{ + va_list ap; + bool res; + + va_start(ap, fmt); + res = question(1, fmt, ap); + va_end(ap); + + return res; +} + +bool +xbps_noyes(const char *fmt, ...) +{ + va_list ap; + bool res; + + va_start(ap, fmt); + res = question(0, fmt, ap); + va_end(ap); + + return res; +} diff --git a/vars.mk b/vars.mk index 15944507..eb63d782 100644 --- a/vars.mk +++ b/vars.mk @@ -22,7 +22,7 @@ WARNFLAGS = -pedantic -std=c99 -Wall -Wextra -Werror -Wshadow -Wformat=2 WARNFLAGS += -Wmissing-declarations -Wcomment -Wunused-macros -Wendif-labels WARNFLAGS += -Wcast-qual -Wcast-align -Wstack-protector CFLAGS = $(DEBUG_FLAGS) $(WARNFLAGS) -fPIC -DPIC -fstack-protector-all -SHAREDLIB_CFLAGS = -fvisibility=hidden +SHAREDLIB_CFLAGS = -fvisibility=default # Grr, hate the static libs! STATIC_LIBS = -lprop -lpthread -larchive -lssl -lcrypto -ldl -lacl