@ -88,6 +88,100 @@ SetDatabasePath(const char *path)
DatabasePath = MemoryContextStrdup ( TopMemoryContext , path ) ;
}
/*
* Validate the proposed data directory .
*
* Also initialize file and directory create modes and mode mask .
*/
void
checkDataDir ( void )
{
struct stat stat_buf ;
Assert ( DataDir ) ;
if ( stat ( DataDir , & stat_buf ) ! = 0 )
{
if ( errno = = ENOENT )
ereport ( FATAL ,
( errcode_for_file_access ( ) ,
errmsg ( " data directory \" %s \" does not exist " ,
DataDir ) ) ) ;
else
ereport ( FATAL ,
( errcode_for_file_access ( ) ,
errmsg ( " could not read permissions of directory \" %s \" : %m " ,
DataDir ) ) ) ;
}
/* eventual chdir would fail anyway, but let's test ... */
if ( ! S_ISDIR ( stat_buf . st_mode ) )
ereport ( FATAL ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
errmsg ( " specified data directory \" %s \" is not a directory " ,
DataDir ) ) ) ;
/*
* Check that the directory belongs to my userid ; if not , reject .
*
* This check is an essential part of the interlock that prevents two
* postmasters from starting in the same directory ( see CreateLockFile ( ) ) .
* Do not remove or weaken it .
*
* XXX can we safely enable this check on Windows ?
*/
# if !defined(WIN32) && !defined(__CYGWIN__)
if ( stat_buf . st_uid ! = geteuid ( ) )
ereport ( FATAL ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
errmsg ( " data directory \" %s \" has wrong ownership " ,
DataDir ) ,
errhint ( " The server must be started by the user that owns the data directory. " ) ) ) ;
# endif
/*
* Check if the directory has correct permissions . If not , reject .
*
* Only two possible modes are allowed , 0700 and 0750. The latter mode
* indicates that group read / execute should be allowed on all newly
* created files and directories .
*
* XXX temporarily suppress check when on Windows , because there may not
* be proper support for Unix - y file permissions . Need to think of a
* reasonable check to apply on Windows .
*/
# if !defined(WIN32) && !defined(__CYGWIN__)
if ( stat_buf . st_mode & PG_MODE_MASK_GROUP )
ereport ( FATAL ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
errmsg ( " data directory \" %s \" has invalid permissions " ,
DataDir ) ,
errdetail ( " Permissions should be u=rwx (0700) or u=rwx,g=rx (0750). " ) ) ) ;
# endif
/*
* Reset creation modes and mask based on the mode of the data directory .
*
* The mask was set earlier in startup to disallow group permissions on
* newly created files and directories . However , if group read / execute
* are present on the data directory then modify the create modes and mask
* to allow group read / execute on newly created files and directories and
* set the data_directory_mode GUC .
*
* Suppress when on Windows , because there may not be proper support for
* Unix - y file permissions .
*/
# if !defined(WIN32) && !defined(__CYGWIN__)
SetDataDirectoryCreatePerm ( stat_buf . st_mode ) ;
umask ( pg_mode_mask ) ;
data_directory_mode = pg_dir_create_mode ;
# endif
/* Check for PG_VERSION */
ValidatePgVersion ( DataDir ) ;
}
/*
* Set data directory , but make sure it ' s an absolute path . Use this ,
* never set DataDir directly .
@ -829,7 +923,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
/*
* Try to create the lock file - - - O_EXCL makes this atomic .
*
* Think not to make the file protection weaker than 060 0. See
* Think not to make the file protection weaker than 0600 / 064 0. See
* comments below .
*/
fd = open ( filename , O_RDWR | O_CREAT | O_EXCL , pg_file_create_mode ) ;
@ -899,17 +993,14 @@ CreateLockFile(const char *filename, bool amPostmaster,
* 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 . )
* other than its own , as enforced in checkDataDir ( ) . Also , since we
* create the lockfiles mode 0600 / 0640 , 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 )