Add dynamic_library_path parameter and automatic appending of shared

library extension.
This commit is contained in:
Peter Eisentraut 2001-05-17 17:44:18 +00:00
parent 8266e8a84b
commit 761a0bb69b
5 changed files with 252 additions and 5 deletions

View 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>

View 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)

View 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;
}

View 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},

View 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;
/*