static int test_depends(void *actdata, struct pkg *pkg, const char *fpath, const char *name, bool is_shlib) { struct pkgdb *db = actdata; struct pkg_dep *dep = NULL; struct pkgdb_it *it = NULL; struct pkg *d; const char *deporigin, *depname, *depversion; const char *pkgname, *pkgversion; bool deplocked; char pathbuf[MAXPATHLEN]; assert(db != NULL); switch(filter_system_shlibs(name, pathbuf, sizeof(pathbuf))) { case EPKG_OK: /* A non-system library */ break; case EPKG_END: /* A system library */ return (EPKG_OK); default: /* Ignore link resolution errors if we're analysing a shared library. */ if (is_shlib) return (EPKG_OK); pkg_get(pkg, PKG_NAME, &pkgname, PKG_VERSION, &pkgversion); warnx("(%s-%s) %s - shared library %s not found", pkgname, pkgversion, fpath, name); return (EPKG_FATAL); } pkg_addshlib_required(pkg, name); if ((it = pkgdb_query_which(db, pathbuf, false)) == NULL) return (EPKG_OK); d = NULL; if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) { pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion, PKG_LOCKED, &deplocked); dep = pkg_dep_lookup(pkg, deporigin); if (dep == NULL) { pkg_debug(1, "Autodeps: adding unlisted depends (%s): %s-%s", pathbuf, depname, depversion); pkg_adddep(pkg, depname, deporigin, depversion, deplocked); } pkg_free(d); } pkgdb_it_free(it); return (EPKG_OK); }
int exec_which(int argc, char **argv) { struct pkgdb *db; struct pkgdb_it *it; struct pkg *pkg = NULL; char pathabs[MAXPATHLEN + 1]; int ret = EPKG_OK, retcode = EPKG_OK; const char *name, *version; if (argc != 2) { usage_which(); return (EX_USAGE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } absolutepath(argv[1], pathabs, sizeof(pathabs)); if ((it = pkgdb_query_which(db, pathabs)) == NULL) { return (EX_IOERR); } if (( ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) { retcode = EPKG_OK; pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version); printf("%s was installed by package %s-%s\n", pathabs, name, version); } else if (ret != EPKG_END) { retcode = EPKG_WARN; } else { printf("%s was not found in the database\n", pathabs); retcode = EPKG_WARN; } pkg_free(pkg); pkgdb_it_free(it); pkgdb_close(db); return (retcode); }
static int analyse_elf(struct pkgdb *db, struct pkg *pkg, const char *fpath) { struct pkg **deps; struct pkg *p = NULL; struct pkgdb_it *it = NULL; Elf *e; Elf_Scn *scn = NULL; GElf_Shdr shdr; Elf_Data *data; GElf_Dyn *dyn, dyn_mem; size_t numdyn; size_t dynidx; void *handle; Link_map *map; char *name; bool found=false; int fd, i; if ((fd = open(fpath, O_RDONLY, 0)) < 0) return (EPKG_FATAL); if (( e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) return (EPKG_FATAL); if (elf_kind(e) != ELF_K_ELF) return (EPKG_FATAL); while (( scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != &shdr) return (EPKG_FATAL); if (shdr.sh_type == SHT_DYNAMIC) break; } data = elf_getdata(scn, NULL); numdyn = shdr.sh_size / shdr.sh_entsize; for (dynidx = 0; dynidx < numdyn; dynidx++) { if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) return (EPKG_FATAL); if (dyn->d_tag != DT_NEEDED) continue; name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val); handle = dlopen(name, RTLD_LAZY); if (handle != NULL) { dlinfo(handle, RTLD_DI_LINKMAP, &map); if ((it = pkgdb_query_which(db, map->l_name)) == NULL) return (EPKG_FATAL); if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) { found = false; if (( deps = pkg_deps(pkg) ) != NULL) { for (i = 0; deps[i]; i++) { if (strcmp(pkg_get(deps[i], PKG_ORIGIN), pkg_get(p, PKG_ORIGIN)) == 0) found = true; } } if (!found) { warnx("adding forgotten depends (%s): %s-%s", map->l_name, pkg_get(p, PKG_NAME), pkg_get(p, PKG_VERSION)); pkg_adddep(pkg, pkg_get(p, PKG_NAME), pkg_get(p, PKG_ORIGIN), pkg_get(p, PKG_VERSION)); } } dlclose(handle); } pkgdb_it_free(it); } pkg_free(p); close(fd); return (EPKG_OK); }
int exec_which(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; char pathabs[MAXPATHLEN]; char *p, *path, *match, *savedpath; int ret = EPKG_OK, retcode = EX_SOFTWARE; int ch, i; int res, pathlen = 0; bool orig = false; bool glob = false; bool search = false; bool search_s = false; charlist patterns; struct option longopts[] = { { "glob", no_argument, NULL, 'g' }, { "origin", no_argument, NULL, 'o' }, { "path-search", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { NULL, 0, NULL, 0 }, }; path = NULL; while ((ch = getopt_long(argc, argv, "+gopq", longopts, NULL)) != -1) { switch (ch) { case 'g': glob = true; break; case 'o': orig = true; break; case 'p': search_s = true; break; case 'q': quiet = true; break; default: usage_which(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_which(); return (EX_USAGE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (search_s) { if ((path = getenv("PATH")) == NULL) { printf("$PATH is not set, falling back to non-search behaviour\n"); search_s = false; } else { pathlen = strlen(path) + 1; } } while (argc >= 1) { kv_init(patterns); retcode = EX_SOFTWARE; if (search_s) { if ((argv[0][0] == '.') || (argv[0][0] == '/')) { search = false; } else { search = true; if (strlen(argv[0]) >= FILENAME_MAX) { retcode = EX_USAGE; goto cleanup; } p = malloc(pathlen); if (p == NULL) { retcode = EX_OSERR; goto cleanup; } strlcpy(p, path, pathlen); match = NULL; savedpath=p; for (;;) { res = get_match(&match, &p, argv[0]); if (p == NULL) break; if (res == (EX_USAGE)) { printf("%s was not found in PATH, falling back to non-search behaviour\n", argv[0]); search = false; } else if (res == (EX_OSERR)) { retcode = EX_OSERR; free(savedpath); goto cleanup; } else { pkg_absolutepath(match, pathabs, sizeof(pathabs)); /* ensure not not append twice an entry if PATH is messy */ if (already_in_list(&patterns, pathabs)) continue; kv_push(char *, patterns, strdup(pathabs)); free(match); } } free(savedpath); } } if (!glob && !search) { pkg_absolutepath(argv[0], pathabs, sizeof(pathabs)); kv_push(char *, patterns, strdup(pathabs)); } else if (!search) { if (strlcpy(pathabs, argv[0], sizeof(pathabs)) >= sizeof(pathabs)) { retcode = EX_USAGE; goto cleanup; } } for (i = 0; i < kv_size(patterns); i++) { if ((it = pkgdb_query_which(db, kv_A(patterns, i), glob)) == NULL) { retcode = EX_IOERR; goto cleanup; } pkg = NULL; while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) { retcode = EX_OK; if (quiet && orig) pkg_printf("%o\n", pkg); else if (quiet && !orig) pkg_printf("%n-%v\n", pkg, pkg); else if (!quiet && orig) pkg_printf("%S was installed by package %o\n", kv_A(patterns, i), pkg); else if (!quiet && !orig) pkg_printf("%S was installed by package %n-%v\n", kv_A(patterns, i), pkg, pkg); } if (retcode != EX_OK && !quiet) printf("%s was not found in the database\n", kv_A(patterns, i)); pkg_free(pkg); pkgdb_it_free(it); } kv_destroy(patterns); argc--; argv++; } cleanup: pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_which(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; char pathabs[MAXPATHLEN + 1]; int ret = EPKG_OK, retcode = EX_OK; const char *name, *version, *origin; int ch; bool orig = false; bool glob = false; while ((ch = getopt(argc, argv, "qgo")) != -1) { switch (ch) { case 'q': quiet = true; break; case 'g': glob = true; break; case 'o': orig = true; break; default: usage_which(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc != 1) { usage_which(); return (EX_USAGE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } if (!glob) absolutepath(argv[0], pathabs, sizeof(pathabs)); else strlcpy(pathabs, argv[0], sizeof(pathabs)); if ((it = pkgdb_query_which(db, pathabs, glob)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) { pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version, PKG_ORIGIN, &origin); if (quiet && orig) printf("%s\n", origin); else if (quiet && !orig) printf("%s-%s\n", name, version); else if (!quiet && orig) printf("%s was installed by package %s\n", pathabs, origin); else if (!quiet && !orig) printf("%s was installed by package %s-%s\n", pathabs, name, version); if (!glob) break; } if (ret != EPKG_END) { retcode = EX_SOFTWARE; } else if (!glob) { if (!quiet) printf("%s was not found in the database\n", pathabs); retcode = EX_DATAERR; } pkg_free(pkg); pkgdb_it_free(it); pkgdb_close(db); return (retcode); }
static int test_depends(void *actdata, struct pkg *pkg, const char *fpath, const char *name, bool is_shlib) { struct pkgdb *db = actdata; struct pkg_dep *dep = NULL; struct pkgdb_it *it = NULL; struct pkg *d; const char *deporigin, *depname, *depversion; bool deplocked; char pathbuf[MAXPATHLEN]; bool found; bool shlibs = false; assert(db != NULL); pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs); switch(filter_system_shlibs(name, pathbuf, sizeof(pathbuf))) { case EPKG_OK: /* A non-system library */ break; case EPKG_END: /* A system library */ return (EPKG_OK); default: /* Ignore link resolution errors if we're analysing a shared library. */ if (is_shlib) return (EPKG_OK); warnx("(%s-%s) %s - shared library %s not found", pkg_name(pkg), pkg_version(pkg), fpath, name); return (EPKG_FATAL); } if (shlibs) pkg_addshlib_required(pkg, name); if ((it = pkgdb_query_which(db, pathbuf)) == NULL) return (EPKG_OK); d = NULL; if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) { found = false; pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion, PKG_LOCKED, &deplocked); dep = NULL; found = false; while (pkg_deps(pkg, &dep) == EPKG_OK) { if (strcmp(pkg_dep_origin(dep), deporigin) == 0) { found = true; break; } } if (!found) { pkg_emit_error("adding forgotten depends (%s): %s-%s", pathbuf, depname, depversion); pkg_adddep(pkg, depname, deporigin, depversion, deplocked); } pkg_free(d); } pkgdb_it_free(it); return (EPKG_OK); }
int exec_which(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; char pathabs[MAXPATHLEN]; char *p, *path, *match; int ret = EPKG_OK, retcode = EX_SOFTWARE; int ch; int res, pathlen; bool orig = false; bool glob = false; bool search = false; bool search_s = false; while ((ch = getopt(argc, argv, "qgop")) != -1) { switch (ch) { case 'q': quiet = true; break; case 'g': glob = true; break; case 'o': orig = true; break; case 'p': search_s = true; break; default: usage_which(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_which(); return (EX_USAGE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY, 0, 0) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (search_s) { if ((path = getenv("PATH")) == NULL) { printf("$PATH is not set, falling back to non-search behaviour\n"); search_s = false; } else { pathlen = strlen(path) + 1; } } while (argc >= 1) { retcode = EX_SOFTWARE; if (search_s) { if ((argv[0][0] == '.') || (argv[0][0] == '/')) { search = false; } else { search = true; if (strlen(argv[0]) >= FILENAME_MAX) { retcode = EX_USAGE; goto cleanup; } p = malloc(pathlen); if (p == NULL) { retcode = EX_OSERR; goto cleanup; } strlcpy(p, path, pathlen); match = NULL; res = get_match(&match, p, argv[0]); free(p); if (res == (EX_USAGE)) { printf("%s was not found in PATH, falling back to non-search behaviour\n", argv[0]); search = false; } else if (res == (EX_OSERR)) { retcode = EX_OSERR; goto cleanup; } else { absolutepath(match, pathabs, sizeof(pathabs)); free(match); } } } if (!glob && !search) absolutepath(argv[0], pathabs, sizeof(pathabs)); else if (!search) { if (strlcpy(pathabs, argv[0], sizeof(pathabs)) >= sizeof(pathabs)) retcode = EX_USAGE; goto cleanup; } if ((it = pkgdb_query_which(db, pathabs, glob)) == NULL) { retcode = EX_IOERR; goto cleanup; } pkg = NULL; while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) { retcode = EX_OK; if (quiet && orig) pkg_printf("%o\n", pkg); else if (quiet && !orig) pkg_printf("%n-%v\n", pkg, pkg); else if (!quiet && orig) pkg_printf("%S was installed by package %o\n", pathabs, pkg); else if (!quiet && !orig) pkg_printf("%S was installed by package %n-%v\n", pathabs, pkg, pkg); } if (retcode != EX_OK && !quiet) printf("%s was not found in the database\n", pathabs); pkg_free(pkg); pkgdb_it_free(it); argc--; argv++; } cleanup: pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }