X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-search.c;h=9b6ec887cd015f45b88f72e0de32df74d31303a2;hb=62f6ff407bc4f2cf03d1fa7cf3dc9a3f4026624a;hp=ff6d7301950ff3171c4cc1e69fe37a80b218adc0;hpb=c907b8ec08b06a4a256fd12b79b4bcf5088fbb19;p=zpackage diff --git a/zpm-search.c b/zpm-search.c index ff6d730..9b6ec88 100644 --- a/zpm-search.c +++ b/zpm-search.c @@ -17,8 +17,50 @@ struct pkgloc { char *id; char *file; int info; + int installed; }; +struct search_ctl { + char *localdb, *repodir, *pkgdir; + struct zpm *zpmdb; + glob_t repos; + int matchallpkgfile; + int matchinstalled; + int suppressinstalled; + int onlylocalinstalled; + int verbose; + int dbrepos; +}; + +char *pathcat(char *dir, char *path) { + size_t dirlen = 0, pathlen = 0; + char *cat; + + /* chop off trailing / on dir */ + if (dir) { + dirlen = strlen(dir); + while (dirlen && dir[dirlen-1] == '/') { + dirlen--; + } + } + + if (path) { + pathlen = strlen(path); + while (*path && *path == '/') { + path++; + pathlen--; + } + } + + cat = malloc(dirlen + pathlen + 2); + if (cat) { + strncpy(cat, dir, dirlen); + cat[dirlen] = '/'; + strcpy(cat+dirlen+1, path); + } + return cat; +} + char *checkfile(char *pkgstr, char *path) { struct zpm pkgfile; char *pkgid = 0; @@ -27,7 +69,7 @@ char *checkfile(char *pkgstr, char *path) { return NULL; } - pkgid = zpm_findpkg(&pkgfile, pkgstr, "hash is not null"); + pkgid = zpm_findpkg(&pkgfile, pkgstr, NULL); zpm_close(&pkgfile); return pkgid; @@ -41,7 +83,7 @@ char *checkfileforlib(char *soname, char *path) { return NULL; } - pkgid = zpm_findlib(&pkgfile, soname, "hash is not null"); + pkgid = zpm_findlib(&pkgfile, soname, NULL); if (pkgfile.error) { fprintf(stderr, "sql error: %s\n", pkgfile.errmsg); } @@ -50,89 +92,94 @@ char *checkfileforlib(char *soname, char *path) { return pkgid; } -int find_lib(char *soname, struct pkgloc *pkg) { +int find_globs(struct search_ctl *opt) { + glob_t *repos; + int rv; + + repos = &opt->repos; + repos->gl_offs = 0; + + int globopts = 0; + + if (opt->repodir) { + char *globstr = pathcat(opt->repodir, "*.repo"); + rv = glob(globstr, globopts, NULL, repos); + switch (rv) { + case GLOB_NOSPACE: + fprintf(stderr, "glob no mem\n"); + return 0; + case GLOB_ABORTED: + fprintf(stderr, "glob abort\n"); + return 0; + case GLOB_NOMATCH: + break; + case 0: + break; + default: + break; + } + globopts = GLOB_APPEND; + free(globstr); + } + + if (opt->pkgdir) { + char *globstr = pathcat(opt->pkgdir, "*.zpm"); + rv = glob(globstr, globopts, NULL, repos); + switch (rv) { + case GLOB_NOSPACE: + fprintf(stderr, "glob no mem\n"); + return 0; + case GLOB_ABORTED: + fprintf(stderr, "glob abort\n"); + return 0; + case GLOB_NOMATCH: + break; + case 0: + break; + default: + break; + } + free(globstr); + } + + return 1; +} + +int find_lib(char *soname, struct search_ctl *opt, struct pkgloc *pkg) { char *latest = 0; char *installed = 0, *found = 0; char *pkgfile = 0; int rv; - struct zpm localdb; - - if (zpm_open(&localdb, NULL)) { - installed = zpm_findlib(&localdb, soname, "status = 'installed'"); - zpm_close(&localdb); + unsigned int i; + if (opt->localdb) { + installed = zpm_findlib(opt->zpmdb, soname, "status = 'installed'"); if (installed) { + if (opt->verbose > 1) { + fprintf(stderr, "library %s installed via %s\n", soname, installed); + } /* we're done, the lib is installed */ return 2; } - } else { - fprintf(stderr, "can't open localdb\n"); } - glob_t repos; - repos.gl_offs = 0; - rv = glob("/var/lib/zpm/repos/*.repo", 0, NULL, &repos); - switch (rv) { - case GLOB_NOSPACE: - fprintf(stderr, "glob no mem\n"); - exit(EXIT_FAILURE); break; - case GLOB_ABORTED: - fprintf(stderr, "glob abort\n"); - exit(EXIT_FAILURE); break; - case GLOB_NOMATCH: - break; - case 0: - break; - default: - break; - } - - unsigned i; - for (i = 0; i < repos.gl_pathc; i++) { - found = checkfileforlib(soname, repos.gl_pathv[i]); - if (found) { - rv = zpm_vercmp(found, latest); - if (rv == 1) { - latest = found; - free(pkgfile); - pkgfile = strdup(repos.gl_pathv[i]); - } + for (i = 0; i < opt->repos.gl_pathc; i++) { + if (opt->verbose > 1) { + fprintf(stderr, "checking %s for %s\n", opt->repos.gl_pathv[i], soname); } - } - - globfree(&repos); - repos.gl_offs = 0; - - char *pkgdir = "/home/zoranix/zrepo/packages"; - char *pkgglob = 0; - - size_t globlen = strlen(pkgdir)+7; - pkgglob = malloc(globlen+1); - snprintf(pkgglob, globlen, "%s/*.zpm", pkgdir); - rv = glob(pkgglob, 0, NULL, &repos); - free(pkgglob); - - switch (rv) { - case GLOB_NOSPACE: - exit(EXIT_FAILURE); break; - case GLOB_ABORTED: - exit(EXIT_FAILURE); break; - case GLOB_NOMATCH: break; - case 0: - break; - default: - break; - } - - for (i = 0; i < repos.gl_pathc; i++) { - found = checkfileforlib(soname, repos.gl_pathv[i]); + found = checkfileforlib(soname, opt->repos.gl_pathv[i]); if (found) { + if (opt->verbose > 1) { + fprintf(stderr, "found %s\n", found); + } rv = zpm_vercmp(found, latest); if (rv == 1) { latest = found; free(pkgfile); - pkgfile = strdup(repos.gl_pathv[i]); + pkgfile = strdup(opt->repos.gl_pathv[i]); } + } else if (opt->verbose > 1) { + fprintf(stderr, "not found\n"); } } @@ -145,92 +192,51 @@ int find_lib(char *soname, struct pkgloc *pkg) { return 0; } -struct pkgloc *find_package(char *pkgstr) { +struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) { char *latest = 0; char *installed = 0, *found = 0; - char *pkgfile; + char *pkgfile = 0; struct pkgloc *pkg = 0; int rv; - struct zpm localdb; + unsigned int i; - if (zpm_open(&localdb, NULL)) { - installed = zpm_findpkg(&localdb, pkgstr, "status = 'installed'"); + if (opt->localdb) { + installed = zpm_findpkg(opt->zpmdb, pkgstr, "status = 'installed'"); if (installed) { latest = installed; + pkgfile = opt->zpmdb->path; } - found = zpm_findpkg(&localdb, pkgstr, NULL); - if (found) { - rv = zpm_vercmp(found, latest); - if (rv == 1) { - latest = found; - pkgfile = localdb.path; + if (!opt->onlylocalinstalled) { + found = zpm_findpkg(opt->zpmdb, pkgstr, NULL); + if (found) { + rv = zpm_vercmp(found, latest); + if (rv == 1) { + latest = found; + pkgfile = opt->zpmdb->path; + } } } - zpm_close(&localdb); - } else { - fprintf(stderr, "can't open localdb\n"); - } - glob_t repos; - repos.gl_offs = 0; - rv = glob("/var/lib/zpm/repos/*.repo", 0, NULL, &repos); - switch (rv) { - case GLOB_NOSPACE: - fprintf(stderr, "glob no mem\n"); - exit(EXIT_FAILURE); break; - case GLOB_ABORTED: - fprintf(stderr, "glob abort\n"); - exit(EXIT_FAILURE); break; - case GLOB_NOMATCH: - break; - case 0: - break; - default: - break; - } - - unsigned i; - for (i = 0; i < repos.gl_pathc; i++) { - found = checkfile(pkgstr, repos.gl_pathv[i]); - if (found) { - rv = zpm_vercmp(found, latest); - if (rv == 1) { - latest = found; - pkgfile = repos.gl_pathv[i]; - } +#if 0 + if (opt->dbrepos) { + zpm_foreach_repo(opt->zpmdb, search_repo, pkg) } +#endif } - globfree(&repos); - repos.gl_offs = 0; - - char *pkgdir = "/home/zoranix/zrepo/packages"; - char *pkgglob = 0; - - size_t globlen = strlen(pkgdir)+strlen(pkgstr)+7; - pkgglob = malloc(globlen+1); - snprintf(pkgglob, globlen, "%s/%s*.zpm", pkgdir, pkgstr); - - rv = glob(pkgglob, 0, NULL, &repos); - switch (rv) { - case GLOB_NOSPACE: - exit(EXIT_FAILURE); break; - case GLOB_ABORTED: - exit(EXIT_FAILURE); break; - case GLOB_NOMATCH: break; - case 0: - break; - default: - break; - } - - for (i = 0; i < repos.gl_pathc; i++) { - found = checkfile(pkgstr, repos.gl_pathv[i]); + for (i = 0; i < opt->repos.gl_pathc; i++) { + if (!opt->matchallpkgfile + && !strstr(opt->repos.gl_pathv[i], pkgstr) + && !strstr(opt->repos.gl_pathv[i], ".repo") + ) { + continue; + } + found = checkfile(pkgstr, opt->repos.gl_pathv[i]); if (found) { rv = zpm_vercmp(found, latest); if (rv == 1) { latest = found; - pkgfile = strdup(repos.gl_pathv[i]); + pkgfile = strdup(opt->repos.gl_pathv[i]); } } } @@ -239,6 +245,10 @@ struct pkgloc *find_package(char *pkgstr) { pkg = malloc(sizeof *pkg); pkg->id = strdup(latest); pkg->file = pkgfile; + pkg->installed = 0; + if (installed) { + pkg->installed = !strcmp(latest, installed); + } } return pkg; @@ -261,7 +271,12 @@ with pkglibs as (\ where PL.pkgid = %Q\ "; -void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { +static int afind_strcmp(const void *a, const void *b) { + return strcmp(a, b); +} + +void checklibs(struct search_ctl *opts, + jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { char *pkgid = 0, *pkgfile = 0; struct zpm src; @@ -275,8 +290,8 @@ void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { jsw_atrav_t *i; char *soname; - checked = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free); - checked_libs = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free); + checked = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); + checked_libs = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); while (jsw_hsize(check) > 0) { free(pkgid); @@ -295,11 +310,22 @@ void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { if (jsw_afind(checked, pkgid)) { /* already checked this one */ + /* fprintf(stderr, "already checked %s\n", pkgid); */ continue; } + fprintf(stderr, "checking libs for %s\n", pkgid); /* we do this now so we catch self deps */ - jsw_ainsert(checked, pkgid); + if (!jsw_ainsert(checked, pkgid)) { + fprintf(stderr, "checked insert failed\n"); + exit(EXIT_FAILURE); + } + + if (!jsw_afind(checked, pkgid)) { + /* already checked this one */ + fprintf(stderr, "checked find failed\n"); + exit(EXIT_FAILURE); + } /* get the libraries needed by this package */ if (!zpm_open(&src, pkgfile)) { @@ -308,7 +334,7 @@ void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { } if (needed) jsw_adelete(needed); - needed = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free); + needed = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); libs = zpm_libraries_needed(&src, pkgid, needed); zpm_close(&src); @@ -324,13 +350,21 @@ void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { /* if it's in checked_libs, we've already looked at this one */ if (jsw_afind(checked_libs, soname)) { + if (opts->verbose > 1) { + fprintf(stderr, "already checked %s\n", soname); + } continue; } +#if 0 + if (opts->verbose > 1) { + fprintf(stderr, "checking for %s\n", soname); + } +#endif /* haven't found this soname */ jsw_ainsert(checked_libs, soname); - found = find_lib(soname, &pkginfo); + found = find_lib(soname, opts, &pkginfo); if (!found) { if (!jsw_hinsert(nfound, soname, pkgid)) { fprintf(stderr,"insert error\n"); @@ -345,47 +379,16 @@ void checklibs(jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) { } /* shouldn't be in there already */ jsw_hinsert(forlibs, pkginfo.id, pkginfo.file); - } - /* otherwise found == 2, so just continue */ - if (found) { free(pkginfo.file); free(pkginfo.id); - } + } + /* otherwise found == 2, so just continue */ } } free(pkgid); free(pkgfile); } -char *pathcat(char *dir, char *path) { - size_t dirlen = 0, pathlen = 0; - char *cat; - - /* chop off trailing / on dir */ - if (dir) { - dirlen = strlen(dir); - while (dirlen && dir[dirlen-1] == '/') { - dirlen--; - } - } - - if (path) { - pathlen = strlen(path); - while (*path && *path == '/') { - path++; - pathlen--; - } - } - - cat = malloc(dirlen + pathlen + 2); - if (cat) { - strncpy(cat, dir, dirlen); - cat[dirlen] = '/'; - strcpy(cat+dirlen+1, path); - } - return cat; -} - void print_pkghash(jsw_hash_t *hash, int json) { const char *pkgid, *file; char *fmt; @@ -414,11 +417,23 @@ void print_pkghash(jsw_hash_t *hash, int json) { } int main(int ac, char *av[]) { - int opt, argn; + int option, argn; int findlibs = 0, json = 0; struct pkgloc *found; jsw_hash_t *packages, *check, *forlibs, *nolib; jsw_atree_t *nfound; + struct search_ctl opt = { 0 }; + struct zpm localdb; + + opt.dbrepos = 1; + + opt.localdb = getenv("ZPMDB"); + if (!opt.localdb) opt.localdb = "/var/lib/zpm/local.db"; + opt.pkgdir = getenv("ZPM_PACKAGE_DIR"); + if (!opt.pkgdir) opt.pkgdir = "/var/lib/zpm/packages"; + opt.repodir = getenv("ZPM_REPO_DIR"); + if (!opt.repodir) opt.repodir = "/var/lib/zpm/repo"; + /* -l also find packages needed for libs * -j output json @@ -428,7 +443,7 @@ int main(int ac, char *av[]) { * * environment: * ZPMDB - path to localdb, /var/lib/zpm/local.db - * ZPM_REPO_DIR - path to *.repo files, '/var/lib/zpm/repos' + * ZPM_REPO_DIR - path to *.repo files, '/var/lib/zpm/repo' * ZPM_PACKAGE_DIRS - : separated paths to *.zpm files, * '/var/lib/zpm/packages' * ZPM_ROOT_DIR :- prepends to above paths @@ -447,11 +462,28 @@ int main(int ac, char *av[]) { */ int output = 1; - while ((opt = getopt(ac, av, "lj")) != -1) { - switch (opt) { + while ((option = getopt(ac, av, "ljqPRDvp:r:d:MiIO")) != -1) { + switch (option) { case 'l': findlibs = 1; break; case 'j': json = 1; break; - case 'q': output = 0; + case 'q': output = 0; break; + /* show installed files */ + case 'i': opt.matchinstalled = 1; break; + case 'I': opt.suppressinstalled = 1; break; + /* only find localdb pkgs if installed */ + case 'O': opt.onlylocalinstalled = 1; break; + case 'd': opt.localdb = optarg; break; + case 'p': opt.pkgdir = optarg; break; + case 'r': opt.repodir = optarg; break; + case 'P': opt.pkgdir = 0; break; + case 'R': opt.repodir = 0; break; + case 'D': opt.localdb = 0; break; + /* matchallpkgfile means look at + * all .zpm files, not just ones + * that have the pkgid string prefix + */ + case 'M': opt.matchallpkgfile = 1; break; + case 'v': opt.verbose++; break; default: exit(EXIT_FAILURE); break; @@ -459,20 +491,55 @@ int main(int ac, char *av[]) { } argn = optind; - packages = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup, + if (opt.localdb) { + if (zpm_open(&localdb, NULL)) { + opt.zpmdb = &localdb; + } else { + fprintf(stderr, "can't open localdb\n"); + return 2; + } + } + + if (!find_globs(&opt)) { + fprintf(stderr, "bad globs\n"); + return 3; + } + + if (opt.verbose > 1) { + unsigned int i; + fprintf(stderr, "globs:"); + for (i = 0; i < opt.repos.gl_pathc; i++) { + fprintf(stderr, " %s", opt.repos.gl_pathv[i]); + } + fprintf(stderr, "\n"); + } + + /* direct packages asked for */ + packages = jsw_hnew(ac,NULL,afind_strcmp,(keydup_f)strdup, (itemdup_f)strdup,free,free); - check = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup, + + /* packages we need to check for libs */ + check = jsw_hnew(ac,NULL,afind_strcmp,(keydup_f)strdup, (itemdup_f)strdup,free,free); - forlibs = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup, + + /* packages we will also need for library dependences */ + forlibs = jsw_hnew(ac,NULL,afind_strcmp,(keydup_f)strdup, (itemdup_f)strdup,free,free); - nolib = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup, + + /* libraries we didn't find */ + nolib = jsw_hnew(ac,NULL,afind_strcmp,(keydup_f)strdup, (itemdup_f)strdup,free,free); - nfound = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free); + + /* packages asked for that we can't find */ + nfound = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free); int arg; for (arg = argn; arg < ac; arg++) { - found = find_package(av[arg]); - if (found) { + found = find_package(av[arg], &opt); + if (found && (opt.matchinstalled || !found->installed)) { + if (found->installed && opt.suppressinstalled) { + continue; + } jsw_hinsert(packages, found->id, found->file); jsw_hinsert(check, found->id, found->file); free(found->id); @@ -481,16 +548,22 @@ int main(int ac, char *av[]) { } else { jsw_ainsert(nfound, av[arg]); } - } if (findlibs) { - checklibs(check, forlibs, nolib); + checklibs(&opt, check, forlibs, nolib); + /* remove from forlibs anything already explicitly + * in packages + */ } if (output) { - print_pkghash(packages, json); - print_pkghash(forlibs, json); + if (jsw_hsize(packages)) { + print_pkghash(packages, json); + } + if (jsw_hsize(forlibs)) { + print_pkghash(forlibs, json); + } } if (jsw_hsize(nolib) > 0) { @@ -508,7 +581,7 @@ int main(int ac, char *av[]) { char *pkgstr; for (pkgstr = jsw_atfirst(i, nfound); pkgstr; pkgstr = jsw_atnext(i)) { - fprintf(stderr, "%s:\n", pkgstr); + fprintf(stderr, "%s: not found\n", pkgstr); } }