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://support.hdfgroup.org/ftp/HDF5/releases. *
9 * If you do not have access to either file, you may request a copy from *
10 * help@hdfgroup.org. *
11 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 #define H5PL_PACKAGE /*suppress error about including H5PLpkg */
13
14 /****************/
15 /* Module Setup */
16 /****************/
17
18 /* Interface initialization */
19 #define H5_INTERFACE_INIT_FUNC H5PL__init_interface
20
21
22 /***********/
23 /* Headers */
24 /***********/
25 #include "H5private.h" /* Generic Functions */
26 #include "H5Eprivate.h" /* Error handling */
27 #include "H5MMprivate.h" /* Memory management */
28 #include "H5PLpkg.h" /* Plugin */
29 #include "H5Zprivate.h" /* Filter pipeline */
30
31
32 /****************/
33 /* Local Macros */
34 /****************/
35 #ifdef H5_HAVE_WIN32_API
36 #define H5PL_EXPAND_ENV_VAR { \
37 long bufCharCount; \
38 char *tempbuf; \
39 if(NULL == (tempbuf = (char *)H5MM_malloc(H5PL_EXPAND_BUFFER_SIZE))) \
40 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for expanded path") \
41 if((bufCharCount = ExpandEnvironmentStringsA(dl_path, tempbuf, H5PL_EXPAND_BUFFER_SIZE)) > H5PL_EXPAND_BUFFER_SIZE) { \
42 tempbuf = (char *)H5MM_xfree(tempbuf); \
43 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "expanded path is too long") \
44 } \
45 if(bufCharCount == 0) { \
46 tempbuf = (char *)H5MM_xfree(tempbuf); \
47 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "failed to expand path") \
48 } \
49 dl_path = (char *)H5MM_xfree(dl_path); \
50 dl_path = tempbuf; \
51 }
52 #else
53 #define H5PL_EXPAND_ENV_VAR
54 #endif /* H5_HAVE_WIN32_API */
55
56 /****************************/
57 /* Macros for supporting
58 * both Windows and Unix */
59 /****************************/
60 /* Windows support
61 *
62 * SPECIAL WINDOWS NOTE
63 *
64 * Some of the Win32 API functions expand to fooA or fooW depending on
65 * whether UNICODE or _UNICODE are defined. You MUST explicitly use
66 * the A version of the functions to force char * behavior until we
67 * work out a scheme for proper Windows Unicode support.
68 *
69 * If you do not do this, people will be unable to incorporate our
70 * source code into their own CMake builds if they define UNICODE.
71 */
72
73 #ifdef H5_HAVE_WIN32_API
74
75 #define H5PL_PATH_SEPARATOR ";"
76
77 /* Handle for dynamic library */
78 #define H5PL_HANDLE HINSTANCE
79
80 /* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
81 #define H5PL_OPEN_DLIB(S) LoadLibraryExA(S, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
82
83 /* Get the address of a symbol in dynamic library */
84 #define H5PL_GET_LIB_FUNC(H,N) GetProcAddress(H,N)
85
86 /* Close dynamic library */
87 #define H5PL_CLOSE_LIB(H) FreeLibrary(H)
88
89 /* Clear error - nothing to do */
90 #define H5PL_CLR_ERROR
91
92 /* maximum size for expanding env vars */
93 #define H5PL_EXPAND_BUFFER_SIZE 32767
94
95 typedef const void *(__cdecl *H5PL_get_plugin_info_t)(void);
96
97 /* Unix support */
98 #else /* H5_HAVE_WIN32_API */
99
100 #define H5PL_PATH_SEPARATOR ":"
101
102 /* Handle for dynamic library */
103 #define H5PL_HANDLE void *
104
105 /* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */
106 #define H5PL_OPEN_DLIB(S) dlopen(S, RTLD_LAZY)
107
108 /* Get the address of a symbol in dynamic library */
109 #define H5PL_GET_LIB_FUNC(H,N) dlsym(H,N)
110
111 /* Close dynamic library */
112 #define H5PL_CLOSE_LIB(H) dlclose(H)
113
114 /* Clear error */
115 #define H5PL_CLR_ERROR HERROR(H5E_PLUGIN, H5E_CANTGET, "can't dlopen:%s", dlerror())
116
117 typedef const void *(*H5PL_get_plugin_info_t)(void);
118 #endif /* H5_HAVE_WIN32_API */
119
120 /* Whether to preload pathnames for plugin libraries */
121 #define H5PL_DEFAULT_PATH H5_DEFAULT_PLUGINDIR
122
123 /* Special symbol to indicate no plugin loading */
124 #define H5PL_NO_PLUGIN "::"
125
126 /******************/
127 /* Local Typedefs */
128 /******************/
129
130 /* Type for the list of info for opened plugin libraries */
131 typedef struct H5PL_table_t {
132 H5PL_type_t pl_type; /* plugin type */
133 int pl_id; /* ID for the plugin */
134 H5PL_HANDLE handle; /* plugin handle */
135 } H5PL_table_t;
136
137
138 /********************/
139 /* Local Prototypes */
140 /********************/
141
142 static herr_t H5PL__init_path_table(void);
143 static htri_t H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info);
144 static htri_t H5PL__open(H5PL_type_t pl_type, char *libname, int plugin_id, const void **pl_info);
145 static htri_t H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info);
146 static herr_t H5PL__close(H5PL_HANDLE handle);
147
148
149 /*********************/
150 /* Package Variables */
151 /*********************/
152
153
154 /*****************************/
155 /* Library Private Variables */
156 /*****************************/
157
158
159 /*******************/
160 /* Local Variables */
161 /*******************/
162
163 /* Table for opened plugin libraries */
164 static size_t H5PL_table_alloc_g = 0;
165 static size_t H5PL_table_used_g = 0;
166 static H5PL_table_t *H5PL_table_g = NULL;
167
168 /* Table of location paths for plugin libraries */
169 static char *H5PL_path_table_g[H5PL_MAX_PATH_NUM];
170 static size_t H5PL_num_paths_g = 0;
171 static hbool_t H5PL_path_found_g = FALSE;
172
173 /* Enable all plugin libraries */
174 static unsigned int H5PL_plugin_g = H5PL_ALL_PLUGIN;
175
176
177 /*--------------------------------------------------------------------------
178 NAME
179 H5PL__init_interface -- Initialize interface-specific information
180 USAGE
181 herr_t H5PL__init_interface()
182 RETURNS
183 Non-negative on success/Negative on failure
184 DESCRIPTION
185 Initializes any interface-specific data or routines.
186
187 --------------------------------------------------------------------------*/
188 static herr_t
H5PL__init_interface(void)189 H5PL__init_interface(void)
190 {
191 char *preload_path;
192
193 FUNC_ENTER_STATIC_NOERR
194
195 /* Retrieve pathnames from HDF5_PLUGIN_PRELOAD if the user sets it
196 * to tell the library to load plugin libraries without search.
197 */
198 if(NULL != (preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD"))) {
199 /* Special symbal "::" means no plugin during data reading. */
200 if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN))
201 H5PL_plugin_g = 0;
202 } /* end if */
203
204 FUNC_LEAVE_NOAPI(SUCCEED)
205 } /* end H5PL__init_interface() */
206
207
208 /*-------------------------------------------------------------------------
209 * Function: H5PLset_loading_state
210 *
211 * Purpose: Control the loading of dynamic plugin types.
212 *
213 * This function will not allow plugin types if the pathname from the HDF5_PLUGIN_PRELOAD
214 * environment variable is set to the special "::" string.
215 *
216 * plugin bit = 0, will prevent the use of that dynamic plugin type.
217 * plugin bit = 1, will allow the use of that dynamic plugin type.
218 *
219 * H5PL_TYPE_FILTER changes just dynamic filters
220 * A H5PL_ALL_PLUGIN will enable all dynamic plugin types
221 * A zero value will disable all dynamic plugin types
222 *
223 * Return: Non-negative or success
224 *
225 *-------------------------------------------------------------------------
226 */
227 herr_t
H5PLset_loading_state(unsigned int plugin_type)228 H5PLset_loading_state(unsigned int plugin_type)
229 {
230 char *preload_path;
231 herr_t ret_value = SUCCEED; /* Return value */
232
233 FUNC_ENTER_API(FAIL)
234 H5TRACE1("e", "Iu", plugin_type);
235
236 /* change the bit value of the requested plugin type(s) */
237 H5PL_plugin_g = plugin_type;
238
239 /* check if special ENV variable is set and disable all plugin types */
240 if(NULL != (preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD"))) {
241 /* Special symbol "::" means no plugin during data reading. */
242 if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN))
243 H5PL_plugin_g = 0;
244 }
245 done:
246 FUNC_LEAVE_API(ret_value)
247 } /* end H5PLset_loading_state() */
248
249
250 /*-------------------------------------------------------------------------
251 * Function: H5PLget_loading_state
252 *
253 * Purpose: Query state of the loading of dynamic plugin types.
254 *
255 * This function will return the state of the global flag.
256 *
257 * Return: Zero if all plugin types are disabled, negative if all
258 * plugin types are enabled, positive if one or more of the plugin types are enabled.
259 *
260 *-------------------------------------------------------------------------
261 */
262 herr_t
H5PLget_loading_state(unsigned int * plugin_type)263 H5PLget_loading_state(unsigned int *plugin_type)
264 {
265 herr_t ret_value = SUCCEED; /* Return value */
266
267 FUNC_ENTER_API(FAIL)
268 H5TRACE1("e", "*Iu", plugin_type);
269
270 if(plugin_type)
271 *plugin_type = H5PL_plugin_g;
272
273 done:
274 FUNC_LEAVE_API(ret_value)
275 } /* end H5PLget_loading_state() */
276
277
278 /*-------------------------------------------------------------------------
279 * Function: H5PL_term_interface
280 *
281 * Purpose: Terminate the H5PL interface: release all memory, reset all
282 * global variables to initial values. This only happens if all
283 * types have been destroyed from other interfaces.
284 *
285 * Return: Success: Positive if any action was taken that might
286 * affect some other interface; zero otherwise.
287 *
288 * Failure: Negative.
289 *
290 * Programmer: Raymond Lu
291 * 20 February 2013
292 *
293 *-------------------------------------------------------------------------
294 */
295 int
H5PL_term_interface(void)296 H5PL_term_interface(void)
297 {
298 int i = 0;
299
300 FUNC_ENTER_NOAPI_NOINIT_NOERR
301
302 if(H5_interface_initialize_g) {
303 size_t u; /* Local index variable */
304
305 /* Close opened dynamic libraries */
306 for(u = 0; u < H5PL_table_used_g; u++)
307 H5PL__close((H5PL_table_g[u]).handle);
308
309 /* Free the table of dynamic libraries */
310 H5PL_table_g = (H5PL_table_t *)H5MM_xfree(H5PL_table_g);
311 H5PL_table_used_g = H5PL_table_alloc_g = 0;
312
313 /* Free the table of search paths */
314 for(u = 0; u < H5PL_num_paths_g; u++)
315 if(H5PL_path_table_g[u])
316 H5PL_path_table_g[u] = (char *)H5MM_xfree(H5PL_path_table_g[u]);
317 H5PL_num_paths_g = 0;
318 H5PL_path_found_g = FALSE;
319
320 H5_interface_initialize_g = 0;
321 i = 1;
322 } /* end if */
323
324 FUNC_LEAVE_NOAPI(i)
325 } /* end H5PL_term_interface() */
326
327
328 /*-------------------------------------------------------------------------
329 * Function: H5PL_load
330 *
331 * Purpose: Given the plugin type and identifier, this function searches
332 * and/or loads a dynamic plugin library first among the already
333 * opened libraries then in the designated location paths.
334 *
335 * Return: Non-NULL on success/NULL on failure
336 *
337 * Programmer: Raymond Lu
338 * 13 February 2013
339 *
340 *-------------------------------------------------------------------------
341 */
342 const void *
H5PL_load(H5PL_type_t type,int id)343 H5PL_load(H5PL_type_t type, int id)
344 {
345 htri_t found; /* Whether the plugin was found */
346 const void *plugin_info = NULL;
347 const void *ret_value = NULL;
348
349 FUNC_ENTER_NOAPI(NULL)
350
351 switch(type) {
352 case H5PL_TYPE_FILTER:
353 if((H5PL_plugin_g & H5PL_FILTER_PLUGIN) == 0)
354 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin filter '%d' is not available", id)
355 break;
356
357 case H5PL_TYPE_ERROR:
358 case H5PL_TYPE_NONE:
359 default:
360 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTLOAD, NULL, "required dynamically loaded plugin '%d' is not valid", id)
361 } /* end switch */
362
363 /* Initialize the location paths for dynamic libraries, if they aren't
364 * already set up.
365 */
366 if(FALSE == H5PL_path_found_g)
367 if(H5PL__init_path_table() < 0)
368 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, NULL, "can't initialize search path table")
369
370 /* Search in the table of already loaded plugin libraries */
371 if((found = H5PL__search_table(type, id, &plugin_info)) < 0)
372 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in table failed")
373
374 /* If not found, iterate through the path table to find the right dynamic library */
375 if(!found) {
376 size_t i; /* Local index variable */
377
378 for(i = 0; i < H5PL_num_paths_g; i++) {
379 if((found = H5PL__find(type, id, H5PL_path_table_g[i], &plugin_info)) < 0)
380 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in paths failed")
381
382 /* Break out if found */
383 if(found) {
384 HDassert(plugin_info);
385 break;
386 } /* end if */
387 } /* end for */
388 } /* end if */
389
390 /* Check if we found the plugin */
391 if(found)
392 ret_value = plugin_info;
393
394 done:
395 FUNC_LEAVE_NOAPI(ret_value)
396 } /* end H5PL_load() */
397
398
399 /*-------------------------------------------------------------------------
400 * Function: H5PLappend
401 *
402 * Purpose: Insert a plugin path at the end of the list.
403 *
404 * Return: Non-negative or success.
405 *
406 *-------------------------------------------------------------------------
407 */
408 herr_t
H5PLappend(const char * plugin_path)409 H5PLappend(const char *plugin_path)
410 {
411 herr_t ret_value = SUCCEED; /* Return value */
412 char *dl_path = NULL;
413
414 FUNC_ENTER_API(FAIL)
415 H5TRACE1("e", "*s", plugin_path);
416 if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
417 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
418 if(NULL == plugin_path)
419 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
420 if(NULL == (dl_path = H5MM_strdup(plugin_path)))
421 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
422
423 H5PL_EXPAND_ENV_VAR
424
425 H5PL_path_table_g[H5PL_num_paths_g] = dl_path;
426 H5PL_num_paths_g++;
427
428 done:
429 FUNC_LEAVE_API(ret_value)
430 } /* end H5PLappend() */
431
432
433 /*-------------------------------------------------------------------------
434 * Function: H5PLprepend
435 *
436 * Purpose: Insert a plugin path at the beginning of the list.
437 *
438 * Return: Non-negative or success.
439 *
440 *-------------------------------------------------------------------------
441 */
442 herr_t
H5PLprepend(const char * plugin_path)443 H5PLprepend(const char *plugin_path)
444 {
445 herr_t ret_value = SUCCEED; /* Return value */
446 char *dl_path = NULL;
447 unsigned int plindex;
448
449 FUNC_ENTER_API(FAIL)
450 H5TRACE1("e", "*s", plugin_path);
451 if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
452 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
453 if(NULL == plugin_path)
454 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
455 if(NULL == (dl_path = H5MM_strdup(plugin_path)))
456 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
457
458 H5PL_EXPAND_ENV_VAR
459
460 for (plindex = (unsigned int)H5PL_num_paths_g; plindex > 0; plindex--)
461 H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex - 1];
462 H5PL_path_table_g[0] = dl_path;
463 H5PL_num_paths_g++;
464
465 done:
466 FUNC_LEAVE_API(ret_value)
467 } /* end H5PLprepend() */
468
469
470 /*-------------------------------------------------------------------------
471 * Function: H5PLreplace
472 *
473 * Purpose: Replace the path at the specified index.
474 *
475 * Return: Non-negative or success.
476 *
477 *-------------------------------------------------------------------------
478 */
479 herr_t
H5PLreplace(const char * plugin_path,unsigned int index)480 H5PLreplace(const char *plugin_path, unsigned int index)
481 {
482 herr_t ret_value = SUCCEED; /* Return value */
483 char *dl_path = NULL;
484
485 FUNC_ENTER_API(FAIL)
486 H5TRACE2("e", "*sIu", plugin_path, index);
487 if(NULL == plugin_path)
488 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
489 if(index >= H5PL_MAX_PATH_NUM)
490 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
491 if(NULL == (dl_path = H5MM_strdup(plugin_path)))
492 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
493
494 H5PL_EXPAND_ENV_VAR
495
496 if(H5PL_path_table_g[index])
497 H5PL_path_table_g[index] = (char *)H5MM_xfree(H5PL_path_table_g[index]);
498 H5PL_path_table_g[index] = dl_path;
499
500 done:
501 FUNC_LEAVE_API(ret_value)
502 } /* end H5PLreplace() */
503
504
505 /*-------------------------------------------------------------------------
506 * Function: H5PLinsert
507 *
508 * Purpose: Insert a plugin path at the specified index, moving other paths after the index.
509 *
510 * Return: Non-negative or success.
511 *
512 *-------------------------------------------------------------------------
513 */
514 herr_t
H5PLinsert(const char * plugin_path,unsigned int index)515 H5PLinsert(const char *plugin_path, unsigned int index)
516 {
517 herr_t ret_value = SUCCEED; /* Return value */
518 char *dl_path = NULL;
519 unsigned int plindex;
520
521 FUNC_ENTER_API(FAIL)
522 H5TRACE2("e", "*sIu", plugin_path, index);
523 if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
524 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
525 if(NULL == plugin_path)
526 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no path provided")
527 if(index >= H5PL_MAX_PATH_NUM)
528 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
529 if(NULL == (dl_path = H5MM_strdup(plugin_path)))
530 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
531
532 H5PL_EXPAND_ENV_VAR
533
534 for(plindex = (unsigned int)H5PL_num_paths_g; plindex > index; plindex--)
535 H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex - 1];
536 H5PL_path_table_g[index] = dl_path;
537 H5PL_num_paths_g++;
538
539 done:
540 FUNC_LEAVE_API(ret_value)
541 } /* end H5PLinsert() */
542
543
544 /*-------------------------------------------------------------------------
545 * Function: H5PLremove
546 *
547 * Purpose: Remove the plugin path at the specifed index and compacting the list.
548 *
549 * Return: Non-negative or success.
550 *
551 *-------------------------------------------------------------------------
552 */
553 herr_t
H5PLremove(unsigned int index)554 H5PLremove(unsigned int index)
555 {
556 herr_t ret_value = SUCCEED; /* Return value */
557 unsigned int plindex;
558
559 FUNC_ENTER_API(FAIL)
560 H5TRACE1("e", "Iu", index);
561 if(H5PL_num_paths_g == 0)
562 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "no directories in table")
563 if(index >= H5PL_MAX_PATH_NUM)
564 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
565 if(NULL == H5PL_path_table_g[index])
566 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no directory path at index")
567 H5PL_path_table_g[index] = (char *)H5MM_xfree(H5PL_path_table_g[index]);
568
569 H5PL_num_paths_g--;
570 for(plindex = index; plindex < (unsigned int)H5PL_num_paths_g; plindex++)
571 H5PL_path_table_g[plindex] = H5PL_path_table_g[plindex + 1];
572 H5PL_path_table_g[H5PL_num_paths_g] = NULL;
573
574 done:
575 FUNC_LEAVE_API(ret_value)
576 } /* end H5PLremove() */
577
578
579 /*-------------------------------------------------------------------------
580 * Function: H5PLget
581 *
582 * Purpose: Query the plugin path at the specified index.
583 *
584 * Return: Success: The length of path.
585 *
586 * If `pathname' is non-NULL then write up to `size' bytes into that
587 * buffer and always return the length of the pathname.
588 * Otherwise `size' is ignored and the function does not store the pathname,
589 * just returning the number of characters required to store the pathname.
590 * If an error occurs then the buffer pointed to by `pathname' (NULL or non-NULL)
591 * is unchanged and the function returns a negative value.
592 * If a zero is returned for the name's length, then there is no pathname
593 * associated with the index.
594 *
595 *-------------------------------------------------------------------------
596 */
597 ssize_t
H5PLget(unsigned int index,char * pathname,size_t size)598 H5PLget(unsigned int index, char *pathname/*out*/, size_t size)
599 {
600 ssize_t ret_value = 0; /* Return value */
601 size_t len = 0; /* Length of pathname */
602 char *dl_path = NULL;
603
604 FUNC_ENTER_API(FAIL)
605 H5TRACE3("Zs", "Iuxz", index, pathname, size);
606 if(H5PL_num_paths_g == 0)
607 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "no directories in table")
608 if(index >= H5PL_MAX_PATH_NUM)
609 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "index path out of bounds for table")
610 if(NULL == (dl_path = H5PL_path_table_g[index]))
611 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "no directory path at index")
612 len = HDstrlen(dl_path);
613 if(pathname) {
614 HDstrncpy(pathname, dl_path, MIN((size_t)(len + 1), size));
615 if((size_t)len >= size)
616 pathname[size - 1] = '\0';
617 } /* end if */
618
619 /* Set return value */
620 ret_value = (ssize_t)len;
621
622 done:
623 FUNC_LEAVE_API(ret_value)
624 } /* end H5PLget() */
625
626
627 /*-------------------------------------------------------------------------
628 * Function: H5PLsize
629 *
630 * Purpose: Query the size of the current list of plugin paths.
631 *
632 * Return: Plugin path size
633 *
634 *-------------------------------------------------------------------------
635 */
636 herr_t
H5PLsize(unsigned int * listsize)637 H5PLsize(unsigned int *listsize)
638 {
639 herr_t ret_value = SUCCEED; /* Return value */
640
641 FUNC_ENTER_API(FAIL)
642 H5TRACE1("e", "*Iu", listsize);
643
644 *listsize = (unsigned int)H5PL_num_paths_g;
645
646 done:
647 FUNC_LEAVE_API(ret_value)
648 } /* end H5PLsize() */
649
650
651 /*-------------------------------------------------------------------------
652 * Function: H5PL__init_path_table
653 *
654 * Purpose: Initialize the path table.
655 *
656 * Return: Non-negative on success/Negative on failure
657 *
658 * Programmer: Quincey Koziol
659 * 18 March 2013
660 *
661 *-------------------------------------------------------------------------
662 */
663 static herr_t
H5PL__init_path_table(void)664 H5PL__init_path_table(void)
665 {
666 char *dl_path = NULL;
667 char *origin_dl_path;
668 char *dir;
669 herr_t ret_value = SUCCEED; /* Return value */
670
671 FUNC_ENTER_STATIC
672
673 /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it
674 * or from the default paths if it isn't set.
675 */
676 origin_dl_path = HDgetenv("HDF5_PLUGIN_PATH");
677 if(NULL == origin_dl_path)
678 dl_path = H5MM_strdup(H5PL_DEFAULT_PATH);
679 else
680 dl_path = H5MM_strdup(origin_dl_path);
681 if(NULL == dl_path)
682 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
683
684 H5PL_EXPAND_ENV_VAR
685
686 /* Put paths in the path table. They are separated by ":" */
687 dir = HDstrtok(dl_path, H5PL_PATH_SEPARATOR);
688 while(dir) {
689 /* Check for too many directories in path */
690 if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM)
691 HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table")
692 if(NULL == (H5PL_path_table_g[H5PL_num_paths_g] = H5MM_strdup(dir)))
693 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
694 H5PL_num_paths_g++;
695 dir = HDstrtok(NULL, H5PL_PATH_SEPARATOR);
696 } /* end while */
697
698 H5PL_path_found_g = TRUE;
699
700 done:
701 if(dl_path)
702 dl_path = (char *)H5MM_xfree(dl_path);
703
704 FUNC_LEAVE_NOAPI(ret_value)
705 } /* end H5PL__init_path_table() */
706
707
708 /*-------------------------------------------------------------------------
709 * Function: H5PL__find
710 *
711 * Purpose: Given a path, this function opens the directory and envokes
712 * another function to go through all files to find the right
713 * plugin library. Two function definitions are for Unix and
714 * Windows.
715 *
716 * Return: TRUE on success,
717 * FALSE on not found,
718 * negative on failure
719 *
720 * Programmer: Raymond Lu
721 * 13 February 2013
722 *
723 *-------------------------------------------------------------------------
724 */
725 #ifndef H5_HAVE_WIN32_API
726 static htri_t
H5PL__find(H5PL_type_t plugin_type,int type_id,char * dir,const void ** info)727 H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info)
728 {
729 char *pathname = NULL;
730 DIR *dirp = NULL;
731 struct dirent *dp;
732 htri_t ret_value = FALSE;
733
734 FUNC_ENTER_STATIC
735
736 /* Open the directory */
737 if(!(dirp = HDopendir(dir)))
738 HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory: %s", dir)
739
740 /* Iterates through all entries in the directory to find the right plugin library */
741 while(NULL != (dp = HDreaddir(dirp))) {
742 /* The library we are looking for should be called libxxx.so... on Unix
743 * or libxxx.xxx.dylib on Mac.
744 */
745 #ifndef __CYGWIN__
746 if(!HDstrncmp(dp->d_name, "lib", (size_t)3) &&
747 (HDstrstr(dp->d_name, ".so") || HDstrstr(dp->d_name, ".dylib"))) {
748 #else
749 if(!HDstrncmp(dp->d_name, "cyg", (size_t)3) &&
750 HDstrstr(dp->d_name, ".dll") ) {
751
752 #endif
753 h5_stat_t my_stat;
754 size_t pathname_len;
755 htri_t found_in_dir;
756
757 /* Allocate & initialize the path name */
758 pathname_len = HDstrlen(dir) + HDstrlen(dp->d_name) + 2;
759 if(NULL == (pathname = (char *)H5MM_malloc(pathname_len)))
760 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
761 HDsnprintf(pathname, pathname_len, "%s/%s", dir, dp->d_name);
762
763 /* Get info for directory entry */
764 if(HDstat(pathname, &my_stat) == -1)
765 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file: %s", HDstrerror(errno))
766
767 /* If it is a directory, skip it */
768 if(S_ISDIR(my_stat.st_mode))
769 continue;
770
771 /* Attempt to open the dynamic library as a filter library */
772 if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
773 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
774 if(found_in_dir)
775 HGOTO_DONE(TRUE) /* Indicate success */
776 pathname = (char *)H5MM_xfree(pathname);
777 } /* end if */
778 } /* end while */
779
780 done:
781 if(dirp)
782 if(HDclosedir(dirp) < 0)
783 HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", HDstrerror(errno))
784 pathname = (char *)H5MM_xfree(pathname);
785
786 FUNC_LEAVE_NOAPI(ret_value)
787 } /* end H5PL__find() */
788 #else /* H5_HAVE_WIN32_API */
789 static htri_t
790 H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info)
791 {
792 WIN32_FIND_DATAA fdFile;
793 HANDLE hFind;
794 char *pathname = NULL;
795 char service[2048];
796 htri_t ret_value = FALSE;
797
798 FUNC_ENTER_STATIC
799
800 /* Specify a file mask. *.* = We want everything! */
801 sprintf(service, "%s\\*.dll", dir);
802 if((hFind = FindFirstFileA(service, &fdFile)) == INVALID_HANDLE_VALUE)
803 HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory")
804
805 do {
806 /* Find first file will always return "."
807 * and ".." as the first two directories.
808 */
809 if(HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) {
810 size_t pathname_len;
811 htri_t found_in_dir;
812
813 /* Allocate & initialize the path name */
814 pathname_len = HDstrlen(dir) + HDstrlen(fdFile.cFileName) + 2;
815 if(NULL == (pathname = (char *)H5MM_malloc(pathname_len)))
816 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path")
817 HDsnprintf(pathname, pathname_len, "%s\\%s", dir, fdFile.cFileName);
818
819 /* Is the entity a File or Folder? */
820 if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
821 continue;
822
823 if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0)
824 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed")
825 if(found_in_dir)
826 HGOTO_DONE(TRUE) /* Indicate success */
827 pathname = (char *)H5MM_xfree(pathname);
828 } /* end if */
829 } while(FindNextFileA(hFind, &fdFile)); /* Find the next file. */
830
831 done:
832 if(hFind)
833 FindClose(hFind);
834 if(pathname)
835 pathname = (char *)H5MM_xfree(pathname);
836
837 FUNC_LEAVE_NOAPI(ret_value)
838 } /* end H5PL__find() */
839 #endif /* H5_HAVE_WIN32_API */
840
841
842 /*-------------------------------------------------------------------------
843 * Function: H5PL__open
844 *
845 * Purpose: Iterates through all files to find the right plugin library.
846 * It loads the dynamic plugin library and keeps it on the list
847 * of loaded libraries.
848 *
849 * Return: TRUE on success,
850 * FALSE on not found,
851 * negative on failure
852 *
853 * Programmer: Raymond Lu
854 * 13 February 2013
855 *
856 *-------------------------------------------------------------------------
857 */
858 static htri_t
859 H5PL__open(H5PL_type_t pl_type, char *libname, int pl_id, const void **pl_info)
860 {
861 H5PL_HANDLE handle = NULL;
862 htri_t ret_value = FALSE;
863
864 FUNC_ENTER_STATIC
865
866 /* There are different reasons why a library can't be open, e.g. wrong architecture.
867 * simply continue if we can't open it.
868 */
869 if(NULL == (handle = H5PL_OPEN_DLIB(libname))) {
870 H5PL_CLR_ERROR; /* clear error */
871 } /* end if */
872 else {
873 H5PL_get_plugin_info_t get_plugin_info = NULL;
874
875 /* Return a handle for the function H5PLget_plugin_info in the dynamic library.
876 * The plugin library is suppose to define this function.
877 */
878 if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) {
879 if(H5PL__close(handle) < 0)
880 HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
881 } /* end if */
882 else {
883 const H5Z_class2_t *plugin_info;
884
885 /* Invoke H5PLget_plugin_info to verify this is the right library we are looking for.
886 * Move on if it isn't.
887 */
888 if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)())) {
889 if(H5PL__close(handle) < 0)
890 HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
891 HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info")
892 } /* end if */
893
894 /* Successfully found plugin library, check if it's the right one */
895 if(plugin_info->id == pl_id) {
896 /* Expand the table if it is too small */
897 if(H5PL_table_used_g >= H5PL_table_alloc_g) {
898 size_t n = MAX(H5Z_MAX_NFILTERS, 2 * H5PL_table_alloc_g);
899 H5PL_table_t *table = (H5PL_table_t *)H5MM_realloc(H5PL_table_g, n * sizeof(H5PL_table_t));
900
901 if(!table)
902 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to extend dynamic library table")
903
904 H5PL_table_g = table;
905 H5PL_table_alloc_g = n;
906 } /* end if */
907
908 (H5PL_table_g[H5PL_table_used_g]).handle = handle;
909 (H5PL_table_g[H5PL_table_used_g]).pl_type = pl_type;
910 (H5PL_table_g[H5PL_table_used_g]).pl_id = plugin_info->id;
911 H5PL_table_used_g++;
912
913 /* Set the plugin info to return */
914 *pl_info = (const void *)plugin_info;
915
916 /* Indicate success */
917 ret_value = TRUE;
918 } /* end if */
919 else
920 if(H5PL__close(handle) < 0)
921 HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library")
922 } /* end if */
923 } /* end else */
924
925 done:
926 FUNC_LEAVE_NOAPI(ret_value)
927 } /* end H5PL__open() */
928
929
930 /*-------------------------------------------------------------------------
931 * Function: H5PL__search_table
932 *
933 * Purpose: Search in the list of already opened dynamic libraries
934 * to see if the one we are looking for is already opened.
935 *
936 * Return: TRUE on success,
937 * FALSE on not found,
938 * Negative on failure
939 *
940 * Programmer: Raymond Lu
941 * 13 February 2013
942 *
943 *-------------------------------------------------------------------------
944 */
945 static htri_t
946 H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info)
947 {
948 htri_t ret_value = FALSE;
949
950 FUNC_ENTER_STATIC
951
952 /* Search in the table of already opened dynamic libraries */
953 if(H5PL_table_used_g > 0) {
954 size_t i;
955
956 for(i = 0; i < H5PL_table_used_g; i++) {
957 if((plugin_type == (H5PL_table_g[i]).pl_type) && (type_id == (H5PL_table_g[i]).pl_id)) {
958 H5PL_get_plugin_info_t get_plugin_info;
959 const H5Z_class2_t *plugin_info;
960
961 if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC((H5PL_table_g[i]).handle, "H5PLget_plugin_info")))
962 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info")
963
964 if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)()))
965 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info")
966
967 *info = plugin_info;
968 HGOTO_DONE(TRUE)
969 } /* end if */
970 } /* end for */
971 } /* end if */
972
973 done:
974 FUNC_LEAVE_NOAPI(ret_value)
975 } /* end H5PL__search_table() */
976
977
978 /*-------------------------------------------------------------------------
979 * Function: H5PL__close
980 *
981 * Purpose: Closes the handle for dynamic library
982 *
983 * Return: Non-negative on success/Negative on failure
984 *
985 * Programmer: Raymond Lu
986 * 13 February 2013
987 *
988 *-------------------------------------------------------------------------
989 */
990 static herr_t
991 H5PL__close(H5PL_HANDLE handle)
992 {
993 FUNC_ENTER_STATIC_NOERR
994
995 H5PL_CLOSE_LIB(handle);
996
997 FUNC_LEAVE_NOAPI(SUCCEED)
998 } /* end H5PL__close() */
999