Port: dirfd is not portable, replace it
[babeltrace.git] / lib / plugin / plugin.c
CommitLineData
33b34c43
PP
1/*
2 * plugin.c
3 *
55bb57e0 4 * Babeltrace Plugin (generic)
33b34c43
PP
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
8c1a3187
PP
30#define BT_LOG_TAG "PLUGIN"
31#include <babeltrace/lib-logging-internal.h>
32
6fbd4105 33#include <babeltrace/babeltrace-internal.h>
3d9990ac 34#include <babeltrace/compiler-internal.h>
33b34c43 35#include <babeltrace/ref.h>
1670bffd 36#include <babeltrace/common-internal.h>
33b34c43 37#include <babeltrace/plugin/plugin-internal.h>
55bb57e0 38#include <babeltrace/plugin/plugin-so-internal.h>
8c1a3187
PP
39#include <babeltrace/graph/component-class.h>
40#include <babeltrace/graph/component-class-internal.h>
c55a9f58 41#include <babeltrace/types.h>
33b34c43 42#include <glib.h>
33b34c43
PP
43#include <unistd.h>
44#include <stdlib.h>
9ac68eb1 45#include <stdint.h>
8c1a3187 46#include <inttypes.h>
33b34c43
PP
47#include <sys/stat.h>
48#include <dirent.h>
49
6fbd4105
PP
50#define PYTHON_PLUGIN_PROVIDER_FILENAME "libbabeltrace-python-plugin-provider." G_MODULE_SUFFIX
51#define PYTHON_PLUGIN_PROVIDER_SYM_NAME bt_plugin_python_create_all_from_file
52#define PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR TOSTRING(PYTHON_PLUGIN_PROVIDER_SYM_NAME)
33b34c43 53
6fbd4105
PP
54#ifdef BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT
55#include <babeltrace/plugin/python-plugin-provider-internal.h>
33b34c43 56static
a8ff38ef 57struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path) =
6fbd4105
PP
58 bt_plugin_python_create_all_from_file;
59#else /* BT_BUILT_IN_PYTHON_PLUGIN_SUPPORT */
60static GModule *python_plugin_provider_module;
61static
a8ff38ef 62struct bt_plugin_set *(*bt_plugin_python_create_all_from_file_sym)(const char *path);
33b34c43 63
6fbd4105
PP
64__attribute__((constructor)) static
65void init_python_plugin_provider(void) {
8c1a3187 66 BT_LOGD_STR("Loading Python plugin provider module.");
6fbd4105
PP
67 python_plugin_provider_module =
68 g_module_open(PYTHON_PLUGIN_PROVIDER_FILENAME,
69 G_MODULE_BIND_LOCAL);
70 if (!python_plugin_provider_module) {
8c1a3187 71 BT_LOGI("Cannot find `%s`: continuing without Python plugin support.",
6fbd4105
PP
72 PYTHON_PLUGIN_PROVIDER_FILENAME);
73 return;
33b34c43
PP
74 }
75
6fbd4105
PP
76 if (!g_module_symbol(python_plugin_provider_module,
77 PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR,
78 (gpointer) &bt_plugin_python_create_all_from_file_sym)) {
8c1a3187
PP
79 BT_LOGI("Cannot find the Python plugin provider loading symbol: continuing without Python plugin support: "
80 "file=\"%s\", symbol=\"%s\"",
81 PYTHON_PLUGIN_PROVIDER_FILENAME,
82 PYTHON_PLUGIN_PROVIDER_SYM_NAME_STR);
83 return;
33b34c43 84 }
8c1a3187 85
9e0bf9b0 86 BT_LOGI("Loaded Python plugin provider module: addr=%p",
8c1a3187 87 python_plugin_provider_module);
33b34c43
PP
88}
89
6fbd4105
PP
90__attribute__((destructor)) static
91void fini_python_plugin_provider(void) {
92 if (python_plugin_provider_module) {
8c1a3187
PP
93 BT_LOGD("Unloading Python plugin provider module.");
94
95 if (!g_module_close(python_plugin_provider_module)) {
96 BT_LOGE("Failed to close the Python plugin provider module: %s.",
97 g_module_error());
98 }
99
6fbd4105 100 python_plugin_provider_module = NULL;
6ba0b073 101 }
6ba0b073 102}
6fbd4105 103#endif
6ba0b073 104
a8ff38ef 105extern
544d0515 106int64_t bt_plugin_set_get_plugin_count(struct bt_plugin_set *plugin_set)
a8ff38ef 107{
544d0515 108 int64_t count = -1;
a8ff38ef
PP
109
110 if (!plugin_set) {
8c1a3187 111 BT_LOGW_STR("Invalid parameter: plugin set is NULL.");
a8ff38ef
PP
112 goto end;
113 }
114
9ac68eb1 115 count = (int64_t) plugin_set->plugins->len;
a8ff38ef
PP
116
117end:
118 return count;
119}
120
121extern
122struct bt_plugin *bt_plugin_set_get_plugin(struct bt_plugin_set *plugin_set,
9ac68eb1 123 uint64_t index)
a8ff38ef
PP
124{
125 struct bt_plugin *plugin = NULL;
126
8c1a3187
PP
127 if (!plugin_set) {
128 BT_LOGW_STR("Invalid parameter: plugin set is NULL.");
129 goto end;
130 }
131
132 if (index >= plugin_set->plugins->len) {
133 BT_LOGW("Invalid parameter: index is out of bounds: "
134 "addr=%p, index=%" PRIu64 ", count=%u",
135 plugin_set, index, plugin_set->plugins->len);
a8ff38ef
PP
136 goto end;
137 }
138
139 plugin = bt_get(g_ptr_array_index(plugin_set->plugins, index));
140
141end:
142 return plugin;
143}
144
145struct bt_plugin_set *bt_plugin_create_all_from_static(void)
6ba0b073 146{
8c1a3187 147 /* bt_plugin_so_create_all_from_static() logs errors */
55bb57e0 148 return bt_plugin_so_create_all_from_static();
6ba0b073
PP
149}
150
a8ff38ef 151struct bt_plugin_set *bt_plugin_create_all_from_file(const char *path)
33b34c43 152{
a8ff38ef 153 struct bt_plugin_set *plugin_set = NULL;
33b34c43
PP
154
155 if (!path) {
8c1a3187 156 BT_LOGW_STR("Invalid parameter: path is NULL.");
6ba0b073 157 goto end;
33b34c43
PP
158 }
159
8c1a3187 160 BT_LOGD("Creating plugins from file: path=\"%s\"", path);
6ba0b073 161
55bb57e0 162 /* Try shared object plugins */
a8ff38ef
PP
163 plugin_set = bt_plugin_so_create_all_from_file(path);
164 if (plugin_set) {
6ba0b073
PP
165 goto end;
166 }
167
6fbd4105
PP
168 /* Try Python plugins if support is available */
169 if (bt_plugin_python_create_all_from_file_sym) {
a8ff38ef
PP
170 plugin_set = bt_plugin_python_create_all_from_file_sym(path);
171 if (plugin_set) {
6fbd4105
PP
172 goto end;
173 }
6ba0b073
PP
174 }
175
33b34c43 176end:
8c1a3187
PP
177 if (plugin_set) {
178 BT_LOGD("Created %u plugins from file: "
179 "path=\"%s\", count=%u, plugin-set-addr=%p",
180 plugin_set->plugins->len, path,
181 plugin_set->plugins->len, plugin_set);
182 } else {
183 BT_LOGD("Found no plugins in file: path=\"%s\"", path);
184 }
185
a8ff38ef 186 return plugin_set;
33b34c43
PP
187}
188
1670bffd
PP
189static void destroy_gstring(void *data)
190{
191 g_string_free(data, TRUE);
192}
193
2b43acf9 194struct bt_plugin *bt_plugin_find(const char *plugin_name)
1670bffd
PP
195{
196 const char *system_plugin_dir;
197 char *home_plugin_dir = NULL;
198 const char *envvar;
199 struct bt_plugin *plugin = NULL;
a8ff38ef 200 struct bt_plugin_set *plugin_set = NULL;
1670bffd
PP
201 GPtrArray *dirs = NULL;
202 int ret;
a8ff38ef 203 size_t i, j;
1670bffd
PP
204
205 if (!plugin_name) {
8c1a3187 206 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
1670bffd
PP
207 goto end;
208 }
209
8c1a3187
PP
210 BT_LOGD("Finding named plugin in standard directories and built-in plugins: "
211 "name=\"%s\"", plugin_name);
1670bffd
PP
212 dirs = g_ptr_array_new_with_free_func((GDestroyNotify) destroy_gstring);
213 if (!dirs) {
8c1a3187 214 BT_LOGE_STR("Failed to allocate a GPtrArray.");
1670bffd
PP
215 goto end;
216 }
217
218 /*
219 * Search order is:
220 *
221 * 1. BABELTRACE_PLUGIN_PATH environment variable
222 * (colon-separated list of directories)
223 * 2. ~/.local/lib/babeltrace/plugins
224 * 3. Default system directory for Babeltrace plugins, usually
225 * /usr/lib/babeltrace/plugins or
226 * /usr/local/lib/babeltrace/plugins if installed
227 * locally
228 * 4. Built-in plugins (static)
229 *
230 * Directories are searched non-recursively.
231 */
232 envvar = getenv("BABELTRACE_PLUGIN_PATH");
233 if (envvar) {
234 ret = bt_common_append_plugin_path_dirs(envvar, dirs);
235 if (ret) {
8c1a3187 236 BT_LOGE_STR("Failed to append plugin path to array of directories.");
1670bffd
PP
237 goto end;
238 }
239 }
240
241 home_plugin_dir = bt_common_get_home_plugin_path();
242 if (home_plugin_dir) {
243 GString *home_plugin_dir_str =
244 g_string_new(home_plugin_dir);
245
246 if (!home_plugin_dir_str) {
8c1a3187 247 BT_LOGE_STR("Failed to allocate a GString.");
1670bffd
PP
248 goto end;
249 }
250
251 g_ptr_array_add(dirs, home_plugin_dir_str);
252 }
253
254 system_plugin_dir = bt_common_get_system_plugin_path();
255 if (system_plugin_dir) {
256 GString *system_plugin_dir_str =
257 g_string_new(system_plugin_dir);
258
259 if (!system_plugin_dir_str) {
8c1a3187 260 BT_LOGE_STR("Failed to allocate a GString.");
1670bffd
PP
261 goto end;
262 }
263
264 g_ptr_array_add(dirs, system_plugin_dir_str);
265 }
266
267 for (i = 0; i < dirs->len; i++) {
268 GString *dir = g_ptr_array_index(dirs, i);
269
a8ff38ef 270 BT_PUT(plugin_set);
8c1a3187 271
50ad9320
PP
272 /*
273 * Skip this if the directory does not exist because
274 * bt_plugin_create_all_from_dir() would log a warning.
275 */
276 if (!g_file_test(dir->str, G_FILE_TEST_IS_DIR)) {
277 BT_LOGV("Skipping nonexistent directory path: "
278 "path=\"%s\"", dir->str);
279 continue;
280 }
281
8c1a3187 282 /* bt_plugin_create_all_from_dir() logs details/errors */
c55a9f58 283 plugin_set = bt_plugin_create_all_from_dir(dir->str, BT_FALSE);
a8ff38ef 284 if (!plugin_set) {
8c1a3187
PP
285 BT_LOGD("No plugins found in directory: path=\"%s\"",
286 dir->str);
1670bffd
PP
287 continue;
288 }
289
a8ff38ef
PP
290 for (j = 0; j < plugin_set->plugins->len; j++) {
291 struct bt_plugin *candidate_plugin =
292 g_ptr_array_index(plugin_set->plugins, j);
1670bffd 293
a8ff38ef
PP
294 if (strcmp(bt_plugin_get_name(candidate_plugin),
295 plugin_name) == 0) {
8c1a3187
PP
296 BT_LOGD("Plugin found in directory: name=\"%s\", path=\"%s\"",
297 plugin_name, dir->str);
a8ff38ef 298 plugin = bt_get(candidate_plugin);
1670bffd
PP
299 goto end;
300 }
1670bffd 301 }
8c1a3187
PP
302
303 BT_LOGD("Plugin not found in directory: name=\"%s\", path=\"%s\"",
304 plugin_name, dir->str);
1670bffd
PP
305 }
306
a8ff38ef
PP
307 bt_put(plugin_set);
308 plugin_set = bt_plugin_create_all_from_static();
8c1a3187
PP
309 if (plugin_set) {
310 for (j = 0; j < plugin_set->plugins->len; j++) {
311 struct bt_plugin *candidate_plugin =
312 g_ptr_array_index(plugin_set->plugins, j);
a8ff38ef 313
8c1a3187
PP
314 if (strcmp(bt_plugin_get_name(candidate_plugin),
315 plugin_name) == 0) {
316 BT_LOGD("Plugin found in built-in plugins: "
317 "name=\"%s\"", plugin_name);
318 plugin = bt_get(candidate_plugin);
319 goto end;
320 }
1670bffd 321 }
1670bffd
PP
322 }
323
324end:
325 free(home_plugin_dir);
a8ff38ef 326 bt_put(plugin_set);
1670bffd
PP
327
328 if (dirs) {
329 g_ptr_array_free(dirs, TRUE);
330 }
331
8c1a3187
PP
332 if (plugin) {
333 BT_LOGD("Found plugin in standard directories and built-in plugins: "
334 "addr=%p, name=\"%s\", path=\"%s\"",
335 plugin, plugin_name, bt_plugin_get_path(plugin));
336 } else {
337 BT_LOGD("No plugin found in standard directories and built-in plugins: "
338 "name=\"%s\"", plugin_name);
339 }
340
1670bffd
PP
341 return plugin;
342}
343
2b43acf9
PP
344struct bt_component_class *bt_plugin_find_component_class(
345 const char *plugin_name, const char *comp_cls_name,
346 enum bt_component_class_type comp_cls_type)
347{
348 struct bt_plugin *plugin = NULL;
349 struct bt_component_class *comp_cls = NULL;
350
8c1a3187
PP
351 if (!plugin_name) {
352 BT_LOGW_STR("Invalid parameter: plugin name is NULL.");
2b43acf9
PP
353 goto end;
354 }
355
8c1a3187
PP
356 if (!comp_cls_name) {
357 BT_LOGW_STR("Invalid parameter: component class name is NULL.");
358 goto end;
359 }
360
361 BT_LOGD("Finding named plugin and component class in standard directories and built-in plugins: "
362 "plugin-name=\"%s\", comp-class-name=\"%s\"",
363 plugin_name, comp_cls_name);
2b43acf9
PP
364 plugin = bt_plugin_find(plugin_name);
365 if (!plugin) {
8c1a3187 366 BT_LOGD_STR("Plugin not found.");
2b43acf9
PP
367 goto end;
368 }
369
370 comp_cls = bt_plugin_get_component_class_by_name_and_type(
371 plugin, comp_cls_name, comp_cls_type);
8c1a3187
PP
372 if (!comp_cls) {
373 BT_LOGD("Component class not found in plugin: "
374 "plugin-addr=%p, plugin-path=\"%s\"",
375 plugin, bt_plugin_get_path(plugin));
376 }
2b43acf9
PP
377
378end:
379 bt_put(plugin);
380 return comp_cls;
381}
382
33b34c43
PP
383/* Allocate dirent as recommended by READDIR(3), NOTES on readdir_r */
384static
385struct dirent *alloc_dirent(const char *path)
386{
387 size_t len;
388 long name_max;
389 struct dirent *entry;
390
391 name_max = pathconf(path, _PC_NAME_MAX);
392 if (name_max == -1) {
393 name_max = PATH_MAX;
394 }
395 len = offsetof(struct dirent, d_name) + name_max + 1;
396 entry = zmalloc(len);
397 return entry;
398}
399
400static
401enum bt_plugin_status bt_plugin_create_append_all_from_dir(
a8ff38ef 402 struct bt_plugin_set *plugin_set, const char *path,
c55a9f58 403 bt_bool recurse)
33b34c43
PP
404{
405 DIR *directory = NULL;
406 struct dirent *entry = NULL, *result = NULL;
407 char *file_path = NULL;
6ba0b073 408 size_t path_len;
33b34c43
PP
409 enum bt_plugin_status ret = BT_PLUGIN_STATUS_OK;
410
6ba0b073 411 if (!path) {
8c1a3187 412 BT_LOGW_STR("Invalid parameter: path is NULL.");
6ba0b073
PP
413 ret = BT_PLUGIN_STATUS_ERROR;
414 goto end;
415 }
416
417 path_len = strlen(path);
33b34c43 418 if (path_len >= PATH_MAX) {
8c1a3187
PP
419 BT_LOGW("Invalid parameter: path length is too large: "
420 "path-length=%zu", path_len);
33b34c43
PP
421 ret = BT_PLUGIN_STATUS_ERROR;
422 goto end;
423 }
424
425 entry = alloc_dirent(path);
426 if (!entry) {
8c1a3187 427 BT_LOGE_STR("Failed to allocate a directory entry.");
33b34c43
PP
428 ret = BT_PLUGIN_STATUS_ERROR;
429 goto end;
430 }
431
432 file_path = zmalloc(PATH_MAX);
433 if (!file_path) {
8c1a3187 434 BT_LOGE("Failed to allocate %zu bytes.", (size_t) PATH_MAX);
33b34c43
PP
435 ret = BT_PLUGIN_STATUS_NOMEM;
436 goto end;
437 }
438
439 strncpy(file_path, path, path_len);
440 /* Append a trailing '/' to the path */
441 if (file_path[path_len - 1] != '/') {
442 file_path[path_len++] = '/';
443 }
444
445 directory = opendir(file_path);
446 if (!directory) {
8c1a3187
PP
447 if (errno == EACCES) {
448 BT_LOGD("Cannot open directory: %s: continuing: "
449 "path=\"%s\", errno=%d",
450 strerror(errno), file_path, errno);
451 goto end;
452 }
453
dbd7f7e9 454 BT_LOGW("Cannot open directory: %s: "
8c1a3187
PP
455 "path=\"%s\", errno=%d",
456 strerror(errno), file_path, errno);
33b34c43
PP
457 ret = BT_PLUGIN_STATUS_ERROR;
458 goto end;
459 }
460
461 /* Recursively walk directory */
462 while (!readdir_r(directory, entry, &result) && result) {
463 struct stat st;
464 int stat_ret;
465 size_t file_name_len;
466
8c1a3187
PP
467 if (strcmp(result->d_name, ".") == 0 ||
468 strcmp(result->d_name, "..") == 0) {
50ad9320 469 /* Obviously not logging this */
8c1a3187
PP
470 continue;
471 }
472
33b34c43
PP
473 if (result->d_name[0] == '.') {
474 /* Skip hidden files, . and .. */
8c1a3187
PP
475 BT_LOGV("Skipping hidden file: path=\"%s/%s\"",
476 path, result->d_name);
33b34c43
PP
477 continue;
478 }
479
480 file_name_len = strlen(result->d_name);
481
482 if (path_len + file_name_len >= PATH_MAX) {
8c1a3187
PP
483 BT_LOGD("Skipping file because its path length is too large: continuing: "
484 "path=\"%s/%s\", length=%zu",
485 path, result->d_name,
486 (size_t) (path_len + file_name_len));
33b34c43
PP
487 continue;
488 }
489
490 strncpy(file_path + path_len, result->d_name, file_name_len);
491 file_path[path_len + file_name_len] = '\0';
33b34c43
PP
492 stat_ret = stat(file_path, &st);
493 if (stat_ret < 0) {
494 /* Continue to next file / directory. */
8c1a3187
PP
495 BT_LOGD("Cannot get file information: %s: continuing: "
496 "path=\"%s\", errno=%d",
497 strerror(errno), file_path, errno);
33b34c43
PP
498 continue;
499 }
500
501 if (S_ISDIR(st.st_mode) && recurse) {
a8ff38ef 502 ret = bt_plugin_create_append_all_from_dir(plugin_set,
c55a9f58 503 file_path, BT_TRUE);
33b34c43 504 if (ret < 0) {
8c1a3187
PP
505 BT_LOGW("Cannot recurse into directory to find plugins: "
506 "path=\"%s\", ret=%d", file_path, ret);
33b34c43
PP
507 goto end;
508 }
509 } else if (S_ISREG(st.st_mode)) {
a8ff38ef 510 struct bt_plugin_set *plugins_from_file =
6ba0b073 511 bt_plugin_create_all_from_file(file_path);
33b34c43 512
6ba0b073 513 if (plugins_from_file) {
a8ff38ef
PP
514 size_t j;
515
516 for (j = 0; j < plugins_from_file->plugins->len; j++) {
517 struct bt_plugin *plugin =
518 g_ptr_array_index(plugins_from_file->plugins, j);
6ba0b073 519
8c1a3187
PP
520 BT_LOGD("Adding plugin to plugin set: "
521 "plugin-path=\"%s\", plugin-addr=%p, plugin-name=\"%s\"",
522 file_path, plugin,
523 bt_plugin_get_name(plugin));
a8ff38ef
PP
524 bt_plugin_set_add_plugin(plugin_set,
525 plugin);
6ba0b073
PP
526 }
527
a8ff38ef 528 bt_put(plugins_from_file);
33b34c43
PP
529 }
530 }
531 }
8c1a3187 532
33b34c43
PP
533end:
534 if (directory) {
535 if (closedir(directory)) {
536 /*
537 * We don't want to override the error since there is
538 * nothing could do.
539 */
8c1a3187
PP
540 BT_LOGE("Cannot close directory entry: %s: "
541 "path=\"%s\", errno=%d",
542 strerror(errno), path, errno);
33b34c43
PP
543 }
544 }
8c1a3187 545
33b34c43
PP
546 free(entry);
547 free(file_path);
548 return ret;
549}
550
a8ff38ef 551struct bt_plugin_set *bt_plugin_create_all_from_dir(const char *path,
c55a9f58 552 bt_bool recurse)
33b34c43 553{
a8ff38ef 554 struct bt_plugin_set *plugin_set;
33b34c43
PP
555 enum bt_plugin_status status;
556
8c1a3187
PP
557 BT_LOGD("Creating all plugins in directory: path=\"%s\", recurse=%d",
558 path, recurse);
a8ff38ef
PP
559 plugin_set = bt_plugin_set_create();
560 if (!plugin_set) {
8c1a3187 561 BT_LOGE_STR("Cannot create empty plugin set.");
a8ff38ef
PP
562 goto error;
563 }
564
33b34c43 565 /* Append found plugins to array */
a8ff38ef 566 status = bt_plugin_create_append_all_from_dir(plugin_set, path,
33b34c43
PP
567 recurse);
568 if (status < 0) {
8c1a3187 569 BT_LOGW("Cannot append plugins found in directory: "
dbd7f7e9
PP
570 "path=\"%s\", status=%s",
571 path, bt_plugin_status_string(status));
33b34c43
PP
572 goto error;
573 }
574
8c1a3187
PP
575 BT_LOGD("Created %u plugins from directory: count=%u, path=\"%s\"",
576 plugin_set->plugins->len, plugin_set->plugins->len, path);
33b34c43
PP
577 goto end;
578
579error:
a8ff38ef 580 BT_PUT(plugin_set);
33b34c43
PP
581
582end:
a8ff38ef 583 return plugin_set;
33b34c43
PP
584}
585
33b34c43
PP
586const char *bt_plugin_get_name(struct bt_plugin *plugin)
587{
8c1a3187
PP
588 const char *val = NULL;
589
590 if (!plugin) {
591 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
592 goto end;
593 }
594
595 if (plugin->info.name_set) {
596 val = plugin->info.name->str;
597 }
598
599end:
600 return val;
33b34c43
PP
601}
602
603const char *bt_plugin_get_author(struct bt_plugin *plugin)
604{
8c1a3187
PP
605 const char *val = NULL;
606
607 if (!plugin) {
608 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
609 goto end;
610 }
611
612 if (plugin->info.author_set) {
613 val = plugin->info.author->str;
614 }
615
616end:
617 return val;
33b34c43
PP
618}
619
620const char *bt_plugin_get_license(struct bt_plugin *plugin)
621{
8c1a3187
PP
622 const char *val = NULL;
623
624 if (!plugin) {
625 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
626 goto end;
627 }
628
629 if (plugin->info.license_set) {
630 val = plugin->info.license->str;
631 }
632
633end:
634 return val;
33b34c43
PP
635}
636
637const char *bt_plugin_get_path(struct bt_plugin *plugin)
638{
8c1a3187
PP
639 const char *val = NULL;
640
641 if (!plugin) {
642 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
643 goto end;
644 }
645
646 if (plugin->info.path_set) {
647 val = plugin->info.path->str;
648 }
649
650end:
651 return val;
33b34c43
PP
652}
653
654const char *bt_plugin_get_description(struct bt_plugin *plugin)
655{
8c1a3187
PP
656 const char *val = NULL;
657
658 if (!plugin) {
659 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
660 goto end;
661 }
662
663 if (plugin->info.description_set) {
664 val = plugin->info.description->str;
665 }
666
667end:
668 return val;
33b34c43
PP
669}
670
b6de043b
PP
671enum bt_plugin_status bt_plugin_get_version(struct bt_plugin *plugin,
672 unsigned int *major, unsigned int *minor, unsigned int *patch,
673 const char **extra)
674{
675 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
676
8c1a3187
PP
677 if (!plugin) {
678 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
679 status = BT_PLUGIN_STATUS_ERROR;
680 goto end;
681 }
682
683 if (!plugin->info.version_set) {
684 BT_LOGV("Plugin's version is not set: addr=%p", plugin);
b6de043b
PP
685 status = BT_PLUGIN_STATUS_ERROR;
686 goto end;
687 }
688
689 if (major) {
55bb57e0 690 *major = plugin->info.version.major;
b6de043b
PP
691 }
692
693 if (minor) {
55bb57e0 694 *minor = plugin->info.version.minor;
b6de043b
PP
695 }
696
697 if (patch) {
55bb57e0 698 *patch = plugin->info.version.patch;
b6de043b
PP
699 }
700
701 if (extra) {
55bb57e0 702 *extra = plugin->info.version.extra->str;
b6de043b
PP
703 }
704
705end:
706 return status;
707}
708
544d0515 709int64_t bt_plugin_get_component_class_count(struct bt_plugin *plugin)
33b34c43 710{
9ac68eb1 711 return plugin ? plugin->comp_classes->len : (int64_t) -1;
33b34c43
PP
712}
713
9ac68eb1
PP
714struct bt_component_class *bt_plugin_get_component_class_by_index(
715 struct bt_plugin *plugin, uint64_t index)
33b34c43
PP
716{
717 struct bt_component_class *comp_class = NULL;
718
8c1a3187
PP
719 if (!plugin) {
720 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
721 goto error;
722 }
723
724 if (index >= plugin->comp_classes->len) {
725 BT_LOGW("Invalid parameter: index is out of bounds: "
726 "addr=%p, index=%" PRIu64 ", count=%u",
727 plugin, index, plugin->comp_classes->len);
33b34c43
PP
728 goto error;
729 }
730
731 comp_class = g_ptr_array_index(plugin->comp_classes, index);
732 bt_get(comp_class);
733 goto end;
734
735error:
736 BT_PUT(comp_class);
737
738end:
739 return comp_class;
740}
741
742struct bt_component_class *bt_plugin_get_component_class_by_name_and_type(
743 struct bt_plugin *plugin, const char *name,
d3e4dcd8 744 enum bt_component_class_type type)
33b34c43
PP
745{
746 struct bt_component_class *comp_class = NULL;
747 size_t i;
748
8c1a3187
PP
749 if (!plugin) {
750 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
751 goto error;
752 }
753
754 if (!name) {
755 BT_LOGW_STR("Invalid parameter: name is NULL.");
33b34c43
PP
756 goto error;
757 }
758
759 for (i = 0; i < plugin->comp_classes->len; i++) {
760 struct bt_component_class *comp_class_candidate =
761 g_ptr_array_index(plugin->comp_classes, i);
762 const char *comp_class_cand_name =
763 bt_component_class_get_name(comp_class_candidate);
d3e4dcd8 764 enum bt_component_class_type comp_class_cand_type =
33b34c43
PP
765 bt_component_class_get_type(comp_class_candidate);
766
767 assert(comp_class_cand_name);
768 assert(comp_class_cand_type >= 0);
769
770 if (strcmp(name, comp_class_cand_name) == 0 &&
771 comp_class_cand_type == type) {
772 comp_class = bt_get(comp_class_candidate);
773 break;
774 }
775 }
776
777 goto end;
778
779error:
780 BT_PUT(comp_class);
781
782end:
783 return comp_class;
784}
785
33b34c43
PP
786enum bt_plugin_status bt_plugin_add_component_class(
787 struct bt_plugin *plugin, struct bt_component_class *comp_class)
788{
789 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
790 struct bt_component_class *comp_class_dup = NULL;
33b34c43
PP
791 int comp_class_index = -1;
792
8c1a3187
PP
793 if (!plugin) {
794 BT_LOGW_STR("Invalid parameter: plugin is NULL.");
795 goto error;
796 }
797
798 if (!comp_class) {
799 BT_LOGW_STR("Invalid parameter: component class is NULL.");
800 goto error;
801 }
802
803 if (plugin->frozen) {
804 BT_LOGW("Invalid parameter: plugin is frozen: "
805 "addr=%p, name=\"%s\"", plugin,
806 bt_plugin_get_name(plugin));
33b34c43
PP
807 goto error;
808 }
809
810 /* Check for duplicate */
811 comp_class_dup = bt_plugin_get_component_class_by_name_and_type(plugin,
812 bt_component_class_get_name(comp_class),
813 bt_component_class_get_type(comp_class));
814 if (comp_class_dup) {
8c1a3187
PP
815 BT_LOGW("Invalid parameter: a component class with this name and type already exists in the plugin: "
816 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
817 "comp-class-name=\"%s\", comp-class-type=%s",
818 plugin, bt_plugin_get_name(plugin),
819 bt_plugin_get_path(plugin),
33b34c43 820 bt_component_class_get_name(comp_class),
8c1a3187
PP
821 bt_component_class_type_string(
822 bt_component_class_get_type(comp_class)));
33b34c43
PP
823 goto error;
824 }
825
826 /* Add new component class */
827 comp_class_index = plugin->comp_classes->len;
828 g_ptr_array_add(plugin->comp_classes, bt_get(comp_class));
829
55bb57e0
PP
830 /* Special case for a shared object plugin */
831 if (plugin->type == BT_PLUGIN_TYPE_SO) {
3230ee6b 832 bt_plugin_so_on_add_component_class(plugin, comp_class);
33b34c43
PP
833 }
834
8c1a3187
PP
835 BT_LOGD("Added component class to plugin: "
836 "plugin-addr=%p, plugin-name=\"%s\", plugin-path=\"%s\", "
837 "comp-class-addr=%p, comp-class-name=\"%s\", comp-class-type=%s",
838 plugin, bt_plugin_get_name(plugin),
839 bt_plugin_get_path(plugin),
840 comp_class,
841 bt_component_class_get_name(comp_class),
842 bt_component_class_type_string(
843 bt_component_class_get_type(comp_class)));
33b34c43
PP
844 goto end;
845
846error:
33b34c43
PP
847 /* Remove entry from plugin's component classes (if added) */
848 if (comp_class_index >= 0) {
849 g_ptr_array_remove_index(plugin->comp_classes,
850 comp_class_index);
851 }
852
853 status = BT_PLUGIN_STATUS_ERROR;
854
855end:
856 bt_put(comp_class_dup);
857 return status;
858}
This page took 0.067676 seconds and 4 git commands to generate.