Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /* |
14 | | * Purpose: Internal routines for managing plugins. |
15 | | * |
16 | | */ |
17 | | |
18 | | /****************/ |
19 | | /* Module Setup */ |
20 | | /****************/ |
21 | | |
22 | | #include "H5PLmodule.h" /* This source code file is part of the H5PL module */ |
23 | | |
24 | | /***********/ |
25 | | /* Headers */ |
26 | | /***********/ |
27 | | #include "H5private.h" /* Generic Functions */ |
28 | | #include "H5Eprivate.h" /* Error handling */ |
29 | | #include "H5PLpkg.h" /* Plugin */ |
30 | | #include "H5Zprivate.h" /* Filter pipeline */ |
31 | | |
32 | | /****************/ |
33 | | /* Local Macros */ |
34 | | /****************/ |
35 | | |
36 | | /******************/ |
37 | | /* Local Typedefs */ |
38 | | /******************/ |
39 | | |
40 | | /********************/ |
41 | | /* Local Prototypes */ |
42 | | /********************/ |
43 | | |
44 | | /*********************/ |
45 | | /* Package Variables */ |
46 | | /*********************/ |
47 | | |
48 | | /* Package initialization variable */ |
49 | | bool H5_PKG_INIT_VAR = false; |
50 | | |
51 | | /*****************************/ |
52 | | /* Library Private Variables */ |
53 | | /*****************************/ |
54 | | |
55 | | /*******************/ |
56 | | /* Local Variables */ |
57 | | /*******************/ |
58 | | |
59 | | /* Bitmask that controls whether classes of plugins |
60 | | * (e.g.: filters, VOL drivers) can be loaded. |
61 | | */ |
62 | | static unsigned int H5PL_plugin_control_mask_g = H5PL_ALL_PLUGIN; |
63 | | |
64 | | /* This flag will be set to false if the HDF5_PLUGIN_PRELOAD |
65 | | * environment variable was set to H5PL_NO_PLUGIN at |
66 | | * package initialization. |
67 | | */ |
68 | | static bool H5PL_allow_plugins_g = true; |
69 | | |
70 | | /*------------------------------------------------------------------------- |
71 | | * Function: H5PL__get_plugin_control_mask |
72 | | * |
73 | | * Purpose: Gets the internal plugin control mask value. |
74 | | * |
75 | | * Return: SUCCEED/FAIL |
76 | | * |
77 | | *------------------------------------------------------------------------- |
78 | | */ |
79 | | herr_t |
80 | | H5PL__get_plugin_control_mask(unsigned int *mask /*out*/) |
81 | 0 | { |
82 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
83 | |
|
84 | 0 | FUNC_ENTER_PACKAGE_NOERR |
85 | | |
86 | | /* Check args - Just assert on package functions */ |
87 | 0 | assert(mask); |
88 | | |
89 | | /* Return the mask */ |
90 | 0 | *mask = H5PL_plugin_control_mask_g; |
91 | |
|
92 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
93 | |
|
94 | 0 | } /* end H5PL__get_plugin_control_mask() */ |
95 | | |
96 | | /*------------------------------------------------------------------------- |
97 | | * Function: H5PL__set_plugin_control_mask |
98 | | * |
99 | | * Purpose: Sets the internal plugin control mask value. |
100 | | * |
101 | | * Return: SUCCEED/FAIL |
102 | | * |
103 | | *------------------------------------------------------------------------- |
104 | | */ |
105 | | herr_t |
106 | | H5PL__set_plugin_control_mask(unsigned int mask) |
107 | 0 | { |
108 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
109 | |
|
110 | 0 | FUNC_ENTER_PACKAGE_NOERR |
111 | | |
112 | | /* Only allow setting this if plugins have not been disabled. |
113 | | * XXX: Note that we don't consider this an error, but instead |
114 | | * silently ignore it. We may want to consider this behavior |
115 | | * more carefully. |
116 | | */ |
117 | 0 | if (H5PL_allow_plugins_g) |
118 | 0 | H5PL_plugin_control_mask_g = mask; |
119 | |
|
120 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
121 | |
|
122 | 0 | } /* end H5PL__set_plugin_control_mask() */ |
123 | | |
124 | | /*------------------------------------------------------------------------- |
125 | | * Function: H5PL__init_package |
126 | | * |
127 | | * Purpose: Initialize any package-specific data and call any init |
128 | | * routines for the package. |
129 | | * |
130 | | * Return: Success: non-negative |
131 | | * Failure: negative |
132 | | *------------------------------------------------------------------------- |
133 | | */ |
134 | | herr_t |
135 | | H5PL__init_package(void) |
136 | 1 | { |
137 | 1 | char *env_var = NULL; |
138 | 1 | herr_t ret_value = SUCCEED; |
139 | | |
140 | 1 | FUNC_ENTER_PACKAGE |
141 | | |
142 | | /* Check the environment variable to determine if the user wants |
143 | | * to ignore plugins. The special symbol H5PL_NO_PLUGIN (defined in |
144 | | * H5PLpublic.h) means we don't want to load plugins. |
145 | | */ |
146 | 1 | if (NULL != (env_var = getenv(HDF5_PLUGIN_PRELOAD))) |
147 | 0 | if (!strcmp(env_var, H5PL_NO_PLUGIN)) { |
148 | 0 | H5PL_plugin_control_mask_g = 0; |
149 | 0 | H5PL_allow_plugins_g = false; |
150 | 0 | } |
151 | | |
152 | | /* Create the table of previously-loaded plugins */ |
153 | 1 | if (H5PL__create_plugin_cache() < 0) |
154 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin cache"); |
155 | | |
156 | | /* Create the table of search paths for dynamic libraries */ |
157 | 1 | if (H5PL__create_path_table() < 0) |
158 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, FAIL, "can't create plugin search path table"); |
159 | | |
160 | 1 | done: |
161 | 1 | FUNC_LEAVE_NOAPI(ret_value) |
162 | 1 | } /* end H5PL__init_package() */ |
163 | | |
164 | | /*------------------------------------------------------------------------- |
165 | | * Function: H5PL_term_package |
166 | | * |
167 | | * Purpose: Terminate the H5PL interface: release all memory, reset all |
168 | | * global variables to initial values. This only happens if all |
169 | | * types have been destroyed from other interfaces. |
170 | | * |
171 | | * Return: Success: Positive if any action was taken that might |
172 | | * affect some other interface; zero otherwise |
173 | | * Failure: Negative |
174 | | * |
175 | | *------------------------------------------------------------------------- |
176 | | */ |
177 | | int |
178 | | H5PL_term_package(void) |
179 | 4 | { |
180 | 4 | bool already_closed = false; |
181 | 4 | int ret_value = 0; |
182 | | |
183 | 4 | FUNC_ENTER_NOAPI_NOINIT |
184 | | |
185 | 2 | if (H5_PKG_INIT_VAR) { |
186 | | /* Close the plugin cache. |
187 | | * We need to bump the return value if we did any real work here. |
188 | | */ |
189 | 2 | if (H5PL__close_plugin_cache(&already_closed) < 0) |
190 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing plugin cache"); |
191 | 2 | if (!already_closed) |
192 | 1 | ret_value++; |
193 | | |
194 | | /* Close the search path table and free the paths */ |
195 | 2 | if (H5PL__close_path_table() < 0) |
196 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTFREE, (-1), "problem closing search path table"); |
197 | | |
198 | | /* Mark the interface as uninitialized */ |
199 | 2 | if (0 == ret_value) |
200 | 1 | H5_PKG_INIT_VAR = false; |
201 | 2 | } /* end if */ |
202 | | |
203 | 2 | done: |
204 | 4 | FUNC_LEAVE_NOAPI(ret_value) |
205 | 4 | } /* end H5PL_term_package() */ |
206 | | |
207 | | /*------------------------------------------------------------------------- |
208 | | * Function: H5PL_load |
209 | | * |
210 | | * Purpose: Given the plugin type and identifier, this function searches |
211 | | * for and, if found, loads a dynamic plugin library. |
212 | | * |
213 | | * The function searches first in the cached plugins and then |
214 | | * in the paths listed in the path table. |
215 | | * |
216 | | * Return: Success: A pointer to the plugin info |
217 | | * Failure: NULL |
218 | | * |
219 | | *------------------------------------------------------------------------- |
220 | | */ |
221 | | const void * |
222 | | H5PL_load(H5PL_type_t type, const H5PL_key_t *key) |
223 | 0 | { |
224 | 0 | H5PL_search_params_t search_params; /* Plugin search parameters */ |
225 | 0 | bool found = false; /* Whether the plugin was found */ |
226 | 0 | const void *plugin_info = NULL; /* Information from the plugin */ |
227 | 0 | const void *ret_value = NULL; |
228 | |
|
229 | 0 | FUNC_ENTER_NOAPI(NULL) |
230 | | |
231 | | /* Check if plugins can be loaded for this plugin type */ |
232 | 0 | switch (type) { |
233 | 0 | case H5PL_TYPE_FILTER: |
234 | 0 | if ((H5PL_plugin_control_mask_g & H5PL_FILTER_PLUGIN) == 0) |
235 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "filter plugins disabled"); |
236 | 0 | break; |
237 | | |
238 | 0 | case H5PL_TYPE_VOL: |
239 | 0 | if ((H5PL_plugin_control_mask_g & H5PL_VOL_PLUGIN) == 0) |
240 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, |
241 | 0 | "Virtual Object Layer (VOL) driver plugins disabled"); |
242 | 0 | break; |
243 | | |
244 | 0 | case H5PL_TYPE_VFD: |
245 | 0 | if ((H5PL_plugin_control_mask_g & H5PL_VFD_PLUGIN) == 0) |
246 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Virtual File Driver (VFD) plugins disabled"); |
247 | 0 | break; |
248 | | |
249 | 0 | case H5PL_TYPE_ERROR: |
250 | 0 | case H5PL_TYPE_NONE: |
251 | 0 | default: |
252 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "Invalid plugin type specified"); |
253 | 0 | } |
254 | | |
255 | | /* Set up the search parameters */ |
256 | 0 | search_params.type = type; |
257 | 0 | search_params.key = key; |
258 | | |
259 | | /* Search in the table of already loaded plugin libraries */ |
260 | 0 | if (H5PL__find_plugin_in_cache(&search_params, &found, &plugin_info) < 0) |
261 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in plugin cache failed"); |
262 | | |
263 | | /* If not found, try iterating through the path table to find an appropriate plugin */ |
264 | 0 | if (!found) |
265 | 0 | if (H5PL__find_plugin_in_path_table(&search_params, &found, &plugin_info) < 0) |
266 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, |
267 | 0 | "can't find plugin in the paths either set by HDF5_PLUGIN_PATH, or default location, " |
268 | 0 | "or set by H5PLxxx functions"); |
269 | | |
270 | | /* Set the return value we found the plugin */ |
271 | 0 | if (found) |
272 | 0 | ret_value = plugin_info; |
273 | 0 | else |
274 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_NOTFOUND, NULL, |
275 | 0 | "can't find plugin. Check either HDF5_VOL_CONNECTOR, HDF5_PLUGIN_PATH, default location, " |
276 | 0 | "or path set by H5PLxxx functions"); |
277 | | |
278 | 0 | done: |
279 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
280 | 0 | } /* end H5PL_load() */ |
281 | | |
282 | | /*------------------------------------------------------------------------- |
283 | | * Function: H5PL__open |
284 | | * |
285 | | * Purpose: Opens a plugin. |
286 | | * |
287 | | * `path` specifies the path to the plugin library file. |
288 | | * |
289 | | * `type` specifies the type of plugin being searched for and |
290 | | * will be used to verify that a loaded plugin matches the |
291 | | * type requested. H5PL_TYPE_NONE may be passed, in which case |
292 | | * no plugin type verification is performed. This is most |
293 | | * useful when iterating over available plugins without regard |
294 | | * to their types. |
295 | | * |
296 | | * `key` specifies the information that will be used to find a |
297 | | * specific plugin. For filter plugins, this is typically an |
298 | | * integer identifier. For VOL connector and VFD plugins, this |
299 | | * is typically either an integer identifier or a name string. |
300 | | * After a plugin has been opened, this information will be |
301 | | * compared against the relevant information provided by the |
302 | | * plugin to ensure that the plugin is a match. If |
303 | | * H5PL_TYPE_NONE is provided for `type`, then `key` should be |
304 | | * NULL. |
305 | | * |
306 | | * On successful open of a plugin, the `success` parameter |
307 | | * will be set to true and the `plugin_type` and `plugin_info` |
308 | | * parameters will be filled appropriately. On failure, the |
309 | | * `success` parameter will be set to false, the `plugin_type` |
310 | | * parameter will be set to H5PL_TYPE_ERROR and the |
311 | | * `plugin_info` parameter will be set to NULL. |
312 | | * |
313 | | * Return: SUCCEED/FAIL |
314 | | * |
315 | | *------------------------------------------------------------------------- |
316 | | */ |
317 | | herr_t |
318 | | H5PL__open(const char *path, H5PL_type_t type, const H5PL_key_t *key, bool *success, H5PL_type_t *plugin_type, |
319 | | const void **plugin_info) |
320 | 0 | { |
321 | 0 | H5PL_HANDLE handle = NULL; |
322 | 0 | H5PL_get_plugin_info_t get_plugin_info = NULL; |
323 | 0 | H5PL_get_plugin_type_t get_plugin_type = NULL; |
324 | 0 | H5PL_type_t loaded_plugin_type; |
325 | 0 | H5PL_key_t tmp_key; |
326 | 0 | herr_t ret_value = SUCCEED; |
327 | |
|
328 | 0 | FUNC_ENTER_PACKAGE |
329 | | |
330 | | /* Check args - Just assert on package functions */ |
331 | 0 | assert(path); |
332 | 0 | if (type == H5PL_TYPE_NONE) |
333 | 0 | assert(!key); |
334 | 0 | assert(success); |
335 | 0 | assert(plugin_info); |
336 | | |
337 | | /* Initialize out parameters */ |
338 | 0 | *success = false; |
339 | 0 | *plugin_info = NULL; |
340 | 0 | if (plugin_type) |
341 | 0 | *plugin_type = H5PL_TYPE_ERROR; |
342 | | |
343 | | /* There are different reasons why a library can't be open, e.g. wrong architecture. |
344 | | * If we can't open the library, just return. |
345 | | */ |
346 | 0 | if (NULL == (handle = H5PL_OPEN_DLIB(path))) { |
347 | 0 | H5PL_CLR_ERROR; /* clear error */ |
348 | 0 | HGOTO_DONE(SUCCEED); |
349 | 0 | } |
350 | | |
351 | | /* NOTE: We turn off -Wpedantic to quiet a warning about converting object |
352 | | * pointers to function pointers, which is undefined in ANSI C. This |
353 | | * is basically unavoidable due to the nature of dlsym() and *is* |
354 | | * defined in POSIX, so it's fine. |
355 | | */ |
356 | | |
357 | | /* Return a handle for the function H5PLget_plugin_type in the dynamic library. |
358 | | * The plugin library is supposed to define this function. |
359 | | */ |
360 | 0 | H5_WARN_OBJ_FXN_POINTER_CONVERSION_OFF |
361 | 0 | if (NULL == (get_plugin_type = (H5PL_get_plugin_type_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_type"))) |
362 | 0 | HGOTO_DONE(SUCCEED); |
363 | 0 | H5_WARN_OBJ_FXN_POINTER_CONVERSION_ON |
364 | | |
365 | | /* Return a handle for the function H5PLget_plugin_info in the dynamic library. |
366 | | * The plugin library is supposed to define this function. |
367 | | */ |
368 | 0 | H5_WARN_OBJ_FXN_POINTER_CONVERSION_OFF |
369 | 0 | if (NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) |
370 | 0 | HGOTO_DONE(SUCCEED); |
371 | 0 | H5_WARN_OBJ_FXN_POINTER_CONVERSION_ON |
372 | | |
373 | | /* Check the plugin type and return if it doesn't match the one passed in */ |
374 | 0 | loaded_plugin_type = (H5PL_type_t)(*get_plugin_type)(); |
375 | 0 | if ((type != H5PL_TYPE_NONE) && (type != loaded_plugin_type)) |
376 | 0 | HGOTO_DONE(SUCCEED); |
377 | | |
378 | | /* Get the plugin information */ |
379 | 0 | switch (loaded_plugin_type) { |
380 | 0 | case H5PL_TYPE_FILTER: { |
381 | 0 | const H5Z_class2_t *filter_info; |
382 | | |
383 | | /* Get the plugin info */ |
384 | 0 | if (NULL == (filter_info = (const H5Z_class2_t *)(*get_plugin_info)())) |
385 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get filter info from plugin"); |
386 | | |
387 | | /* Setup temporary plugin key if one wasn't supplied */ |
388 | 0 | if (!key) { |
389 | 0 | tmp_key.id = filter_info->id; |
390 | 0 | key = &tmp_key; |
391 | 0 | } |
392 | | |
393 | | /* If the filter IDs match, we're done. Set the output parameters. */ |
394 | 0 | if (filter_info->id == key->id) { |
395 | 0 | if (plugin_type) |
396 | 0 | *plugin_type = H5PL_TYPE_FILTER; |
397 | 0 | *plugin_info = (const void *)filter_info; |
398 | 0 | *success = true; |
399 | 0 | } |
400 | |
|
401 | 0 | break; |
402 | 0 | } |
403 | | |
404 | 0 | case H5PL_TYPE_VOL: { |
405 | 0 | const void *cls; |
406 | | |
407 | | /* Get the plugin info */ |
408 | 0 | if (NULL == (cls = (const void *)(*get_plugin_info)())) |
409 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VOL connector info from plugin"); |
410 | | |
411 | | /* Setup temporary plugin key if one wasn't supplied */ |
412 | 0 | if (!key) { |
413 | 0 | tmp_key.vol.kind = H5VL_GET_CONNECTOR_BY_NAME; |
414 | 0 | tmp_key.vol.u.name = ((const H5VL_class_t *)cls)->name; |
415 | 0 | key = &tmp_key; |
416 | 0 | } |
417 | | |
418 | | /* Ask VOL interface if this class is the one we are looking for and is compatible, etc */ |
419 | 0 | if (H5VL_check_plugin_load(cls, key, success) < 0) |
420 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VOL connector compatibility check failed"); |
421 | | |
422 | | /* Check for finding the correct plugin */ |
423 | 0 | if (*success) { |
424 | 0 | if (plugin_type) |
425 | 0 | *plugin_type = H5PL_TYPE_VOL; |
426 | 0 | *plugin_info = cls; |
427 | 0 | } |
428 | |
|
429 | 0 | break; |
430 | 0 | } |
431 | | |
432 | 0 | case H5PL_TYPE_VFD: { |
433 | 0 | const void *cls; |
434 | | |
435 | | /* Get the plugin info */ |
436 | 0 | if (NULL == (cls = (const void *)(*get_plugin_info)())) |
437 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get VFD info from plugin"); |
438 | | |
439 | | /* Setup temporary plugin key if one wasn't supplied */ |
440 | 0 | if (!key) { |
441 | 0 | tmp_key.vfd.kind = H5FD_GET_DRIVER_BY_NAME; |
442 | 0 | tmp_key.vfd.u.name = ((const H5FD_class_t *)cls)->name; |
443 | 0 | key = &tmp_key; |
444 | 0 | } |
445 | | |
446 | | /* Ask VFD interface if this class is the one we are looking for and is compatible, etc */ |
447 | 0 | if (H5FD_check_plugin_load(cls, key, success) < 0) |
448 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, FAIL, "VFD compatibility check failed"); |
449 | | |
450 | | /* Check for finding the correct plugin */ |
451 | 0 | if (*success) { |
452 | 0 | if (plugin_type) |
453 | 0 | *plugin_type = H5PL_TYPE_VFD; |
454 | 0 | *plugin_info = cls; |
455 | 0 | } |
456 | |
|
457 | 0 | break; |
458 | 0 | } |
459 | | |
460 | 0 | case H5PL_TYPE_ERROR: |
461 | 0 | case H5PL_TYPE_NONE: |
462 | 0 | default: |
463 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "Invalid plugin type specified"); |
464 | 0 | } /* end switch */ |
465 | | |
466 | | /* If we found the correct plugin, store it in the cache */ |
467 | 0 | if (*success) |
468 | 0 | if (H5PL__add_plugin(loaded_plugin_type, key, handle)) |
469 | 0 | HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINSERT, FAIL, "unable to add new plugin to plugin cache"); |
470 | | |
471 | 0 | done: |
472 | 0 | if (!(*success) && handle) |
473 | 0 | if (H5PL__close(handle) < 0) |
474 | 0 | HDONE_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library"); |
475 | |
|
476 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
477 | 0 | } /* end H5PL__open() */ |
478 | | |
479 | | /*------------------------------------------------------------------------- |
480 | | * Function: H5PL__close |
481 | | * |
482 | | * Purpose: Closes the handle for dynamic library |
483 | | * |
484 | | * Return: SUCCEED/FAIL |
485 | | * |
486 | | *------------------------------------------------------------------------- |
487 | | */ |
488 | | herr_t |
489 | | H5PL__close(H5PL_HANDLE handle) |
490 | 0 | { |
491 | 0 | FUNC_ENTER_PACKAGE_NOERR |
492 | |
|
493 | 0 | H5PL_CLOSE_LIB(handle); |
494 | |
|
495 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
496 | 0 | } /* end H5PL__close() */ |
497 | | |
498 | | /*------------------------------------------------------------------------- |
499 | | * Function: H5PL_iterate |
500 | | * |
501 | | * Purpose: Iterates over all the available plugins and calls the |
502 | | * specified callback function on each plugin. |
503 | | * |
504 | | * Return: H5_ITER_CONT if all plugins are processed successfully |
505 | | * H5_ITER_STOP if short-circuit success occurs while |
506 | | * processing plugins |
507 | | * H5_ITER_ERROR if an error occurs while processing plugins |
508 | | * |
509 | | *------------------------------------------------------------------------- |
510 | | */ |
511 | | herr_t |
512 | | H5PL_iterate(H5PL_iterate_type_t iter_type, H5PL_iterate_t iter_op, void *op_data) |
513 | 4 | { |
514 | 4 | herr_t ret_value = H5_ITER_CONT; |
515 | | |
516 | 4 | FUNC_ENTER_NOAPI(H5_ITER_ERROR) |
517 | | |
518 | 4 | ret_value = H5PL__path_table_iterate(iter_type, iter_op, op_data); |
519 | | |
520 | 4 | done: |
521 | 4 | FUNC_LEAVE_NOAPI(ret_value) |
522 | 4 | } /* end H5PL_iterate() */ |