xbps-pkgdb: simplify the check code; make the reqby check work again.

This commit is contained in:
Juan RP 2012-11-17 17:43:54 +01:00
parent fcdb6b0930
commit e763f154a0
8 changed files with 70 additions and 146 deletions

View File

@ -38,7 +38,6 @@ struct checkpkg {
size_t totalpkgs; size_t totalpkgs;
size_t npkgs; size_t npkgs;
size_t nbrokenpkgs; size_t nbrokenpkgs;
bool flush;
}; };
static int static int
@ -49,19 +48,18 @@ cb_pkg_integrity(struct xbps_handle *xhp,
{ {
struct checkpkg *cpkg = arg; struct checkpkg *cpkg = arg;
const char *pkgname, *version; const char *pkgname, *version;
bool flush = false;
(void)done; (void)done;
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(obj, "version", &version); prop_dictionary_get_cstring_nocopy(obj, "version", &version);
printf("[%zu/%zu] checking %s-%s ...\n", printf("[%zu/%zu] checking %s-%s ...\n",
cpkg->npkgs, cpkg->totalpkgs, pkgname, version); cpkg->npkgs, cpkg->totalpkgs, pkgname, version);
if (check_pkg_integrity(xhp, obj, pkgname, false, &flush) != 0)
if (check_pkg_integrity(xhp, obj, pkgname) != 0)
cpkg->nbrokenpkgs++; cpkg->nbrokenpkgs++;
if (flush && !cpkg->flush)
cpkg->flush = flush;
cpkg->npkgs++; cpkg->npkgs++;
return 0; return 0;
} }
@ -78,13 +76,11 @@ check_pkg_integrity_all(struct xbps_handle *xhp)
cpkg.totalpkgs = prop_array_count(xhp->pkgdb); cpkg.totalpkgs = prop_array_count(xhp->pkgdb);
(void)xbps_pkgdb_foreach_cb(xhp, cb_pkg_integrity, &cpkg); (void)xbps_pkgdb_foreach_cb(xhp, cb_pkg_integrity, &cpkg);
if (cpkg.flush) {
if ((rv = xbps_pkgdb_update(xhp, true)) != 0) { if ((rv = xbps_pkgdb_update(xhp, true)) != 0) {
xbps_error_printf("failed to write pkgdb: %s\n", xbps_error_printf("failed to write pkgdb: %s\n",
strerror(rv)); strerror(rv));
return rv; return rv;
} }
}
printf("%zu package%s processed: %zu broken.\n", cpkg.npkgs, printf("%zu package%s processed: %zu broken.\n", cpkg.npkgs,
cpkg.npkgs == 1 ? "" : "s", cpkg.nbrokenpkgs); cpkg.npkgs == 1 ? "" : "s", cpkg.nbrokenpkgs);
return 0; return 0;
@ -93,15 +89,12 @@ check_pkg_integrity_all(struct xbps_handle *xhp)
int int
check_pkg_integrity(struct xbps_handle *xhp, check_pkg_integrity(struct xbps_handle *xhp,
prop_dictionary_t pkgd, prop_dictionary_t pkgd,
const char *pkgname, const char *pkgname)
bool flush,
bool *setflush)
{ {
prop_dictionary_t opkgd, propsd; prop_dictionary_t opkgd, propsd;
const char *sha256; const char *sha256;
char *buf; char *buf;
int rv = 0; int rv = 0;
bool pkgdb_update = false, broken = false;
propsd = opkgd = NULL; propsd = opkgd = NULL;
@ -127,14 +120,13 @@ check_pkg_integrity(struct xbps_handle *xhp,
printf("%s: unexistent metafile, converting to 0.18 " printf("%s: unexistent metafile, converting to 0.18 "
"format...\n", pkgname); "format...\n", pkgname);
if ((rv = convert_pkgd_metadir(xhp, opkgd)) != 0) if ((rv = convert_pkgd_metadir(xhp, opkgd)) != 0)
goto out; return rv;
return 0;
pkgdb_update = true;
goto out1;
} else if (prop_dictionary_count(propsd) == 0) { } else if (prop_dictionary_count(propsd) == 0) {
xbps_error_printf("%s: incomplete metadata file.\n", pkgname); xbps_error_printf("%s: incomplete metadata file.\n", pkgname);
broken = true; return 1;
goto out;
} }
prop_dictionary_get_cstring_nocopy(opkgd, "metafile-sha256", &sha256); prop_dictionary_get_cstring_nocopy(opkgd, "metafile-sha256", &sha256);
@ -144,47 +136,32 @@ check_pkg_integrity(struct xbps_handle *xhp,
rv = xbps_file_hash_check(buf, sha256); rv = xbps_file_hash_check(buf, sha256);
free(buf); free(buf);
if (rv == ERANGE) { if (rv == ERANGE) {
broken = true;
fprintf(stderr, "%s: metadata file has been " fprintf(stderr, "%s: metadata file has been "
"modified!\n", pkgname); "modified!\n", pkgname);
goto out; return 1;
} }
} }
#define RUN_PKG_CHECK(x, name, arg, arg2) \ #define RUN_PKG_CHECK(x, name, arg) \
do { \ do { \
rv = check_pkg_##name(x, pkgname, arg, arg2); \ rv = check_pkg_##name(x, pkgname, arg); \
if (rv) \ if (rv) \
broken = true; \ return rv; \
else if (rv == -1) { \ else if (rv == -1) { \
xbps_error_printf("%s: the %s test " \ xbps_error_printf("%s: the %s test " \
"returned error!\n", pkgname, #name); \ "returned error!\n", pkgname, #name); \
goto out; \ return rv; \
} \ } \
} while (0) } while (0)
/* Execute pkg checks */ /* Execute pkg checks */
RUN_PKG_CHECK(xhp, files, propsd, &pkgdb_update); RUN_PKG_CHECK(xhp, files, propsd);
RUN_PKG_CHECK(xhp, symlinks, propsd, &pkgdb_update); RUN_PKG_CHECK(xhp, symlinks, propsd);
RUN_PKG_CHECK(xhp, rundeps, propsd, &pkgdb_update); RUN_PKG_CHECK(xhp, rundeps, propsd);
RUN_PKG_CHECK(xhp, requiredby, opkgd, &pkgdb_update); RUN_PKG_CHECK(xhp, requiredby, opkgd);
RUN_PKG_CHECK(xhp, unneeded, opkgd, &pkgdb_update); RUN_PKG_CHECK(xhp, unneeded, opkgd);
out1:
if (flush && pkgdb_update) {
if (!xbps_pkgdb_replace_pkgd(xhp, opkgd, pkgname, false, true)) {
rv = EINVAL;
goto out;
}
}
if (setflush && pkgdb_update)
*setflush = true;
#undef RUN_PKG_CHECK #undef RUN_PKG_CHECK
out: return 0;
if (broken)
return 1;
return rv;
} }

View File

@ -46,10 +46,7 @@
* Return 0 if test ran successfully, 1 otherwise and -1 on error. * Return 0 if test ran successfully, 1 otherwise and -1 on error.
*/ */
int int
check_pkg_files(struct xbps_handle *xhp, check_pkg_files(struct xbps_handle *xhp, const char *pkgname, void *arg)
const char *pkgname,
void *arg,
bool *pkgdb_update)
{ {
prop_array_t array; prop_array_t array;
prop_object_t obj; prop_object_t obj;
@ -60,8 +57,6 @@ check_pkg_files(struct xbps_handle *xhp,
int rv = 0; int rv = 0;
bool mutable, broken = false, test_broken = false; bool mutable, broken = false, test_broken = false;
(void)pkgdb_update;
array = prop_dictionary_get(pkg_filesd, "files"); array = prop_dictionary_get(pkg_filesd, "files");
if (array != NULL && prop_array_count(array) > 0) { if (array != NULL && prop_array_count(array) > 0) {
iter = xbps_array_iter_from_dict(pkg_filesd, "files"); iter = xbps_array_iter_from_dict(pkg_filesd, "files");

View File

@ -34,31 +34,25 @@
#include <xbps_api.h> #include <xbps_api.h>
#include "defs.h" #include "defs.h"
struct check_reqby_data {
prop_dictionary_t pkgd;
prop_array_t pkgd_reqby;
const char *pkgname;
const char *pkgver;
bool pkgd_reqby_alloc;
};
static int static int
check_reqby_pkg_cb(struct xbps_handle *xhp, check_reqby_pkg_cb(struct xbps_handle *xhp,
prop_object_t obj, prop_object_t obj,
void *arg, void *arg,
bool *done) bool *done)
{ {
struct check_reqby_data *crd = arg; prop_dictionary_t pkgd = arg;
prop_array_t curpkg_rdeps, provides; prop_array_t curpkg_rdeps, provides, pkgd_reqby;
prop_dictionary_t curpkg_propsd; prop_dictionary_t curpkg_propsd;
prop_string_t curpkgver; prop_string_t curpkgver;
const char *curpkgn; const char *curpkgn, *pkgname, *pkgver;
(void)done; (void)done;
prop_dictionary_get_cstring_nocopy(pkgd, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &curpkgn); prop_dictionary_get_cstring_nocopy(obj, "pkgname", &curpkgn);
/* skip same pkg */ /* skip same pkg */
if (strcmp(curpkgn, crd->pkgname) == 0) if (strcmp(curpkgn, pkgname) == 0)
return 0; return 0;
/* /*
@ -80,13 +74,13 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
/* /*
* Check for pkgpattern match with real packages... * Check for pkgpattern match with real packages...
*/ */
if (!xbps_match_pkgdep_in_array(curpkg_rdeps, crd->pkgver)) { if (!xbps_match_pkgdep_in_array(curpkg_rdeps, pkgver)) {
/* /*
* ... otherwise check if package provides any virtual * ... otherwise check if package provides any virtual
* package and is matched against any object in * package and is matched against any object in
* run_depends. * run_depends.
*/ */
provides = prop_dictionary_get(obj, "provides"); provides = prop_dictionary_get(pkgd, "provides");
if (provides == NULL) { if (provides == NULL) {
/* doesn't provide any virtual pkg */ /* doesn't provide any virtual pkg */
return 0; return 0;
@ -97,14 +91,14 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
return 0; return 0;
} }
} }
crd->pkgd_reqby = prop_dictionary_get(crd->pkgd, "requiredby"); pkgd_reqby = prop_dictionary_get(pkgd, "requiredby");
curpkgver = prop_dictionary_get(curpkg_propsd, "pkgver"); curpkgver = prop_dictionary_get(curpkg_propsd, "pkgver");
if (crd->pkgd_reqby != NULL) { if (pkgd_reqby != NULL) {
/* /*
* Now check that current pkgver has been registered into * Now check that current pkgver has been registered into
* its requiredby array. * its requiredby array.
*/ */
if (xbps_match_string_in_array(crd->pkgd_reqby, if (xbps_match_string_in_array(pkgd_reqby,
prop_string_cstring_nocopy(curpkgver))) { prop_string_cstring_nocopy(curpkgver))) {
/* /*
* Current package already requires our package, * Current package already requires our package,
@ -116,55 +110,49 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
/* /*
* Missing requiredby array object, create it. * Missing requiredby array object, create it.
*/ */
crd->pkgd_reqby = prop_array_create(); pkgd_reqby = prop_array_create();
assert(crd->pkgd_reqby); assert(pkgd_reqby);
crd->pkgd_reqby_alloc = true;
} }
/* /*
* Added pkgdep into pkg's requiredby array. * Added pkgdep into pkg's requiredby array.
*/ */
if (!prop_array_add(crd->pkgd_reqby, curpkgver)) if (!prop_array_add(pkgd_reqby, curpkgver))
return -1; return -1;
printf("%s: added missing requiredby entry for %s.\n\n", printf("%s: added requiredby entry for %s.\n\n",
crd->pkgver, prop_string_cstring_nocopy(curpkgver)); pkgver, prop_string_cstring_nocopy(curpkgver));
return 1; return 0;
} }
/* /*
* Removes unused entries in pkg's requiredby array. * Removes unused entries in pkg's requiredby array.
*/ */
static bool static void
remove_stale_entries_in_reqby(struct xbps_handle *xhp, remove_stale_entries_in_reqby(struct xbps_handle *xhp, prop_dictionary_t pkgd)
struct check_reqby_data *crd)
{ {
prop_array_t reqby; prop_array_t reqby;
prop_dictionary_t pkgd; const char *str, *pkgver;
const char *str;
size_t i; size_t i;
bool needs_update = false;
reqby = prop_dictionary_get(crd->pkgd, "requiredby"); reqby = prop_dictionary_get(pkgd, "requiredby");
if (reqby == NULL || prop_array_count(reqby) == 0) if (reqby == NULL || prop_array_count(reqby) == 0)
return false; return;
crd->pkgd_reqby = prop_dictionary_get(crd->pkgd, "requiredby"); prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
for (i = 0; i < prop_array_count(reqby); i++) { for (i = 0; i < prop_array_count(reqby); i++) {
prop_array_get_cstring_nocopy(reqby, i, &str); prop_array_get_cstring_nocopy(reqby, i, &str);
if ((pkgd = xbps_pkgdb_get_pkgd_by_pkgver(xhp, str)) != NULL) if ((pkgd = xbps_pkgdb_get_pkgd_by_pkgver(xhp, str)) != NULL)
continue; continue;
printf("%s: found stale entry in requiredby `%s' (fixed)\n",
crd->pkgver, str); if (!xbps_remove_string_from_array(xhp, reqby, str))
if (xbps_remove_string_from_array(xhp, crd->pkgd_reqby, str)) fprintf(stderr, "%s: failed to remove %s from "
needs_update = true; "requiredby!\n", pkgver, str);
else
printf("%s: removed stale entry in requiredby `%s'\n",
pkgver, str);
} }
if (needs_update) {
prop_dictionary_set(crd->pkgd, "requiredby", crd->pkgd_reqby);
return true;
}
return false;
} }
/* /*
@ -177,36 +165,20 @@ remove_stale_entries_in_reqby(struct xbps_handle *xhp,
* Returns 0 if test ran successfully, 1 otherwise and -1 on error. * Returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/ */
int int
check_pkg_requiredby(struct xbps_handle *xhp, check_pkg_requiredby(struct xbps_handle *xhp, const char *pkgname, void *arg)
const char *pkgname,
void *arg,
bool *pkgdb_update)
{ {
prop_dictionary_t pkgd = arg; prop_dictionary_t pkgd = arg;
struct check_reqby_data crd;
int rv; int rv;
crd.pkgd = pkgd; (void)pkgname;
crd.pkgd_reqby = NULL;
crd.pkgd_reqby_alloc = false;
crd.pkgname = pkgname;
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &crd.pkgver);
/* missing reqby entries in pkgs */ /* missing reqby entries in pkgs */
rv = xbps_pkgdb_foreach_cb(xhp, check_reqby_pkg_cb, &crd); rv = xbps_pkgdb_foreach_cb(xhp, check_reqby_pkg_cb, pkgd);
if (rv < 0) { if (rv != 0)
return rv; return rv;
} else if (rv == 1) {
*pkgdb_update = true;
prop_dictionary_set(pkgd, "requiredby", crd.pkgd_reqby);
if (crd.pkgd_reqby_alloc)
prop_object_release(crd.pkgd_reqby);
printf("%s: requiredby fix done!\n\n", crd.pkgver);
}
/* remove stale entries in pkg's reqby */ /* remove stale entries in pkg's reqby */
if (remove_stale_entries_in_reqby(xhp, &crd)) remove_stale_entries_in_reqby(xhp, pkgd);
*pkgdb_update = true;
return 0; return 0;
} }

View File

@ -45,10 +45,7 @@
*/ */
int int
check_pkg_rundeps(struct xbps_handle *xhp, check_pkg_rundeps(struct xbps_handle *xhp, const char *pkgname, void *arg)
const char *pkgname,
void *arg,
bool *pkgdb_update)
{ {
prop_dictionary_t pkg_propsd = arg; prop_dictionary_t pkg_propsd = arg;
prop_object_t obj; prop_object_t obj;
@ -56,8 +53,6 @@ check_pkg_rundeps(struct xbps_handle *xhp,
const char *reqpkg; const char *reqpkg;
bool test_broken = false; bool test_broken = false;
(void)pkgdb_update;
if (!xbps_pkg_has_rundeps(pkg_propsd)) if (!xbps_pkg_has_rundeps(pkg_propsd))
return 0; return 0;

View File

@ -46,10 +46,7 @@
* returns 0 if test ran successfully, 1 otherwise and -1 on error. * returns 0 if test ran successfully, 1 otherwise and -1 on error.
*/ */
int int
check_pkg_symlinks(struct xbps_handle *xhp, check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg)
const char *pkgname,
void *arg,
bool *pkgdb_update)
{ {
prop_array_t array; prop_array_t array;
prop_object_t obj; prop_object_t obj;
@ -59,8 +56,6 @@ check_pkg_symlinks(struct xbps_handle *xhp,
char *path, *buf, *buf2, *buf3, *dname, *path_target; char *path, *buf, *buf2, *buf3, *dname, *path_target;
bool broken = false, test_broken = false; bool broken = false, test_broken = false;
(void)pkgdb_update;
array = prop_dictionary_get(pkg_filesd, "links"); array = prop_dictionary_get(pkg_filesd, "links");
if ((prop_object_type(array) == PROP_TYPE_ARRAY) && if ((prop_object_type(array) == PROP_TYPE_ARRAY) &&
prop_array_count(array) > 0) { prop_array_count(array) > 0) {

View File

@ -43,23 +43,18 @@
* and remove them if that was true. * and remove them if that was true.
*/ */
int int
check_pkg_unneeded(struct xbps_handle *xhp, check_pkg_unneeded(struct xbps_handle *xhp, const char *pkgname, void *arg)
const char *pkgname,
void *arg,
bool *pkgdb_update)
{ {
prop_dictionary_t pkgd = arg; prop_dictionary_t pkgd = arg;
(void)pkgname;
(void)xhp; (void)xhp;
(void)pkgname;
if (prop_dictionary_get(pkgd, "remove-and-update")) { if (prop_dictionary_get(pkgd, "remove-and-update"))
*pkgdb_update = true;
prop_dictionary_remove(pkgd, "remove-and-update"); prop_dictionary_remove(pkgd, "remove-and-update");
}
if (prop_dictionary_get(pkgd, "transaction")) { if (prop_dictionary_get(pkgd, "transaction"))
*pkgdb_update = true;
prop_dictionary_remove(pkgd, "transaction"); prop_dictionary_remove(pkgd, "transaction");
}
return 0; return 0;
} }

View File

@ -30,15 +30,11 @@
#include <xbps_api.h> #include <xbps_api.h>
/* from check.c */ /* from check.c */
int check_pkg_integrity(struct xbps_handle *, int check_pkg_integrity(struct xbps_handle *, prop_dictionary_t, const char *);
prop_dictionary_t,
const char *,
bool,
bool *);
int check_pkg_integrity_all(struct xbps_handle *); int check_pkg_integrity_all(struct xbps_handle *);
#define CHECK_PKG_DECL(type) \ #define CHECK_PKG_DECL(type) \
int check_pkg_##type (struct xbps_handle *, const char *, void *, bool *) int check_pkg_##type (struct xbps_handle *, const char *, void *)
CHECK_PKG_DECL(unneeded); CHECK_PKG_DECL(unneeded);
CHECK_PKG_DECL(files); CHECK_PKG_DECL(files);

View File

@ -115,8 +115,7 @@ main(int argc, char **argv)
rv = check_pkg_integrity_all(&xh); rv = check_pkg_integrity_all(&xh);
} else { } else {
for (i = optind; i < argc; i++) { for (i = optind; i < argc; i++) {
rv = check_pkg_integrity(&xh, NULL, argv[i], rv = check_pkg_integrity(&xh, NULL, argv[i]);
true, NULL);
if (rv != 0) if (rv != 0)
fprintf(stderr, "Failed to check " fprintf(stderr, "Failed to check "
"`%s': %s\n", argv[i], strerror(rv)); "`%s': %s\n", argv[i], strerror(rv));