#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include #include #include #include #include "zpm.h" #include "t/ctap/ctap.h" #include "lib/jsw/jsw_atree.h" struct config { char *dbfile; char *pkgid; int plan; int ran; int failed; int quiet; int skipuninstalled; int failed_only; int tap; int check_owner; int check_group; int check_perms; int check_content; /* ignored for config files */ int check_mtime; }; static void usage() { printf("usage: zpm verify [-f file] -eF [pkgid ...]\n"); } static char *column(char *col, int ncols, char **vals, char **cols) { int i = 0; char *val = NULL; for (i=0; i < ncols; i++) { if (!strcmp(col, cols[i])) { val = vals[i]; break; } } return val; } static int count_plan(void *f, int ncols, char **vals, char **cols) { struct config *conf = f; int ftype, configfile = 0; char *v; v = column("filetype", ncols, vals, cols); ftype = *v; v = column("configuration", ncols, vals, cols); if (*v == '1') { configfile = 1; } if (ftype == 'r' && !configfile) { conf->plan++; } conf->plan++; return 0; } static int verify(void *f, int ncols, char **vals, char **cols) { struct config *conf = f; char *path; struct stat st; int rv; int ftype, configfile = 0; char *v, *hash, ehash[ZPM_HASH_STRLEN+1]; path = column("path", ncols, vals, cols); hash = column("hash", ncols, vals, cols); v = column("filetype", ncols, vals, cols); ftype = *v; v = column("configuration", ncols, vals, cols); if (*v == '1') { configfile = 1; } conf->ran++; rv = lstat(path, &st); if (rv == -1) { switch (errno) { case ENOENT: ok(0, "%s does not exist", path); conf->failed++; break; default: ok(0, "%s%scannot stat %s: %s", conf->pkgid ? conf->pkgid : "", conf->pkgid ? " " : "", path, strerror(errno)); conf->failed++; break; } if (ftype == 'r' && !configfile) { skip("no hash"); } return 0; } if (!conf->failed_only) { ok(1, "%s%s%s exists", conf->pkgid ? conf->pkgid : "", conf->pkgid ? " " : "", path); } if (ftype != 'r') { return 0; } if (ftype == 'r' && !configfile) { zpm_hash(path, ehash, 0); rv = strcmp(ehash, hash); if (rv != 0) { conf->failed++; } if (rv != 0 || !conf->failed_only) { is_string(ehash, hash, "%s%shash %s", conf->pkgid ? conf->pkgid : "", conf->pkgid ? " " : "", path); } } return 0; } static int afind_strcmp(const void *a, const void *b) { return strcmp(a, b); } int main(int ac, char **av) { struct zpm pkg; char *s; int opt; char *pkgid; jsw_atree_t *pkglist; jsw_atrav_t *list; int i, errors = 0; struct config conf = { 0 }; /* TODO could do nothing for the dup */ pkglist = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); conf.dbfile = "/var/lib/zpm/local.db"; if ((s = getenv("ZPMDB"))) { /* TODO does this need to be copied ? */ conf.dbfile = s; } while ((opt = getopt(ac, av, "f:eF")) != -1) { switch (opt) { case 'f': conf.dbfile = optarg; break; case 'e': conf.skipuninstalled = 1; break; case 'F': conf.failed_only = 1; break; default: usage(); exit(EXIT_FAILURE); break; } } int argn = optind; if (!zpm_open(&pkg, conf.dbfile)) { fprintf(stderr, "can't open zpm db %s\n", conf.dbfile); exit(EXIT_FAILURE); } char *errmsg = 0; if (argn < ac) { for (i = argn; i < ac; i++) { pkgid = zpm_findpkg(&pkg, av[i], "status = 'installed'"); if (!pkgid) { if (conf.skipuninstalled) { continue; } fprintf(stderr, "no installed package: %s\n", av[i]); errors++; free(pkgid); pkgid = 0; continue; } if (!jsw_ainsert(pkglist, pkgid)) { fprintf(stderr, "pkglist insert failed\n"); exit(EXIT_FAILURE); } free(pkgid); } } else { fprintf(stderr, "must specify pkgid\n"); usage(); exit(EXIT_FAILURE); } list = jsw_atnew(); for (pkgid = jsw_atfirst(list, pkglist); pkgid; pkgid = jsw_atnext(list)) { conf.pkgid = pkgid; if (!zpm_foreach_path(&pkg, pkgid, 0, count_plan, &conf, &errmsg)) { if (errmsg) { fprintf(stderr, "database error: %s\n", errmsg); exit(EXIT_FAILURE); } if (pkg.error == 1) { fprintf(stderr, "unable to allocate memory\n"); } exit(EXIT_FAILURE); } } if (errors) { exit(EXIT_FAILURE); } plan(conf.plan); list = jsw_atnew(); for (pkgid = jsw_atfirst(list, pkglist); pkgid; pkgid = jsw_atnext(list)) { conf.pkgid = pkgid; if (!zpm_foreach_path(&pkg, pkgid, 0, verify, &conf, &errmsg)) { if (errmsg) { fprintf(stderr, "database error: %s\n", errmsg); exit(EXIT_FAILURE); } if (pkg.error == 1) { fprintf(stderr, "unable to allocate memory\n"); } exit(EXIT_FAILURE); } } if (pkglist) jsw_adelete(pkglist); zpm_close(&pkg); return conf.failed ? 1 : 0; }