[Rpm-maint] [PATCH 1/2] Extending rpm plugin interface, part 1

Elena Reshetova elena.reshetova at intel.com
Wed Oct 17 12:50:29 UTC 2012


This change adds a new type of the rpm plugin, called transaction plugin and a set of initial hooks for this plugin.
The hooks are:

PLUGINHOOK_TSM_PRE
Pre-transaction hook that is called before an rpm transaction begins
PLUGINHOOK_TSM_POST
Post-transaction hook that is called after an rpm transaction ends
PLUGINHOOK_PSM_PRE
Pre-transaction-element hook that is called before an rpm transaction-element is processed
PLUGINHOOK_PSM_POST
Post-transaction-element hook that is called after an rpm transaction-element is processed
PLUGINHOOK_SCRIPT_SETUP
Per-script hook that is called once for each rpm mainainers script that is present in the package

Each hook is called for every plugin that have this hook registered.
The avaliable transaction plugins can be specified in macros.in via transaction_plugins element.
---
 lib/psm.c         |    3 +-
 lib/rpmplugins.c  |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rpmplugins.h  |   64 ++++++++++++++++++++++++++++-
 lib/rpmscript.c   |   17 +++++---
 lib/rpmscript.h   |    2 +-
 lib/rpmte.c       |   14 ++++++-
 lib/transaction.c |   39 ++++++++++++++++++
 plugins/plugin.h  |   14 +++++++
 8 files changed, 260 insertions(+), 11 deletions(-)

diff --git a/lib/psm.c b/lib/psm.c
index 8f5376d..1a0c27e 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -23,6 +23,7 @@
 #include "lib/rpmfi_internal.h" /* XXX replaced/states... */
 #include "lib/rpmte_internal.h"	/* XXX internal apis */
 #include "lib/rpmdb_internal.h" /* rpmdbAdd/Remove */
+#include "lib/rpmts_internal.h" /* ts->plugins */
 #include "lib/rpmscript.h"
 
 #include "debug.h"
@@ -421,7 +422,7 @@ static rpmRC runScript(rpmpsm psm, ARGV_const_t prefixes,
 
     rpmswEnter(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
     rc = rpmScriptRun(script, arg1, arg2, sfd,
-		      prefixes, warn_only, selinux);
+		      prefixes, warn_only, selinux, psm->ts->plugins);
     rpmswExit(rpmtsOp(psm->ts, RPMTS_OP_SCRIPTLETS), 0);
 
     /* Map warn-only errors to "notfound" for script stop callback */
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
index 9098aa5..bb44f34 100644
--- a/lib/rpmplugins.c
+++ b/lib/rpmplugins.c
@@ -110,6 +110,39 @@ rpmRC rpmpluginsAddCollectionPlugin(rpmPlugins plugins, const char *name)
     return rc;
 }
 
+rpmRC rpmpluginsAddTransactionPlugin(rpmPlugins plugins, const char *name)
+{
+    char *path;
+    char *options;
+    int rc = RPMRC_FAIL;
+
+    path = rpmExpand("%{?__transaction_",name, "}", NULL);
+    if (!path || rstreq(path, "")) {
+	rpmlog(RPMLOG_INFO, _("Failed to expand %%__transaction_%s macro\n"), name);
+	goto exit;
+    }
+
+    /* split the options from the path */
+#define SKIPSPACE(s)    { while (*(s) &&  risspace(*(s))) (s)++; }
+#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
+    options = path;
+    SKIPNONSPACE(options);
+    if (risspace(*options)) {
+	*options = '\0';
+	options++;
+	SKIPSPACE(options);
+    }
+    if (*options == '\0') {
+	options = NULL;
+    }
+
+    rc = rpmpluginsAdd(plugins, name, path, options);
+
+  exit:
+    _free(path);
+    return rc;
+}
+
 rpmPlugins rpmpluginsFree(rpmPlugins plugins)
 {
     int i;
@@ -195,3 +228,88 @@ rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins plugins, const char *name)
     RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_PRE_REMOVE);
     return hookFunc();
 }
+
+rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts)
+{
+    rpmRC (*hookFunc)(rpmts);
+    int i;
+    rpmRC rc = RPMRC_OK;
+    const char *name = NULL;
+
+    for (i = 0; i < plugins->count; i++) {
+	name = plugins->names[i];
+    	RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_PRE);
+    	if ( hookFunc(ts) == RPMRC_FAIL )
+		rc = RPMRC_FAIL;
+    }
+
+    return rc;
+}
+
+rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts)
+{
+    rpmRC (*hookFunc)(rpmts);
+    int i;
+    rpmRC rc = RPMRC_OK;
+    const char *name = NULL;
+
+    for (i = 0; i < plugins->count; i++) {
+	name = plugins->names[i];
+    	RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_POST);
+    	if ( hookFunc(ts) == RPMRC_FAIL )
+		rc = RPMRC_FAIL;
+    }
+
+    return rc;
+}
+
+rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te)
+{
+    rpmRC (*hookFunc)(rpmte);
+    int i;
+    rpmRC rc = RPMRC_OK;
+    const char *name = NULL;
+
+    for (i = 0; i < plugins->count; i++) {
+	name = plugins->names[i];
+    	RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_PRE);
+    	if ( hookFunc(te) == RPMRC_FAIL )
+		rc = RPMRC_FAIL;
+    }
+
+    return rc;
+}
+
+rpmRC rpmpluginsCallPsmPost(rpmPlugins plugins, rpmte te)
+{
+    rpmRC (*hookFunc)(rpmte);
+    int i;
+    rpmRC rc = RPMRC_OK;
+    const char *name = NULL;
+
+    for (i = 0; i < plugins->count; i++) {
+	name = plugins->names[i];
+    	RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_POST);
+    	if ( hookFunc(te) == RPMRC_FAIL )
+		rc = RPMRC_FAIL;
+    }
+
+    return rc;
+}
+
+rpmRC rpmpluginsCallScriptSetup(rpmPlugins plugins, char* path)
+{
+    rpmRC (*hookFunc)(char*);
+    int i;
+    rpmRC rc = RPMRC_OK;
+    const char *name = NULL;
+
+    for (i = 0; i < plugins->count; i++) {
+	name = plugins->names[i];
+    	RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_SCRIPT_SETUP);
+    	if ( hookFunc(path) == RPMRC_FAIL )
+		rc = RPMRC_FAIL;
+    }
+
+    return rc;
+}
diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h
index 7985559..b30f80d 100644
--- a/lib/rpmplugins.h
+++ b/lib/rpmplugins.h
@@ -11,11 +11,20 @@ extern "C" {
 
 #define PLUGINHOOK_INIT_FUNC			pluginhook_init
 #define PLUGINHOOK_CLEANUP_FUNC			pluginhook_cleanup
+
 #define PLUGINHOOK_OPENTE_FUNC			pluginhook_opente
 #define PLUGINHOOK_COLL_POST_ADD_FUNC		pluginhook_coll_post_add
 #define PLUGINHOOK_COLL_POST_ANY_FUNC		pluginhook_coll_post_any
 #define PLUGINHOOK_COLL_PRE_REMOVE_FUNC		pluginhook_coll_pre_remove
 
+#define PLUGINHOOK_TSM_PRE_FUNC			pluginhook_tsm_pre
+#define PLUGINHOOK_TSM_POST_FUNC		pluginhook_tsm_post
+
+#define PLUGINHOOK_PSM_PRE_FUNC			pluginhook_psm_pre
+#define PLUGINHOOK_PSM_POST_FUNC		pluginhook_psm_post
+ 
+#define PLUGINHOOK_SCRIPT_SETUP_FUNC		pluginhook_script_setup
+
 enum rpmPluginHook_e {
     PLUGINHOOK_NONE		= 0,
     PLUGINHOOK_INIT		= 1 << 0,
@@ -23,7 +32,12 @@ enum rpmPluginHook_e {
     PLUGINHOOK_OPENTE		= 1 << 2,
     PLUGINHOOK_COLL_POST_ADD	= 1 << 3,
     PLUGINHOOK_COLL_POST_ANY	= 1 << 4,
-    PLUGINHOOK_COLL_PRE_REMOVE	= 1 << 5
+    PLUGINHOOK_COLL_PRE_REMOVE	= 1 << 5,
+    PLUGINHOOK_TSM_PRE		= 1 << 6,
+    PLUGINHOOK_TSM_POST	        = 1 << 7,
+    PLUGINHOOK_PSM_PRE		= 1 << 8,			
+    PLUGINHOOK_PSM_POST	        = 1 << 9,		
+    PLUGINHOOK_SCRIPT_SETUP	= 1 << 10
 };
 
 typedef rpmFlags rpmPluginHook;
@@ -61,6 +75,14 @@ rpmRC rpmpluginsAdd(rpmPlugins plugins, const char *name, const char *path, cons
 rpmRC rpmpluginsAddCollectionPlugin(rpmPlugins plugins, const char *name);
 
 /** \ingroup rpmplugins
+ * Add and open a transaction plugin
+ * @param plugins	plugins structure to add a transaction plugin to
+ * @param name		name of transaction plugin to open
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsAddTransactionPlugin(rpmPlugins plugins, const char *name);
+
+/** \ingroup rpmplugins
  * Determine if a plugin has been added already
  * @param plugins	plugins structure
  * @param name		name of plugin to check
@@ -119,6 +141,46 @@ rpmRC rpmpluginsCallCollectionPostAny(rpmPlugins plugins, const char *name);
  */
 rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins plugins, const char *name);
 
+/** \ingroup rpmplugins
+ * Call the pre transaction plugin hook
+ * @param plugins	plugins structure
+ * @param ts		processed transaction
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts);
+
+/** \ingroup rpmplugins
+ * Call the post transaction plugin hook
+ * @param plugins	plugins structure
+ * @param ts		processed transaction
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts);
+
+/** \ingroup rpmplugins
+ * Call the post transaction element plugin hook
+ * @param plugins	plugins structure
+ * @param te		processed transaction element
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te);
+
+/** \ingroup rpmplugins
+ * Call the post transaction element plugin hook
+ * @param plugins	plugins structure
+ * @param te		processed transaction element
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallPsmPost(rpmPlugins plugins, rpmte te);
+
+/** \ingroup rpmplugins
+ * Call the script setup plugin hook
+ * @param plugins	plugins structure
+ * @param path		script path
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallScriptSetup(rpmPlugins plugins, char* path);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/rpmscript.c b/lib/rpmscript.c
index 57c24c6..d1e042c 100644
--- a/lib/rpmscript.c
+++ b/lib/rpmscript.c
@@ -14,6 +14,8 @@
 #include "rpmio/rpmlua.h"
 #include "lib/rpmscript.h"
 
+#include "lib/rpmplugins.h"     /* rpm plugins hooks */
+
 #include "debug.h"
 
 struct rpmScript_s {
@@ -91,7 +93,7 @@ static rpmRC runLuaScript(int selinux, ARGV_const_t prefixes,
 
 static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
 
-static void doScriptExec(int selinux, ARGV_const_t argv, ARGV_const_t prefixes,
+static void doScriptExec(rpmPlugins plugins, int selinux, ARGV_const_t argv, ARGV_const_t prefixes,
 			FD_t scriptFd, FD_t out)
 {
     int pipes[2];
@@ -169,7 +171,10 @@ static void doScriptExec(int selinux, ARGV_const_t argv, ARGV_const_t prefixes,
 	}
 
 	if (xx == 0) {
-	    xx = execv(argv[0], argv);
+                /* Run script setup hook for all plugins */
+                if (rpmpluginsCallScriptSetup(plugins, argv[0]) != RPMRC_FAIL) {
+		        xx = execv(argv[0], argv);
+                }
 	}
     }
     _exit(127); /* exit 127 for compatibility with bash(1) */
@@ -202,7 +207,7 @@ exit:
 /**
  * Run an external script.
  */
-static rpmRC runExtScript(int selinux, ARGV_const_t prefixes,
+static rpmRC runExtScript(rpmPlugins plugins, int selinux, ARGV_const_t prefixes,
 		   const char *sname, rpmlogLvl lvl, FD_t scriptFd,
 		   ARGV_t * argvp, const char *script, int arg1, int arg2)
 {
@@ -258,7 +263,7 @@ static rpmRC runExtScript(int selinux, ARGV_const_t prefixes,
     } else if (pid == 0) {/* Child */
 	rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n",
 	       sname, *argvp[0], (unsigned)getpid());
-	doScriptExec(selinux, *argvp, prefixes, scriptFd, out);
+	doScriptExec(plugins, selinux, *argvp, prefixes, scriptFd, out);
     }
 
     do {
@@ -297,7 +302,7 @@ exit:
 }
 
 rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
-		   ARGV_const_t prefixes, int warn_only, int selinux)
+		   ARGV_const_t prefixes, int warn_only, int selinux, rpmPlugins plugins)
 {
     ARGV_t args = NULL;
     rpmlogLvl lvl = warn_only ? RPMLOG_WARNING : RPMLOG_ERR;
@@ -315,7 +320,7 @@ rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
     if (rstreq(args[0], "<lua>")) {
 	rc = runLuaScript(selinux, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2);
     } else {
-	rc = runExtScript(selinux, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2);
+	rc = runExtScript(plugins, selinux, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2);
     }
     argvFree(args);
 
diff --git a/lib/rpmscript.h b/lib/rpmscript.h
index 7d584bc..852735b 100644
--- a/lib/rpmscript.h
+++ b/lib/rpmscript.h
@@ -29,7 +29,7 @@ rpmScript rpmScriptFree(rpmScript script);
 
 RPM_GNUC_INTERNAL
 rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd,
-                   ARGV_const_t prefixes, int warn_only, int selinux);
+                   ARGV_const_t prefixes, int warn_only, int selinux, rpmPlugins plugins);
 
 RPM_GNUC_INTERNAL
 rpmTagVal rpmScriptTag(rpmScript script);
diff --git a/lib/rpmte.c b/lib/rpmte.c
index 35b8e3e..5972505 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -941,7 +941,7 @@ int rpmteProcess(rpmte te, pkgGoal goal)
     int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE);
     int test = (rpmtsFlags(te->ts) & RPMTRANS_FLAG_TEST);
     int reset_fi = (scriptstage == 0 && test == 0);
-    int failed = 1;
+    int failed = 0;
 
     /* Dont bother opening for elements without pre/posttrans scripts */
     if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) {
@@ -955,7 +955,17 @@ int rpmteProcess(rpmte te, pkgGoal goal)
     }
 
     if (rpmteOpen(te, reset_fi)) {
-	failed = rpmpsmRun(te->ts, te, goal);
+
+    	/* Run pre transaction element hook for all plugins */
+    	if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS) {
+    		failed = rpmpluginsCallPsmPre(rpmtsPlugins(te->ts), te);
+    	}
+	if (!failed) {
+		failed = rpmpsmRun(te->ts, te, goal);
+        	/* Run post transaction element hook for all plugins*/
+        	if (goal != PKG_PRETRANS && goal != PKG_POSTTRANS)
+    			failed = rpmpluginsCallPsmPost(rpmtsPlugins(te->ts), te);
+		}
 	rpmteClose(te, reset_fi);
     }
     
diff --git a/lib/transaction.c b/lib/transaction.c
index c05d3af..3d25347 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -21,6 +21,8 @@
 #include "lib/rpmts_internal.h"
 #include "rpmio/rpmhook.h"
 
+#include "lib/rpmplugins.h"
+
 /* XXX FIXME: merge with existing (broken?) tests in system.h */
 /* portability fiddles */
 #if STATFS_IN_SYS_STATVFS
@@ -1414,6 +1416,30 @@ static int rpmtsProcess(rpmts ts)
     return rc;
 }
 
+static rpmRC rpmteSetupTransactionPlugins(rpmts ts)
+{
+    rpmRC rc = 0;
+    char *plugins = NULL, *plugin = NULL;
+    char delims[] = ",";
+
+    plugins = rpmExpand("%{?__transaction_plugins}", NULL);
+    if (!plugins || rstreq(plugins, "")) {
+        rpmlog(RPMLOG_INFO, _("Failed to expand %%__transaction_plugins macro\n"));
+	return -1;
+    }
+
+    plugin = strtok(plugins, delims);
+    while(plugin != NULL) {
+	rpmlog(RPMLOG_DEBUG, _("plugin is %s\n"), plugin);
+        if (!rpmpluginsPluginAdded(ts->plugins, (const char*)plugin)) {
+	        rc = rpmpluginsAddTransactionPlugin(ts->plugins, (const char*)plugin);
+        }
+        plugin = strtok(NULL, delims);
+    }
+    free(plugins);
+    return rc;
+}
+
 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 {
     int rc = -1; /* assume failure */
@@ -1441,11 +1467,19 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 	goto exit;
     }
 
+
+    rc = rpmteSetupTransactionPlugins(ts);
+
     rpmtsSetupCollections(ts);
 
     /* Check package set for problems */
     tsprobs = checkProblems(ts);
 
+    /* Run pre transaction hook for all plugins */
+    if ( rpmpluginsCallTsmPre(ts->plugins, ts) == RPMRC_FAIL) {
+	goto exit;
+    }
+
     /* Run pre-transaction scripts, but only if there are no known
      * problems up to this point and not disabled otherwise. */
     if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_NOPRE))
@@ -1489,6 +1523,11 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 	runTransScripts(ts, PKG_POSTTRANS);
     }
 
+    /* Run post transaction hook for all plugins */
+    if ( rpmpluginsCallTsmPost(ts->plugins, ts) == RPMRC_FAIL) {
+	goto exit;
+    }
+
 exit:
     /* Finish up... */
     (void) umask(oldmask);
diff --git a/plugins/plugin.h b/plugins/plugin.h
index 5156f93..cf49f8a 100644
--- a/plugins/plugin.h
+++ b/plugins/plugin.h
@@ -7,9 +7,23 @@
 #include "lib/rpmplugins.h"
 #include "lib/rpmchroot.h"
 
+/* general plugin hooks */
 rpmRC PLUGINHOOK_INIT_FUNC(rpmts ts, const char * name, const char * opts);
 rpmRC PLUGINHOOK_CLEANUP_FUNC(void);
+
+/* collection plugin hooks */
 rpmRC PLUGINHOOK_OPENTE_FUNC(rpmte te);
 rpmRC PLUGINHOOK_COLL_POST_ANY_FUNC(void);
 rpmRC PLUGINHOOK_COLL_POST_ADD_FUNC(void);
 rpmRC PLUGINHOOK_COLL_PRE_REMOVE_FUNC(void);
+
+/* per transaction plugin hooks */
+rpmRC PLUGINHOOK_TSM_PRE_FUNC(rpmts ts);
+rpmRC PLUGINHOOK_TSM_POST_FUNC(rpmts ts);
+
+/* per transaction element plugin hooks */
+rpmRC PLUGINHOOK_PSM_PRE_FUNC(rpmte te);
+rpmRC PLUGINHOOK_PSM_POST_FUNC(rpmte te);
+
+/*per script plugin hooks */
+rpmRC PLUGINHOOK_SCRIPT_SETUP_FUNC(char* path);
-- 
1.7.9.5



More information about the Rpm-maint mailing list