#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include #include #include #include #include "zpm.h" #include "t/ctap/ctap.h" struct config { char *dbfile; int plan; int ran; int failed; int quiet; 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 foreach-path [-fncC] args ...\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); break; default: ok(0, "cannot stat %s: %s", path, strerror(errno)); conf->failed++; break; } if (ftype == 'r' && !configfile) { skip("no hash"); } return 0; } ok(1, "%s exists", path); if (ftype == 'r' && !configfile) { zpm_hash(path, ehash, 0); if (!is_string(ehash, hash, "hash %s", path)) { conf->failed++; } } return 0; } int main(int ac, char **av) { struct zpm pkg; char *s; int opt; char *pkgid; struct config conf = { 0 }; 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:")) != -1) { switch (opt) { case 'f': conf.dbfile = optarg; 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) { pkgid = av[argn]; argn++; } else { fprintf(stderr, "must specify pkgid\n"); usage(); exit(EXIT_FAILURE); } /* TODO lookup pkgid via zpm-findpkg equivalent */ 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"); } fprintf(stderr, "unable to plan\n"); exit(EXIT_FAILURE); } plan(conf.plan); 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); } zpm_close(&pkg); return conf.failed ? 1 : 0; }