/* * libopensync - A synchronization framework * Copyright (C) 2004-2005 Armin Bauer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "opensync.h" #include "opensync_internals.h" #include "opensync-module.h" #include "opensync_module_internals.h" typedef osync_bool (* fkt_b_plugenv_error)(OSyncPluginEnv *env, OSyncError **error); typedef osync_bool (* fkt_b_fmtenv_error)(OSyncFormatEnv *env, OSyncError **error); OSyncModule *osync_module_new(OSyncError **error) { OSyncModule *module = NULL; osync_trace(TRACE_ENTRY, "%s(%p)", __func__, error); module = osync_try_malloc0(sizeof(OSyncModule), error); if (!module) { osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return NULL; } osync_trace(TRACE_EXIT, "%s: %p", __func__, module); return module; } /*! @brief Used to free a module * * Frees a module * * @param module Pointer to the module * */ void osync_module_free(OSyncModule *module) { osync_trace(TRACE_ENTRY, "%s(%p)", __func__, module); if (module->module) osync_module_unload(module); if (module->path) g_free(module->path); g_free(module); osync_trace(TRACE_EXIT, "%s", __func__); } /*! @brief Used to look up a symbol on the plugin * * Looks up and returns a function * * @param plugin Pointer to the plugin * @param name The name of the function to look up * @param error Pointer to a error struct * @return Pointer to the function * */ void *osync_module_get_function(OSyncModule *module, const char *name, OSyncError **error) { void *function = NULL; if (!module->module) { osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "You need to load the module before getting a function"); return NULL; } if (!g_module_symbol(module->module, name, &function)) { osync_error_set(error, OSYNC_ERROR_PARAMETER, "Unable to locate symbol %s: %s", name, g_module_error()); return NULL; } return function; } osync_bool osync_module_get_sync_info(OSyncModule *module, OSyncPluginEnv *env, OSyncError **error) { fkt_b_plugenv_error fct_info = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, module, env, error); /* Load the get_info symbol */ fct_info = (fkt_b_plugenv_error) osync_module_get_function(module, "get_sync_info", NULL); if (!fct_info) { osync_trace(TRACE_EXIT, "%s: Not get_sync_info function", __func__); return TRUE; } /* Call the get_info function */ if (!fct_info(env, error)) goto error; osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } osync_bool osync_module_get_format_info(OSyncModule *module, OSyncFormatEnv *env, OSyncError **error) { fkt_b_fmtenv_error fct_info = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, module, env, error); /* Load the get_info symbol */ fct_info = (fkt_b_fmtenv_error) osync_module_get_function(module, "get_format_info", NULL); if (!fct_info) { osync_trace(TRACE_EXIT, "%s: Not get_format_info function", __func__); return TRUE; } /* Call the get_info function */ if (!fct_info(env, error)) goto error; osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } osync_bool osync_module_get_conversion_info(OSyncModule *module, OSyncFormatEnv *env, OSyncError **error) { fkt_b_fmtenv_error fct_info = NULL; osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, module, env, error); /* Load the get_info symbol */ fct_info = (fkt_b_fmtenv_error) osync_module_get_function(module, "get_conversion_info", NULL); if (!fct_info) { osync_trace(TRACE_EXIT, "%s: Not get_format_info function", __func__); return TRUE; } /* Call the get_info function */ if (!fct_info(env, error)) goto error; osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } int osync_module_get_version(OSyncModule *module) { void *function = NULL; int (* fct_version)(void) = NULL; int version = 0; osync_trace(TRACE_ENTRY, "%s(%p)", __func__, module); /* Load the get_info symbol */ if (!g_module_symbol(module->module, "get_version", &function) || !function) { osync_trace(TRACE_EXIT, "%s: get_version not found. Not a library?", __func__); return 0; } fct_version = (int (* )(void)) function; /* Call the get_info function */ version = fct_version(); osync_trace(TRACE_EXIT, "%s: %i", __func__, version); return version; } osync_bool osync_module_check(OSyncModule *module, OSyncError **error) { int version = 0; osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, module, error); version = osync_module_get_version(module); if (!version) { osync_trace(TRACE_EXIT, "%s: No version", __func__); return FALSE; } if (version != OPENSYNC_PLUGINVERSION) { osync_error_set(error, OSYNC_ERROR_GENERIC, "Plugin API version mismatch. Is: %i. Should %i", version, OPENSYNC_PLUGINVERSION); osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; } /*! @brief dlopen()s a format plugin * * The get_info() function on the format plugin gets called * * @param env The environment in which to open the plugin * @param path Where to find this plugin * @param error Pointer to a error struct * @return Pointer to the plugin on success, NULL otherwise * */ osync_bool osync_module_load(OSyncModule *module, const char *path, OSyncError **error) { osync_trace(TRACE_ENTRY, "%s(%p, %s, %p)", __func__, module, path, error); osync_assert(!module->module); if (!g_module_supported()) { osync_error_set(error, OSYNC_ERROR_GENERIC, "This platform does not support loading of modules"); goto error; } /* Try to open the module or fail if an error occurs */ module->module = g_module_open(path, G_MODULE_BIND_LAZY); if (!module->module) { osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to open module %s: %s", path, g_module_error()); goto error; } module->path = g_strdup(path); osync_trace(TRACE_EXIT, "%s", __func__); return TRUE; error: osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); return FALSE; } /*! @brief Closes a module * * @param env The environment from which to remove the module * @param module The module to unload * */ void osync_module_unload(OSyncModule *module) { osync_trace(TRACE_ENTRY, "%s(%p)", __func__, module); osync_assert(module->module); if (!osync_module_get_function(module, "dont_free", NULL)) #ifndef DEBUG_MODULES g_module_close(module->module); #endif module->module = NULL; osync_trace(TRACE_EXIT, "%s", __func__); } /*@}*/