libalpm
Arch Linux Package Manager Library
|
00001 /* 00002 * remove.c 00003 * 00004 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> 00005 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include <fnmatch.h> 00022 #include <stdlib.h> 00023 #include <stdio.h> 00024 00025 #include <alpm.h> 00026 #include <alpm_list.h> 00027 00028 /* pacman */ 00029 #include "pacman.h" 00030 #include "util.h" 00031 #include "conf.h" 00032 00033 static int fnmatch_cmp(const void *pattern, const void *string) 00034 { 00035 return fnmatch(pattern, string, 0); 00036 } 00037 00038 static int remove_target(const char *target) 00039 { 00040 alpm_pkg_t *pkg; 00041 alpm_db_t *db_local = alpm_option_get_localdb(config->handle); 00042 alpm_list_t *p; 00043 00044 if((pkg = alpm_db_get_pkg(db_local, target)) != NULL) { 00045 if(alpm_remove_pkg(config->handle, pkg) == -1) { 00046 pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", target, 00047 alpm_strerror(alpm_errno(config->handle))); 00048 return -1; 00049 } 00050 config->explicit_removes = alpm_list_add(config->explicit_removes, pkg); 00051 return 0; 00052 } 00053 00054 /* fallback to group */ 00055 alpm_group_t *grp = alpm_db_readgroup(db_local, target); 00056 if(grp == NULL) { 00057 pm_printf(ALPM_LOG_ERROR, "'%s': target not found\n", target); 00058 return -1; 00059 } 00060 for(p = grp->packages; p; p = alpm_list_next(p)) { 00061 pkg = p->data; 00062 if(alpm_remove_pkg(config->handle, pkg) == -1) { 00063 pm_printf(ALPM_LOG_ERROR, "'%s': %s\n", target, 00064 alpm_strerror(alpm_errno(config->handle))); 00065 return -1; 00066 } 00067 config->explicit_removes = alpm_list_add(config->explicit_removes, pkg); 00068 } 00069 return 0; 00070 } 00071 00072 /** 00073 * @brief Remove a specified list of packages. 00074 * 00075 * @param targets a list of packages (as strings) to remove from the system 00076 * 00077 * @return 0 on success, 1 on failure 00078 */ 00079 int pacman_remove(alpm_list_t *targets) 00080 { 00081 int retval = 0; 00082 alpm_list_t *i, *data = NULL; 00083 00084 if(targets == NULL) { 00085 pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n")); 00086 return 1; 00087 } 00088 00089 /* Step 0: create a new transaction */ 00090 if(trans_init(config->flags, 0) == -1) { 00091 return 1; 00092 } 00093 00094 /* Step 1: add targets to the created transaction */ 00095 for(i = targets; i; i = alpm_list_next(i)) { 00096 char *target = i->data; 00097 char *targ = strchr(target, '/'); 00098 if(targ && strncmp(target, "local", 5) == 0) { 00099 targ++; 00100 } else { 00101 targ = target; 00102 } 00103 if(remove_target(targ) == -1) { 00104 retval = 1; 00105 } 00106 } 00107 00108 if(retval == 1) { 00109 goto cleanup; 00110 } 00111 00112 /* Step 2: prepare the transaction based on its type, targets and flags */ 00113 if(alpm_trans_prepare(config->handle, &data) == -1) { 00114 alpm_errno_t err = alpm_errno(config->handle); 00115 pm_printf(ALPM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), 00116 alpm_strerror(err)); 00117 switch(err) { 00118 case ALPM_ERR_PKG_INVALID_ARCH: 00119 for(i = data; i; i = alpm_list_next(i)) { 00120 const char *pkg = i->data; 00121 printf(_(":: package %s does not have a valid architecture\n"), pkg); 00122 } 00123 break; 00124 case ALPM_ERR_UNSATISFIED_DEPS: 00125 for(i = data; i; i = alpm_list_next(i)) { 00126 alpm_depmissing_t *miss = i->data; 00127 char *depstring = alpm_dep_compute_string(miss->depend); 00128 printf(_(":: %s: requires %s\n"), miss->target, depstring); 00129 free(depstring); 00130 } 00131 break; 00132 default: 00133 break; 00134 } 00135 FREELIST(data); 00136 retval = 1; 00137 goto cleanup; 00138 } 00139 00140 /* Search for holdpkg in target list */ 00141 int holdpkg = 0; 00142 for(i = alpm_trans_get_remove(config->handle); i; i = alpm_list_next(i)) { 00143 alpm_pkg_t *pkg = i->data; 00144 if(alpm_list_find(config->holdpkg, alpm_pkg_get_name(pkg), fnmatch_cmp)) { 00145 pm_printf(ALPM_LOG_WARNING, _("%s is designated as a HoldPkg.\n"), 00146 alpm_pkg_get_name(pkg)); 00147 holdpkg = 1; 00148 } 00149 } 00150 if(holdpkg && (noyes(_("HoldPkg was found in target list. Do you want to continue?")) == 0)) { 00151 retval = 1; 00152 goto cleanup; 00153 } 00154 00155 /* Step 3: actually perform the removal */ 00156 alpm_list_t *pkglist = alpm_trans_get_remove(config->handle); 00157 if(pkglist == NULL) { 00158 printf(_(" there is nothing to do\n")); 00159 goto cleanup; /* we are done */ 00160 } 00161 00162 if(config->print) { 00163 print_packages(pkglist); 00164 goto cleanup; 00165 } 00166 00167 /* print targets and ask user confirmation */ 00168 display_targets(); 00169 printf("\n"); 00170 if(yesno(_("Do you want to remove these packages?")) == 0) { 00171 retval = 1; 00172 goto cleanup; 00173 } 00174 00175 if(alpm_trans_commit(config->handle, &data) == -1) { 00176 pm_printf(ALPM_LOG_ERROR, _("failed to commit transaction (%s)\n"), 00177 alpm_strerror(alpm_errno(config->handle))); 00178 retval = 1; 00179 } 00180 00181 FREELIST(data); 00182 00183 /* Step 4: release transaction resources */ 00184 cleanup: 00185 if(trans_release() == -1) { 00186 retval = 1; 00187 } 00188 return retval; 00189 } 00190 00191 /* vim: set ts=2 sw=2 noet: */