1 /*-------------------------------------------------------------------------
4 * Dynamic function manager code.
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
13 *-------------------------------------------------------------------------
19 #ifndef WIN32_ONLY_COMPILER
20 #include "dynloader.h"
22 #include "port/dynloader/win32.h"
24 #include "lib/stringinfo.h"
25 #include "miscadmin.h"
26 #include "utils/dynamic_loader.h"
27 #include "utils/hsearch.h"
30 /* signatures for PostgreSQL-specific library init/fini functions */
31 typedef void (*PG_init_t
) (void);
32 typedef void (*PG_fini_t
) (void);
34 /* hashtable entry for rendezvous variables */
37 char varName
[NAMEDATALEN
]; /* hash key (must be first) */
39 } rendezvousHashEntry
;
42 * List of dynamically loaded files (kept in malloc'd memory).
45 typedef struct df_files
47 struct df_files
*next
; /* List link */
48 dev_t device
; /* Device file is on */
49 #ifndef WIN32 /* ensures we never again depend on this under
51 ino_t inode
; /* Inode number of file */
53 void *handle
; /* a handle for pg_dl* functions */
54 char filename
[1]; /* Full pathname of file */
57 * we allocate the block big enough for actual length of pathname.
58 * filename[] must be last item in struct!
62 static DynamicFileList
*file_list
= NULL
;
63 static DynamicFileList
*file_tail
= NULL
;
65 /* stat() call under Win32 returns an st_ino field, but it has no meaning */
67 #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
69 #define SAME_INODE(A,B) false
72 char *Dynamic_library_path
;
74 static void *internal_load_library(const char *libname
);
75 static void incompatible_module_error(const char *libname
,
76 const Pg_magic_struct
*module_magic_data
);
77 static void internal_unload_library(const char *libname
);
78 static bool file_exists(const char *name
);
79 static char *expand_dynamic_library_name(const char *name
);
80 static void check_restricted_library_name(const char *name
);
81 static char *substitute_libpath_macro(const char *name
);
82 static char *find_in_dynamic_libpath(const char *basename
);
84 /* Magic structure that module needs to match to be accepted */
85 static const Pg_magic_struct magic_data
= PG_MODULE_MAGIC_DATA
;
89 * Load the specified dynamic-link library file, and look for a function
90 * named funcname in it.
92 * If the function is not found, we raise an error if signalNotFound is true,
93 * else return (PGFunction) NULL. Note that errors in loading the library
94 * will provoke ereport() regardless of signalNotFound.
96 * If filehandle is not NULL, then *filehandle will be set to a handle
97 * identifying the library file. The filehandle can be used with
98 * lookup_external_function to lookup additional functions in the same file
99 * at less cost than repeating load_external_function.
102 load_external_function(char *filename
, char *funcname
,
103 bool signalNotFound
, void **filehandle
)
109 /* Expand the possibly-abbreviated filename to an exact path name */
110 fullname
= expand_dynamic_library_name(filename
);
112 /* Load the shared library, unless we already did */
113 lib_handle
= internal_load_library(fullname
);
115 /* Return handle if caller wants it */
117 *filehandle
= lib_handle
;
119 /* Look up the function within the library */
120 retval
= (PGFunction
) pg_dlsym(lib_handle
, funcname
);
122 if (retval
== NULL
&& signalNotFound
)
124 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
125 errmsg("could not find function \"%s\" in file \"%s\"",
126 funcname
, fullname
)));
133 * This function loads a shlib file without looking up any particular
134 * function in it. If the same shlib has previously been loaded,
135 * unload and reload it.
137 * When 'restricted' is true, only libraries in the presumed-secure
138 * directory $libdir/plugins may be referenced.
141 load_file(const char *filename
, bool restricted
)
145 /* Apply security restriction if requested */
147 check_restricted_library_name(filename
);
149 /* Expand the possibly-abbreviated filename to an exact path name */
150 fullname
= expand_dynamic_library_name(filename
);
152 /* Unload the library if currently loaded */
153 internal_unload_library(fullname
);
155 /* Load the shared library */
156 (void) internal_load_library(fullname
);
162 * Lookup a function whose library file is already loaded.
163 * Return (PGFunction) NULL if not found.
166 lookup_external_function(void *filehandle
, char *funcname
)
168 return (PGFunction
) pg_dlsym(filehandle
, funcname
);
173 * Load the specified dynamic-link library file, unless it already is
174 * loaded. Return the pg_dl* handle for the file.
176 * Note: libname is expected to be an exact name for the library file.
179 internal_load_library(const char *libname
)
181 DynamicFileList
*file_scanner
;
182 PGModuleMagicFunction magic_func
;
184 struct stat stat_buf
;
188 * Scan the list of loaded FILES to see if the file has been loaded.
190 for (file_scanner
= file_list
;
191 file_scanner
!= NULL
&&
192 strcmp(libname
, file_scanner
->filename
) != 0;
193 file_scanner
= file_scanner
->next
)
196 if (file_scanner
== NULL
)
199 * Check for same files - different paths (ie, symlink or link)
201 if (stat(libname
, &stat_buf
) == -1)
203 (errcode_for_file_access(),
204 errmsg("could not access file \"%s\": %m",
207 for (file_scanner
= file_list
;
208 file_scanner
!= NULL
&&
209 !SAME_INODE(stat_buf
, *file_scanner
);
210 file_scanner
= file_scanner
->next
)
214 if (file_scanner
== NULL
)
217 * File not loaded yet.
219 file_scanner
= (DynamicFileList
*)
220 malloc(sizeof(DynamicFileList
) + strlen(libname
));
221 if (file_scanner
== NULL
)
223 (errcode(ERRCODE_OUT_OF_MEMORY
),
224 errmsg("out of memory")));
226 MemSet(file_scanner
, 0, sizeof(DynamicFileList
));
227 strcpy(file_scanner
->filename
, libname
);
228 file_scanner
->device
= stat_buf
.st_dev
;
230 file_scanner
->inode
= stat_buf
.st_ino
;
232 file_scanner
->next
= NULL
;
234 file_scanner
->handle
= pg_dlopen(file_scanner
->filename
);
235 if (file_scanner
->handle
== NULL
)
237 load_error
= (char *) pg_dlerror();
238 free((char *) file_scanner
);
239 /* errcode_for_file_access might not be appropriate here? */
241 (errcode_for_file_access(),
242 errmsg("could not load library \"%s\": %s",
243 libname
, load_error
)));
246 /* Check the magic function to determine compatibility */
247 magic_func
= (PGModuleMagicFunction
)
248 pg_dlsym(file_scanner
->handle
, PG_MAGIC_FUNCTION_NAME_STRING
);
251 const Pg_magic_struct
*magic_data_ptr
= (*magic_func
) ();
253 if (magic_data_ptr
->len
!= magic_data
.len
||
254 memcmp(magic_data_ptr
, &magic_data
, magic_data
.len
) != 0)
256 /* copy data block before unlinking library */
257 Pg_magic_struct module_magic_data
= *magic_data_ptr
;
259 /* try to unlink library */
260 pg_dlclose(file_scanner
->handle
);
261 free((char *) file_scanner
);
263 /* issue suitable complaint */
264 incompatible_module_error(libname
, &module_magic_data
);
269 /* try to unlink library */
270 pg_dlclose(file_scanner
->handle
);
271 free((char *) file_scanner
);
274 (errmsg("incompatible library \"%s\": missing magic block",
276 errhint("Extension libraries are required to use the PG_MODULE_MAGIC macro.")));
280 * If the library has a _PG_init() function, call it.
282 PG_init
= (PG_init_t
) pg_dlsym(file_scanner
->handle
, "_PG_init");
286 /* OK to link it into list */
287 if (file_list
== NULL
)
288 file_list
= file_scanner
;
290 file_tail
->next
= file_scanner
;
291 file_tail
= file_scanner
;
294 return file_scanner
->handle
;
298 * Report a suitable error for an incompatible magic block.
301 incompatible_module_error(const char *libname
,
302 const Pg_magic_struct
*module_magic_data
)
304 StringInfoData details
;
307 * If the version doesn't match, just report that, because the rest of the
308 * block might not even have the fields we expect.
310 if (magic_data
.version
!= module_magic_data
->version
)
312 (errmsg("incompatible library \"%s\": version mismatch",
314 errdetail("Server is version %d.%d, library is version %d.%d.",
315 magic_data
.version
/ 100,
316 magic_data
.version
% 100,
317 module_magic_data
->version
/ 100,
318 module_magic_data
->version
% 100)));
321 * Otherwise, spell out which fields don't agree.
323 * XXX this code has to be adjusted any time the set of fields in a magic
326 initStringInfo(&details
);
328 if (module_magic_data
->funcmaxargs
!= magic_data
.funcmaxargs
)
331 appendStringInfoChar(&details
, '\n');
332 appendStringInfo(&details
,
333 _("Server has FUNC_MAX_ARGS = %d, library has %d."),
334 magic_data
.funcmaxargs
,
335 module_magic_data
->funcmaxargs
);
337 if (module_magic_data
->indexmaxkeys
!= magic_data
.indexmaxkeys
)
340 appendStringInfoChar(&details
, '\n');
341 appendStringInfo(&details
,
342 _("Server has INDEX_MAX_KEYS = %d, library has %d."),
343 magic_data
.indexmaxkeys
,
344 module_magic_data
->indexmaxkeys
);
346 if (module_magic_data
->namedatalen
!= magic_data
.namedatalen
)
349 appendStringInfoChar(&details
, '\n');
350 appendStringInfo(&details
,
351 _("Server has NAMEDATALEN = %d, library has %d."),
352 magic_data
.namedatalen
,
353 module_magic_data
->namedatalen
);
355 if (module_magic_data
->float4byval
!= magic_data
.float4byval
)
358 appendStringInfoChar(&details
, '\n');
359 appendStringInfo(&details
,
360 _("Server has FLOAT4PASSBYVAL = %s, library has %s."),
361 magic_data
.float4byval
? "true" : "false",
362 module_magic_data
->float4byval
? "true" : "false");
364 if (module_magic_data
->float8byval
!= magic_data
.float8byval
)
367 appendStringInfoChar(&details
, '\n');
368 appendStringInfo(&details
,
369 _("Server has FLOAT8PASSBYVAL = %s, library has %s."),
370 magic_data
.float8byval
? "true" : "false",
371 module_magic_data
->float8byval
? "true" : "false");
374 if (details
.len
== 0)
375 appendStringInfo(&details
,
376 _("Magic block has unexpected length or padding difference."));
379 (errmsg("incompatible library \"%s\": magic block mismatch",
381 errdetail("%s", details
.data
)));
385 * Unload the specified dynamic-link library file, if it is loaded.
387 * Note: libname is expected to be an exact name for the library file.
390 internal_unload_library(const char *libname
)
392 DynamicFileList
*file_scanner
,
395 struct stat stat_buf
;
399 * We need to do stat() in order to determine whether this is the same
400 * file as a previously loaded file; it's also handy so as to give a good
401 * error message if bogus file name given.
403 if (stat(libname
, &stat_buf
) == -1)
405 (errcode_for_file_access(),
406 errmsg("could not access file \"%s\": %m", libname
)));
409 * We have to zap all entries in the list that match on either filename or
410 * inode, else internal_load_library() will still think it's present.
413 for (file_scanner
= file_list
; file_scanner
!= NULL
; file_scanner
= nxt
)
415 nxt
= file_scanner
->next
;
416 if (strcmp(libname
, file_scanner
->filename
) == 0 ||
417 SAME_INODE(stat_buf
, *file_scanner
))
425 * If the library has a _PG_fini() function, call it.
427 PG_fini
= (PG_fini_t
) pg_dlsym(file_scanner
->handle
, "_PG_fini");
431 clear_external_function_hash(file_scanner
->handle
);
432 pg_dlclose(file_scanner
->handle
);
433 free((char *) file_scanner
);
434 /* prv does not change */
442 file_exists(const char *name
)
446 AssertArg(name
!= NULL
);
448 if (stat(name
, &st
) == 0)
449 return S_ISDIR(st
.st_mode
) ? false : true;
450 else if (!(errno
== ENOENT
|| errno
== ENOTDIR
|| errno
== EACCES
))
452 (errcode_for_file_access(),
453 errmsg("could not access file \"%s\": %m", name
)));
459 /* Example format: ".so" */
461 #error "DLSUFFIX must be defined to compile this file."
465 * If name contains a slash, check if the file exists, if so return
466 * the name. Else (no slash) try to expand using search path (see
467 * find_in_dynamic_libpath below); if that works, return the fully
468 * expanded file name. If the previous failed, append DLSUFFIX and
469 * try again. If all fails, just return the original name.
471 * The result will always be freshly palloc'd.
474 expand_dynamic_library_name(const char *name
)
482 have_slash
= (first_dir_separator(name
) != NULL
);
486 full
= find_in_dynamic_libpath(name
);
492 full
= substitute_libpath_macro(name
);
493 if (file_exists(full
))
498 new = palloc(strlen(name
) + strlen(DLSUFFIX
) + 1);
500 strcat(new, DLSUFFIX
);
504 full
= find_in_dynamic_libpath(new);
511 full
= substitute_libpath_macro(new);
513 if (file_exists(full
))
519 * If we can't find the file, just return the string as-is. The ensuing
520 * load attempt will fail and report a suitable message.
522 return pstrdup(name
);
526 * Check a restricted library name. It must begin with "$libdir/plugins/"
527 * and there must not be any directory separators after that (this is
528 * sufficient to prevent ".." style attacks).
531 check_restricted_library_name(const char *name
)
533 if (strncmp(name
, "$libdir/plugins/", 16) != 0 ||
534 first_dir_separator(name
+ 16) != NULL
)
536 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
537 errmsg("access to library \"%s\" is not allowed",
542 * Substitute for any macros appearing in the given string.
543 * Result is always freshly palloc'd.
546 substitute_libpath_macro(const char *name
)
551 AssertArg(name
!= NULL
);
553 /* Currently, we only recognize $libdir at the start of the string */
555 return pstrdup(name
);
557 if ((sep_ptr
= first_dir_separator(name
)) == NULL
)
558 sep_ptr
= name
+ strlen(name
);
560 if (strlen("$libdir") != sep_ptr
- name
||
561 strncmp(name
, "$libdir", strlen("$libdir")) != 0)
563 (errcode(ERRCODE_INVALID_NAME
),
564 errmsg("invalid macro name in dynamic library path: %s",
567 ret
= palloc(strlen(pkglib_path
) + strlen(sep_ptr
) + 1);
569 strcpy(ret
, pkglib_path
);
570 strcat(ret
, sep_ptr
);
577 * Search for a file called 'basename' in the colon-separated search
578 * path Dynamic_library_path. If the file is found, the full file name
579 * is returned in freshly palloc'd memory. If the file is not found,
583 find_in_dynamic_libpath(const char *basename
)
588 AssertArg(basename
!= NULL
);
589 AssertArg(first_dir_separator(basename
) == NULL
);
590 AssertState(Dynamic_library_path
!= NULL
);
592 p
= Dynamic_library_path
;
596 baselen
= strlen(basename
);
605 piece
= first_path_separator(p
);
608 (errcode(ERRCODE_INVALID_NAME
),
609 errmsg("zero-length component in parameter \"dynamic_library_path\"")));
616 piece
= palloc(len
+ 1);
617 strlcpy(piece
, p
, len
+ 1);
619 mangled
= substitute_libpath_macro(piece
);
622 canonicalize_path(mangled
);
624 /* only absolute paths */
625 if (!is_absolute_path(mangled
))
627 (errcode(ERRCODE_INVALID_NAME
),
628 errmsg("component in parameter \"dynamic_library_path\" is not an absolute path")));
630 full
= palloc(strlen(mangled
) + 1 + baselen
+ 1);
631 sprintf(full
, "%s/%s", mangled
, basename
);
634 elog(DEBUG3
, "find_in_dynamic_libpath: trying \"%s\"", full
);
636 if (file_exists(full
))
652 * Find (or create) a rendezvous variable that one dynamically
653 * loaded library can use to meet up with another.
655 * On the first call of this function for a particular varName,
656 * a "rendezvous variable" is created with the given name.
657 * The value of the variable is a void pointer (initially set to NULL).
658 * Subsequent calls with the same varName just return the address of
659 * the existing variable. Once created, a rendezvous variable lasts
660 * for the life of the process.
662 * Dynamically loaded libraries can use rendezvous variables
663 * to find each other and share information: they just need to agree
664 * on the variable name and the data it will point to.
667 find_rendezvous_variable(const char *varName
)
669 static HTAB
*rendezvousHash
= NULL
;
671 rendezvousHashEntry
*hentry
;
674 /* Create a hashtable if we haven't already done so in this process */
675 if (rendezvousHash
== NULL
)
679 MemSet(&ctl
, 0, sizeof(ctl
));
680 ctl
.keysize
= NAMEDATALEN
;
681 ctl
.entrysize
= sizeof(rendezvousHashEntry
);
682 rendezvousHash
= hash_create("Rendezvous variable hash",
688 /* Find or create the hashtable entry for this varName */
689 hentry
= (rendezvousHashEntry
*) hash_search(rendezvousHash
,
694 /* Initialize to NULL if first time */
696 hentry
->varValue
= NULL
;
698 return &hentry
->varValue
;