libalpm
Arch Linux Package Manager Library
remove.c
Go to the documentation of this file.
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: */