Re: [pacman-dev] [PATCH] Add support for user defined per package post install actions
Hi! Oh, that was a neat idea... Which I have unfortunetly missed when searching in the archives. :-) I think it should be possible to have it triggered by packages as well, something like this: [kernel-install] Package = kernel26 Run = rebuildoutofkerneltreedrivers (I recognice the ridiculous name of the Run-argument and that this probably wouldn't work as a reboot probably is necessery first but just something as an example. (and it was this need that triggered my own idea).) Of course it is possible to have it triggered by file in this case as well, just list files in this package and choose one of them, but it is still an unecessery extra step (even if it is a small one). BR, Mårten ----- Original Message ----- From: "Allan McRae" <allan@archlinux.org> To: "Discussion list for pacman development" <pacman-dev@archlinux.org> Sent: Sunday, February 1, 2009 2:59:10 AM GMT +01:00 Amsterdam / Berlin / Bern / Rome / Stockholm / Vienna Subject: Re: [pacman-dev] [PATCH] Add support for user defined per package post install actions 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@purplescout.se> To: pacman-dev@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) {
_______________________________________________ pacman-dev mailing list pacman-dev@archlinux.org http://www.archlinux.org/mailman/listinfo/pacman-dev
Mårten Olsson wrote:
Hi!
Oh, that was a neat idea... Which I have unfortunetly missed when searching in the archives. :-)
If you want to read the discussion check out the archives from about 23 Jan this year.
I think it should be possible to have it triggered by packages as well, something like this:
[kernel-install] Package = kernel26 Run = rebuildoutofkerneltreedrivers
In the example config file in the wiki page, the "Run" parameter is when to run the script specified in the [ ] brackets at the top.
(I recognice the ridiculous name of the Run-argument and that this probably wouldn't work as a reboot probably is necessery first but just something as an example. (and it was this need that triggered my own idea).)
Of course it is possible to have it triggered by file in this case as well, just list files in this package and choose one of them, but it is still an unecessery extra step (even if it is a small one)
I'm sure it would be possible to have a package set off a hook such as you are suggesting, although I think most packages would have a file that would be the obvious choice to use (e.g. /boot/vmlinuz26 for kernel26). Please add a comment to the wiki page about this. Once we have agreed on good configuration file formats, etc then you are more than welcome to help out coding this. Cheers, Allan
Hi! I renamed this thread because we're moving away from the patch. I will edit the wiki but have some additonal questions (and comments), so I don't make some more mistakes, I have added them below. ----- "Allan McRae" <allan@archlinux.org> wrote:
Mårten Olsson wrote:
Hi!
Oh, that was a neat idea... Which I have unfortunetly missed when searching in the archives. :-)
If you want to read the discussion check out the archives from about 23 Jan this year.
I think it should be possible to have it triggered by packages as well, something like this:
[kernel-install] Package = kernel26 Run = rebuildoutofkerneltreedrivers
In the example config file in the wiki page, the "Run" parameter is when to run the script specified in the [ ] brackets at the top.
So this example would be something like: [rebuildoutofkerneltreedrivers] Package = kernel26 Run = postinstall Or have I missed something?
(I recognice the ridiculous name of the Run-argument and that this probably wouldn't work as a reboot probably is necessery first but just something as an example. (and it was this need that triggered my own idea).)
Of course it is possible to have it triggered by file in this case as well, just list files in this package and choose one of them, but it is still an unecessery extra step (even if it is a small one)
I'm sure it would be possible to have a package set off a hook such as you are suggesting, although I think most packages would have a file that would be the obvious choice to use (e.g. /boot/vmlinuz26 for kernel26). Please add a comment to the wiki page about this.
Yep, I don't see that as a major problem.
From what I have seen of the code it might however be easier to start with Package matching (I might be wrong about this but it is my personal opinion). In the end both options would be good, we have at least seen that between us that both variants are desirable.
Once we have agreed on good configuration file formats, etc then you are more than welcome to help out coding this.
I would love to help with that, just hope I will have time for it when it gets that far.
Cheers, Allan
BR, Mårten
Mårten Olsson wrote:
<snip>
In the example config file in the wiki page, the "Run" parameter is when to run the script specified in the [ ] brackets at the top.
So this example would be something like: [rebuildoutofkerneltreedrivers] Package = kernel26 Run = postinstall
Or have I missed something?
That looks fine to me.
<snip> I'm sure it would be possible to have a package set off a hook such as you are suggesting, although I think most packages would have a file that would be the obvious choice to use (e.g. /boot/vmlinuz26 for kernel26). Please add a comment to the wiki page about this.
Yep, I don't see that as a major problem. From what I have seen of the code it might however be easier to start with Package matching (I might be wrong about this but it is my personal opinion). In the end both options would be good, we have at least seen that between us that both variants are desirable.
From my understanding, there should be a list of files involved in a transaction created during conflict checking. So we can hopefully use that to test which hooks need to be run. However, I am not very familiar with that part of the pacman code...
Once we have agreed on good configuration file formats, etc then you are more than welcome to help out coding this.
I would love to help with that, just hope I will have time for it when it gets that far.
That would be great. We always have more ideas floating around that people to code them so it is good to see new coders join in. Allan
----- "Allan McRae" <allan@archlinux.org> skrev:
Mårten Olsson wrote:
<snip>
In the example config file in the wiki page, the "Run" parameter is when to run the script specified in the [ ] brackets at the top.
So this example would be something like: [rebuildoutofkerneltreedrivers] Package = kernel26 Run = postinstall
Or have I missed something?
That looks fine to me.
Ok I will add something about this to the wiki when I get the chanse.
<snip> I'm sure it would be possible to have a package set off a hook such as you are suggesting, although I think most packages would have a file that would be the obvious choice to use (e.g. /boot/vmlinuz26 for kernel26). Please add a comment to the wiki page about this.
Yep, I don't see that as a major problem. From what I have seen of the code it might however be easier to start with Package matching (I might be wrong about this but it is my personal opinion). In the end both options would be good, we have at least seen that between us that both variants are desirable.
From my understanding, there should be a list of files involved in a transaction created during conflict checking. So we can hopefully use that to test which hooks need to be run. However, I am not very familiar with that part of the pacman code...
Ah that seems resonable.
Once we have agreed on good configuration file formats, etc then you are more than welcome to help out coding this.
I would love to help with that, just hope I will have time for it when it gets that far.
That would be great. We always have more ideas floating around that people to code them so it is good to see new coders join in.
Yep, it is always the question about time, I don't understand how you guys do it. But enough about that...
Allan
//Mårten
participants (2)
-
Allan McRae
-
Mårten Olsson