autoremove.c
1 /*- 2 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org> 3 * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com> 4 * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org> 5 * Copyright (c) 2016 Vsevolod Stakhov <vsevolod@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer 13 * in this position and unchanged. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <err.h> 31 #include <getopt.h> 32 #include <stdio.h> 33 #include <unistd.h> 34 35 #include <pkg.h> 36 37 #include "pkgcli.h" 38 39 void 40 usage_autoremove(void) 41 { 42 fprintf(stderr, "Usage: pkg autoremove [-Dynq]\n\n"); 43 fprintf(stderr, "For more information see 'pkg help autoremove'.\n"); 44 } 45 46 int 47 exec_autoremove(int argc, char **argv) 48 { 49 struct pkgdb *db = NULL; 50 struct pkg_jobs *jobs = NULL; 51 int retcode = EXIT_SUCCESS; 52 int ch; 53 int nbactions = 0; 54 pkg_flags f = PKG_FLAG_FORCE; 55 bool rc = false; 56 int lock_type = PKGDB_LOCK_ADVISORY; 57 58 struct option longopts[] = { 59 { "dry-run", no_argument, NULL, 'n' }, 60 { "no-scripts", no_argument, NULL, 'D' }, 61 { "quiet", no_argument, NULL, 'q' }, 62 { "yes", no_argument, NULL, 'y' }, 63 { NULL, 0, NULL, 0 }, 64 }; 65 66 while ((ch = getopt_long(argc, argv, "+Dnqy", longopts, NULL)) != -1) { 67 switch (ch) { 68 case 'n': 69 f |= PKG_FLAG_DRY_RUN; 70 dry_run = true; 71 lock_type = PKGDB_LOCK_READONLY; 72 break; 73 case 'D': 74 f |= PKG_FLAG_NOSCRIPT; 75 break; 76 case 'q': 77 quiet = true; 78 break; 79 case 'y': 80 yes = true; 81 break; 82 default: 83 usage_autoremove(); 84 return (EXIT_FAILURE); 85 } 86 } 87 argc -= optind; 88 89 if (argc != 0) { 90 usage_autoremove(); 91 return (EXIT_FAILURE); 92 } 93 94 if (dry_run) 95 retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); 96 else 97 retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE, 98 PKGDB_DB_LOCAL); 99 100 if (retcode == EPKG_ENOACCESS) { 101 warnx("Insufficient privileges to autoremove packages"); 102 return (EXIT_FAILURE); 103 } else if (retcode == EPKG_ENODB) { 104 warnx("No packages installed. Nothing to do!"); 105 return (EXIT_SUCCESS); 106 } else if (retcode != EPKG_OK) { 107 warnx("Error accessing the package database"); 108 return (EXIT_FAILURE); 109 } 110 111 if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { 112 return (EXIT_FAILURE); 113 } 114 115 if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) { 116 pkgdb_close(db); 117 warnx("Cannot get an advisory lock on a database, it is locked by another process"); 118 return (EXIT_FAILURE); 119 } 120 /* Always force packages to be removed */ 121 if (pkg_jobs_new(&jobs, PKG_JOBS_AUTOREMOVE, db) != EPKG_OK) { 122 pkgdb_close(db); 123 return (EXIT_FAILURE); 124 } 125 126 pkg_jobs_set_flags(jobs, f); 127 128 if ((retcode = pkg_jobs_solve(jobs)) != EPKG_OK) { 129 retcode = EXIT_FAILURE; 130 goto cleanup; 131 } 132 133 if ((nbactions = pkg_jobs_count(jobs)) == 0) { 134 if (!quiet) 135 printf("Nothing to do.\n"); 136 goto cleanup; 137 } 138 139 if (!quiet || dry_run) { 140 print_jobs_summary(jobs, 141 "Deinstallation has been requested for the following %d packages:\n\n", nbactions); 142 if (!dry_run) 143 rc = query_yesno(false, 144 "\nProceed with deinstalling packages? "); 145 } 146 if ((yes || rc ) && !dry_run && ((retcode = pkg_jobs_apply(jobs)) != EPKG_OK)) { 147 goto cleanup; 148 } 149 150 if (!yes && !rc) 151 retcode = EXIT_FAILURE; 152 153 pkgdb_compact(db); 154 155 cleanup: 156 pkg_jobs_free(jobs); 157 pkgdb_release_lock(db, lock_type); 158 pkgdb_close(db); 159 160 return (retcode); 161 }