[pacman-dev] [PATCH] Add support for user defined per package post install actions

Mårten Olsson marten.olsson at purplescout.se
Sat Jan 31 20:36:46 EST 2009


This adds suport for user to add per package post install
actions, somewhat similar to post-install scripts in packages
but controlled by local user and not part of package/not done
by package maintainer.
The actions is performed by "system" call and can't contain
spaces (not even when inside ").
Syntax in logfile is
PostInstallAction = <packagename>:<action>
Functionality added inside libalpm, add support for configuring
in pacman.

Signed-off-by: Mårten Olsson <marten.olsson_at_purplescout.se>
---
 lib/libalpm/add.c    |   43 +++++++++++++++++++++++++++++++++
 lib/libalpm/alpm.h   |    3 ++
 lib/libalpm/handle.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/libalpm/handle.h |    6 ++++
 src/pacman/pacman.c  |   20 +++++++++++++++
 5 files changed, 137 insertions(+), 0 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index 6eb2085..1cd6e28 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -632,6 +632,46 @@ static int extract_single_file(struct archive *archive,
 	return(errors);
 }
 
+static int postinstallcompare(const void *postinstalldata, const void *pkgname)
+{
+	const postinstallaction_t *postinstallaction=postinstalldata;
+
+	if( (pkgname != NULL) && (postinstallaction->pkgname != NULL) && (strcmp(postinstallaction->pkgname, pkgname) == 0)) {
+		return(0);
+	}
+
+	return(1);
+}
+
+/** Test if a package has a postinstallaction associated with it and executes the action.
+ *
+ * Checks if the package has a postinstallaction associated with it
+ * and if so executes the action by the system call
+ *
+ * @param pkg the package to test
+ *
+ * @return 0 if no action found or if the associated action completed succesfully, 1 otherwise
+ */
+static int check_run_postinstallaction(pmpkg_t *pkg)
+{
+	postinstallaction_t *postinstallaction = NULL;
+
+	_alpm_log(PM_LOG_DEBUG, "PostInstallAction: finding PostInstallAction for package: %s\n", alpm_pkg_get_name(pkg));
+
+	postinstallaction=alpm_list_find(handle->postinstallactions, alpm_pkg_get_name(pkg), postinstallcompare);
+
+	if( postinstallaction != NULL) {
+		_alpm_log(PM_LOG_DEBUG, "PostInstallAction: package: %s action: %s \n", postinstallaction->pkgname, postinstallaction->action);
+
+		/* should this be more like the install-scriptlet code */
+		if( system(postinstallaction->action) != 0) {
+			return(1);
+		}
+	}
+
+	return(0);
+}
+
 static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
 		pmtrans_t *trans, pmdb_t *db)
 {
@@ -847,6 +887,9 @@ static int commit_single_pkg(pmpkg_t *newpkg, int pkg_current, int pkg_count,
 		}
 	}
 
+	/* check and run postinstall action */
+	check_run_postinstallaction(newpkg);
+
 	if(is_upgrade) {
 		EVENT(trans, PM_TRANS_EVT_UPGRADE_DONE, newpkg, oldpkg);
 	} else {
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 7b7ca4e..04ff886 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -122,6 +122,9 @@ void alpm_option_add_noupgrade(const char *pkg);
 void alpm_option_set_noupgrades(alpm_list_t *noupgrade);
 int alpm_option_remove_noupgrade(const char *pkg);
 
+int alpm_option_add_postinstallaction(const char *pkg, const char *action);
+int alpm_option_remove_postinstallaction(const char *pkg);
+
 alpm_list_t *alpm_option_get_noextracts();
 void alpm_option_add_noextract(const char *pkg);
 void alpm_option_set_noextracts(alpm_list_t *noextract);
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 813f439..504157d 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -53,6 +53,23 @@ pmhandle_t *_alpm_handle_new()
 	return(handle);
 }
 
+void postinstallactionfree(void *data)
+{
+	postinstallaction_t *postinstallaction=data;
+
+	if(postinstallaction->pkgname != NULL)
+	{
+		free(postinstallaction->pkgname);
+	}
+
+	if(postinstallaction->action != NULL)
+	{
+		free(postinstallaction->action);
+	}
+
+	free(postinstallaction);
+}
+
 void _alpm_handle_free(pmhandle_t *handle)
 {
 	ALPM_LOG_FUNC;
@@ -84,6 +101,8 @@ void _alpm_handle_free(pmhandle_t *handle)
 	FREELIST(handle->noextract);
 	FREELIST(handle->ignorepkg);
 	FREELIST(handle->ignoregrp);
+	alpm_list_free_inner(handle->postinstallactions, postinstallactionfree);
+	alpm_list_free(handle->postinstallactions);
 	FREE(handle);
 }
 
@@ -453,6 +472,52 @@ int SYMEXPORT alpm_option_remove_noupgrade(const char *pkg)
 	return(0);
 }
 
+int SYMEXPORT alpm_option_add_postinstallaction(const char *pkg, const char *action)
+{
+	postinstallaction_t *postinstallaction=0;
+
+	postinstallaction=malloc(sizeof(postinstallaction_t));
+
+	if(postinstallaction == NULL) {
+		return(1);
+	}
+
+	postinstallaction->pkgname = strdup(pkg);
+	postinstallaction->action= strdup(action);
+
+	handle->postinstallactions = alpm_list_add(handle->postinstallactions, postinstallaction);
+
+	return(0);
+}
+
+/* Duplicated here for now, cleanup needed */
+static int postinstallcompare(const void *postinstalldata, const void *pkgname)
+{
+	const postinstallaction_t *postinstallaction=postinstalldata;
+
+	if( (pkgname != NULL) && (postinstallaction->pkgname != NULL) && (strcmp(postinstallaction->pkgname, pkgname) == 0)) {
+		return(0);
+	}
+
+	return(1);
+}
+
+int SYMEXPORT alpm_option_remove_postinstallaction(const char *pkg)
+{
+	postinstallaction_t *postinstallaction=0;
+
+	handle->postinstallactions=alpm_list_remove(handle->postinstallactions, pkg, postinstallcompare, (void *)&postinstallaction );
+
+	if( postinstallaction != NULL) {
+		free(postinstallaction->pkgname);
+		free(postinstallaction->action);
+		free(postinstallaction);
+		return(1);
+	}
+
+	return(0);
+}
+
 void SYMEXPORT alpm_option_add_noextract(const char *pkg)
 {
 	handle->noextract = alpm_list_add(handle->noextract, strdup(pkg));
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index ad7666d..c53e7f6 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -28,6 +28,11 @@
 #include "alpm.h"
 #include "trans.h"
 
+typedef struct _postinstallaction_t {
+	char *pkgname;
+	char *action;
+} postinstallaction_t;
+
 typedef struct _pmhandle_t {
 	/* internal usage */
 	pmdb_t *db_local;       /* local db pointer */
@@ -53,6 +58,7 @@ typedef struct _pmhandle_t {
 	alpm_list_t *noextract;   /* List of files NOT to extract */
 	alpm_list_t *ignorepkg;   /* List of packages to ignore */
 	alpm_list_t *ignoregrp;   /* List of groups to ignore */
+	alpm_list_t *postinstallactions;   /* List of packages to perform actions postinstall */
 
 	/* options */
 	unsigned short usesyslog;    /* Use syslog instead of logfile? */ /* TODO move to frontend */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 59916d6..1f1371d 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -549,6 +549,24 @@ static void option_add_syncfirst(const char *name) {
 	config->syncfirst = alpm_list_add(config->syncfirst, strdup(name));
 }
 
+/* helper for being used with setrepeatingoption, additional parsing done here*/
+static void option_add_postinstallaction(const char *string) {
+	char *name = (char *)string;
+	char *action = 0;
+
+	action=strchr(string,':');
+
+	if( action != NULL)	{
+		*action = '\0';
+		action++;
+
+		pm_printf(PM_LOG_DEBUG, "config: Postinstallaction package %s action: %s\n", name, action);
+
+		alpm_option_add_postinstallaction(name, action);
+	}
+
+}
+
 /** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm
  * settings. Refactored out of the parseconfig code since all of them did
  * the exact same thing and duplicated code.
@@ -710,6 +728,8 @@ static int _parseconfig(const char *file, const char *givensection,
 						setrepeatingoption(ptr, "HoldPkg", option_add_holdpkg);
 					} else if(strcmp(key, "SyncFirst") == 0) {
 						setrepeatingoption(ptr, "SyncFirst", option_add_syncfirst);
+					} else if(strcmp(key, "PostInstallAction") == 0) {
+						setrepeatingoption(ptr, "PostInstallAction", option_add_postinstallaction);
 					} else if(strcmp(key, "DBPath") == 0) {
 						/* don't overwrite a path specified on the command line */
 						if(!config->dbpath) {
-- 
1.6.1.2



More information about the pacman-dev mailing list