static int pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const char * const outdir, bool overwrite) { int i, ret = EPKG_OK, retcode = EPKG_OK; struct pkg *pkg = NULL; struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; int query_flags = PKG_LOAD_DEPS | PKG_LOAD_FILES | PKG_LOAD_CATEGORIES | PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS | PKG_LOAD_LICENSES | PKG_LOAD_USERS | PKG_LOAD_GROUPS | PKG_LOAD_SHLIBS_REQUIRED | PKG_LOAD_PROVIDES | PKG_LOAD_REQUIRES | PKG_LOAD_SHLIBS_PROVIDED | PKG_LOAD_ANNOTATIONS; struct pkg_entry *e = NULL, *etmp; char pkgpath[MAXPATHLEN]; const char *format = NULL; bool foundone; if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } /* XXX: get rid of hardcoded timeouts */ 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); } switch (fmt) { case TXZ: format = "txz"; break; case TBZ: format = "tbz"; break; case TGZ: format = "tgz"; break; case TAR: format = "tar"; break; } for (i = 0; i < argc || match == MATCH_ALL; i++) { if (match == MATCH_ALL) { printf("Loading the package list...\n"); if ((it = pkgdb_query(db, NULL, match)) == NULL) goto cleanup; match = !MATCH_ALL; } else if ((it = pkgdb_query(db, argv[i], match)) == NULL) goto cleanup; foundone = false; while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { if ((e = malloc(sizeof(struct pkg_entry))) == NULL) err(1, "malloc(pkg_entry)"); e->pkg = pkg; pkg = NULL; DL_APPEND(pkg_head, e); foundone = true; } if (!foundone) { warnx("No installed package matching \"%s\" found\n", argv[i]); retcode++; } pkgdb_it_free(it); if (ret != EPKG_END) retcode++; } DL_FOREACH_SAFE(pkg_head, e, etmp) { DL_DELETE(pkg_head, e); if (!overwrite) { pkg_snprintf(pkgpath, sizeof(pkgpath), "%S/%n-%v.%S", outdir, e->pkg, e->pkg, format); if (access(pkgpath, F_OK) == 0) { pkg_printf("%n-%v already packaged, skipping...\n", e->pkg, e->pkg); pkg_free(e->pkg); free(e); continue; } } pkg_printf("Creating package for %n-%v\n", e->pkg, e->pkg); if (pkg_create_installed(outdir, fmt, e->pkg) != EPKG_OK) retcode++; pkg_free(e->pkg); free(e); }
int exec_audit(int argc, char **argv) { struct pkg_audit *audit; struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; const char *db_dir; char *name; char *version; char audit_file_buf[MAXPATHLEN]; char *audit_file = audit_file_buf; unsigned int vuln = 0; bool fetch = false, recursive = false; int ch, i; int ret = EX_OK; const char *portaudit_site = NULL; struct sbuf *sb; kh_pkgs_t *check = NULL; db_dir = pkg_object_string(pkg_config_get("PKG_DBDIR")); snprintf(audit_file_buf, sizeof(audit_file_buf), "%s/vuln.xml", db_dir); struct option longopts[] = { { "fetch", no_argument, NULL, 'F' }, { "file", required_argument, NULL, 'f' }, { "recursive", no_argument, NULL, 'r' }, { "quiet", no_argument, NULL, 'q' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+Ff:qr", longopts, NULL)) != -1) { switch (ch) { case 'F': fetch = true; break; case 'f': audit_file = optarg; break; case 'q': quiet = true; break; case 'r': recursive = true; break; default: usage_audit(); return(EX_USAGE); } } argc -= optind; argv += optind; audit = pkg_audit_new(); if (fetch == true) { portaudit_site = pkg_object_string(pkg_config_get("VULNXML_SITE")); if (pkg_audit_fetch(portaudit_site, audit_file) != EPKG_OK) { pkg_audit_free(audit); return (EX_IOERR); } } if (pkg_audit_load(audit, audit_file) != EPKG_OK) { if (errno == ENOENT) warnx("vulnxml file %s does not exist. " "Try running 'pkg audit -F' first", audit_file); else warn("unable to open vulnxml file %s", audit_file); pkg_audit_free(audit); return (EX_DATAERR); } check = kh_init_pkgs(); if (argc >= 1) { for (i = 0; i < argc; i ++) { name = argv[i]; version = strrchr(name, '-'); if (version != NULL) { version[0] = '\0'; version++; } if (pkg_new(&pkg, PKG_FILE) != EPKG_OK) err(EX_OSERR, "malloc"); if (version != NULL) pkg_set(pkg, PKG_NAME, name, PKG_VERSION, version); else pkg_set(pkg, PKG_NAME, name); /* Fake uniqueid */ pkg_set(pkg, PKG_UNIQUEID, name); add_to_check(check, pkg); pkg = NULL; } } else { /* * if the database doesn't exist it just means there are no * packages to audit. */ ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENODB) { pkg_audit_free(audit); kh_destroy_pkgs(check); return (EX_OK); } else if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to read the package database"); pkg_audit_free(audit); kh_destroy_pkgs(check); return (EX_NOPERM); } else if (ret != EPKG_OK) { warnx("Error accessing the package database"); pkg_audit_free(audit); kh_destroy_pkgs(check); return (EX_IOERR); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkg_audit_free(audit); kh_destroy_pkgs(check); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); pkg_audit_free(audit); kh_destroy_pkgs(check); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) { warnx("Error accessing the package database"); ret = EX_IOERR; } else { while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_RDEPS)) == EPKG_OK) { add_to_check(check, pkg); pkg = NULL; } ret = EX_OK; } if (db != NULL) { pkgdb_it_free(it); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); } if (ret != EX_OK) { pkg_audit_free(audit); kh_destroy_pkgs(check); return (ret); } } /* Now we have vulnxml loaded and check list formed */ #ifdef HAVE_CAPSICUM if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); pkg_audit_free(audit); kh_destroy_pkgs(check); return (EPKG_FATAL); } #endif if (pkg_audit_process(audit) == EPKG_OK) { kh_foreach_value(check, pkg, { if (pkg_audit_is_vulnerable(audit, pkg, quiet, &sb)) { vuln ++; printf("%s", sbuf_data(sb)); if (recursive) { const char *name; kh_pkgs_t *seen = kh_init_pkgs(); pkg_get(pkg, PKG_NAME, &name); sbuf_clear(sb); sbuf_printf(sb, "Packages that depend on %s: ", name); print_recursive_rdeps(check, pkg , sb, seen, true); sbuf_finish(sb); printf("%s\n\n", sbuf_data(sb)); kh_destroy_pkgs(seen); } sbuf_delete(sb); } pkg_free(pkg); });
int exec_upgrade(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode; int updcode; int ch; int lock_type = PKGDB_LOCK_ADVISORY; bool yes = true, yes_arg = false; bool dry_run = false; bool auto_update; int done = 0; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST; yes_arg = pkg_object_bool(pkg_config_get("ASSUME_ALWAYS_YES")); auto_update = pkg_object_bool(pkg_config_get("REPO_AUTOUPDATE")); while ((ch = getopt(argc, argv, "fInqFr:Uy")) != -1) { switch (ch) { case 'f': f |= PKG_FLAG_FORCE; break; case 'I': f |= PKG_FLAG_NOSCRIPT; break; case 'U': auto_update = false; break; case 'n': f |= PKG_FLAG_DRY_RUN; lock_type = PKGDB_LOCK_READONLY; dry_run = true; break; case 'F': f |= PKG_FLAG_SKIP_INSTALL; lock_type = PKGDB_LOCK_READONLY; break; case 'q': quiet = true; break; case 'r': reponame = optarg; break; case 'y': yes_arg = true; break; default: usage_upgrade(); return (EX_USAGE); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 0) { usage_upgrade(); return (EX_USAGE); } if (dry_run && !auto_update) retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL|PKGDB_DB_REPO); else retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL|PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS && dry_run) { auto_update = false; retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL|PKGDB_DB_REPO); } if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privilege to upgrade packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); else retcode = EX_SOFTWARE; /* first update the remote repositories if needed */ if (auto_update && (updcode = pkgcli_update(false, reponame)) != EPKG_OK) return (updcode); if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, lock_type, 0, 0) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK) goto cleanup; if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK) goto cleanup; pkg_jobs_set_flags(jobs, f); if (pkg_jobs_solve(jobs) != EPKG_OK) goto cleanup; while ((nbactions = pkg_jobs_count(jobs)) > 0) { /* print a summary before applying the jobs */ yes = yes_arg; if (!quiet || dry_run) { print_jobs_summary(jobs, "The following %d packages will be affected (of %d checked):\n\n", nbactions, pkg_jobs_total(jobs)); if (!yes && !dry_run) yes = query_yesno(false, "\nProceed with this action [y/N]: "); if (dry_run) yes = false; } if (yes) { retcode = pkg_jobs_apply(jobs); done = 1; if (retcode == EPKG_CONFLICT) { printf ("The conflicts with the existing packages have been found.\n" "We need to run one more solver iteration to resolve them.\n"); continue; } else if (retcode != EPKG_OK) goto cleanup; } if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } break; } if (done == 0 && yes) printf("Your packages are up to date\n"); retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_release_lock(db, lock_type); pkgdb_close(db); if (!yes && newpkgversion) newpkgversion = false; return (retcode); }
int exec_delete(int argc, char **argv) { struct pkg_jobs *jobs = NULL; struct pkgdb *db = NULL; match_t match = MATCH_EXACT; pkg_flags f = PKG_FLAG_NONE; bool recursive_flag = false, rc = false; int retcode = EX_SOFTWARE; int ch; int i; int lock_type = PKGDB_LOCK_ADVISORY; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "no-deinstall-script", no_argument, NULL, 'D' }, { "force", no_argument, NULL, 'f' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "dry-run", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "recursive", no_argument, NULL, 'R' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; nbactions = nbdone = 0; while ((ch = getopt_long(argc, argv, "+aCDfginqRxy", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'D': f |= PKG_FLAG_NOSCRIPT; break; case 'f': f |= PKG_FLAG_FORCE; force = true; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'n': f |= PKG_FLAG_DRY_RUN; lock_type = PKGDB_LOCK_READONLY; dry_run = true; break; case 'q': quiet = true; break; case 'R': recursive_flag = true; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_delete(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1 && match != MATCH_ALL) { usage_delete(); return (EX_USAGE); } if (dry_run) retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); else retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENODB) { warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to delete packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } /* * By default delete packages recursively. * If force mode is enabled then we try to remove packages non-recursively. * However, if -f and -R flags are both enabled then we return to * recursive deletion. */ if (!force || recursive_flag) f |= PKG_FLAG_RECURSIVE; pkg_jobs_set_flags(jobs, f); if (match == MATCH_EXACT) { for (i = 0; i < argc; i++) { if (strchr(argv[i], '*') != NULL) { match = MATCH_GLOB; break; } } } if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL) goto cleanup; if (pkg_jobs_solve(jobs) != EPKG_OK) { fprintf(stderr, "Cannot perform request\n"); retcode = EX_NOPERM; goto cleanup; } /* check if we have something to deinstall */ if ((nbactions = pkg_jobs_count(jobs)) == 0) { if (argc == 0) { if (!quiet) printf("Nothing to do.\n"); retcode = EX_OK; } else { fprintf(stderr, "Package(s) not found!\n"); retcode = EX_DATAERR; } goto cleanup; } if (!quiet || dry_run) { if (!quiet) { print_jobs_summary(jobs, "Deinstallation has been requested for the following %d packages " "(of %d packages in the universe):\n\n", nbactions, pkg_jobs_total(jobs)); } if (dry_run) { retcode = EX_OK; goto cleanup; } rc = query_yesno(false, "\nProceed with deinstalling packages? "); } else rc = yes; if (!rc || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK) goto cleanup; pkgdb_compact(db); retcode = EX_OK; cleanup: pkgdb_release_lock(db, lock_type); pkg_jobs_free(jobs); pkgdb_close(db); return (retcode); }
int exec_set(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; int ch; int i; match_t match = MATCH_EXACT; int64_t newautomatic = -1; bool automatic = false; bool rc = false; const char *changed = NULL; char *newvalue = NULL; char *oldvalue = NULL; unsigned int loads = PKG_LOAD_BASIC; unsigned int sets = 0; unsigned int field = 0, depfield = 0; int retcode; struct option longopts[] = { { "automatic", required_argument, NULL, 'A' }, { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "change-origin", required_argument, NULL, 'o' }, { "change-name", required_argument, NULL, 'n' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+A:aCgio:xyn:", longopts, NULL)) != -1) { switch (ch) { case 'A': sets |= AUTOMATIC; newautomatic = optarg[0] - '0'; if (newautomatic != 0 && newautomatic != 1) errx(EX_USAGE, "Wrong value for -A. " "Expecting 0 or 1, got: %s", optarg); break; case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'o': sets |= ORIGIN; loads |= PKG_LOAD_DEPS; match = MATCH_ALL; changed = "origin"; if (!check_change_values(optarg, &oldvalue, &newvalue, '/')) { errx(EX_USAGE, "Wrong format for -o. " "Expecting oldorigin:neworigin, got: %s", optarg); } break; case 'n': sets |= NAME; loads |= PKG_LOAD_DEPS; match = MATCH_ALL; changed = "name"; if (!check_change_values(optarg, &oldvalue, &newvalue, '\0')) { errx(EX_USAGE, "Wrong format for -n. " "Expecting oldname:newname, got: %s", optarg); } break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: free(oldvalue); usage_set(); return (EX_USAGE); } } argc -= optind; argv += optind; if ((argc < 1 && match != MATCH_ALL) || (newautomatic == -1 && newvalue == NULL) || (sets & (NAME|ORIGIN)) == (NAME|ORIGIN)) { usage_set(); return (EX_USAGE); } if (sets & NAME) { field = PKG_SET_NAME; depfield = PKG_SET_DEPNAME; } else if (sets & ORIGIN) { field = PKG_SET_ORIGIN; depfield = PKG_SET_DEPORIGIN; } retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENODB) { if (match == MATCH_ALL) return (EX_OK); if (!quiet) warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to modify the package database"); return (EX_NOPERM); } else if (retcode != EPKG_OK) { warnx("Error accessing package database"); return (EX_SOFTWARE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { free(newvalue); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); free(newvalue); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkgdb_transaction_begin(db, NULL) != EPKG_OK) { pkgdb_close(db); free(newvalue); warnx("Cannot start transaction for update"); return (EX_TEMPFAIL); } if (oldvalue != NULL) { match = MATCH_ALL; if ((it = pkgdb_query(db, oldvalue, MATCH_EXACT)) == NULL) { retcode = EX_IOERR; goto cleanup; } if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) != EPKG_OK) { pkg = NULL; /* fprintf(stderr, "%s not installed\n", oldorigin); free(oldorigin); pkgdb_it_free(it); pkgdb_close(db); return (EX_SOFTWARE);*/ } rc = yes; if (!yes) { if (pkg != NULL) rc = query_yesno(false, "Change %S from %S to %S for %n-%v? ", changed, oldvalue, newvalue, pkg, pkg); else rc = query_yesno(false, "Change %S from %S to %S for all dependencies? ", changed, oldvalue, newvalue); } if (pkg != NULL && rc) { if (pkgdb_set(db, pkg, field, newvalue) != EPKG_OK) { retcode = EX_IOERR; goto cleanup; } } pkgdb_it_free(it); } i = 0; do { bool saved_rc = rc; if ((it = pkgdb_query(db, argv[i], match)) == NULL) { retcode = EX_IOERR; goto cleanup; } while (pkgdb_it_next(it, &pkg, loads) == EPKG_OK) { if ((sets & AUTOMATIC) == AUTOMATIC) { pkg_get(pkg, PKG_AUTOMATIC, &automatic); if (automatic == newautomatic) continue; if (!rc) { if (newautomatic) rc = query_yesno(false, "Mark %n-%v as automatically installed? ", pkg, pkg); else rc = query_yesno(false, "Mark %n-%v as not automatically installed? ", pkg, pkg); } if (rc) pkgdb_set(db, pkg, PKG_SET_AUTOMATIC, (int)newautomatic); rc = saved_rc; } if (sets & (ORIGIN|NAME)) { struct pkg_dep *d = NULL; while (pkg_deps(pkg, &d) == EPKG_OK) { /* * Do not query user when he has already * been queried. */ if (pkgdb_set(db, pkg, depfield, oldvalue, newvalue) != EPKG_OK) { retcode = EX_IOERR; goto cleanup; } } } } pkgdb_it_free(it); i++; } while (i < argc); cleanup: free(oldvalue); free(newvalue); pkg_free(pkg); if (retcode == 0) { pkgdb_transaction_commit(db, NULL); } else { pkgdb_transaction_rollback(db, NULL); } pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); return (retcode); }
int exec_install(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode; int updcode = EPKG_OK; int ch; int mode, repo_type; int done = 0; int lock_type = PKGDB_LOCK_ADVISORY; bool rc = true; bool local_only = false; match_t match = MATCH_EXACT; pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST; struct option longopts[] = { { "automatic", no_argument, NULL, 'A' }, { "case-sensitive", no_argument, NULL, 'C' }, { "force", no_argument, NULL, 'f' }, { "fetch-only", no_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "no-install-scripts", no_argument, NULL, 'I' }, { "local-only", no_argument, NULL, 'l' }, { "ignore-missing", no_argument, NULL, 'M' }, { "dry-run", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "repository", required_argument, NULL, 'r' }, { "from-root", no_argument, NULL, 'R' }, { "no-repo-update", no_argument, NULL, 'U' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; nbactions = nbdone = 0; if (strcmp(argv[0], "add") == 0) { auto_update = false; local_only = true; yes = true; quiet = true; } while ((ch = getopt_long(argc, argv, "+ACfFgiIlMnqr:RUxy", longopts, NULL)) != -1) { switch (ch) { case 'A': f |= PKG_FLAG_AUTOMATIC; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'f': f |= PKG_FLAG_FORCE; break; case 'F': f |= PKG_FLAG_SKIP_INSTALL; lock_type = PKGDB_LOCK_READONLY; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'I': f |= PKG_FLAG_NOSCRIPT; break; case 'l': local_only = true; auto_update = false; break; case 'M': f |= PKG_FLAG_FORCE_MISSING; break; case 'n': f |= PKG_FLAG_DRY_RUN; lock_type = PKGDB_LOCK_READONLY; dry_run = true; break; case 'q': quiet = true; break; case 'r': reponame = optarg; break; case 'R': f |= PKG_FLAG_RECURSIVE; break; case 'U': auto_update = false; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_install(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_install(); return (EX_USAGE); } if (dry_run && !auto_update) mode = PKGDB_MODE_READ; else mode = PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE; if (local_only) repo_type = PKGDB_DB_LOCAL; else repo_type = PKGDB_DB_LOCAL|PKGDB_DB_REPO; retcode = pkgdb_access(mode, repo_type); if (retcode == EPKG_ENOACCESS && dry_run) { auto_update = false; retcode = pkgdb_access(PKGDB_MODE_READ, repo_type); } if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to install packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); else retcode = EX_SOFTWARE; /* first update the remote repositories if needed */ if (auto_update && (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK) return (updcode); if (pkgdb_open_all(&db, local_only ? PKGDB_DEFAULT : PKGDB_MAYBE_REMOTE, reponame) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) goto cleanup; if (!local_only && reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK) goto cleanup; pkg_jobs_set_flags(jobs, f); if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL) goto cleanup; if (pkg_jobs_solve(jobs) != EPKG_OK) goto cleanup; while ((nbactions = pkg_jobs_count(jobs)) > 0) { rc = yes; /* print a summary before applying the jobs */ if (!quiet || dry_run) { print_jobs_summary(jobs, "The following %d packages will be affected (of %d checked):\n\n", nbactions, pkg_jobs_total(jobs)); if (!dry_run) { rc = query_yesno(false, "\nProceed with this action? [y/N]: "); } else { rc = false; } } if (rc) { retcode = pkg_jobs_apply(jobs); done = 1; if (retcode == EPKG_CONFLICT) { printf("Conflicts with the existing packages " "have been found.\nOne more solver " "iteration is needed to resolve them.\n"); continue; } else if (retcode != EPKG_OK) goto cleanup; } if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } break; } if (done == 0 && rc) printf("The most recent version of packages are already installed\n"); retcode = EX_OK; cleanup: pkgdb_release_lock(db, lock_type); pkg_jobs_free(jobs); pkgdb_close(db); if (!rc && newpkgversion) newpkgversion = false; return (retcode); }
int exec_register(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb *db = NULL; struct pkg_manifest_key *keys = NULL; regex_t preg; regmatch_t pmatch[2]; char *arch = NULL; char myarch[BUFSIZ]; char *www = NULL; char fpath[MAXPATHLEN]; const char *plist = NULL; const char *mdir = NULL; const char *mfile = NULL; const char *input_path = NULL; const char *desc = NULL; const char *location = NULL; size_t size; bool developer; bool legacy = false; bool old = false; bool __unused metadata_only = false; bool testing_mode = false; int ch; int i; int ret = EPKG_OK; int retcode = EX_OK; /* options descriptor */ struct option longopts[] = { { "automatic", no_argument, NULL, 'A' }, { "plist", required_argument, NULL, 'f' }, { "root", required_argument, NULL, 'i' }, { "legacy", no_argument, NULL, 'l' }, { "manifest", required_argument, NULL, 'M' }, { "metadata", required_argument, NULL, 'm' }, { "old", no_argument, NULL, 'O' }, { "test", no_argument, NULL, 't' }, { "relocate", required_argument, NULL, 1 }, { NULL, 0, NULL, 0}, }; developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE")); if (pkg_new(&pkg, PKG_INSTALLED) != EPKG_OK) err(EX_OSERR, "malloc"); while ((ch = getopt_long(argc, argv, "Adf:i:lM:m:Ot", longopts, NULL)) != -1) { switch (ch) { case 'A': case 'd': pkg_set(pkg, PKG_AUTOMATIC, (bool)true); break; case 'f': plist = optarg; break; case 'i': input_path = optarg; break; case 'l': legacy = true; break; case 'M': metadata_only = true; mfile = optarg; break; case 'm': mdir = optarg; break; case 'O': old = true; break; case 't': testing_mode = true; break; case 1: location = optarg; break; default: warnx("Unrecognised option -%c\n", ch); usage_register(); return (EX_USAGE); } } if (!old) { retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to register packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); else retcode = EX_OK; } /* * Ideally, the +MANIFEST should be all that is necessary, * since it can contain all of the meta-data supplied by the * other files mentioned below. These are here for backwards * compatibility with the way the ports tree works with * pkg_tools. * * The -M option specifies one manifest file to read the * meta-data from, and overrides the use of legacy meta-data * inputs. * * Dependencies, shlibs, files etc. may be derived by * analysing the package files (maybe discovered as the * content of the staging directory) unless -t (testing_mode) * is used. */ if (mfile != NULL && mdir != NULL) { warnx("Cannot use both -m and -M together"); usage_register(); return (EX_USAGE); } if (mfile == NULL && mdir == NULL) { warnx("One of either -m or -M flags is required"); usage_register(); return (EX_USAGE); } if (mfile != NULL && plist != NULL) { warnx("-M incompatible with -f option"); usage_register(); return (EX_USAGE); } if (testing_mode && input_path != NULL) { warnx("-i incompatible with -t option"); usage_register(); return (EX_USAGE); } pkg_manifest_keys_new(&keys); if (mfile != NULL) { ret = pkg_parse_manifest_file(pkg, mfile, keys); pkg_manifest_keys_free(keys); if (ret != EPKG_OK) return (EX_IOERR); } else { snprintf(fpath, sizeof(fpath), "%s/+MANIFEST", mdir); ret = pkg_parse_manifest_file(pkg, fpath, keys); pkg_manifest_keys_free(keys); if (ret != EPKG_OK) return (EX_IOERR); snprintf(fpath, sizeof(fpath), "%s/+DESC", mdir); pkg_set_from_file(pkg, PKG_DESC, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+DISPLAY", mdir); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_MESSAGE, fpath, false); snprintf(fpath, sizeof(fpath), "%s/+MTREE_DIRS", mdir); if (access(fpath, F_OK) == 0) pkg_set_from_file(pkg, PKG_MTREE, fpath, false); for (i = 0; scripts[i] != NULL; i++) { snprintf(fpath, sizeof(fpath), "%s/%s", mdir, scripts[i]); if (access(fpath, F_OK) == 0) pkg_addscript_file(pkg, fpath); } if (www != NULL) { pkg_set(pkg, PKG_WWW, www); free(www); } pkg_get(pkg, PKG_WWW, &www); /* * if www is not given then try to determine it from * description */ if (www == NULL) { pkg_get(pkg, PKG_DESC, &desc); regcomp(&preg, "^WWW:[[:space:]]*(.*)$", REG_EXTENDED|REG_ICASE|REG_NEWLINE); if (regexec(&preg, desc, 2, pmatch, 0) == 0) { size = pmatch[1].rm_eo - pmatch[1].rm_so; www = strndup(&desc[pmatch[1].rm_so], size); pkg_set(pkg, PKG_WWW, www); free(www); } else { pkg_set(pkg, PKG_WWW, "UNKNOWN"); } regfree(&preg); } if (plist != NULL) ret += ports_parse_plist(pkg, plist, input_path); } if (ret != EPKG_OK) { return (EX_IOERR); } if (!old) { if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } } /* * testing_mode allows updating the local package database * without any check that the files etc. listed in the meta * data actually exist on the system. Inappropriate use of * testing_mode can really screw things up. */ if (!testing_mode) pkg_analyse_files(db, pkg, input_path); pkg_get(pkg, PKG_ARCH, &arch); if (arch == NULL) { /* * do not take the one from configuration on purpose * but the real abi of the package. */ pkg_get_myarch(myarch, BUFSIZ); if (developer) pkg_suggest_arch(pkg, myarch, true); pkg_set(pkg, PKG_ARCH, myarch); } else { if (developer) pkg_suggest_arch(pkg, arch, false); } if (!testing_mode && input_path != NULL) pkg_copy_tree(pkg, input_path, location ? location : "/"); if (location != NULL) pkg_addannotation(pkg, "relocated", location); if (old) { if (pkg_register_old(pkg) != EPKG_OK) retcode = EX_SOFTWARE; } else { if (pkgdb_register_ports(db, pkg) != EPKG_OK) retcode = EX_SOFTWARE; } if (!legacy && pkg_has_message(pkg)) pkg_printf("%M\n", pkg); if (!old) { pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); } pkg_free(pkg); return (retcode); }
int exec_check(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb_it *it = NULL; struct pkgdb *db = NULL; match_t match = MATCH_EXACT; int flags = PKG_LOAD_BASIC; int ret, rc = EX_OK; int ch; bool yes; bool dcheck = false; bool checksums = false; bool recompute = false; bool reanalyse_shlibs = false; bool noinstall = false; int nbpkgs = 0; int i; int verbose = 0; yes = pkg_object_bool(pkg_config_get("ASSUME_ALWAYS_YES")); /* Set default case sensitivity for searching */ pkgdb_set_case_sensitivity( pkg_object_bool(pkg_config_get("CASE_SENSITIVE_MATCH")) ); struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh); while ((ch = getopt(argc, argv, "aBCdginrsvxy")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'B': reanalyse_shlibs = true; flags |= PKG_LOAD_FILES; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': dcheck = true; flags |= PKG_LOAD_DEPS; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'n': noinstall = true; break; case 'r': recompute = true; flags |= PKG_LOAD_FILES; break; case 's': checksums = true; flags |= PKG_LOAD_FILES; break; case 'v': verbose = 1; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_check(); return (EX_USAGE); } } argc -= optind; argv += optind; /* Default to all packages if no pkg provided */ if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) { match = MATCH_ALL; } else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) { usage_check(); return (EX_USAGE); } if (recompute || reanalyse_shlibs) ret = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); else ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENODB) { warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to access the package database"); return (EX_NOPERM); } else if (ret != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_ADVISORY, 0, 0) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } i = 0; do { if ((it = pkgdb_query(db, argv[i], match)) == NULL) { rc = EX_IOERR; goto cleanup; } while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) { /* check for missing dependencies */ if (dcheck) { if (verbose) pkg_printf("Checking dependencies: %n\n", pkg); nbpkgs += check_deps(db, pkg, &dh, noinstall); if (noinstall && nbpkgs > 0) { rc = EX_UNAVAILABLE; } } if (checksums) { if (verbose) pkg_printf("Checking checksums: %n\n", pkg); if (pkg_test_filesum(pkg) != EPKG_OK) { rc = EX_DATAERR; } } if (recompute) { if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE, 0.5, 20) == EPKG_OK) { if (verbose) pkg_printf("Recomputing size and checksums: %n\n", pkg); if (pkg_recompute(db, pkg) != EPKG_OK) { rc = EX_DATAERR; } pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); } else { rc = EX_TEMPFAIL; } } if (reanalyse_shlibs) { if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE, 0.5, 20) == EPKG_OK) { if (verbose) pkg_printf("Reanalyzing files for shlibs: %n\n", pkg); if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK) { pkg_printf("Failed to reanalyse for shlibs: %n\n", pkg); rc = EX_UNAVAILABLE; } pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); } else { rc = EX_TEMPFAIL; } } } if (dcheck && nbpkgs > 0 && !noinstall) { printf("\n>>> Missing package dependencies were detected.\n"); printf(">>> Found %d issue(s) in the package database.\n\n", nbpkgs); if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE, 0.5, 20) == EPKG_OK) { ret = fix_deps(db, &dh, nbpkgs, yes); if (ret == EPKG_OK) check_summary(db, &dh); else if (ret == EPKG_ENODB) { db = NULL; rc = EX_IOERR; } pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); if (rc == EX_IOERR) goto cleanup; } else { rc = EX_TEMPFAIL; goto cleanup; } } pkgdb_it_free(it); i++; } while (i < argc); cleanup: deps_free(&dh); pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_ADVISORY); pkgdb_close(db); return (rc); }
int exec_annotate(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; enum action action = NONE; const char *tag; const char *value; const char *pkgname; struct sbuf *input = NULL; int ch; int match = MATCH_EXACT; int retcode; int exitcode = EX_OK; int flags = 0; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "add", no_argument, NULL, 'A' }, { "case-insensitive", no_argument, NULL, 'C' }, { "delete", no_argument, NULL, 'D' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "modify", no_argument, NULL, 'M' }, { "quiet", no_argument, NULL, 'q' }, { "show", no_argument, NULL, 'S' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; /* Set default case sensitivity for searching */ pkgdb_set_case_sensitivity( pkg_object_bool(pkg_config_get("CASE_SENSITIVE_MATCH")) ); while ((ch = getopt_long(argc, argv, "+aACDgiMqSxy", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'A': action = ADD; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'D': action = DELETE; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'M': action = MODIFY; break; case 'q': quiet = true; break; case 'S': action = SHOW; flags |= PKG_LOAD_ANNOTATIONS; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_annotate(); return (EX_USAGE); } } argc -= optind; argv += optind; if (action == NONE || (match == MATCH_ALL && argc < 1) || (match != MATCH_ALL && argc < 2)) { usage_annotate(); return (EX_USAGE); } if (match == MATCH_ALL) { pkgname = NULL; tag = argv[0]; value = (argc > 1) ? argv[1] : NULL; } else { pkgname = argv[0]; tag = argv[1]; value = (argc > 2) ? argv[2] : NULL; } if ((action == ADD || action == MODIFY) && value == NULL) { /* try and read data for the value from stdin. */ input = read_input(); value = sbuf_data(input); } retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENODB) { if (match == MATCH_ALL) { exitcode = EX_OK; goto cleanup; } if (!quiet) warnx("No packages installed. Nothing to do!"); exitcode = EX_OK; goto cleanup; } else if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to modify the package database"); exitcode = EX_NOPERM; goto cleanup; } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); exitcode = EX_SOFTWARE; goto cleanup; } retcode = pkgdb_open(&db, PKGDB_DEFAULT); if (retcode != EPKG_OK) { return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if ((it = pkgdb_query(db, pkgname, match)) == NULL) { exitcode = EX_IOERR; goto cleanup; } while ((retcode = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) { switch(action) { case NONE: /* Should never happen */ usage_annotate(); exitcode = EX_USAGE; break; case ADD: retcode = do_add(db, pkg, tag, value); break; case MODIFY: retcode = do_modify(db, pkg, tag, value); break; case DELETE: retcode = do_delete(db, pkg, tag); break; case SHOW: retcode = do_show(pkg, tag); break; } if (retcode == EPKG_WARN) exitcode = EX_DATAERR; if (retcode != EPKG_OK && retcode != EPKG_WARN) { exitcode = EX_IOERR; goto cleanup; } } cleanup: pkg_free(pkg); pkgdb_it_free(it); pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); if (input != NULL) sbuf_delete(input); return (exitcode); }
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); }
static int fix_deps(struct pkgdb *db, struct deps_head *dh, int nbpkgs, bool yes) { struct pkg_jobs *jobs = NULL; struct deps_entry *e = NULL; char **pkgs = NULL; int i = 0; pkg_flags f = PKG_FLAG_AUTOMATIC; assert(db != NULL); assert(nbpkgs > 0); if ((pkgs = calloc(nbpkgs, sizeof (char *))) == NULL) err(1, "calloc()"); STAILQ_FOREACH(e, dh, next) pkgs[i++] = e->origin; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { free(pkgs); return (EPKG_ENODB); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_ADVISORY, 0, 0) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) { goto cleanup; } pkg_jobs_set_flags(jobs, f); if (pkg_jobs_add(jobs, MATCH_EXACT, pkgs, nbpkgs) == EPKG_FATAL) { goto cleanup; } if (pkg_jobs_solve(jobs) != EPKG_OK) { goto cleanup; } if (pkg_jobs_count(jobs) == 0) { printf("\nUnable to find packages for installation.\n\n"); goto cleanup; } /* print a summary before applying the jobs */ print_jobs_summary(jobs, "The following packages will be installed:\n\n"); if (!yes) yes = query_yesno(false, "\n>>> Try to fix the missing dependencies [y/N]: "); if (yes) { if (pkgdb_access(PKGDB_MODE_WRITE, PKGDB_DB_LOCAL) == EPKG_ENOACCESS) { warnx("Insufficient privileges to modify the package " "database"); goto cleanup; } pkg_jobs_apply(jobs); } cleanup: if (pkgs != NULL) free(pkgs); if (jobs != NULL) pkg_jobs_free(jobs); pkgdb_release_lock(db, PKGDB_LOCK_ADVISORY); pkgdb_close(db); return (EPKG_OK); }
static int convert_from_old(const char *pkg_add_dbdir, bool dry_run) { DIR *d; struct dirent *dp; struct pkg *p = NULL; char path[MAXPATHLEN]; struct pkgdb *db = NULL; struct stat sb; int lock_type = PKGDB_LOCK_EXCLUSIVE; int ret; if (dry_run) ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); else ret = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE| PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to convert packages"); return (EX_NOPERM); } else if (ret != EPKG_OK && ret != EPKG_ENODB) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } if ((d = opendir(pkg_add_dbdir)) == NULL) err(EX_NOINPUT, "%s", pkg_add_dbdir); if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } if (dry_run) lock_type = PKGDB_LOCK_READONLY; if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked" " by another process"); return (EX_TEMPFAIL); } while ((dp = readdir(d)) != NULL) { if (fstatat(dirfd(d), dp->d_name, &sb, 0) == 0 && S_ISDIR(sb.st_mode)) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; if (p != NULL) pkg_free(p); if (pkg_new(&p, PKG_OLD_FILE) != EPKG_OK) err(EX_OSERR, "malloc"); printf("Converting %s...\n", dp->d_name); snprintf(path, sizeof(path), "%s/%s", pkg_add_dbdir, dp->d_name); if (pkg_old_load_from_path(p, path) != EPKG_OK) { fprintf(stderr, "Skipping invalid package: %s\n", path); continue; } pkg_from_old(p); if (!dry_run) pkgdb_register_ports(db, p); } } pkg_free(p); pkgdb_release_lock(db, lock_type); pkgdb_close(db); return (EX_OK); }
int exec_fetch(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int ch; int retcode = EX_SOFTWARE; bool upgrades_for_installed = false, rc; unsigned mode; match_t match = MATCH_EXACT; pkg_flags f = PKG_FLAG_NONE; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "dependencies", no_argument, NULL, 'd' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "quiet", no_argument, NULL, 'q' }, { "repository", required_argument, NULL, 'r' }, { "avaialbe-updates", no_argument, NULL, 'u' }, { "no-repo-update", no_argument, NULL, 'U' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "aCdgiqr:Uuxy", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': f |= PKG_FLAG_WITH_DEPS | PKG_FLAG_RECURSIVE; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'q': quiet = true; break; case 'r': reponame = optarg; break; case 'u': f |= PKG_FLAG_UPGRADES_FOR_INSTALLED; upgrades_for_installed = true; break; case 'U': auto_update = false; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_fetch(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1 && match != MATCH_ALL && !upgrades_for_installed) { usage_fetch(); return (EX_USAGE); } if (match == MATCH_ALL && upgrades_for_installed) { usage_fetch(); return (EX_USAGE); } /* TODO: Allow the user to specify an output directory via -o outdir */ if (auto_update) mode = PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE; else mode = PKGDB_MODE_READ; retcode = pkgdb_access(mode, PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to access repo catalogue"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); if (upgrades_for_installed) { retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to access the package database"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); } /* first update the remote repositories if needed */ if (auto_update && (retcode = pkgcli_update(false, reponame)) != EPKG_OK) return (retcode); if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != 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 (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK) goto cleanup; if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK) goto cleanup; pkg_jobs_set_flags(jobs, f); if (!upgrades_for_installed && pkg_jobs_add(jobs, match, argv, argc) != EPKG_OK) goto cleanup; if (pkg_jobs_solve(jobs) != EPKG_OK) goto cleanup; if (pkg_jobs_count(jobs) == 0) goto cleanup; if (!quiet) { print_jobs_summary(jobs, "The following packages will be fetched:\n\n"); rc = query_yesno(false, "\nProceed with fetching packages [y/N]: "); } else { rc = true; } if (!rc || pkg_jobs_apply(jobs) != EPKG_OK) goto cleanup; retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_upgrade(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode; int updcode; int ch; int lock_type = PKGDB_LOCK_ADVISORY; match_t match = MATCH_EXACT; int done = 0; bool rc = true; pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST; size_t dlbytes, diffbytes, limbytes; limbytes = pkg_object_int(pkg_config_get("WARN_SIZE_LIMIT")); struct option longopts[] = { { "case-sensitive", no_argument, NULL, 'C' }, { "force", no_argument, NULL, 'f' }, { "fetch-only", no_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "no-install-scripts", no_argument, NULL, 'I' }, { "dry-run", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "repository", required_argument, NULL, 'r' }, { "no-repo-update", no_argument, NULL, 'U' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; nbactions = nbdone = 0; while ((ch = getopt_long(argc, argv, "+CfFgiInqr:Uxy", longopts, NULL)) != -1) { switch (ch) { case 'C': pkgdb_set_case_sensitivity(true); break; case 'f': f |= PKG_FLAG_FORCE; break; case 'F': f |= PKG_FLAG_SKIP_INSTALL; lock_type = PKGDB_LOCK_READONLY; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'I': f |= PKG_FLAG_NOSCRIPT; break; case 'n': f |= PKG_FLAG_DRY_RUN; lock_type = PKGDB_LOCK_READONLY; dry_run = true; break; case 'q': quiet = true; break; case 'r': reponame = optarg; break; case 'U': auto_update = false; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_upgrade(); return (EX_USAGE); /* NOTREACHED */ } } argc -= optind; argv += optind; if (dry_run && !auto_update) retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL|PKGDB_DB_REPO); else retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL|PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS && dry_run) { auto_update = false; retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL|PKGDB_DB_REPO); } if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privilege to upgrade packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); else retcode = EX_SOFTWARE; /* first update the remote repositories if needed */ if (auto_update && (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK) return (updcode); if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK) goto cleanup; if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK) goto cleanup; pkg_jobs_set_flags(jobs, f); if (argc > 0) if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL) goto cleanup; if (pkg_jobs_solve(jobs) != EPKG_OK) goto cleanup; while ((nbactions = pkg_jobs_count(jobs)) > 0) { /* print a summary before applying the jobs */ rc = yes; if (!quiet || dry_run) { print_jobs_summary(jobs, &diffbytes, &dlbytes, "The following %d package(s) will be affected (of %d checked):\n\n", nbactions, pkg_jobs_total(jobs)); if (!dry_run) { if (limbytes && (diffbytes > limbytes || dlbytes > limbytes)) { rc = query_yesno(false, "\nProceed with this " "action? "); } else { rc = true; } } else { rc = false; } } if (rc) { retcode = pkg_jobs_apply(jobs); done = 1; if (retcode == EPKG_CONFLICT) { printf("Conflicts with the existing packages " "have been found.\nOne more solver " "iteration is needed to resolve them.\n"); continue; } else if (retcode != EPKG_OK) goto cleanup; } if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } break; } if (done == 0 && rc && !quiet) printf("Your packages are up to date.\n"); retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_release_lock(db, lock_type); pkgdb_close(db); if (!dry_run) pkg_cache_full_clean(); if (!rc && newpkgversion) newpkgversion = false; return (retcode); }
int exec_add(int argc, char **argv) { struct pkgdb *db = NULL; struct sbuf *failedpkgs = NULL; char path[MAXPATHLEN]; char *file; int retcode; int ch; int i; int failedpkgcount = 0; pkg_flags f = PKG_FLAG_NONE; struct pkg_manifest_key *keys = NULL; const char *location = NULL; /* options descriptor */ struct option longopts[] = { { "no-scripts", no_argument, NULL, 'I' }, { "automatic", no_argument, NULL, 'A' }, { "force", no_argument, NULL, 'f' }, { "accept-missing", no_argument, NULL, 'M' }, { "quiet", no_argument, NULL, 'q' }, { "relocate", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 } }; while ((ch = getopt_long(argc, argv, "IAfqM", longopts, NULL)) != -1) { switch (ch) { case 'I': f |= PKG_ADD_NOSCRIPT; break; case 'A': f |= PKG_ADD_AUTOMATIC; break; case 'f': f |= PKG_ADD_FORCE; force = true; break; case 'M': f |= PKG_ADD_FORCE_MISSING; break; case 'q': quiet = true; break; case 1: location = optarg; break; default: usage_add(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_add(); return (EX_USAGE); } retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to add packages"); return (EX_NOPERM); } else if (retcode != EPKG_OK) return (EX_IOERR); if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } failedpkgs = sbuf_new_auto(); pkg_manifest_keys_new(&keys); for (i = 0; i < argc; i++) { if (is_url(argv[i]) == EPKG_OK) { snprintf(path, sizeof(path), "%s/%s.XXXXX", getenv("TMPDIR") != NULL ? getenv("TMPDIR") : "/tmp", basename(argv[i])); if ((retcode = pkg_fetch_file(NULL, argv[i], path, 0)) != EPKG_OK) break; file = path; } else { file = argv[i]; /* Special case: treat a filename of "-" as meaning 'read from stdin.' It doesn't make sense to have a filename of "-" more than once per command line, but we aren't testing for that at the moment */ if (strcmp(file, "-") != 0 && access(file, F_OK) != 0) { warn("%s", file); if (errno == ENOENT) warnx("Was 'pkg install %s' meant?", file); sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; continue; } } if ((retcode = pkg_add(db, file, f, keys, location)) != EPKG_OK) { sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; } if (is_url(argv[i]) == EPKG_OK) unlink(file); } pkg_manifest_keys_free(keys); pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); if(failedpkgcount > 0) { sbuf_finish(failedpkgs); printf("\nFailed to install the following %d package(s): %s\n", failedpkgcount, sbuf_data(failedpkgs)); retcode = EPKG_FATAL; } sbuf_delete(failedpkgs); if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE); }
int exec_autoremove(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; int retcode = EX_OK; int ch; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_FORCE; bool rc = false; struct option longopts[] = { { "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, "+nqy", longopts, NULL)) != -1) { switch (ch) { case 'n': f |= PKG_FLAG_DRY_RUN; dry_run = true; break; case 'q': quiet = true; break; case 'y': yes = true; break; default: break; } } argc -= optind; argv += optind; if (argc != 0) { usage_autoremove(); return (EX_USAGE); } if (dry_run) retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); else retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to autoremove packages"); return (EX_NOPERM); } else if (retcode == EPKG_ENODB) { warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_ADVISORY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } /* Always force packages to be removed */ if (pkg_jobs_new(&jobs, PKG_JOBS_AUTOREMOVE, db) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } pkg_jobs_set_flags(jobs, f); if ((retcode = pkg_jobs_solve(jobs)) != EPKG_OK) { retcode = EX_SOFTWARE; goto cleanup; } if ((nbactions = pkg_jobs_count(jobs)) == 0) { printf("Nothing to do.\n"); goto cleanup; } if (!quiet || dry_run) { print_jobs_summary(jobs, "Deinstallation has been requested for the following %d packages:\n\n", nbactions); if (!dry_run) rc = query_yesno(false, "\nProceed with deinstalling packages [y/N]: "); } if (!rc || dry_run || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK) { goto cleanup; } pkgdb_compact(db); cleanup: pkg_jobs_free(jobs); pkgdb_release_lock(db, PKGDB_LOCK_ADVISORY); pkgdb_close(db); return (retcode); }
int exec_info(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; int query_flags; struct pkg *pkg = NULL; uint64_t opt = INFO_TAG_NAMEVER; match_t match = MATCH_GLOB; char *pkgname; char *pkgversion = NULL, *pkgversion2 = NULL; const char *file = NULL; int ch, fd; int ret = EPKG_OK; int retcode = 0; bool gotone = false; int i, j; int sign = 0; int sign2 = 0; int open_flags = 0; bool pkg_exists = false; bool origin_search = false; bool e_flag = false; struct pkg_manifest_key *keys = NULL; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "annotations", no_argument, NULL, 'A' }, { "provided-shlibs", no_argument, NULL, 'b' }, { "required-shlibs", no_argument, NULL, 'B' }, { "case-sensitive", no_argument, NULL, 'C' }, { "dependencies", no_argument, NULL, 'd' }, { "pkg-message", no_argument, NULL, 'D' }, { "exists", no_argument, NULL, 'e' }, { "show-name-only", no_argument, NULL, 'E' }, { "full", no_argument, NULL, 'f' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "comment", no_argument, NULL, 'I' }, { "locked", no_argument, NULL, 'k' }, { "list-files", no_argument, NULL, 'l' }, { "origin", no_argument, NULL, 'o' }, { "by-origin", no_argument, NULL, 'O' }, { "prefix", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "required-by", no_argument, NULL, 'r' }, { "raw", no_argument, NULL, 'R' }, { "size", no_argument, NULL, 's' }, { "regex", no_argument, NULL, 'x' }, { "raw-format", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; /* TODO: exclusive opts ? */ while ((ch = getopt_long(argc, argv, "+aAbBCdDeEfF:giIkloOpqrRsx", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'A': opt |= INFO_ANNOTATIONS; break; case 'b': opt |= INFO_SHLIBS_PROVIDED; break; case 'B': opt |= INFO_SHLIBS_REQUIRED; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': opt |= INFO_DEPS; break; case 'D': opt |= INFO_MESSAGE; break; case 'e': pkg_exists = true;; retcode = 1; break; case 'E': /* ports compatibility */ e_flag = true; break; case 'f': opt |= INFO_FULL; break; case 'F': file = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'I': opt |= INFO_COMMENT; break; case 'k': opt |= INFO_LOCKED; break; case 'l': opt |= INFO_FILES; break; case 'o': opt |= INFO_ORIGIN; break; case 'O': origin_search = true; /* only for ports compat */ break; case 'p': opt |= INFO_PREFIX; break; case 'q': quiet = true; break; case 'r': opt |= INFO_RDEPS; break; case 'R': opt |= INFO_RAW; break; case 's': opt |= INFO_FLATSIZE; 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_info(); return(EX_USAGE); } } if (argc == 1 || (argc == 2 && quiet)) match = MATCH_ALL; argc -= optind; argv += optind; if (argc == 0 && file == NULL && match != MATCH_ALL) { /* which -O bsd.*.mk always execpt clean output */ if (origin_search) return (EX_OK); usage_info(); return (EX_USAGE); } /* When no other data is requested, default is to print * 'name-ver comment' For -O, just print name-ver */ if (!origin_search && (opt & INFO_ALL) == 0 && match == MATCH_ALL && !quiet) opt |= INFO_COMMENT; /* Special compatibility: handle -O and -q -O */ if (origin_search) { if (quiet) { opt = INFO_TAG_NAMEVER; quiet = false; } else { opt = INFO_TAG_NAMEVER|INFO_COMMENT; } } if (match == MATCH_ALL && opt == INFO_TAG_NAMEVER) quiet = false; if (file != NULL) { if ((fd = open(file, O_RDONLY)) == -1) { warn("Unable to open %s", file); return (EX_IOERR); } #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ, CAP_FSTAT); if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS ) { warn("cap_rights_limit() failed"); close(fd); return (EX_SOFTWARE); } if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); close(fd); return (EX_SOFTWARE); } #endif if (opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; pkg_manifest_keys_new(&keys); if (opt & INFO_RAW) { if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) == 0) opt |= INFO_RAW_YAML; } if ((opt & (INFO_RAW | INFO_FILES | INFO_DIRS)) == 0) open_flags = PKG_OPEN_MANIFEST_COMPACT; if (pkg_open_fd(&pkg, fd, keys, open_flags) != EPKG_OK) { close(fd); return (1); } pkg_manifest_keys_free(keys); print_info(pkg, opt); close(fd); pkg_free(pkg); return (EX_OK); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (match == MATCH_ALL) return (EX_OK); if (origin_search) return (EX_OK); if (!quiet) warnx("No packages installed"); return (EX_UNAVAILABLE); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != 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); } i = 0; do { gotone = false; pkgname = argv[i]; /* * allow to search for origin with a trailing / * likes audio/linux-vsound depending on ${PORTSDIR}/audio/sox/ */ if (argc > 0 && pkgname[strlen(pkgname) -1] == '/') pkgname[strlen(pkgname) -1] = '\0'; if (argc > 0) { j=0; while (pkgname[j] != '\0') { if (pkgname[j] == '<') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = LT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=LE; j++; } } else { pkgversion = pkgname + j; sign = LT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=LE; j++; } } } else if (pkgname[j] == '>') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = GT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=GE; j++; } } else { pkgversion = pkgname + j; sign = GT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=GE; j++; } } } else if (pkgname[j] == '=') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = EQ; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=EQ; j++; } } else { pkgversion = pkgname + j; sign = EQ; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=EQ; j++; } } } j++; } } if (match != MATCH_ALL && pkgname[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); i++; continue; } if ((it = pkgdb_query(db, pkgname, match)) == NULL) { goto cleanup; } /* this is place for compatibility hacks */ /* ports infrastructure expects pkg info -q -O to * always return 0 even if the ports doesn't exists */ if (origin_search) gotone = true; /* end of compatibility hacks */ /* * only show full version in case of match glob with a * single argument specified which does not contains * any glob pattern */ if (argc == 1 && !origin_search && !quiet && !e_flag && match == MATCH_GLOB && strcspn(pkgname, "*[]{}()") == strlen(pkgname) && opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; query_flags = info_flags(opt, false); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { gotone = true; const char *version; pkg_get(pkg, PKG_VERSION, &version); if (pkgversion != NULL) { switch (pkg_version_cmp(version, pkgversion)) { case -1: if (sign != LT && sign != LE) { gotone = false; continue; } break; case 0: if (sign != LE && sign != GE && sign != EQ) { gotone = false; continue; } break; case 1: if (sign != GT && sign != GE) { gotone = false; continue; } break; } } if (pkgversion2 != NULL) { switch (pkg_version_cmp(version, pkgversion2)) { case -1: if (sign2 != LT && sign2 != LE) { gotone = false; continue; } break; case 0: if (sign2 != LE && sign2 != GE && sign2 != EQ) { gotone = false; continue; } break; case 1: if (sign2 != GT && sign2 != GE) { gotone = false; continue; } break; } } if (pkg_exists) retcode = EX_OK; else print_info(pkg, opt); } if (ret != EPKG_END) { retcode = EX_IOERR; } if (retcode == EX_OK && !gotone && match != MATCH_ALL) { if (!quiet) warnx("No package(s) matching %s", argv[i]); retcode = EX_SOFTWARE; } pkgdb_it_free(it); i++; } while (i < argc); cleanup: pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_check(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb_it *it = NULL; struct pkgdb *db = NULL; struct sbuf *msg = NULL; match_t match = MATCH_EXACT; int flags = PKG_LOAD_BASIC; int ret, rc = EX_OK; int ch; bool dcheck = false; bool checksums = false; bool recompute = false; bool reanalyse_shlibs = false; bool noinstall = false; int nbpkgs = 0; int i, processed, total = 0; int verbose = 0; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "shlibs", no_argument, NULL, 'B' }, { "case-sensitive", no_argument, NULL, 'C' }, { "dependencies", no_argument, NULL, 'd' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "dry-run", no_argument, NULL, 'n' }, { "recompute", no_argument, NULL, 'r' }, { "checksums", no_argument, NULL, 's' }, { "verbose", no_argument, NULL, 'v' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; struct deps_head dh = STAILQ_HEAD_INITIALIZER(dh); processed = 0; while ((ch = getopt_long(argc, argv, "+aBCdginrsvxy", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'B': reanalyse_shlibs = true; flags |= PKG_LOAD_FILES; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': dcheck = true; flags |= PKG_LOAD_DEPS; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'n': noinstall = true; break; case 'r': recompute = true; flags |= PKG_LOAD_FILES; break; case 's': checksums = true; flags |= PKG_LOAD_FILES; break; case 'v': verbose = 1; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_check(); return (EX_USAGE); } } argc -= optind; argv += optind; /* Default to all packages if no pkg provided */ if (argc == 0 && (dcheck || checksums || recompute || reanalyse_shlibs)) { match = MATCH_ALL; } else if ((argc == 0 && match != MATCH_ALL) || !(dcheck || checksums || recompute || reanalyse_shlibs)) { usage_check(); return (EX_USAGE); } if (recompute || reanalyse_shlibs) ret = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); else ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENODB) { warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to access the package database"); return (EX_NOPERM); } else if (ret != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_ADVISORY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an advisory lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } i = 0; nbdone = 0; do { /* XXX: This is really quirky, it would be cleaner to pass * in multiple matches and only run this top-loop once. */ if ((it = pkgdb_query(db, argv[i], match)) == NULL) { rc = EX_IOERR; goto cleanup; } if (msg == NULL) msg = sbuf_new_auto(); if (!verbose) { if (match == MATCH_ALL) progressbar_start("Checking all packages"); else { sbuf_printf(msg, "Checking %s", argv[i]); sbuf_finish(msg); progressbar_start(sbuf_data(msg)); } processed = 0; total = pkgdb_it_count(it); } else { if (match == MATCH_ALL) nbactions = pkgdb_it_count(it); else nbactions = argc; } while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) { if (!verbose) progressbar_tick(processed, total); else { ++nbdone; job_status_begin(msg); pkg_sbuf_printf(msg, "Checking %n-%v:", pkg, pkg); sbuf_flush(msg); } /* check for missing dependencies */ if (dcheck) { if (verbose) printf(" dependencies..."); nbpkgs += check_deps(db, pkg, &dh, noinstall); if (noinstall && nbpkgs > 0) { rc = EX_UNAVAILABLE; } } if (checksums) { if (verbose) printf(" checksums..."); if (pkg_test_filesum(pkg) != EPKG_OK) { rc = EX_DATAERR; } } if (recompute) { if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) { if (verbose) printf(" recomputing..."); if (pkg_recompute(db, pkg) != EPKG_OK) { rc = EX_DATAERR; } pkgdb_downgrade_lock(db, PKGDB_LOCK_EXCLUSIVE, PKGDB_LOCK_ADVISORY); } else { rc = EX_TEMPFAIL; } } if (reanalyse_shlibs) { if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) { if (verbose) printf(" shared libraries..."); if (pkgdb_reanalyse_shlibs(db, pkg) != EPKG_OK) { pkg_fprintf(stderr, "Failed to " "reanalyse for shlibs: " "%n-%v\n", pkg, pkg); rc = EX_UNAVAILABLE; } pkgdb_downgrade_lock(db, PKGDB_LOCK_EXCLUSIVE, PKGDB_LOCK_ADVISORY); } else { rc = EX_TEMPFAIL; } } if (!verbose) ++processed; else printf(" done\n"); } if (!verbose) progressbar_tick(processed, total); if (msg != NULL) { sbuf_delete(msg); msg = NULL; } if (dcheck && nbpkgs > 0 && !noinstall) { printf("\n>>> Missing package dependencies were detected.\n"); printf(">>> Found %d issue(s) in the package database.\n\n", nbpkgs); if (pkgdb_upgrade_lock(db, PKGDB_LOCK_ADVISORY, PKGDB_LOCK_EXCLUSIVE) == EPKG_OK) { ret = fix_deps(db, &dh, nbpkgs, yes); if (ret == EPKG_OK) check_summary(db, &dh); else if (ret == EPKG_ENODB) { db = NULL; rc = EX_IOERR; } pkgdb_downgrade_lock(db, PKGDB_LOCK_EXCLUSIVE, PKGDB_LOCK_ADVISORY); if (rc == EX_IOERR) goto cleanup; } else { rc = EX_TEMPFAIL; goto cleanup; } } pkgdb_it_free(it); i++; } while (i < argc); cleanup: if (!verbose) progressbar_stop(); if (msg != NULL) sbuf_delete(msg); deps_free(&dh); pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_ADVISORY); pkgdb_close(db); return (rc); }
int exec_set(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; int ch; int i; bool yes; match_t match = MATCH_EXACT; int64_t newautomatic = -1; bool automatic = false; const char *errstr; char *neworigin = NULL; char *oldorigin = NULL; unsigned int loads = PKG_LOAD_BASIC; unsigned int sets = 0; int retcode; yes = pkg_object_bool(pkg_config_get("ASSUME_ALWAYS_YES")); while ((ch = getopt(argc, argv, "A:agio:xy")) != -1) { switch (ch) { case 'A': sets |= AUTOMATIC; newautomatic = strtonum(optarg, 0, 1, &errstr); if (errstr) errx(EX_USAGE, "Wrong value for -A. " "Expecting 0 or 1, got: %s (%s)", optarg, errstr); break; case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'o': sets |= ORIGIN; loads |= PKG_LOAD_DEPS; match = MATCH_ALL; oldorigin = strdup(optarg); neworigin = strrchr(oldorigin, ':'); if (neworigin == NULL) { free(oldorigin); errx(EX_USAGE, "Wrong format for -o. " "Expecting oldorigin:neworigin, got: %s", optarg); } *neworigin = '\0'; neworigin++; if (strrchr(oldorigin, '/') == NULL || strrchr(neworigin, '/') == NULL) { free(oldorigin); errx(EX_USAGE, "Bad origin format, got: %s", optarg); } break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: if (oldorigin != NULL) free(oldorigin); usage_set(); return (EX_USAGE); } } argc -= optind; argv += optind; if ((argc < 1 && match != MATCH_ALL) || (newautomatic == -1 && neworigin == NULL)) { usage_set(); return (EX_USAGE); } retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENODB) { if (match == MATCH_ALL) return (EX_OK); if (!quiet) warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to modify the package database"); return (EX_NOPERM); } else if (retcode != EPKG_OK) { warnx("Error accessing package database"); return (EX_SOFTWARE); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE, 0, 0) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (oldorigin != NULL) { match = MATCH_ALL; if ((it = pkgdb_query(db, oldorigin, MATCH_EXACT)) == NULL) { retcode = EX_IOERR; goto cleanup; } if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) != EPKG_OK) { pkg = NULL; /* fprintf(stderr, "%s not installed\n", oldorigin); free(oldorigin); pkgdb_it_free(it); pkgdb_close(db); return (EX_SOFTWARE);*/ } if (!yes) { if (pkg != NULL) yes = query_yesno(false, "Change origin from %S to %S for %n-%v? [y/N]: ", oldorigin, neworigin, pkg, pkg); else yes = query_yesno(false, "Change origin from %S to %S for all dependencies? " "[y/N]: ", oldorigin, neworigin); } if (pkg != NULL && yes) { if (pkgdb_set(db, pkg, PKG_SET_ORIGIN, neworigin) != EPKG_OK) { retcode = EX_IOERR; goto cleanup; } } pkgdb_it_free(it); } i = 0; do { bool save_yes = yes; if ((it = pkgdb_query(db, argv[i], match)) == NULL) { retcode = EX_IOERR; goto cleanup; } while (pkgdb_it_next(it, &pkg, loads) == EPKG_OK) { if ((sets & AUTOMATIC) == AUTOMATIC) { pkg_get(pkg, PKG_AUTOMATIC, &automatic); if (automatic == newautomatic) continue; if (!yes) { if (newautomatic) yes = query_yesno(false, "Mark %n-%v as automatically installed? [y/N]: ", pkg, pkg); else yes = query_yesno(false, "Mark %n-%v as not automatically installed? [y/N]: ", pkg, pkg); } if (yes) pkgdb_set(db, pkg, PKG_SET_AUTOMATIC, newautomatic); yes = save_yes; } if ((sets & ORIGIN) == ORIGIN) { struct pkg_dep *d = NULL; while (pkg_deps(pkg, &d) == EPKG_OK) { /* * Do not query user when he has already * been queried. */ if (pkgdb_set(db, pkg, PKG_SET_DEPORIGIN, oldorigin, neworigin) != EPKG_OK) { retcode = EX_IOERR; goto cleanup; } } } } pkgdb_it_free(it); i++; } while (i < argc); cleanup: if (oldorigin) free(oldorigin); if (pkg != NULL) pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); return (retcode); }
int exec_register(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb *db = NULL; const char *plist = NULL; const char *mdir = NULL; const char *mfile = NULL; const char *input_path = NULL; const char *location = NULL; bool legacy = false; bool testing_mode = false; int ch; int ret = EPKG_OK; int retcode = EX_OK; /* options descriptor */ struct option longopts[] = { { "automatic", no_argument, NULL, 'A' }, { "debug", no_argument, NULL, 'd' }, { "legacy", no_argument, NULL, 'l' }, { "manifest", required_argument, NULL, 'M' }, { "metadata", required_argument, NULL, 'm' }, { "plist", required_argument, NULL, 'f' }, { "relocate", required_argument, NULL, 1 }, { "root", required_argument, NULL, 'i' }, { "test", no_argument, NULL, 't' }, { NULL, 0, NULL, 0}, }; if (pkg_new(&pkg, PKG_INSTALLED) != EPKG_OK) err(EX_OSERR, "malloc"); while ((ch = getopt_long(argc, argv, "+Adf:i:lM:m:t", longopts, NULL)) != -1) { switch (ch) { case 'A': case 'd': pkg_set(pkg, PKG_AUTOMATIC, (bool)true); break; case 'f': plist = optarg; break; case 'i': input_path = optarg; break; case 'l': legacy = true; break; case 'M': mfile = optarg; break; case 'm': mdir = optarg; break; case 't': testing_mode = true; break; case 1: location = optarg; break; default: warnx("Unrecognised option -%c\n", ch); usage_register(); pkg_free(pkg); return (EX_USAGE); } } retcode = pkgdb_access(PKGDB_MODE_READ | PKGDB_MODE_WRITE | PKGDB_MODE_CREATE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to register packages"); pkg_free(pkg); return (EX_NOPERM); } else if (retcode != EPKG_OK) { pkg_free(pkg); return (EX_IOERR); } else retcode = EX_OK; /* * Ideally, the +MANIFEST should be all that is necessary, * since it can contain all of the meta-data supplied by the * other files mentioned below. These are here for backwards * compatibility with the way the ports tree works with * pkg_tools. * * The -M option specifies one manifest file to read the * meta-data from, and overrides the use of legacy meta-data * inputs. * * Dependencies, shlibs, files etc. may be derived by * analysing the package files (maybe discovered as the * content of the staging directory) unless -t (testing_mode) * is used. */ if (mfile != NULL && mdir != NULL) { warnx("Cannot use both -m and -M together"); usage_register(); pkg_free(pkg); return (EX_USAGE); } if (mfile == NULL && mdir == NULL) { warnx("One of either -m or -M flags is required"); usage_register(); pkg_free(pkg); return (EX_USAGE); } if (testing_mode && input_path != NULL) { warnx("-i incompatible with -t option"); usage_register(); pkg_free(pkg); return (EX_USAGE); } ret = pkg_load_metadata(pkg, mfile, mdir, plist, input_path, testing_mode); if (ret != EPKG_OK) { pkg_free(pkg); return (EX_IOERR); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { pkg_free(pkg); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); pkg_free(pkg); warnx("Cannot get an exclusive lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } retcode = pkg_add_port(db, pkg, input_path, location, testing_mode); if (!legacy && retcode == EPKG_OK && messages != NULL) { printf("%s\n", utstring_body(messages)); } pkg_free(pkg); return (retcode != EPKG_OK ? EX_SOFTWARE : EX_OK); }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg_manifest_key *keys = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = NELEM(accepted_query_flags); struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "evaluate", required_argument, NULL, 'e' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "regex", no_argument, NULL, 'x' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+aCe:F:gix", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'e': match = MATCH_CONDITION; condition = optarg; break; case 'F': pkgname = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'x': match = MATCH_REGEX; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if (((argc == 1) ^ (match == MATCH_ALL)) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { pkg_manifest_keys_new(&keys); if (pkg_open(&pkg, pkgname, keys, 0) != EPKG_OK) { return (EX_IOERR); } pkg_manifest_keys_free(keys); print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (!quiet) warnx("No packages installed"); return (EX_OK); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != 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 (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { int nprinted = 0; for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) { retcode = EX_IOERR; goto cleanup; } while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { nprinted++; print_query(pkg, argv[0], multiline); } if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } if (nprinted == 0 && retcode == EX_OK) { /* ensure to return a non-zero status when no package were found. */ retcode = EX_UNAVAILABLE; } } cleanup: pkg_free(pkg); 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]; 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_stats(int argc, char **argv) { struct pkgdb *db = NULL; int64_t flatsize = 0; unsigned int opt = 0; char size[7]; int ch; bool show_bytes = false; struct option longopts[] = { { "bytes", no_argument, NULL, 'b' }, { "local", no_argument, NULL, 'l' }, { "quiet", no_argument, NULL, 'q' }, { "remote", no_argument, NULL, 'r' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+blqr", longopts, NULL)) != -1) { switch (ch) { case 'b': show_bytes = true; break; case 'l': opt |= STATS_LOCAL; break; case 'q': quiet = true; break; case 'r': opt |= STATS_REMOTE; break; default: usage_stats(); return (EX_USAGE); } } argc -= optind; argv += optind; /* default is to show everything we have */ if (opt == 0) opt |= (STATS_LOCAL | STATS_REMOTE); 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 (opt & STATS_LOCAL) { printf("Local package database:\n"); printf("\tInstalled packages: %" PRId64 "\n", pkgdb_stats(db, PKG_STATS_LOCAL_COUNT)); flatsize = pkgdb_stats(db, PKG_STATS_LOCAL_SIZE); if (show_bytes) printf("\tDisk space occupied: %" PRId64 "\n\n", flatsize); else { humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0); printf("\tDisk space occupied: %s\n\n", size); } } if ((opt & STATS_REMOTE) && pkg_repos_total_count() > 0) { printf("Remote package database(s):\n"); printf("\tNumber of repositories: %" PRId64 "\n", pkgdb_stats(db, PKG_STATS_REMOTE_REPOS)); printf("\tPackages available: %" PRId64 "\n", pkgdb_stats(db, PKG_STATS_REMOTE_COUNT)); printf("\tUnique packages: %" PRId64 "\n", pkgdb_stats(db, PKG_STATS_REMOTE_UNIQUE)); flatsize = pkgdb_stats(db, PKG_STATS_REMOTE_SIZE); if (show_bytes) printf("\tTotal size of packages: %" PRId64 "\n", flatsize); else { humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0); printf("\tTotal size of packages: %s\n", size); } } pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (EX_OK); }
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); }
static int exec_lock_unlock(int argc, char **argv, enum action action) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; const char *pkgname; int match = MATCH_EXACT; int retcode; int exitcode = EX_OK; int ch; bool show_locked = false; struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "glob", no_argument, NULL, 'g' }, { "show-locked", no_argument, NULL, 'l' }, { "quiet", no_argument, NULL, 'q' }, { "regex", no_argument, NULL, 'x' }, { "yes", no_argument, NULL, 'y' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "aCgilqxy", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'l': show_locked = true; break; case 'q': quiet = true; break; case 'x': match = MATCH_REGEX; break; case 'y': yes = true; break; default: usage_lock(); return (EX_USAGE); } } argc -= optind; argv += optind; if (!(match == MATCH_ALL && argc == 0) && argc != 1 && !show_locked) { usage_lock(); return (EX_USAGE); } if (match == MATCH_ALL) pkgname = NULL; else pkgname = argv[0]; retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, PKGDB_DB_LOCAL); if (retcode == EPKG_ENODB) { if (match == MATCH_ALL) return (EX_OK); if (!quiet) warnx("No packages installed. Nothing to do!"); return (EX_OK); } else if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to modify the package database"); return (EX_NOPERM); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); return (EX_SOFTWARE); } retcode = pkgdb_open(&db, PKGDB_DEFAULT); if (retcode != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_EXCLUSIVE) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get an exclusive lock on database. " "It is locked by another process"); return (EX_TEMPFAIL); } if (match == MATCH_ALL || argc != 0) { if ((it = pkgdb_query(db, pkgname, match)) == NULL) { exitcode = EX_IOERR; goto cleanup; } while ((retcode = pkgdb_it_next(it, &pkg, 0)) == EPKG_OK) { if (action == LOCK) retcode = do_lock(db, pkg); else retcode = do_unlock(db, pkg); if (retcode != EPKG_OK) { exitcode = EX_IOERR; goto cleanup; } } } if (show_locked) retcode = list_locked(db); if (retcode != EPKG_END) exitcode = EX_IOERR; cleanup: if (pkg != NULL) pkg_free(pkg); if (it != NULL) pkgdb_it_free(it); pkgdb_release_lock(db, PKGDB_LOCK_EXCLUSIVE); pkgdb_close(db); return (exitcode); }
int exec_clean(int argc, char **argv) { struct pkgdb *db = NULL; kh_sum_t *sumlist = NULL; dl_list dl; const char *cachedir; bool all = false; int retcode; int ch; int cachefd = -1; size_t total = 0; char size[8]; char *cksum; struct pkg_manifest_key *keys = NULL; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif 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")); cachefd = open(cachedir, O_DIRECTORY); if (cachefd == -1) { warn("Impossible to open %s", cachedir); return (EX_IOERR); } retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO); if (retcode == EPKG_ENOACCESS) { warnx("Insufficient privileges to clean old packages"); close(cachefd); return (EX_NOPERM); } else if (retcode == EPKG_ENODB) { warnx("No package database installed. Nothing to do!"); close(cachefd); return (EX_OK); } else if (retcode != EPKG_OK) { warnx("Error accessing the package database"); close(cachefd); return (EX_SOFTWARE); } retcode = EX_SOFTWARE; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { close(cachefd); return (EX_IOERR); } if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); close(cachefd); warnx("Cannot get a read lock on a database, it is locked by " "another process"); return (EX_TEMPFAIL); } #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ, CAP_LOOKUP, CAP_FSTATFS, CAP_FSTAT, CAP_UNLINKAT); if (cap_rights_limit(cachefd, &rights) < 0 && errno != ENOSYS ) { warn("cap_rights_limit() failed"); close(cachefd); return (EX_SOFTWARE); } if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); close(cachefd); return (EX_SOFTWARE); } #endif kv_init(dl); /* Build the list of out-of-date or obsolete packages */ pkg_manifest_keys_new(&keys); recursive_analysis(cachefd, db, cachedir, cachedir, &dl, &sumlist, all, &total); if (sumlist != NULL) { kh_foreach_value(sumlist, cksum, free(cksum)); kh_destroy_sum(sumlist); } if (kv_size(dl) == 0) { if (!quiet) printf("Nothing to do.\n"); retcode = EX_OK; goto cleanup; } humanize_number(size, sizeof(size), total, "B", HN_AUTOSCALE, HN_IEC_PREFIXES); if (!quiet) printf("The cleanup will free %s\n", size); if (!dry_run) { if (query_yesno(false, "\nProceed with cleaning the cache? ")) { retcode = delete_dellist(cachefd, cachedir, &dl, kv_size(dl)); } } else { retcode = EX_OK; } cleanup: pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); pkg_manifest_keys_free(keys); free_dellist(&dl); if (cachefd != -1) close(cachefd); return (retcode); }