|
|
|
@ -8,7 +8,7 @@ |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* IDENTIFICATION |
|
|
|
|
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.96 2008/01/01 19:45:53 momjian Exp $ |
|
|
|
|
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.97 2008/09/03 22:34:50 tgl Exp $ |
|
|
|
|
* |
|
|
|
|
*------------------------------------------------------------------------- |
|
|
|
|
*/ |
|
|
|
@ -21,6 +21,7 @@ |
|
|
|
|
#else |
|
|
|
|
#include "port/dynloader/win32.h" |
|
|
|
|
#endif |
|
|
|
|
#include "lib/stringinfo.h" |
|
|
|
|
#include "miscadmin.h" |
|
|
|
|
#include "utils/dynamic_loader.h" |
|
|
|
|
#include "utils/hsearch.h" |
|
|
|
@ -71,6 +72,8 @@ static DynamicFileList *file_tail = NULL; |
|
|
|
|
char *Dynamic_library_path; |
|
|
|
|
|
|
|
|
|
static void *internal_load_library(const char *libname); |
|
|
|
|
static void incompatible_module_error(const char *libname, |
|
|
|
|
const Pg_magic_struct *module_magic_data); |
|
|
|
|
static void internal_unload_library(const char *libname); |
|
|
|
|
static bool file_exists(const char *name); |
|
|
|
|
static char *expand_dynamic_library_name(const char *name); |
|
|
|
@ -257,23 +260,8 @@ internal_load_library(const char *libname) |
|
|
|
|
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))); |
|
|
|
|
/* issue suitable complaint */ |
|
|
|
|
incompatible_module_error(libname, &module_magic_data); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
@ -306,6 +294,93 @@ internal_load_library(const char *libname) |
|
|
|
|
return file_scanner->handle; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Report a suitable error for an incompatible magic block. |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
incompatible_module_error(const char *libname, |
|
|
|
|
const Pg_magic_struct *module_magic_data) |
|
|
|
|
{ |
|
|
|
|
StringInfoData details; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the version doesn't match, just report that, because the rest of the |
|
|
|
|
* block might not even have the fields we expect. |
|
|
|
|
*/ |
|
|
|
|
if (magic_data.version != module_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))); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Otherwise, spell out which fields don't agree. |
|
|
|
|
* |
|
|
|
|
* XXX this code has to be adjusted any time the set of fields in a magic |
|
|
|
|
* block change! |
|
|
|
|
*/ |
|
|
|
|
initStringInfo(&details); |
|
|
|
|
|
|
|
|
|
if (module_magic_data->funcmaxargs != magic_data.funcmaxargs) |
|
|
|
|
{ |
|
|
|
|
if (details.len) |
|
|
|
|
appendStringInfoChar(&details, '\n'); |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Server has FUNC_MAX_ARGS = %d, library has %d."), |
|
|
|
|
magic_data.funcmaxargs, |
|
|
|
|
module_magic_data->funcmaxargs); |
|
|
|
|
} |
|
|
|
|
if (module_magic_data->indexmaxkeys != magic_data.indexmaxkeys) |
|
|
|
|
{ |
|
|
|
|
if (details.len) |
|
|
|
|
appendStringInfoChar(&details, '\n'); |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Server has INDEX_MAX_KEYS = %d, library has %d."), |
|
|
|
|
magic_data.indexmaxkeys, |
|
|
|
|
module_magic_data->indexmaxkeys); |
|
|
|
|
} |
|
|
|
|
if (module_magic_data->namedatalen != magic_data.namedatalen) |
|
|
|
|
{ |
|
|
|
|
if (details.len) |
|
|
|
|
appendStringInfoChar(&details, '\n'); |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Server has NAMEDATALEN = %d, library has %d."), |
|
|
|
|
magic_data.namedatalen, |
|
|
|
|
module_magic_data->namedatalen); |
|
|
|
|
} |
|
|
|
|
if (module_magic_data->float4byval != magic_data.float4byval) |
|
|
|
|
{ |
|
|
|
|
if (details.len) |
|
|
|
|
appendStringInfoChar(&details, '\n'); |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Server has FLOAT4PASSBYVAL = %s, library has %s."), |
|
|
|
|
magic_data.float4byval ? "true" : "false", |
|
|
|
|
module_magic_data->float4byval ? "true" : "false"); |
|
|
|
|
} |
|
|
|
|
if (module_magic_data->float8byval != magic_data.float8byval) |
|
|
|
|
{ |
|
|
|
|
if (details.len) |
|
|
|
|
appendStringInfoChar(&details, '\n'); |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Server has FLOAT8PASSBYVAL = %s, library has %s."), |
|
|
|
|
magic_data.float8byval ? "true" : "false", |
|
|
|
|
module_magic_data->float8byval ? "true" : "false"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (details.len == 0) |
|
|
|
|
appendStringInfo(&details, |
|
|
|
|
_("Magic block has unexpected length or padding difference.")); |
|
|
|
|
|
|
|
|
|
ereport(ERROR, |
|
|
|
|
(errmsg("incompatible library \"%s\": magic block mismatch", |
|
|
|
|
libname), |
|
|
|
|
errdetail("%s", details.data))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Unload the specified dynamic-link library file, if it is loaded. |
|
|
|
|
* |
|
|
|
|