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

_______________________________________________
pacman-dev mailing list
[email protected]
http://www.archlinux.org/mailman/listinfo/pacman-dev

Reply via email to