]> granicus.if.org Git - postgresql/commitdiff
Add dynamic_library_path parameter and automatic appending of shared
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 17 May 2001 17:44:18 +0000 (17:44 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
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 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.66 2001/05/12 22:51:35 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.67 2001/05/17 17:44:17 petere Exp $
 -->
 
 <Chapter Id="runtime">
@@ -996,6 +996,49 @@ env PGOPTIONS='-c geqo=off' psql
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>DYNAMIC_LIBRARY_PATH (<type>string</type>)</term>
+      <listitem>
+       <para>
+        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 <command>CREATE FUNCTION</command> or
+        <command>LOAD</command> command.)
+       </para>
+
+       <para>
+        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 <literal>$libdir</literal>, the
+        compiled-in PostgreSQL library directory, which is where the
+        modules provided by the PostgreSQL distribution are installed,
+        is substituted.  An example value:
+        <informalexample>
+<programlisting>
+dynamic_library_path = '/usr/local/lib:/home/my_project/lib:$libdir:$libdir/contrib'
+</programlisting>
+        </informalexample>
+       </para>
+
+       <para>
+        The default value for this parameter is
+        <literal>$libdir</literal>.  If the value is set to the empty
+        string, the automatic path search is turned off.
+       </para>
+
+       <para>
+        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 <filename>postgresql.conf</filename>
+        configuration file.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <indexterm>
        <primary>fsync</primary>
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 <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #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 <peter_e@gmx.net>.
@@ -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;
 
 
 /*