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 + -
显示快捷键?