4 #include <rpm/rpmmacro.h>
5 #include <rpm/rpmtypes.h>
6 #include <rpm/rpmlog.h>
7 #include <rpm/rpmstring.h>
10 #include "lib/rpmplugins.h"
13 #define STR(x) STR1(x)
22 static int rpmpluginsGetPluginIndex(rpmPlugins plugins, const char *name)
25 for (i = 0; i < plugins->count; i++) {
26 if (rstreq(plugins->names[i], name)) {
33 static int rpmpluginsHookIsSupported(void *handle, rpmPluginHook hook)
35 rpmPluginHook *supportedHooks =
36 (rpmPluginHook *) dlsym(handle, STR(PLUGIN_HOOKS));
37 return (*supportedHooks & hook);
40 int rpmpluginsPluginAdded(rpmPlugins plugins, const char *name)
42 return (rpmpluginsGetPluginIndex(plugins, name) >= 0);
45 rpmPlugins rpmpluginsNew(rpmts ts)
47 rpmPlugins plugins = xcalloc(1, sizeof(*plugins));
52 rpmRC rpmpluginsAdd(rpmPlugins plugins, const char *name, const char *path,
57 void *handle = dlopen(path, RTLD_LAZY);
59 rpmlog(RPMLOG_ERR, _("Failed to dlopen %s %s\n"), path, dlerror());
63 /* make sure the plugin has the supported hooks flag */
64 (void) dlsym(handle, STR(PLUGIN_HOOKS));
65 if ((error = dlerror()) != NULL) {
66 rpmlog(RPMLOG_ERR, _("Failed to resolve symbol %s: %s\n"),
67 STR(PLUGIN_HOOKS), error);
71 argvAdd(&plugins->names, name);
72 plugins->handles = xrealloc(plugins->handles, (plugins->count + 1) * sizeof(*plugins->handles));
73 plugins->handles[plugins->count] = handle;
76 return rpmpluginsCallInit(plugins, name, opts);
79 rpmRC rpmpluginsAddPlugin(rpmPlugins plugins, const char *type, const char *name)
83 rpmRC rc = RPMRC_FAIL;
85 path = rpmExpand("%{?__", type, "_", name, "}", NULL);
86 if (!path || rstreq(path, "")) {
87 rpmlog(RPMLOG_ERR, _("Failed to expand %%__%s_%s macro\n"),
92 /* split the options from the path */
93 #define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
94 #define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
96 SKIPNONSPACE(options);
97 if (risspace(*options)) {
102 if (*options == '\0') {
106 rc = rpmpluginsAdd(plugins, name, path, options);
113 rpmPlugins rpmpluginsFree(rpmPlugins plugins)
116 for (i = 0; i < plugins->count; i++) {
117 rpmpluginsCallCleanup(plugins, plugins->names[i]);
118 dlclose(plugins->handles[i]);
120 plugins->handles = _free(plugins->handles);
121 plugins->names = argvFree(plugins->names);
129 /* Common define for all rpmpluginsCall* hook functions */
130 #define RPMPLUGINS_SET_HOOK_FUNC(hook) \
131 void *handle = NULL; \
134 index = rpmpluginsGetPluginIndex(plugins, name); \
136 rpmlog(RPMLOG_ERR, _("Plugin %s not loaded\n"), name); \
139 handle = plugins->handles[index]; \
141 rpmlog(RPMLOG_ERR, _("Plugin %s not loaded\n"), name); \
144 if (!rpmpluginsHookIsSupported(handle, hook)) { \
147 *(void **)(&hookFunc) = dlsym(handle, STR(hook##_FUNC)); \
148 if ((error = dlerror()) != NULL) { \
149 rpmlog(RPMLOG_ERR, _("Failed to resolve %s plugin symbol %s: %s\n"), name, STR(hook##_FUNC), error); \
152 if (rpmtsFlags(plugins->ts) & (RPMTRANS_FLAG_TEST | RPMTRANS_FLAG_JUSTDB)) { \
155 rpmlog(RPMLOG_DEBUG, "Plugin: calling hook %s in %s plugin\n", STR(hook##_FUNC), name);
157 rpmRC rpmpluginsCallInit(rpmPlugins plugins, const char *name, const char *opts)
159 rpmRC (*hookFunc)(rpmts, const char *, const char *);
160 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_INIT);
161 return hookFunc(plugins->ts, name, opts);
164 rpmRC rpmpluginsCallCleanup(rpmPlugins plugins, const char *name)
166 rpmRC (*hookFunc)(void);
167 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_CLEANUP);
171 rpmRC rpmpluginsCallOpenTE(rpmPlugins plugins, const char *name, rpmte te)
173 rpmRC (*hookFunc)(rpmte);
174 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_OPENTE);
178 rpmRC rpmpluginsCallCollectionPostAdd(rpmPlugins plugins, const char *name)
180 rpmRC (*hookFunc)(void);
181 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_POST_ADD);
185 rpmRC rpmpluginsCallCollectionPostAny(rpmPlugins plugins, const char *name)
187 rpmRC (*hookFunc)(void);
188 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_POST_ANY);
192 rpmRC rpmpluginsCallCollectionPreRemove(rpmPlugins plugins, const char *name)
194 rpmRC (*hookFunc)(void);
195 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_COLL_PRE_REMOVE);
199 rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts)
201 rpmRC (*hookFunc)(rpmts);
204 const char *name = NULL;
206 for (i = 0; i < plugins->count; i++) {
207 name = plugins->names[i];
208 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_PRE);
209 if (hookFunc(ts) == RPMRC_FAIL)
216 rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts)
218 rpmRC (*hookFunc)(rpmts);
221 const char *name = NULL;
223 for (i = 0; i < plugins->count; i++) {
224 name = plugins->names[i];
225 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_TSM_POST);
226 if (hookFunc(ts) == RPMRC_FAIL)
233 rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te)
235 rpmRC (*hookFunc)(rpmte);
238 const char *name = NULL;
240 for (i = 0; i < plugins->count; i++) {
241 name = plugins->names[i];
242 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_PRE);
243 if (hookFunc(te) == RPMRC_FAIL)
250 rpmRC rpmpluginsCallPsmPost(rpmPlugins plugins, rpmte te)
252 rpmRC (*hookFunc)(rpmte);
255 const char *name = NULL;
257 for (i = 0; i < plugins->count; i++) {
258 name = plugins->names[i];
259 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_PSM_POST);
260 if (hookFunc(te) == RPMRC_FAIL)
267 rpmRC rpmpluginsCallScriptletPre(rpmPlugins plugins, const char *s_name, int type)
269 rpmRC (*hookFunc)(const char*, int);
272 const char *name = NULL;
274 for (i = 0; i < plugins->count; i++) {
275 name = plugins->names[i];
276 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_SCRIPTLET_PRE);
277 if (hookFunc(s_name, type) == RPMRC_FAIL)
284 rpmRC rpmpluginsCallScriptletForkPost(rpmPlugins plugins, const char *path, int type)
286 rpmRC (*hookFunc)(const char*, int);
289 const char *name = NULL;
291 for (i = 0; i < plugins->count; i++) {
292 name = plugins->names[i];
293 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_SCRIPTLET_FORK_POST);
294 if (hookFunc(path, type) == RPMRC_FAIL)
301 rpmRC rpmpluginsCallScriptletPost(rpmPlugins plugins, const char *s_name, int type, int res)
303 rpmRC (*hookFunc)(const char*, int, int);
306 const char *name = NULL;
308 for (i = 0; i < plugins->count; i++) {
309 name = plugins->names[i];
310 RPMPLUGINS_SET_HOOK_FUNC(PLUGINHOOK_SCRIPTLET_POST);
311 if (hookFunc(s_name, type, res) == RPMRC_FAIL)