1 #define _POSIX_C_SOURCE 200809L
9 #include "lib/jsw/jsw_hlib.h"
10 #include "lib/jsw/jsw_atree.h"
13 * find packages, and lib deps
23 char *localdb, *repodir, *pkgdir;
30 char *pathcat(char *dir, char *path) {
31 size_t dirlen = 0, pathlen = 0;
34 /* chop off trailing / on dir */
37 while (dirlen && dir[dirlen-1] == '/') {
43 pathlen = strlen(path);
44 while (*path && *path == '/') {
50 cat = malloc(dirlen + pathlen + 2);
52 strncpy(cat, dir, dirlen);
54 strcpy(cat+dirlen+1, path);
59 char *checkfile(char *pkgstr, char *path) {
63 if (!zpm_open(&pkgfile, path)) {
67 pkgid = zpm_findpkg(&pkgfile, pkgstr, NULL);
73 char *checkfileforlib(char *soname, char *path) {
77 if (!zpm_open(&pkgfile, path)) {
81 pkgid = zpm_findlib(&pkgfile, soname, NULL);
83 fprintf(stderr, "sql error: %s\n", pkgfile.errmsg);
90 int find_globs(struct search_ctl *opt) {
100 char *globstr = pathcat(opt->repodir, "*.repo");
101 rv = glob(globstr, globopts, NULL, repos);
104 fprintf(stderr, "glob no mem\n");
107 fprintf(stderr, "glob abort\n");
116 globopts = GLOB_APPEND;
121 char *globstr = pathcat(opt->pkgdir, "*.zpm");
122 rv = glob(globstr, globopts, NULL, repos);
125 fprintf(stderr, "glob no mem\n");
128 fprintf(stderr, "glob abort\n");
137 globopts = GLOB_APPEND;
144 int find_lib(char *soname, struct search_ctl *opt, struct pkgloc *pkg) {
146 char *installed = 0, *found = 0;
152 installed = zpm_findlib(opt->zpmdb, soname, "status = 'installed'");
154 if (opt->verbose > 1) {
155 fprintf(stderr, "library %s installed via %s\n", soname, installed);
157 /* we're done, the lib is installed */
162 for (i = 0; i < opt->repos.gl_pathc; i++) {
163 if (opt->verbose > 1) {
164 fprintf(stderr, "checking %s for %s\n", opt->repos.gl_pathv[i], soname);
166 found = checkfileforlib(soname, opt->repos.gl_pathv[i]);
168 if (opt->verbose > 1) {
169 fprintf(stderr, "found %s\n", found);
171 rv = zpm_vercmp(found, latest);
175 pkgfile = strdup(opt->repos.gl_pathv[i]);
177 } else if (opt->verbose > 1) {
178 fprintf(stderr, "not found\n");
182 if (latest && pkgfile) {
183 pkg->id = strdup(latest);
191 struct pkgloc *find_package(char *pkgstr, struct search_ctl *opt) {
193 char *installed = 0, *found = 0;
195 struct pkgloc *pkg = 0;
200 installed = zpm_findpkg(opt->zpmdb, pkgstr, "status = 'installed'");
204 found = zpm_findpkg(opt->zpmdb, pkgstr, NULL);
206 rv = zpm_vercmp(found, latest);
209 pkgfile = opt->zpmdb->path;
214 for (i = 0; i < opt->repos.gl_pathc; i++) {
215 if (!opt->matchallpkgfile
216 && !strstr(opt->repos.gl_pathv[i], pkgstr)
217 && !strstr(opt->repos.gl_pathv[i], ".repo")
221 found = checkfile(pkgstr, opt->repos.gl_pathv[i]);
223 rv = zpm_vercmp(found, latest);
226 pkgfile = strdup(opt->repos.gl_pathv[i]);
231 if (latest && pkgfile) {
232 pkg = malloc(sizeof *pkg);
233 pkg->id = strdup(latest);
240 char *pkglibsneeded = "\
242 select distinct EN.needed as soname, PF.pkgid\
244 join packagefiles_pkgid PF on PF.hash = EN.file\
247 select distinct EL.soname, PF.pkgid\
248 from elflibraries EL\
249 join packagefiles_pkgid PF on PF.hash = EL.file\
251 select distinct PL.soname, PP.soname is not null as selfsatisfied\
253 left join pkgprovides PP on PL.pkgid = PP.pkgid and PL.soname = PP.soname\
257 void checklibs(struct search_ctl *opts,
258 jsw_hash_t *check, jsw_hash_t *forlibs, jsw_hash_t *nfound) {
259 char *pkgid = 0, *pkgfile = 0;
262 /* checked_libs is a list of checked sonames
263 * checked is a list of checked packages
264 * needed is list of libs for package
266 jsw_atree_t *needed = 0, *checked, *checked_libs;
272 checked = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free);
273 checked_libs = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free);
275 while (jsw_hsize(check) > 0) {
281 pkgid = strdup(jsw_hkey(check));
282 pkgfile = strdup(jsw_hitem(check));
284 if (!pkgid || !pkgfile) {
288 jsw_herase(check, pkgid);
290 if (jsw_afind(checked, pkgid)) {
291 /* already checked this one */
295 /* we do this now so we catch self deps */
296 jsw_ainsert(checked, pkgid);
298 /* get the libraries needed by this package */
299 if (!zpm_open(&src, pkgfile)) {
300 fprintf(stderr, "can't zpm open %s\n", pkgfile);
304 if (needed) jsw_adelete(needed);
305 needed = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free);
306 libs = zpm_libraries_needed(&src, pkgid, needed);
315 for (soname = jsw_atfirst(i, needed); soname; soname = jsw_atnext(i)) {
317 struct pkgloc pkginfo;
319 if (opts->verbose > 1) {
320 fprintf(stderr, "checking for %s\n", soname);
322 /* if it's in checked_libs, we've already looked at this one */
323 if (jsw_afind(checked_libs, soname)) {
324 if (opts->verbose > 1) {
325 fprintf(stderr, "already checked for %s\n", soname);
330 /* haven't found this soname */
331 jsw_ainsert(checked_libs, soname);
333 found = find_lib(soname, opts, &pkginfo);
335 if (!jsw_hinsert(nfound, soname, pkgid)) {
336 fprintf(stderr,"insert error\n");
342 /* if not alreacy checked, add to check */
343 if (!jsw_afind(checked, pkginfo.file)) {
344 jsw_hinsert(check,pkginfo.id,pkginfo.file);
346 /* shouldn't be in there already */
347 jsw_hinsert(forlibs, pkginfo.id, pkginfo.file);
349 /* otherwise found == 2, so just continue */
360 void print_pkghash(jsw_hash_t *hash, int json) {
361 const char *pkgid, *file;
366 fmt = json ? "\"%s\": \"%s\"" : "%s:%s";
367 sep = json ? ", " : "\n";
373 if (jsw_hsize(hash) > 0) {
374 for (jsw_hreset(hash); jsw_hitem(hash); jsw_hnext(hash)) {
375 pkgid = jsw_hkey(hash);
376 file = jsw_hitem(hash);
380 printf(fmt, pkgid, file);
383 if (json) printf(" }");
387 int main(int ac, char *av[]) {
389 int findlibs = 0, json = 0;
390 struct pkgloc *found;
391 jsw_hash_t *packages, *check, *forlibs, *nolib;
393 struct search_ctl opt = { 0 };
396 opt.localdb = getenv("ZPMDB");
397 if (!opt.localdb) opt.localdb = "/var/lib/zpm/local.db";
398 opt.pkgdir = getenv("ZPM_PACKAGE_DIR");
399 if (!opt.pkgdir) opt.pkgdir = "/var/lib/zpm/packages";
400 opt.repodir = getenv("ZPM_REPO_DIR");
401 if (!opt.repodir) opt.repodir = "/var/lib/zpm/repo/";
403 /* -l also find packages needed for libs
405 * -q quiet - suppress output
407 * -d debug - trace each step
410 * ZPMDB - path to localdb, /var/lib/zpm/local.db
411 * ZPM_REPO_DIR - path to *.repo files, '/var/lib/zpm/repos'
412 * ZPM_PACKAGE_DIRS - : separated paths to *.zpm files,
413 * '/var/lib/zpm/packages'
414 * ZPM_ROOT_DIR :- prepends to above paths
416 * -M (missing) invert the output and only output missing
418 * packages found (suppress with -P)
419 * package strings not found (suppress with -S)
420 * library dependency packages needed and found (suppress with -N)
421 * library dependency packages already installed (suppress with -H)
422 * library dependency packages in install set (suppress with -I)
423 * library dependency sonames not found (suppress with -L)
425 * exit value is 0 if no missing libs and no bad package strings
426 * exit value is non zero otherwise
430 while ((option = getopt(ac, av, "ljqPRDvp:r:d:M")) != -1) {
432 case 'l': findlibs = 1; break;
433 case 'j': json = 1; break;
434 case 'q': output = 0;
435 case 'd': opt.localdb = optarg; break;
436 case 'p': opt.pkgdir = optarg; break;
437 case 'r': opt.repodir = optarg; break;
438 case 'P': opt.pkgdir = 0; break;
439 case 'R': opt.repodir = 0; break;
440 case 'D': opt.localdb = 0; break;
441 case 'M': opt.matchallpkgfile = 1; break;
442 case 'v': opt.verbose++; break;
451 if (zpm_open(&localdb, NULL)) {
452 opt.zpmdb = &localdb;
454 fprintf(stderr, "can't open localdb\n");
460 if (!find_globs(&opt)) {
461 fprintf(stderr, "bad globs\n");
465 if (opt.verbose > 1) {
467 fprintf(stderr, "globs:");
468 for (i = 0; i < opt.repos.gl_pathc; i++) {
469 fprintf(stderr, " %s", opt.repos.gl_pathv[i]);
471 fprintf(stderr, "\n");
474 packages = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup,
475 (itemdup_f)strdup,free,free);
476 check = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup,
477 (itemdup_f)strdup,free,free);
478 forlibs = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup,
479 (itemdup_f)strdup,free,free);
480 nolib = jsw_hnew(ac,NULL,(cmp_f)strcmp,(keydup_f)strdup,
481 (itemdup_f)strdup,free,free);
482 nfound = jsw_anew((cmp_f)strcmp, (dup_f)strdup, (rel_f)free);
485 for (arg = argn; arg < ac; arg++) {
486 found = find_package(av[arg], &opt);
488 jsw_hinsert(packages, found->id, found->file);
489 jsw_hinsert(check, found->id, found->file);
494 jsw_ainsert(nfound, av[arg]);
500 checklibs(&opt, check, forlibs, nolib);
504 print_pkghash(packages, json);
505 if (jsw_hsize(forlibs)) {
506 print_pkghash(forlibs, json);
510 if (jsw_hsize(nolib) > 0) {
511 for (jsw_hreset(nolib); jsw_hitem(nolib); jsw_hnext(nolib)) {
512 const char *pkgid, *file;
513 pkgid = jsw_hkey(nolib);
514 file = jsw_hitem(nolib);
515 fprintf(stderr, "no lib found %s:%s\n", pkgid, file);
519 if (jsw_asize(nfound) > 0) {
524 for (pkgstr = jsw_atfirst(i, nfound); pkgstr; pkgstr = jsw_atnext(i)) {
525 fprintf(stderr, "%s: not found\n", pkgstr);
529 return jsw_asize(nfound) > 0 || jsw_hsize(nolib) > 0 ? 1 : 0;