dfmgr.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 625 行 · 第 1/2 页
C
625 行
/*------------------------------------------------------------------------- * * dfmgr.c * Dynamic function manager code. * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.96 2008/01/01 19:45:53 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <sys/stat.h>#ifndef WIN32_ONLY_COMPILER#include "dynloader.h"#else#include "port/dynloader/win32.h"#endif#include "miscadmin.h"#include "utils/dynamic_loader.h"#include "utils/hsearch.h"/* signatures for PostgreSQL-specific library init/fini functions */typedef void (*PG_init_t) (void);typedef void (*PG_fini_t) (void);/* hashtable entry for rendezvous variables */typedef struct{ char varName[NAMEDATALEN]; /* hash key (must be first) */ void *varValue;} rendezvousHashEntry;/* * List of dynamically loaded files (kept in malloc'd memory). */typedef struct df_files{ struct df_files *next; /* List link */ dev_t device; /* Device file is on */#ifndef WIN32 /* ensures we never again depend on this under * win32 */ ino_t inode; /* Inode number of file */#endif void *handle; /* a handle for pg_dl* functions */ char filename[1]; /* Full pathname of file */ /* * we allocate the block big enough for actual length of pathname. * filename[] must be last item in struct! */} DynamicFileList;static DynamicFileList *file_list = NULL;static DynamicFileList *file_tail = NULL;/* stat() call under Win32 returns an st_ino field, but it has no meaning */#ifndef WIN32#define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)#else#define SAME_INODE(A,B) false#endifchar *Dynamic_library_path;static void *internal_load_library(const char *libname);static void internal_unload_library(const char *libname);static bool file_exists(const char *name);static char *expand_dynamic_library_name(const char *name);static void check_restricted_library_name(const char *name);static char *substitute_libpath_macro(const char *name);static char *find_in_dynamic_libpath(const char *basename);/* Magic structure that module needs to match to be accepted */static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;/* * Load the specified dynamic-link library file, and look for a function * named funcname in it. * * If the function is not found, we raise an error if signalNotFound is true, * else return (PGFunction) NULL. Note that errors in loading the library * will provoke ereport() regardless of signalNotFound. * * If filehandle is not NULL, then *filehandle will be set to a handle * identifying the library file. The filehandle can be used with * lookup_external_function to lookup additional functions in the same file * at less cost than repeating load_external_function. */PGFunctionload_external_function(char *filename, char *funcname, bool signalNotFound, void **filehandle){ char *fullname; void *lib_handle; PGFunction retval; /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); /* Load the shared library, unless we already did */ lib_handle = internal_load_library(fullname); /* Return handle if caller wants it */ if (filehandle) *filehandle = lib_handle; /* Look up the function within the library */ retval = (PGFunction) pg_dlsym(lib_handle, funcname); if (retval == NULL && signalNotFound) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not find function \"%s\" in file \"%s\"", funcname, fullname))); pfree(fullname); return retval;}/* * This function loads a shlib file without looking up any particular * function in it. If the same shlib has previously been loaded, * unload and reload it. * * When 'restricted' is true, only libraries in the presumed-secure * directory $libdir/plugins may be referenced. */voidload_file(const char *filename, bool restricted){ char *fullname; /* Apply security restriction if requested */ if (restricted) check_restricted_library_name(filename); /* Expand the possibly-abbreviated filename to an exact path name */ fullname = expand_dynamic_library_name(filename); /* Unload the library if currently loaded */ internal_unload_library(fullname); /* Load the shared library */ (void) internal_load_library(fullname); pfree(fullname);}/* * Lookup a function whose library file is already loaded. * Return (PGFunction) NULL if not found. */PGFunctionlookup_external_function(void *filehandle, char *funcname){ return (PGFunction) pg_dlsym(filehandle, funcname);}/* * Load the specified dynamic-link library file, unless it already is * loaded. Return the pg_dl* handle for the file. * * Note: libname is expected to be an exact name for the library file. */static void *internal_load_library(const char *libname){ DynamicFileList *file_scanner; PGModuleMagicFunction magic_func; char *load_error; struct stat stat_buf; PG_init_t PG_init; /* * Scan the list of loaded FILES to see if the file has been loaded. */ for (file_scanner = file_list; file_scanner != NULL && strcmp(libname, file_scanner->filename) != 0; file_scanner = file_scanner->next) ; if (file_scanner == NULL) { /* * Check for same files - different paths (ie, symlink or link) */ if (stat(libname, &stat_buf) == -1) ereport(ERROR, (errcode_for_file_access(), errmsg("could not access file \"%s\": %m", libname))); for (file_scanner = file_list; file_scanner != NULL && !SAME_INODE(stat_buf, *file_scanner); file_scanner = file_scanner->next) ; } if (file_scanner == NULL) { /* * File not loaded yet. */ file_scanner = (DynamicFileList *) malloc(sizeof(DynamicFileList) + strlen(libname)); if (file_scanner == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); MemSet(file_scanner, 0, sizeof(DynamicFileList)); strcpy(file_scanner->filename, libname); file_scanner->device = stat_buf.st_dev;#ifndef WIN32 file_scanner->inode = stat_buf.st_ino;#endif file_scanner->next = NULL; file_scanner->handle = pg_dlopen(file_scanner->filename); if (file_scanner->handle == NULL) { load_error = (char *) pg_dlerror(); free((char *) file_scanner); /* errcode_for_file_access might not be appropriate here? */ ereport(ERROR, (errcode_for_file_access(), errmsg("could not load library \"%s\": %s", libname, load_error))); } /* Check the magic function to determine compatibility */ magic_func = (PGModuleMagicFunction) pg_dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING); if (magic_func) { const Pg_magic_struct *magic_data_ptr = (*magic_func) (); if (magic_data_ptr->len != magic_data.len || memcmp(magic_data_ptr, &magic_data, magic_data.len) != 0) { /* copy data block before unlinking library */ Pg_magic_struct module_magic_data = *magic_data_ptr; /* try to unlink library */ pg_dlclose(file_scanner->handle); free((char *) file_scanner); /* * Report suitable error. It's probably not worth writing a * separate error message for each field; only the most common * case of wrong major version gets its own message. */ if (module_magic_data.version != magic_data.version) ereport(ERROR, (errmsg("incompatible library \"%s\": version mismatch", libname), errdetail("Server is version %d.%d, library is version %d.%d.", magic_data.version / 100, magic_data.version % 100, module_magic_data.version / 100, module_magic_data.version % 100))); ereport(ERROR, (errmsg("incompatible library \"%s\": magic block mismatch", libname))); } } else { /* try to unlink library */ pg_dlclose(file_scanner->handle); free((char *) file_scanner); /* complain */ ereport(ERROR, (errmsg("incompatible library \"%s\": missing magic block", libname), errhint("Extension libraries are required to use the PG_MODULE_MAGIC macro."))); } /* * If the library has a _PG_init() function, call it. */ PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init"); if (PG_init) (*PG_init) (); /* OK to link it into list */ if (file_list == NULL) file_list = file_scanner; else file_tail->next = file_scanner; file_tail = file_scanner; } return file_scanner->handle;}/* * Unload the specified dynamic-link library file, if it is loaded. * * Note: libname is expected to be an exact name for the library file. */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?