[pacman-dev] [PATCH] do not rely on localdb for hook matching

Andrew Gregory andrew.gregory.8 at gmail.com
Mon Feb 22 02:46:35 UTC 2016


Relying on localdb to determine which trigger operations should match is
completely broken for PostTransaction hooks because the localdb has
already been updated.  Store a copy of the old version of any packages
being updated to use instead.

Fixes FS#47996

Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---
 lib/libalpm/add.c                                  | 14 +++----------
 lib/libalpm/hook.c                                 |  4 ++--
 lib/libalpm/package.c                              |  3 +++
 lib/libalpm/package.h                              |  1 +
 lib/libalpm/sync.c                                 |  8 ++++++++
 test/pacman/tests/TESTS                            |  1 +
 .../tests/hook-pkg-postinstall-trigger-match.py    | 23 ++++++++++++++++++++++
 7 files changed, 41 insertions(+), 13 deletions(-)
 create mode 100644 test/pacman/tests/hook-pkg-postinstall-trigger-match.py

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 2639fa7..f5c9a95 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -409,9 +409,8 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 	ASSERT(trans != NULL, return -1);
 
 	/* see if this is an upgrade. if so, remove the old package first */
-	alpm_pkg_t *local = _alpm_db_get_pkgfromcache(db, newpkg->name);
-	if(local) {
-		int cmp = _alpm_pkg_compare_versions(newpkg, local);
+	if((oldpkg = newpkg->oldpkg)) {
+		int cmp = _alpm_pkg_compare_versions(newpkg, oldpkg);
 		if(cmp < 0) {
 			log_msg = "downgrading";
 			progress = ALPM_PROGRESS_DOWNGRADE_START;
@@ -427,14 +426,8 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 		}
 		is_upgrade = 1;
 
-		/* we'll need to save some record for backup checks later */
-		if(_alpm_pkg_dup(local, &oldpkg) == -1) {
-			ret = -1;
-			goto cleanup;
-		}
-
 		/* copy over the install reason */
-		newpkg->reason = alpm_pkg_get_reason(local);
+		newpkg->reason = alpm_pkg_get_reason(oldpkg);
 	} else {
 		event.operation = ALPM_PACKAGE_INSTALL;
 	}
@@ -630,7 +623,6 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 	EVENT(handle, &event);
 
 cleanup:
-	_alpm_pkg_free(oldpkg);
 	return ret;
 }
 
diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c
index 81c347e..6890a6e 100644
--- a/lib/libalpm/hook.c
+++ b/lib/libalpm/hook.c
@@ -374,7 +374,7 @@ static int _alpm_hook_trigger_match_file(alpm_handle_t *handle,
 	/* check if file will be removed due to package upgrade */
 	for(i = handle->trans->add; i; i = i->next) {
 		alpm_pkg_t *spkg = i->data;
-		alpm_pkg_t *pkg = alpm_db_get_pkg(handle->db_local, spkg->name);
+		alpm_pkg_t *pkg = spkg->oldpkg;
 		if(pkg) {
 			alpm_filelist_t filelist = pkg->files;
 			size_t f;
@@ -463,7 +463,7 @@ static int _alpm_hook_trigger_match_pkg(alpm_handle_t *handle,
 		for(i = handle->trans->add; i; i = i->next) {
 			alpm_pkg_t *pkg = i->data;
 			if(_alpm_fnmatch_patterns(t->targets, pkg->name) == 0) {
-				if(alpm_db_get_pkg(handle->db_local, pkg->name)) {
+				if(pkg->oldpkg) {
 					if(t->op & ALPM_HOOK_OP_UPGRADE) {
 						if(hook->needs_targets) {
 							upgrade = alpm_list_add(upgrade, pkg->name);
diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c
index 4f8ddb3..f08df8b 100644
--- a/lib/libalpm/package.c
+++ b/lib/libalpm/package.c
@@ -682,6 +682,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
 	alpm_list_free(pkg->deltas);
 	alpm_list_free(pkg->delta_path);
 	alpm_list_free(pkg->removes);
+	_alpm_pkg_free(pkg->oldpkg);
 
 	if(pkg->origin == ALPM_PKG_FROM_FILE) {
 		FREE(pkg->origin_data.file);
@@ -707,6 +708,8 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg)
 
 	alpm_list_free(pkg->removes);
 	pkg->removes = NULL;
+	_alpm_pkg_free(pkg->oldpkg);
+	pkg->oldpkg = NULL;
 }
 
 /* Is spkg an upgrade for localpkg? */
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index 65afaf7..9fea356 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -117,6 +117,7 @@ struct __alpm_pkg_t {
 	alpm_list_t *deltas;
 	alpm_list_t *delta_path;
 	alpm_list_t *removes; /* in transaction targets only */
+	alpm_pkg_t *oldpkg; /* in transaction targets only */
 
 	struct pkg_operations *ops;
 
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 3d3915c..00b68d0 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -659,10 +659,15 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 	for(i = trans->add; i; i = i->next) {
 		/* update download size field */
 		alpm_pkg_t *spkg = i->data;
+		alpm_pkg_t *lpkg = alpm_db_get_pkg(handle->db_local, spkg->name);
 		if(compute_download_size(spkg) < 0) {
 			ret = -1;
 			goto cleanup;
 		}
+		if(lpkg && _alpm_pkg_dup(lpkg, &spkg->oldpkg) != 0) {
+			ret = -1;
+			goto cleanup;
+		}
 	}
 
 cleanup:
@@ -1260,6 +1265,9 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
 		pkgfile->reason = spkg->reason;
 		/* copy over validation method */
 		pkgfile->validation = spkg->validation;
+		/* transfer oldpkg */
+		pkgfile->oldpkg = spkg->oldpkg;
+		spkg->oldpkg = NULL;
 		i->data = pkgfile;
 		/* spkg has been removed from the target list, so we can free the
 		 * sync-specific fields */
diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
index acdf769..9c33020 100644
--- a/test/pacman/tests/TESTS
+++ b/test/pacman/tests/TESTS
@@ -59,6 +59,7 @@ TESTS += test/pacman/tests/hook-file-remove-trigger-match.py
 TESTS += test/pacman/tests/hook-file-upgrade-nomatch.py
 TESTS += test/pacman/tests/hook-invalid-trigger.py
 TESTS += test/pacman/tests/hook-pkg-install-trigger-match.py
+TESTS += test/pacman/tests/hook-pkg-postinstall-trigger-match.py
 TESTS += test/pacman/tests/hook-pkg-remove-trigger-match.py
 TESTS += test/pacman/tests/hook-pkg-upgrade-trigger-match.py
 TESTS += test/pacman/tests/hook-target-list.py
diff --git a/test/pacman/tests/hook-pkg-postinstall-trigger-match.py b/test/pacman/tests/hook-pkg-postinstall-trigger-match.py
new file mode 100644
index 0000000..b9b07cd
--- /dev/null
+++ b/test/pacman/tests/hook-pkg-postinstall-trigger-match.py
@@ -0,0 +1,23 @@
+self.description = "Install a package matching a PostTransaction Install hook"
+
+self.add_script("hook-script", ": > hook-output")
+self.add_hook("hook",
+        """
+        [Trigger]
+        Type = Package
+        Operation = Install
+        Target = foo
+
+        [Action]
+        When = PostTransaction
+        Exec = bin/hook-script
+        """);
+
+sp = pmpkg("foo")
+self.addpkg2db("sync", sp)
+
+self.args = "-S foo"
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PKG_EXIST=foo")
+self.addrule("FILE_EXIST=hook-output")
-- 
2.7.1


More information about the pacman-dev mailing list