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, MAXPATHLEN + 1)) == 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 (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) { free(pkgs); return (EPKG_FATAL); } pkg_jobs_set_flags(jobs, f); if (pkg_jobs_add(jobs, MATCH_EXACT, pkgs, nbpkgs) == EPKG_FATAL) { pkg_jobs_free(jobs); return (EPKG_FATAL); } if (pkg_jobs_solve(jobs) != EPKG_OK) { pkg_jobs_free(jobs); return (EPKG_FATAL); } if (pkg_jobs_count(jobs) == 0) { printf("\nUnable to find packages for installation.\n\n"); pkg_jobs_free(jobs); return (EPKG_FATAL); } /* print a summary before applying the jobs */ print_jobs_summary(jobs, "The following packages will be installed:\n\n"); if (yes == false) yes = query_yesno("\n>>> Try to fix the missing dependencies [y/N]: "); if (yes == true) pkg_jobs_apply(jobs); free(pkgs); pkg_jobs_free(jobs); return (EPKG_OK); }
static int fix_deps(struct pkgdb *db, struct deps_head *dh, int nbpkgs, bool yes) { struct pkg *pkg = NULL; struct pkgdb_it *it = NULL; struct pkg_jobs *jobs = NULL; struct deps_entry *e = NULL; char **pkgs = NULL; int i = 0; assert(db != NULL); assert(nbpkgs > 0); if ((pkgs = calloc(nbpkgs, MAXPATHLEN + 1)) == NULL) err(1, "calloc()"); STAILQ_FOREACH(e, dh, next) pkgs[i++] = e->origin; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EPKG_ENODB); if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) free(pkgs); if ((it = pkgdb_query_installs(db, MATCH_EXACT, nbpkgs, pkgs, NULL, false)) == NULL) { free(pkgs); pkg_jobs_free(jobs); } while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) { pkg_jobs_add(jobs, pkg); pkg = NULL; } if (pkg_jobs_is_empty(jobs)) { printf("\n>>> Unable to find packages for installation.\n\n"); return (EPKG_FATAL); } /* print a summary before applying the jobs */ pkg = NULL; print_jobs_summary(jobs, PKG_JOBS_INSTALL, "The following packages will be installed:\n\n"); if (yes == false) yes = query_yesno("\n>>> Try to fix the missing dependencies [y/N]: "); if (yes == true) pkg_jobs_apply(jobs, 0); free(pkgs); pkg_free(pkg); pkg_jobs_free(jobs); pkgdb_it_free(it); return (EPKG_OK); }
static int do_unlock(struct pkgdb *db, struct pkg *pkg) { if (!pkg_is_locked(pkg)) { if (!quiet) pkg_printf("%n-%v: already unlocked\n", pkg, pkg); return (EPKG_OK); } if (!query_yesno(false, "%n-%v: unlock this package? [y/N]: ", pkg, pkg)) return (EPKG_OK); if (!quiet) pkg_printf("Unlocking %n-%v\n", pkg, pkg); return (pkgdb_set(db, pkg, PKG_SET_LOCKED, (int64_t)false)); }
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_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_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_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_install(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb_it *it = NULL; struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode = 1; int ch; bool yes = false; int64_t dlsize = 0; int64_t oldsize = 0, newsize = 0; char size[7]; match_t match = MATCH_EXACT; while ((ch = getopt(argc, argv, "ygxXr:")) != -1) { switch (ch) { case 'y': yes = true; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'X': match = MATCH_EREGEX; break; case 'r': reponame = optarg; break; default: usage_install(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1) { usage_install(); return (EX_USAGE); } if (geteuid() != 0) { warnx("installing packages can only be done as root"); return (EX_NOPERM); } if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { return (EX_IOERR); } if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) { goto cleanup; } if ((it = pkgdb_query_installs(db, match, argc, argv, reponame)) == NULL) goto cleanup; while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) { pkg_jobs_add(jobs, pkg); pkg = NULL; } pkgdb_it_free(it); if (pkg_jobs_is_empty(jobs)) { printf("Nothing to do\n"); retcode = 0; goto cleanup; } /* print a summary before applying the jobs */ pkg = NULL; printf("The following packages will be installed:\n"); while (pkg_jobs(jobs, &pkg) == EPKG_OK) { const char *name, *version, *newversion; int64_t flatsize, newflatsize, pkgsize; pkg_get(pkg, PKG_NEWVERSION, &newversion, PKG_NAME, &name, PKG_VERSION, &version, PKG_FLATSIZE, &flatsize, PKG_NEW_FLATSIZE, &newflatsize, PKG_NEW_PKGSIZE, &pkgsize); dlsize += pkgsize; if (newversion != NULL) { printf("\tUpgrading %s: %s -> %s\n", name, version, newversion); oldsize += flatsize; newsize += flatsize; } else { newsize += flatsize; printf("\tInstalling %s: %s\n", name, version); } } if (oldsize > newsize) { newsize *= -1; humanize_number(size, sizeof(size), oldsize - newsize, "B", HN_AUTOSCALE, 0); printf("\nthe installation will save %s\n", size); } else { humanize_number(size, sizeof(size), newsize - oldsize, "B", HN_AUTOSCALE, 0); printf("\nthe installation will require %s more space\n", size); } humanize_number(size, sizeof(size), dlsize, "B", HN_AUTOSCALE, 0); printf("%s to be downloaded\n", size); if (yes == false) pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); if (yes == false) yes = query_yesno("\nProceed with installing packages [y/N]: "); if (yes == true) if (pkg_jobs_apply(jobs, 0) != EPKG_OK) goto cleanup; retcode = 0; cleanup: pkg_jobs_free(jobs); pkgdb_close(db); return (retcode); }
int event_callback(void *data, struct pkg_event *ev) { struct pkg *pkg = NULL, *pkg_new, *pkg_old; int *debug = data; struct pkg_event_conflict *cur_conflict; const char *filename; if (msg_buf == NULL) { msg_buf = sbuf_new_auto(); } /* * If a progressbar has been interrupted by another event, then * we need to add a newline to prevent bad formatting. */ if (progress_started && ev->type != PKG_EVENT_PROGRESS_TICK && !progress_interrupted) { putchar('\n'); progress_interrupted = true; } switch(ev->type) { case PKG_EVENT_ERRNO: warnx("%s(%s): %s", ev->e_errno.func, ev->e_errno.arg, strerror(ev->e_errno.no)); break; case PKG_EVENT_ERROR: warnx("%s", ev->e_pkg_error.msg); break; case PKG_EVENT_NOTICE: if (!quiet) printf("%s\n", ev->e_pkg_notice.msg); break; case PKG_EVENT_DEVELOPER_MODE: warnx("DEVELOPER_MODE: %s", ev->e_pkg_error.msg); break; case PKG_EVENT_UPDATE_ADD: if (quiet || !isatty(STDOUT_FILENO)) break; printf("\rPushing new entries %d/%d", ev->e_upd_add.done, ev->e_upd_add.total); if (ev->e_upd_add.total == ev->e_upd_add.done) printf("\n"); break; case PKG_EVENT_UPDATE_REMOVE: if (quiet || !isatty(STDOUT_FILENO)) break; printf("\rRemoving entries %d/%d", ev->e_upd_remove.done, ev->e_upd_remove.total); if (ev->e_upd_remove.total == ev->e_upd_remove.done) printf("\n"); break; case PKG_EVENT_FETCH_BEGIN: if (quiet) break; filename = strrchr(ev->e_fetching.url, '/'); if (filename != NULL) { filename++; } else { /* * We failed at being smart, so display * the entire url. */ filename = ev->e_fetching.url; } job_status_begin(msg_buf); progress_debit = true; sbuf_printf(msg_buf, "Fetching %s", filename); break; case PKG_EVENT_FETCH_FINISHED: progress_debit = false; break; case PKG_EVENT_INSTALL_BEGIN: if (quiet) break; else { nbdone++; job_status_begin(msg_buf); pkg = ev->e_install_begin.pkg; pkg_sbuf_printf(msg_buf, "Installing %n-%v...\n", pkg, pkg); sbuf_finish(msg_buf); printf("%s", sbuf_data(msg_buf)); } break; case PKG_EVENT_INSTALL_FINISHED: if (quiet) break; pkg = ev->e_install_finished.pkg; if (pkg_has_message(pkg)) { if (messages == NULL) messages = sbuf_new_auto(); pkg_sbuf_printf(messages, "Message for %n-%v:\n%M\n", pkg, pkg, pkg); } break; case PKG_EVENT_EXTRACT_BEGIN: if (quiet) break; else { job_status_begin(msg_buf); pkg = ev->e_install_begin.pkg; pkg_sbuf_printf(msg_buf, "Extracting %n-%v", pkg, pkg); } break; case PKG_EVENT_EXTRACT_FINISHED: break; case PKG_EVENT_ADD_DEPS_BEGIN: ++add_deps_depth; break; case PKG_EVENT_ADD_DEPS_FINISHED: --add_deps_depth; break; case PKG_EVENT_INTEGRITYCHECK_BEGIN: if (quiet) break; printf("Checking integrity..."); break; case PKG_EVENT_INTEGRITYCHECK_FINISHED: if (quiet) break; printf(" done (%d conflicting)\n", ev->e_integrity_finished.conflicting); break; case PKG_EVENT_INTEGRITYCHECK_CONFLICT: if (*debug == 0) break; printf("\nConflict found on path %s between %s and ", ev->e_integrity_conflict.pkg_path, ev->e_integrity_conflict.pkg_uid); cur_conflict = ev->e_integrity_conflict.conflicts; while (cur_conflict) { if (cur_conflict->next) printf("%s, ", cur_conflict->uid); else printf("%s", cur_conflict->uid); cur_conflict = cur_conflict->next; } printf("\n"); break; case PKG_EVENT_DEINSTALL_BEGIN: if (quiet) break; nbdone++; job_status_begin(msg_buf); pkg = ev->e_install_begin.pkg; pkg_sbuf_printf(msg_buf, "Deinstalling %n-%v...\n", pkg, pkg); sbuf_finish(msg_buf); printf("%s", sbuf_data(msg_buf)); break; case PKG_EVENT_DEINSTALL_FINISHED: if (quiet) break; break; case PKG_EVENT_DELETE_FILES_BEGIN: if (quiet) break; else { job_status_begin(msg_buf); pkg = ev->e_install_begin.pkg; pkg_sbuf_printf(msg_buf, "Deleting files for %n-%v", pkg, pkg); } break; case PKG_EVENT_DELETE_FILES_FINISHED: break; case PKG_EVENT_UPGRADE_BEGIN: if (quiet) break; pkg_new = ev->e_upgrade_begin.n; pkg_old = ev->e_upgrade_begin.o; nbdone++; job_status_begin(msg_buf); switch (pkg_version_change_between(pkg_new, pkg_old)) { case PKG_DOWNGRADE: pkg_sbuf_printf(msg_buf, "Downgrading %n from %v to %v...\n", pkg_new, pkg_old, pkg_new); break; case PKG_REINSTALL: pkg_sbuf_printf(msg_buf, "Reinstalling %n-%v...\n", pkg_old, pkg_old); break; case PKG_UPGRADE: pkg_sbuf_printf(msg_buf, "Upgrading %n from %v to %v...\n", pkg_new, pkg_old, pkg_new); break; } sbuf_finish(msg_buf); printf("%s", sbuf_data(msg_buf)); break; case PKG_EVENT_UPGRADE_FINISHED: if (quiet) break; pkg_new = ev->e_upgrade_finished.n; if (pkg_has_message(pkg_new)) { if (messages == NULL) messages = sbuf_new_auto(); pkg_sbuf_printf(messages, "Message for %n-%v:\n %M\n", pkg_new, pkg_new, pkg_new); } break; case PKG_EVENT_LOCKED: pkg = ev->e_locked.pkg; pkg_printf("\n%n-%v is locked and may not be modified\n", pkg, pkg); break; case PKG_EVENT_REQUIRED: pkg = ev->e_required.pkg; pkg_printf("\n%n-%v is required by: %r%{%rn-%rv%| %}", pkg, pkg, pkg); if (ev->e_required.force == 1) fprintf(stderr, ", deleting anyway\n"); else fprintf(stderr, "\n"); break; case PKG_EVENT_ALREADY_INSTALLED: if (quiet) break; pkg = ev->e_already_installed.pkg; pkg_printf("the most recent version of %n-%v is already installed\n", pkg, pkg); break; case PKG_EVENT_NOT_FOUND: printf("Package '%s' was not found in " "the repositories\n", ev->e_not_found.pkg_name); break; case PKG_EVENT_MISSING_DEP: warnx("Missing dependency '%s-%s'", pkg_dep_name(ev->e_missing_dep.dep), pkg_dep_version(ev->e_missing_dep.dep)); break; case PKG_EVENT_NOREMOTEDB: fprintf(stderr, "Unable to open remote database \"%s\". " "Try running '%s update' first.\n", ev->e_remotedb.repo, getprogname()); break; case PKG_EVENT_NOLOCALDB: fprintf(stderr, "Local package database nonexistent!\n"); break; case PKG_EVENT_NEWPKGVERSION: newpkgversion = true; printf("New version of pkg detected; it needs to be " "installed first.\n"); break; case PKG_EVENT_FILE_MISMATCH: pkg = ev->e_file_mismatch.pkg; pkg_fprintf(stderr, "%n-%v: checksum mismatch for %Fn\n", pkg, pkg, ev->e_file_mismatch.file); break; case PKG_EVENT_PLUGIN_ERRNO: warnx("%s: %s(%s): %s", pkg_plugin_get(ev->e_plugin_errno.plugin, PKG_PLUGIN_NAME), ev->e_plugin_errno.func, ev->e_plugin_errno.arg, strerror(ev->e_plugin_errno.no)); break; case PKG_EVENT_PLUGIN_ERROR: warnx("%s: %s", pkg_plugin_get(ev->e_plugin_error.plugin, PKG_PLUGIN_NAME), ev->e_plugin_error.msg); break; case PKG_EVENT_PLUGIN_INFO: if (quiet) break; printf("%s: %s\n", pkg_plugin_get(ev->e_plugin_info.plugin, PKG_PLUGIN_NAME), ev->e_plugin_info.msg); break; case PKG_EVENT_INCREMENTAL_UPDATE: if (!quiet) printf("%s repository update completed. %d packages processed.\n", ev->e_incremental_update.reponame, ev->e_incremental_update.processed); break; case PKG_EVENT_DEBUG: fprintf(stderr, "DBG(%d)[%d]> %s\n", ev->e_debug.level, (int)getpid(), ev->e_debug.msg); break; case PKG_EVENT_QUERY_YESNO: return ( ev->e_query_yesno.deft ? query_yesno(true, ev->e_query_yesno.msg, "[Y/n]") : query_yesno(false, ev->e_query_yesno.msg, "[y/N]") ); break; case PKG_EVENT_QUERY_SELECT: return query_select(ev->e_query_select.msg, ev->e_query_select.items, ev->e_query_select.ncnt, ev->e_query_select.deft); break; case PKG_EVENT_SANDBOX_CALL: return ( event_sandboxed_call(ev->e_sandbox_call.call, ev->e_sandbox_call.fd, ev->e_sandbox_call.userdata) ); break; case PKG_EVENT_SANDBOX_GET_STRING: return ( event_sandboxed_get_string(ev->e_sandbox_call_str.call, ev->e_sandbox_call_str.result, ev->e_sandbox_call_str.len, ev->e_sandbox_call_str.userdata) ); break; case PKG_EVENT_PROGRESS_START: progressbar_start(ev->e_progress_start.msg); break; case PKG_EVENT_PROGRESS_TICK: progressbar_tick(ev->e_progress_tick.current, ev->e_progress_tick.total); break; case PKG_EVENT_BACKUP: sbuf_cat(msg_buf, "Backing up"); sbuf_finish(msg_buf); break; case PKG_EVENT_RESTORE: sbuf_cat(msg_buf, "Restoring"); sbuf_finish(msg_buf); break; default: break; } return 0; }
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; bool rc; 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 (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"); rc = query_yesno(false, "\n>>> Try to fix the missing dependencies? [y/N]: "); if (rc) { 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: free(pkgs); if (jobs != NULL) pkg_jobs_free(jobs); return (EPKG_OK); }
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_autoremove(__unused int argc, __unused char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; int retcode; int ch; bool yes = false; bool dry_run = false; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_FORCE; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); while ((ch = getopt(argc, argv, "ynq")) != -1) { switch (ch) { case 'q': quiet = true; break; case 'y': yes = true; break; case 'n': f |= PKG_FLAG_DRY_RUN; dry_run = 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); } /* 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 (!yes && !dry_run) yes = query_yesno( "\nProceed with deinstalling packages [y/N]: "); if (dry_run) yes = false; } if (!yes || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK) { retcode = EX_SOFTWARE; goto cleanup; } pkgdb_compact(db); retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_close(db); return (retcode); }
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_clean(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg *p = NULL; FTS *fts = NULL; FTSENT *ent = NULL; struct dl_head dl = STAILQ_HEAD_INITIALIZER(dl); const char *cachedir; char *paths[2]; char *repopath; bool dry_run = false; bool yes; int retcode = EX_SOFTWARE; int ret; int ch; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); while ((ch = getopt(argc, argv, "nqy")) != -1) { switch (ch) { 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; if (pkg_config_string(PKG_CONFIG_CACHEDIR, &cachedir) != EPKG_OK) { warnx("Cannot get cachedir config entry"); return 1; } paths[0] = __DECONST(char*, cachedir); paths[1] = NULL; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { goto cleanup; } 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 */ while ((ent = fts_read(fts)) != NULL) { const char *origin, *pkgrepopath; if (ent->fts_info != FTS_F) continue; repopath = ent->fts_path + strlen(cachedir); if (repopath[0] == '/') repopath++; if (pkg_open(&pkg, ent->fts_path) != EPKG_OK) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } pkg_get(pkg, PKG_ORIGIN, &origin); it = pkgdb_search(db, origin, MATCH_EXACT, FIELD_ORIGIN, FIELD_NONE, NULL); if (it == NULL) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } if ((ret = pkgdb_it_next(it, &p, PKG_LOAD_BASIC)) == EPKG_FATAL) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } pkg_get(p, PKG_REPOPATH, &pkgrepopath); if (ret == EPKG_END) { ret = add_to_dellist(&dl, REMOVED, ent->fts_path, origin, NULL, NULL); } else if (strcmp(repopath, pkgrepopath)) { const char *newname; const char *newversion; pkg_get(p, PKG_NAME, &newname, PKG_VERSION, &newversion); ret = add_to_dellist(&dl, OUT_OF_DATE, ent->fts_path, origin, newname, newversion); } else { char local_cksum[SHA256_DIGEST_LENGTH * 2 +1]; const char *cksum; pkg_get(p, PKG_CKSUM, &cksum); if (hash_file(ent->fts_path, local_cksum) == EPKG_OK) { if (strcmp(cksum, local_cksum) != 0) { ret = add_to_dellist(&dl, CKSUM_MISMATCH, ent->fts_path, origin, NULL, NULL); } } } if (ret != EPKG_OK && ret != EPKG_END) { retcode = EX_OSERR; /* out of memory */ goto cleanup; } pkgdb_it_free(it); } if (STAILQ_EMPTY(&dl)) { if (!quiet) printf("Nothing to do.\n"); retcode = EX_OK; goto cleanup; } if (dry_run || !yes || !quiet) display_dellist(&dl, cachedir); if (!dry_run) { if (!yes) yes = query_yesno( "\nProceed with cleaning cache [y/N]: "); if (yes) retcode = delete_dellist(&dl); } else retcode = EX_OK; cleanup: free_dellist(&dl); pkg_free(pkg); pkg_free(p); if (fts != NULL) fts_close(fts); if (db != NULL) pkgdb_close(db); return (retcode); }
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 auto_update; bool upgrades_for_installed = false; bool yes; unsigned mode; match_t match = MATCH_EXACT; pkg_flags f = PKG_FLAG_NONE; pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update); pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); while ((ch = getopt(argc, argv, "adgiqr:Uuxy")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'd': f |= PKG_FLAG_WITH_DEPS; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'U': auto_update = 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 '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)) != EPKG_OK) return (retcode); if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EX_IOERR); 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"); if (!yes) yes = query_yesno("\nProceed with fetching packages [y/N]: "); } if (!yes || pkg_jobs_apply(jobs) != EPKG_OK) goto cleanup; retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_close(db); return (retcode); }
int exec_delete(int argc, char **argv) { struct pkg_jobs *jobs = NULL; struct pkgdb *db = NULL; match_t match = MATCH_EXACT; int ch; bool force = false; bool yes; bool dry_run = false; int retcode = EX_SOFTWARE; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_NONE; int i; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); while ((ch = getopt(argc, argv, "aDfginqRxy")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; 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; dry_run = true; break; case 'q': quiet = true; break; case 'R': f |= PKG_FLAG_RECURSIVE; 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); } 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 privilege to delete packages"); 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 (pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db) != EPKG_OK) { pkgdb_close(db); return (EX_IOERR); } 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) goto cleanup; if ((pkg_jobs_find(jobs, "ports-mgmt/pkg", NULL) == EPKG_OK) && !force) { warnx("You are about to delete 'ports-mgmt/pkg' which is really " "dangerous, you can't do that without specifying -f"); 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) { print_jobs_summary(jobs, "Deinstallation has been requested for the following %d packages:\n\n", nbactions); if (!yes && !dry_run) yes = query_yesno( "\nProceed with deinstalling packages [y/N]: "); if (dry_run) yes = false; } if (!yes || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK) goto cleanup; pkgdb_compact(db); retcode = EX_OK; cleanup: 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; bool yes_flag = false; bool yes = yes_flag; match_t match = MATCH_EXACT; int newautomatic = -1; bool automatic = false; const char *errstr; const char *name; const char *version; char *neworigin = NULL; char *oldorigin = NULL; unsigned int loads = PKG_LOAD_BASIC; unsigned int sets = 0; int retcode; while ((ch = getopt(argc, argv, "ayA:kxgo:")) != -1) { switch (ch) { case 'y': yes_flag = true; break; case 'a': match = MATCH_ALL; break; case 'x': match = MATCH_REGEX; break; case 'g': match = MATCH_GLOB; break; 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 '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; 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 privilege to modify 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 (!yes_flag) pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes_flag); if (oldorigin != NULL) { yes = yes_flag; match = MATCH_ALL; if ((it = pkgdb_query(db, oldorigin, MATCH_EXACT)) == NULL) { pkgdb_close(db); return (EX_IOERR); } 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 (pkg != NULL) pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version); if (!yes) { if (pkg != NULL) yes = query_yesno("Change origin from %s to %s for %s-%s? [y/N]: ", oldorigin, neworigin, name, version); else yes = query_yesno("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) return (EX_IOERR); } pkgdb_it_free(it); } i = 0; do { if ((it = pkgdb_query(db, argv[i], match)) == NULL) { free(oldorigin); pkgdb_close(db); return (EX_IOERR); } while (pkgdb_it_next(it, &pkg, loads) == EPKG_OK) { yes = yes_flag; if ((sets & AUTOMATIC) == AUTOMATIC) { pkg_get(pkg, PKG_AUTOMATIC, &automatic); if (automatic == newautomatic) continue; if (!yes) { pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version); if (newautomatic) yes = query_yesno("Mark %s-%s as automatically installed? [y/N]: ", name, version); else yes = query_yesno("Mark %s-%s as not automatically installed? [y/N]: ", name, version); } if (yes) pkgdb_set(db, pkg, PKG_SET_AUTOMATIC, newautomatic); } 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) return (EX_IOERR); } } } pkgdb_it_free(it); i++; } while (i < argc); free(oldorigin); pkg_free(pkg); pkgdb_close(db); return (EX_OK); }
int exec_fetch(int argc, char **argv) { struct pkg *pkg = NULL; struct pkgdb_it *it = NULL; struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode = EXIT_FAILURE; int ch; int flags = PKG_LOAD_BASIC; bool yes = false; bool auto_update = true; match_t match = MATCH_EXACT; while ((ch = getopt(argc, argv, "ygxXr:qaLd")) != -1) { switch (ch) { case 'y': yes = true; break; case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'X': match = MATCH_EREGEX; break; case 'r': reponame = optarg; break; case 'q': quiet = true; break; case 'L': auto_update = false; break; case 'd': flags |= PKG_LOAD_DEPS; break; default: usage_fetch(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1 && match != MATCH_ALL) { usage_fetch(); return (EX_USAGE); } /* TODO: Allow the user to specify an output directory via -o outdir */ if (geteuid() != 0) { warnx("Fetching packages can only be done as root"); return (EX_NOPERM); } /* first update the remote repositories if needed */ if (auto_update && (retcode = pkgcli_update()) != EPKG_OK) return (retcode); if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { return (EX_IOERR); } if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK) { goto cleanup; } if ((it = pkgdb_query_fetch(db, match, argc, argv, reponame, flags)) == NULL) goto cleanup; while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) { pkg_jobs_add(jobs, pkg); pkg = NULL; } pkgdb_it_free(it); if (pkg_jobs_is_empty(jobs)) goto cleanup; if (!quiet) { print_jobs_summary(jobs, PKG_JOBS_FETCH, "The following packages will be fetched:\n\n"); if (!yes) pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); if (!yes) yes = query_yesno("\nProceed with fetching packages [y/N]: "); } if (yes) if (pkg_jobs_apply(jobs, 0) != EPKG_OK) goto cleanup; retcode = EXIT_SUCCESS; cleanup: pkg_jobs_free(jobs); 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; bool yes; bool dry_run = false; bool auto_update; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update); while ((ch = getopt(argc, argv, "fLnqFr:Uy")) != -1) { switch (ch) { case 'f': f |= PKG_FLAG_FORCE; break; case 'I': f |= PKG_FLAG_NOSCRIPT; break; case 'L': warnx("!!! The -L flag is deprecated and will be removed. Please use -U now."); /* FALLTHROUGH */ case 'U': auto_update = false; break; case 'n': f |= PKG_FLAG_DRY_RUN; dry_run = true; break; case 'F': f |= PKG_FLAG_SKIP_INSTALL; break; case 'q': quiet = true; break; case 'r': reponame = optarg; break; case 'y': yes = true; break; default: usage_upgrade(); return (EX_USAGE); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 0) { usage_upgrade(); return (EX_USAGE); } if (dry_run) 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) { 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 (!dry_run && auto_update && (updcode = pkgcli_update(false)) != EPKG_OK) return (updcode); if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EX_IOERR); 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; if ((nbactions = pkg_jobs_count(jobs)) == 0) { if (!quiet) printf("Nothing to do\n"); retcode = EXIT_SUCCESS; goto cleanup; } if (!quiet || dry_run) { print_jobs_summary(jobs, "Uprgades have been requested for the following %d " "packages:\n\n", nbactions); if (!yes && !dry_run) yes = query_yesno("\nProceed with upgrading " "packages [y/N]: "); if (dry_run) yes = false; } if (yes && pkg_jobs_apply(jobs) != EPKG_OK) goto cleanup; if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } retcode = EXIT_SUCCESS; cleanup: pkg_jobs_free(jobs); pkgdb_close(db); return (retcode); }
int exec_fetch(int argc, char **argv) { struct pkgdb *db = NULL; struct pkg_jobs *jobs = NULL; const char *reponame = NULL; int retcode = EX_SOFTWARE; int ch; bool force = false; bool yes = false; bool auto_update = true; match_t match = MATCH_EXACT; pkg_flags f = PKG_FLAG_NONE; while ((ch = getopt(argc, argv, "ygxr:qaLd")) != -1) { switch (ch) { case 'y': yes = true; break; case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'r': reponame = optarg; break; case 'q': quiet = true; break; case 'L': auto_update = false; break; case 'd': f |= PKG_FLAG_WITH_DEPS; force = true; break; default: usage_fetch(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc < 1 && match != MATCH_ALL) { usage_fetch(); return (EX_USAGE); } /* TODO: Allow the user to specify an output directory via -o outdir */ if (geteuid() != 0) { warnx("Fetching packages can only be done as root"); return (EX_NOPERM); } /* first update the remote repositories if needed */ if (auto_update && (retcode = pkgcli_update(false)) != EPKG_OK) return (retcode); if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EX_IOERR); if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK) goto cleanup; pkg_jobs_set_flags(jobs, f); if (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"); if (!yes) pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); if (!yes) yes = query_yesno("\nProceed with fetching packages [y/N]: "); } if (!yes || pkg_jobs_apply(jobs) != EPKG_OK) goto cleanup; retcode = EX_OK; cleanup: 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_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_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; bool yes; bool auto_update; match_t match = MATCH_EXACT; bool dry_run = false; nbactions = nbdone = 0; pkg_flags f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); pkg_config_bool(PKG_CONFIG_REPO_AUTOUPDATE, &auto_update); while ((ch = getopt(argc, argv, "AfgIiFnqRr:Uxy")) != -1) { switch (ch) { case 'A': f |= PKG_FLAG_AUTOMATIC; break; case 'f': f |= PKG_FLAG_FORCE; break; case 'g': match = MATCH_GLOB; break; case 'I': f |= PKG_FLAG_NOSCRIPT; break; case 'F': f |= PKG_FLAG_SKIP_INSTALL; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'U': auto_update = false; break; case 'n': f |= PKG_FLAG_DRY_RUN; dry_run = true; break; case 'q': quiet = true; break; case 'R': f |= PKG_FLAG_RECURSIVE; break; case 'r': reponame = optarg; 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) 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 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)) != EPKG_OK) return (updcode); if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EX_IOERR); if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, 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_add(jobs, match, argv, argc) == EPKG_FATAL) goto cleanup; if (pkg_jobs_solve(jobs) != EPKG_OK) goto cleanup; if ((nbactions = pkg_jobs_count(jobs)) > 0) { /* print a summary before applying the jobs */ if (!quiet || dry_run) { print_jobs_summary(jobs, "The following %d packages will be installed:\n\n", nbactions); if (!yes && !dry_run) yes = query_yesno( "\nProceed with installing packages [y/N]: "); if (dry_run) yes = false; } if (yes && pkg_jobs_apply(jobs) != EPKG_OK) goto cleanup; if (messages != NULL) { sbuf_finish(messages); printf("%s", sbuf_data(messages)); } } retcode = EX_OK; cleanup: pkg_jobs_free(jobs); pkgdb_close(db); if (!yes && newpkgversion) newpkgversion = false; return (retcode); }
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); }