aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/lib/eina_module.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/lib/eina_module.c')
-rw-r--r--libraries/eina/src/lib/eina_module.c604
1 files changed, 0 insertions, 604 deletions
diff --git a/libraries/eina/src/lib/eina_module.c b/libraries/eina/src/lib/eina_module.c
deleted file mode 100644
index f4f3242..0000000
--- a/libraries/eina/src/lib/eina_module.c
+++ /dev/null
@@ -1,604 +0,0 @@
1/* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric BAIL
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H
20# include "config.h"
21#endif
22
23#ifdef HAVE_ALLOCA_H
24# include <alloca.h>
25#elif defined __GNUC__
26# define alloca __builtin_alloca
27#elif defined _AIX
28# define alloca __alloca
29#elif defined _MSC_VER
30# include <malloc.h>
31# define alloca _alloca
32#else
33# include <stddef.h>
34# ifdef __cplusplus
35extern "C"
36# endif
37void *alloca (size_t);
38#endif
39
40#include <stdlib.h>
41#include <stdio.h>
42#include <sys/types.h>
43#include <string.h>
44
45#ifdef HAVE_LIBGEN_H
46# include <libgen.h>
47#endif
48
49#ifdef HAVE_DLOPEN
50# include <dlfcn.h>
51#endif
52
53#ifdef HAVE_EVIL
54# include <Evil.h>
55#endif
56
57#ifdef HAVE_ESCAPE
58# include <Escape.h>
59#endif
60
61#ifdef HAVE_EXOTIC_H
62# include <Exotic.h>
63#endif
64
65#include "eina_config.h"
66#include "eina_private.h"
67#include "eina_error.h"
68#include "eina_file.h"
69#include "eina_log.h"
70
71/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
72#include "eina_safety_checks.h"
73#include "eina_module.h"
74
75/*============================================================================*
76* Local *
77*============================================================================*/
78
79/**
80 * @cond LOCAL
81 */
82
83static int EINA_MODULE_LOG_DOM = -1;
84#ifdef ERR
85#undef ERR
86#endif
87#define ERR(...) EINA_LOG_DOM_ERR(EINA_MODULE_LOG_DOM, __VA_ARGS__)
88
89#ifdef WRN
90#undef WRN
91#endif
92#define WRN(...) EINA_LOG_DOM_WARN(EINA_MODULE_LOG_DOM, __VA_ARGS__)
93
94#ifdef DBG
95#undef DBG
96#endif
97#define DBG(...) EINA_LOG_DOM_DBG(EINA_MODULE_LOG_DOM, __VA_ARGS__)
98
99#ifdef _WIN32
100# define SEP_C '\\'
101# define SEP_S "\\"
102#else
103# define SEP_C '/'
104# define SEP_S "/"
105#endif
106
107#define EINA_MODULE_SYMBOL_INIT "__eina_module_init"
108#define EINA_MODULE_SYMBOL_SHUTDOWN "__eina_module_shutdown"
109
110struct _Eina_Module
111{
112 void *handle;
113 int ref;
114 const char file[];
115};
116
117typedef struct _Dir_List_Get_Cb_Data
118{
119 Eina_Module_Cb cb;
120 void *data;
121 Eina_Array *array;
122} Dir_List_Get_Cb_Data;
123
124typedef struct _Dir_List_Cb_Data
125{
126 Eina_Module_Cb cb;
127 void *data;
128} Dir_List_Cb_Data;
129
130static Eina_Bool _dir_list_get_cb(Eina_Module *m, void *data)
131{
132 Dir_List_Get_Cb_Data *cb_data = data;
133 Eina_Bool ret = EINA_TRUE;
134
135 if (cb_data->cb)
136 ret = cb_data->cb(m, cb_data->data);
137
138 if (ret)
139 eina_array_push(cb_data->array, m);
140
141 return ret;
142}
143
144static void _dir_list_cb(const char *name, const char *path, void *data)
145{
146 Dir_List_Cb_Data *cb_data = data;
147 size_t length;
148
149 length = strlen(name);
150 if (length < sizeof(SHARED_LIB_SUFFIX)) /* x.so */
151 return;
152
153 if (!strcmp(name + length - sizeof(SHARED_LIB_SUFFIX) + 1,
154 SHARED_LIB_SUFFIX))
155 {
156 char *file;
157 Eina_Module *m;
158
159 length = strlen(path) + strlen(name) + 2;
160
161 file = alloca(sizeof (char) * length);
162
163 snprintf(file, length, "%s" SEP_S "%s", path, name);
164 m = eina_module_new(file);
165 if (!m)
166 {
167 return; /* call the user provided cb on this module */
168
169 }
170
171 if (!cb_data->cb(m, cb_data->data))
172 eina_module_free(m);
173 }
174}
175
176static void _dir_arch_list_cb(const char *name, const char *path, void *data)
177{
178 Dir_List_Get_Cb_Data *cb_data = data;
179 Eina_Module *m;
180 char *file = NULL;
181 size_t length;
182
183 length = strlen(path) + 1 + strlen(name) + 1 +
184 strlen((char *)(cb_data->data)) + 1 + sizeof("module") +
185 sizeof(SHARED_LIB_SUFFIX) + 1;
186
187 file = alloca(length);
188 snprintf(file, length, "%s" SEP_S "%s" SEP_S "%s" SEP_S "module" SHARED_LIB_SUFFIX,
189 path, name, (char *)(cb_data->data));
190 m = eina_module_new(file);
191 if (!m)
192 return;
193
194 eina_array_push(cb_data->array, m);
195}
196
197/**
198 * @endcond
199 */
200
201
202/*============================================================================*
203* Global *
204*============================================================================*/
205
206/**
207 * @cond LOCAL
208 */
209
210static const char EINA_ERROR_WRONG_MODULE_STR[] =
211 "Wrong file format or no file module found";
212static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] =
213 "Module initialisation function failed";
214
215EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0;
216EAPI Eina_Error EINA_ERROR_MODULE_INIT_FAILED = 0;
217
218/**
219 * @endcond
220 */
221
222/**
223 * @internal
224 * @brief Initialize the module loader module.
225 *
226 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
227 *
228 * This function sets up the module loader module of Eina. It is
229 * called by eina_init().
230 *
231 * This function sets up the module module of Eina. It also registers
232 * the errors #EINA_ERROR_WRONG_MODULE and
233 * #EINA_ERROR_MODULE_INIT_FAILED.
234 *
235 * @see eina_init()
236 */
237Eina_Bool
238eina_module_init(void)
239{
240 EINA_MODULE_LOG_DOM = eina_log_domain_register
241 ("eina_module", EINA_LOG_COLOR_DEFAULT);
242 if (EINA_MODULE_LOG_DOM < 0)
243 {
244 EINA_LOG_ERR("Could not register log domain: eina_module");
245 return EINA_FALSE;
246 }
247
248#define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
249 EEMR(EINA_ERROR_WRONG_MODULE);
250 EEMR(EINA_ERROR_MODULE_INIT_FAILED);
251#undef EEMR
252
253 return EINA_TRUE;
254}
255
256/**
257 * @internal
258 * @brief Shut down the module loader module.
259 *
260 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
261 *
262 * This function shuts down the module loader module set up by
263 * eina_module_init(). It is called by eina_shutdown().
264 *
265 * @see eina_shutdown()
266 */
267Eina_Bool
268eina_module_shutdown(void)
269{
270 /* TODO should we store every module when "new" is called and
271 * delete the list of modules here
272 */
273
274 eina_log_domain_unregister(EINA_MODULE_LOG_DOM);
275 EINA_MODULE_LOG_DOM = -1;
276 return EINA_TRUE;
277}
278
279/*============================================================================*
280* API *
281*============================================================================*/
282
283EAPI Eina_Module *eina_module_new(const char *file)
284{
285 Eina_Module *m;
286 size_t len;
287
288 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
289 /* TODO check that the file exists. Update doc too */
290
291 len = strlen(file);
292 EINA_SAFETY_ON_FALSE_RETURN_VAL(len > 0, NULL);
293
294 m = malloc(sizeof(Eina_Module) + len + 1);
295 if (!m)
296 {
297 ERR("could not malloc(%lu)",
298 (unsigned long)(sizeof(Eina_Module) + len + 1));
299 return NULL;
300 }
301
302 memcpy((char *)m->file, file, len + 1);
303 m->ref = 0;
304 m->handle = NULL;
305 DBG("m=%p, file=%s", m, file);
306
307 return m;
308}
309
310EAPI Eina_Bool eina_module_free(Eina_Module *m)
311{
312 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
313
314 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
315
316 if (m->handle)
317 if (eina_module_unload(m) == EINA_FALSE)
318 return EINA_FALSE;
319
320 free(m);
321 return EINA_TRUE;
322}
323
324EAPI Eina_Bool eina_module_load(Eina_Module *m)
325{
326#ifdef HAVE_DLOPEN
327 void *dl_handle;
328 Eina_Module_Init *initcall;
329
330 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
331
332 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
333
334 if (m->handle)
335 goto loaded;
336
337 dl_handle = dlopen(m->file, RTLD_NOW);
338 if (!dl_handle)
339 {
340 WRN("could not dlopen(\"%s\", RTLD_NOW): %s", m->file, dlerror());
341 eina_error_set(EINA_ERROR_WRONG_MODULE);
342 return EINA_FALSE;
343 }
344
345 initcall = dlsym(dl_handle, EINA_MODULE_SYMBOL_INIT);
346 if ((!initcall) || (!(*initcall)))
347 goto ok;
348
349 if ((*initcall)() == EINA_TRUE)
350 goto ok;
351
352 WRN("could not find eina's entry symbol %s inside module %s",
353 EINA_MODULE_SYMBOL_INIT, m->file);
354 eina_error_set(EINA_ERROR_MODULE_INIT_FAILED);
355 dlclose(dl_handle);
356 return EINA_FALSE;
357ok:
358 DBG("successfully loaded %s", m->file);
359 m->handle = dl_handle;
360loaded:
361 m->ref++;
362 DBG("ref %d", m->ref);
363
364 eina_error_set(0);
365 return EINA_TRUE;
366#else
367 (void) m;
368 return EINA_FALSE;
369#endif
370}
371
372EAPI Eina_Bool eina_module_unload(Eina_Module *m)
373{
374#ifdef HAVE_DLOPEN
375 Eina_Module_Shutdown *shut;
376 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
377
378 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
379
380 m->ref--;
381 if (!m->ref)
382 {
383 shut = dlsym(m->handle, EINA_MODULE_SYMBOL_SHUTDOWN);
384 if ((shut) && (*shut))
385 (*shut)();
386
387 dlclose(m->handle);
388 m->handle = NULL;
389 DBG("unloaded module %s", m->file);
390 return EINA_TRUE;
391 }
392
393 return EINA_FALSE;
394#else
395 (void) m;
396 return EINA_FALSE;
397#endif
398}
399
400EAPI void *eina_module_symbol_get(const Eina_Module *m, const char *symbol)
401{
402#ifdef HAVE_DLOPEN
403 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
404 EINA_SAFETY_ON_NULL_RETURN_VAL(m->handle, NULL);
405 return dlsym(m->handle, symbol);
406#else
407 (void) m;
408 (void) symbol;
409 return NULL;
410#endif
411}
412
413EAPI const char *eina_module_file_get(const Eina_Module *m)
414{
415 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
416 return m->file;
417}
418
419EAPI char *eina_module_symbol_path_get(const void *symbol, const char *sub_dir)
420{
421#ifdef HAVE_DLADDR
422 Dl_info eina_dl;
423
424 EINA_SAFETY_ON_NULL_RETURN_VAL(symbol, NULL);
425
426 if (dladdr(symbol, &eina_dl))
427 {
428 char *pos = strrchr(eina_dl.dli_fname, SEP_C);
429 if (pos)
430 {
431 char *path;
432 int l0;
433 int l1;
434 int l2 = 0;
435
436 l0 = strlen(eina_dl.dli_fname);
437 l1 = strlen(pos);
438 if (sub_dir && (*sub_dir != '\0'))
439 l2 = strlen(sub_dir);
440
441 path = malloc(l0 - l1 + l2 + 1);
442 if (path)
443 {
444 memcpy(path, eina_dl.dli_fname, l0 - l1);
445 if (sub_dir && (*sub_dir != '\0'))
446 memcpy(path + l0 - l1, sub_dir, l2);
447
448 path[l0 - l1 + l2] = '\0';
449 return path;
450 }
451 }
452 }
453#else
454 (void) symbol;
455 (void) sub_dir;
456#endif /* ! HAVE_DLADDR */
457
458 return NULL;
459}
460
461EAPI char *eina_module_environment_path_get(const char *env,
462 const char *sub_dir)
463{
464 const char *env_dir;
465
466 EINA_SAFETY_ON_NULL_RETURN_VAL(env, NULL);
467
468 env_dir = getenv(env);
469 if (env_dir)
470 {
471 char *path;
472 size_t l1;
473 size_t l2 = 0;
474
475 l1 = strlen(env_dir);
476 if (sub_dir && (*sub_dir != '\0'))
477 l2 = strlen(sub_dir);
478
479 path = (char *)malloc(l1 + l2 + 1);
480 if (path)
481 {
482 memcpy(path, env_dir, l1);
483 if (sub_dir && (*sub_dir != '\0'))
484 memcpy(path + l1, sub_dir, l2);
485
486 path[l1 + l2] = '\0';
487
488 return path;
489 }
490 }
491
492 return NULL;
493}
494
495EAPI Eina_Array *eina_module_arch_list_get(Eina_Array *array,
496 const char *path,
497 const char *arch)
498{
499 Dir_List_Get_Cb_Data list_get_cb_data;
500
501 if ((!path) || (!arch))
502 return array;
503
504 list_get_cb_data.array = array ? array : eina_array_new(4);
505 list_get_cb_data.cb = NULL;
506 list_get_cb_data.data = (void *)arch;
507
508 eina_file_dir_list(path, 0, &_dir_arch_list_cb, &list_get_cb_data);
509
510 return list_get_cb_data.array;
511}
512
513EAPI Eina_Array *eina_module_list_get(Eina_Array *array,
514 const char *path,
515 Eina_Bool recursive,
516 Eina_Module_Cb cb,
517 void *data)
518{
519 Dir_List_Get_Cb_Data list_get_cb_data;
520 Dir_List_Cb_Data list_cb_data;
521
522 if (!path)
523 return array;
524
525 list_get_cb_data.array = array ? array : eina_array_new(4);
526 list_get_cb_data.cb = cb;
527 list_get_cb_data.data = data;
528
529 list_cb_data.cb = &_dir_list_get_cb;
530 list_cb_data.data = &list_get_cb_data;
531
532 eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data);
533
534 return list_get_cb_data.array;
535}
536
537EAPI Eina_Module *
538eina_module_find(const Eina_Array *array, const char *module)
539{
540 unsigned int i;
541 Eina_Array_Iterator iterator;
542 Eina_Module *m;
543
544 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
545 {
546 char *file_m;
547 char *tmp;
548 ssize_t len;
549
550 /* basename() can modify its argument, so we first get a copie */
551 /* do not use strdupa, as opensolaris does not have it */
552 len = strlen(eina_module_file_get(m));
553 tmp = alloca(len + 1);
554 memcpy(tmp, eina_module_file_get(m), len + 1);
555 file_m = basename(tmp);
556 len = strlen(file_m);
557 len -= sizeof(SHARED_LIB_SUFFIX) - 1;
558 if (len <= 0)
559 continue;
560
561 if (!strncmp(module, file_m, len))
562 return m;;
563 }
564
565 return NULL;
566}
567
568EAPI void eina_module_list_load(Eina_Array *array)
569{
570 Eina_Array_Iterator iterator;
571 Eina_Module *m;
572 unsigned int i;
573
574 EINA_SAFETY_ON_NULL_RETURN(array);
575 DBG("array %p, count %u", array, array->count);
576 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
577 eina_module_load(m);
578}
579
580EAPI void eina_module_list_unload(Eina_Array *array)
581{
582 Eina_Array_Iterator iterator;
583 Eina_Module *m;
584 unsigned int i;
585
586 EINA_SAFETY_ON_NULL_RETURN(array);
587 DBG("array %p, count %u", array, array->count);
588 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
589 eina_module_unload(m);
590}
591
592EAPI void eina_module_list_free(Eina_Array *array)
593{
594 Eina_Array_Iterator iterator;
595 Eina_Module *m;
596 unsigned int i;
597
598 EINA_SAFETY_ON_NULL_RETURN(array);
599 DBG("array %p, count %u", array, array->count);
600 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
601 eina_module_free(m);
602
603 eina_array_flush(array);
604}