Add dynamic_library_path parameter and automatic appending of shared
authorPeter Eisentraut
Thu, 17 May 2001 17:44:18 +0000 (17:44 +0000)
committerPeter Eisentraut
Thu, 17 May 2001 17:44:18 +0000 (17:44 +0000)
library extension.

doc/src/sgml/runtime.sgml
src/backend/utils/fmgr/Makefile
src/backend/utils/fmgr/dfmgr.c
src/backend/utils/misc/guc.c
src/include/fmgr.h

index bc7a86dba1def93d415e554cd6aaea0c437a5878..f5ed95be5d4648dbe88312f09cfcea12edf10773 100644 (file)
@@ -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
index 1e7c19db3319f1193ce555ea95874ef3cbeb4b61..a449b80942b2694ca5aa382a6183ae53f960f9bb 100644 (file)
@@ -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)
index 49be6b37903bd2619b3847059b1e18e7f6a6b142..695fb1ed76e8c769d9bf72d4411bbd1f7122f350 100644 (file)
@@ -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;
+}
index 1d779979a194f92584d2597d3abccf3d97ad22fc..6e080594f8b6662891da9be5b2bb5a0c566f22d2 100644 (file)
@@ -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},
 
index 3ccd1c39c615e7fe8659bcf04e4618676703de6d..44641bdcb1829dab3f070500a4cb2655a51ebf5c 100644 (file)
@@ -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;
 
 
 /*