diff options
Diffstat (limited to 'src/H5PLint.c')
| -rw-r--r-- | src/H5PLint.c | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/src/H5PLint.c b/src/H5PLint.c new file mode 100644 index 0000000..4c970c5 --- /dev/null +++ b/src/H5PLint.c @@ -0,0 +1,509 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Internal routines for managing plugins. + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5PLmodule.h" /* This source code file is part of the H5PL module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5PLpkg.h" /* Plugin */ +#include "H5Zprivate.h" /* Filter pipeline */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Bitmask that controls whether classes of plugins + * (e.g.: filters, VOL drivers) can be loaded. + */ +static unsigned int H5PL_plugin_control_mask_g = H5PL_ALL_PLUGIN; + +/* This flag will be set to FALSE if the HDF5_PLUGIN_PRELOAD + * environment variable was set to H5PL_NO_PLUGIN at + * package initialization. + */ +static hbool_t H5PL_allow_plugins_g = TRUE; + +/*------------------------------------------------------------------------- + * Function: H5PL__get_plugin_control_mask + * + * Purpose: Gets the internal plugin control mask value. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5PL__get_plugin_control_mask(unsigned int *mask /*out*/) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Check args - Just assert on package functions */ + HDassert(mask); + + /* Return the mask */ + *mask = H5PL_plugin_control_mask_g; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5PL__get_plugin_control_mask() */ + +/*------------------------------------------------------------------------- + * Function: H5PL__set_plugin_control_mask + * + * Purpose: Sets the internal plugin control mask value. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5PL__set_plugin_control_mask(unsigned int mask) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Only allow setting this if plugins have not been disabled. + * XXX: Note that we don't consider this an error, but instead + * silently ignore it. We may want to consider this behavior + * more carefully. + */ + if (H5PL_allow_plugins_g) + H5PL_plugin_control_mask_g = mask; + + FUNC_LEAVE_NOAPI(ret_value) + +} /* end H5PL__set_plugin_control_mask() */ + +/*------------------------------------------------------------------------- + * Function: H5PL_init + * + * Purpose: Initialize the interface from some other layer. + * + * Return: Success: non-negative + * Failure: negative + *------------------------------------------------------------------------- + */ +herr_t +H5PL_init(void) +{ + char *env_var = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(FAIL) + + /* Check the environment variable to determine if the user wants + * to ignore plugins. The special symbol H5PL_NO_PLUGIN (defined in + * H5PLpublic.h) means we don't want to load plugins. + */ + if (NULL != (env_var = HDgetenv(HDF5_PLUGIN_PRELOAD))) + if (!HDstrcmp(env_var, H5PL_NO_PLUGIN)) { + H5PL_plugin_control_mask_g = 0; + H5PL_allow_plugins_g = FALSE; + } + + /* Create the table of previously-loaded plugins */ + if (H5PL__create_plugin_cache() < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin cache") + + /* Create the table of search paths for dynamic libraries */ + if (H5PL__create_path_table() < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin search path table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- + * Function: H5PL_term_package + * + * Purpose: Terminate the H5PL interface: release all memory, reset all + * global variables to initial values. This only happens if all + * types have been destroyed from other interfaces. + * + * Return: Success: Positive if any action was taken that might + * affect some other interface; zero otherwise + * Failure: Negative + * + *------------------------------------------------------------------------- + */ +int +H5PL_term_package(void) +{ + hbool_t already_closed = FALSE; + int ret_value = 0; + + FUNC_ENTER_NOAPI_NOINIT + + /* Close the plugin cache. + * We need to bump the return value if we did any real work here. + */ + if (H5PL__close_plugin_cache(&already_closed) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing plugin cache") + if (!already_closed) + ret_value++; + + /* Close the search path table and free the paths */ + if (H5PL__close_path_table() < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing search path table") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL_term_package() */ + +/*------------------------------------------------------------------------- + * Function: H5PL_load + * + * Purpose: Given the plugin type and identifier, this function searches + * for and, if found, loads a dynamic plugin library. + * + * The function searches first in the cached plugins and then + * in the paths listed in the path table. + * + * Return: Success: A pointer to the plugin info + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +const void * +H5PL_load(H5PL_type_t type, const H5PL_key_t *key) +{ + H5PL_search_params_t search_params; /* Plugin search parameters */ + hbool_t found = FALSE; /* Whether the plugin was found */ + const void *plugin_info = NULL; /* Information from the plugin */ + const void *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) + + /* Check if plugins can be loaded for this plugin type */ + switch (type) { + case H5PL_TYPE_FILTER: + if ((H5PL_plugin_control_mask_g & H5PL_FILTER_PLUGIN) == 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "filter plugins disabled") + break; + + case H5PL_TYPE_VOL: + if ((H5PL_plugin_control_mask_g & H5PL_VOL_PLUGIN) == 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, + "Virtual Object Layer (VOL) driver plugins disabled") + break; + + case H5PL_TYPE_VFD: + if ((H5PL_plugin_control_mask_g & H5PL_VFD_PLUGIN) == 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Virtual File Driver (VFD) plugins disabled") + break; + + case H5PL_TYPE_ERROR: + case H5PL_TYPE_NONE: + default: + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Invalid plugin type specified") + } + + /* Set up the search parameters */ + search_params.type = type; + search_params.key = key; + + /* Search in the table of already loaded plugin libraries */ + if (H5PL__find_plugin_in_cache(&search_params, &found, &plugin_info) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in plugin cache failed") + + /* If not found, try iterating through the path table to find an appropriate plugin */ + if (!found) + if (H5PL__find_plugin_in_path_table(&search_params, &found, &plugin_info) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in path table failed") + + /* Set the return value we found the plugin */ + if (found) + ret_value = plugin_info; + else + HGOTO_ERROR(H5E_PLUGIN, H5E_NOTFOUND, NULL, "unable to locate plugin") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL_load() */ + +/*------------------------------------------------------------------------- + * Function: H5PL__open + * + * Purpose: Opens a plugin. + * + * `path` specifies the path to the plugin library file. + * + * `type` specifies the type of plugin being searched for and + * will be used to verify that a loaded plugin matches the + * type requested. H5PL_TYPE_NONE may be passed, in which case + * no plugin type verification is performed. This is most + * useful when iterating over available plugins without regard + * to their types. + * + * `key` specifies the information that will be used to find a + * specific plugin. For filter plugins, this is typically an + * integer identifier. For VOL connector and VFD plugins, this + * is typically either an integer identifier or a name string. + * After a plugin has been opened, this information will be + * compared against the relevant information provided by the + * plugin to ensure that the plugin is a match. If + * H5PL_TYPE_NONE is provided for `type`, then `key` should be + * NULL. + * + * On successful open of a plugin, the `success` parameter + * will be set to TRUE and the `plugin_type` and `plugin_info` + * parameters will be filled appropriately. On failure, the + * `success` parameter will be set to FALSE, the `plugin_type` + * parameter will be set to H5PL_TYPE_ERROR and the + * `plugin_info` parameter will be set to NULL. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +/* NOTE: We turn off -Wpedantic in gcc to quiet a warning about converting + * object pointers to function pointers, which is undefined in ANSI C. + * This is basically unavoidable due to the nature of dlsym() and *is* + * defined in POSIX, so it's fine. + * + * This pragma only needs to surround the assignment of the + * get_plugin_info function pointer, but early (4.4.7, at least) gcc + * only allows diagnostic pragmas to be toggled outside of functions. + */ +H5_GCC_CLANG_DIAG_OFF("pedantic") +herr_t +H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, hbool_t *success, + H5PL_type_t *plugin_type, const void **plugin_info) +{ + H5PL_HANDLE handle = NULL; + H5PL_get_plugin_type_t get_plugin_type = NULL; + H5PL_get_plugin_info_t get_plugin_info = NULL; + H5PL_type_t loaded_plugin_type; + H5PL_key_t tmp_key; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + /* Check args - Just assert on package functions */ + HDassert(path); + if (type == H5PL_TYPE_NONE) + HDassert(!key); + HDassert(success); + HDassert(plugin_info); + + /* Initialize out parameters */ + *success = FALSE; + *plugin_info = NULL; + if (plugin_type) + *plugin_type = H5PL_TYPE_ERROR; + + /* There are different reasons why a library can't be open, e.g. wrong architecture. + * If we can't open the library, just return. + */ + if (NULL == (handle = H5PL_OPEN_DLIB(path))) { + H5PL_CLR_ERROR; /* clear error */ + HGOTO_DONE(SUCCEED) + } + + /* Return a handle for the function H5PLget_plugin_type in the dynamic library. + * The plugin library is supposed to define this function. + */ + if (NULL == (get_plugin_type = (H5PL_get_plugin_type_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_type"))) + HGOTO_DONE(SUCCEED) + + /* Return a handle for the function H5PLget_plugin_info in the dynamic library. + * The plugin library is supposed to define this function. + */ + if (NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) + HGOTO_DONE(SUCCEED) + + /* Check the plugin type and return if it doesn't match the one passed in */ + loaded_plugin_type = (H5PL_type_t)(*get_plugin_type)(); + if ((type != H5PL_TYPE_NONE) && (type != loaded_plugin_type)) + HGOTO_DONE(SUCCEED) + + /* Get the plugin information */ + switch (loaded_plugin_type) { + case H5PL_TYPE_FILTER: { + const H5Z_class2_t *filter_info; + + /* Get the plugin info */ + if (NULL == (filter_info = (const H5Z_class2_t *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get filter info from plugin") + + /* Setup temporary plugin key if one wasn't supplied */ + if (!key) { + tmp_key.id = filter_info->id; + key = &tmp_key; + } + + /* If the filter IDs match, we're done. Set the output parameters. */ + if (filter_info->id == key->id) { + if (plugin_type) + *plugin_type = H5PL_TYPE_FILTER; + *plugin_info = (const void *)filter_info; + *success = TRUE; + } + + break; + } + + case H5PL_TYPE_VOL: { + const void *cls; + + /* Get the plugin info */ + if (NULL == (cls = (const void *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VOL connector info from plugin") + + /* Setup temporary plugin key if one wasn't supplied */ + if (!key) { + tmp_key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME; + tmp_key.vol.u.name = ((const H5VL_class_t *)cls)->name; + key = &tmp_key; + } + + /* Ask VOL interface if this class is the one we are looking for and is compatible, etc */ + if (H5VL_check_plugin_load(cls, key, success) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VOL connector compatibility check failed") + + /* Check for finding the correct plugin */ + if (*success) { + if (plugin_type) + *plugin_type = H5PL_TYPE_VOL; + *plugin_info = cls; + } + + break; + } + + case H5PL_TYPE_VFD: { + const void *cls; + + /* Get the plugin info */ + if (NULL == (cls = (const void *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VFD info from plugin") + + /* Setup temporary plugin key if one wasn't supplied */ + if (!key) { + tmp_key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; + tmp_key.vfd.u.name = ((const H5FD_class_t *)cls)->name; + key = &tmp_key; + } + + /* Ask VFD interface if this class is the one we are looking for and is compatible, etc */ + if (H5FD_check_plugin_load(cls, key, success) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VFD compatibility check failed") + + /* Check for finding the correct plugin */ + if (*success) { + if (plugin_type) + *plugin_type = H5PL_TYPE_VFD; + *plugin_info = cls; + } + + break; + } + + case H5PL_TYPE_ERROR: + case H5PL_TYPE_NONE: + default: + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "Invalid plugin type specified") + } /* end switch */ + + /* If we found the correct plugin, store it in the cache */ + if (*success) + if (H5PL__add_plugin(loaded_plugin_type, key, handle)) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to add new plugin to plugin cache") + +done: + if (!(*success) && handle) + if (H5PL__close(handle) < 0) + HDONE_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__open() */ +H5_GCC_CLANG_DIAG_ON("pedantic") + +/*------------------------------------------------------------------------- + * Function: H5PL__close + * + * Purpose: Closes the handle for dynamic library + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5PL__close(H5PL_HANDLE handle) +{ + FUNC_ENTER_PACKAGE_NOERR + + H5PL_CLOSE_LIB(handle); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5PL__close() */ + +/*------------------------------------------------------------------------- + * Function: H5PL_iterate + * + * Purpose: Iterates over all the available plugins and calls the + * specified callback function on each plugin. + * + * Return: H5_ITER_CONT if all plugins are processed successfully + * H5_ITER_STOP if short-circuit success occurs while + * processing plugins + * H5_ITER_ERROR if an error occurs while processing plugins + * + *------------------------------------------------------------------------- + */ +herr_t +H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data) +{ + herr_t ret_value = H5_ITER_CONT; + + FUNC_ENTER_NOAPI_NOERR + + ret_value = H5PL__path_table_iterate(iter_type, iter_op, op_data); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL_iterate() */ |
