dfmgr.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 625 行 · 第 1/2 页

C
625
字号
static voidinternal_unload_library(const char *libname){	DynamicFileList *file_scanner,			   *prv,			   *nxt;	struct stat stat_buf;	PG_fini_t	PG_fini;	/*	 * We need to do stat() in order to determine whether this is the same	 * file as a previously loaded file; it's also handy so as to give a good	 * error message if bogus file name given.	 */	if (stat(libname, &stat_buf) == -1)		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not access file \"%s\": %m", libname)));	/*	 * We have to zap all entries in the list that match on either filename or	 * inode, else internal_load_library() will still think it's present.	 */	prv = NULL;	for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt)	{		nxt = file_scanner->next;		if (strcmp(libname, file_scanner->filename) == 0 ||			SAME_INODE(stat_buf, *file_scanner))		{			if (prv)				prv->next = nxt;			else				file_list = nxt;			/*			 * If the library has a _PG_fini() function, call it.			 */			PG_fini = (PG_fini_t) pg_dlsym(file_scanner->handle, "_PG_fini");			if (PG_fini)				(*PG_fini) ();			clear_external_function_hash(file_scanner->handle);			pg_dlclose(file_scanner->handle);			free((char *) file_scanner);			/* prv does not change */		}		else			prv = file_scanner;	}}static boolfile_exists(const char *name){	struct stat st;	AssertArg(name != NULL);	if (stat(name, &st) == 0)		return S_ISDIR(st.st_mode) ? false : true;	else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES))		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not access file \"%s\": %m", name)));	return false;}/* Example format: ".so" */#ifndef DLSUFFIX#error "DLSUFFIX must 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, just return the original name. * * The result will always be freshly palloc'd. */static char *expand_dynamic_library_name(const char *name){	bool		have_slash;	char	   *new;	char	   *full;	AssertArg(name);	have_slash = (first_dir_separator(name) != NULL);	if (!have_slash)	{		full = find_in_dynamic_libpath(name);		if (full)			return full;	}	else	{		full = substitute_libpath_macro(name);		if (file_exists(full))			return full;		pfree(full);	}	new = palloc(strlen(name) + strlen(DLSUFFIX) + 1);	strcpy(new, name);	strcat(new, DLSUFFIX);	if (!have_slash)	{		full = find_in_dynamic_libpath(new);		pfree(new);		if (full)			return full;	}	else	{		full = substitute_libpath_macro(new);		pfree(new);		if (file_exists(full))			return full;		pfree(full);	}	/*	 * If we can't find the file, just return the string as-is. The ensuing	 * load attempt will fail and report a suitable message.	 */	return pstrdup(name);}/* * Check a restricted library name.  It must begin with "$libdir/plugins/" * and there must not be any directory separators after that (this is * sufficient to prevent ".." style attacks). */static voidcheck_restricted_library_name(const char *name){	if (strncmp(name, "$libdir/plugins/", 16) != 0 ||		first_dir_separator(name + 16) != NULL)		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("access to library \"%s\" is not allowed",						name)));}/* * Substitute for any macros appearing in the given string. * Result is always freshly palloc'd. */static char *substitute_libpath_macro(const char *name){	const char *sep_ptr;	char	   *ret;	AssertArg(name != NULL);	/* Currently, we only recognize $libdir at the start of the string */	if (name[0] != '$')		return pstrdup(name);	if ((sep_ptr = first_dir_separator(name)) == NULL)		sep_ptr = name + strlen(name);	if (strlen("$libdir") != sep_ptr - name ||		strncmp(name, "$libdir", strlen("$libdir")) != 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_NAME),				 errmsg("invalid macro name in dynamic library path: %s",						name)));	ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);	strcpy(ret, pkglib_path);	strcat(ret, sep_ptr);	return ret;}/* * Search for a file called 'basename' in the colon-separated search * path Dynamic_library_path.  If the file is found, the full file name * is returned in freshly palloc'd memory.  If the file is not found, * return NULL. */static char *find_in_dynamic_libpath(const char *basename){	const char *p;	size_t		baselen;	AssertArg(basename != NULL);	AssertArg(first_dir_separator(basename) == NULL);	AssertState(Dynamic_library_path != NULL);	p = Dynamic_library_path;	if (strlen(p) == 0)		return NULL;	baselen = strlen(basename);	for (;;)	{		size_t		len;		char	   *piece;		char	   *mangled;		char	   *full;		piece = first_path_separator(p);		if (piece == p)			ereport(ERROR,					(errcode(ERRCODE_INVALID_NAME),					 errmsg("zero-length component in parameter \"dynamic_library_path\"")));		if (piece == 0)			len = strlen(p);		else			len = piece - p;		piece = palloc(len + 1);		strlcpy(piece, p, len + 1);		mangled = substitute_libpath_macro(piece);		pfree(piece);		canonicalize_path(mangled);		/* only absolute paths */		if (!is_absolute_path(mangled))			ereport(ERROR,					(errcode(ERRCODE_INVALID_NAME),					 errmsg("component in parameter \"dynamic_library_path\" is not an absolute path")));		full = palloc(strlen(mangled) + 1 + baselen + 1);		sprintf(full, "%s/%s", mangled, basename);		pfree(mangled);		elog(DEBUG3, "find_in_dynamic_libpath: trying \"%s\"", full);		if (file_exists(full))			return full;		pfree(full);		if (p[len] == '\0')			break;		else			p += len + 1;	}	return NULL;}/* * Find (or create) a rendezvous variable that one dynamically * loaded library can use to meet up with another. * * On the first call of this function for a particular varName, * a "rendezvous variable" is created with the given name. * The value of the variable is a void pointer (initially set to NULL). * Subsequent calls with the same varName just return the address of * the existing variable.  Once created, a rendezvous variable lasts * for the life of the process. * * Dynamically loaded libraries can use rendezvous variables * to find each other and share information: they just need to agree * on the variable name and the data it will point to. */void	  **find_rendezvous_variable(const char *varName){	static HTAB *rendezvousHash = NULL;	rendezvousHashEntry *hentry;	bool		found;	/* Create a hashtable if we haven't already done so in this process */	if (rendezvousHash == NULL)	{		HASHCTL		ctl;		MemSet(&ctl, 0, sizeof(ctl));		ctl.keysize = NAMEDATALEN;		ctl.entrysize = sizeof(rendezvousHashEntry);		rendezvousHash = hash_create("Rendezvous variable hash",									 16,									 &ctl,									 HASH_ELEM);	}	/* Find or create the hashtable entry for this varName */	hentry = (rendezvousHashEntry *) hash_search(rendezvousHash,												 varName,												 HASH_ENTER,												 &found);	/* Initialize to NULL if first time */	if (!found)		hentry->varValue = NULL;	return &hentry->varValue;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?