#include "postgres.h"#include <sys/param.h>#include <signal.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/time.h>#include <fcntl.h>#include <unistd.h>#include <grp.h>#include <pwd.h>#include <netinet/in.h>#include <arpa/inet.h>#include "access/htup_details.h"#include "catalog/pg_authid.h"#include "mb/pg_wchar.h"#include "miscadmin.h"#include "postmaster/autovacuum.h"#include "postmaster/postmaster.h"#include "storage/fd.h"#include "storage/ipc.h"#include "storage/pg_shmem.h"#include "storage/proc.h"#include "storage/procarray.h"#include "utils/builtins.h"#include "utils/guc.h"#include "utils/memutils.h"#include "utils/syscache.h"
Go to the source code of this file.
Defines | |
| #define | DIRECTORY_LOCK_FILE "postmaster.pid" |
Functions | |
| void | SetDatabasePath (const char *path) |
| void | SetDataDir (const char *dir) |
| void | ChangeToDataDir (void) |
| char * | make_absolute_path (const char *path) |
| Oid | GetUserId (void) |
| Oid | GetOuterUserId (void) |
| static void | SetOuterUserId (Oid userid) |
| Oid | GetSessionUserId (void) |
| static void | SetSessionUserId (Oid userid, bool is_superuser) |
| void | GetUserIdAndSecContext (Oid *userid, int *sec_context) |
| void | SetUserIdAndSecContext (Oid userid, int sec_context) |
| bool | InLocalUserIdChange (void) |
| bool | InSecurityRestrictedOperation (void) |
| void | GetUserIdAndContext (Oid *userid, bool *sec_def_context) |
| void | SetUserIdAndContext (Oid userid, bool sec_def_context) |
| bool | has_rolreplication (Oid roleid) |
| void | InitializeSessionUserId (const char *rolename) |
| void | InitializeSessionUserIdStandalone (void) |
| void | SetSessionAuthorization (Oid userid, bool is_superuser) |
| Oid | GetCurrentRoleId (void) |
| void | SetCurrentRoleId (Oid roleid, bool is_superuser) |
| char * | GetUserNameFromId (Oid roleid) |
| static void | UnlinkLockFiles (int status, Datum arg) |
| static void | CreateLockFile (const char *filename, bool amPostmaster, const char *socketDir, bool isDDLock, const char *refName) |
| void | CreateDataDirLockFile (bool amPostmaster) |
| void | CreateSocketLockFile (const char *socketfile, bool amPostmaster, const char *socketDir) |
| void | TouchSocketLockFiles (void) |
| void | AddToDataDirLockFile (int target_line, const char *str) |
| void | ValidatePgVersion (const char *path) |
| static void | load_libraries (const char *libraries, const char *gucname, bool restricted) |
| void | process_shared_preload_libraries (void) |
| void | process_local_preload_libraries (void) |
| void | pg_bindtextdomain (const char *domain) |
Variables | |
| ProcessingMode | Mode = InitProcessing |
| static List * | lock_files = NIL |
| bool | IgnoreSystemIndexes = false |
| static Oid | AuthenticatedUserId = InvalidOid |
| static Oid | SessionUserId = InvalidOid |
| static Oid | OuterUserId = InvalidOid |
| static Oid | CurrentUserId = InvalidOid |
| static bool | AuthenticatedUserIsSuperuser = false |
| static bool | SessionUserIsSuperuser = false |
| static int | SecurityRestrictionContext = 0 |
| static bool | SetRoleIsActive = false |
| char * | shared_preload_libraries_string = NULL |
| char * | local_preload_libraries_string = NULL |
| bool | process_shared_preload_libraries_in_progress = false |
| #define DIRECTORY_LOCK_FILE "postmaster.pid" |
Definition at line 49 of file miscinit.c.
Referenced by AddToDataDirLockFile(), CreateDataDirLockFile(), and TouchSocketLockFiles().
| void AddToDataDirLockFile | ( | int | target_line, | |
| const char * | str | |||
| ) |
Definition at line 1048 of file miscinit.c.
References close, DIRECTORY_LOCK_FILE, elog, ereport, errcode_for_file_access(), errmsg(), LOG, NULL, PG_BINARY, pg_fsync(), read, snprintf(), and write.
{
int fd;
int len;
int lineno;
char *srcptr;
char *destptr;
char srcbuffer[BLCKSZ];
char destbuffer[BLCKSZ];
fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
if (fd < 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
return;
}
len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
if (len < 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not read from file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
close(fd);
return;
}
srcbuffer[len] = '\0';
/*
* Advance over lines we are not supposed to rewrite, then copy them
* to destbuffer.
*/
srcptr = srcbuffer;
for (lineno = 1; lineno < target_line; lineno++)
{
if ((srcptr = strchr(srcptr, '\n')) == NULL)
{
elog(LOG, "incomplete data in \"%s\": found only %d newlines while trying to add line %d",
DIRECTORY_LOCK_FILE, lineno - 1, target_line);
close(fd);
return;
}
srcptr++;
}
memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
destptr = destbuffer + (srcptr - srcbuffer);
/*
* Write or rewrite the target line.
*/
snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
destptr += strlen(destptr);
/*
* If there are more lines in the old file, append them to destbuffer.
*/
if ((srcptr = strchr(srcptr, '\n')) != NULL)
{
srcptr++;
snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
srcptr);
}
/*
* And rewrite the data. Since we write in a single kernel call, this
* update should appear atomic to onlookers.
*/
len = strlen(destbuffer);
errno = 0;
if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
(int) write(fd, destbuffer, len) != len)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)
errno = ENOSPC;
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
close(fd);
return;
}
if (pg_fsync(fd) != 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
}
if (close(fd) != 0)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m",
DIRECTORY_LOCK_FILE)));
}
}
| void ChangeToDataDir | ( | void | ) |
Definition at line 109 of file miscinit.c.
References AssertState, DataDir, ereport, errcode_for_file_access(), errmsg(), and FATAL.
Referenced by AuxiliaryProcessMain(), PostgresMain(), and PostmasterMain().
{
AssertState(DataDir);
if (chdir(DataDir) < 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not change directory to \"%s\": %m",
DataDir)));
}
| void CreateDataDirLockFile | ( | bool | amPostmaster | ) |
Definition at line 972 of file miscinit.c.
References CreateLockFile(), DataDir, and DIRECTORY_LOCK_FILE.
Referenced by AuxiliaryProcessMain(), PostgresMain(), and PostmasterMain().
{
CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, "", true, DataDir);
}
| static void CreateLockFile | ( | const char * | filename, | |
| bool | amPostmaster, | |||
| const char * | socketDir, | |||
| bool | isDDLock, | |||
| const char * | refName | |||
| ) | [static] |
Definition at line 671 of file miscinit.c.
References close, DataDir, elog, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), FATAL, lappend(), MAXPGPATH, MyStartTime, NIL, NULL, on_proc_exit(), pg_fsync(), PGSharedMemoryIsInUse(), PostPortNumber, pstrdup(), read, snprintf(), strlcat(), unlink(), UnlinkLockFiles(), and write.
Referenced by CreateDataDirLockFile(), and CreateSocketLockFile().
{
int fd;
char buffer[MAXPGPATH * 2 + 256];
int ntries;
int len;
int encoded_pid;
pid_t other_pid;
pid_t my_pid,
my_p_pid,
my_gp_pid;
const char *envvar;
/*
* If the PID in the lockfile is our own PID or our parent's or
* grandparent's PID, then the file must be stale (probably left over from
* a previous system boot cycle). We need to check this because of the
* likelihood that a reboot will assign exactly the same PID as we had in
* the previous reboot, or one that's only one or two counts larger and
* hence the lockfile's PID now refers to an ancestor shell process. We
* allow pg_ctl to pass down its parent shell PID (our grandparent PID)
* via the environment variable PG_GRANDPARENT_PID; this is so that
* launching the postmaster via pg_ctl can be just as reliable as
* launching it directly. There is no provision for detecting
* further-removed ancestor processes, but if the init script is written
* carefully then all but the immediate parent shell will be root-owned
* processes and so the kill test will fail with EPERM. Note that we
* cannot get a false negative this way, because an existing postmaster
* would surely never launch a competing postmaster or pg_ctl process
* directly.
*/
my_pid = getpid();
#ifndef WIN32
my_p_pid = getppid();
#else
/*
* Windows hasn't got getppid(), but doesn't need it since it's not using
* real kill() either...
*/
my_p_pid = 0;
#endif
envvar = getenv("PG_GRANDPARENT_PID");
if (envvar)
my_gp_pid = atoi(envvar);
else
my_gp_pid = 0;
/*
* We need a loop here because of race conditions. But don't loop forever
* (for example, a non-writable $PGDATA directory might cause a failure
* that won't go away). 100 tries seems like plenty.
*/
for (ntries = 0;; ntries++)
{
/*
* Try to create the lock file --- O_EXCL makes this atomic.
*
* Think not to make the file protection weaker than 0600. See
* comments below.
*/
fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0)
break; /* Success; exit the retry loop */
/*
* Couldn't create the pid file. Probably it already exists.
*/
if ((errno != EEXIST && errno != EACCES) || ntries > 100)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not create lock file \"%s\": %m",
filename)));
/*
* Read the file to get the old owner's PID. Note race condition
* here: file might have been deleted since we tried to create it.
*/
fd = open(filename, O_RDONLY, 0600);
if (fd < 0)
{
if (errno == ENOENT)
continue; /* race condition; try again */
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open lock file \"%s\": %m",
filename)));
}
if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read lock file \"%s\": %m",
filename)));
close(fd);
if (len == 0)
{
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("lock file \"%s\" is empty", filename),
errhint("Either another server is starting, or the lock file is the remnant of a previous server startup crash.")));
}
buffer[len] = '\0';
encoded_pid = atoi(buffer);
/* if pid < 0, the pid is for postgres, not postmaster */
other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid);
if (other_pid <= 0)
elog(FATAL, "bogus data in lock file \"%s\": \"%s\"",
filename, buffer);
/*
* Check to see if the other process still exists
*
* Per discussion above, my_pid, my_p_pid, and my_gp_pid can be
* ignored as false matches.
*
* Normally kill() will fail with ESRCH if the given PID doesn't
* exist.
*
* We can treat the EPERM-error case as okay because that error
* implies that the existing process has a different userid than we
* do, which means it cannot be a competing postmaster. A postmaster
* cannot successfully attach to a data directory owned by a userid
* other than its own. (This is now checked directly in
* checkDataDir(), but has been true for a long time because of the
* restriction that the data directory isn't group- or
* world-accessible.) Also, since we create the lockfiles mode 600,
* we'd have failed above if the lockfile belonged to another userid
* --- which means that whatever process kill() is reporting about
* isn't the one that made the lockfile. (NOTE: this last
* consideration is the only one that keeps us from blowing away a
* Unix socket file belonging to an instance of Postgres being run by
* someone else, at least on machines where /tmp hasn't got a
* stickybit.)
*/
if (other_pid != my_pid && other_pid != my_p_pid &&
other_pid != my_gp_pid)
{
if (kill(other_pid, 0) == 0 ||
(errno != ESRCH && errno != EPERM))
{
/* lockfile belongs to a live process */
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("lock file \"%s\" already exists",
filename),
isDDLock ?
(encoded_pid < 0 ?
errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
(int) other_pid, refName) :
errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
(int) other_pid, refName)) :
(encoded_pid < 0 ?
errhint("Is another postgres (PID %d) using socket file \"%s\"?",
(int) other_pid, refName) :
errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
(int) other_pid, refName))));
}
}
/*
* No, the creating process did not exist. However, it could be that
* the postmaster crashed (or more likely was kill -9'd by a clueless
* admin) but has left orphan backends behind. Check for this by
* looking to see if there is an associated shmem segment that is
* still in use.
*
* Note: because postmaster.pid is written in multiple steps, we might
* not find the shmem ID values in it; we can't treat that as an
* error.
*/
if (isDDLock)
{
char *ptr = buffer;
unsigned long id1,
id2;
int lineno;
for (lineno = 1; lineno < LOCK_FILE_LINE_SHMEM_KEY; lineno++)
{
if ((ptr = strchr(ptr, '\n')) == NULL)
break;
ptr++;
}
if (ptr != NULL &&
sscanf(ptr, "%lu %lu", &id1, &id2) == 2)
{
if (PGSharedMemoryIsInUse(id1, id2))
ereport(FATAL,
(errcode(ERRCODE_LOCK_FILE_EXISTS),
errmsg("pre-existing shared memory block "
"(key %lu, ID %lu) is still in use",
id1, id2),
errhint("If you're sure there are no old "
"server processes still running, remove "
"the shared memory block "
"or just delete the file \"%s\".",
filename)));
}
}
/*
* Looks like nobody's home. Unlink the file and try again to create
* it. Need a loop because of possible race condition against other
* would-be creators.
*/
if (unlink(filename) < 0)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not remove old lock file \"%s\": %m",
filename),
errhint("The file seems accidentally left over, but "
"it could not be removed. Please remove the file "
"by hand and try again.")));
}
/*
* Successfully created the file, now fill it. See comment in miscadmin.h
* about the contents. Note that we write the same first five lines into
* both datadir and socket lockfiles; although more stuff may get added to
* the datadir lockfile later.
*/
snprintf(buffer, sizeof(buffer), "%d\n%s\n%ld\n%d\n%s\n",
amPostmaster ? (int) my_pid : -((int) my_pid),
DataDir,
(long) MyStartTime,
PostPortNumber,
socketDir);
/*
* In a standalone backend, the next line (LOCK_FILE_LINE_LISTEN_ADDR)
* will never receive data, so fill it in as empty now.
*/
if (isDDLock && !amPostmaster)
strlcat(buffer, "\n", sizeof(buffer));
errno = 0;
if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
{
int save_errno = errno;
close(fd);
unlink(filename);
/* if write didn't set errno, assume problem is no disk space */
errno = save_errno ? save_errno : ENOSPC;
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write lock file \"%s\": %m", filename)));
}
if (pg_fsync(fd) != 0)
{
int save_errno = errno;
close(fd);
unlink(filename);
errno = save_errno;
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write lock file \"%s\": %m", filename)));
}
if (close(fd) != 0)
{
int save_errno = errno;
unlink(filename);
errno = save_errno;
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not write lock file \"%s\": %m", filename)));
}
/*
* Arrange to unlink the lock file(s) at proc_exit. If this is the
* first one, set up the on_proc_exit function to do it; then add this
* lock file to the list of files to unlink.
*/
if (lock_files == NIL)
on_proc_exit(UnlinkLockFiles, 0);
lock_files = lappend(lock_files, pstrdup(filename));
}
| void CreateSocketLockFile | ( | const char * | socketfile, | |
| bool | amPostmaster, | |||
| const char * | socketDir | |||
| ) |
Definition at line 981 of file miscinit.c.
References CreateLockFile(), and snprintf().
{
char lockfile[MAXPGPATH];
snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
CreateLockFile(lockfile, amPostmaster, socketDir, false, socketfile);
}
| Oid GetCurrentRoleId | ( | void | ) |
Definition at line 555 of file miscinit.c.
References OuterUserId, and SetRoleIsActive.
Referenced by show_role().
{
if (SetRoleIsActive)
return OuterUserId;
else
return InvalidOid;
}
| Oid GetOuterUserId | ( | void | ) |
Definition at line 252 of file miscinit.c.
References AssertState, OidIsValid, and OuterUserId.
Referenced by DropRole(), and RenameRole().
{
AssertState(OidIsValid(OuterUserId));
return OuterUserId;
}
| Oid GetSessionUserId | ( | void | ) |
Definition at line 275 of file miscinit.c.
References AssertState, OidIsValid, and SessionUserId.
Referenced by check_role(), DropRole(), InitPostgres(), pgstat_bestart(), RenameRole(), and session_user().
{
AssertState(OidIsValid(SessionUserId));
return SessionUserId;
}
| Oid GetUserId | ( | void | ) |
Definition at line 241 of file miscinit.c.
References AssertState, CurrentUserId, and OidIsValid.
Referenced by AddRoleMems(), AggregateCreate(), AlterDatabase(), AlterDatabaseOwner(), AlterDatabaseSet(), AlterEventTrigger(), AlterEventTriggerOwner_internal(), AlterExtensionNamespace(), AlterForeignServer(), AlterForeignServerOwner_internal(), AlterFunction(), AlterObjectNamespace_internal(), AlterObjectOwner_internal(), AlterObjectRename_internal(), AlterOpFamilyAdd(), AlterRole(), AlterRoleSet(), AlterSchemaOwner_internal(), AlterSequence(), AlterTableSpaceOptions(), AlterTSConfiguration(), AlterTSDictionary(), AlterTypeNamespace_oid(), AlterTypeOwner(), analyze_rel(), ATExecAddColumn(), ATExecChangeOwner(), ATPrepAlterColumnType(), ATPrepSetStatistics(), ATPrepSetTableSpace(), ATSimplePermissions(), BuildDescForRelation(), calculate_database_size(), calculate_tablespace_size(), check_temp_tablespaces(), checkDomainOwner(), checkEnumOwner(), checkFkeyPermissions(), CheckMyDatabase(), CheckRelationOwnership(), cluster_rel(), CommentObject(), compile_plperl_function(), compile_pltcl_function(), compute_return_type(), create_empty_extension(), CreateCast(), CreateConversionCommand(), createdb(), CreateEventTrigger(), CreateExtension(), CreateForeignDataWrapper(), CreateForeignServer(), CreateForeignTable(), CreateFunction(), CreateOpFamily(), CreateProceduralLanguage(), CreateRole(), CreateTableSpace(), CreateTrigger(), current_user(), currtid_byrelname(), currtid_byreloid(), currval_oid(), DefineAggregate(), DefineCollation(), DefineDomain(), DefineEnum(), DefineIndex(), DefineOpClass(), DefineOperator(), DefineOpFamily(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineTSConfiguration(), DefineTSDictionary(), DefineType(), DelRoleMems(), do_pg_start_backup(), do_pg_stop_backup(), do_setval(), dropdb(), DropOwnedObjects(), DropRole(), DropTableSpace(), EnableDisableRule(), examine_parameter_list(), ExecAlterDefaultPrivilegesStmt(), ExecAlterExtensionContentsStmt(), ExecAlterExtensionStmt(), ExecCheckRTEPerms(), ExecEvalArrayCoerceExpr(), ExecGrant_Attribute(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), ExecInitAgg(), ExecInitWindowAgg(), ExecSecLabelStmt(), ExecuteDoStmt(), ExecuteTruncate(), findRangeCanonicalFunction(), findRangeSubtypeDiffFunction(), FinishPreparedTransaction(), get_connect_string(), get_other_operator(), get_rel_from_relname(), get_tables_to_cluster(), GetUserOidFromMapping(), GrantRole(), HandleFunctionRequest(), has_any_column_privilege_id(), has_any_column_privilege_name(), has_column_privilege_id_attnum(), has_column_privilege_id_name(), has_column_privilege_name_attnum(), has_column_privilege_name_name(), has_database_privilege_id(), has_database_privilege_name(), has_foreign_data_wrapper_privilege_id(), has_foreign_data_wrapper_privilege_name(), has_function_privilege_id(), has_function_privilege_name(), has_language_privilege_id(), has_language_privilege_name(), has_schema_privilege_id(), has_schema_privilege_name(), has_sequence_privilege_id(), has_sequence_privilege_name(), has_server_privilege_id(), has_server_privilege_name(), has_table_privilege_id(), has_table_privilege_name(), has_tablespace_privilege_id(), has_tablespace_privilege_name(), has_type_privilege_id(), has_type_privilege_name(), have_createdb_privilege(), have_createrole_privilege(), init_fcache(), InitializeSearchPath(), InitPostgres(), InitTempTableNamespace(), inline_function(), inline_set_returning_function(), insert_username(), inv_create(), LargeObjectCreate(), lastval(), lo_read(), lo_truncate_internal(), lo_unlink(), lo_write(), LockTableAclCheck(), lookup_agg_function(), LookupCreationNamespace(), LookupExplicitNamespace(), MergeAttributes(), movedb(), nextval_internal(), OperatorCreate(), OperatorShellMake(), pg_has_role_id(), pg_has_role_name(), pg_sequence_parameters(), pg_signal_backend(), pg_stat_get_activity(), pg_stat_get_backend_activity(), pg_stat_get_backend_activity_start(), pg_stat_get_backend_client_addr(), pg_stat_get_backend_client_port(), pg_stat_get_backend_start(), pg_stat_get_backend_waiting(), pg_stat_get_backend_xact_start(), pg_stat_statements(), pgrowlocks(), pgss_store(), pgstat_get_backend_current_activity(), pltcl_fetch_interp(), postgresBeginForeignModify(), postgresBeginForeignScan(), postgresGetForeignRelSize(), PrepareTempTablespaces(), PrepareTransaction(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForReindexIndex(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsTable(), RangeVarGetAndCheckCreationNamespace(), ReassignOwnedObjects(), recomputeNamespacePath(), ReindexDatabase(), RemoveObjects(), renameatt_check(), RenameDatabase(), RenameSchema(), RenameTableSpace(), RenameType(), select_perl_context(), superuser(), timetravel(), transformTableLikeClause(), truncate_check_rel(), user_mapping_ddl_aclcheck(), and vacuum_rel().
{
AssertState(OidIsValid(CurrentUserId));
return CurrentUserId;
}
Definition at line 369 of file miscinit.c.
References CurrentUserId, and InLocalUserIdChange().
{
*userid = CurrentUserId;
*sec_def_context = InLocalUserIdChange();
}
| void GetUserIdAndSecContext | ( | Oid * | userid, | |
| int * | sec_context | |||
| ) |
Definition at line 329 of file miscinit.c.
References CurrentUserId, and SecurityRestrictionContext.
Referenced by CreateSchemaCommand(), do_analyze_rel(), fmgr_security_definer(), index_build(), PushTransaction(), ri_PerformCheck(), ri_PlanCheck(), StartTransaction(), vacuum_rel(), and validate_index().
{
*userid = CurrentUserId;
*sec_context = SecurityRestrictionContext;
}
| char* GetUserNameFromId | ( | Oid | roleid | ) |
Definition at line 610 of file miscinit.c.
References AUTHOID, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, pstrdup(), ReleaseSysCache(), and SearchSysCache1.
Referenced by check_is_member_of_role(), current_user(), getObjectDescription(), getObjectIdentity(), insert_username(), session_user(), and timetravel().
{
HeapTuple tuple;
char *result;
tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("invalid role OID: %u", roleid)));
result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
ReleaseSysCache(tuple);
return result;
}
Definition at line 396 of file miscinit.c.
References AUTHOID, GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), and SearchSysCache1.
Referenced by do_pg_start_backup(), do_pg_stop_backup(), and InitPostgres().
{
bool result = false;
HeapTuple utup;
utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
if (HeapTupleIsValid(utup))
{
result = ((Form_pg_authid) GETSTRUCT(utup))->rolreplication;
ReleaseSysCache(utup);
}
return result;
}
| void InitializeSessionUserId | ( | const char * | rolename | ) |
Definition at line 414 of file miscinit.c.
References AssertState, AuthenticatedUserId, AuthenticatedUserIsSuperuser, AUTHNAME, CountUserBackends(), ereport, errcode(), errmsg(), FATAL, GETSTRUCT, HeapTupleGetOid, HeapTupleIsValid, IsBootstrapProcessingMode, IsUnderPostmaster, MyProc, OidIsValid, PGC_BACKEND, PGC_INTERNAL, PGC_S_OVERRIDE, PointerGetDatum, ReleaseSysCache(), PGPROC::roleId, SearchSysCache1, SetConfigOption(), and SetSessionUserId().
Referenced by InitPostgres().
{
HeapTuple roleTup;
Form_pg_authid rform;
Oid roleid;
/*
* Don't do scans if we're bootstrapping, none of the system catalogs
* exist yet, and they should be owned by postgres anyway.
*/
AssertState(!IsBootstrapProcessingMode());
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
if (!HeapTupleIsValid(roleTup))
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role \"%s\" does not exist", rolename)));
rform = (Form_pg_authid) GETSTRUCT(roleTup);
roleid = HeapTupleGetOid(roleTup);
AuthenticatedUserId = roleid;
AuthenticatedUserIsSuperuser = rform->rolsuper;
/* This sets OuterUserId/CurrentUserId too */
SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
/* Also mark our PGPROC entry with the authenticated user id */
/* (We assume this is an atomic store so no lock is needed) */
MyProc->roleId = roleid;
/*
* These next checks are not enforced when in standalone mode, so that
* there is a way to recover from sillinesses like "UPDATE pg_authid SET
* rolcanlogin = false;".
*/
if (IsUnderPostmaster)
{
/*
* Is role allowed to login at all?
*/
if (!rform->rolcanlogin)
ereport(FATAL,
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
errmsg("role \"%s\" is not permitted to log in",
rolename)));
/*
* Check connection limit for this role.
*
* There is a race condition here --- we create our PGPROC before
* checking for other PGPROCs. If two backends did this at about the
* same time, they might both think they were over the limit, while
* ideally one should succeed and one fail. Getting that to work
* exactly seems more trouble than it is worth, however; instead we
* just document that the connection limit is approximate.
*/
if (rform->rolconnlimit >= 0 &&
!AuthenticatedUserIsSuperuser &&
CountUserBackends(roleid) > rform->rolconnlimit)
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("too many connections for role \"%s\"",
rolename)));
}
/* Record username and superuser status as GUC settings too */
SetConfigOption("session_authorization", rolename,
PGC_BACKEND, PGC_S_OVERRIDE);
SetConfigOption("is_superuser",
AuthenticatedUserIsSuperuser ? "on" : "off",
PGC_INTERNAL, PGC_S_OVERRIDE);
ReleaseSysCache(roleTup);
}
| void InitializeSessionUserIdStandalone | ( | void | ) |
Definition at line 498 of file miscinit.c.
References AssertState, AuthenticatedUserId, AuthenticatedUserIsSuperuser, BOOTSTRAP_SUPERUSERID, IsAutoVacuumWorkerProcess(), IsBackgroundWorker, IsUnderPostmaster, OidIsValid, and SetSessionUserId().
Referenced by InitPostgres().
{
/*
* This function should only be called in single-user mode, in
* autovacuum workers, and in background workers.
*/
AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsBackgroundWorker);
/* call only once */
AssertState(!OidIsValid(AuthenticatedUserId));
AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
AuthenticatedUserIsSuperuser = true;
SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
}
| bool InLocalUserIdChange | ( | void | ) |
Definition at line 347 of file miscinit.c.
References SECURITY_LOCAL_USERID_CHANGE, and SecurityRestrictionContext.
Referenced by GetUserIdAndContext(), and set_config_option().
{
return (SecurityRestrictionContext & SECURITY_LOCAL_USERID_CHANGE) != 0;
}
| bool InSecurityRestrictedOperation | ( | void | ) |
Definition at line 356 of file miscinit.c.
References SECURITY_RESTRICTED_OPERATION, and SecurityRestrictionContext.
Referenced by CheckRestrictedOperation(), DefineRelation(), set_config_option(), and SetUserIdAndContext().
{
return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
}
| static void load_libraries | ( | const char * | libraries, | |
| const char * | gucname, | |||
| bool | restricted | |||
| ) | [static] |
Definition at line 1238 of file miscinit.c.
References canonicalize_path(), elevel, ereport, errcode(), errmsg(), filename, first_dir_separator(), IsUnderPostmaster, lfirst, list_free(), load_file(), LOG, NULL, palloc(), pfree(), process_shared_preload_libraries_in_progress, pstrdup(), and SplitIdentifierString().
Referenced by process_local_preload_libraries(), and process_shared_preload_libraries().
{
char *rawstring;
List *elemlist;
int elevel;
ListCell *l;
if (libraries == NULL || libraries[0] == '\0')
return; /* nothing to do */
/* Need a modifiable copy of string */
rawstring = pstrdup(libraries);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawstring, ',', &elemlist))
{
/* syntax error in list */
pfree(rawstring);
list_free(elemlist);
ereport(LOG,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid list syntax in parameter \"%s\"",
gucname)));
return;
}
/*
* Choose notice level: avoid repeat messages when re-loading a library
* that was preloaded into the postmaster. (Only possible in EXEC_BACKEND
* configurations)
*/
#ifdef EXEC_BACKEND
if (IsUnderPostmaster && process_shared_preload_libraries_in_progress)
elevel = DEBUG2;
else
#endif
elevel = LOG;
foreach(l, elemlist)
{
char *tok = (char *) lfirst(l);
char *filename;
filename = pstrdup(tok);
canonicalize_path(filename);
/* If restricting, insert $libdir/plugins if not mentioned already */
if (restricted && first_dir_separator(filename) == NULL)
{
char *expanded;
expanded = palloc(strlen("$libdir/plugins/") + strlen(filename) + 1);
strcpy(expanded, "$libdir/plugins/");
strcat(expanded, filename);
pfree(filename);
filename = expanded;
}
load_file(filename, restricted);
ereport(elevel,
(errmsg("loaded library \"%s\"", filename)));
pfree(filename);
}
pfree(rawstring);
list_free(elemlist);
}
| char* make_absolute_path | ( | const char * | path | ) |
Definition at line 131 of file miscinit.c.
References buf, canonicalize_path(), elog, ereport, errcode(), errmsg(), FATAL, free, is_absolute_path, malloc, and NULL.
Referenced by regression_main(), SelectConfigFiles(), and SetDataDir().
{
char *new;
/* Returning null for null input is convenient for some callers */
if (path == NULL)
return NULL;
if (!is_absolute_path(path))
{
char *buf;
size_t buflen;
buflen = MAXPGPATH;
for (;;)
{
buf = malloc(buflen);
if (!buf)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
if (getcwd(buf, buflen))
break;
else if (errno == ERANGE)
{
free(buf);
buflen *= 2;
continue;
}
else
{
free(buf);
elog(FATAL, "could not get current working directory: %m");
}
}
new = malloc(strlen(buf) + strlen(path) + 2);
if (!new)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
sprintf(new, "%s/%s", buf, path);
free(buf);
}
else
{
new = strdup(path);
if (!new)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
}
/* Make sure punctuation is canonical, too */
canonicalize_path(new);
return new;
}
| void pg_bindtextdomain | ( | const char * | domain | ) |
Definition at line 1329 of file miscinit.c.
References get_locale_path(), my_exec_path, and pg_bind_textdomain_codeset().
Referenced by _PG_init().
{
#ifdef ENABLE_NLS
if (my_exec_path[0] != '\0')
{
char locale_path[MAXPGPATH];
get_locale_path(my_exec_path, locale_path);
bindtextdomain(domain, locale_path);
pg_bind_textdomain_codeset(domain);
}
#endif
}
| void process_local_preload_libraries | ( | void | ) |
Definition at line 1321 of file miscinit.c.
References load_libraries(), and local_preload_libraries_string.
Referenced by PostgresMain().
{
load_libraries(local_preload_libraries_string,
"local_preload_libraries",
true);
}
| void process_shared_preload_libraries | ( | void | ) |
Definition at line 1308 of file miscinit.c.
References load_libraries(), process_shared_preload_libraries_in_progress, and shared_preload_libraries_string.
Referenced by PostmasterMain().
{
process_shared_preload_libraries_in_progress = true;
load_libraries(shared_preload_libraries_string,
"shared_preload_libraries",
false);
process_shared_preload_libraries_in_progress = false;
}
Definition at line 576 of file miscinit.c.
References OidIsValid, PGC_INTERNAL, PGC_S_OVERRIDE, SessionUserId, SessionUserIsSuperuser, SetConfigOption(), SetOuterUserId(), and SetRoleIsActive.
Referenced by assign_role().
{
/*
* Get correct info if it's SET ROLE NONE
*
* If SessionUserId hasn't been set yet, just do nothing --- the eventual
* SetSessionUserId call will fix everything. This is needed since we
* will get called during GUC initialization.
*/
if (!OidIsValid(roleid))
{
if (!OidIsValid(SessionUserId))
return;
roleid = SessionUserId;
is_superuser = SessionUserIsSuperuser;
SetRoleIsActive = false;
}
else
SetRoleIsActive = true;
SetOuterUserId(roleid);
SetConfigOption("is_superuser",
is_superuser ? "on" : "off",
PGC_INTERNAL, PGC_S_OVERRIDE);
}
| void SetDatabasePath | ( | const char * | path | ) |
Definition at line 76 of file miscinit.c.
References Assert, DatabasePath, MemoryContextStrdup(), and TopMemoryContext.
Referenced by InitPostgres().
{
/* This should happen only once per process */
Assert(!DatabasePath);
DatabasePath = MemoryContextStrdup(TopMemoryContext, path);
}
| void SetDataDir | ( | const char * | dir | ) |
Definition at line 88 of file miscinit.c.
References AssertArg, DataDir, free, and make_absolute_path().
Referenced by SelectConfigFiles().
| static void SetOuterUserId | ( | Oid | userid | ) | [static] |
Definition at line 260 of file miscinit.c.
References AssertArg, AssertState, CurrentUserId, OidIsValid, OuterUserId, and SecurityRestrictionContext.
Referenced by SetCurrentRoleId().
{
AssertState(SecurityRestrictionContext == 0);
AssertArg(OidIsValid(userid));
OuterUserId = userid;
/* We force the effective user ID to match, too */
CurrentUserId = userid;
}
Definition at line 530 of file miscinit.c.
References AssertState, AuthenticatedUserId, AuthenticatedUserIsSuperuser, ereport, errcode(), errmsg(), ERROR, OidIsValid, PGC_INTERNAL, PGC_S_OVERRIDE, SetConfigOption(), and SetSessionUserId().
Referenced by assign_session_authorization().
{
/* Must have authenticated already, else can't make permission check */
AssertState(OidIsValid(AuthenticatedUserId));
if (userid != AuthenticatedUserId &&
!AuthenticatedUserIsSuperuser)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set session authorization")));
SetSessionUserId(userid, is_superuser);
SetConfigOption("is_superuser",
is_superuser ? "on" : "off",
PGC_INTERNAL, PGC_S_OVERRIDE);
}
Definition at line 283 of file miscinit.c.
References AssertArg, AssertState, CurrentUserId, OidIsValid, OuterUserId, SecurityRestrictionContext, SessionUserId, SessionUserIsSuperuser, and SetRoleIsActive.
Referenced by InitializeSessionUserId(), InitializeSessionUserIdStandalone(), and SetSessionAuthorization().
{
AssertState(SecurityRestrictionContext == 0);
AssertArg(OidIsValid(userid));
SessionUserId = userid;
SessionUserIsSuperuser = is_superuser;
SetRoleIsActive = false;
/* We force the effective user IDs to match, too */
OuterUserId = userid;
CurrentUserId = userid;
}
Definition at line 376 of file miscinit.c.
References CurrentUserId, ereport, errcode(), errmsg(), ERROR, InSecurityRestrictedOperation(), and SecurityRestrictionContext.
{
/* We throw the same error SET ROLE would. */
if (InSecurityRestrictedOperation())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("cannot set parameter \"%s\" within security-restricted operation",
"role")));
CurrentUserId = userid;
if (sec_def_context)
SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE;
else
SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
}
| void SetUserIdAndSecContext | ( | Oid | userid, | |
| int | sec_context | |||
| ) |
Definition at line 336 of file miscinit.c.
References CurrentUserId, and SecurityRestrictionContext.
Referenced by AbortSubTransaction(), AbortTransaction(), CreateSchemaCommand(), do_analyze_rel(), fmgr_security_definer(), index_build(), ri_PerformCheck(), ri_PlanCheck(), vacuum_rel(), and validate_index().
{
CurrentUserId = userid;
SecurityRestrictionContext = sec_context;
}
| void TouchSocketLockFiles | ( | void | ) |
Definition at line 999 of file miscinit.c.
References close, DIRECTORY_LOCK_FILE, lfirst, NULL, PG_BINARY, and read.
Referenced by ServerLoop().
{
ListCell *l;
foreach(l, lock_files)
{
char *socketLockFile = (char *) lfirst(l);
/* No need to touch the data directory lock file, we trust */
if (strcmp(socketLockFile, DIRECTORY_LOCK_FILE) == 0)
continue;
/*
* utime() is POSIX standard, utimes() is a common alternative; if we
* have neither, fall back to actually reading the file (which only
* sets the access time not mod time, but that should be enough in
* most cases). In all paths, we ignore errors.
*/
#ifdef HAVE_UTIME
utime(socketLockFile, NULL);
#else /* !HAVE_UTIME */
#ifdef HAVE_UTIMES
utimes(socketLockFile, NULL);
#else /* !HAVE_UTIMES */
int fd;
char buffer[1];
fd = open(socketLockFile, O_RDONLY | PG_BINARY, 0);
if (fd >= 0)
{
read(fd, buffer, sizeof(buffer));
close(fd);
}
#endif /* HAVE_UTIMES */
#endif /* HAVE_UTIME */
}
}
| static void UnlinkLockFiles | ( | int | status, | |
| Datum | arg | |||
| ) | [static] |
Definition at line 647 of file miscinit.c.
References lfirst, and unlink().
Referenced by CreateLockFile().
{
ListCell *l;
foreach(l, lock_files)
{
char *curfile = (char *) lfirst(l);
unlink(curfile);
/* Should we complain if the unlink fails? */
}
/* Since we're about to exit, no need to reclaim storage */
lock_files = NIL;
}
| void ValidatePgVersion | ( | const char * | path | ) |
Definition at line 1162 of file miscinit.c.
References AllocateFile(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), FATAL, FreeFile(), NULL, and snprintf().
Referenced by AuxiliaryProcessMain(), checkDataDir(), InitPostgres(), and PostgresMain().
{
char full_path[MAXPGPATH];
FILE *file;
int ret;
long file_major,
file_minor;
long my_major = 0,
my_minor = 0;
char *endptr;
const char *version_string = PG_VERSION;
my_major = strtol(version_string, &endptr, 10);
if (*endptr == '.')
my_minor = strtol(endptr + 1, NULL, 10);
snprintf(full_path, sizeof(full_path), "%s/PG_VERSION", path);
file = AllocateFile(full_path, "r");
if (!file)
{
if (errno == ENOENT)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a valid data directory",
path),
errdetail("File \"%s\" is missing.", full_path)));
else
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", full_path)));
}
ret = fscanf(file, "%ld.%ld", &file_major, &file_minor);
if (ret != 2)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" is not a valid data directory",
path),
errdetail("File \"%s\" does not contain valid data.",
full_path),
errhint("You might need to initdb.")));
FreeFile(file);
if (my_major != file_major || my_minor != file_minor)
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("database files are incompatible with server"),
errdetail("The data directory was initialized by PostgreSQL version %ld.%ld, "
"which is not compatible with this version %s.",
file_major, file_minor, version_string)));
}
Oid AuthenticatedUserId = InvalidOid [static] |
Definition at line 220 of file miscinit.c.
Referenced by InitializeSessionUserId(), InitializeSessionUserIdStandalone(), and SetSessionAuthorization().
bool AuthenticatedUserIsSuperuser = false [static] |
Definition at line 226 of file miscinit.c.
Referenced by InitializeSessionUserId(), InitializeSessionUserIdStandalone(), and SetSessionAuthorization().
Oid CurrentUserId = InvalidOid [static] |
Definition at line 223 of file miscinit.c.
Referenced by GetUserId(), GetUserIdAndContext(), GetUserIdAndSecContext(), SetOuterUserId(), SetSessionUserId(), SetUserIdAndContext(), and SetUserIdAndSecContext().
| bool IgnoreSystemIndexes = false |
Definition at line 67 of file miscinit.c.
Referenced by AuxiliaryProcessMain(), get_relation_info(), systable_beginscan(), and systable_beginscan_ordered().
| char* local_preload_libraries_string = NULL |
Definition at line 1226 of file miscinit.c.
Referenced by process_local_preload_libraries().
List* lock_files = NIL [static] |
Definition at line 54 of file miscinit.c.
| ProcessingMode Mode = InitProcessing |
Definition at line 51 of file miscinit.c.
Oid OuterUserId = InvalidOid [static] |
Definition at line 222 of file miscinit.c.
Referenced by GetCurrentRoleId(), GetOuterUserId(), SetOuterUserId(), and SetSessionUserId().
Definition at line 1229 of file miscinit.c.
Referenced by _PG_init(), init_custom_variable(), load_libraries(), process_shared_preload_libraries(), and RegisterBackgroundWorker().
int SecurityRestrictionContext = 0 [static] |
Definition at line 229 of file miscinit.c.
Referenced by GetUserIdAndSecContext(), InLocalUserIdChange(), InSecurityRestrictedOperation(), SetOuterUserId(), SetSessionUserId(), SetUserIdAndContext(), and SetUserIdAndSecContext().
Oid SessionUserId = InvalidOid [static] |
Definition at line 221 of file miscinit.c.
Referenced by GetSessionUserId(), SetCurrentRoleId(), and SetSessionUserId().
bool SessionUserIsSuperuser = false [static] |
Definition at line 227 of file miscinit.c.
Referenced by SetCurrentRoleId(), and SetSessionUserId().
bool SetRoleIsActive = false [static] |
Definition at line 232 of file miscinit.c.
Referenced by GetCurrentRoleId(), SetCurrentRoleId(), and SetSessionUserId().
| char* shared_preload_libraries_string = NULL |
Definition at line 1225 of file miscinit.c.
Referenced by process_shared_preload_libraries().
1.7.1