mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Add pgmagic header block to store compile-time constants:
It now only checks four things: Major version number (7.4 or 8.1 for example) NAMEDATALEN FUNC_MAX_ARGS INDEX_MAX_KEYS The three constants were chosen because: 1. We document them in the config page in the docs 2. We mark them as changable in pg_config_manual.h 3. Changing any of these will break some of the more popular modules: FUNC_MAX_ARGS changes fmgr interface, every module uses this NAMEDATALEN changes syscache interface, every PL as well as tsearch uses this INDEX_MAX_KEYS breaks tsearch and anything using GiST. Martijn van Oosterhout
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.82 2006/03/05 15:58:46 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.83 2006/05/30 14:09:32 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,7 +20,7 @@
|
||||
#include "dynloader.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/dynamic_loader.h"
|
||||
|
||||
#include "pgmagic.h"
|
||||
|
||||
/*
|
||||
* List of dynamically loaded files (kept in malloc'd memory).
|
||||
@ -60,6 +60,9 @@ static char *find_in_dynamic_libpath(const char *basename);
|
||||
static char *expand_dynamic_library_name(const char *name);
|
||||
static char *substitute_libpath_macro(const char *name);
|
||||
|
||||
/* Magic structure that module needs to match to be accepted */
|
||||
static Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
|
||||
|
||||
/*
|
||||
* Load the specified dynamic-link library file, and look for a function
|
||||
* named funcname in it. (funcname can be NULL to just load the file.)
|
||||
@ -116,6 +119,7 @@ load_external_function(char *filename, char *funcname,
|
||||
|
||||
if (file_scanner == NULL)
|
||||
{
|
||||
PGModuleMagicFunction magic_func;
|
||||
/*
|
||||
* File not loaded yet.
|
||||
*/
|
||||
@ -146,6 +150,45 @@ load_external_function(char *filename, char *funcname,
|
||||
fullname, load_error)));
|
||||
}
|
||||
|
||||
/* Check the magic function to determine compatability */
|
||||
magic_func = pg_dlsym( file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING );
|
||||
if( magic_func )
|
||||
{
|
||||
Pg_magic_struct *module_magic_data = magic_func();
|
||||
if( module_magic_data->len != magic_data.len ||
|
||||
memcmp( module_magic_data, &magic_data, magic_data.len ) != 0 )
|
||||
{
|
||||
pg_dlclose( file_scanner->handle );
|
||||
|
||||
if( module_magic_data->len != magic_data.len )
|
||||
ereport(ERROR,
|
||||
(errmsg("incompatible library \"%s\": Magic block length mismatch",
|
||||
fullname)));
|
||||
if( module_magic_data->version != magic_data.version )
|
||||
ereport(ERROR,
|
||||
(errmsg("incompatible library \"%s\": Version mismatch",
|
||||
fullname),
|
||||
errdetail("Expected %d.%d, got %d.%d",
|
||||
magic_data.version/100, magic_data.version % 100,
|
||||
module_magic_data->version/100, module_magic_data->version % 100)));
|
||||
|
||||
if( module_magic_data->magic != magic_data.magic )
|
||||
ereport(ERROR,
|
||||
(errmsg("incompatible library \"%s\": Magic constant mismatch",
|
||||
fullname),
|
||||
errdetail("Expected 0x%08X, got 0x%08X",
|
||||
magic_data.magic, magic_data.magic)));
|
||||
/* Should never get here */
|
||||
ereport(ERROR,(errmsg("incompatible library \"%s\": Reason unknown",
|
||||
fullname)));
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Currently we do not penalize modules for not having a
|
||||
magic block, it would break every external module in
|
||||
existance. At some point though... */
|
||||
ereport(LOG, (errmsg("external library \"%s\" did not have magic block", fullname )));
|
||||
|
||||
/* OK to link it into list */
|
||||
if (file_list == NULL)
|
||||
file_list = file_scanner;
|
||||
|
73
src/include/pgmagic.h
Normal file
73
src/include/pgmagic.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgmagic.h
|
||||
* Defines a magic block that can mark a module in a way so show that
|
||||
* it is compatible with the server it is being loaded into.
|
||||
*
|
||||
* This file is intended to be included into modules that wish to load
|
||||
* themselves into the backend. All they need to do is include this header
|
||||
* into one of the source files and include the line:
|
||||
*
|
||||
* PG_MODULE_MAGIC;
|
||||
*
|
||||
* The trailing semi-colon is optional. To work with versions of PostgreSQL
|
||||
* that do not support this, you may put an #ifdef/endif block around it.
|
||||
*
|
||||
* Note, there is space available, particularly in the bitfield part. If it
|
||||
* turns out that a change has happened within a major release that would
|
||||
* require all modules to be recompiled, just setting one unused bit there
|
||||
* will do the trick.
|
||||
*
|
||||
* Originally written by Martijn van Oosterhout <kleptog@svana.org>
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/pgmagic.h,v 1.1 2006/05/30 14:09:32 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PGMAGIC_H
|
||||
#define PGMAGIC_H
|
||||
|
||||
#include "c.h"
|
||||
|
||||
/* The main structure in which the magic is stored. the length field is used
|
||||
* to detect major changes */
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
int version;
|
||||
int magic;
|
||||
} Pg_magic_struct;
|
||||
|
||||
/* Declare the module magic function. It needs to be a function as the dlsym
|
||||
* in the backend is only guarenteed to work on functions, not data */
|
||||
|
||||
typedef Pg_magic_struct *(*PGModuleMagicFunction) (void);
|
||||
|
||||
#define PG_MAGIC_FUNCTION_NAME Pg_magic_func
|
||||
#define PG_MAGIC_FUNCTION_NAME_STRING "Pg_magic_func"
|
||||
|
||||
#define PG_MODULE_MAGIC \
|
||||
extern DLLIMPORT Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \
|
||||
Pg_magic_struct * \
|
||||
PG_MAGIC_FUNCTION_NAME(void) \
|
||||
{ \
|
||||
static Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
|
||||
return &Pg_magic_data; \
|
||||
}
|
||||
|
||||
/* Common user adjustable constants */
|
||||
#define PG_MODULE_MAGIC_CONST \
|
||||
((INDEX_MAX_KEYS << 0) + \
|
||||
(FUNC_MAX_ARGS << 8) + \
|
||||
(NAMEDATALEN << 16))
|
||||
|
||||
/* Finally, the actual data block */
|
||||
#define PG_MODULE_MAGIC_DATA \
|
||||
{ \
|
||||
sizeof(Pg_magic_struct), \
|
||||
PG_VERSION_NUM / 100, /* Major version of postgres */ \
|
||||
PG_MODULE_MAGIC_CONST, /* Constants users can configure */ \
|
||||
}
|
||||
|
||||
#endif /* PGMAGIC_H */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $PostgreSQL: pgsql/src/test/regress/regress.c,v 1.65 2006/01/11 20:12:43 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/test/regress/regress.c,v 1.66 2006/05/30 14:09:32 momjian Exp $
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
@ -9,6 +9,7 @@
|
||||
#include "utils/geo_decls.h" /* includes <math.h> */
|
||||
#include "executor/executor.h" /* For GetAttributeByName */
|
||||
#include "commands/sequence.h" /* for nextval() */
|
||||
#include "pgmagic.h"
|
||||
|
||||
#define P_MAXDIG 12
|
||||
#define LDELIM '('
|
||||
@ -27,7 +28,7 @@ extern int oldstyle_length(int n, text *t);
|
||||
extern Datum int44in(PG_FUNCTION_ARGS);
|
||||
extern Datum int44out(PG_FUNCTION_ARGS);
|
||||
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
/*
|
||||
* Distance from a point to a path
|
||||
*/
|
||||
|
Reference in New Issue
Block a user