Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

miscinit.c File Reference

#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"
Include dependency graph for miscinit.c:

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 Listlock_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 Documentation

#define DIRECTORY_LOCK_FILE   "postmaster.pid"

Definition at line 49 of file miscinit.c.

Referenced by AddToDataDirLockFile(), CreateDataDirLockFile(), and TouchSocketLockFiles().


Function Documentation

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().

Oid GetSessionUserId ( void   ) 
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().

void GetUserIdAndContext ( Oid userid,
bool sec_def_context 
)

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 
)
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;
}

bool has_rolreplication ( Oid  roleid  ) 

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   ) 
bool InSecurityRestrictedOperation ( void   ) 
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   ) 
void SetCurrentRoleId ( Oid  roleid,
bool  is_superuser 
)

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().

{
    char       *new;

    AssertArg(dir);

    /* If presented path is relative, convert to absolute */
    new = make_absolute_path(dir);

    if (DataDir)
        free(DataDir);
    DataDir = new;
}

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;
}

void SetSessionAuthorization ( Oid  userid,
bool  is_superuser 
)

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);
}

static void SetSessionUserId ( Oid  userid,
bool  is_superuser 
) [static]
void SetUserIdAndContext ( Oid  userid,
bool  sec_def_context 
)

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 
)
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)));
}


Variable Documentation

Oid AuthenticatedUserId = InvalidOid [static]
Oid CurrentUserId = InvalidOid [static]

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().

int SecurityRestrictionContext = 0 [static]
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().

Definition at line 1225 of file miscinit.c.

Referenced by process_shared_preload_libraries().