From ba9f37f066cffbc327936fe35d08778c23be6e16 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 3 Sep 2008 22:34:50 +0000 Subject: [PATCH] If a loadable module has wrong values in its magic block, spell out exactly what they are in the complaint message. Marko Kreen, some editorialization by me. --- src/backend/utils/fmgr/dfmgr.c | 111 +++++++++++++++++++++++++++------ src/include/fmgr.h | 5 +- 2 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 743df3a916..eedab5f30b 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -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. * diff --git a/src/include/fmgr.h b/src/include/fmgr.h index f0cc26f531..c348086fbc 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.59 2008/05/15 00:17:41 tgl Exp $ + * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.60 2008/09/03 22:34:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -357,6 +357,9 @@ extern int no_such_variable * * Note: we compare magic blocks with memcmp(), so there had better not be * any alignment pad bytes in them. + * + * Note: when changing the contents of magic blocks, be sure to adjust the + * incompatible_module_error() function in dfmgr.c. *------------------------------------------------------------------------- */