From: Peter Eisentraut Date: Thu, 17 May 2001 17:44:18 +0000 (+0000) Subject: Add dynamic_library_path parameter and automatic appending of shared X-Git-Tag: REL7_2_BETA1~1242 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=761a0bb69b5a9a773786f90da8e2efa91e5a2804;p=postgresql Add dynamic_library_path parameter and automatic appending of shared library extension. --- diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index bc7a86dba1..f5ed95be5d 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -996,6 +996,49 @@ env PGOPTIONS='-c geqo=off' psql + + DYNAMIC_LIBRARY_PATH (string) + + + If a dynamically loadable module needs to be opened and the + specified name does not have a directory component (i.e., the + name does not contain a slash), the system will search this + path for the specified file. (The name that is used is the + name specified in the CREATE FUNCTION or + LOAD command.) + + + + The value for dynamic_library_path has to be a colon-separated + list of absolute directory names. If a directory name starts + with the special value $libdir, the + compiled-in PostgreSQL library directory, which is where the + modules provided by the PostgreSQL distribution are installed, + is substituted. An example value: + + +dynamic_library_path = '/usr/local/lib:/home/my_project/lib:$libdir:$libdir/contrib' + + + + + + The default value for this parameter is + $libdir. If the value is set to the empty + string, the automatic path search is turned off. + + + + This parameter can be changed at run time by superusers, but + note that a setting done that way will only persist till the + end of the client connection, so this method should be + reserved for development purposes. The recommended way to set + this parameter is in the postgresql.conf + configuration file. + + + + fsync diff --git a/src/backend/utils/fmgr/Makefile b/src/backend/utils/fmgr/Makefile index 1e7c19db33..a449b80942 100644 --- a/src/backend/utils/fmgr/Makefile +++ b/src/backend/utils/fmgr/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/fmgr # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.10 2000/08/31 16:10:50 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.11 2001/05/17 17:44:18 petere Exp $ # #------------------------------------------------------------------------- @@ -14,6 +14,9 @@ include $(top_builddir)/src/Makefile.global OBJS = dfmgr.o fmgr.o +override CPPFLAGS += -DLIBDIR=\"$(libdir)\" -DDLSUFFIX=\"$(DLSUFFIX)\" + + all: SUBSYS.o SUBSYS.o: $(OBJS) diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 49be6b3790..695fb1ed76 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -8,16 +8,18 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.48 2001/03/22 03:59:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.49 2001/05/17 17:44:18 petere Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include #include #include #include "dynloader.h" +#include "miscadmin.h" #include "utils/dynamic_loader.h" @@ -44,6 +46,12 @@ static DynamicFileList *file_tail = (DynamicFileList *) NULL; #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device) +char * Dynamic_library_path; + +static bool file_exists(const char *name); +static char * find_in_dynamic_libpath(const char * basename); +static char * expand_dynamic_library_name(const char *name); + /* * Load the specified dynamic-link library file, and look for a function @@ -60,6 +68,11 @@ load_external_function(char *filename, char *funcname, PGFunction retval; char *load_error; struct stat stat_buf; + char *fullname; + + fullname = expand_dynamic_library_name(filename); + if (fullname) + filename = fullname; /* * Scan the list of loaded FILES to see if the file has been loaded. @@ -143,6 +156,11 @@ load_file(char *filename) DynamicFileList *file_scanner, *p; struct stat stat_buf; + char *fullname; + + fullname = expand_dynamic_library_name(filename); + if (fullname) + filename = fullname; /* * We need to do stat() in order to determine whether this is the same @@ -181,3 +199,181 @@ load_file(char *filename) load_external_function(filename, (char *) NULL, false); } + + + +static bool +file_exists(const char *name) +{ + struct stat st; + + AssertArg(name != NULL); + + if (stat(name, &st) == 0) + return true; + else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES)) + elog(ERROR, "stat failed on %s: %s", name, strerror(errno)); + + return false; +} + + +/* Example format: ".so" */ +#ifndef DLSUFFIX +#error "DLSUFFIX must be defined to compile this file." +#endif + +/* Example format: "/usr/local/pgsql/lib" */ +#ifndef LIBDIR +#error "LIBDIR needs to be defined to compile this file." +#endif + + +/* + * If name contains a slash, check if the file exists, if so return + * the name. Else (no slash) try to expand using search path (see + * find_in_dynamic_libpath below); if that works, return the fully + * expanded file name. If the previous failed, append DLSUFFIX and + * try again. If all fails, return NULL. The return value is + * palloc'ed. + */ +static char * +expand_dynamic_library_name(const char *name) +{ + bool have_slash; + char * new; + size_t len; + + AssertArg(name); + + have_slash = (strchr(name, '/') != NULL); + + if (!have_slash) + { + char * full; + + full = find_in_dynamic_libpath(name); + if (full) + return full; + } + else + { + if (file_exists(name)) + return pstrdup(name); + } + + len = strlen(name); + + new = palloc(len + strlen(DLSUFFIX) + 1); + strcpy(new, name); + strcpy(new + len, DLSUFFIX); + + if (!have_slash) + { + char * full; + + full = find_in_dynamic_libpath(new); + pfree(new); + if (full) + return full; + } + else + { + if (file_exists(new)) + return new; + } + + return NULL; +} + + + +/* + * Search for a file called 'basename' in the colon-separated search + * path 'path'. If the file is found, the full file name is returned + * in palloced memory. The the file is not found, return NULL. + */ +static char * +find_in_dynamic_libpath(const char * basename) +{ + const char *p; + char *full; + size_t len; + size_t baselen; + + AssertArg(basename != NULL); + AssertArg(strchr(basename, '/') == NULL); + AssertState(Dynamic_library_path != NULL); + + p = Dynamic_library_path; + if (strlen(p) == 0) + return NULL; + + baselen = strlen(basename); + + do { + len = strcspn(p, ":"); + + if (len == 0) + elog(ERROR, "zero length dynamic_library_path component"); + + /* substitute special value */ + if (p[0] == '$') + { + size_t varname_len = strcspn(p + 1, "/") + 1; + const char * replacement = NULL; + size_t repl_len; + + if (strncmp(p, "$libdir", varname_len)==0) + replacement = LIBDIR; + else + elog(ERROR, "invalid dynamic_library_path specification"); + + repl_len = strlen(replacement); + + if (p[varname_len] == '\0') + { + full = palloc(repl_len + 1 + baselen + 1); + snprintf(full, repl_len + 1 + baselen + 1, + "%s/%s", replacement, basename); + } + else + { + full = palloc(repl_len + (len - varname_len) + 1 + baselen + 1); + + strcpy(full, replacement); + strncat(full, p + varname_len, len - varname_len); + full[repl_len + (len - varname_len)] = '\0'; + strcat(full, "/"); + strcat(full, basename); + } + } + + /* regular case */ + else + { + /* only absolute paths */ + if (p[0] != '/') + elog(ERROR, "dynamic_library_path component is not absolute"); + + full = palloc(len + 1 + baselen + 1); + strncpy(full, p, len); + full[len] = '/'; + strcpy(full + len + 1, basename); + } + + if (DebugLvl > 1) + elog(DEBUG, "find_in_dynamic_libpath: trying %s", full); + + if (file_exists(full)) + return full; + + pfree(full); + if (p[len] == '\0') + break; + else + p += len + 1; + } while(1); + + return NULL; +} diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 1d779979a1..6e080594f8 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4,7 +4,7 @@ * Support for grand unified configuration scheme, including SET * command, configuration file, and command line options. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.35 2001/03/22 17:41:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.36 2001/05/17 17:44:18 petere Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -22,6 +22,7 @@ #include "access/xlog.h" #include "commands/async.h" +#include "fmgr.h" #include "libpq/auth.h" #include "libpq/pqcomm.h" #include "miscadmin.h" @@ -328,6 +329,9 @@ static struct config_real static struct config_string ConfigureNamesString[] = { + {"dynamic_library_path", PGC_SUSET, &Dynamic_library_path, + "$libdir", NULL, NULL}, + {"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile, PG_KRB_SRVTAB, NULL, NULL}, diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 3ccd1c39c6..44641bdcb1 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: fmgr.h,v 1.13 2001/03/22 04:00:25 momjian Exp $ + * $Id: fmgr.h,v 1.14 2001/05/17 17:44:18 petere Exp $ * *------------------------------------------------------------------------- */ @@ -350,6 +350,7 @@ extern Oid fmgr_internal_function(const char *proname); extern PGFunction load_external_function(char *filename, char *funcname, bool signalNotFound); extern void load_file(char *filename); +extern char * Dynamic_library_path; /*