[Rpm-maint] [PATCH 1/6] Update the plugin architecture to allow for remembering state

Steve Lawrence slawrence at tresys.com
Mon Aug 30 20:32:27 UTC 2010


This moves most of the plugin logic to a new rpmplugins file with a
struct and functions for managing plugins, allowing for plugins to carry
state. This also adds init and cleanup hooks for plugins to initialize
and cleanup their state, and a new 'open te' hook allowing plugins to
read and save information from transaction elements.

This also generalizes the plugin architecture a bit so it isn't so
specific to collections.
---
 Makefile.am          |    1 +
 lib/Makefile.am      |    2 +-
 lib/collections.h    |   26 -------
 lib/rpmplugins.c     |  198 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rpmplugins.h     |  123 +++++++++++++++++++++++++++++++
 lib/rpmte.c          |  136 ++++++++++-------------------------
 lib/rpmte_internal.h |    7 ++
 lib/rpmts.c          |   10 +++
 lib/rpmts.h          |    7 ++
 lib/rpmts_internal.h |    2 +
 lib/rpmtypes.h       |    2 +
 lib/transaction.c    |    6 +-
 plugins/Makefile.am  |    2 +-
 plugins/collection.h |   12 ---
 plugins/exec.c       |   29 ++++++-
 plugins/plugin.h     |   15 ++++
 preinstall.am        |    4 +
 17 files changed, 437 insertions(+), 145 deletions(-)
 delete mode 100644 lib/collections.h
 create mode 100644 lib/rpmplugins.c
 create mode 100644 lib/rpmplugins.h
 delete mode 100644 plugins/collection.h
 create mode 100644 plugins/plugin.h

diff --git a/Makefile.am b/Makefile.am
index 87e812f..798549a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ pkginclude_HEADERS += lib/rpmte.h
 pkginclude_HEADERS += lib/rpmts.h
 pkginclude_HEADERS += lib/rpmtypes.h
 pkginclude_HEADERS += lib/rpmvf.h
+pkginclude_HEADERS += lib/rpmplugins.h
 
 pkginclude_HEADERS += build/rpmbuild.h
 pkginclude_HEADERS += build/rpmfc.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 1357c7c..d34588e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,7 +34,7 @@ librpm_la_SOURCES = \
 	verify.c rpmlock.c rpmlock.h misc.h \
 	rpmscript.h rpmscript.c legacy.c merge.c \
 	rpmliblua.c rpmliblua.h rpmchroot.c rpmchroot.h \
-	collections.h
+	rpmplugins.c rpmplugins.h
 
 librpm_la_LDFLAGS = -version-info 1:0:0
 
diff --git a/lib/collections.h b/lib/collections.h
deleted file mode 100644
index 78fbaec..0000000
--- a/lib/collections.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _COLLECTIONS_H
-#define _COLLECTIONS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef rpmRC(*collHookFunc) (rpmts, const char *, const char *);
-
-#define COLLHOOK_POST_ADD_FUNC		post_add
-#define COLLHOOK_POST_ANY_FUNC		post_any
-#define COLLHOOK_PRE_REMOVE_FUNC	pre_remove
-
-#define COLLECTION_HOOKS	collection_hooks
-typedef enum rpmCollHook_e {
-    COLLHOOK_NONE		= 0,
-    COLLHOOK_POST_ADD		= 1 << 0,
-    COLLHOOK_POST_ANY		= 1 << 1,
-    COLLHOOK_PRE_REMOVE		= 1 << 2
-} rpmCollHook;
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* _COLLECTIONS_H */
diff --git a/lib/rpmplugins.c b/lib/rpmplugins.c
new file mode 100644
index 0000000..e97d088
--- /dev/null
+++ b/lib/rpmplugins.c
@@ -0,0 +1,198 @@
+
+#include "system.h"
+
+#include <rpm/rpmmacro.h>
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmstring.h>
+#include <rpm/rpmts.h>
+
+#include <rpm/rpmplugins.h>
+
+#define STR1(x) #x
+#define STR(x) STR1(x)
+
+struct rpmPlugins_s {
+    void **handles;
+    ARGV_t names;
+    int count;
+    rpmts ts;
+};
+
+static int rpmpluginsGetPluginIndex(rpmPlugins plugins, const char *name)
+{
+    int i;
+    for (i = 0; i < plugins->count; i++) {
+	if (rstreq(plugins->names[i], name)) {
+	    return i;
+	}
+    }
+    return -1;
+}
+
+static rpmRC rpmpluginsHookIsSupported(void *handle, rpmPluginHook hook)
+{
+    rpmPluginHook *supportedHooks =
+	(rpmPluginHook *) dlsym(handle, STR(PLUGIN_HOOKS));
+    return (*supportedHooks & hook);
+}
+
+int rpmpluginsPluginAdded(rpmPlugins plugins, const char *name)
+{
+    return (rpmpluginsGetPluginIndex(plugins, name) >= 0);
+}
+
+rpmPlugins rpmpluginsNew(rpmts ts)
+{
+    rpmPlugins plugins = xcalloc(1, sizeof(*plugins));
+    plugins->ts = ts;
+    return plugins;
+}
+
+rpmRC rpmpluginsAdd(rpmPlugins plugins, const char *name, const char *path,
+		    const char *opts)
+{
+    rpmPluginHook *supportedHooks;
+    char *error;
+
+    void *handle = dlopen(path, RTLD_LAZY);
+    if (!handle) {
+	rpmlog(RPMLOG_ERR, _("Failed to dlopen %s %s\n"), path, dlerror());
+	return RPMRC_FAIL;
+    }
+
+    /* make sure the plugin has the supported hooks flag */
+    supportedHooks = (rpmPluginHook *) dlsym(handle, STR(PLUGIN_HOOKS));
+    if ((error = dlerror()) != NULL) {
+	rpmlog(RPMLOG_ERR, _("Failed to resolve symbol %s: %s\n"),
+	       STR(PLUGIN_HOOKS), error);
+	return RPMRC_FAIL;
+    }
+
+    argvAdd(&plugins->names, name);
+    plugins->handles = xrealloc(plugins->handles, (plugins->count + 1) * sizeof(*plugins->handles));
+    plugins->handles[plugins->count] = handle;
+    plugins->count++;
+
+    return rpmpluginsCallInit(plugins, name, opts);
+}
+
+rpmRC rpmpluginsAddCollectionPlugin(rpmPlugins plugins, const char *name)
+{
+    char *path;
+    char *options;
+    int rc = RPMRC_FAIL;
+
+    path = rpmExpand("%{?__collection_", name, "}", NULL);
+    if (!path || rstreq(path, "")) {
+	rpmlog(RPMLOG_ERR, _("Failed to expand %%__collection_%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;
+    for (i = 0; i < plugins->count; i++) {
+	rpmpluginsCallCleanup(plugins, plugins->names[i]);
+	dlclose(plugins->handles[i]);
+    }
+    plugins->handles = _free(plugins->handles);
+    plugins->names = argvFree(plugins->names);
+    plugins->ts = NULL;
+    _free(plugins);
+
+    return NULL;
+}
+
+
+/* Common define for all rpmpluginsCall* hook functions */
+#define RPMPLUGINS_SET_HOOK_FUNC(hook) \
+	void *handle = NULL; \
+	int index; \
+	char * error; \
+	index = rpmpluginsGetPluginIndex(plugins, name); \
+	if (index < 0) { \
+		rpmlog(RPMLOG_ERR, _("Plugin %s not loaded\n"), name); \
+		return RPMRC_FAIL; \
+	} \
+	handle = plugins->handles[index]; \
+	if (!handle) { \
+		rpmlog(RPMLOG_ERR, _("Plugin %s not loaded\n"), name); \
+		return RPMRC_FAIL; \
+	} \
+	if (!rpmpluginsHookIsSupported(handle, hook)) { \
+		return RPMRC_OK; \
+	} \
+	*(void **)(&hookFunc) = dlsym(handle, STR(hook##_FUNC)); \
+	if ((error = dlerror()) != NULL) { \
+		rpmlog(RPMLOG_ERR, _("Failed to resolve %s plugin symbol %s: %s\n"), name, STR(hook##_FUNC), error); \
+		return RPMRC_FAIL; \
+	} \
+	if (rpmtsFlags(plugins->ts) & (RPMTRANS_FLAG_TEST | RPMTRANS_FLAG_JUSTDB)) { \
+		return RPMRC_OK; \
+	} \
+	rpmlog(RPMLOG_DEBUG, "Plugin: calling hook %s in %s plugin\n", STR(hook##_FUNC), name);
+
+rpmRC rpmpluginsCallInit(rpmPlugins plugins, const char *name, const char *opts)
+{
+    rpmRC (*hookFunc)(rpmts, const char *, const char *);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_INIT);
+    return hookFunc(plugins->ts, name, opts);
+}
+
+rpmRC rpmpluginsCallCleanup(rpmPlugins plugins, const char *name)
+{
+    rpmRC (*hookFunc)(void);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_CLEANUP);
+    return hookFunc();
+}
+
+rpmRC rpmpluginsCallOpenTE(rpmPlugins plugins, const char *name, rpmte te)
+{
+    rpmRC (*hookFunc)(rpmte);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_OPENTE);
+    return hookFunc(te);
+}
+
+rpmRC rpmpluginsCallCollectionPostAdd(rpmPlugins plugins, const char *name)
+{
+    rpmRC (*hookFunc)(void);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_POST_ADD);
+    return hookFunc();
+}
+
+rpmRC rpmpluginsCallCollectionPostAny(rpmPlugins plugins, const char *name)
+{
+    rpmRC (*hookFunc)(void);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_POST_ANY);
+    return hookFunc();
+}
+
+rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins plugins, const char *name)
+{
+    rpmRC (*hookFunc)(void);
+    RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_PRE_REMOVE);
+    return hookFunc();
+}
diff --git a/lib/rpmplugins.h b/lib/rpmplugins.h
new file mode 100644
index 0000000..ae82865
--- /dev/null
+++ b/lib/rpmplugins.h
@@ -0,0 +1,123 @@
+#ifndef _PLUGINS_H
+#define _PLUGINS_H
+
+#include <rpm/rpmtypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PLUGIN_HOOKS	plugin_hooks
+
+#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
+
+typedef enum rpmPluginHook_e {
+    PLUGINHOOK_NONE		= 0,
+    PLUGINHOOK_INIT		= 1 << 0,
+    PLUGINHOOK_CLEANUP		= 1 << 1,
+    PLUGINHOOK_OPENTE		= 1 << 2,
+    PLUGINHOOK_COLL_POST_ADD	= 1 << 3,
+    PLUGINHOOK_COLL_POST_ANY	= 1 << 4,
+    PLUGINHOOK_COLL_PRE_REMOVE	= 1 << 5
+} rpmPluginHook;
+
+/** \ingroup rpmplugins
+ * Create a new plugins structure
+ * @param ts		transaction set
+ * @return		new plugin structure
+ */
+rpmPlugins rpmpluginsNew(rpmts ts);
+
+/** \ingroup rpmplugins
+ * Destroy a plugins structure
+ * @param plugins	plugins structure to destroy
+ * @return		NULL always
+ */
+rpmPlugins rpmpluginsFree(rpmPlugins plugins);
+
+/** \ingroup rpmplugins
+ * Add and open a plugin
+ * @param plugins	plugins structure to add a plugin to
+ * @param name		name to access plugin
+ * @param path		path of plugin to open
+ * @param opts		options to pass to the plugin
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsAdd(rpmPlugins plugins, const char *name, const char *path, const char *opts);
+
+/** \ingroup rpmplugins
+ * Add and open a collection plugin
+ * @param plugins	plugins structure to add a collection plugin to
+ * @param name		name of collection to open
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsAddCollectionPlugin(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
+ * @return		1 if plugin name has already been added, 0 otherwise
+ */
+int rpmpluginsPluginAdded(rpmPlugins plugins, const char *name);
+
+
+/** \ingroup rpmplugins
+ * Call the init plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @param opts		plugin options
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallInit(rpmPlugins plugins, const char *name, const char *opts);
+
+/** \ingroup rpmplugins
+ * Call the cleanup plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallCleanup(rpmPlugins plugins, const char *name);
+
+/** \ingroup rpmplugins
+ * Call the open te plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @param te		transaction element opened
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallOpenTE(rpmPlugins plugins, const char *name, rpmte te);
+
+/** \ingroup rpmplugins
+ * Call the collection post add plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallCollectionPostAdd(rpmPlugins plugins, const char *name);
+
+/** \ingroup rpmplugins
+ * Call the collection post any plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallCollectionPostAny(rpmPlugins plugins, const char *name);
+
+/** \ingroup rpmplugins
+ * Call the collection pre remove plugin hook
+ * @param plugins	plugins structure
+ * @param name		name of plugin
+ * @return		RPMRC_OK on success, RPMRC_FAIL otherwise
+ */
+rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins plugins, const char *name);
+
+#ifdef __cplusplus
+}
+#endif
+#endif	/* _PLUGINS_H */
diff --git a/lib/rpmte.c b/lib/rpmte.c
index ee86957..316ed5b 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -12,8 +12,8 @@
 #include <rpm/rpmts.h>
 #include <rpm/rpmdb.h>
 #include <rpm/rpmlog.h>
+#include <rpm/rpmplugins.h>
 
-#include "lib/collections.h"
 #include "lib/rpmte_internal.h"
 
 #include "debug.h"
@@ -816,126 +816,66 @@ rpmfs rpmteGetFileStates(rpmte te) {
     return te->fs;
 }
 
-static int rpmteRunCollection(rpmte te, const char *collname,
-			      rpmCollHook hook)
+rpmRC rpmteSetupCollectionPlugins(rpmte te)
 {
-#define STR1(x) #x
-#define STR(x) STR1(x)
-
-    void *handle = NULL;
-    collHookFunc hookFunc;
-    const char *hookFuncSym;
-    rpmCollHook *pluginHooks;
-    char *plugin;
-    char *options;
-    char *error;
-
-    int rc = RPMRC_FAIL;
-    if (rpmtsFlags(te->ts) & RPMTRANS_FLAG_NOCOLLECTIONS) {
-	return RPMRC_OK;
-    }
-
-    plugin = rpmExpand("%{?__collection_", collname, "}", NULL);
-    if (!plugin || rstreq(plugin, "")) {
-	rpmlog(RPMLOG_ERR, _("Failed to expand %%__collection_%s macro\n"),
-		collname);
-	goto exit;
-    }
-
-    /* split the options from the plugin string */
-#define SKIPSPACE(s)    { while (*(s) &&  risspace(*(s))) (s)++; }
-#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
-    options = plugin;
-    SKIPNONSPACE(options);
-    if (risspace(*options)) {
-	*options = '\0';
-	options++;
-	SKIPSPACE(options);
-    }
-    if (*options == '\0') {
-	options = NULL;
-    }
-
-    handle = dlopen(plugin, RTLD_LAZY);
-    if (!handle) {
-	rpmlog(RPMLOG_ERR, _("Failed to open %s: %s\n"), plugin, dlerror());
-	goto exit;
-    }
-
-    dlerror();
-
-    pluginHooks = (rpmCollHook *) dlsym(handle, STR(COLLECTION_HOOKS));
-    if ((error = dlerror()) != NULL) {
-	rpmlog(RPMLOG_ERR, _("Failed to resolve symbol: %s\n"),
-		STR(COLLECTION_HOOKS));
-	goto exit;
-    }
-
-    if (!(*pluginHooks & hook)) {
-	/* plugin doesn't support this hook, exit */
-	rc = RPMRC_OK;
-	goto exit;
-    }
-
-    switch (hook) {
-    case COLLHOOK_POST_ADD:
-	hookFuncSym = STR(COLLHOOK_POST_ADD_FUNC);
-	break;
-    case COLLHOOK_POST_ANY:
-	hookFuncSym = STR(COLLHOOK_POST_ANY_FUNC);
-	break;
-    case COLLHOOK_PRE_REMOVE:
-	hookFuncSym = STR(COLLHOOK_PRE_REMOVE_FUNC);
-	break;
-    default:
-	goto exit;
-    }
+    ARGV_const_t colls = rpmteCollections(te);
+    rpmPlugins plugins = rpmtsPlugins(te->ts);
+    rpmRC rc = RPMRC_OK;
 
-    *(void **) (&hookFunc) = dlsym(handle, hookFuncSym);
-    if ((error = dlerror()) != NULL) {
-	rpmlog(RPMLOG_ERR, _("Failed to resolve symbol %s: %s\n"),
-		hookFuncSym, error);
-	goto exit;
+    if (!colls) {
+	return rc;
     }
 
-    if (rpmtsFlags(te->ts) & (RPMTRANS_FLAG_TEST | RPMTRANS_FLAG_JUSTDB)) {
-	/* don't perform the action if --test or --justdb are set */
-	rc = RPMRC_OK;
-    } else {
-	rc = (*hookFunc) (te->ts, collname, options);
+    rpmteOpen(te, 0);
+    for (; colls && *colls; colls++) {
+	if (!rpmpluginsPluginAdded(plugins, *colls)) {
+	    rc = rpmpluginsAddCollectionPlugin(plugins, *colls);
+	    if (rc != RPMRC_OK) {
+		break;
+	    }
+	}
+	rc = rpmpluginsCallOpenTE(plugins, *colls, te);
+	if (rc != RPMRC_OK) {
+	    break;
+	}
     }
-
-  exit:
-    if (handle)
-	dlclose(handle);
-    _free(plugin);
+    rpmteClose(te, 0);
 
     return rc;
 }
 
-static rpmRC rpmteRunAllCollections(rpmte te, rpmCollHook hook)
+static rpmRC rpmteRunAllCollections(rpmte te, rpmPluginHook hook)
 {
     ARGV_const_t colls;
+    rpmRC(*collHook) (rpmPlugins, const char *);
     rpmRC rc = RPMRC_OK;
 
+    if (rpmtsFlags(te->ts) & RPMTRANS_FLAG_NOCOLLECTIONS) {
+	goto exit;
+    }
+
     switch (hook) {
-    case COLLHOOK_POST_ADD:
+    case PLUGINHOOK_COLL_POST_ADD:
 	colls = te->lastInCollectionsAdd;
+	collHook = rpmpluginsCallCollectionPostAdd;
 	break;
-    case COLLHOOK_POST_ANY:
+    case PLUGINHOOK_COLL_POST_ANY:
 	colls = te->lastInCollectionsAny;
+	collHook = rpmpluginsCallCollectionPostAny;
 	break;
-    case COLLHOOK_PRE_REMOVE:
+    case PLUGINHOOK_COLL_PRE_REMOVE:
 	colls = te->firstInCollectionsRemove;
+	collHook = rpmpluginsCallCollectionPreRemove;
 	break;
     default:
-	colls = NULL;
+	goto exit;
     }
 
     for (; colls && *colls; colls++) {
-	rpmteRunCollection(te, *colls, hook);
+	rc = collHook(rpmtsPlugins(te->ts), *colls);
     }
 
+  exit:
     return rc;
 }
 
@@ -953,15 +893,15 @@ int rpmteProcess(rpmte te, pkgGoal goal)
 	}
     }
 
-    rpmteRunAllCollections(te, COLLHOOK_PRE_REMOVE);
+    rpmteRunAllCollections(te, PLUGINHOOK_COLL_PRE_REMOVE);
 
     if (rpmteOpen(te, reset_fi)) {
 	failed = rpmpsmRun(te->ts, te, goal);
 	rpmteClose(te, reset_fi);
     }
     
-    rpmteRunAllCollections(te, COLLHOOK_POST_ADD);
-    rpmteRunAllCollections(te, COLLHOOK_POST_ANY);
+    rpmteRunAllCollections(te, PLUGINHOOK_COLL_POST_ADD);
+    rpmteRunAllCollections(te, PLUGINHOOK_COLL_POST_ANY);
 
     /* XXX should %pretrans failure fail the package install? */
     if (failed && !scriptstage) {
diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h
index 2425868..4f1a9f9 100644
--- a/lib/rpmte_internal.h
+++ b/lib/rpmte_internal.h
@@ -134,6 +134,13 @@ int rpmteAddToLastInCollectionAny(rpmte te, const char * collname);
 RPM_GNUC_INTERNAL
 int rpmteAddToFirstInCollectionRemove(rpmte te, const char * collname);
 
+/** \ingroup rpmte
+ * Sends the open te plugin hook for each plugins with the transaction element open
+ * @param te		transaction element
+ * @return		0 on success, non-zero on error
+ */
+RPM_GNUC_INTERNAL
+rpmRC rpmteSetupCollectionPlugins(rpmte te);
 
 #endif	/* _RPMTE_INTERNAL_H */
 
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 43966e9..506742e 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -19,6 +19,7 @@
 #include <rpm/rpmfi.h>
 #include <rpm/rpmlog.h>
 #include <rpm/rpmte.h>
+#include <rpm/rpmplugins.h>
 
 #include "rpmio/digest.h"
 #include "lib/rpmal.h"
@@ -615,6 +616,8 @@ rpmts rpmtsFree(rpmts ts)
     ts->netsharedPaths = argvFree(ts->netsharedPaths);
     ts->installLangs = argvFree(ts->installLangs);
 
+    ts->plugins = rpmpluginsFree(ts->plugins);
+
     if (_rpmts_stats)
 	rpmtsPrintStats(ts);
 
@@ -825,6 +828,11 @@ rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
     return op;
 }
 
+rpmPlugins rpmtsPlugins(rpmts ts)
+{
+    return (ts != NULL ? ts->plugins : NULL);
+}
+
 int rpmtsSetNotifyCallback(rpmts ts,
 		rpmCallbackFunction notify, rpmCallbackData notifyData)
 {
@@ -900,6 +908,8 @@ rpmts rpmtsCreate(void)
 
     ts->nrefs = 0;
 
+    ts->plugins = rpmpluginsNew(ts);
+
     return rpmtsLink(ts);
 }
 
diff --git a/lib/rpmts.h b/lib/rpmts.h
index 8ea01f3..50fdd01 100644
--- a/lib/rpmts.h
+++ b/lib/rpmts.h
@@ -514,6 +514,13 @@ rpm_color_t rpmtsSetPrefColor(rpmts ts, rpm_color_t color);
 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx);
 
 /** \ingroup rpmts
+ * Get the plugins associated with a transaction set
+ * @param ts		transaction set
+ * @return		plugins
+ */
+rpmPlugins rpmtsPlugins(rpmts ts);
+
+/** \ingroup rpmts
  * Set transaction notify callback function and argument.
  *
  * @warning This call must be made before rpmtsRun() for
diff --git a/lib/rpmts_internal.h b/lib/rpmts_internal.h
index 1a16457..4a4de45 100644
--- a/lib/rpmts_internal.h
+++ b/lib/rpmts_internal.h
@@ -62,6 +62,8 @@ struct rpmts_s {
 
     rpmSpec spec;		/*!< Spec file control structure. */
 
+    rpmPlugins plugins;		/*!< Transaction plugins */
+
     int nrefs;			/*!< Reference count. */
 };
 
diff --git a/lib/rpmtypes.h b/lib/rpmtypes.h
index 434ba16..197516e 100644
--- a/lib/rpmtypes.h
+++ b/lib/rpmtypes.h
@@ -72,6 +72,8 @@ typedef void * rpmCallbackData;
 typedef struct rpmPubkey_s * rpmPubkey;
 typedef struct rpmKeyring_s * rpmKeyring;
 
+typedef struct rpmPlugins_s * rpmPlugins;
+
 typedef struct rpmgi_s * rpmgi;
 
 typedef struct rpmSpec_s * rpmSpec;
diff --git a/lib/transaction.c b/lib/transaction.c
index 31abe4f..7e1d42d 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -1108,7 +1108,7 @@ static int runTransScripts(rpmts ts, pkgGoal goal)
     return 0; /* what to do about failures? */
 }
 
-static int rpmtsDetermineCollectionPoints(rpmts ts)
+static int rpmtsSetupCollections(rpmts ts)
 {
     /* seenCollectionsPost and TEs are basically a key-value pair. each item in
      * seenCollectionsPost is a collection that has been seen from any package,
@@ -1139,6 +1139,8 @@ static int rpmtsDetermineCollectionPoints(rpmts ts)
 	    }
 	}
 
+	rpmteSetupCollectionPlugins(p);
+
 	for (collname = rpmteCollections(p); collname && *collname; collname++) {
 	    /* figure out if we've seen this collection in post before */
 	    for (i = 0; i < numSeenPost && strcmp(*collname, seenCollectionsPost[i]); i++) {
@@ -1426,7 +1428,7 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
 	goto exit;
     }
 
-    rpmtsDetermineCollectionPoints(ts);
+    rpmtsSetupCollections(ts);
 
     /* Check package set for problems */
     tsprobs = checkProblems(ts);
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 41a9ca4..07560f0 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -15,5 +15,5 @@ pluginsdir = $(rpmconfigdir)/plugins
 
 plugins_LTLIBRARIES = exec.la
 
-exec_la_SOURCES = collection.h exec.c
+exec_la_SOURCES = plugin.h exec.c
 exec_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
diff --git a/plugins/collection.h b/plugins/collection.h
deleted file mode 100644
index e0818d6..0000000
--- a/plugins/collection.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "system.h"
-
-#include <rpm/rpmlib.h>
-#include <rpm/rpmlog.h>
-#include <rpm/rpmts.h>
-
-#include "lib/collections.h"
-#include "lib/rpmchroot.h"
-
-rpmRC COLLHOOK_POST_ANY_FUNC(rpmts ts, const char * collname, const char * options);
-rpmRC COLLHOOK_POST_ADD_FUNC(rpmts ts, const char * collname, const char * options);
-rpmRC COLLHOOK_PRE_REMOVE_FUNC(rpmts ts, const char * collname, const char * options);
diff --git a/plugins/exec.c b/plugins/exec.c
index ab2536f..fd25f2b 100644
--- a/plugins/exec.c
+++ b/plugins/exec.c
@@ -1,11 +1,30 @@
-#include "collection.h"
+#include "plugin.h"
 
 #include <sys/wait.h>
 
-rpmCollHook COLLECTION_HOOKS = COLLHOOK_POST_ANY;
+static char * options;
+static char * name;
 
-rpmRC COLLHOOK_POST_ANY_FUNC(rpmts ts, const char *collname,
-			     const char *options)
+rpmPluginHook PLUGIN_HOOKS = \
+	PLUGINHOOK_INIT | \
+	PLUGINHOOK_CLEANUP | \
+	PLUGINHOOK_COLL_POST_ANY;
+
+rpmRC PLUGINHOOK_INIT_FUNC(rpmts ts, const char *name, const char *opts)
+{
+    options = strdup(opts);
+    name = strdup(name);
+    return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_CLEANUP_FUNC(void)
+{
+    options = _free(options);
+    name = _free(name);
+    return RPMRC_OK;
+}
+
+rpmRC PLUGINHOOK_COLL_POST_ANY_FUNC(void)
 {
     int rc = RPMRC_FAIL;
 
@@ -16,7 +35,7 @@ rpmRC COLLHOOK_POST_ANY_FUNC(rpmts ts, const char *collname,
     if (options) {
 	int status = system(options);
 	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
-	    rpmlog(RPMLOG_ERR, "%s collection action failed\n", collname);
+	    rpmlog(RPMLOG_ERR, "%s collection action failed\n", name);
 	    goto exit;
 	}
     }
diff --git a/plugins/plugin.h b/plugins/plugin.h
new file mode 100644
index 0000000..5156f93
--- /dev/null
+++ b/plugins/plugin.h
@@ -0,0 +1,15 @@
+#include "system.h"
+
+#include <rpm/rpmlib.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmts.h>
+
+#include "lib/rpmplugins.h"
+#include "lib/rpmchroot.h"
+
+rpmRC PLUGINHOOK_INIT_FUNC(rpmts ts, const char * name, const char * opts);
+rpmRC PLUGINHOOK_CLEANUP_FUNC(void);
+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);
diff --git a/preinstall.am b/preinstall.am
index ab3a072..7f64837 100644
--- a/preinstall.am
+++ b/preinstall.am
@@ -110,6 +110,10 @@ include/rpm/rpmvf.h: lib/rpmvf.h include/rpm/$(dirstamp)
 	$(INSTALL_DATA) $(top_srcdir)/lib/rpmvf.h include/rpm/rpmvf.h
 BUILT_SOURCES += include/rpm/rpmvf.h
 CLEANFILES += include/rpm/rpmvf.h
+include/rpm/rpmplugins.h: lib/rpmplugins.h include/rpm/$(dirstamp)
+	$(INSTALL_DATA) $(top_srcdir)/lib/rpmplugins.h include/rpm/rpmplugins.h
+BUILT_SOURCES += include/rpm/rpmplugins.h
+CLEANFILES += include/rpm/rpmplugins.h
 include/rpm/rpmbuild.h: build/rpmbuild.h include/rpm/$(dirstamp)
 	$(INSTALL_DATA) $(top_srcdir)/build/rpmbuild.h include/rpm/rpmbuild.h
 BUILT_SOURCES += include/rpm/rpmbuild.h
-- 
1.6.2.5



More information about the Rpm-maint mailing list