Blame lib/rpmplugins.c

2ff057
2ff057
#include "system.h"
2ff057
2ff057
#include <rpm/rpmmacro.h>
2ff057
#include <rpm/rpmtypes.h>
2ff057
#include <rpm/rpmlog.h>
2ff057
#include <rpm/rpmstring.h>
2ff057
#include <rpm/rpmts.h>
2ff057
2ff057
#include "lib/rpmplugins.h"
2ff057
2ff057
#define STR1(x) #x
2ff057
#define STR(x) STR1(x)
2ff057
2ff057
static rpmRC rpmpluginsCallInit(rpmPlugin plugin, rpmts ts);
2ff057
2ff057
struct rpmPlugin_s {
2ff057
    char *name;
2ff057
    char *opts;
2ff057
    void *handle;
2ff057
    void *priv;
2ff057
    rpmPluginHooks hooks;
2ff057
};
2ff057
2ff057
struct rpmPlugins_s {
2ff057
    rpmPlugin *plugins;
2ff057
    int count;
2ff057
    rpmts ts;
2ff057
};
2ff057
2ff057
static rpmPlugin rpmpluginsGetPlugin(rpmPlugins plugins, const char *name)
2ff057
{
2ff057
    int i;
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	if (rstreq(plugin->name, name)) {
2ff057
	    return plugin;
2ff057
	}
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
int rpmpluginsPluginAdded(rpmPlugins plugins, const char *name)
2ff057
{
2ff057
    return (rpmpluginsGetPlugin(plugins, name) != NULL);
2ff057
}
2ff057
2ff057
rpmPlugins rpmpluginsNew(rpmts ts)
2ff057
{
2ff057
    rpmPlugins plugins = xcalloc(1, sizeof(*plugins));
2ff057
    plugins->ts = ts;
2ff057
    return plugins;
2ff057
}
2ff057
2ff057
static rpmPlugin rpmPluginNew(const char *name, const char *path,
2ff057
			      const char *opts)
2ff057
{
2ff057
    rpmPlugin plugin = NULL;
2ff057
    rpmPluginHooks hooks = NULL;
2ff057
    char *error;
2ff057
    char *hooks_name = NULL;
2ff057
2ff057
    void *handle = dlopen(path, RTLD_LAZY);
2ff057
    if (!handle) {
2ff057
	rpmlog(RPMLOG_ERR, _("Failed to dlopen %s %s\n"), path, dlerror());
2ff057
	return NULL;
2ff057
    }
2ff057
2ff057
    /* make sure the plugin has the supported hooks flag */
2ff057
    hooks_name = rstrscat(NULL, name, "_hooks", NULL);
2ff057
    hooks = dlsym(handle, hooks_name);
2ff057
    if ((error = dlerror()) != NULL) {
2ff057
	rpmlog(RPMLOG_ERR, _("Failed to resolve symbol %s: %s\n"),
2ff057
	       hooks_name, error);
2ff057
	dlclose(handle);
2ff057
    } else {
2ff057
	plugin = xcalloc(1, sizeof(*plugin));
2ff057
	plugin->name = xstrdup(name);
2ff057
	plugin->handle = handle;
2ff057
	plugin->hooks = hooks;
2ff057
	if (opts)
2ff057
	    plugin->opts = xstrdup(opts);
2ff057
    }
2ff057
    free(hooks_name);
2ff057
2ff057
    return plugin;
2ff057
}
2ff057
2ff057
static rpmPlugin rpmPluginFree(rpmPlugin plugin)
2ff057
{
2ff057
    if (plugin) {
2ff057
	rpmPluginHooks hooks = plugin->hooks;
2ff057
	if (hooks->cleanup)
2ff057
	    hooks->cleanup(plugin);
2ff057
	dlclose(plugin->handle);
2ff057
	free(plugin->name);
2ff057
	free(plugin->opts);
2ff057
	free(plugin);
2ff057
    }
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
const char *rpmPluginName(rpmPlugin plugin)
2ff057
{
2ff057
    return (plugin != NULL) ? plugin->name : NULL;
2ff057
}
2ff057
2ff057
const char *rpmPluginOpts(rpmPlugin plugin)
2ff057
{
2ff057
    return (plugin != NULL) ? plugin->opts : NULL;
2ff057
}
2ff057
2ff057
void * rpmPluginGetData(rpmPlugin plugin)
2ff057
{
2ff057
    return (plugin != NULL) ? plugin->priv : NULL;
2ff057
}
2ff057
2ff057
void rpmPluginSetData(rpmPlugin plugin, void *data)
2ff057
{
2ff057
    if (plugin)
2ff057
	plugin->priv = data;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsAdd(rpmPlugins plugins, const char *name, const char *path,
2ff057
		    const char *opts)
2ff057
{
2ff057
    rpmRC rc;
2ff057
    rpmPlugin plugin = rpmPluginNew(name, path, opts);
2ff057
2ff057
    if (plugin == NULL)
2ff057
	return RPMRC_FAIL;
2ff057
    
2ff057
    rc = rpmpluginsCallInit(plugin, plugins->ts);
2ff057
2ff057
    if (rc == RPMRC_OK) {
2ff057
	plugins->plugins = xrealloc(plugins->plugins,
2ff057
			    (plugins->count + 1) * sizeof(*plugins->plugins));
2ff057
	plugins->plugins[plugins->count] = plugin;
2ff057
	plugins->count++;
2ff057
    } else {
2ff057
	rpmPluginFree(plugin);
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsAddPlugin(rpmPlugins plugins, const char *type, const char *name)
2ff057
{
2ff057
    char *path;
2ff057
    char *options;
2ff057
    rpmRC rc = RPMRC_FAIL;
2ff057
2ff057
    path = rpmExpand("%{?__", type, "_", name, "}", NULL);
2ff057
    if (!path || rstreq(path, "")) {
2ff057
	rpmlog(RPMLOG_DEBUG, _("Plugin %%__%s_%s not configured\n"),
2ff057
	       type, name);
2ff057
	rc = RPMRC_NOTFOUND;
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
    /* split the options from the path */
2ff057
#define SKIPSPACE(s)    { while (*(s) &&  risspace(*(s))) (s)++; }
2ff057
#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
2ff057
    options = path;
2ff057
    SKIPNONSPACE(options);
2ff057
    if (risspace(*options)) {
2ff057
	*options = '\0';
2ff057
	options++;
2ff057
	SKIPSPACE(options);
2ff057
    }
2ff057
    if (*options == '\0') {
2ff057
	options = NULL;
2ff057
    }
2ff057
2ff057
    rc = rpmpluginsAdd(plugins, name, path, options);
2ff057
2ff057
  exit:
2ff057
    _free(path);
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmPlugins rpmpluginsFree(rpmPlugins plugins)
2ff057
{
2ff057
    if (plugins) {
2ff057
	for (int i = 0; i < plugins->count; i++) {
2ff057
	    rpmPlugin plugin = plugins->plugins[i];
2ff057
	    rpmPluginFree(plugin);
2ff057
	}
2ff057
	plugins->plugins = _free(plugins->plugins);
2ff057
	plugins->ts = NULL;
2ff057
	_free(plugins);
2ff057
    }
2ff057
2ff057
    return NULL;
2ff057
}
2ff057
2ff057
#define RPMPLUGINS_GET_PLUGIN(name) \
2ff057
	plugin = rpmpluginsGetPlugin(plugins, name); \
2ff057
	if (plugin == NULL || plugin->handle == NULL) { \
2ff057
		rpmlog(RPMLOG_ERR, _("Plugin %s not loaded\n"), name); \
2ff057
		return RPMRC_FAIL; \
2ff057
	}
2ff057
2ff057
/* Common define for all rpmpluginsCall* hook functions */
2ff057
#define RPMPLUGINS_SET_HOOK_FUNC(hook) \
2ff057
	rpmPluginHooks hooks = (plugin != NULL) ? plugin->hooks : NULL; \
2ff057
	hookFunc = (hooks != NULL) ? hooks->hook : NULL; \
2ff057
	if (hookFunc) { \
2ff057
	    rpmlog(RPMLOG_DEBUG, "Plugin: calling hook %s in %s plugin\n", \
2ff057
		   STR(hook), plugin->name); \
2ff057
	}
2ff057
2ff057
static rpmRC rpmpluginsCallInit(rpmPlugin plugin, rpmts ts)
2ff057
{
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
    plugin_init_func hookFunc;
2ff057
    RPMPLUGINS_SET_HOOK_FUNC(init);
2ff057
    if (hookFunc) {
2ff057
        rc = hookFunc(plugin, ts);
2ff057
        if (rc != RPMRC_OK && rc != RPMRC_NOTFOUND)
2ff057
            rpmlog(RPMLOG_ERR, "Plugin %s: hook init failed\n", plugin->name);
2ff057
    }
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallTsmPre(rpmPlugins plugins, rpmts ts)
2ff057
{
2ff057
    plugin_tsm_pre_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(tsm_pre);
2ff057
	if (hookFunc && hookFunc(plugin, ts) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook tsm_pre failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallTsmPost(rpmPlugins plugins, rpmts ts, int res)
2ff057
{
2ff057
    plugin_tsm_post_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(tsm_post);
2ff057
	if (hookFunc && hookFunc(plugin, ts, res) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_WARNING, "Plugin %s: hook tsm_post failed\n", plugin->name);
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallPsmPre(rpmPlugins plugins, rpmte te)
2ff057
{
2ff057
    plugin_psm_pre_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(psm_pre);
2ff057
	if (hookFunc && hookFunc(plugin, te) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook psm_pre failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallPsmPost(rpmPlugins plugins, rpmte te, int res)
2ff057
{
2ff057
    plugin_psm_post_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(psm_post);
2ff057
	if (hookFunc && hookFunc(plugin, te, res) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_WARNING, "Plugin %s: hook psm_post failed\n", plugin->name);
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallScriptletPre(rpmPlugins plugins, const char *s_name, int type)
2ff057
{
2ff057
    plugin_scriptlet_pre_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(scriptlet_pre);
2ff057
	if (hookFunc && hookFunc(plugin, s_name, type) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook scriplet_pre failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallScriptletForkPost(rpmPlugins plugins, const char *path, int type)
2ff057
{
2ff057
    plugin_scriptlet_fork_post_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(scriptlet_fork_post);
2ff057
	if (hookFunc && hookFunc(plugin, path, type) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook scriplet_fork_post failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallScriptletPost(rpmPlugins plugins, const char *s_name, int type, int res)
2ff057
{
2ff057
    plugin_scriptlet_post_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(scriptlet_post);
2ff057
	if (hookFunc && hookFunc(plugin, s_name, type, res) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_WARNING, "Plugin %s: hook scriplet_post failed\n", plugin->name);
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallFsmFilePre(rpmPlugins plugins, rpmfi fi, const char *path,
2ff057
			       mode_t file_mode, rpmFsmOp op)
2ff057
{
2ff057
    plugin_fsm_file_pre_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(fsm_file_pre);
2ff057
	if (hookFunc && hookFunc(plugin, fi, path, file_mode, op) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_pre failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallFsmFilePost(rpmPlugins plugins, rpmfi fi, const char *path,
2ff057
                                mode_t file_mode, rpmFsmOp op, int res)
2ff057
{
2ff057
    plugin_fsm_file_post_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(fsm_file_post);
2ff057
	if (hookFunc && hookFunc(plugin, fi, path, file_mode, op, res) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_WARNING, "Plugin %s: hook fsm_file_post failed\n", plugin->name);
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmpluginsCallFsmFilePrepare(rpmPlugins plugins, rpmfi fi,
2ff057
				   const char *path, const char *dest,
2ff057
				   mode_t file_mode, rpmFsmOp op)
2ff057
{
2ff057
    plugin_fsm_file_prepare_func hookFunc;
2ff057
    int i;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
2ff057
    for (i = 0; i < plugins->count; i++) {
2ff057
	rpmPlugin plugin = plugins->plugins[i];
2ff057
	RPMPLUGINS_SET_HOOK_FUNC(fsm_file_prepare);
2ff057
	if (hookFunc && hookFunc(plugin, fi, path, dest, file_mode, op) == RPMRC_FAIL) {
2ff057
	    rpmlog(RPMLOG_ERR, "Plugin %s: hook fsm_file_prepare failed\n", plugin->name);
2ff057
	    rc = RPMRC_FAIL;
2ff057
	}
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}