diff --git a/bin/xbps-bin/check.c b/bin/xbps-bin/check.c index 7d63cd1e..7c9395fb 100644 --- a/bin/xbps-bin/check.c +++ b/bin/xbps-bin/check.c @@ -35,54 +35,67 @@ #include #include "defs.h" +struct checkpkg { + size_t npkgs; + size_t nbrokenpkgs; +}; + +static int +cb_pkg_integrity(prop_object_t obj, void *arg, bool *done) +{ + struct checkpkg *cpkg = arg; + const char *pkgname, *version; + + (void)done; + + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + prop_dictionary_get_cstring_nocopy(obj, "version", &version); + printf("Checking %s-%s ...\n", pkgname, version); + if (check_pkg_integrity(obj, pkgname) != 0) + cpkg->nbrokenpkgs++; + + cpkg->npkgs++; + return 0; +} + int check_pkg_integrity_all(void) { - const struct xbps_handle *xhp; - prop_array_t regpkgs; - prop_object_t obj; - const char *pkgname, *version; - size_t i, npkgs = 0, nbrokenpkgs = 0; + struct checkpkg *cpkg; - xhp = xbps_handle_get(); - regpkgs = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages"); - if (prop_object_type(regpkgs) != PROP_TYPE_ARRAY) - return 0; + cpkg = calloc(1, sizeof(*cpkg)); + if (cpkg == NULL) + return ENOMEM; - for (i = 0; i < prop_array_count(regpkgs); i++) { - obj = prop_array_get(regpkgs, i); - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - printf("Checking %s-%s ...\n", pkgname, version); - if (check_pkg_integrity(pkgname) != 0) - nbrokenpkgs++; - - npkgs++; - } - printf("%zu package%s processed: %zu broken.\n", npkgs, - npkgs == 1 ? "" : "s", nbrokenpkgs); + (void)xbps_regpkgdb_foreach_pkg_cb(cb_pkg_integrity, cpkg); + printf("%zu package%s processed: %zu broken.\n", cpkg->npkgs, + cpkg->npkgs == 1 ? "" : "s", cpkg->nbrokenpkgs); + free(cpkg); return 0; } int -check_pkg_integrity(const char *pkgname) +check_pkg_integrity(prop_dictionary_t pkgd, const char *pkgname) { - prop_dictionary_t pkgd, propsd, filesd; + prop_dictionary_t opkgd, propsd, filesd; int rv = 0; bool broken = false; - propsd = filesd = NULL; + propsd = filesd = opkgd = NULL; /* find real pkg by name */ - pkgd = xbps_find_pkg_dict_installed(pkgname, false); if (pkgd == NULL) { - /* find virtual pkg by name */ - pkgd = xbps_find_virtualpkg_dict_installed(pkgname, false); - } - if (pkgd == NULL) { - printf("Package %s is not installed.\n", pkgname); - return 0; + opkgd = xbps_find_pkg_dict_installed(pkgname, false); + if (opkgd == NULL) { + /* find virtual pkg by name */ + pkgd = xbps_find_virtualpkg_dict_installed(pkgname, + false); + } + if (opkgd == NULL) { + printf("Package %s is not installed.\n", pkgname); + return 0; + } } /* * Check for props.plist metadata file. @@ -115,16 +128,16 @@ check_pkg_integrity(const char *pkgname) goto out; } -#define RUN_PKG_CHECK(name) \ -do { \ - rv = check_pkg_##name(pkgd, propsd, filesd); \ - if (rv) \ - broken = true; \ - else if (rv == -1) { \ - xbps_error_printf("%s: the %s test " \ - "returned error!\n", pkgname, #name); \ - goto out; \ - } \ +#define RUN_PKG_CHECK(name) \ +do { \ + rv = check_pkg_##name(pkgd ? pkgd : opkgd, propsd, filesd); \ + if (rv) \ + broken = true; \ + else if (rv == -1) { \ + xbps_error_printf("%s: the %s test " \ + "returned error!\n", pkgname, #name); \ + goto out; \ + } \ } while (0) /* Execute pkg checks */ @@ -141,8 +154,8 @@ out: prop_object_release(filesd); if (prop_object_type(propsd) == PROP_TYPE_DICTIONARY) prop_object_release(propsd); - if (prop_object_type(pkgd) == PROP_TYPE_DICTIONARY) - prop_object_release(pkgd); + if (prop_object_type(opkgd) == PROP_TYPE_DICTIONARY) + prop_object_release(opkgd); if (broken) return 1; diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index 05ef6eff..59b1d310 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -56,7 +56,7 @@ int exec_transaction(bool, bool); int remove_installed_pkgs(int, char **, bool, bool, bool, bool); /* from check.c */ -int check_pkg_integrity(const char *); +int check_pkg_integrity(prop_dictionary_t, const char *); int check_pkg_integrity_all(void); #define CHECK_PKG_DECL(type) \ diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 013bfaa2..264c64d5 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -295,7 +295,7 @@ main(int argc, char **argv) if (strcasecmp(argv[1], "all") == 0) rv = check_pkg_integrity_all(); else - rv = check_pkg_integrity(argv[1]); + rv = check_pkg_integrity(NULL, argv[1]); } else if (strcasecmp(argv[0], "autoupdate") == 0) { /* diff --git a/include/xbps_api.h b/include/xbps_api.h index d0118c13..03fe45b0 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -56,8 +56,8 @@ */ #define XBPS_PKGINDEX_VERSION "1.3" -#define XBPS_API_VERSION "20111219" -#define XBPS_VERSION "0.11.0" +#define XBPS_API_VERSION "20111222" +#define XBPS_VERSION "0.12" /** * @def XBPS_RELVER @@ -419,7 +419,7 @@ struct xbps_handle { */ cfg_t *cfg; /** - * @var regpkgdb_dictionary. + * @private regpkgdb_dictionary. * * Internalized proplib dictionary with the registed package database * stored in XBPS_META_PATH/XBPS_REGPKGDB. @@ -545,13 +545,8 @@ struct xbps_handle { * Initialize the XBPS library with the following steps: * * - Set function callbacks for fetching and unpacking. - * - Set root directory (if not set, defaults to /). - * - Set cache directory (if not set, defaults to XBPS_CACHE_PATH). - * - Set global flags. * - Set default cache connections for libfetch. - * - Initialize the debug printfs. - * - Internalize the proplib dictionary in config file. - * - Internalize the regpkgdb dictionary (if available). + * - Parse configuration file. * * @param[in] xhp Pointer to an xbps_handle structure, as returned by * \a xbps_handle_alloc(). @@ -769,6 +764,19 @@ int xbps_callback_array_iter_reverse_in_dict(prop_dictionary_t dict, int (*fn)(prop_object_t, void *, bool *), void *arg); +/** + * Executes a function callback per a package dictionary registered + * in "regpkgdb" plist. + * + * @param[in] fn Function callback to run for any pkg dictionary. + * @param[in] arg Argument to be passed to the function callback. + * + * @return 0 on success (all objects were processed), otherwise an + * errno value. + */ +int xbps_regpkgdb_foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *), + void *arg); + /** * Finds the proplib's dictionary associated with a package, by looking * it via its name in a proplib dictionary. diff --git a/lib/regpkgdb_dictionary.c b/lib/regpkgdb_dictionary.c index b74b15ac..d8f4a847 100644 --- a/lib/regpkgdb_dictionary.c +++ b/lib/regpkgdb_dictionary.c @@ -100,3 +100,31 @@ xbps_regpkgdb_dictionary_release(void) regpkgdb_initialized = false; xbps_dbg_printf("[regpkgdb] released ok.\n"); } + +int +xbps_regpkgdb_foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *), + void *arg) +{ + prop_array_t array; + prop_object_t obj; + struct xbps_handle *xhp = xbps_handle_get(); + size_t i; + int rv; + bool done = false; + + /* initialize regpkgdb */ + if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0) + return rv; + + array = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages"); + if (prop_object_type(array) != PROP_TYPE_ARRAY) + return EINVAL; + + for (i = 0; i < prop_array_count(array); i++) { + obj = prop_array_get(array, i); + rv = (*fn)(obj, arg, &done); + if (rv != 0 || done) + break; + } + return rv; +}