Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  3 *
  4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5 * This program is free software; you can redistribute it and/or
  6 * modify it under the terms of the GNU Lesser General Public
  7 * License as published by the Free Software Foundation;
  8 * version 2.1 of the License (not later!)
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU Lesser General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU Lesser General Public
 16 * License along with this program; if not,  see <http://www.gnu.org/licenses>
 17 *
 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 19 */
 20
 21#include <string.h>
 22#include <dlfcn.h>
 23#include <stdlib.h>
 24#include <sys/types.h>
 25#include <sys/stat.h>
 26#include <unistd.h>
 27#include <dirent.h>
 28#include "event-parse.h"
 29#include "event-utils.h"
 30
 31#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
 32
 33struct plugin_list {
 34	struct plugin_list	*next;
 35	char			*name;
 36	void			*handle;
 37};
 38
 39static void
 40load_plugin(struct pevent *pevent, const char *path,
 41	    const char *file, void *data)
 42{
 43	struct plugin_list **plugin_list = data;
 44	pevent_plugin_load_func func;
 45	struct plugin_list *list;
 46	const char *alias;
 47	char *plugin;
 48	void *handle;
 49
 50	plugin = malloc(strlen(path) + strlen(file) + 2);
 51	if (!plugin) {
 52		warning("could not allocate plugin memory\n");
 53		return;
 54	}
 55
 56	strcpy(plugin, path);
 57	strcat(plugin, "/");
 58	strcat(plugin, file);
 59
 60	handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
 61	if (!handle) {
 62		warning("could not load plugin '%s'\n%s\n",
 63			plugin, dlerror());
 64		goto out_free;
 65	}
 66
 67	alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
 68	if (!alias)
 69		alias = file;
 70
 71	func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
 72	if (!func) {
 73		warning("could not find func '%s' in plugin '%s'\n%s\n",
 74			PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
 75		goto out_free;
 76	}
 77
 78	list = malloc(sizeof(*list));
 79	if (!list) {
 80		warning("could not allocate plugin memory\n");
 81		goto out_free;
 82	}
 83
 84	list->next = *plugin_list;
 85	list->handle = handle;
 86	list->name = plugin;
 87	*plugin_list = list;
 88
 89	pr_stat("registering plugin: %s", plugin);
 90	func(pevent);
 91	return;
 92
 93 out_free:
 94	free(plugin);
 95}
 96
 97static void
 98load_plugins_dir(struct pevent *pevent, const char *suffix,
 99		 const char *path,
100		 void (*load_plugin)(struct pevent *pevent,
101				     const char *path,
102				     const char *name,
103				     void *data),
104		 void *data)
105{
106	struct dirent *dent;
107	struct stat st;
108	DIR *dir;
109	int ret;
110
111	ret = stat(path, &st);
112	if (ret < 0)
113		return;
114
115	if (!S_ISDIR(st.st_mode))
116		return;
117
118	dir = opendir(path);
119	if (!dir)
120		return;
121
122	while ((dent = readdir(dir))) {
123		const char *name = dent->d_name;
124
125		if (strcmp(name, ".") == 0 ||
126		    strcmp(name, "..") == 0)
127			continue;
128
129		/* Only load plugins that end in suffix */
130		if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
131			continue;
132
133		load_plugin(pevent, path, name, data);
134	}
135
136	closedir(dir);
137}
138
139static void
140load_plugins(struct pevent *pevent, const char *suffix,
141	     void (*load_plugin)(struct pevent *pevent,
142				 const char *path,
143				 const char *name,
144				 void *data),
145	     void *data)
146{
147	char *home;
148	char *path;
149	char *envdir;
150
151	/*
152	 * If a system plugin directory was defined,
153	 * check that first.
154	 */
155#ifdef PLUGIN_DIR
156	load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
157#endif
158
159	/*
160	 * Next let the environment-set plugin directory
161	 * override the system defaults.
162	 */
163	envdir = getenv("TRACEEVENT_PLUGIN_DIR");
164	if (envdir)
165		load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
166
167	/*
168	 * Now let the home directory override the environment
169	 * or system defaults.
170	 */
171	home = getenv("HOME");
172	if (!home)
173		return;
174
175	path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
176	if (!path) {
177		warning("could not allocate plugin memory\n");
178		return;
179	}
180
181	strcpy(path, home);
182	strcat(path, "/");
183	strcat(path, LOCAL_PLUGIN_DIR);
184
185	load_plugins_dir(pevent, suffix, path, load_plugin, data);
186
187	free(path);
188}
189
190struct plugin_list*
191traceevent_load_plugins(struct pevent *pevent)
192{
193	struct plugin_list *list = NULL;
194
195	load_plugins(pevent, ".so", load_plugin, &list);
196	return list;
197}
198
199void
200traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent)
201{
202	pevent_plugin_unload_func func;
203	struct plugin_list *list;
204
205	while (plugin_list) {
206		list = plugin_list;
207		plugin_list = list->next;
208		func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
209		if (func)
210			func(pevent);
211		dlclose(list->handle);
212		free(list->name);
213		free(list);
214	}
215}