static kh_sum_t * populate_sums(struct pkgdb *db) { struct pkg *p = NULL; struct pkgdb_it *it = NULL; const char *sum; char *cksum; size_t slen; kh_sum_t *suml = NULL; khint_t k; int ret; suml = kh_init_sum(); it = pkgdb_repo_search(db, "*", MATCH_GLOB, FIELD_NAME, FIELD_NONE, NULL); while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) { pkg_get(p, PKG_CKSUM, &sum); slen = MIN(strlen(sum), PKG_FILE_CKSUM_CHARS); cksum = strndup(sum, slen); k = kh_put_sum(suml, cksum, &ret); if (ret != 0) kh_value(suml, k) = cksum; } return (suml); }
int exec_search(int argc, char **argv) { const char *pattern = NULL; const char *reponame = NULL; int ret = EPKG_OK, ch; int flags; uint64_t opt = 0; match_t match = MATCH_REGEX; pkgdb_field search = FIELD_NONE; pkgdb_field label = FIELD_NONE; struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; bool atleastone = false; bool old_quiet; struct option longopts[] = { { "case-sensitive", no_argument, NULL, 'C' }, { "comment", no_argument, NULL, 'c' }, { "description", no_argument, NULL, 'D' }, { "depends-on", no_argument, NULL, 'd' }, { "exact", no_argument, NULL, 'e' }, { "full", no_argument, NULL, 'f' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "label", required_argument, NULL, 'L' }, { "origins", no_argument, NULL, 'o' }, { "prefix", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "query-modifier", required_argument, NULL, 'Q' }, { "repository", required_argument, NULL, 'r' }, { "raw", no_argument, NULL, 'R' }, { "search", required_argument, NULL, 'S' }, { "size", no_argument, NULL, 's' }, { "no-repo-update", no_argument, NULL, 'U' }, { "regex", no_argument, NULL, 'x' }, { "raw-format", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+CcDdefgiL:opqQ:r:RS:sUx", longopts, NULL)) != -1) { switch (ch) { case 'C': pkgdb_set_case_sensitivity(true); break; case 'c': /* Same as -S comment */ search = search_label_opt("comment"); break; case 'D': /* Same as -S description */ search = search_label_opt("description"); break; case 'd': /* Same as -Q depends-on */ opt |= modifier_opt("depends-on"); break; case 'e': match = MATCH_EXACT; break; case 'f': /* Same as -Q full */ opt |= modifier_opt("full"); break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'L': label = search_label_opt(optarg); break; case 'o': /* Same as -L origin */ label = search_label_opt("origin"); break; case 'p': /* Same as -Q prefix */ opt |= modifier_opt("prefix"); break; case 'q': quiet = true; break; case 'Q': opt |= modifier_opt(optarg); break; case 'r': reponame = optarg; break; case 'R': opt = INFO_RAW; break; case 'S': search = search_label_opt(optarg); break; case 's': /* Same as -Q size */ opt |= modifier_opt("size"); break; case 'U': auto_update = false; break; case 'x': match = MATCH_REGEX; break; case 1: if (strcasecmp(optarg, "json") == 0) opt |= INFO_RAW_JSON; else if (strcasecmp(optarg, "json-compact") == 0) opt |= INFO_RAW_JSON_COMPACT; else if (strcasecmp(optarg, "yaml") == 0) opt |= INFO_RAW_YAML; else if (strcasecmp(optarg, "ucl") == 0) opt |= INFO_RAW_UCL; else errx(EX_USAGE, "Invalid format '%s' for the " "raw output, expecting json, json-compact " "or yaml", optarg); break; default: usage_search(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc != 1) { usage_search(); return (EX_USAGE); } pattern = argv[0]; if (pattern[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); return (EX_USAGE); } if (search == FIELD_NONE) { if (strchr(pattern, '/') != NULL) search = FIELD_ORIGIN; else search = FIELD_NAMEVER; /* Default search */ } if (label == FIELD_NONE) label = search; /* By default, show what was searched */ switch(label) { case FIELD_NONE: break; /* should never happen */ case FIELD_ORIGIN: opt |= INFO_TAG_ORIGIN|INFO_COMMENT; break; case FIELD_NAME: opt |= INFO_TAG_NAME|INFO_COMMENT; break; case FIELD_NAMEVER: opt |= INFO_TAG_NAMEVER|INFO_COMMENT; break; case FIELD_COMMENT: opt |= INFO_TAG_NAMEVER|INFO_COMMENT; break; case FIELD_DESC: opt |= INFO_TAG_NAMEVER|INFO_DESCR; break; } if (quiet) { opt = INFO_TAG_NAMEVER; quiet = false; } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO); switch(ret) { case EPKG_ENOACCESS: warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); case EPKG_ENODB: if (!auto_update) { warnx("Unable to open remote repository catalogues. Try running '%s update' first.", getprogname()); return (EX_IOERR); } break; case EPKG_OK: break; default: return (EX_IOERR); } /* first update the remote repositories if needed */ old_quiet = quiet; quiet = true; if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK) return (ret); quiet = old_quiet; if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK) return (EX_IOERR); if ((it = pkgdb_repo_search(db, pattern, match, search, search, reponame)) == NULL) { pkgdb_close(db); return (EX_IOERR); } if (opt & INFO_RAW) { if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT)) == 0) opt |= INFO_RAW_YAML; } flags = info_flags(opt, true); while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) { print_info(pkg, opt); atleastone = true; } pkg_free(pkg); pkgdb_it_free(it); pkgdb_close(db); if (!atleastone) ret = EPKG_FATAL; return ((ret == EPKG_OK || ret == EPKG_END) ? EX_OK : EX_SOFTWARE); }
int exec_clean(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *p = NULL; struct sumlist *sumlist = NULL, *s, *t; FTS *fts = NULL; FTSENT *ent = NULL; struct dl_head dl = STAILQ_HEAD_INITIALIZER(dl); const char *cachedir, *sum, *name; char *paths[2], csum[PKG_FILE_CKSUM_CHARS + 1], link_buf[MAXPATHLEN]; bool all = false; bool sumloaded = false; int retcode; int ch, cnt = 0; size_t total = 0, slen; ssize_t link_len; char size[7]; struct pkg_manifest_key *keys = NULL; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "dry-run", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+anqy", longopts, NULL)) != -1) { switch (ch) { case 'a': all = true; break; case 'n': dry_run = true; break; case 'q': quiet = true; break; case 'y': yes = true; break; default: usage_clean(); return (EX_USAGE); } } argc -= optind; argv += optind; cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR")); paths[0] = __DECONST(char*, cachedir); paths[1] = NULL; retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to clean old packages"); return (EX_NOPERM); } else if (retcode == EPKG_ENODB) { warnx("No package database installed. Nothing to do!"); return (EX_OK); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } retcode = EX_SOFTWARE; if (pkgdb_open(&db, PKGDB_REMOTE) != 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 ((fts = fts_open(paths, FTS_PHYSICAL, NULL)) == NULL) { warn("fts_open(%s)", cachedir); goto cleanup; } /* Build the list of out-of-date or obsolete packages */ pkg_manifest_keys_new(&keys); while ((ent = fts_read(fts)) != NULL) { if (ent->fts_info != FTS_F && ent->fts_info != FTS_SL) continue; if (all) { retcode = add_to_dellist(&dl, ent->fts_path); if (retcode == EPKG_OK) { total += ent->fts_statp->st_size; ++cnt; } continue; } if (sumlist == NULL && !sumloaded) { it = pkgdb_repo_search(db, "*", MATCH_GLOB, FIELD_NAME, FIELD_NONE, NULL); while (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) { pkg_get(p, PKG_CKSUM, &sum); slen = MIN(strlen(sum), PKG_FILE_CKSUM_CHARS); s = calloc(1, sizeof(struct sumlist)); memcpy(s->sum, sum, slen); s->sum[slen] = '\0'; HASH_ADD_STR(sumlist, sum, s); } } if (ent->fts_info == FTS_SL) { /* Dereference the symlink and check it for being * recognized checksum file, or delete the symlink * later. */ if ((link_len = readlink(ent->fts_name, link_buf, sizeof(link_buf))) == -1) continue; link_buf[link_len] = '\0'; name = link_buf; } else name = ent->fts_name; s = NULL; if (extract_filename_sum(name, csum)) HASH_FIND_STR(sumlist, csum, s); if (s == NULL) { retcode = add_to_dellist(&dl, ent->fts_path); if (retcode == EPKG_OK) { total += ent->fts_statp->st_size; ++cnt; } continue; } } HASH_ITER(hh, sumlist, s, t) { HASH_DEL(sumlist, s); free(s); }