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

Allan McRae allan at archlinux.org
Sat Jan 31 20:59:10 EST 2009


Hi,

This seems similar to the hooks mechanism the we have been discussing 
but less general.  Have a look at 
http://wiki.archlinux.org/index.php/User:Allan/Pacman_Hooks for more 
information.  So in short, I like the idea but would want a more general 
approach taken.

Allan

Mårten Olsson wrote:
> Hi all!
>
> Wasn't sure if I could include additonal text in "patch-mail".
> So I hope it is ok to send an additonal mail with extra info:
>
> At some places the code needs cleanup which I will do if the concept shown
> is accepted (didn't want to take to much time on that if the concept is disliked
> and never will be accpeted for that reason).
> I want to fix the code-duplication issue (one function) and make the parsign so one
> can have arguments with spaces inside " ".
>
> I wasn't sure if this functionality can be considered dangerous because it will run a script
> with full access to the system, but I guess the same problem could show up if you make "bad"
> packages with an install script.  
>
> BR,
> Mårten
>
> ----- Original Message -----
> From: "Mårten Olsson" <marten.olsson at purplescout.se>
> To: pacman-dev at archlinux.org
> Sent: Sunday, February 1, 2009 2:36:46 AM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna
> Subject: [pacman-dev] [PATCH] Add support for user defined per package post install actions
>
> 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) {
>   





More information about the pacman-dev mailing list