xbps-pkgdb: simplify the check code; make the reqby check work again.
This commit is contained in:
parent
fcdb6b0930
commit
e763f154a0
@ -38,7 +38,6 @@ struct checkpkg {
|
||||
size_t totalpkgs;
|
||||
size_t npkgs;
|
||||
size_t nbrokenpkgs;
|
||||
bool flush;
|
||||
};
|
||||
|
||||
static int
|
||||
@ -49,19 +48,18 @@ cb_pkg_integrity(struct xbps_handle *xhp,
|
||||
{
|
||||
struct checkpkg *cpkg = arg;
|
||||
const char *pkgname, *version;
|
||||
bool flush = false;
|
||||
|
||||
(void)done;
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
|
||||
|
||||
printf("[%zu/%zu] checking %s-%s ...\n",
|
||||
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++;
|
||||
|
||||
if (flush && !cpkg->flush)
|
||||
cpkg->flush = flush;
|
||||
cpkg->npkgs++;
|
||||
return 0;
|
||||
}
|
||||
@ -78,12 +76,10 @@ check_pkg_integrity_all(struct xbps_handle *xhp)
|
||||
cpkg.totalpkgs = prop_array_count(xhp->pkgdb);
|
||||
|
||||
(void)xbps_pkgdb_foreach_cb(xhp, cb_pkg_integrity, &cpkg);
|
||||
if (cpkg.flush) {
|
||||
if ((rv = xbps_pkgdb_update(xhp, true)) != 0) {
|
||||
xbps_error_printf("failed to write pkgdb: %s\n",
|
||||
strerror(rv));
|
||||
return rv;
|
||||
}
|
||||
if ((rv = xbps_pkgdb_update(xhp, true)) != 0) {
|
||||
xbps_error_printf("failed to write pkgdb: %s\n",
|
||||
strerror(rv));
|
||||
return rv;
|
||||
}
|
||||
printf("%zu package%s processed: %zu broken.\n", cpkg.npkgs,
|
||||
cpkg.npkgs == 1 ? "" : "s", cpkg.nbrokenpkgs);
|
||||
@ -93,15 +89,12 @@ check_pkg_integrity_all(struct xbps_handle *xhp)
|
||||
int
|
||||
check_pkg_integrity(struct xbps_handle *xhp,
|
||||
prop_dictionary_t pkgd,
|
||||
const char *pkgname,
|
||||
bool flush,
|
||||
bool *setflush)
|
||||
const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t opkgd, propsd;
|
||||
const char *sha256;
|
||||
char *buf;
|
||||
int rv = 0;
|
||||
bool pkgdb_update = false, broken = false;
|
||||
|
||||
propsd = opkgd = NULL;
|
||||
|
||||
@ -127,14 +120,13 @@ check_pkg_integrity(struct xbps_handle *xhp,
|
||||
printf("%s: unexistent metafile, converting to 0.18 "
|
||||
"format...\n", pkgname);
|
||||
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) {
|
||||
xbps_error_printf("%s: incomplete metadata file.\n", pkgname);
|
||||
broken = true;
|
||||
goto out;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
free(buf);
|
||||
if (rv == ERANGE) {
|
||||
broken = true;
|
||||
fprintf(stderr, "%s: metadata file has been "
|
||||
"modified!\n", pkgname);
|
||||
goto out;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define RUN_PKG_CHECK(x, name, arg, arg2) \
|
||||
#define RUN_PKG_CHECK(x, name, arg) \
|
||||
do { \
|
||||
rv = check_pkg_##name(x, pkgname, arg, arg2); \
|
||||
rv = check_pkg_##name(x, pkgname, arg); \
|
||||
if (rv) \
|
||||
broken = true; \
|
||||
return rv; \
|
||||
else if (rv == -1) { \
|
||||
xbps_error_printf("%s: the %s test " \
|
||||
"returned error!\n", pkgname, #name); \
|
||||
goto out; \
|
||||
return rv; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Execute pkg checks */
|
||||
RUN_PKG_CHECK(xhp, files, propsd, &pkgdb_update);
|
||||
RUN_PKG_CHECK(xhp, symlinks, propsd, &pkgdb_update);
|
||||
RUN_PKG_CHECK(xhp, rundeps, propsd, &pkgdb_update);
|
||||
RUN_PKG_CHECK(xhp, requiredby, opkgd, &pkgdb_update);
|
||||
RUN_PKG_CHECK(xhp, unneeded, opkgd, &pkgdb_update);
|
||||
|
||||
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;
|
||||
RUN_PKG_CHECK(xhp, files, propsd);
|
||||
RUN_PKG_CHECK(xhp, symlinks, propsd);
|
||||
RUN_PKG_CHECK(xhp, rundeps, propsd);
|
||||
RUN_PKG_CHECK(xhp, requiredby, opkgd);
|
||||
RUN_PKG_CHECK(xhp, unneeded, opkgd);
|
||||
|
||||
#undef RUN_PKG_CHECK
|
||||
|
||||
out:
|
||||
if (broken)
|
||||
return 1;
|
||||
|
||||
return rv;
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,10 +46,7 @@
|
||||
* Return 0 if test ran successfully, 1 otherwise and -1 on error.
|
||||
*/
|
||||
int
|
||||
check_pkg_files(struct xbps_handle *xhp,
|
||||
const char *pkgname,
|
||||
void *arg,
|
||||
bool *pkgdb_update)
|
||||
check_pkg_files(struct xbps_handle *xhp, const char *pkgname, void *arg)
|
||||
{
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
@ -60,8 +57,6 @@ check_pkg_files(struct xbps_handle *xhp,
|
||||
int rv = 0;
|
||||
bool mutable, broken = false, test_broken = false;
|
||||
|
||||
(void)pkgdb_update;
|
||||
|
||||
array = prop_dictionary_get(pkg_filesd, "files");
|
||||
if (array != NULL && prop_array_count(array) > 0) {
|
||||
iter = xbps_array_iter_from_dict(pkg_filesd, "files");
|
||||
|
@ -34,31 +34,25 @@
|
||||
#include <xbps_api.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
|
||||
check_reqby_pkg_cb(struct xbps_handle *xhp,
|
||||
prop_object_t obj,
|
||||
void *arg,
|
||||
bool *done)
|
||||
{
|
||||
struct check_reqby_data *crd = arg;
|
||||
prop_array_t curpkg_rdeps, provides;
|
||||
prop_dictionary_t pkgd = arg;
|
||||
prop_array_t curpkg_rdeps, provides, pkgd_reqby;
|
||||
prop_dictionary_t curpkg_propsd;
|
||||
prop_string_t curpkgver;
|
||||
const char *curpkgn;
|
||||
const char *curpkgn, *pkgname, *pkgver;
|
||||
|
||||
(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);
|
||||
/* skip same pkg */
|
||||
if (strcmp(curpkgn, crd->pkgname) == 0)
|
||||
if (strcmp(curpkgn, pkgname) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -80,13 +74,13 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
|
||||
/*
|
||||
* 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
|
||||
* package and is matched against any object in
|
||||
* run_depends.
|
||||
*/
|
||||
provides = prop_dictionary_get(obj, "provides");
|
||||
provides = prop_dictionary_get(pkgd, "provides");
|
||||
if (provides == NULL) {
|
||||
/* doesn't provide any virtual pkg */
|
||||
return 0;
|
||||
@ -97,14 +91,14 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
|
||||
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");
|
||||
if (crd->pkgd_reqby != NULL) {
|
||||
if (pkgd_reqby != NULL) {
|
||||
/*
|
||||
* Now check that current pkgver has been registered into
|
||||
* 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))) {
|
||||
/*
|
||||
* Current package already requires our package,
|
||||
@ -116,55 +110,49 @@ check_reqby_pkg_cb(struct xbps_handle *xhp,
|
||||
/*
|
||||
* Missing requiredby array object, create it.
|
||||
*/
|
||||
crd->pkgd_reqby = prop_array_create();
|
||||
assert(crd->pkgd_reqby);
|
||||
crd->pkgd_reqby_alloc = true;
|
||||
pkgd_reqby = prop_array_create();
|
||||
assert(pkgd_reqby);
|
||||
}
|
||||
/*
|
||||
* Added pkgdep into pkg's requiredby array.
|
||||
*/
|
||||
if (!prop_array_add(crd->pkgd_reqby, curpkgver))
|
||||
if (!prop_array_add(pkgd_reqby, curpkgver))
|
||||
return -1;
|
||||
|
||||
printf("%s: added missing requiredby entry for %s.\n\n",
|
||||
crd->pkgver, prop_string_cstring_nocopy(curpkgver));
|
||||
printf("%s: added requiredby entry for %s.\n\n",
|
||||
pkgver, prop_string_cstring_nocopy(curpkgver));
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes unused entries in pkg's requiredby array.
|
||||
*/
|
||||
static bool
|
||||
remove_stale_entries_in_reqby(struct xbps_handle *xhp,
|
||||
struct check_reqby_data *crd)
|
||||
static void
|
||||
remove_stale_entries_in_reqby(struct xbps_handle *xhp, prop_dictionary_t pkgd)
|
||||
{
|
||||
prop_array_t reqby;
|
||||
prop_dictionary_t pkgd;
|
||||
const char *str;
|
||||
const char *str, *pkgver;
|
||||
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)
|
||||
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++) {
|
||||
prop_array_get_cstring_nocopy(reqby, i, &str);
|
||||
if ((pkgd = xbps_pkgdb_get_pkgd_by_pkgver(xhp, str)) != NULL)
|
||||
continue;
|
||||
printf("%s: found stale entry in requiredby `%s' (fixed)\n",
|
||||
crd->pkgver, str);
|
||||
if (xbps_remove_string_from_array(xhp, crd->pkgd_reqby, str))
|
||||
needs_update = true;
|
||||
|
||||
if (!xbps_remove_string_from_array(xhp, reqby, str))
|
||||
fprintf(stderr, "%s: failed to remove %s from "
|
||||
"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.
|
||||
*/
|
||||
int
|
||||
check_pkg_requiredby(struct xbps_handle *xhp,
|
||||
const char *pkgname,
|
||||
void *arg,
|
||||
bool *pkgdb_update)
|
||||
check_pkg_requiredby(struct xbps_handle *xhp, const char *pkgname, void *arg)
|
||||
{
|
||||
prop_dictionary_t pkgd = arg;
|
||||
struct check_reqby_data crd;
|
||||
int rv;
|
||||
|
||||
crd.pkgd = pkgd;
|
||||
crd.pkgd_reqby = NULL;
|
||||
crd.pkgd_reqby_alloc = false;
|
||||
crd.pkgname = pkgname;
|
||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &crd.pkgver);
|
||||
(void)pkgname;
|
||||
|
||||
/* missing reqby entries in pkgs */
|
||||
rv = xbps_pkgdb_foreach_cb(xhp, check_reqby_pkg_cb, &crd);
|
||||
if (rv < 0) {
|
||||
rv = xbps_pkgdb_foreach_cb(xhp, check_reqby_pkg_cb, pkgd);
|
||||
if (rv != 0)
|
||||
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 */
|
||||
if (remove_stale_entries_in_reqby(xhp, &crd))
|
||||
*pkgdb_update = true;
|
||||
remove_stale_entries_in_reqby(xhp, pkgd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -45,10 +45,7 @@
|
||||
*/
|
||||
|
||||
int
|
||||
check_pkg_rundeps(struct xbps_handle *xhp,
|
||||
const char *pkgname,
|
||||
void *arg,
|
||||
bool *pkgdb_update)
|
||||
check_pkg_rundeps(struct xbps_handle *xhp, const char *pkgname, void *arg)
|
||||
{
|
||||
prop_dictionary_t pkg_propsd = arg;
|
||||
prop_object_t obj;
|
||||
@ -56,8 +53,6 @@ check_pkg_rundeps(struct xbps_handle *xhp,
|
||||
const char *reqpkg;
|
||||
bool test_broken = false;
|
||||
|
||||
(void)pkgdb_update;
|
||||
|
||||
if (!xbps_pkg_has_rundeps(pkg_propsd))
|
||||
return 0;
|
||||
|
||||
|
@ -46,10 +46,7 @@
|
||||
* returns 0 if test ran successfully, 1 otherwise and -1 on error.
|
||||
*/
|
||||
int
|
||||
check_pkg_symlinks(struct xbps_handle *xhp,
|
||||
const char *pkgname,
|
||||
void *arg,
|
||||
bool *pkgdb_update)
|
||||
check_pkg_symlinks(struct xbps_handle *xhp, const char *pkgname, void *arg)
|
||||
{
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
@ -59,8 +56,6 @@ check_pkg_symlinks(struct xbps_handle *xhp,
|
||||
char *path, *buf, *buf2, *buf3, *dname, *path_target;
|
||||
bool broken = false, test_broken = false;
|
||||
|
||||
(void)pkgdb_update;
|
||||
|
||||
array = prop_dictionary_get(pkg_filesd, "links");
|
||||
if ((prop_object_type(array) == PROP_TYPE_ARRAY) &&
|
||||
prop_array_count(array) > 0) {
|
||||
|
@ -43,23 +43,18 @@
|
||||
* and remove them if that was true.
|
||||
*/
|
||||
int
|
||||
check_pkg_unneeded(struct xbps_handle *xhp,
|
||||
const char *pkgname,
|
||||
void *arg,
|
||||
bool *pkgdb_update)
|
||||
check_pkg_unneeded(struct xbps_handle *xhp, const char *pkgname, void *arg)
|
||||
{
|
||||
prop_dictionary_t pkgd = arg;
|
||||
|
||||
(void)pkgname;
|
||||
(void)xhp;
|
||||
(void)pkgname;
|
||||
|
||||
if (prop_dictionary_get(pkgd, "remove-and-update")) {
|
||||
*pkgdb_update = true;
|
||||
if (prop_dictionary_get(pkgd, "remove-and-update"))
|
||||
prop_dictionary_remove(pkgd, "remove-and-update");
|
||||
}
|
||||
if (prop_dictionary_get(pkgd, "transaction")) {
|
||||
*pkgdb_update = true;
|
||||
|
||||
if (prop_dictionary_get(pkgd, "transaction"))
|
||||
prop_dictionary_remove(pkgd, "transaction");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,15 +30,11 @@
|
||||
#include <xbps_api.h>
|
||||
|
||||
/* from check.c */
|
||||
int check_pkg_integrity(struct xbps_handle *,
|
||||
prop_dictionary_t,
|
||||
const char *,
|
||||
bool,
|
||||
bool *);
|
||||
int check_pkg_integrity(struct xbps_handle *, prop_dictionary_t, const char *);
|
||||
int check_pkg_integrity_all(struct xbps_handle *);
|
||||
|
||||
#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(files);
|
||||
|
@ -115,8 +115,7 @@ main(int argc, char **argv)
|
||||
rv = check_pkg_integrity_all(&xh);
|
||||
} else {
|
||||
for (i = optind; i < argc; i++) {
|
||||
rv = check_pkg_integrity(&xh, NULL, argv[i],
|
||||
true, NULL);
|
||||
rv = check_pkg_integrity(&xh, NULL, argv[i]);
|
||||
if (rv != 0)
|
||||
fprintf(stderr, "Failed to check "
|
||||
"`%s': %s\n", argv[i], strerror(rv));
|
||||
|
Loading…
Reference in New Issue
Block a user