*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
***************
*** 1313,1385 **** getInstallationPaths(const char *argv0)
  static void
  checkDataDir(void)
  {
  	char		path[MAXPGPATH];
  	FILE	   *fp;
- 	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 group or world access.  If so, reject.
- 	 *
- 	 * It would be possible to allow weaker constraints (for example, allow
- 	 * group access) but we cannot make a general assumption that that is
- 	 * okay; for example there are platforms where nearly all users
- 	 * customarily belong to the same group.  Perhaps this test should be
- 	 * configurable.
- 	 *
- 	 * 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 & (S_IRWXG | S_IRWXO))
- 		ereport(FATAL,
- 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- 				 errmsg("data directory \"%s\" has group or world access",
- 						DataDir),
- 				 errdetail("Permissions should be u=rwx (0700).")));
- #endif
- 
  	/* Look for PG_VERSION before looking for pg_control */
  	ValidatePgVersion(DataDir);
  
--- 1313,1363 ----
  static void
  checkDataDir(void)
  {
+ 	CheckDirErrcode	err;
  	char		path[MAXPGPATH];
  	FILE	   *fp;
  
  	Assert(DataDir);
  
! 	err = checkDirectoryPermissions(DataDir);
! 	switch (err)
  	{
! 		case CKDIR_OK:
! 			break;
! 		case CKDIR_NOT_EXISTS:
  			ereport(FATAL,
  					(errcode_for_file_access(),
  					 errmsg("data directory \"%s\" does not exist",
  							DataDir)));
! 			break;
! 		case CKDIR_CANT_READ_PERMS:
  			ereport(FATAL,
  					(errcode_for_file_access(),
! 					 errmsg("could not read permissions of data directory \"%s\": %m",
! 							DataDir)));
! 			break;
! 		case CKDIR_NOT_DIR:
! 			ereport(FATAL,
! 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 					 errmsg("specified data directory \"%s\" is not a directory",
! 							DataDir)));
! 			break;
! 		case CKDIR_WRONG_OWNER:
! 			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.")));
! 			break;
! 		case CKDIR_TOO_ACCESSIBLE:
! 			ereport(FATAL,
! 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 					 errmsg("data directory \"%s\" has group or world access",
! 							DataDir),
! 					 errdetail("Permissions should be u=rwx (0700).")));
! 			break;
  	}
  
  	/* Look for PG_VERSION before looking for pg_control */
  	ValidatePgVersion(DataDir);
  
*** a/src/include/port.h
--- b/src/include/port.h
***************
*** 463,468 **** extern char *inet_net_ntop(int af, const void *src, int bits,
--- 463,479 ----
  /* port/pgcheckdir.c */
  extern int	pg_check_dir(const char *dir);
  
+ typedef enum
+ {
+ 	CKDIR_OK,
+ 	CKDIR_NOT_EXISTS,
+ 	CKDIR_CANT_READ_PERMS,
+ 	CKDIR_NOT_DIR,
+ 	CKDIR_WRONG_OWNER,
+ 	CKDIR_TOO_ACCESSIBLE
+ } CheckDirErrcode;
+ extern CheckDirErrcode checkDirectoryPermissions(char *directory);
+ 
  /* port/pgmkdirp.c */
  extern int	pg_mkdir_p(char *path, int omode);
  
*** a/src/port/pgcheckdir.c
--- b/src/port/pgcheckdir.c
***************
*** 14,19 ****
--- 14,22 ----
  #include "c.h"
  
  #include <dirent.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
  
  
  /*
***************
*** 88,90 **** pg_check_dir(const char *dir)
--- 91,147 ----
  
  	return result;
  }
+ 
+ /*
+  * Verify permissions of a directory
+  */
+ CheckDirErrcode
+ checkDirectoryPermissions(char *directory)
+ {
+ 	struct stat stat_buf;
+ 
+ 	if (stat(directory, &stat_buf) != 0)
+ 	{
+ 		if (errno == ENOENT)
+ 			return CKDIR_NOT_EXISTS;
+ 		else
+ 			return CKDIR_CANT_READ_PERMS;
+ 	}
+ 
+ 	if (!S_ISDIR(stat_buf.st_mode))
+ 		return CKDIR_NOT_DIR;
+ 
+ 	/*
+ 	 * 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())
+ 		return CKDIR_WRONG_OWNER;
+ #endif
+ 
+ 	/*
+ 	 * Check if the directory has group or world access.  If so, reject.
+ 	 *
+ 	 * It would be possible to allow weaker constraints (for example, allow
+ 	 * group access) but we cannot make a general assumption that that is
+ 	 * okay; for example there are platforms where nearly all users
+ 	 * customarily belong to the same group.  Perhaps this test should be
+ 	 * configurable.
+ 	 *
+ 	 * 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 & (S_IRWXG | S_IRWXO))
+ 		return CKDIR_TOO_ACCESSIBLE;
+ #endif
+ 
+ 	return CKDIR_OK;
+ }
