LCOV - code coverage report
Current view: top level - src/backend/utils/init - miscinit.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 258 399 64.7 %
Date: 2017-09-29 13:40:31 Functions: 35 39 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * miscinit.c
       4             :  *    miscellaneous initialization support stuff
       5             :  *
       6             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/init/miscinit.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include <sys/param.h>
      18             : #include <signal.h>
      19             : #include <time.h>
      20             : #include <sys/file.h>
      21             : #include <sys/stat.h>
      22             : #include <sys/time.h>
      23             : #include <fcntl.h>
      24             : #include <unistd.h>
      25             : #include <grp.h>
      26             : #include <pwd.h>
      27             : #include <netinet/in.h>
      28             : #include <arpa/inet.h>
      29             : #ifdef HAVE_UTIME_H
      30             : #include <utime.h>
      31             : #endif
      32             : 
      33             : #include "access/htup_details.h"
      34             : #include "catalog/pg_authid.h"
      35             : #include "libpq/libpq.h"
      36             : #include "mb/pg_wchar.h"
      37             : #include "miscadmin.h"
      38             : #include "pgstat.h"
      39             : #include "postmaster/autovacuum.h"
      40             : #include "postmaster/postmaster.h"
      41             : #include "storage/fd.h"
      42             : #include "storage/ipc.h"
      43             : #include "storage/latch.h"
      44             : #include "storage/pg_shmem.h"
      45             : #include "storage/proc.h"
      46             : #include "storage/procarray.h"
      47             : #include "utils/builtins.h"
      48             : #include "utils/guc.h"
      49             : #include "utils/memutils.h"
      50             : #include "utils/pidfile.h"
      51             : #include "utils/syscache.h"
      52             : #include "utils/varlena.h"
      53             : 
      54             : 
      55             : #define DIRECTORY_LOCK_FILE     "postmaster.pid"
      56             : 
      57             : ProcessingMode Mode = InitProcessing;
      58             : 
      59             : /* List of lock files to be removed at proc exit */
      60             : static List *lock_files = NIL;
      61             : 
      62             : static Latch LocalLatchData;
      63             : 
      64             : /* ----------------------------------------------------------------
      65             :  *      ignoring system indexes support stuff
      66             :  *
      67             :  * NOTE: "ignoring system indexes" means we do not use the system indexes
      68             :  * for lookups (either in hardwired catalog accesses or in planner-generated
      69             :  * plans).  We do, however, still update the indexes when a catalog
      70             :  * modification is made.
      71             :  * ----------------------------------------------------------------
      72             :  */
      73             : 
      74             : bool        IgnoreSystemIndexes = false;
      75             : 
      76             : 
      77             : /* ----------------------------------------------------------------
      78             :  *              database path / name support stuff
      79             :  * ----------------------------------------------------------------
      80             :  */
      81             : 
      82             : void
      83         336 : SetDatabasePath(const char *path)
      84             : {
      85             :     /* This should happen only once per process */
      86         336 :     Assert(!DatabasePath);
      87         336 :     DatabasePath = MemoryContextStrdup(TopMemoryContext, path);
      88         336 : }
      89             : 
      90             : /*
      91             :  * Set data directory, but make sure it's an absolute path.  Use this,
      92             :  * never set DataDir directly.
      93             :  */
      94             : void
      95           5 : SetDataDir(const char *dir)
      96             : {
      97             :     char       *new;
      98             : 
      99           5 :     AssertArg(dir);
     100             : 
     101             :     /* If presented path is relative, convert to absolute */
     102           5 :     new = make_absolute_path(dir);
     103             : 
     104           5 :     if (DataDir)
     105           0 :         free(DataDir);
     106           5 :     DataDir = new;
     107           5 : }
     108             : 
     109             : /*
     110             :  * Change working directory to DataDir.  Most of the postmaster and backend
     111             :  * code assumes that we are in DataDir so it can use relative paths to access
     112             :  * stuff in and under the data directory.  For convenience during path
     113             :  * setup, however, we don't force the chdir to occur during SetDataDir.
     114             :  */
     115             : void
     116           5 : ChangeToDataDir(void)
     117             : {
     118           5 :     AssertState(DataDir);
     119             : 
     120           5 :     if (chdir(DataDir) < 0)
     121           0 :         ereport(FATAL,
     122             :                 (errcode_for_file_access(),
     123             :                  errmsg("could not change directory to \"%s\": %m",
     124             :                         DataDir)));
     125           5 : }
     126             : 
     127             : 
     128             : /* ----------------------------------------------------------------
     129             :  *  User ID state
     130             :  *
     131             :  * We have to track several different values associated with the concept
     132             :  * of "user ID".
     133             :  *
     134             :  * AuthenticatedUserId is determined at connection start and never changes.
     135             :  *
     136             :  * SessionUserId is initially the same as AuthenticatedUserId, but can be
     137             :  * changed by SET SESSION AUTHORIZATION (if AuthenticatedUserIsSuperuser).
     138             :  * This is the ID reported by the SESSION_USER SQL function.
     139             :  *
     140             :  * OuterUserId is the current user ID in effect at the "outer level" (outside
     141             :  * any transaction or function).  This is initially the same as SessionUserId,
     142             :  * but can be changed by SET ROLE to any role that SessionUserId is a
     143             :  * member of.  (XXX rename to something like CurrentRoleId?)
     144             :  *
     145             :  * CurrentUserId is the current effective user ID; this is the one to use
     146             :  * for all normal permissions-checking purposes.  At outer level this will
     147             :  * be the same as OuterUserId, but it changes during calls to SECURITY
     148             :  * DEFINER functions, as well as locally in some specialized commands.
     149             :  *
     150             :  * SecurityRestrictionContext holds flags indicating reason(s) for changing
     151             :  * CurrentUserId.  In some cases we need to lock down operations that are
     152             :  * not directly controlled by privilege settings, and this provides a
     153             :  * convenient way to do it.
     154             :  * ----------------------------------------------------------------
     155             :  */
     156             : static Oid  AuthenticatedUserId = InvalidOid;
     157             : static Oid  SessionUserId = InvalidOid;
     158             : static Oid  OuterUserId = InvalidOid;
     159             : static Oid  CurrentUserId = InvalidOid;
     160             : 
     161             : /* We also have to remember the superuser state of some of these levels */
     162             : static bool AuthenticatedUserIsSuperuser = false;
     163             : static bool SessionUserIsSuperuser = false;
     164             : 
     165             : static int  SecurityRestrictionContext = 0;
     166             : 
     167             : /* We also remember if a SET ROLE is currently active */
     168             : static bool SetRoleIsActive = false;
     169             : 
     170             : /*
     171             :  * Initialize the basic environment for a postmaster child
     172             :  *
     173             :  * Should be called as early as possible after the child's startup.
     174             :  */
     175             : void
     176         341 : InitPostmasterChild(void)
     177             : {
     178         341 :     IsUnderPostmaster = true;   /* we are a postmaster subprocess now */
     179             : 
     180         341 :     MyProcPid = getpid();       /* reset MyProcPid */
     181             : 
     182         341 :     MyStartTime = time(NULL);   /* set our start time in case we call elog */
     183             : 
     184             :     /*
     185             :      * make sure stderr is in binary mode before anything can possibly be
     186             :      * written to it, in case it's actually the syslogger pipe, so the pipe
     187             :      * chunking protocol isn't disturbed. Non-logpipe data gets translated on
     188             :      * redirection (e.g. via pg_ctl -l) anyway.
     189             :      */
     190             : #ifdef WIN32
     191             :     _setmode(fileno(stderr), _O_BINARY);
     192             : #endif
     193             : 
     194             :     /* We don't want the postmaster's proc_exit() handlers */
     195         341 :     on_exit_reset();
     196             : 
     197             :     /* Initialize process-local latch support */
     198         341 :     InitializeLatchSupport();
     199         341 :     MyLatch = &LocalLatchData;
     200         341 :     InitLatch(MyLatch);
     201             : 
     202             :     /*
     203             :      * If possible, make this process a group leader, so that the postmaster
     204             :      * can signal any child processes too. Not all processes will have
     205             :      * children, but for consistency we make all postmaster child processes do
     206             :      * this.
     207             :      */
     208             : #ifdef HAVE_SETSID
     209         341 :     if (setsid() < 0)
     210           0 :         elog(FATAL, "setsid() failed: %m");
     211             : #endif
     212         341 : }
     213             : 
     214             : /*
     215             :  * Initialize the basic environment for a standalone process.
     216             :  *
     217             :  * argv0 has to be suitable to find the program's executable.
     218             :  */
     219             : void
     220           4 : InitStandaloneProcess(const char *argv0)
     221             : {
     222           4 :     Assert(!IsPostmasterEnvironment);
     223             : 
     224           4 :     MyProcPid = getpid();       /* reset MyProcPid */
     225             : 
     226           4 :     MyStartTime = time(NULL);   /* set our start time in case we call elog */
     227             : 
     228             :     /* Initialize process-local latch support */
     229           4 :     InitializeLatchSupport();
     230           4 :     MyLatch = &LocalLatchData;
     231           4 :     InitLatch(MyLatch);
     232             : 
     233             :     /* Compute paths, no postmaster to inherit from */
     234           4 :     if (my_exec_path[0] == '\0')
     235             :     {
     236           4 :         if (find_my_exec(argv0, my_exec_path) < 0)
     237           0 :             elog(FATAL, "%s: could not locate my own executable path",
     238             :                  argv0);
     239             :     }
     240             : 
     241           4 :     if (pkglib_path[0] == '\0')
     242           4 :         get_pkglib_path(my_exec_path, pkglib_path);
     243           4 : }
     244             : 
     245             : void
     246         342 : SwitchToSharedLatch(void)
     247             : {
     248         342 :     Assert(MyLatch == &LocalLatchData);
     249         342 :     Assert(MyProc != NULL);
     250             : 
     251         342 :     MyLatch = &MyProc->procLatch;
     252             : 
     253         342 :     if (FeBeWaitSet)
     254         215 :         ModifyWaitEvent(FeBeWaitSet, 1, WL_LATCH_SET, MyLatch);
     255             : 
     256             :     /*
     257             :      * Set the shared latch as the local one might have been set. This
     258             :      * shouldn't normally be necessary as code is supposed to check the
     259             :      * condition before waiting for the latch, but a bit care can't hurt.
     260             :      */
     261         342 :     SetLatch(MyLatch);
     262         342 : }
     263             : 
     264             : void
     265         342 : SwitchBackToLocalLatch(void)
     266             : {
     267         342 :     Assert(MyLatch != &LocalLatchData);
     268         342 :     Assert(MyProc != NULL && MyLatch == &MyProc->procLatch);
     269             : 
     270         342 :     MyLatch = &LocalLatchData;
     271             : 
     272         342 :     if (FeBeWaitSet)
     273         215 :         ModifyWaitEvent(FeBeWaitSet, 1, WL_LATCH_SET, MyLatch);
     274             : 
     275         342 :     SetLatch(MyLatch);
     276         342 : }
     277             : 
     278             : /*
     279             :  * GetUserId - get the current effective user ID.
     280             :  *
     281             :  * Note: there's no SetUserId() anymore; use SetUserIdAndSecContext().
     282             :  */
     283             : Oid
     284      333485 : GetUserId(void)
     285             : {
     286      333485 :     AssertState(OidIsValid(CurrentUserId));
     287      333485 :     return CurrentUserId;
     288             : }
     289             : 
     290             : 
     291             : /*
     292             :  * GetOuterUserId/SetOuterUserId - get/set the outer-level user ID.
     293             :  */
     294             : Oid
     295         123 : GetOuterUserId(void)
     296             : {
     297         123 :     AssertState(OidIsValid(OuterUserId));
     298         123 :     return OuterUserId;
     299             : }
     300             : 
     301             : 
     302             : static void
     303         120 : SetOuterUserId(Oid userid)
     304             : {
     305         120 :     AssertState(SecurityRestrictionContext == 0);
     306         120 :     AssertArg(OidIsValid(userid));
     307         120 :     OuterUserId = userid;
     308             : 
     309             :     /* We force the effective user ID to match, too */
     310         120 :     CurrentUserId = userid;
     311         120 : }
     312             : 
     313             : 
     314             : /*
     315             :  * GetSessionUserId/SetSessionUserId - get/set the session user ID.
     316             :  */
     317             : Oid
     318         912 : GetSessionUserId(void)
     319             : {
     320         912 :     AssertState(OidIsValid(SessionUserId));
     321         912 :     return SessionUserId;
     322             : }
     323             : 
     324             : 
     325             : static void
     326        1087 : SetSessionUserId(Oid userid, bool is_superuser)
     327             : {
     328        1087 :     AssertState(SecurityRestrictionContext == 0);
     329        1087 :     AssertArg(OidIsValid(userid));
     330        1087 :     SessionUserId = userid;
     331        1087 :     SessionUserIsSuperuser = is_superuser;
     332        1087 :     SetRoleIsActive = false;
     333             : 
     334             :     /* We force the effective user IDs to match, too */
     335        1087 :     OuterUserId = userid;
     336        1087 :     CurrentUserId = userid;
     337        1087 : }
     338             : 
     339             : /*
     340             :  * GetAuthenticatedUserId - get the authenticated user ID
     341             :  */
     342             : Oid
     343          17 : GetAuthenticatedUserId(void)
     344             : {
     345          17 :     AssertState(OidIsValid(AuthenticatedUserId));
     346          17 :     return AuthenticatedUserId;
     347             : }
     348             : 
     349             : 
     350             : /*
     351             :  * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
     352             :  * and the SecurityRestrictionContext flags.
     353             :  *
     354             :  * Currently there are three valid bits in SecurityRestrictionContext:
     355             :  *
     356             :  * SECURITY_LOCAL_USERID_CHANGE indicates that we are inside an operation
     357             :  * that is temporarily changing CurrentUserId via these functions.  This is
     358             :  * needed to indicate that the actual value of CurrentUserId is not in sync
     359             :  * with guc.c's internal state, so SET ROLE has to be disallowed.
     360             :  *
     361             :  * SECURITY_RESTRICTED_OPERATION indicates that we are inside an operation
     362             :  * that does not wish to trust called user-defined functions at all.  This
     363             :  * bit prevents not only SET ROLE, but various other changes of session state
     364             :  * that normally is unprotected but might possibly be used to subvert the
     365             :  * calling session later.  An example is replacing an existing prepared
     366             :  * statement with new code, which will then be executed with the outer
     367             :  * session's permissions when the prepared statement is next used.  Since
     368             :  * these restrictions are fairly draconian, we apply them only in contexts
     369             :  * where the called functions are really supposed to be side-effect-free
     370             :  * anyway, such as VACUUM/ANALYZE/REINDEX.
     371             :  *
     372             :  * SECURITY_NOFORCE_RLS indicates that we are inside an operation which should
     373             :  * ignore the FORCE ROW LEVEL SECURITY per-table indication.  This is used to
     374             :  * ensure that FORCE RLS does not mistakenly break referential integrity
     375             :  * checks.  Note that this is intentionally only checked when running as the
     376             :  * owner of the table (which should always be the case for referential
     377             :  * integrity checks).
     378             :  *
     379             :  * Unlike GetUserId, GetUserIdAndSecContext does *not* Assert that the current
     380             :  * value of CurrentUserId is valid; nor does SetUserIdAndSecContext require
     381             :  * the new value to be valid.  In fact, these routines had better not
     382             :  * ever throw any kind of error.  This is because they are used by
     383             :  * StartTransaction and AbortTransaction to save/restore the settings,
     384             :  * and during the first transaction within a backend, the value to be saved
     385             :  * and perhaps restored is indeed invalid.  We have to be able to get
     386             :  * through AbortTransaction without asserting in case InitPostgres fails.
     387             :  */
     388             : void
     389       29298 : GetUserIdAndSecContext(Oid *userid, int *sec_context)
     390             : {
     391       29298 :     *userid = CurrentUserId;
     392       29298 :     *sec_context = SecurityRestrictionContext;
     393       29298 : }
     394             : 
     395             : void
     396        9123 : SetUserIdAndSecContext(Oid userid, int sec_context)
     397             : {
     398        9123 :     CurrentUserId = userid;
     399        9123 :     SecurityRestrictionContext = sec_context;
     400        9123 : }
     401             : 
     402             : 
     403             : /*
     404             :  * InLocalUserIdChange - are we inside a local change of CurrentUserId?
     405             :  */
     406             : bool
     407         852 : InLocalUserIdChange(void)
     408             : {
     409         852 :     return (SecurityRestrictionContext & SECURITY_LOCAL_USERID_CHANGE) != 0;
     410             : }
     411             : 
     412             : /*
     413             :  * InSecurityRestrictedOperation - are we inside a security-restricted command?
     414             :  */
     415             : bool
     416        1257 : InSecurityRestrictedOperation(void)
     417             : {
     418        1257 :     return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
     419             : }
     420             : 
     421             : /*
     422             :  * InNoForceRLSOperation - are we ignoring FORCE ROW LEVEL SECURITY ?
     423             :  */
     424             : bool
     425          20 : InNoForceRLSOperation(void)
     426             : {
     427          20 :     return (SecurityRestrictionContext & SECURITY_NOFORCE_RLS) != 0;
     428             : }
     429             : 
     430             : 
     431             : /*
     432             :  * These are obsolete versions of Get/SetUserIdAndSecContext that are
     433             :  * only provided for bug-compatibility with some rather dubious code in
     434             :  * pljava.  We allow the userid to be set, but only when not inside a
     435             :  * security restriction context.
     436             :  */
     437             : void
     438           0 : GetUserIdAndContext(Oid *userid, bool *sec_def_context)
     439             : {
     440           0 :     *userid = CurrentUserId;
     441           0 :     *sec_def_context = InLocalUserIdChange();
     442           0 : }
     443             : 
     444             : void
     445           0 : SetUserIdAndContext(Oid userid, bool sec_def_context)
     446             : {
     447             :     /* We throw the same error SET ROLE would. */
     448           0 :     if (InSecurityRestrictedOperation())
     449           0 :         ereport(ERROR,
     450             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     451             :                  errmsg("cannot set parameter \"%s\" within security-restricted operation",
     452             :                         "role")));
     453           0 :     CurrentUserId = userid;
     454           0 :     if (sec_def_context)
     455           0 :         SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE;
     456             :     else
     457           0 :         SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
     458           0 : }
     459             : 
     460             : 
     461             : /*
     462             :  * Check whether specified role has explicit REPLICATION privilege
     463             :  */
     464             : bool
     465           0 : has_rolreplication(Oid roleid)
     466             : {
     467           0 :     bool        result = false;
     468             :     HeapTuple   utup;
     469             : 
     470           0 :     utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
     471           0 :     if (HeapTupleIsValid(utup))
     472             :     {
     473           0 :         result = ((Form_pg_authid) GETSTRUCT(utup))->rolreplication;
     474           0 :         ReleaseSysCache(utup);
     475             :     }
     476           0 :     return result;
     477             : }
     478             : 
     479             : /*
     480             :  * Initialize user identity during normal backend startup
     481             :  */
     482             : void
     483         330 : InitializeSessionUserId(const char *rolename, Oid roleid)
     484             : {
     485             :     HeapTuple   roleTup;
     486             :     Form_pg_authid rform;
     487             :     char       *rname;
     488             : 
     489             :     /*
     490             :      * Don't do scans if we're bootstrapping, none of the system catalogs
     491             :      * exist yet, and they should be owned by postgres anyway.
     492             :      */
     493         330 :     AssertState(!IsBootstrapProcessingMode());
     494             : 
     495             :     /* call only once */
     496         330 :     AssertState(!OidIsValid(AuthenticatedUserId));
     497             : 
     498         330 :     if (rolename != NULL)
     499             :     {
     500         215 :         roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
     501         215 :         if (!HeapTupleIsValid(roleTup))
     502           0 :             ereport(FATAL,
     503             :                     (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     504             :                      errmsg("role \"%s\" does not exist", rolename)));
     505             :     }
     506             :     else
     507             :     {
     508         115 :         roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
     509         115 :         if (!HeapTupleIsValid(roleTup))
     510           0 :             ereport(FATAL,
     511             :                     (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     512             :                      errmsg("role with OID %u does not exist", roleid)));
     513             :     }
     514             : 
     515         330 :     rform = (Form_pg_authid) GETSTRUCT(roleTup);
     516         330 :     roleid = HeapTupleGetOid(roleTup);
     517         330 :     rname = NameStr(rform->rolname);
     518             : 
     519         330 :     AuthenticatedUserId = roleid;
     520         330 :     AuthenticatedUserIsSuperuser = rform->rolsuper;
     521             : 
     522             :     /* This sets OuterUserId/CurrentUserId too */
     523         330 :     SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
     524             : 
     525             :     /* Also mark our PGPROC entry with the authenticated user id */
     526             :     /* (We assume this is an atomic store so no lock is needed) */
     527         330 :     MyProc->roleId = roleid;
     528             : 
     529             :     /*
     530             :      * These next checks are not enforced when in standalone mode, so that
     531             :      * there is a way to recover from sillinesses like "UPDATE pg_authid SET
     532             :      * rolcanlogin = false;".
     533             :      */
     534         330 :     if (IsUnderPostmaster)
     535             :     {
     536             :         /*
     537             :          * Is role allowed to login at all?
     538             :          */
     539         330 :         if (!rform->rolcanlogin)
     540           0 :             ereport(FATAL,
     541             :                     (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     542             :                      errmsg("role \"%s\" is not permitted to log in",
     543             :                             rname)));
     544             : 
     545             :         /*
     546             :          * Check connection limit for this role.
     547             :          *
     548             :          * There is a race condition here --- we create our PGPROC before
     549             :          * checking for other PGPROCs.  If two backends did this at about the
     550             :          * same time, they might both think they were over the limit, while
     551             :          * ideally one should succeed and one fail.  Getting that to work
     552             :          * exactly seems more trouble than it is worth, however; instead we
     553             :          * just document that the connection limit is approximate.
     554             :          */
     555         330 :         if (rform->rolconnlimit >= 0 &&
     556           0 :             !AuthenticatedUserIsSuperuser &&
     557           0 :             CountUserBackends(roleid) > rform->rolconnlimit)
     558           0 :             ereport(FATAL,
     559             :                     (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
     560             :                      errmsg("too many connections for role \"%s\"",
     561             :                             rname)));
     562             :     }
     563             : 
     564             :     /* Record username and superuser status as GUC settings too */
     565         330 :     SetConfigOption("session_authorization", rname,
     566             :                     PGC_BACKEND, PGC_S_OVERRIDE);
     567         330 :     SetConfigOption("is_superuser",
     568         330 :                     AuthenticatedUserIsSuperuser ? "on" : "off",
     569             :                     PGC_INTERNAL, PGC_S_OVERRIDE);
     570             : 
     571         330 :     ReleaseSysCache(roleTup);
     572         330 : }
     573             : 
     574             : 
     575             : /*
     576             :  * Initialize user identity during special backend startup
     577             :  */
     578             : void
     579           7 : InitializeSessionUserIdStandalone(void)
     580             : {
     581             :     /*
     582             :      * This function should only be called in single-user mode, in autovacuum
     583             :      * workers, and in background workers.
     584             :      */
     585           7 :     AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess() || IsBackgroundWorker);
     586             : 
     587             :     /* call only once */
     588           7 :     AssertState(!OidIsValid(AuthenticatedUserId));
     589             : 
     590           7 :     AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
     591           7 :     AuthenticatedUserIsSuperuser = true;
     592             : 
     593           7 :     SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
     594           7 : }
     595             : 
     596             : 
     597             : /*
     598             :  * Change session auth ID while running
     599             :  *
     600             :  * Only a superuser may set auth ID to something other than himself.  Note
     601             :  * that in case of multiple SETs in a single session, the original userid's
     602             :  * superuserness is what matters.  But we set the GUC variable is_superuser
     603             :  * to indicate whether the *current* session userid is a superuser.
     604             :  *
     605             :  * Note: this is not an especially clean place to do the permission check.
     606             :  * It's OK because the check does not require catalog access and can't
     607             :  * fail during an end-of-transaction GUC reversion, but we may someday
     608             :  * have to push it up into assign_session_authorization.
     609             :  */
     610             : void
     611         750 : SetSessionAuthorization(Oid userid, bool is_superuser)
     612             : {
     613             :     /* Must have authenticated already, else can't make permission check */
     614         750 :     AssertState(OidIsValid(AuthenticatedUserId));
     615             : 
     616         988 :     if (userid != AuthenticatedUserId &&
     617         238 :         !AuthenticatedUserIsSuperuser)
     618           0 :         ereport(ERROR,
     619             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     620             :                  errmsg("permission denied to set session authorization")));
     621             : 
     622         750 :     SetSessionUserId(userid, is_superuser);
     623             : 
     624         750 :     SetConfigOption("is_superuser",
     625             :                     is_superuser ? "on" : "off",
     626             :                     PGC_INTERNAL, PGC_S_OVERRIDE);
     627         750 : }
     628             : 
     629             : /*
     630             :  * Report current role id
     631             :  *      This follows the semantics of SET ROLE, ie return the outer-level ID
     632             :  *      not the current effective ID, and return InvalidOid when the setting
     633             :  *      is logically SET ROLE NONE.
     634             :  */
     635             : Oid
     636           1 : GetCurrentRoleId(void)
     637             : {
     638           1 :     if (SetRoleIsActive)
     639           0 :         return OuterUserId;
     640             :     else
     641           1 :         return InvalidOid;
     642             : }
     643             : 
     644             : /*
     645             :  * Change Role ID while running (SET ROLE)
     646             :  *
     647             :  * If roleid is InvalidOid, we are doing SET ROLE NONE: revert to the
     648             :  * session user authorization.  In this case the is_superuser argument
     649             :  * is ignored.
     650             :  *
     651             :  * When roleid is not InvalidOid, the caller must have checked whether
     652             :  * the session user has permission to become that role.  (We cannot check
     653             :  * here because this routine must be able to execute in a failed transaction
     654             :  * to restore a prior value of the ROLE GUC variable.)
     655             :  */
     656             : void
     657         125 : SetCurrentRoleId(Oid roleid, bool is_superuser)
     658             : {
     659             :     /*
     660             :      * Get correct info if it's SET ROLE NONE
     661             :      *
     662             :      * If SessionUserId hasn't been set yet, just do nothing --- the eventual
     663             :      * SetSessionUserId call will fix everything.  This is needed since we
     664             :      * will get called during GUC initialization.
     665             :      */
     666         125 :     if (!OidIsValid(roleid))
     667             :     {
     668          50 :         if (!OidIsValid(SessionUserId))
     669         130 :             return;
     670             : 
     671          45 :         roleid = SessionUserId;
     672          45 :         is_superuser = SessionUserIsSuperuser;
     673             : 
     674          45 :         SetRoleIsActive = false;
     675             :     }
     676             :     else
     677          75 :         SetRoleIsActive = true;
     678             : 
     679         120 :     SetOuterUserId(roleid);
     680             : 
     681         120 :     SetConfigOption("is_superuser",
     682             :                     is_superuser ? "on" : "off",
     683             :                     PGC_INTERNAL, PGC_S_OVERRIDE);
     684             : }
     685             : 
     686             : 
     687             : /*
     688             :  * Get user name from user oid, returns NULL for nonexistent roleid if noerr
     689             :  * is true.
     690             :  */
     691             : char *
     692         918 : GetUserNameFromId(Oid roleid, bool noerr)
     693             : {
     694             :     HeapTuple   tuple;
     695             :     char       *result;
     696             : 
     697         918 :     tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
     698         918 :     if (!HeapTupleIsValid(tuple))
     699             :     {
     700           0 :         if (!noerr)
     701           0 :             ereport(ERROR,
     702             :                     (errcode(ERRCODE_UNDEFINED_OBJECT),
     703             :                      errmsg("invalid role OID: %u", roleid)));
     704           0 :         result = NULL;
     705             :     }
     706             :     else
     707             :     {
     708         918 :         result = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname));
     709         918 :         ReleaseSysCache(tuple);
     710             :     }
     711         918 :     return result;
     712             : }
     713             : 
     714             : 
     715             : /*-------------------------------------------------------------------------
     716             :  *              Interlock-file support
     717             :  *
     718             :  * These routines are used to create both a data-directory lockfile
     719             :  * ($DATADIR/postmaster.pid) and Unix-socket-file lockfiles ($SOCKFILE.lock).
     720             :  * Both kinds of files contain the same info initially, although we can add
     721             :  * more information to a data-directory lockfile after it's created, using
     722             :  * AddToDataDirLockFile().  See miscadmin.h for documentation of the contents
     723             :  * of these lockfiles.
     724             :  *
     725             :  * On successful lockfile creation, a proc_exit callback to remove the
     726             :  * lockfile is automatically created.
     727             :  *-------------------------------------------------------------------------
     728             :  */
     729             : 
     730             : /*
     731             :  * proc_exit callback to remove lockfiles.
     732             :  */
     733             : static void
     734           5 : UnlinkLockFiles(int status, Datum arg)
     735             : {
     736             :     ListCell   *l;
     737             : 
     738          11 :     foreach(l, lock_files)
     739             :     {
     740           6 :         char       *curfile = (char *) lfirst(l);
     741             : 
     742           6 :         unlink(curfile);
     743             :         /* Should we complain if the unlink fails? */
     744             :     }
     745             :     /* Since we're about to exit, no need to reclaim storage */
     746           5 :     lock_files = NIL;
     747             : 
     748             :     /*
     749             :      * Lock file removal should always be the last externally visible action
     750             :      * of a postmaster or standalone backend, while we won't come here at all
     751             :      * when exiting postmaster child processes.  Therefore, this is a good
     752             :      * place to log completion of shutdown.  We could alternatively teach
     753             :      * proc_exit() to do it, but that seems uglier.  In a standalone backend,
     754             :      * use NOTICE elevel to be less chatty.
     755             :      */
     756           5 :     ereport(IsPostmasterEnvironment ? LOG : NOTICE,
     757             :             (errmsg("database system is shut down")));
     758           5 : }
     759             : 
     760             : /*
     761             :  * Create a lockfile.
     762             :  *
     763             :  * filename is the path name of the lockfile to create.
     764             :  * amPostmaster is used to determine how to encode the output PID.
     765             :  * socketDir is the Unix socket directory path to include (possibly empty).
     766             :  * isDDLock and refName are used to determine what error message to produce.
     767             :  */
     768             : static void
     769           6 : CreateLockFile(const char *filename, bool amPostmaster,
     770             :                const char *socketDir,
     771             :                bool isDDLock, const char *refName)
     772             : {
     773             :     int         fd;
     774             :     char        buffer[MAXPGPATH * 2 + 256];
     775             :     int         ntries;
     776             :     int         len;
     777             :     int         encoded_pid;
     778             :     pid_t       other_pid;
     779             :     pid_t       my_pid,
     780             :                 my_p_pid,
     781             :                 my_gp_pid;
     782             :     const char *envvar;
     783             : 
     784             :     /*
     785             :      * If the PID in the lockfile is our own PID or our parent's or
     786             :      * grandparent's PID, then the file must be stale (probably left over from
     787             :      * a previous system boot cycle).  We need to check this because of the
     788             :      * likelihood that a reboot will assign exactly the same PID as we had in
     789             :      * the previous reboot, or one that's only one or two counts larger and
     790             :      * hence the lockfile's PID now refers to an ancestor shell process.  We
     791             :      * allow pg_ctl to pass down its parent shell PID (our grandparent PID)
     792             :      * via the environment variable PG_GRANDPARENT_PID; this is so that
     793             :      * launching the postmaster via pg_ctl can be just as reliable as
     794             :      * launching it directly.  There is no provision for detecting
     795             :      * further-removed ancestor processes, but if the init script is written
     796             :      * carefully then all but the immediate parent shell will be root-owned
     797             :      * processes and so the kill test will fail with EPERM.  Note that we
     798             :      * cannot get a false negative this way, because an existing postmaster
     799             :      * would surely never launch a competing postmaster or pg_ctl process
     800             :      * directly.
     801             :      */
     802           6 :     my_pid = getpid();
     803             : 
     804             : #ifndef WIN32
     805           6 :     my_p_pid = getppid();
     806             : #else
     807             : 
     808             :     /*
     809             :      * Windows hasn't got getppid(), but doesn't need it since it's not using
     810             :      * real kill() either...
     811             :      */
     812             :     my_p_pid = 0;
     813             : #endif
     814             : 
     815           6 :     envvar = getenv("PG_GRANDPARENT_PID");
     816           6 :     if (envvar)
     817           0 :         my_gp_pid = atoi(envvar);
     818             :     else
     819           6 :         my_gp_pid = 0;
     820             : 
     821             :     /*
     822             :      * We need a loop here because of race conditions.  But don't loop forever
     823             :      * (for example, a non-writable $PGDATA directory might cause a failure
     824             :      * that won't go away).  100 tries seems like plenty.
     825             :      */
     826           6 :     for (ntries = 0;; ntries++)
     827             :     {
     828             :         /*
     829             :          * Try to create the lock file --- O_EXCL makes this atomic.
     830             :          *
     831             :          * Think not to make the file protection weaker than 0600.  See
     832             :          * comments below.
     833             :          */
     834           6 :         fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
     835           6 :         if (fd >= 0)
     836           6 :             break;              /* Success; exit the retry loop */
     837             : 
     838             :         /*
     839             :          * Couldn't create the pid file. Probably it already exists.
     840             :          */
     841           0 :         if ((errno != EEXIST && errno != EACCES) || ntries > 100)
     842           0 :             ereport(FATAL,
     843             :                     (errcode_for_file_access(),
     844             :                      errmsg("could not create lock file \"%s\": %m",
     845             :                             filename)));
     846             : 
     847             :         /*
     848             :          * Read the file to get the old owner's PID.  Note race condition
     849             :          * here: file might have been deleted since we tried to create it.
     850             :          */
     851           0 :         fd = open(filename, O_RDONLY, 0600);
     852           0 :         if (fd < 0)
     853             :         {
     854           0 :             if (errno == ENOENT)
     855           0 :                 continue;       /* race condition; try again */
     856           0 :             ereport(FATAL,
     857             :                     (errcode_for_file_access(),
     858             :                      errmsg("could not open lock file \"%s\": %m",
     859             :                             filename)));
     860             :         }
     861           0 :         pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_READ);
     862           0 :         if ((len = read(fd, buffer, sizeof(buffer) - 1)) < 0)
     863           0 :             ereport(FATAL,
     864             :                     (errcode_for_file_access(),
     865             :                      errmsg("could not read lock file \"%s\": %m",
     866             :                             filename)));
     867           0 :         pgstat_report_wait_end();
     868           0 :         close(fd);
     869             : 
     870           0 :         if (len == 0)
     871             :         {
     872           0 :             ereport(FATAL,
     873             :                     (errcode(ERRCODE_LOCK_FILE_EXISTS),
     874             :                      errmsg("lock file \"%s\" is empty", filename),
     875             :                      errhint("Either another server is starting, or the lock file is the remnant of a previous server startup crash.")));
     876             :         }
     877             : 
     878           0 :         buffer[len] = '\0';
     879           0 :         encoded_pid = atoi(buffer);
     880             : 
     881             :         /* if pid < 0, the pid is for postgres, not postmaster */
     882           0 :         other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid);
     883             : 
     884           0 :         if (other_pid <= 0)
     885           0 :             elog(FATAL, "bogus data in lock file \"%s\": \"%s\"",
     886             :                  filename, buffer);
     887             : 
     888             :         /*
     889             :          * Check to see if the other process still exists
     890             :          *
     891             :          * Per discussion above, my_pid, my_p_pid, and my_gp_pid can be
     892             :          * ignored as false matches.
     893             :          *
     894             :          * Normally kill() will fail with ESRCH if the given PID doesn't
     895             :          * exist.
     896             :          *
     897             :          * We can treat the EPERM-error case as okay because that error
     898             :          * implies that the existing process has a different userid than we
     899             :          * do, which means it cannot be a competing postmaster.  A postmaster
     900             :          * cannot successfully attach to a data directory owned by a userid
     901             :          * other than its own.  (This is now checked directly in
     902             :          * checkDataDir(), but has been true for a long time because of the
     903             :          * restriction that the data directory isn't group- or
     904             :          * world-accessible.)  Also, since we create the lockfiles mode 600,
     905             :          * we'd have failed above if the lockfile belonged to another userid
     906             :          * --- which means that whatever process kill() is reporting about
     907             :          * isn't the one that made the lockfile.  (NOTE: this last
     908             :          * consideration is the only one that keeps us from blowing away a
     909             :          * Unix socket file belonging to an instance of Postgres being run by
     910             :          * someone else, at least on machines where /tmp hasn't got a
     911             :          * stickybit.)
     912             :          */
     913           0 :         if (other_pid != my_pid && other_pid != my_p_pid &&
     914             :             other_pid != my_gp_pid)
     915             :         {
     916           0 :             if (kill(other_pid, 0) == 0 ||
     917           0 :                 (errno != ESRCH && errno != EPERM))
     918             :             {
     919             :                 /* lockfile belongs to a live process */
     920           0 :                 ereport(FATAL,
     921             :                         (errcode(ERRCODE_LOCK_FILE_EXISTS),
     922             :                          errmsg("lock file \"%s\" already exists",
     923             :                                 filename),
     924             :                          isDDLock ?
     925             :                          (encoded_pid < 0 ?
     926             :                           errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
     927             :                                   (int) other_pid, refName) :
     928             :                           errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
     929             :                                   (int) other_pid, refName)) :
     930             :                          (encoded_pid < 0 ?
     931             :                           errhint("Is another postgres (PID %d) using socket file \"%s\"?",
     932             :                                   (int) other_pid, refName) :
     933             :                           errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
     934             :                                   (int) other_pid, refName))));
     935             :             }
     936             :         }
     937             : 
     938             :         /*
     939             :          * No, the creating process did not exist.  However, it could be that
     940             :          * the postmaster crashed (or more likely was kill -9'd by a clueless
     941             :          * admin) but has left orphan backends behind.  Check for this by
     942             :          * looking to see if there is an associated shmem segment that is
     943             :          * still in use.
     944             :          *
     945             :          * Note: because postmaster.pid is written in multiple steps, we might
     946             :          * not find the shmem ID values in it; we can't treat that as an
     947             :          * error.
     948             :          */
     949           0 :         if (isDDLock)
     950             :         {
     951           0 :             char       *ptr = buffer;
     952             :             unsigned long id1,
     953             :                         id2;
     954             :             int         lineno;
     955             : 
     956           0 :             for (lineno = 1; lineno < LOCK_FILE_LINE_SHMEM_KEY; lineno++)
     957             :             {
     958           0 :                 if ((ptr = strchr(ptr, '\n')) == NULL)
     959           0 :                     break;
     960           0 :                 ptr++;
     961             :             }
     962             : 
     963           0 :             if (ptr != NULL &&
     964           0 :                 sscanf(ptr, "%lu %lu", &id1, &id2) == 2)
     965             :             {
     966           0 :                 if (PGSharedMemoryIsInUse(id1, id2))
     967           0 :                     ereport(FATAL,
     968             :                             (errcode(ERRCODE_LOCK_FILE_EXISTS),
     969             :                              errmsg("pre-existing shared memory block "
     970             :                                     "(key %lu, ID %lu) is still in use",
     971             :                                     id1, id2),
     972             :                              errhint("If you're sure there are no old "
     973             :                                      "server processes still running, remove "
     974             :                                      "the shared memory block "
     975             :                                      "or just delete the file \"%s\".",
     976             :                                      filename)));
     977             :             }
     978             :         }
     979             : 
     980             :         /*
     981             :          * Looks like nobody's home.  Unlink the file and try again to create
     982             :          * it.  Need a loop because of possible race condition against other
     983             :          * would-be creators.
     984             :          */
     985           0 :         if (unlink(filename) < 0)
     986           0 :             ereport(FATAL,
     987             :                     (errcode_for_file_access(),
     988             :                      errmsg("could not remove old lock file \"%s\": %m",
     989             :                             filename),
     990             :                      errhint("The file seems accidentally left over, but "
     991             :                              "it could not be removed. Please remove the file "
     992             :                              "by hand and try again.")));
     993           0 :     }
     994             : 
     995             :     /*
     996             :      * Successfully created the file, now fill it.  See comment in miscadmin.h
     997             :      * about the contents.  Note that we write the same first five lines into
     998             :      * both datadir and socket lockfiles; although more stuff may get added to
     999             :      * the datadir lockfile later.
    1000             :      */
    1001           6 :     snprintf(buffer, sizeof(buffer), "%d\n%s\n%ld\n%d\n%s\n",
    1002             :              amPostmaster ? (int) my_pid : -((int) my_pid),
    1003             :              DataDir,
    1004             :              (long) MyStartTime,
    1005             :              PostPortNumber,
    1006             :              socketDir);
    1007             : 
    1008             :     /*
    1009             :      * In a standalone backend, the next line (LOCK_FILE_LINE_LISTEN_ADDR)
    1010             :      * will never receive data, so fill it in as empty now.
    1011             :      */
    1012           6 :     if (isDDLock && !amPostmaster)
    1013           4 :         strlcat(buffer, "\n", sizeof(buffer));
    1014             : 
    1015           6 :     errno = 0;
    1016           6 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_WRITE);
    1017           6 :     if (write(fd, buffer, strlen(buffer)) != strlen(buffer))
    1018             :     {
    1019           0 :         int         save_errno = errno;
    1020             : 
    1021           0 :         close(fd);
    1022           0 :         unlink(filename);
    1023             :         /* if write didn't set errno, assume problem is no disk space */
    1024           0 :         errno = save_errno ? save_errno : ENOSPC;
    1025           0 :         ereport(FATAL,
    1026             :                 (errcode_for_file_access(),
    1027             :                  errmsg("could not write lock file \"%s\": %m", filename)));
    1028             :     }
    1029           6 :     pgstat_report_wait_end();
    1030             : 
    1031           6 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_CREATE_SYNC);
    1032           6 :     if (pg_fsync(fd) != 0)
    1033             :     {
    1034           0 :         int         save_errno = errno;
    1035             : 
    1036           0 :         close(fd);
    1037           0 :         unlink(filename);
    1038           0 :         errno = save_errno;
    1039           0 :         ereport(FATAL,
    1040             :                 (errcode_for_file_access(),
    1041             :                  errmsg("could not write lock file \"%s\": %m", filename)));
    1042             :     }
    1043           6 :     pgstat_report_wait_end();
    1044           6 :     if (close(fd) != 0)
    1045             :     {
    1046           0 :         int         save_errno = errno;
    1047             : 
    1048           0 :         unlink(filename);
    1049           0 :         errno = save_errno;
    1050           0 :         ereport(FATAL,
    1051             :                 (errcode_for_file_access(),
    1052             :                  errmsg("could not write lock file \"%s\": %m", filename)));
    1053             :     }
    1054             : 
    1055             :     /*
    1056             :      * Arrange to unlink the lock file(s) at proc_exit.  If this is the first
    1057             :      * one, set up the on_proc_exit function to do it; then add this lock file
    1058             :      * to the list of files to unlink.
    1059             :      */
    1060           6 :     if (lock_files == NIL)
    1061           5 :         on_proc_exit(UnlinkLockFiles, 0);
    1062             : 
    1063             :     /*
    1064             :      * Use lcons so that the lock files are unlinked in reverse order of
    1065             :      * creation; this is critical!
    1066             :      */
    1067           6 :     lock_files = lcons(pstrdup(filename), lock_files);
    1068           6 : }
    1069             : 
    1070             : /*
    1071             :  * Create the data directory lockfile.
    1072             :  *
    1073             :  * When this is called, we must have already switched the working
    1074             :  * directory to DataDir, so we can just use a relative path.  This
    1075             :  * helps ensure that we are locking the directory we should be.
    1076             :  *
    1077             :  * Note that the socket directory path line is initially written as empty.
    1078             :  * postmaster.c will rewrite it upon creating the first Unix socket.
    1079             :  */
    1080             : void
    1081           5 : CreateDataDirLockFile(bool amPostmaster)
    1082             : {
    1083           5 :     CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, "", true, DataDir);
    1084           5 : }
    1085             : 
    1086             : /*
    1087             :  * Create a lockfile for the specified Unix socket file.
    1088             :  */
    1089             : void
    1090           1 : CreateSocketLockFile(const char *socketfile, bool amPostmaster,
    1091             :                      const char *socketDir)
    1092             : {
    1093             :     char        lockfile[MAXPGPATH];
    1094             : 
    1095           1 :     snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
    1096           1 :     CreateLockFile(lockfile, amPostmaster, socketDir, false, socketfile);
    1097           1 : }
    1098             : 
    1099             : /*
    1100             :  * TouchSocketLockFiles -- mark socket lock files as recently accessed
    1101             :  *
    1102             :  * This routine should be called every so often to ensure that the socket
    1103             :  * lock files have a recent mod or access date.  That saves them
    1104             :  * from being removed by overenthusiastic /tmp-directory-cleaner daemons.
    1105             :  * (Another reason we should never have put the socket file in /tmp...)
    1106             :  */
    1107             : void
    1108           0 : TouchSocketLockFiles(void)
    1109             : {
    1110             :     ListCell   *l;
    1111             : 
    1112           0 :     foreach(l, lock_files)
    1113             :     {
    1114           0 :         char       *socketLockFile = (char *) lfirst(l);
    1115             : 
    1116             :         /* No need to touch the data directory lock file, we trust */
    1117           0 :         if (strcmp(socketLockFile, DIRECTORY_LOCK_FILE) == 0)
    1118           0 :             continue;
    1119             : 
    1120             :         /*
    1121             :          * utime() is POSIX standard, utimes() is a common alternative; if we
    1122             :          * have neither, fall back to actually reading the file (which only
    1123             :          * sets the access time not mod time, but that should be enough in
    1124             :          * most cases).  In all paths, we ignore errors.
    1125             :          */
    1126             : #ifdef HAVE_UTIME
    1127           0 :         utime(socketLockFile, NULL);
    1128             : #else                           /* !HAVE_UTIME */
    1129             : #ifdef HAVE_UTIMES
    1130             :         utimes(socketLockFile, NULL);
    1131             : #else                           /* !HAVE_UTIMES */
    1132             :         int         fd;
    1133             :         char        buffer[1];
    1134             : 
    1135             :         fd = open(socketLockFile, O_RDONLY | PG_BINARY, 0);
    1136             :         if (fd >= 0)
    1137             :         {
    1138             :             read(fd, buffer, sizeof(buffer));
    1139             :             close(fd);
    1140             :         }
    1141             : #endif                          /* HAVE_UTIMES */
    1142             : #endif                          /* HAVE_UTIME */
    1143             :     }
    1144           0 : }
    1145             : 
    1146             : 
    1147             : /*
    1148             :  * Add (or replace) a line in the data directory lock file.
    1149             :  * The given string should not include a trailing newline.
    1150             :  *
    1151             :  * Note: because we don't truncate the file, if we were to rewrite a line
    1152             :  * with less data than it had before, there would be garbage after the last
    1153             :  * line.  While we could fix that by adding a truncate call, that would make
    1154             :  * the file update non-atomic, which we'd rather avoid.  Therefore, callers
    1155             :  * should endeavor never to shorten a line once it's been written.
    1156             :  */
    1157             : void
    1158          10 : AddToDataDirLockFile(int target_line, const char *str)
    1159             : {
    1160             :     int         fd;
    1161             :     int         len;
    1162             :     int         lineno;
    1163             :     char       *srcptr;
    1164             :     char       *destptr;
    1165             :     char        srcbuffer[BLCKSZ];
    1166             :     char        destbuffer[BLCKSZ];
    1167             : 
    1168          10 :     fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
    1169          10 :     if (fd < 0)
    1170             :     {
    1171           0 :         ereport(LOG,
    1172             :                 (errcode_for_file_access(),
    1173             :                  errmsg("could not open file \"%s\": %m",
    1174             :                         DIRECTORY_LOCK_FILE)));
    1175           0 :         return;
    1176             :     }
    1177          10 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ);
    1178          10 :     len = read(fd, srcbuffer, sizeof(srcbuffer) - 1);
    1179          10 :     pgstat_report_wait_end();
    1180          10 :     if (len < 0)
    1181             :     {
    1182           0 :         ereport(LOG,
    1183             :                 (errcode_for_file_access(),
    1184             :                  errmsg("could not read from file \"%s\": %m",
    1185             :                         DIRECTORY_LOCK_FILE)));
    1186           0 :         close(fd);
    1187           0 :         return;
    1188             :     }
    1189          10 :     srcbuffer[len] = '\0';
    1190             : 
    1191             :     /*
    1192             :      * Advance over lines we are not supposed to rewrite, then copy them to
    1193             :      * destbuffer.
    1194             :      */
    1195          10 :     srcptr = srcbuffer;
    1196          70 :     for (lineno = 1; lineno < target_line; lineno++)
    1197             :     {
    1198          60 :         char       *eol = strchr(srcptr, '\n');
    1199             : 
    1200          60 :         if (eol == NULL)
    1201           0 :             break;              /* not enough lines in file yet */
    1202          60 :         srcptr = eol + 1;
    1203             :     }
    1204          10 :     memcpy(destbuffer, srcbuffer, srcptr - srcbuffer);
    1205          10 :     destptr = destbuffer + (srcptr - srcbuffer);
    1206             : 
    1207             :     /*
    1208             :      * Fill in any missing lines before the target line, in case lines are
    1209             :      * added to the file out of order.
    1210             :      */
    1211          10 :     for (; lineno < target_line; lineno++)
    1212             :     {
    1213           0 :         if (destptr < destbuffer + sizeof(destbuffer))
    1214           0 :             *destptr++ = '\n';
    1215             :     }
    1216             : 
    1217             :     /*
    1218             :      * Write or rewrite the target line.
    1219             :      */
    1220          10 :     snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s\n", str);
    1221          10 :     destptr += strlen(destptr);
    1222             : 
    1223             :     /*
    1224             :      * If there are more lines in the old file, append them to destbuffer.
    1225             :      */
    1226          10 :     if ((srcptr = strchr(srcptr, '\n')) != NULL)
    1227             :     {
    1228           3 :         srcptr++;
    1229           3 :         snprintf(destptr, destbuffer + sizeof(destbuffer) - destptr, "%s",
    1230             :                  srcptr);
    1231             :     }
    1232             : 
    1233             :     /*
    1234             :      * And rewrite the data.  Since we write in a single kernel call, this
    1235             :      * update should appear atomic to onlookers.
    1236             :      */
    1237          10 :     len = strlen(destbuffer);
    1238          10 :     errno = 0;
    1239          10 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE);
    1240          20 :     if (lseek(fd, (off_t) 0, SEEK_SET) != 0 ||
    1241          10 :         (int) write(fd, destbuffer, len) != len)
    1242             :     {
    1243           0 :         pgstat_report_wait_end();
    1244             :         /* if write didn't set errno, assume problem is no disk space */
    1245           0 :         if (errno == 0)
    1246           0 :             errno = ENOSPC;
    1247           0 :         ereport(LOG,
    1248             :                 (errcode_for_file_access(),
    1249             :                  errmsg("could not write to file \"%s\": %m",
    1250             :                         DIRECTORY_LOCK_FILE)));
    1251           0 :         close(fd);
    1252           0 :         return;
    1253             :     }
    1254          10 :     pgstat_report_wait_end();
    1255          10 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC);
    1256          10 :     if (pg_fsync(fd) != 0)
    1257             :     {
    1258           0 :         ereport(LOG,
    1259             :                 (errcode_for_file_access(),
    1260             :                  errmsg("could not write to file \"%s\": %m",
    1261             :                         DIRECTORY_LOCK_FILE)));
    1262             :     }
    1263          10 :     pgstat_report_wait_end();
    1264          10 :     if (close(fd) != 0)
    1265             :     {
    1266           0 :         ereport(LOG,
    1267             :                 (errcode_for_file_access(),
    1268             :                  errmsg("could not write to file \"%s\": %m",
    1269             :                         DIRECTORY_LOCK_FILE)));
    1270             :     }
    1271             : }
    1272             : 
    1273             : 
    1274             : /*
    1275             :  * Recheck that the data directory lock file still exists with expected
    1276             :  * content.  Return TRUE if the lock file appears OK, FALSE if it isn't.
    1277             :  *
    1278             :  * We call this periodically in the postmaster.  The idea is that if the
    1279             :  * lock file has been removed or replaced by another postmaster, we should
    1280             :  * do a panic database shutdown.  Therefore, we should return TRUE if there
    1281             :  * is any doubt: we do not want to cause a panic shutdown unnecessarily.
    1282             :  * Transient failures like EINTR or ENFILE should not cause us to fail.
    1283             :  * (If there really is something wrong, we'll detect it on a future recheck.)
    1284             :  */
    1285             : bool
    1286           1 : RecheckDataDirLockFile(void)
    1287             : {
    1288             :     int         fd;
    1289             :     int         len;
    1290             :     long        file_pid;
    1291             :     char        buffer[BLCKSZ];
    1292             : 
    1293           1 :     fd = open(DIRECTORY_LOCK_FILE, O_RDWR | PG_BINARY, 0);
    1294           1 :     if (fd < 0)
    1295             :     {
    1296             :         /*
    1297             :          * There are many foreseeable false-positive error conditions.  For
    1298             :          * safety, fail only on enumerated clearly-something-is-wrong
    1299             :          * conditions.
    1300             :          */
    1301           0 :         switch (errno)
    1302             :         {
    1303             :             case ENOENT:
    1304             :             case ENOTDIR:
    1305             :                 /* disaster */
    1306           0 :                 ereport(LOG,
    1307             :                         (errcode_for_file_access(),
    1308             :                          errmsg("could not open file \"%s\": %m",
    1309             :                                 DIRECTORY_LOCK_FILE)));
    1310           0 :                 return false;
    1311             :             default:
    1312             :                 /* non-fatal, at least for now */
    1313           0 :                 ereport(LOG,
    1314             :                         (errcode_for_file_access(),
    1315             :                          errmsg("could not open file \"%s\": %m; continuing anyway",
    1316             :                                 DIRECTORY_LOCK_FILE)));
    1317           0 :                 return true;
    1318             :         }
    1319             :     }
    1320           1 :     pgstat_report_wait_start(WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ);
    1321           1 :     len = read(fd, buffer, sizeof(buffer) - 1);
    1322           1 :     pgstat_report_wait_end();
    1323           1 :     if (len < 0)
    1324             :     {
    1325           0 :         ereport(LOG,
    1326             :                 (errcode_for_file_access(),
    1327             :                  errmsg("could not read from file \"%s\": %m",
    1328             :                         DIRECTORY_LOCK_FILE)));
    1329           0 :         close(fd);
    1330           0 :         return true;            /* treat read failure as nonfatal */
    1331             :     }
    1332           1 :     buffer[len] = '\0';
    1333           1 :     close(fd);
    1334           1 :     file_pid = atol(buffer);
    1335           1 :     if (file_pid == getpid())
    1336           1 :         return true;            /* all is well */
    1337             : 
    1338             :     /* Trouble: someone's overwritten the lock file */
    1339           0 :     ereport(LOG,
    1340             :             (errmsg("lock file \"%s\" contains wrong PID: %ld instead of %ld",
    1341             :                     DIRECTORY_LOCK_FILE, file_pid, (long) getpid())));
    1342           0 :     return false;
    1343             : }
    1344             : 
    1345             : 
    1346             : /*-------------------------------------------------------------------------
    1347             :  *              Version checking support
    1348             :  *-------------------------------------------------------------------------
    1349             :  */
    1350             : 
    1351             : /*
    1352             :  * Determine whether the PG_VERSION file in directory `path' indicates
    1353             :  * a data version compatible with the version of this program.
    1354             :  *
    1355             :  * If compatible, return. Otherwise, ereport(FATAL).
    1356             :  */
    1357             : void
    1358         344 : ValidatePgVersion(const char *path)
    1359             : {
    1360             :     char        full_path[MAXPGPATH];
    1361             :     FILE       *file;
    1362             :     int         ret;
    1363             :     long        file_major;
    1364             :     long        my_major;
    1365             :     char       *endptr;
    1366             :     char        file_version_string[64];
    1367         344 :     const char *my_version_string = PG_VERSION;
    1368             : 
    1369         344 :     my_major = strtol(my_version_string, &endptr, 10);
    1370             : 
    1371         344 :     snprintf(full_path, sizeof(full_path), "%s/PG_VERSION", path);
    1372             : 
    1373         344 :     file = AllocateFile(full_path, "r");
    1374         344 :     if (!file)
    1375             :     {
    1376           0 :         if (errno == ENOENT)
    1377           0 :             ereport(FATAL,
    1378             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1379             :                      errmsg("\"%s\" is not a valid data directory",
    1380             :                             path),
    1381             :                      errdetail("File \"%s\" is missing.", full_path)));
    1382             :         else
    1383           0 :             ereport(FATAL,
    1384             :                     (errcode_for_file_access(),
    1385             :                      errmsg("could not open file \"%s\": %m", full_path)));
    1386             :     }
    1387             : 
    1388         344 :     file_version_string[0] = '\0';
    1389         344 :     ret = fscanf(file, "%63s", file_version_string);
    1390         344 :     file_major = strtol(file_version_string, &endptr, 10);
    1391             : 
    1392         344 :     if (ret != 1 || endptr == file_version_string)
    1393           0 :         ereport(FATAL,
    1394             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1395             :                  errmsg("\"%s\" is not a valid data directory",
    1396             :                         path),
    1397             :                  errdetail("File \"%s\" does not contain valid data.",
    1398             :                            full_path),
    1399             :                  errhint("You might need to initdb.")));
    1400             : 
    1401         344 :     FreeFile(file);
    1402             : 
    1403         344 :     if (my_major != file_major)
    1404           0 :         ereport(FATAL,
    1405             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1406             :                  errmsg("database files are incompatible with server"),
    1407             :                  errdetail("The data directory was initialized by PostgreSQL version %s, "
    1408             :                            "which is not compatible with this version %s.",
    1409             :                            file_version_string, my_version_string)));
    1410         344 : }
    1411             : 
    1412             : /*-------------------------------------------------------------------------
    1413             :  *              Library preload support
    1414             :  *-------------------------------------------------------------------------
    1415             :  */
    1416             : 
    1417             : /*
    1418             :  * GUC variables: lists of library names to be preloaded at postmaster
    1419             :  * start and at backend start
    1420             :  */
    1421             : char       *session_preload_libraries_string = NULL;
    1422             : char       *shared_preload_libraries_string = NULL;
    1423             : char       *local_preload_libraries_string = NULL;
    1424             : 
    1425             : /* Flag telling that we are loading shared_preload_libraries */
    1426             : bool        process_shared_preload_libraries_in_progress = false;
    1427             : 
    1428             : /*
    1429             :  * load the shared libraries listed in 'libraries'
    1430             :  *
    1431             :  * 'gucname': name of GUC variable, for error reports
    1432             :  * 'restricted': if true, force libraries to be in $libdir/plugins/
    1433             :  */
    1434             : static void
    1435         433 : load_libraries(const char *libraries, const char *gucname, bool restricted)
    1436             : {
    1437             :     char       *rawstring;
    1438             :     List       *elemlist;
    1439             :     ListCell   *l;
    1440             : 
    1441         433 :     if (libraries == NULL || libraries[0] == '\0')
    1442         866 :         return;                 /* nothing to do */
    1443             : 
    1444             :     /* Need a modifiable copy of string */
    1445           0 :     rawstring = pstrdup(libraries);
    1446             : 
    1447             :     /* Parse string into list of filename paths */
    1448           0 :     if (!SplitDirectoriesString(rawstring, ',', &elemlist))
    1449             :     {
    1450             :         /* syntax error in list */
    1451           0 :         list_free_deep(elemlist);
    1452           0 :         pfree(rawstring);
    1453           0 :         ereport(LOG,
    1454             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    1455             :                  errmsg("invalid list syntax in parameter \"%s\"",
    1456             :                         gucname)));
    1457           0 :         return;
    1458             :     }
    1459             : 
    1460           0 :     foreach(l, elemlist)
    1461             :     {
    1462             :         /* Note that filename was already canonicalized */
    1463           0 :         char       *filename = (char *) lfirst(l);
    1464           0 :         char       *expanded = NULL;
    1465             : 
    1466             :         /* If restricting, insert $libdir/plugins if not mentioned already */
    1467           0 :         if (restricted && first_dir_separator(filename) == NULL)
    1468             :         {
    1469           0 :             expanded = psprintf("$libdir/plugins/%s", filename);
    1470           0 :             filename = expanded;
    1471             :         }
    1472           0 :         load_file(filename, restricted);
    1473           0 :         ereport(DEBUG1,
    1474             :                 (errmsg("loaded library \"%s\"", filename)));
    1475           0 :         if (expanded)
    1476           0 :             pfree(expanded);
    1477             :     }
    1478             : 
    1479           0 :     list_free_deep(elemlist);
    1480           0 :     pfree(rawstring);
    1481             : }
    1482             : 
    1483             : /*
    1484             :  * process any libraries that should be preloaded at postmaster start
    1485             :  */
    1486             : void
    1487           1 : process_shared_preload_libraries(void)
    1488             : {
    1489           1 :     process_shared_preload_libraries_in_progress = true;
    1490           1 :     load_libraries(shared_preload_libraries_string,
    1491             :                    "shared_preload_libraries",
    1492             :                    false);
    1493           1 :     process_shared_preload_libraries_in_progress = false;
    1494           1 : }
    1495             : 
    1496             : /*
    1497             :  * process any libraries that should be preloaded at backend start
    1498             :  */
    1499             : void
    1500         216 : process_session_preload_libraries(void)
    1501             : {
    1502         216 :     load_libraries(session_preload_libraries_string,
    1503             :                    "session_preload_libraries",
    1504             :                    false);
    1505         216 :     load_libraries(local_preload_libraries_string,
    1506             :                    "local_preload_libraries",
    1507             :                    true);
    1508         216 : }
    1509             : 
    1510             : void
    1511         160 : pg_bindtextdomain(const char *domain)
    1512             : {
    1513             : #ifdef ENABLE_NLS
    1514             :     if (my_exec_path[0] != '\0')
    1515             :     {
    1516             :         char        locale_path[MAXPGPATH];
    1517             : 
    1518             :         get_locale_path(my_exec_path, locale_path);
    1519             :         bindtextdomain(domain, locale_path);
    1520             :         pg_bind_textdomain_codeset(domain);
    1521             :     }
    1522             : #endif
    1523         160 : }

Generated by: LCOV version 1.11