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