diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 62dec87..98f8170 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -1858,8 +1858,7 @@ qtext_store(const char *query, int query_len,
*query_offset = off;
/* Now write the data into the successfully-reserved part of the file */
- fd = OpenTransientFile(PGSS_TEXT_FILE, O_RDWR | O_CREAT | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(PGSS_TEXT_FILE, O_RDWR | O_CREAT | PG_BINARY);
if (fd < 0)
goto error;
@@ -1923,7 +1922,7 @@ qtext_load_file(Size *buffer_size)
int fd;
struct stat stat;
- fd = OpenTransientFile(PGSS_TEXT_FILE, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile(PGSS_TEXT_FILE, O_RDONLY | PG_BINARY);
if (fd < 0)
{
if (errno != ENOENT)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1b390a2..2371878 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -812,6 +812,38 @@ include_dir 'conf.d'
+
+ file_mode_mask (integer)
+
+ file_mode_mask> configuration parameter
+
+
+
+
+ Sets the file mode mask (umask) for the data directory. The parameter
+ value is expected to be a numeric mode specified in the format
+ accepted by the chmod and
+ umask system calls. (To use the customary octal
+ format the number must start with a 0 (zero).)
+
+
+
+ The default file_mode_mask is 0077,
+ meaning that the only the database owner can read and write files in
+ the data directory. For example, setting the
+ file_mode_mask to 0027 would allow
+ any user in the same group as the database owner to read all database
+ files, which would be useful for producing a backup using a relatively
+ unprivileged user.
+
+
+
+ This parameter can only be set at server start.
+
+
+
+
+
bonjour (boolean)
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index c7b283c..53a2acc 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -1010,8 +1010,7 @@ logical_rewrite_log_mapping(RewriteState state, TransactionId xid,
src->off = 0;
memcpy(src->path, path, sizeof(path));
src->vfd = PathNameOpenFile(path,
- O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
if (src->vfd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -1130,8 +1129,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
xlrec->mapped_xid, XLogRecGetXid(r));
fd = OpenTransientFile(path,
- O_CREAT | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_WRONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -1249,7 +1247,7 @@ CheckPointLogicalRewriteHeap(void)
}
else
{
- int fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ int fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
/*
* The file cannot vanish due to concurrency since this function
diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c
index a66ef5c..f385b79 100644
--- a/src/backend/access/transam/slru.c
+++ b/src/backend/access/transam/slru.c
@@ -594,7 +594,7 @@ SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
SlruFileName(ctl, path, segno);
- fd = OpenTransientFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
if (fd < 0)
{
/* expected: file doesn't exist */
@@ -649,7 +649,7 @@ SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno)
* SlruPhysicalWritePage). Hence, if we are InRecovery, allow the case
* where the file doesn't exist, and return zeroes instead.
*/
- fd = OpenTransientFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
if (fd < 0)
{
if (errno != ENOENT || !InRecovery)
@@ -796,8 +796,7 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata)
* don't use O_EXCL or O_TRUNC or anything like that.
*/
SlruFileName(ctl, path, segno);
- fd = OpenTransientFile(path, O_RDWR | O_CREAT | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(path, O_RDWR | O_CREAT | PG_BINARY);
if (fd < 0)
{
slru_errcause = SLRU_OPEN_FAILED;
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index 1fdc591..baa766a 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -306,8 +306,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
unlink(tmppath);
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
- fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -324,7 +323,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
else
TLHistoryFilePath(path, parentTLI);
- srcfd = OpenTransientFile(path, O_RDONLY, 0);
+ srcfd = OpenTransientFile(path, O_RDONLY);
if (srcfd < 0)
{
if (errno != ENOENT)
@@ -452,8 +451,7 @@ writeTimeLineHistoryFile(TimeLineID tli, char *content, int size)
unlink(tmppath);
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
- fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 0a8edb9..1f02dd1 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1151,7 +1151,7 @@ ReadTwoPhaseFile(TransactionId xid, bool give_warnings)
TwoPhaseFilePath(path, xid);
- fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (fd < 0)
{
if (give_warnings)
@@ -1533,8 +1533,7 @@ RecreateTwoPhaseFile(TransactionId xid, void *content, int len)
TwoPhaseFilePath(path, xid);
fd = OpenTransientFile(path,
- O_CREAT | O_TRUNC | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_TRUNC | O_WRONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 8973583..eed7dda 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -3156,8 +3156,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
*/
if (*use_existent)
{
- fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method),
- S_IRUSR | S_IWUSR);
+ fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
if (fd < 0)
{
if (errno != ENOENT)
@@ -3182,8 +3181,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
unlink(tmppath);
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
- fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = BasicOpenFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -3275,8 +3273,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
*use_existent = false;
/* Now open original target segment (might not be file I just made) */
- fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method),
- S_IRUSR | S_IWUSR);
+ fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -3317,7 +3314,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
* Open the source file
*/
XLogFilePath(path, srcTLI, srcsegno);
- srcfd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ srcfd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (srcfd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -3331,8 +3328,7 @@ XLogFileCopy(XLogSegNo destsegno, TimeLineID srcTLI, XLogSegNo srcsegno,
unlink(tmppath);
/* do not use get_sync_bit() here --- want to fsync only at end of fill */
- fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(tmppath, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -3504,8 +3500,7 @@ XLogFileOpen(XLogSegNo segno)
XLogFilePath(path, ThisTimeLineID, segno);
- fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method),
- S_IRUSR | S_IWUSR);
+ fd = BasicOpenFile(path, O_RDWR | PG_BINARY | get_sync_bit(sync_method));
if (fd < 0)
ereport(PANIC,
(errcode_for_file_access(),
@@ -3571,7 +3566,7 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlogfname);
}
- fd = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
+ fd = BasicOpenFile(path, O_RDONLY | PG_BINARY);
if (fd >= 0)
{
/* Success! */
@@ -4065,7 +4060,7 @@ ValidateXLOGDirectoryStructure(void)
{
ereport(LOG,
(errmsg("creating missing WAL directory \"%s\"", path)));
- if (mkdir(path, S_IRWXU) < 0)
+ if (mkdir(path, PG_DEFAULT_DIR_MODE) < 0)
ereport(FATAL,
(errmsg("could not create missing directory \"%s\": %m",
path)));
@@ -4404,8 +4399,7 @@ WriteControlFile(void)
memcpy(buffer, ControlFile, sizeof(ControlFileData));
fd = BasicOpenFile(XLOG_CONTROL_FILE,
- O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (fd < 0)
ereport(PANIC,
(errcode_for_file_access(),
@@ -4444,8 +4438,7 @@ ReadControlFile(void)
* Read data...
*/
fd = BasicOpenFile(XLOG_CONTROL_FILE,
- O_RDWR | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_RDWR | PG_BINARY);
if (fd < 0)
ereport(PANIC,
(errcode_for_file_access(),
@@ -4624,8 +4617,7 @@ UpdateControlFile(void)
FIN_CRC32C(ControlFile->crc);
fd = BasicOpenFile(XLOG_CONTROL_FILE,
- O_RDWR | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_RDWR | PG_BINARY);
if (fd < 0)
ereport(PANIC,
(errcode_for_file_access(),
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 8b99b78..96ac73f 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -687,7 +687,7 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
XLogFilePath(path, tli, sendSegNo);
- sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
+ sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY);
if (sendFile < 0)
{
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 11ee536..578b46b 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -428,7 +428,7 @@ GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
/* Check for existing file of same name */
rpath = relpath(rnode, MAIN_FORKNUM);
- fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);
+ fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY);
if (fd >= 0)
{
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index f9c2620..312ac07 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -151,7 +151,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
else
{
/* Directory creation failed? */
- if (mkdir(dir, S_IRWXU) < 0)
+ if (mkdir(dir, PG_DEFAULT_DIR_MODE) < 0)
{
char *parentdir;
@@ -173,7 +173,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 (mkdir(parentdir, PG_DEFAULT_DIR_MODE) < 0 && errno != EEXIST)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
@@ -184,7 +184,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 (mkdir(parentdir, PG_DEFAULT_DIR_MODE) < 0 && errno != EEXIST)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
@@ -192,7 +192,7 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
pfree(parentdir);
/* Create database directory */
- if (mkdir(dir, S_IRWXU) < 0)
+ if (mkdir(dir, PG_DEFAULT_DIR_MODE) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
@@ -610,7 +610,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 (mkdir(location_with_version_dir, PG_DEFAULT_DIR_MODE) < 0)
{
if (errno == EEXIST)
ereport(ERROR,
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index f537aff..c0c8d94 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -462,7 +462,7 @@ lo_import_internal(text *filename, Oid lobjOid)
* open the file to be read in
*/
text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf));
- fd = OpenTransientFile(fnamebuf, O_RDONLY | PG_BINARY, S_IRWXU);
+ fd = OpenTransientFile(fnamebuf, O_RDONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -538,8 +538,8 @@ be_lo_export(PG_FUNCTION_ARGS)
*/
text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf));
oumask = umask(S_IWGRP | S_IWOTH);
- fd = OpenTransientFile(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ fd = OpenTransientFilePerm(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
umask(oumask);
if (fd < 0)
ereport(ERROR,
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 271c492..bfb6c7d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -579,9 +579,10 @@ PostmasterMain(int argc, char *argv[])
IsPostmasterEnvironment = true;
/*
- * for security, no dir or file created can be group or other accessible
+ * Initially set most restrictive umask in case any files are
+ * accidentally created before file_mode_mask is loaded from GUC.
*/
- umask(S_IRWXG | S_IRWXO);
+ umask(file_mode_mask);
/*
* Initialize random(3) so we don't get the same values in every run.
@@ -854,6 +855,9 @@ PostmasterMain(int argc, char *argv[])
ExitPostmaster(0);
}
+ /* Reset the file mode creation mask now that GUC has been loaded. */
+ umask(file_mode_mask);
+
/* Verify that DataDir looks reasonable */
checkDataDir();
@@ -1489,25 +1493,20 @@ checkDataDir(void)
#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.
+ * Check if the directory has the correct permissions. If not, then reject.
*
* 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))
+ if (stat_buf.st_mode & file_mode_mask)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("data directory \"%s\" has group or world access",
+ errmsg("data directory \"%s\" has incorrect permissions",
DataDir),
- errdetail("Permissions should be u=rwx (0700).")));
+ errdetail("Permissions should be (%04o).",
+ (PG_DEFAULT_DIR_MODE & ~file_mode_mask))));
#endif
/* Look for PG_VERSION before looking for pg_control */
@@ -4393,7 +4392,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
* As in OpenTemporaryFileInTablespace, try to make the temp-file
* directory
*/
- mkdir(PG_TEMP_FILES_DIR, S_IRWXU);
+ mkdir(PG_TEMP_FILES_DIR, PG_DEFAULT_DIR_MODE);
fp = AllocateFile(tmpfilename, PG_BINARY_W);
if (!fp)
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index 13a0301..684944d 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -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"
@@ -320,7 +321,7 @@ SysLoggerMain(int argc, char *argv[])
/*
* Also, create new directory if not present; ignore errors
*/
- mkdir(Log_directory, S_IRWXU);
+ mkdir(Log_directory, PG_DEFAULT_DIR_MODE);
}
if (strcmp(Log_filename, currentLogFilename) != 0)
{
@@ -555,7 +556,7 @@ SysLogger_Start(void)
/*
* Create log directory if not present; ignore errors
*/
- mkdir(Log_directory, S_IRWXU);
+ mkdir(Log_directory, PG_DEFAULT_DIR_MODE);
/*
* The initial logfile is created right in the postmaster, to verify that
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index bf84c68..51d54ab 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -527,8 +527,7 @@ CheckPointReplicationOrigin(void)
* CheckpointLock.
*/
tmpfd = OpenTransientFile((char *) tmppath,
- O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
if (tmpfd < 0)
ereport(PANIC,
(errcode_for_file_access(),
@@ -637,7 +636,7 @@ StartupReplicationOrigin(void)
elog(DEBUG2, "starting up replication origin progress state");
- fd = OpenTransientFile((char *) path, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile((char *) path, O_RDONLY | PG_BINARY);
/*
* might have had max_replication_slots == 0 last run, or we just brought
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 8aac670..af7edea 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -2103,8 +2103,7 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
/* open segment, create it if necessary */
fd = OpenTransientFile(path,
- O_CREAT | O_WRONLY | O_APPEND | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_WRONLY | O_APPEND | PG_BINARY);
if (fd < 0)
ereport(ERROR,
@@ -2345,7 +2344,7 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
NameStr(MyReplicationSlot->data.name), txn->xid,
(uint32) (recptr >> 32), (uint32) recptr);
- *fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ *fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (*fd < 0 && errno == ENOENT)
{
*fd = -1;
@@ -3030,7 +3029,7 @@ ApplyLogicalMappingFile(HTAB *tuplecid_data, Oid relid, const char *fname)
LogicalRewriteMappingData map;
sprintf(path, "pg_logical/mappings/%s", fname);
- fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index 6f19cdc..961b0f9 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -1574,8 +1574,7 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
/* we have valid data now, open tempfile and write it there */
fd = OpenTransientFile(tmppath,
- O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errmsg("could not open file \"%s\": %m", path)));
@@ -1655,7 +1654,7 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
sprintf(path, "pg_logical/snapshots/%X-%X.snap",
(uint32) (lsn >> 32), (uint32) lsn);
- fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (fd < 0 && errno == ENOENT)
return false;
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index 10d69d0..7e8b50e 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1011,7 +1011,7 @@ CreateSlotOnDisk(ReplicationSlot *slot)
rmtree(tmppath, true);
/* Create and fsync the temporary slot directory. */
- if (mkdir(tmppath, S_IRWXU) < 0)
+ if (mkdir(tmppath, PG_DEFAULT_DIR_MODE) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
@@ -1072,9 +1072,7 @@ SaveSlotToPath(ReplicationSlot *slot, const char *dir, int elevel)
sprintf(tmppath, "%s/state.tmp", dir);
sprintf(path, "%s/state", dir);
- fd = OpenTransientFile(tmppath,
- O_CREAT | O_EXCL | O_WRONLY | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(tmppath, O_CREAT | O_EXCL | O_WRONLY | PG_BINARY);
if (fd < 0)
{
ereport(elevel,
@@ -1187,7 +1185,7 @@ RestoreSlotFromDisk(const char *name)
elog(DEBUG1, "restoring replication slot from \"%s\"", path);
- fd = OpenTransientFile(path, O_RDWR | PG_BINARY, 0);
+ fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
/*
* We do not need to handle this as we are rename()ing the directory into
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 9cf9eb0..e1af7a3 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -437,7 +437,7 @@ SendTimeLineHistory(TimeLineHistoryCmd *cmd)
pq_sendint(&buf, len, 4); /* col1 len */
pq_sendbytes(&buf, histfname, len);
- fd = OpenTransientFile(path, O_RDONLY | PG_BINARY, 0666);
+ fd = OpenTransientFile(path, O_RDONLY | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -2031,7 +2031,7 @@ retry:
XLogFilePath(path, curFileTimeLine, sendSegNo);
- sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
+ sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY);
if (sendFile < 0)
{
/*
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index 101da47..0e078f5 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -41,7 +41,7 @@ copydir(char *fromdir, char *todir, bool recurse)
char fromfile[MAXPGPATH];
char tofile[MAXPGPATH];
- if (mkdir(todir, S_IRWXU) != 0)
+ if (mkdir(todir, PG_DEFAULT_DIR_MODE) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m", todir)));
@@ -148,14 +148,13 @@ copy_file(char *fromfile, char *tofile)
/*
* Open the files
*/
- srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY, 0);
+ srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY);
if (srcfd < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open file \"%s\": %m", fromfile)));
- dstfd = OpenTransientFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ dstfd = OpenTransientFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (dstfd < 0)
ereport(ERROR,
(errcode_for_file_access(),
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index fd02fc0..46caf90 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -138,6 +138,8 @@ int max_files_per_process = 1000;
*/
int max_safe_fds = 32; /* default if not changed */
+/* The file mode creation mask for creating new files and directories. */
+int file_mode_mask = PG_DEFAULT_MODE_MASK;
/* Debugging.... */
@@ -604,7 +606,7 @@ durable_rename(const char *oldfile, const char *newfile, int elevel)
if (fsync_fname_ext(oldfile, false, false, elevel) != 0)
return -1;
- fd = OpenTransientFile((char *) newfile, PG_BINARY | O_RDWR, 0);
+ fd = OpenTransientFile((char *) newfile, PG_BINARY | O_RDWR);
if (fd < 0)
{
if (errno != ENOENT)
@@ -896,7 +898,7 @@ set_max_safe_fds(void)
* this module wouldn't have any open files to close at that point anyway.
*/
int
-BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
+BasicOpenFilePerm(FileName fileName, int fileFlags, int fileMode)
{
int fd;
@@ -922,6 +924,12 @@ tryAgain:
return -1; /* failure */
}
+int
+BasicOpenFile(FileName fileName, int fileFlags)
+{
+ return BasicOpenFilePerm(fileName, fileFlags, PG_DEFAULT_FILE_MODE);
+}
+
#if defined(FDDEBUG)
static void
@@ -1047,8 +1055,8 @@ LruInsert(File file)
* overall system file table being full. So, be prepared to release
* another FD if necessary...
*/
- vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
- vfdP->fileMode);
+ vfdP->fd = BasicOpenFilePerm(vfdP->fileName, vfdP->fileFlags,
+ vfdP->fileMode);
if (vfdP->fd < 0)
{
DO_DB(elog(LOG, "re-open failed: %m"));
@@ -1263,13 +1271,19 @@ FileInvalidate(File file)
* (which should always be $PGDATA when this code is running).
*/
File
-PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
+PathNameOpenFile(FileName fileName, int fileFlags)
+{
+ return PathNameOpenFilePerm(fileName, fileFlags, PG_DEFAULT_FILE_MODE);
+}
+
+File
+PathNameOpenFilePerm(FileName fileName, int fileFlags, int fileMode)
{
char *fnamecopy;
File file;
Vfd *vfdP;
- DO_DB(elog(LOG, "PathNameOpenFile: %s %x %o",
+ DO_DB(elog(LOG, "PathNameOpenFilePerm: %s %x %o",
fileName, fileFlags, fileMode));
/*
@@ -1287,7 +1301,7 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
/* Close excess kernel FDs. */
ReleaseLruFiles();
- vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
+ vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
if (vfdP->fd < 0)
{
@@ -1424,8 +1438,7 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
* temp file that can be reused.
*/
file = PathNameOpenFile(tempfilepath,
- O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
- 0600);
+ O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
if (file <= 0)
{
/*
@@ -1436,11 +1449,10 @@ OpenTemporaryFileInTablespace(Oid tblspcOid, bool rejectError)
* 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);
+ mkdir(tempdirpath, PG_DEFAULT_DIR_MODE);
file = PathNameOpenFile(tempfilepath,
- O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
- 0600);
+ O_RDWR | O_CREAT | O_TRUNC | PG_BINARY);
if (file <= 0 && rejectError)
elog(ERROR, "could not create temporary file \"%s\": %m",
tempfilepath);
@@ -2090,7 +2102,7 @@ TryAgain:
* Like AllocateFile, but returns an unbuffered fd like open(2)
*/
int
-OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
+OpenTransientFilePerm(FileName fileName, int fileFlags, int fileMode)
{
int fd;
@@ -2107,7 +2119,7 @@ OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
/* Close excess kernel FDs. */
ReleaseLruFiles();
- fd = BasicOpenFile(fileName, fileFlags, fileMode);
+ fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);
if (fd >= 0)
{
@@ -2124,6 +2136,12 @@ OpenTransientFile(FileName fileName, int fileFlags, int fileMode)
return -1; /* failure */
}
+int
+OpenTransientFile(FileName fileName, int fileFlags)
+{
+ return OpenTransientFilePerm(fileName, fileFlags, PG_DEFAULT_FILE_MODE);
+}
+
/*
* Routines that want to initiate a pipe stream should use OpenPipeStream
* rather than plain popen(). This lets fd.c deal with freeing FDs if
@@ -3030,7 +3048,7 @@ pre_sync_fname(const char *fname, bool isdir, int elevel)
if (isdir)
return;
- fd = OpenTransientFile((char *) fname, O_RDONLY | PG_BINARY, 0);
+ fd = OpenTransientFile((char *) fname, O_RDONLY | PG_BINARY);
if (fd < 0)
{
@@ -3090,7 +3108,7 @@ fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel)
else
flags |= O_RDONLY;
- fd = OpenTransientFile((char *) fname, flags, 0);
+ fd = OpenTransientFile((char *) fname, flags);
/*
* Some OSs don't allow us to open directories at all (Windows returns
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index b2c9cdc..80ee4fa 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -283,7 +283,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_DEFAULT_FILE_MODE)) == -1)
{
if (errno != EEXIST)
ereport(elevel,
@@ -834,7 +834,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size,
/* Create new segment or open an existing one for attach or resize. */
flags = O_RDWR | (op == DSM_OP_CREATE ? O_CREAT | O_EXCL : 0);
- if ((fd = OpenTransientFile(name, flags, 0600)) == -1)
+ if ((fd = OpenTransientFile(name, flags)) == -1)
{
if (errno != EEXIST)
ereport(elevel,
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index ffd91f5..dfc5b75 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -28,6 +28,7 @@
#include "postmaster/autovacuum.h"
#endif
#include "storage/dsm.h"
+#include "storage/fd.h"
#include "storage/ipc.h"
#include "tcop/tcopprot.h"
@@ -132,8 +133,8 @@ proc_exit(int code)
else
snprintf(gprofDirName, 32, "gprof/%d", (int) getpid());
- mkdir("gprof", S_IRWXU | S_IRWXG | S_IRWXO);
- mkdir(gprofDirName, S_IRWXU | S_IRWXG | S_IRWXO);
+ mkdir("gprof", PG_DEFAULT_DIR_MODE);
+ mkdir(gprofDirName, PG_DEFAULT_DIR_MODE);
chdir(gprofDirName);
}
#endif
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 6c17b54..cf951a2 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -303,7 +303,7 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
path = relpath(reln->smgr_rnode, forkNum);
- fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600);
+ fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (fd < 0)
{
@@ -316,7 +316,7 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
* already, even if isRedo is not set. (See also mdopen)
*/
if (isRedo || IsBootstrapProcessingMode())
- fd = PathNameOpenFile(path, O_RDWR | PG_BINARY, 0600);
+ fd = PathNameOpenFile(path, O_RDWR | PG_BINARY);
if (fd < 0)
{
/* be sure to report the error reported by create, not open */
@@ -429,7 +429,7 @@ mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, bool isRedo)
/* truncate(2) would be easier here, but Windows hasn't got it */
int fd;
- fd = OpenTransientFile(path, O_RDWR | PG_BINARY, 0);
+ fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
if (fd >= 0)
{
int save_errno;
@@ -582,7 +582,7 @@ mdopen(SMgrRelation reln, ForkNumber forknum, int behavior)
path = relpath(reln->smgr_rnode, forknum);
- fd = PathNameOpenFile(path, O_RDWR | PG_BINARY, 0600);
+ fd = PathNameOpenFile(path, O_RDWR | PG_BINARY);
if (fd < 0)
{
@@ -593,7 +593,7 @@ mdopen(SMgrRelation reln, ForkNumber forknum, int behavior)
* substitute for mdcreate() in bootstrap mode only. (See mdcreate)
*/
if (IsBootstrapProcessingMode())
- fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600);
+ fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
if (fd < 0)
{
if ((behavior & EXTENSION_RETURN_NULL) &&
@@ -1779,7 +1779,7 @@ _mdfd_openseg(SMgrRelation reln, ForkNumber forknum, BlockNumber segno,
fullpath = _mdfd_segpath(reln, forknum, segno);
/* open the file */
- fd = PathNameOpenFile(fullpath, O_RDWR | PG_BINARY | oflags, 0600);
+ fd = PathNameOpenFile(fullpath, O_RDWR | PG_BINARY | oflags);
pfree(fullpath);
diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c
index c9d6e44..fe68b5b 100644
--- a/src/backend/utils/cache/relmapper.c
+++ b/src/backend/utils/cache/relmapper.c
@@ -643,8 +643,7 @@ load_relmap_file(bool shared)
}
/* Read data ... */
- fd = OpenTransientFile(mapfilename,
- O_RDONLY | PG_BINARY, S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(mapfilename, O_RDONLY | PG_BINARY);
if (fd < 0)
ereport(FATAL,
(errcode_for_file_access(),
@@ -742,9 +741,7 @@ write_relmap_file(bool shared, RelMapFile *newmap,
realmap = &local_map;
}
- fd = OpenTransientFile(mapfilename,
- O_WRONLY | O_CREAT | PG_BINARY,
- S_IRUSR | S_IWUSR);
+ fd = OpenTransientFile(mapfilename, O_WRONLY | O_CREAT | PG_BINARY);
if (fd < 0)
ereport(ERROR,
(errcode_for_file_access(),
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0707f66..bb3e471 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -190,6 +190,7 @@ static void assign_application_name(const char *newval, void *extra);
static bool check_cluster_name(char **newval, void **extra, GucSource source);
static const char *show_unix_socket_permissions(void);
static const char *show_log_file_mode(void);
+static const char *show_file_mode_mask(void);
/* Private functions in guc-file.l that need to be called from guc.c */
static ConfigVariable *ProcessConfigFileInternal(GucContext context,
@@ -2841,6 +2842,18 @@ static struct config_int ConfigureNamesInt[] =
4096, 64, MAX_KILOBYTES,
NULL, NULL, NULL
},
+ {
+ {"file_mode_mask", PGC_POSTMASTER, UNGROUPED,
+ gettext_noop("Sets the file mode creation mask for the backend process."),
+ gettext_noop("The parameter value is expected to be a numeric mode"
+ "specification in the form accepted by the chmod and "
+ "umask system calls. (To use the customary octal "
+ "format the number must start with a 0 (zero).)")
+ },
+ &file_mode_mask,
+ PG_DEFAULT_MODE_MASK, 0000, 0777,
+ NULL, NULL, show_file_mode_mask
+ },
/* End-of-list marker */
{
@@ -7186,8 +7199,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
* truncate and reuse it.
*/
Tmpfd = BasicOpenFile(AutoConfTmpFileName,
- O_CREAT | O_RDWR | O_TRUNC,
- S_IRUSR | S_IWUSR);
+ O_CREAT | O_RDWR | O_TRUNC);
if (Tmpfd < 0)
ereport(ERROR,
(errcode_for_file_access(),
@@ -10444,6 +10456,15 @@ show_unix_socket_permissions(void)
}
static const char *
+show_file_mode_mask(void)
+{
+ static char buf[8];
+
+ snprintf(buf, sizeof(buf), "%04o", file_mode_mask);
+ return buf;
+}
+
+static const char *
show_log_file_mode(void)
{
static char buf[8];
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 157d775..81fd9da 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -49,6 +49,7 @@
#external_pid_file = '' # write an extra PID file
# (change requires restart)
+#file_mode_mask = 0077
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 1ed0d20..283ec09 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -110,6 +110,15 @@ static const char *const auth_methods_local[] = {
NULL
};
+/* File mode to use with chmod on files. */
+#define PG_DEFAULT_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+
+/* File mode to use with chmod on directories. */
+#define PG_DEFAULT_DIR_MODE (S_IRWXU | S_IRWXG | S_IRWXO)
+
+/* Default file mode creation mask. */
+#define PG_DEFAULT_MODE_MASK (S_IRWXG | S_IRWXO)
+
/*
* these values are passed in by makefile defines
*/
@@ -139,6 +148,7 @@ static bool sync_only = false;
static bool show_setting = false;
static bool data_checksums = false;
static char *xlog_dir = "";
+static mode_t file_mode_mask = PG_DEFAULT_MODE_MASK;
/* internal vars */
@@ -1095,6 +1105,11 @@ setup_config(void)
conflines = replace_token(conflines, "#dynamic_shared_memory_type = posix",
repltok);
+ snprintf(repltok, sizeof(repltok), "file_mode_mask = %04o",
+ file_mode_mask);
+ conflines = replace_token(conflines, "#file_mode_mask = 0077",
+ repltok);
+
#if DEFAULT_BACKEND_FLUSH_AFTER > 0
snprintf(repltok, sizeof(repltok), "#backend_flush_after = %dkB",
DEFAULT_BACKEND_FLUSH_AFTER * (BLCKSZ / 1024));
@@ -1131,7 +1146,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_DEFAULT_FILE_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
progname, path, strerror(errno));
@@ -1151,7 +1166,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_DEFAULT_FILE_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
progname, path, strerror(errno));
@@ -1235,7 +1250,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_DEFAULT_FILE_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
progname, path, strerror(errno));
@@ -1251,7 +1266,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_DEFAULT_FILE_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
progname, path, strerror(errno));
@@ -2243,6 +2258,7 @@ usage(const char *progname)
printf(_(" --auth-local=METHOD default authentication method for local-socket connections\n"));
printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
+ printf(_(" -u, --file-mode-mask=MASK set default file mode creation mask (umask)\n"));
printf(_(" --locale=LOCALE set default locale for new databases\n"));
printf(_(" --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n"
" --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n"
@@ -2624,7 +2640,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_DEFAULT_DIR_MODE) != 0)
{
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
progname, pg_data, strerror(errno));
@@ -2642,7 +2658,7 @@ create_data_directory(void)
pg_data);
fflush(stdout);
- if (chmod(pg_data, S_IRWXU) != 0)
+ if (chmod(pg_data, (PG_DEFAULT_DIR_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
progname, pg_data, strerror(errno));
@@ -2710,7 +2726,8 @@ create_xlog_or_symlink(void)
xlog_dir);
fflush(stdout);
- if (pg_mkdir_p(xlog_dir, S_IRWXU) != 0)
+ printf("MASK: %04o\n", file_mode_mask);
+ if (pg_mkdir_p(xlog_dir, PG_DEFAULT_DIR_MODE) != 0)
{
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
progname, xlog_dir, strerror(errno));
@@ -2728,7 +2745,8 @@ create_xlog_or_symlink(void)
xlog_dir);
fflush(stdout);
- if (chmod(xlog_dir, S_IRWXU) != 0)
+ printf("MASK: %04o\n", file_mode_mask);
+ if (chmod(xlog_dir, (PG_DEFAULT_DIR_MODE & ~file_mode_mask)) != 0)
{
fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
progname, xlog_dir, strerror(errno));
@@ -2778,7 +2796,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_DEFAULT_DIR_MODE) < 0)
{
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
progname, subdirloc, strerror(errno));
@@ -2814,7 +2832,9 @@ initialize_data_directory(void)
setup_signals();
- umask(S_IRWXG | S_IRWXO);
+ /* Set the file mode creation mask. */
+ umask(file_mode_mask);
+ printf(_("Initializing with file mode creation mask: %04o\n"), file_mode_mask);
create_data_directory();
@@ -2834,7 +2854,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_DEFAULT_DIR_MODE) < 0)
{
fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
progname, path, strerror(errno));
@@ -2942,6 +2962,7 @@ main(int argc, char *argv[])
{"sync-only", no_argument, NULL, 'S'},
{"waldir", required_argument, NULL, 'X'},
{"data-checksums", no_argument, NULL, 'k'},
+ {"file-mode-mask", required_argument, NULL, 'u'},
{NULL, 0, NULL, 0}
};
@@ -2983,7 +3004,7 @@ main(int argc, char *argv[])
/* process command-line options */
- while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
+ while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:u:", long_options, &option_index)) != -1)
{
switch (c)
{
@@ -3074,6 +3095,9 @@ main(int argc, char *argv[])
case 'X':
xlog_dir = pg_strdup(optarg);
break;
+ case 'u':
+ file_mode_mask = strtoul(optarg, NULL, 8);
+ break;
default:
/* getopt_long already emitted a complaint */
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 1a43a2c..6660b7b 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -22,7 +22,7 @@
* Use them for all file activity...
*
* File fd;
- * fd = PathNameOpenFile("foo", O_RDONLY, 0600);
+ * fd = PathNameOpenFile("foo", O_RDONLY);
*
* AllocateFile();
* FreeFile();
@@ -59,13 +59,21 @@ extern int max_files_per_process;
*/
extern int max_safe_fds;
+/* The file mode creation mask for creating new files and directories. */
+extern int file_mode_mask;
+
+/* Define default modes and masks. */
+#define PG_DEFAULT_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
+#define PG_DEFAULT_DIR_MODE (S_IRWXU | S_IRWXG | S_IRWXO)
+#define PG_DEFAULT_MODE_MASK (S_IRWXG | S_IRWXO)
/*
* prototypes for functions in fd.c
*/
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
-extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
+extern File PathNameOpenFilePerm(FileName fileName, int fileFlags, int fileMode);
+extern File PathNameOpenFile(FileName fileName, int fileFlags);
extern File OpenTemporaryFile(bool interXact);
extern void FileClose(File file);
extern int FilePrefetch(File file, off_t offset, int amount);
@@ -94,11 +102,13 @@ extern struct dirent *ReadDir(DIR *dir, const char *dirname);
extern int FreeDir(DIR *dir);
/* Operations to allow use of a plain kernel FD, with automatic cleanup */
-extern int OpenTransientFile(FileName fileName, int fileFlags, int fileMode);
+extern int OpenTransientFilePerm(FileName fileName, int fileFlags, int fileMode);
+extern int OpenTransientFile(FileName fileName, int fileFlags);
extern int CloseTransientFile(int fd);
/* If you've really really gotta have a plain kernel FD, use this */
-extern int BasicOpenFile(FileName fileName, int fileFlags, int fileMode);
+extern int BasicOpenFilePerm(FileName fileName, int fileFlags, int fileMode);
+extern int BasicOpenFile(FileName fileName, int fileFlags);
/* Miscellaneous support routines */
extern void InitFileAccess(void);