summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/remove.c
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-08-19 18:06:55 +0200
committerDan McGee <dan@archlinux.org>2011-08-19 18:09:57 +0200
commit6d544984f2418ea34caab4c433580487b760362a (patch)
treecf0510b97a6495587c87598a70bf8761189f5c32 /lib/libalpm/remove.c
parent9934b3bd345011eef6a96249d8d90de594c04cd0 (diff)
downloadpacman-6d544984f2418ea34caab4c433580487b760362a.tar.gz
pacman-6d544984f2418ea34caab4c433580487b760362a.tar.xz
Be more robust when copying package data
This changes the signature of _alpm_pkg_dup() to return an integer error code and provide the new package in a passed pointer argument. All callers are now more robust with checking the return value of this function to ensure a fatal error did not occur. We allow load failures to proceed as otherwise we have a chicken and egg problem- if a 'desc' local database entry is missing, the best way of restoring said file is `pacman -Sf --dbonly packagename`. This patch fixes a segfault that was occurring in this case. Fixes the segfault reported in FS#25667. Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib/libalpm/remove.c')
-rw-r--r--lib/libalpm/remove.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index c6886c6f..7903a0f5 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -49,6 +49,7 @@ int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg)
{
const char *pkgname;
alpm_trans_t *trans;
+ alpm_pkg_t *copy;
/* Sanity checks */
CHECK_HANDLE(handle, return -1);
@@ -67,11 +68,14 @@ int SYMEXPORT alpm_remove_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg)
_alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s to the transaction remove list\n",
pkgname);
- trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(pkg));
+ if(_alpm_pkg_dup(pkg, &copy) == -1) {
+ return -1;
+ }
+ trans->remove = alpm_list_add(trans->remove, copy);
return 0;
}
-static void remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
+static int remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
{
alpm_trans_t *trans = handle->trans;
@@ -81,14 +85,18 @@ static void remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
alpm_depmissing_t *miss = i->data;
alpm_pkg_t *info = _alpm_db_get_pkgfromcache(handle->db_local, miss->target);
if(info) {
+ alpm_pkg_t *copy;
if(!_alpm_pkg_find(trans->remove, info->name)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "pulling %s in target list\n",
info->name);
- trans->remove = alpm_list_add(trans->remove, _alpm_pkg_dup(info));
+ if(_alpm_pkg_dup(info, &copy) == -1) {
+ return -1;
+ }
+ trans->remove = alpm_list_add(trans->remove, copy);
}
} else {
- _alpm_log(handle, ALPM_LOG_ERROR, _("could not find %s in database -- skipping\n"),
- miss->target);
+ _alpm_log(handle, ALPM_LOG_ERROR,
+ _("could not find %s in database -- skipping\n"), miss->target);
}
}
alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
@@ -96,6 +104,7 @@ static void remove_prepare_cascade(alpm_handle_t *handle, alpm_list_t *lp)
lp = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local),
trans->remove, NULL, 1);
}
+ return 0;
}
static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp)
@@ -134,6 +143,7 @@ static void remove_prepare_keep_needed(alpm_handle_t *handle, alpm_list_t *lp)
* the packages blocking the transaction.
* @param handle the context handle
* @param data a pointer to an alpm_list_t* to fill
+ * @return 0 on success, -1 on error
*/
int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
{
@@ -144,8 +154,10 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
if((trans->flags & ALPM_TRANS_FLAG_RECURSE)
&& !(trans->flags & ALPM_TRANS_FLAG_CASCADE)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->remove,
- trans->flags & ALPM_TRANS_FLAG_RECURSEALL);
+ if(_alpm_recursedeps(db, trans->remove,
+ trans->flags & ALPM_TRANS_FLAG_RECURSEALL)) {
+ return -1;
+ }
}
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
@@ -156,7 +168,9 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
if(lp != NULL) {
if(trans->flags & ALPM_TRANS_FLAG_CASCADE) {
- remove_prepare_cascade(handle, lp);
+ if(remove_prepare_cascade(handle, lp)) {
+ return -1;
+ }
} else if(trans->flags & ALPM_TRANS_FLAG_UNNEEDED) {
/* Remove needed packages (which would break dependencies)
* from target list */
@@ -184,7 +198,10 @@ int _alpm_remove_prepare(alpm_handle_t *handle, alpm_list_t **data)
if((trans->flags & ALPM_TRANS_FLAG_CASCADE)
&& (trans->flags & ALPM_TRANS_FLAG_RECURSE)) {
_alpm_log(handle, ALPM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->remove, trans->flags & ALPM_TRANS_FLAG_RECURSEALL);
+ if(_alpm_recursedeps(db, trans->remove,
+ trans->flags & ALPM_TRANS_FLAG_RECURSEALL)) {
+ return -1;
+ }
}
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {