1 /* EINA - EFL data type library
2 * Copyright (C) 2007-2008 Jorge Luis Zapata Muga, Cedric BAIL
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.
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.
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/>.
25 #elif defined __GNUC__
26 # define alloca __builtin_alloca
28 # define alloca __alloca
29 #elif defined _MSC_VER
31 # define alloca _alloca
37 void *alloca (size_t);
42 #include <sys/types.h>
65 #include "eina_config.h"
66 #include "eina_private.h"
67 #include "eina_error.h"
68 #include "eina_file.h"
71 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
72 #include "eina_safety_checks.h"
73 #include "eina_module.h"
75 /*============================================================================*
77 *============================================================================*/
83 static int EINA_MODULE_LOG_DOM = -1;
87 #define ERR(...) EINA_LOG_DOM_ERR(EINA_MODULE_LOG_DOM, __VA_ARGS__)
92 #define WRN(...) EINA_LOG_DOM_WARN(EINA_MODULE_LOG_DOM, __VA_ARGS__)
97 #define DBG(...) EINA_LOG_DOM_DBG(EINA_MODULE_LOG_DOM, __VA_ARGS__)
107 #define EINA_MODULE_SYMBOL_INIT "__eina_module_init"
108 #define EINA_MODULE_SYMBOL_SHUTDOWN "__eina_module_shutdown"
117 typedef struct _Dir_List_Get_Cb_Data
122 } Dir_List_Get_Cb_Data;
124 typedef struct _Dir_List_Cb_Data
130 static Eina_Bool _dir_list_get_cb(Eina_Module *m, void *data)
132 Dir_List_Get_Cb_Data *cb_data = data;
133 Eina_Bool ret = EINA_TRUE;
136 ret = cb_data->cb(m, cb_data->data);
139 eina_array_push(cb_data->array, m);
144 static void _dir_list_cb(const char *name, const char *path, void *data)
146 Dir_List_Cb_Data *cb_data = data;
149 length = strlen(name);
150 if (length < sizeof(SHARED_LIB_SUFFIX)) /* x.so */
153 if (!strcmp(name + length - sizeof(SHARED_LIB_SUFFIX) + 1,
159 length = strlen(path) + strlen(name) + 2;
161 file = alloca(sizeof (char) * length);
163 snprintf(file, length, "%s" SEP_S "%s", path, name);
164 m = eina_module_new(file);
167 return; /* call the user provided cb on this module */
171 if (!cb_data->cb(m, cb_data->data))
176 static void _dir_arch_list_cb(const char *name, const char *path, void *data)
178 Dir_List_Get_Cb_Data *cb_data = data;
183 length = strlen(path) + 1 + strlen(name) + 1 +
184 strlen((char *)(cb_data->data)) + 1 + sizeof("module") +
185 sizeof(SHARED_LIB_SUFFIX) + 1;
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);
194 eina_array_push(cb_data->array, m);
202 /*============================================================================*
204 *============================================================================*/
210 static const char EINA_ERROR_WRONG_MODULE_STR[] =
211 "Wrong file format or no file module found";
212 static const char EINA_ERROR_MODULE_INIT_FAILED_STR[] =
213 "Module initialisation function failed";
215 EAPI Eina_Error EINA_ERROR_WRONG_MODULE = 0;
216 EAPI Eina_Error EINA_ERROR_MODULE_INIT_FAILED = 0;
224 * @brief Initialize the module loader module.
226 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
228 * This function sets up the module loader module of Eina. It is
229 * called by eina_init().
231 * This function sets up the module module of Eina. It also registers
232 * the errors #EINA_ERROR_WRONG_MODULE and #EINA_ERROR_MODULE_INIT_FAILED.
237 eina_module_init(void)
239 EINA_MODULE_LOG_DOM = eina_log_domain_register
240 ("eina_module", EINA_LOG_COLOR_DEFAULT);
241 if (EINA_MODULE_LOG_DOM < 0)
243 EINA_LOG_ERR("Could not register log domain: eina_module");
247 #define EEMR(n) n = eina_error_msg_static_register(n ## _STR)
248 EEMR(EINA_ERROR_WRONG_MODULE);
249 EEMR(EINA_ERROR_MODULE_INIT_FAILED);
257 * @brief Shut down the module loader module.
259 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
261 * This function shuts down the module loader module set up by
262 * eina_module_init(). It is called by eina_shutdown().
264 * @see eina_shutdown()
267 eina_module_shutdown(void)
269 /* TODO should we store every module when "new" is called and
270 * delete the list of modules here
273 eina_log_domain_unregister(EINA_MODULE_LOG_DOM);
274 EINA_MODULE_LOG_DOM = -1;
278 /*============================================================================*
280 *============================================================================*/
282 EAPI Eina_Module *eina_module_new(const char *file)
287 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
288 /* TODO check that the file exists. Update doc too */
291 EINA_SAFETY_ON_FALSE_RETURN_VAL(len > 0, NULL);
293 m = malloc(sizeof(Eina_Module) + len + 1);
296 ERR("could not malloc(%lu)",
297 (unsigned long)(sizeof(Eina_Module) + len + 1));
301 memcpy((char *)m->file, file, len + 1);
304 DBG("m=%p, file=%s", m, file);
309 EAPI Eina_Bool eina_module_free(Eina_Module *m)
311 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
313 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
316 if (eina_module_unload(m) == EINA_FALSE)
323 EAPI Eina_Bool eina_module_load(Eina_Module *m)
327 Eina_Module_Init *initcall;
329 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
331 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
336 dl_handle = dlopen(m->file, RTLD_NOW);
339 WRN("could not dlopen(\"%s\", RTLD_NOW): %s", m->file, dlerror());
340 eina_error_set(EINA_ERROR_WRONG_MODULE);
344 initcall = dlsym(dl_handle, EINA_MODULE_SYMBOL_INIT);
345 if ((!initcall) || (!(*initcall)))
348 if ((*initcall)() == EINA_TRUE)
351 WRN("could not find eina's entry symbol %s inside module %s",
352 EINA_MODULE_SYMBOL_INIT, m->file);
353 eina_error_set(EINA_ERROR_MODULE_INIT_FAILED);
357 DBG("successfully loaded %s", m->file);
358 m->handle = dl_handle;
361 DBG("ref %d", m->ref);
371 EAPI Eina_Bool eina_module_unload(Eina_Module *m)
374 Eina_Module_Shutdown *shut;
375 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
377 DBG("m=%p, handle=%p, file=%s, refs=%d", m, m->handle, m->file, m->ref);
382 shut = dlsym(m->handle, EINA_MODULE_SYMBOL_SHUTDOWN);
383 if ((shut) && (*shut))
388 DBG("unloaded module %s", m->file);
399 EAPI void *eina_module_symbol_get(const Eina_Module *m, const char *symbol)
402 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
403 EINA_SAFETY_ON_NULL_RETURN_VAL(m->handle, NULL);
404 return dlsym(m->handle, symbol);
412 EAPI const char *eina_module_file_get(const Eina_Module *m)
414 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
418 EAPI char *eina_module_symbol_path_get(const void *symbol, const char *sub_dir)
423 EINA_SAFETY_ON_NULL_RETURN_VAL(symbol, NULL);
425 if (dladdr(symbol, &eina_dl))
427 char *pos = strrchr(eina_dl.dli_fname, SEP_C);
435 l0 = strlen(eina_dl.dli_fname);
437 if (sub_dir && (*sub_dir != '\0'))
438 l2 = strlen(sub_dir);
440 path = malloc(l0 - l1 + l2 + 1);
443 memcpy(path, eina_dl.dli_fname, l0 - l1);
444 if (sub_dir && (*sub_dir != '\0'))
445 memcpy(path + l0 - l1, sub_dir, l2);
447 path[l0 - l1 + l2] = '\0';
455 #endif /* ! HAVE_DLADDR */
460 EAPI char *eina_module_environment_path_get(const char *env,
465 EINA_SAFETY_ON_NULL_RETURN_VAL(env, NULL);
467 env_dir = getenv(env);
474 l1 = strlen(env_dir);
475 if (sub_dir && (*sub_dir != '\0'))
476 l2 = strlen(sub_dir);
478 path = (char *)malloc(l1 + l2 + 1);
481 memcpy(path, env_dir, l1);
482 if (sub_dir && (*sub_dir != '\0'))
483 memcpy(path + l1, sub_dir, l2);
485 path[l1 + l2] = '\0';
494 EAPI Eina_Array *eina_module_arch_list_get(Eina_Array *array,
498 Dir_List_Get_Cb_Data list_get_cb_data;
500 if ((!path) || (!arch))
503 list_get_cb_data.array = array ? array : eina_array_new(4);
504 list_get_cb_data.cb = NULL;
505 list_get_cb_data.data = (void *)arch;
507 eina_file_dir_list(path, 0, &_dir_arch_list_cb, &list_get_cb_data);
509 return list_get_cb_data.array;
512 EAPI Eina_Array *eina_module_list_get(Eina_Array *array,
518 Dir_List_Get_Cb_Data list_get_cb_data;
519 Dir_List_Cb_Data list_cb_data;
524 list_get_cb_data.array = array ? array : eina_array_new(4);
525 list_get_cb_data.cb = cb;
526 list_get_cb_data.data = data;
528 list_cb_data.cb = &_dir_list_get_cb;
529 list_cb_data.data = &list_get_cb_data;
531 eina_file_dir_list(path, recursive, &_dir_list_cb, &list_cb_data);
533 return list_get_cb_data.array;
537 eina_module_find(const Eina_Array *array, const char *module)
540 Eina_Array_Iterator iterator;
543 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
549 /* basename() can modify its argument, so we first get a copie */
550 /* do not use strdupa, as opensolaris does not have it */
551 len = strlen(eina_module_file_get(m));
552 tmp = alloca(len + 1);
553 memcpy(tmp, eina_module_file_get(m), len + 1);
554 file_m = basename(tmp);
555 len = strlen(file_m);
556 len -= sizeof(SHARED_LIB_SUFFIX) - 1;
560 if (!strncmp(module, file_m, len))
567 EAPI void eina_module_list_load(Eina_Array *array)
569 Eina_Array_Iterator iterator;
573 EINA_SAFETY_ON_NULL_RETURN(array);
574 DBG("array %p, count %u", array, array->count);
575 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
579 EAPI void eina_module_list_unload(Eina_Array *array)
581 Eina_Array_Iterator iterator;
585 EINA_SAFETY_ON_NULL_RETURN(array);
586 DBG("array %p, count %u", array, array->count);
587 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
588 eina_module_unload(m);
591 EAPI void eina_module_list_free(Eina_Array *array)
593 Eina_Array_Iterator iterator;
597 EINA_SAFETY_ON_NULL_RETURN(array);
598 DBG("array %p, count %u", array, array->count);
599 EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
602 eina_array_flush(array);