Fix oversight in previous error-reporting patch; mustn't pfree path string
[PostgreSQL.git] / src / backend / utils / fmgr / dfmgr.c
blobcad18f297d09328b902a07ebc861c7f055a8802f
1 /*-------------------------------------------------------------------------
3 * dfmgr.c
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
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include <sys/stat.h>
19 #ifndef WIN32_ONLY_COMPILER
20 #include "dynloader.h"
21 #else
22 #include "port/dynloader/win32.h"
23 #endif
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 */
35 typedef struct
37 char varName[NAMEDATALEN]; /* hash key (must be first) */
38 void *varValue;
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
50 * win32 */
51 ino_t inode; /* Inode number of file */
52 #endif
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!
60 } DynamicFileList;
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 */
66 #ifndef WIN32
67 #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
68 #else
69 #define SAME_INODE(A,B) false
70 #endif
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.
101 PGFunction
102 load_external_function(char *filename, char *funcname,
103 bool signalNotFound, void **filehandle)
105 char *fullname;
106 void *lib_handle;
107 PGFunction retval;
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 */
116 if (filehandle)
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)
123 ereport(ERROR,
124 (errcode(ERRCODE_UNDEFINED_FUNCTION),
125 errmsg("could not find function \"%s\" in file \"%s\"",
126 funcname, fullname)));
128 pfree(fullname);
129 return retval;
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.
140 void
141 load_file(const char *filename, bool restricted)
143 char *fullname;
145 /* Apply security restriction if requested */
146 if (restricted)
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);
158 pfree(fullname);
162 * Lookup a function whose library file is already loaded.
163 * Return (PGFunction) NULL if not found.
165 PGFunction
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.
178 static void *
179 internal_load_library(const char *libname)
181 DynamicFileList *file_scanner;
182 PGModuleMagicFunction magic_func;
183 char *load_error;
184 struct stat stat_buf;
185 PG_init_t PG_init;
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)
202 ereport(ERROR,
203 (errcode_for_file_access(),
204 errmsg("could not access file \"%s\": %m",
205 libname)));
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)
222 ereport(ERROR,
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;
229 #ifndef WIN32
230 file_scanner->inode = stat_buf.st_ino;
231 #endif
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? */
240 ereport(ERROR,
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);
249 if (magic_func)
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);
267 else
269 /* try to unlink library */
270 pg_dlclose(file_scanner->handle);
271 free((char *) file_scanner);
272 /* complain */
273 ereport(ERROR,
274 (errmsg("incompatible library \"%s\": missing magic block",
275 libname),
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");
283 if (PG_init)
284 (*PG_init) ();
286 /* OK to link it into list */
287 if (file_list == NULL)
288 file_list = file_scanner;
289 else
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.
300 static void
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)
311 ereport(ERROR,
312 (errmsg("incompatible library \"%s\": version mismatch",
313 libname),
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
324 * block change!
326 initStringInfo(&details);
328 if (module_magic_data->funcmaxargs != magic_data.funcmaxargs)
330 if (details.len)
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)
339 if (details.len)
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)
348 if (details.len)
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)
357 if (details.len)
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)
366 if (details.len)
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."));
378 ereport(ERROR,
379 (errmsg("incompatible library \"%s\": magic block mismatch",
380 libname),
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.
389 static void
390 internal_unload_library(const char *libname)
392 DynamicFileList *file_scanner,
393 *prv,
394 *nxt;
395 struct stat stat_buf;
396 PG_fini_t PG_fini;
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)
404 ereport(ERROR,
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.
412 prv = NULL;
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))
419 if (prv)
420 prv->next = nxt;
421 else
422 file_list = nxt;
425 * If the library has a _PG_fini() function, call it.
427 PG_fini = (PG_fini_t) pg_dlsym(file_scanner->handle, "_PG_fini");
428 if (PG_fini)
429 (*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 */
436 else
437 prv = file_scanner;
441 static bool
442 file_exists(const char *name)
444 struct stat st;
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))
451 ereport(ERROR,
452 (errcode_for_file_access(),
453 errmsg("could not access file \"%s\": %m", name)));
455 return false;
459 /* Example format: ".so" */
460 #ifndef DLSUFFIX
461 #error "DLSUFFIX must be defined to compile this file."
462 #endif
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.
473 static char *
474 expand_dynamic_library_name(const char *name)
476 bool have_slash;
477 char *new;
478 char *full;
480 AssertArg(name);
482 have_slash = (first_dir_separator(name) != NULL);
484 if (!have_slash)
486 full = find_in_dynamic_libpath(name);
487 if (full)
488 return full;
490 else
492 full = substitute_libpath_macro(name);
493 if (file_exists(full))
494 return full;
495 pfree(full);
498 new = palloc(strlen(name) + strlen(DLSUFFIX) + 1);
499 strcpy(new, name);
500 strcat(new, DLSUFFIX);
502 if (!have_slash)
504 full = find_in_dynamic_libpath(new);
505 pfree(new);
506 if (full)
507 return full;
509 else
511 full = substitute_libpath_macro(new);
512 pfree(new);
513 if (file_exists(full))
514 return full;
515 pfree(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).
530 static void
531 check_restricted_library_name(const char *name)
533 if (strncmp(name, "$libdir/plugins/", 16) != 0 ||
534 first_dir_separator(name + 16) != NULL)
535 ereport(ERROR,
536 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
537 errmsg("access to library \"%s\" is not allowed",
538 name)));
542 * Substitute for any macros appearing in the given string.
543 * Result is always freshly palloc'd.
545 static char *
546 substitute_libpath_macro(const char *name)
548 const char *sep_ptr;
549 char *ret;
551 AssertArg(name != NULL);
553 /* Currently, we only recognize $libdir at the start of the string */
554 if (name[0] != '$')
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)
562 ereport(ERROR,
563 (errcode(ERRCODE_INVALID_NAME),
564 errmsg("invalid macro name in dynamic library path: %s",
565 name)));
567 ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
569 strcpy(ret, pkglib_path);
570 strcat(ret, sep_ptr);
572 return ret;
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,
580 * return NULL.
582 static char *
583 find_in_dynamic_libpath(const char *basename)
585 const char *p;
586 size_t baselen;
588 AssertArg(basename != NULL);
589 AssertArg(first_dir_separator(basename) == NULL);
590 AssertState(Dynamic_library_path != NULL);
592 p = Dynamic_library_path;
593 if (strlen(p) == 0)
594 return NULL;
596 baselen = strlen(basename);
598 for (;;)
600 size_t len;
601 char *piece;
602 char *mangled;
603 char *full;
605 piece = first_path_separator(p);
606 if (piece == p)
607 ereport(ERROR,
608 (errcode(ERRCODE_INVALID_NAME),
609 errmsg("zero-length component in parameter \"dynamic_library_path\"")));
611 if (piece == 0)
612 len = strlen(p);
613 else
614 len = piece - p;
616 piece = palloc(len + 1);
617 strlcpy(piece, p, len + 1);
619 mangled = substitute_libpath_macro(piece);
620 pfree(piece);
622 canonicalize_path(mangled);
624 /* only absolute paths */
625 if (!is_absolute_path(mangled))
626 ereport(ERROR,
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);
632 pfree(mangled);
634 elog(DEBUG3, "find_in_dynamic_libpath: trying \"%s\"", full);
636 if (file_exists(full))
637 return full;
639 pfree(full);
641 if (p[len] == '\0')
642 break;
643 else
644 p += len + 1;
647 return NULL;
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.
666 void **
667 find_rendezvous_variable(const char *varName)
669 static HTAB *rendezvousHash = NULL;
671 rendezvousHashEntry *hentry;
672 bool found;
674 /* Create a hashtable if we haven't already done so in this process */
675 if (rendezvousHash == NULL)
677 HASHCTL ctl;
679 MemSet(&ctl, 0, sizeof(ctl));
680 ctl.keysize = NAMEDATALEN;
681 ctl.entrysize = sizeof(rendezvousHashEntry);
682 rendezvousHash = hash_create("Rendezvous variable hash",
684 &ctl,
685 HASH_ELEM);
688 /* Find or create the hashtable entry for this varName */
689 hentry = (rendezvousHashEntry *) hash_search(rendezvousHash,
690 varName,
691 HASH_ENTER,
692 &found);
694 /* Initialize to NULL if first time */
695 if (!found)
696 hentry->varValue = NULL;
698 return &hentry->varValue;