]> granicus.if.org Git - postgresql/commitdiff
Refactor dir/file permissions
authorStephen Frost <sfrost@snowman.net>
Sat, 7 Apr 2018 21:45:39 +0000 (17:45 -0400)
committerStephen Frost <sfrost@snowman.net>
Sat, 7 Apr 2018 21:45:39 +0000 (17:45 -0400)
Consolidate directory and file create permissions for tools which work
with the PG data directory by adding a new module (common/file_perm.c)
that contains variables (pg_file_create_mode, pg_dir_create_mode) and
constants to initialize them (0600 for files and 0700 for directories).

Convert mkdir() calls in the backend to MakePGDirectory() if the
original call used default permissions (always the case for regular PG
directories).

Add tests to make sure permissions in PGDATA are set correctly by the
tools which modify the PG data directory.

Authors: David Steele <david@pgmasters.net>,
         Adam Brightwell <adam.brightwell@crunchydata.com>
Reviewed-By: Michael Paquier, with discussion amongst many others.
Discussion: https://postgr.es/m/ad346fe6-b23e-59f1-ecb7-0e08390ad629%40pgmasters.net

34 files changed:
src/backend/access/transam/xlog.c
src/backend/commands/tablespace.c
src/backend/postmaster/postmaster.c
src/backend/postmaster/syslogger.c
src/backend/replication/basebackup.c
src/backend/replication/slot.c
src/backend/storage/file/copydir.c
src/backend/storage/file/fd.c
src/backend/storage/ipc/dsm_impl.c
src/backend/storage/ipc/ipc.c
src/backend/utils/init/miscinit.c
src/bin/initdb/initdb.c
src/bin/initdb/t/001_initdb.pl
src/bin/pg_basebackup/pg_basebackup.c
src/bin/pg_basebackup/t/010_pg_basebackup.pl
src/bin/pg_basebackup/t/020_pg_receivewal.pl
src/bin/pg_basebackup/walmethods.c
src/bin/pg_ctl/pg_ctl.c
src/bin/pg_ctl/t/001_start_stop.pl
src/bin/pg_resetwal/pg_resetwal.c
src/bin/pg_resetwal/t/001_basic.pl
src/bin/pg_rewind/RewindTest.pm
src/bin/pg_rewind/file_ops.c
src/bin/pg_rewind/t/001_basic.pl
src/bin/pg_upgrade/file.c
src/bin/pg_upgrade/pg_upgrade.c
src/bin/pg_upgrade/test.sh
src/common/Makefile
src/common/file_perm.c [new file with mode: 0644]
src/include/common/file_perm.h [new file with mode: 0644]
src/include/storage/fd.h
src/test/perl/PostgresNode.pm
src/test/perl/TestLib.pm
src/tools/msvc/Mkvcbuild.pm

index 813b2afaac2e8490bc67c61ef503280d1406847f..4a47395174cafe11ab473d827c6847af5aefb18f 100644 (file)
@@ -4107,7 +4107,7 @@ ValidateXLOGDirectoryStructure(void)
        {
                ereport(LOG,
                                (errmsg("creating missing WAL directory \"%s\"", path)));
-               if (mkdir(path, S_IRWXU) < 0)
+               if (MakePGDirectory(path) < 0)
                        ereport(FATAL,
                                        (errmsg("could not create missing directory \"%s\": %m",
                                                        path)));
index 5c450caa4ee16f0e8349a57e941c8746b4d76cc3..f7e9160a4f6e11b2d496dee92bd810bb117941e3 100644 (file)
@@ -68,6 +68,7 @@
 #include "commands/seclabel.h"
 #include "commands/tablecmds.h"
 #include "commands/tablespace.h"
+#include "common/file_perm.h"
 #include "miscadmin.h"
 #include "postmaster/bgwriter.h"
 #include "storage/fd.h"
@@ -151,7 +152,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
                        else
                        {
                                /* Directory creation failed? */
-                               if (mkdir(dir, S_IRWXU) < 0)
+                               if (MakePGDirectory(dir) < 0)
                                {
                                        char       *parentdir;
 
@@ -173,7 +174,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
                                        get_parent_directory(parentdir);
                                        get_parent_directory(parentdir);
                                        /* Can't create parent and it doesn't already exist? */
-                                       if (mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
+                                       if (MakePGDirectory(parentdir) < 0 && errno != EEXIST)
                                                ereport(ERROR,
                                                                (errcode_for_file_access(),
                                                                 errmsg("could not create directory \"%s\": %m",
@@ -184,7 +185,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
                                        parentdir = pstrdup(dir);
                                        get_parent_directory(parentdir);
                                        /* Can't create parent and it doesn't already exist? */
-                                       if (mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
+                                       if (MakePGDirectory(parentdir) < 0 && errno != EEXIST)
                                                ereport(ERROR,
                                                                (errcode_for_file_access(),
                                                                 errmsg("could not create directory \"%s\": %m",
@@ -192,7 +193,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
                                        pfree(parentdir);
 
                                        /* Create database directory */
-                                       if (mkdir(dir, S_IRWXU) < 0)
+                                       if (MakePGDirectory(dir) < 0)
                                                ereport(ERROR,
                                                                (errcode_for_file_access(),
                                                                 errmsg("could not create directory \"%s\": %m",
@@ -279,7 +280,8 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
        /*
         * Check that location isn't too long. Remember that we're going to append
         * 'PG_XXX/<dboid>/<relid>_<fork>.<nnn>'.  FYI, we never actually
-        * reference the whole path here, but mkdir() uses the first two parts.
+        * reference the whole path here, but MakePGDirectory() uses the first two
+        * parts.
         */
        if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
                OIDCHARS + 1 + OIDCHARS + 1 + FORKNAMECHARS + 1 + OIDCHARS > MAXPGPATH)
@@ -574,7 +576,7 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
         * Attempt to coerce target directory to safe permissions.  If this fails,
         * it doesn't exist or has the wrong owner.
         */
-       if (chmod(location, S_IRWXU) != 0)
+       if (chmod(location, pg_dir_create_mode) != 0)
        {
                if (errno == ENOENT)
                        ereport(ERROR,
@@ -599,7 +601,7 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
                if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
                {
                        if (!rmtree(location_with_version_dir, true))
-                               /* If this failed, mkdir() below is going to error. */
+                               /* If this failed, MakePGDirectory() below is going to error. */
                                ereport(WARNING,
                                                (errmsg("some useless files may be left behind in old database directory \"%s\"",
                                                                location_with_version_dir)));
@@ -610,7 +612,7 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
         * The creation of the version directory prevents more than one tablespace
         * in a single location.
         */
-       if (mkdir(location_with_version_dir, S_IRWXU) < 0)
+       if (MakePGDirectory(location_with_version_dir) < 0)
        {
                if (errno == EEXIST)
                        ereport(ERROR,
index 3dfb87d7019073e4c6510bc910b1fefc26980633..10afecffb37e160c06cf66311d91dae14550cc16 100644 (file)
@@ -97,6 +97,7 @@
 #include "access/xlog.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/pg_control.h"
+#include "common/file_perm.h"
 #include "common/ip.h"
 #include "lib/ilist.h"
 #include "libpq/auth.h"
@@ -589,7 +590,7 @@ PostmasterMain(int argc, char *argv[])
        /*
         * for security, no dir or file created can be group or other accessible
         */
-       umask(S_IRWXG | S_IRWXO);
+       umask(PG_MODE_MASK_OWNER);
 
        /*
         * Initialize random(3) so we don't get the same values in every run.
@@ -4490,9 +4491,9 @@ internal_forkexec(int argc, char *argv[], Port *port)
        {
                /*
                 * As in OpenTemporaryFileInTablespace, try to make the temp-file
-                * directory
+                * directory, ignoring errors.
                 */
-               mkdir(PG_TEMP_FILES_DIR, S_IRWXU);
+               (void) MakePGDirectory(PG_TEMP_FILES_DIR);
 
                fp = AllocateFile(tmpfilename, PG_BINARY_W);
                if (!fp)
index f70eea37df9e73833375c04016f0fa9f83c82988..58b759f305f39f53179b3936f94c330f8230d532 100644 (file)
@@ -41,6 +41,7 @@
 #include "postmaster/postmaster.h"
 #include "postmaster/syslogger.h"
 #include "storage/dsm.h"
+#include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
 #include "storage/pg_shmem.h"
@@ -322,7 +323,7 @@ SysLoggerMain(int argc, char *argv[])
                                /*
                                 * Also, create new directory if not present; ignore errors
                                 */
-                               mkdir(Log_directory, S_IRWXU);
+                               (void) MakePGDirectory(Log_directory);
                        }
                        if (strcmp(Log_filename, currentLogFilename) != 0)
                        {
@@ -564,7 +565,7 @@ SysLogger_Start(void)
        /*
         * Create log directory if not present; ignore errors
         */
-       mkdir(Log_directory, S_IRWXU);
+       (void) MakePGDirectory(Log_directory);
 
        /*
         * The initial logfile is created right in the postmaster, to verify that
index 8ba29453b91d33b8852ec63a65e7a73bd74036e6..babf85a6eaf62a6ac4776ef111a1789e2ceb57be 100644 (file)
@@ -19,6 +19,7 @@
 #include "access/xlog_internal.h"      /* for pg_start/stop_backup */
 #include "catalog/catalog.h"
 #include "catalog/pg_type.h"
+#include "common/file_perm.h"
 #include "lib/stringinfo.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
@@ -930,7 +931,7 @@ sendFileWithContent(const char *filename, const char *content)
        statbuf.st_gid = getegid();
 #endif
        statbuf.st_mtime = time(NULL);
-       statbuf.st_mode = S_IRUSR | S_IWUSR;
+       statbuf.st_mode = pg_file_create_mode;
        statbuf.st_size = len;
 
        _tarWriteHeader(filename, NULL, &statbuf, false);
@@ -1628,7 +1629,7 @@ _tarWriteDir(const char *pathbuf, int basepathlen, struct stat *statbuf,
 #else
        if (pgwin32_is_junction(pathbuf))
 #endif
-               statbuf->st_mode = S_IFDIR | S_IRWXU;
+               statbuf->st_mode = S_IFDIR | pg_dir_create_mode;
 
        return _tarWriteHeader(pathbuf + basepathlen + 1, NULL, statbuf, sizeonly);
 }
index fc9ef22b0be26a49bde7e5fc10a47ae75ee1bf2f..056628fe8e3fc23541e6634ed0b30ba691bc1fa5 100644 (file)
@@ -1166,13 +1166,14 @@ CreateSlotOnDisk(ReplicationSlot *slot)
         * It's just barely possible that some previous effort to create or drop a
         * slot with this name left a temp directory lying around. If that seems
         * to be the case, try to remove it.  If the rmtree() fails, we'll error
-        * out at the mkdir() below, so we don't bother checking success.
+        * out at the MakePGDirectory() below, so we don't bother checking
+        * success.
         */
        if (stat(tmppath, &st) == 0 && S_ISDIR(st.st_mode))
                rmtree(tmppath, true);
 
        /* Create and fsync the temporary slot directory. */
-       if (mkdir(tmppath, S_IRWXU) < 0)
+       if (MakePGDirectory(tmppath) < 0)
                ereport(ERROR,
                                (errcode_for_file_access(),
                                 errmsg("could not create directory \"%s\": %m",
index ca6342db0d2aa754588d4972ffbfd0deb80a9b19..4a0d23b11e30dcac2b9a931e41bc1db7b8595c20 100644 (file)
@@ -41,7 +41,7 @@ copydir(char *fromdir, char *todir, bool recurse)
        char            fromfile[MAXPGPATH * 2];
        char            tofile[MAXPGPATH * 2];
 
-       if (mkdir(todir, S_IRWXU) != 0)
+       if (MakePGDirectory(todir) != 0)
                ereport(ERROR,
                                (errcode_for_file_access(),
                                 errmsg("could not create directory \"%s\": %m", todir)));
index d30a725f9009aec46fbbd6fb73383f0efef615f9..36eea9d11d05e67a1066988ab9dbf841e99aa488 100644 (file)
@@ -84,6 +84,7 @@
 #include "access/xlog.h"
 #include "catalog/catalog.h"
 #include "catalog/pg_tablespace.h"
+#include "common/file_perm.h"
 #include "pgstat.h"
 #include "portability/mem.h"
 #include "storage/fd.h"
  */
 #define FD_MINFREE                             10
 
-/*
- * Default mode for created files, unless something else is specified using
- * the *Perm() function variants.
- */
-#define PG_FILE_MODE_DEFAULT   (S_IRUSR | S_IWUSR)
-
 /*
  * A number of platforms allow individual processes to open many more files
  * than they can really support when *many* processes do the same thing.
@@ -937,7 +932,7 @@ set_max_safe_fds(void)
 int
 BasicOpenFile(const char *fileName, int fileFlags)
 {
-       return BasicOpenFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT);
+       return BasicOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
 }
 
 /*
@@ -1356,7 +1351,7 @@ FileInvalidate(File file)
 File
 PathNameOpenFile(const char *fileName, int fileFlags)
 {
-       return PathNameOpenFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT);
+       return PathNameOpenFilePerm(fileName, fileFlags, pg_file_create_mode);
 }
 
 /*
@@ -1434,7 +1429,7 @@ PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
 void
 PathNameCreateTemporaryDir(const char *basedir, const char *directory)
 {
-       if (mkdir(directory, S_IRWXU) < 0)
+       if (MakePGDirectory(directory) < 0)
        {
                if (errno == EEXIST)
                        return;
@@ -1444,14 +1439,14 @@ PathNameCreateTemporaryDir(const char *basedir, const char *directory)
                 * EEXIST to close a race against another process following the same
                 * algorithm.
                 */
-               if (mkdir(basedir, S_IRWXU) < 0 && errno != EEXIST)
+               if (MakePGDirectory(basedir) < 0 && errno != EEXIST)
                        ereport(ERROR,
                                        (errcode_for_file_access(),
                                         errmsg("cannot create temporary directory \"%s\": %m",
                                                        basedir)));
 
                /* Try again. */
-               if (mkdir(directory, S_IRWXU) < 0 && errno != EEXIST)
+               if (MakePGDirectory(directory) < 0 && errno != EEXIST)
                        ereport(ERROR,
                                        (errcode_for_file_access(),
                                         errmsg("cannot create temporary subdirectory \"%s\": %m",
@@ -1601,11 +1596,11 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
                 * We might need to create the tablespace's tempfile directory, if no
                 * one has yet done so.
                 *
-                * Don't check for error from mkdir; it could fail if someone else
-                * just did the same thing.  If it doesn't work then we'll bomb out on
-                * the second create attempt, instead.
+                * Don't check for an error from MakePGDirectory; it could fail if
+                * someone else just did the same thing.  If it doesn't work then
+                * we'll bomb out on the second create attempt, instead.
                 */
-               mkdir(tempdirpath, S_IRWXU);
+               (void) MakePGDirectory(tempdirpath);
 
                file = PathNameOpenFile(tempfilepath,
                                                                O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
@@ -2401,7 +2396,7 @@ TryAgain:
 int
 OpenTransientFile(const char *fileName, int fileFlags)
 {
-       return OpenTransientFilePerm(fileName, fileFlags, PG_FILE_MODE_DEFAULT);
+       return OpenTransientFilePerm(fileName, fileFlags, pg_file_create_mode);
 }
 
 /*
@@ -3554,3 +3549,27 @@ fsync_parent_path(const char *fname, int elevel)
 
        return 0;
 }
+
+/*
+ * Create a PostgreSQL data sub-directory
+ *
+ * The data directory itself, along with most other directories, are created at
+ * initdb-time, but we do have some occations where we create directories from
+ * the backend (CREATE TABLESPACE, for example).  In those cases, we want to
+ * make sure that those directories are created consistently.  Today, that means
+ * making sure that the created directory has the correct permissions, which is
+ * what pg_dir_create_mode tracks for us.
+ *
+ * Note that we also set the umask() based on what we understand the correct
+ * permissions to be (see file_perm.c).
+ *
+ * For permissions other than the default mkdir() can be used directly, but be
+ * sure to consider carefully such cases -- a directory with incorrect
+ * permissions in a PostgreSQL data directory could cause backups and other
+ * processes to fail.
+ */
+int
+MakePGDirectory(const char *directoryName)
+{
+       return mkdir(directoryName, pg_dir_create_mode);
+}
index 67e76b98fe7982d4013d8c484072438565b9c06d..2fca9fae512e34ead3cd05c15958c65deb851d88 100644 (file)
@@ -60,6 +60,7 @@
 #ifdef HAVE_SYS_SHM_H
 #include <sys/shm.h>
 #endif
+#include "common/file_perm.h"
 #include "pgstat.h"
 
 #include "portability/mem.h"
@@ -285,7 +286,7 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
         * returning.
         */
        flags = O_RDWR | (op == DSM_OP_CREATE ? O_CREAT | O_EXCL : 0);
-       if ((fd = shm_open(name, flags, 0600)) == -1)
+       if ((fd = shm_open(name, flags, PG_FILE_MODE_OWNER)) == -1)
        {
                if (errno != EEXIST)
                        ereport(elevel,
index fc0a9c075660e9308366a513d182205ecfc80b08..53f7c1e77ea9df6db0395646423c856305f37acc 100644 (file)
@@ -137,6 +137,10 @@ proc_exit(int code)
                else
                        snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
 
+               /*
+                * Use mkdir() instead of MakePGDirectory() since we aren't making a
+                * PG directory here.
+                */
                mkdir("gprof", S_IRWXU | S_IRWXG | S_IRWXO);
                mkdir(gprofDirName, S_IRWXU | S_IRWXG | S_IRWXO);
                chdir(gprofDirName);
index 87ed7d3f71551874efdcb9d801504e0f613375f7..f8f08f3f88bfe9190466e1223790db14a8037ed4 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "access/htup_details.h"
 #include "catalog/pg_authid.h"
+#include "common/file_perm.h"
 #include "libpq/libpq.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
@@ -831,7 +832,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
                 * Think not to make the file protection weaker than 0600.  See
                 * comments below.
                 */
-               fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+               fd = open(filename, O_RDWR | O_CREAT | O_EXCL, pg_file_create_mode);
                if (fd >= 0)
                        break;                          /* Success; exit the retry loop */
 
@@ -848,7 +849,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
                 * Read the file to get the old owner's PID.  Note race condition
                 * here: file might have been deleted since we tried to create it.
                 */
-               fd = open(filename, O_RDONLY, 0600);
+               fd = open(filename, O_RDONLY, pg_file_create_mode);
                if (fd < 0)
                {
                        if (errno == ENOENT)
index 78990f5a2736749fd309cf45ae4e8e244b879976..3765548a249c3160fa8b715ec6f228bdc61ce85d 100644 (file)
@@ -64,6 +64,7 @@
 #include "catalog/pg_authid.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_collation.h"
+#include "common/file_perm.h"
 #include "common/file_utils.h"
 #include "common/restricted_token.h"
 #include "common/username.h"
@@ -1170,7 +1171,7 @@ setup_config(void)
        snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
 
        writefile(path, conflines);
-       if (chmod(path, S_IRUSR | S_IWUSR) != 0)
+       if (chmod(path, pg_file_create_mode) != 0)
        {
                fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
                                progname, path, strerror(errno));
@@ -1190,7 +1191,7 @@ setup_config(void)
        sprintf(path, "%s/postgresql.auto.conf", pg_data);
 
        writefile(path, autoconflines);
-       if (chmod(path, S_IRUSR | S_IWUSR) != 0)
+       if (chmod(path, pg_file_create_mode) != 0)
        {
                fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
                                progname, path, strerror(errno));
@@ -1277,7 +1278,7 @@ setup_config(void)
        snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
 
        writefile(path, conflines);
-       if (chmod(path, S_IRUSR | S_IWUSR) != 0)
+       if (chmod(path, pg_file_create_mode) != 0)
        {
                fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
                                progname, path, strerror(errno));
@@ -1293,7 +1294,7 @@ setup_config(void)
        snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data);
 
        writefile(path, conflines);
-       if (chmod(path, S_IRUSR | S_IWUSR) != 0)
+       if (chmod(path, pg_file_create_mode) != 0)
        {
                fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
                                progname, path, strerror(errno));
@@ -2692,7 +2693,7 @@ create_data_directory(void)
                                   pg_data);
                        fflush(stdout);
 
-                       if (pg_mkdir_p(pg_data, S_IRWXU) != 0)
+                       if (pg_mkdir_p(pg_data, pg_dir_create_mode) != 0)
                        {
                                fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
                                                progname, pg_data, strerror(errno));
@@ -2710,7 +2711,7 @@ create_data_directory(void)
                                   pg_data);
                        fflush(stdout);
 
-                       if (chmod(pg_data, S_IRWXU) != 0)
+                       if (chmod(pg_data, pg_dir_create_mode) != 0)
                        {
                                fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
                                                progname, pg_data, strerror(errno));
@@ -2778,7 +2779,7 @@ create_xlog_or_symlink(void)
                                           xlog_dir);
                                fflush(stdout);
 
-                               if (pg_mkdir_p(xlog_dir, S_IRWXU) != 0)
+                               if (pg_mkdir_p(xlog_dir, pg_dir_create_mode) != 0)
                                {
                                        fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
                                                        progname, xlog_dir, strerror(errno));
@@ -2796,7 +2797,7 @@ create_xlog_or_symlink(void)
                                           xlog_dir);
                                fflush(stdout);
 
-                               if (chmod(xlog_dir, S_IRWXU) != 0)
+                               if (chmod(xlog_dir, pg_dir_create_mode) != 0)
                                {
                                        fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
                                                        progname, xlog_dir, strerror(errno));
@@ -2846,7 +2847,7 @@ create_xlog_or_symlink(void)
        else
        {
                /* Without -X option, just make the subdirectory normally */
-               if (mkdir(subdirloc, S_IRWXU) < 0)
+               if (mkdir(subdirloc, pg_dir_create_mode) < 0)
                {
                        fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
                                        progname, subdirloc, strerror(errno));
@@ -2882,7 +2883,8 @@ initialize_data_directory(void)
 
        setup_signals();
 
-       umask(S_IRWXG | S_IRWXO);
+       /* Set dir/file mode mask */
+       umask(PG_MODE_MASK_OWNER);
 
        create_data_directory();
 
@@ -2902,7 +2904,7 @@ initialize_data_directory(void)
                 * The parent directory already exists, so we only need mkdir() not
                 * pg_mkdir_p() here, which avoids some failure modes; cf bug #13853.
                 */
-               if (mkdir(path, S_IRWXU) < 0)
+               if (mkdir(path, pg_dir_create_mode) < 0)
                {
                        fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
                                        progname, path, strerror(errno));
index c0cfa6e92c491fe0d262254ce87e7850456f6fca..9dfb2ed96ff20b3e1cb15609557fd7aacd6bdef7 100644 (file)
@@ -6,7 +6,7 @@ use strict;
 use warnings;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 15;
+use Test::More tests => 16;
 
 my $tempdir = TestLib::tempdir;
 my $xlogdir = "$tempdir/pgxlog";
@@ -45,6 +45,15 @@ mkdir $datadir;
 
        command_ok([ 'initdb', '-N', '-T', 'german', '-X', $xlogdir, $datadir ],
                'successful creation');
+
+       # Permissions on PGDATA should be default
+       SKIP:
+       {
+               skip "unix-style permissions not supported on Windows", 1 if ($windows_os);
+
+               ok(check_mode_recursive($datadir, 0700, 0600),
+                  "check PGDATA permissions");
+       }
 }
 command_ok([ 'initdb', '-S', $datadir ], 'sync only');
 command_fails([ 'initdb', $datadir ], 'existing data directory');
index 8610fe8a1a89dd0e53f2f80f978141125ac1b319..32b41e313cc35b9638b3531128b4a8aa170cdcdd 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include "access/xlog_internal.h"
+#include "common/file_perm.h"
 #include "common/file_utils.h"
 #include "common/string.h"
 #include "fe_utils/string_utils.h"
@@ -629,7 +630,7 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
                                 PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
                                 "pg_xlog" : "pg_wal");
 
-               if (pg_mkdir_p(statusdir, S_IRWXU) != 0 && errno != EEXIST)
+               if (pg_mkdir_p(statusdir, pg_dir_create_mode) != 0 && errno != EEXIST)
                {
                        fprintf(stderr,
                                        _("%s: could not create directory \"%s\": %s\n"),
@@ -685,7 +686,7 @@ verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
                        /*
                         * Does not exist, so create
                         */
-                       if (pg_mkdir_p(dirname, S_IRWXU) == -1)
+                       if (pg_mkdir_p(dirname, pg_dir_create_mode) == -1)
                        {
                                fprintf(stderr,
                                                _("%s: could not create directory \"%s\": %s\n"),
@@ -1129,7 +1130,7 @@ ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
 
                                tarCreateHeader(header, "recovery.conf", NULL,
                                                                recoveryconfcontents->len,
-                                                               0600, 04000, 02000,
+                                                               pg_file_create_mode, 04000, 02000,
                                                                time(NULL));
 
                                padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
@@ -1441,7 +1442,7 @@ ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
                                         * Directory
                                         */
                                        filename[strlen(filename) - 1] = '\0';  /* Remove trailing slash */
-                                       if (mkdir(filename, S_IRWXU) != 0)
+                                       if (mkdir(filename, pg_dir_create_mode) != 0)
                                        {
                                                /*
                                                 * When streaming WAL, pg_wal (or pg_xlog for pre-9.6
index afb392dbb3936abc21705f93222da866c353ab88..ac5bb99f1b84bd913ab1c51b1ba4a1e5410c3448 100644 (file)
@@ -6,7 +6,7 @@ use File::Basename qw(basename dirname);
 use File::Path qw(rmtree);
 use PostgresNode;
 use TestLib;
-use Test::More tests => 104;
+use Test::More tests => 105;
 
 program_help_ok('pg_basebackup');
 program_version_ok('pg_basebackup');
@@ -16,6 +16,9 @@ my $tempdir = TestLib::tempdir;
 
 my $node = get_new_node('main');
 
+# Set umask so test directories and files are created with default permissions
+umask(0077);
+
 # Initialize node without replication settings
 $node->init(extra => [ '--data-checksums' ]);
 $node->start;
@@ -94,6 +97,15 @@ $node->command_ok([ 'pg_basebackup', '-D', "$tempdir/backup", '-X', 'none' ],
        'pg_basebackup runs');
 ok(-f "$tempdir/backup/PG_VERSION", 'backup was created');
 
+# Permissions on backup should be default
+SKIP:
+{
+       skip "unix-style permissions not supported on Windows", 1 if ($windows_os);
+
+       ok(check_mode_recursive("$tempdir/backup", 0700, 0600),
+          "check backup dir permissions");
+}
+
 # Only archive_status directory should be copied in pg_wal/.
 is_deeply(
        [ sort(slurp_dir("$tempdir/backup/pg_wal/")) ],
index 64e3a35a87b8b1e0e0039a50140deaac34acd1c6..19c106d9f59d28e71a82b4ba6bd56687c7c1f291 100644 (file)
@@ -2,12 +2,15 @@ use strict;
 use warnings;
 use TestLib;
 use PostgresNode;
-use Test::More tests => 18;
+use Test::More tests => 19;
 
 program_help_ok('pg_receivewal');
 program_version_ok('pg_receivewal');
 program_options_handling_ok('pg_receivewal');
 
+# Set umask so test directories and files are created with default permissions
+umask(0077);
+
 my $primary = get_new_node('primary');
 $primary->init(allows_streaming => 1);
 $primary->start;
@@ -56,3 +59,12 @@ $primary->command_ok(
        [   'pg_receivewal', '-D',     $stream_dir,     '--verbose',
                '--endpos',      $nextlsn, '--synchronous', '--no-loop' ],
        'streaming some WAL with --synchronous');
+
+# Permissions on WAL files should be default
+SKIP:
+{
+       skip "unix-style permissions not supported on Windows", 1 if ($windows_os);
+
+       ok(check_mode_recursive($stream_dir, 0700, 0600),
+          "check stream dir permissions");
+}
index b4558a01847e5d04c1f398e5eab399f337de10b5..267a40debbfe5968c1941031d6f2cd2f43368e3e 100644 (file)
@@ -22,6 +22,7 @@
 #endif
 
 #include "pgtar.h"
+#include "common/file_perm.h"
 #include "common/file_utils.h"
 
 #include "receivelog.h"
@@ -89,7 +90,7 @@ dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
         * does not do any system calls to fsync() to make changes permanent on
         * disk.
         */
-       fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR);
+       fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, pg_file_create_mode);
        if (fd < 0)
                return NULL;
 
@@ -534,7 +535,8 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_
                 * We open the tar file only when we first try to write to it.
                 */
                tar_data->fd = open(tar_data->tarfilename,
-                                                       O_WRONLY | O_CREAT | PG_BINARY, S_IRUSR | S_IWUSR);
+                                                       O_WRONLY | O_CREAT | PG_BINARY,
+                                                       pg_file_create_mode);
                if (tar_data->fd < 0)
                        return NULL;
 
index 9bc830b08524e373692ffe71b9ef94733e6d0d26..5ede385e6ab73e1396783222db3936ca4204359b 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "catalog/pg_control.h"
 #include "common/controldata_utils.h"
+#include "common/file_perm.h"
 #include "getopt_long.h"
 #include "utils/pidfile.h"
 
@@ -2170,7 +2171,8 @@ main(int argc, char **argv)
         */
        argv0 = argv[0];
 
-       umask(S_IRWXG | S_IRWXO);
+       /* Set dir/file mode mask */
+       umask(PG_MODE_MASK_OWNER);
 
        /* support --help and --version even if invoked as root */
        if (argc > 1)
index 5da4746cb40dfede55bbd1cd93165125790a5167..067a084c87c3c442cfa0cc7a37c89d0af024e182 100644 (file)
@@ -4,7 +4,7 @@ use warnings;
 use Config;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 19;
+use Test::More tests => 21;
 
 my $tempdir       = TestLib::tempdir;
 my $tempdir_short = TestLib::tempdir_short;
@@ -57,9 +57,23 @@ command_ok([ 'pg_ctl', 'stop', '-D', "$tempdir/data" ], 'pg_ctl stop');
 command_fails([ 'pg_ctl', 'stop', '-D', "$tempdir/data" ],
        'second pg_ctl stop fails');
 
+# Log file for default permission test.  The permissions won't be checked on
+# Windows but we still want to do the restart test.
+my $logFileName = "$tempdir/data/perm-test-600.log";
+
 command_ok(
-       [ 'pg_ctl', 'restart', '-D', "$tempdir/data" ],
+       [ 'pg_ctl', 'restart', '-D', "$tempdir/data", '-l', $logFileName ],
        'pg_ctl restart with server not running');
+
+# Permissions on log file should be default
+SKIP:
+{
+       skip "unix-style permissions not supported on Windows", 2 if ($windows_os);
+
+       ok(-f $logFileName);
+       ok(check_mode_recursive("$tempdir/data", 0700, 0600));
+}
+
 command_ok([ 'pg_ctl', 'restart', '-D', "$tempdir/data" ],
        'pg_ctl restart with server running');
 
index eba7c5fdee0464827b9638fc059af569421d4a16..bdf71886ee2694dd0be49e9bc68cd6cacbc808fd 100644 (file)
@@ -52,6 +52,7 @@
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
 #include "common/fe_memutils.h"
+#include "common/file_perm.h"
 #include "common/restricted_token.h"
 #include "storage/large_object.h"
 #include "pg_getopt.h"
@@ -967,7 +968,7 @@ RewriteControlFile(void)
 
        fd = open(XLOG_CONTROL_FILE,
                          O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-                         S_IRUSR | S_IWUSR);
+                         pg_file_create_mode);
        if (fd < 0)
        {
                fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
@@ -1249,7 +1250,7 @@ WriteEmptyXLOG(void)
        unlink(path);
 
        fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-                         S_IRUSR | S_IWUSR);
+                         pg_file_create_mode);
        if (fd < 0)
        {
                fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
index 1b157cb55572bb1bfc60c3423c29595a486456fe..0d6ab20073a2c8bca76d917e17bd533472eec7f4 100644 (file)
@@ -3,7 +3,7 @@ use warnings;
 
 use PostgresNode;
 use TestLib;
-use Test::More tests => 11;
+use Test::More tests => 12;
 
 program_help_ok('pg_resetwal');
 program_version_ok('pg_resetwal');
@@ -15,3 +15,13 @@ $node->init;
 command_like([ 'pg_resetwal', '-n', $node->data_dir ],
                         qr/checkpoint/,
                         'pg_resetwal -n produces output');
+
+
+# Permissions on PGDATA should be default
+SKIP:
+{
+       skip "unix-style permissions not supported on Windows", 1 if ($windows_os);
+
+       ok(check_mode_recursive($node->data_dir, 0700, 0600),
+               'check PGDATA permissions');
+}
index 00b5b42dd796499667fe2942f9616cf62ce9c37c..7b632c7dcdb097e51a47abfd6fa1a7703f160c8e 100644 (file)
@@ -237,6 +237,10 @@ sub run_pg_rewind
                "$tmp_folder/master-postgresql.conf.tmp",
                "$master_pgdata/postgresql.conf");
 
+       chmod(0600, "$master_pgdata/postgresql.conf")
+               or BAIL_OUT(
+                       "unable to set permissions for $master_pgdata/postgresql.conf");
+
        # Plug-in rewound node to the now-promoted standby node
        my $port_standby = $node_standby->port;
        $node_master->append_conf(
index f491ed7f5cce7458c21c238091062076a537da0a..94bcc13ae866894af221be1bc35a2b7178d9da77 100644 (file)
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include "common/file_perm.h"
 #include "file_ops.h"
 #include "filemap.h"
 #include "logging.h"
@@ -57,7 +58,7 @@ open_target_file(const char *path, bool trunc)
        mode = O_WRONLY | O_CREAT | PG_BINARY;
        if (trunc)
                mode |= O_TRUNC;
-       dstfd = open(dstpath, mode, 0600);
+       dstfd = open(dstpath, mode, pg_file_create_mode);
        if (dstfd < 0)
                pg_fatal("could not open target file \"%s\": %s\n",
                                 dstpath, strerror(errno));
@@ -198,7 +199,7 @@ truncate_target_file(const char *path, off_t newsize)
 
        snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
 
-       fd = open(dstpath, O_WRONLY, 0);
+       fd = open(dstpath, O_WRONLY, pg_file_create_mode);
        if (fd < 0)
                pg_fatal("could not open file \"%s\" for truncation: %s\n",
                                 dstpath, strerror(errno));
@@ -219,7 +220,7 @@ create_target_dir(const char *path)
                return;
 
        snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
-       if (mkdir(dstpath, S_IRWXU) != 0)
+       if (mkdir(dstpath, pg_dir_create_mode) != 0)
                pg_fatal("could not create directory \"%s\": %s\n",
                                 dstpath, strerror(errno));
 }
index 736f34eae3f9fcb03a22dfb0b00982b63de49adb..1b0f823b0ccb89c2c98f3921b5d51fb21cefa9e6 100644 (file)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use TestLib;
-use Test::More tests => 8;
+use Test::More tests => 10;
 
 use RewindTest;
 
@@ -86,6 +86,15 @@ in master, before promotion
 ),
                'tail-copy');
 
+       # Permissions on PGDATA should be default
+       SKIP:
+       {
+               skip "unix-style permissions not supported on Windows", 1 if ($windows_os);
+
+               ok(check_mode_recursive($node_master->data_dir(), 0700, 0600),
+                       'check PGDATA permissions');
+       }
+
        RewindTest::clean_rewind_test();
 }
 
index f38bfacf02960e8ed8ebeb6f3dddbc1b71c574d0..f68211aa20ad876aa1c584e0990084db6e9c49ba 100644 (file)
@@ -10,6 +10,7 @@
 #include "postgres_fe.h"
 
 #include "access/visibilitymap.h"
+#include "common/file_perm.h"
 #include "pg_upgrade.h"
 #include "storage/bufpage.h"
 #include "storage/checksum.h"
@@ -44,7 +45,7 @@ copyFile(const char *src, const char *dst,
                                 schemaName, relName, src, strerror(errno));
 
        if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-                                               S_IRUSR | S_IWUSR)) < 0)
+                                               pg_file_create_mode)) < 0)
                pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s\n",
                                 schemaName, relName, dst, strerror(errno));
 
@@ -151,7 +152,7 @@ rewriteVisibilityMap(const char *fromfile, const char *tofile,
                                 schemaName, relName, fromfile, strerror(errno));
 
        if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-                                          S_IRUSR | S_IWUSR)) < 0)
+                                          pg_file_create_mode)) < 0)
                pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s\n",
                                 schemaName, relName, tofile, strerror(errno));
 
index d12412799fa19d40483f81584a31d51f7d165fe4..1d351881435b618a519aeec8259192f3b3164f14 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "pg_upgrade.h"
 #include "catalog/pg_class.h"
+#include "common/file_perm.h"
 #include "common/restricted_token.h"
 #include "fe_utils/string_utils.h"
 
@@ -79,7 +80,7 @@ main(int argc, char **argv)
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_upgrade"));
 
        /* Ensure that all files created by pg_upgrade are non-world-readable */
-       umask(S_IRWXG | S_IRWXO);
+       umask(PG_MODE_MASK_OWNER);
 
        parseCommandLine(argc, argv);
 
index 39983abea13618efb974f680e333d84e7e16cae0..574639d47e56f57ae69dac6fba8ba68185f990d2 100644 (file)
@@ -230,6 +230,17 @@ standard_initdb 'initdb'
 
 pg_upgrade $PG_UPGRADE_OPTS -d "${PGDATA}.old" -D "${PGDATA}" -b "$oldbindir" -B "$bindir" -p "$PGPORT" -P "$PGPORT"
 
+# make sure all directories and files have correct permissions
+if [ $(find ${PGDATA} -type f ! -perm 600 | wc -l) -ne 0 ]; then
+       echo "files in PGDATA with permission != 600";
+       exit 1;
+fi
+
+if [ $(find ${PGDATA} -type d ! -perm 700 | wc -l) -ne 0 ]; then
+       echo "directories in PGDATA with permission != 700";
+       exit 1;
+fi
+
 pg_ctl start -l "$logdir/postmaster2.log" -o "$POSTMASTER_OPTS" -w
 
 case $testhost in
index 873fbb64380d13ab8d4591a494835119cbc24642..e9e75867f3c3429daca70d83f0ca9a22e8cc14d1 100644 (file)
@@ -40,8 +40,8 @@ override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
 override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
 LIBS += $(PTHREAD_LIBS)
 
-OBJS_COMMON = base64.o config_info.o controldata_utils.o exec.o ip.o \
-       keywords.o md5.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
+OBJS_COMMON = base64.o config_info.o controldata_utils.o exec.o file_perm.o \
+       ip.o keywords.o md5.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
        rmtree.o saslprep.o scram-common.o string.o unicode_norm.o \
        username.o wait_error.o
 
diff --git a/src/common/file_perm.c b/src/common/file_perm.c
new file mode 100644 (file)
index 0000000..fdfbb9a
--- /dev/null
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * File and directory permission routines
+ *
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_perm.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <sys/stat.h>
+
+#include "common/file_perm.h"
+
+/* Modes for creating directories and files in the data directory */
+int pg_dir_create_mode = PG_DIR_MODE_OWNER;
+int pg_file_create_mode = PG_FILE_MODE_OWNER;
diff --git a/src/include/common/file_perm.h b/src/include/common/file_perm.h
new file mode 100644 (file)
index 0000000..37631a7
--- /dev/null
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * File and directory permission constants
+ *
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/file_perm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_PERM_H
+#define FILE_PERM_H
+
+/*
+ * Mode mask for data directory permissions that only allows the owner to
+ * read/write directories and files.
+ *
+ * This is the default.
+ */
+#define PG_MODE_MASK_OWNER                 (S_IRWXG | S_IRWXO)
+
+/* Default mode for creating directories */
+#define PG_DIR_MODE_OWNER                      S_IRWXU
+
+/* Default mode for creating files */
+#define PG_FILE_MODE_OWNER                 (S_IRUSR | S_IWUSR)
+
+/* Modes for creating directories and files in the data directory */
+extern int pg_dir_create_mode;
+extern int pg_file_create_mode;
+
+#endif                                                 /* FILE_PERM_H */
index e49b42ce867a0f8ab49644a7a29b257f6158b580..484339b7690f297bb7ea33947264df0ff7894666 100644 (file)
@@ -112,6 +112,9 @@ extern int  CloseTransientFile(int fd);
 extern int     BasicOpenFile(const char *fileName, int fileFlags);
 extern int     BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
 
+ /* Make a directory with default permissions */
+extern int     MakePGDirectory(const char *directoryName);
+
 /* Miscellaneous support routines */
 extern void InitFileAccess(void);
 extern void set_max_safe_fds(void);
index 80188315f15d265c872dd7a2dfb7c2c35ad0dabe..76e571b98c8cd5b7fab0db0ab40ee99bdffa9e0c 100644 (file)
@@ -484,6 +484,9 @@ sub append_conf
        my $conffile = $self->data_dir . '/' . $filename;
 
        TestLib::append_to_file($conffile, $str . "\n");
+
+    chmod(0600, $conffile)
+        or die("unable to set permissions for $conffile");
 }
 
 =pod
index b6862688d4fd44f19d82eb1e522cb826273271e9..93610e4bc400098599387f2edd20d7490839f808 100644 (file)
@@ -13,8 +13,11 @@ use warnings;
 use Config;
 use Cwd;
 use Exporter 'import';
+use Fcntl qw(:mode);
 use File::Basename;
+use File::Find;
 use File::Spec;
+use File::stat qw(stat);
 use File::Temp ();
 use IPC::Run;
 use SimpleTee;
@@ -27,6 +30,7 @@ our @EXPORT = qw(
   slurp_dir
   slurp_file
   append_to_file
+  check_mode_recursive
   check_pg_config
   system_or_bail
   system_log
@@ -240,6 +244,75 @@ sub append_to_file
        close $fh;
 }
 
+# Check that all file/dir modes in a directory match the expected values,
+# ignoring the mode of any specified files.
+sub check_mode_recursive
+{
+       my ($dir, $expected_dir_mode, $expected_file_mode, $ignore_list) = @_;
+
+       # Result defaults to true
+       my $result = 1;
+
+       find
+       (
+               {follow_fast => 1,
+               wanted =>
+                       sub
+                       {
+                               my $file_stat = stat($File::Find::name);
+
+                               # Is file in the ignore list?
+                               foreach my $ignore ($ignore_list ? @{$ignore_list} : [])
+                               {
+                                       if ("$dir/$ignore" eq $File::Find::name)
+                                       {
+                                               return;
+                                       }
+                               }
+
+                               defined($file_stat)
+                                       or die("unable to stat $File::Find::name");
+
+                               my $file_mode = S_IMODE($file_stat->mode);
+
+                               # Is this a file?
+                               if (S_ISREG($file_stat->mode))
+                               {
+                                       if ($file_mode != $expected_file_mode)
+                                       {
+                                               print(*STDERR,
+                                                       sprintf("$File::Find::name mode must be %04o\n",
+                                                       $expected_file_mode));
+
+                                               $result = 0;
+                                               return;
+                                       }
+                               }
+                               # Else a directory?
+                               elsif (S_ISDIR($file_stat->mode))
+                               {
+                                       if ($file_mode != $expected_dir_mode)
+                                       {
+                                               print(*STDERR,
+                                                       sprintf("$File::Find::name mode must be %04o\n",
+                                                       $expected_dir_mode));
+
+                                               $result = 0;
+                                               return;
+                                       }
+                               }
+                               # Else something we can't handle
+                               else
+                               {
+                                       die "unknown file type for $File::Find::name";
+                               }
+                       }},
+               $dir
+       );
+
+       return $result;
+}
+
 # Check presence of a given regexp within pg_config.h for the installation
 # where tests are running, returning a match status result depending on
 # that.
index 41d720880a8dec93b286bbaa6f7648d1cedf117f..1d3ed6b0b102f001cda1e7d2213611f06e2c9115 100644 (file)
@@ -111,8 +111,8 @@ sub mkvcbuild
        }
 
        our @pgcommonallfiles = qw(
-         base64.c config_info.c controldata_utils.c exec.c ip.c keywords.c
-         md5.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
+         base64.c config_info.c controldata_utils.c exec.c file_perm.c ip.c
+         keywords.c md5.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
          saslprep.c scram-common.c string.c unicode_norm.c username.c
          wait_error.c);