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