On 07/02/2012 09:45 PM, Tom Lane wrote:
Honza Horak <hho...@redhat.com> writes:
On 06/15/2012 05:40 PM, Honza Horak wrote:
I realized the patch has some difficulties -- namely the socket path in the
data dir lock file, which currently uses one port for socket and the same for
interface. So to allow users to use arbitrary port for all unix sockets, we'd
need to add another line only for unix socket, which doesn't apply for other
platforms. Or we could just say that the first socket will allways use the
default port (PostPortNumber), which is a solution I prefer currently, but will
be glad for any other opinion. This is also why there is still un-necesary
string splitting in pg_ctl.c, which will be removed after the issue above is
solved.
I did a review pass over this patch.
I have finally an enhanced patch, see the attachment and feel free to
comment.
Well, not so much "forbids" as "silently ignores", which doesn't seem like
great user-interface design to me. If we're going to adopt this solution
I think we need it to throw an error instead of just ignoring the port
specification.
Alternate-port-number support has been removed from the patch, as per
Tom's e-mail from 07/03/12. It can be add in the future, if we really
need it.
* I'm not especially thrilled with propagating SplitUnixDirectories calls
into those two places anyway, nor with the weird decision for
SplitUnixDirectories to return a separate "mainSocket" value. Perhaps
what would be most sensible is to attach an assign hook to the
unix_socket_directories GUC parameter that would automatically split the
string and store the components into a globally-visible List variable
(which could replace the globally-visible string value we have now).
Replacing the old global string value would probably need a new
configuration type "List" to be added, since otherwise guc works with it
as with a string. Adding that seems like too big overhead to me and thus
it seems better to add a new global (List *) variable and let the
original value of type (char *) to store non-parsed value.
Except that I believe all other Tom's comments have been involved.
Regards,
Honza
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index cfdb33a..679c40a 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -838,7 +838,7 @@ omicron bryanh guest1
<varname>unix_socket_permissions</varname> (and possibly
<varname>unix_socket_group</varname>) configuration parameters as
described in <xref linkend="runtime-config-connection">. Or you
- could set the <varname>unix_socket_directory</varname>
+ could set the <varname>unix_socket_directories</varname>
configuration parameter to place the socket file in a suitably
restricted directory.
</para>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 3a0b16d..67997d6 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -445,17 +445,18 @@ SET ENABLE_SEQSCAN TO OFF;
</listitem>
</varlistentry>
- <varlistentry id="guc-unix-socket-directory" xreflabel="unix_socket_directory">
- <term><varname>unix_socket_directory</varname> (<type>string</type>)</term>
+ <varlistentry id="guc-unix-socket-directories" xreflabel="unix_socket_directories">
+ <term><varname>unix_socket_directories</varname> (<type>string</type>)</term>
<indexterm>
- <primary><varname>unix_socket_directory</> configuration parameter</primary>
+ <primary><varname>unix_socket_directories</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
- Specifies the directory of the Unix-domain socket on which the
+ Specifies the directories of the Unix-domain sockets on which the
server is to listen for
connections from client applications. The default is normally
<filename>/tmp</filename>, but can be changed at build time.
+ Directories are separated by ','.
This parameter can only be set at server start.
</para>
@@ -464,7 +465,7 @@ SET ENABLE_SEQSCAN TO OFF;
<literal>.s.PGSQL.<replaceable>nnnn</></literal> where
<replaceable>nnnn</> is the server's port number, an ordinary file
named <literal>.s.PGSQL.<replaceable>nnnn</>.lock</literal> will be
- created in the <varname>unix_socket_directory</> directory. Neither
+ created in the <varname>unix_socket_directories</> directories. Neither
file should ever be removed manually.
</para>
@@ -6551,7 +6552,7 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
</row>
<row>
<entry><option>-k <replaceable>x</replaceable></option></entry>
- <entry><literal>unix_socket_directory = <replaceable>x</replaceable></></entry>
+ <entry><literal>unix_socket_directories = <replaceable>x</replaceable></></entry>
</row>
<row>
<entry><option>-l</option></entry>
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 8717798..9cc9d42 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1718,7 +1718,7 @@ pg_dumpall -p 5432 | psql -d postgres -p 5433
<para>
The simplest way to prevent spoofing for <literal>local</>
connections is to use a Unix domain socket directory (<xref
- linkend="guc-unix-socket-directory">) that has write permission only
+ linkend="guc-unix-socket-directories">) that has write permission only
for a trusted local user. This prevents a malicious user from creating
their own socket file in that directory. If you are concerned that
some applications might still reference <filename>/tmp</> for the
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 5272811..3e22388 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -103,8 +103,8 @@ int Unix_socket_permissions;
char *Unix_socket_group;
-/* Where the Unix socket file is */
-static char sock_path[MAXPGPATH];
+/* Where the Unix socket files are */
+static List *sock_paths = NIL;
/*
@@ -140,8 +140,9 @@ static int internal_flush(void);
static void pq_set_nonblocking(bool nonblocking);
#ifdef HAVE_UNIX_SOCKETS
-static int Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName);
-static int Setup_AF_UNIX(void);
+static int Lock_AF_UNIX(unsigned short portNumber, char *unixSocketDir,
+ char *unixSocketPath);
+static int Setup_AF_UNIX(char *sock_path);
#endif /* HAVE_UNIX_SOCKETS */
@@ -234,14 +235,23 @@ pq_close(int code, Datum arg)
/* StreamDoUnlink()
* Shutdown routine for backend connection
- * If a Unix socket is used for communication, explicitly close it.
+ * If any Unix sockets are used for communication, explicitly close them.
*/
#ifdef HAVE_UNIX_SOCKETS
static void
StreamDoUnlink(int code, Datum arg)
{
- Assert(sock_path[0]);
- unlink(sock_path);
+ ListCell *l;
+ char *cursocket;
+
+ /* Loop through all created sockets... */
+ foreach(l, sock_paths)
+ {
+ cursocket = (char *) lfirst(l);
+ unlink(cursocket);
+ }
+ list_free(sock_paths);
+ sock_paths = NIL;
}
#endif /* HAVE_UNIX_SOCKETS */
@@ -256,7 +266,7 @@ StreamDoUnlink(int code, Datum arg)
int
StreamServerPort(int family, char *hostName, unsigned short portNumber,
- char *unixSocketName,
+ char *unixSocketDir,
pgsocket ListenSocket[], int MaxListen)
{
pgsocket fd;
@@ -267,6 +277,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
const char *familyDesc;
char familyDescBuf[64];
char *service;
+ char unixSocketPath[MAXPGPATH];
struct addrinfo *addrs = NULL,
*addr;
struct addrinfo hint;
@@ -286,10 +297,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
#ifdef HAVE_UNIX_SOCKETS
if (family == AF_UNIX)
{
- /* Lock_AF_UNIX will also fill in sock_path. */
- if (Lock_AF_UNIX(portNumber, unixSocketName) != STATUS_OK)
+ /*
+ * Create unixSocketPath from portNumber and unixSocketDir
+ * and lock that file
+ */
+ UNIXSOCK_PATH(unixSocketPath, portNumber, unixSocketDir);
+ if (Lock_AF_UNIX(portNumber, unixSocketDir, unixSocketPath) != STATUS_OK)
return STATUS_ERROR;
- service = sock_path;
+ service = unixSocketPath;
}
else
#endif /* HAVE_UNIX_SOCKETS */
@@ -432,7 +447,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
(IS_AF_UNIX(addr->ai_family)) ?
errhint("Is another postmaster already running on port %d?"
" If not, remove socket file \"%s\" and retry.",
- (int) portNumber, sock_path) :
+ (int) portNumber, service) :
errhint("Is another postmaster already running on port %d?"
" If not, wait a few seconds and retry.",
(int) portNumber)));
@@ -443,7 +458,7 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
#ifdef HAVE_UNIX_SOCKETS
if (addr->ai_family == AF_UNIX)
{
- if (Setup_AF_UNIX() != STATUS_OK)
+ if (Setup_AF_UNIX(service) != STATUS_OK)
{
closesocket(fd);
break;
@@ -490,10 +505,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber,
* Lock_AF_UNIX -- configure unix socket file path
*/
static int
-Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
+Lock_AF_UNIX(unsigned short portNumber, char *unixSocketDir, char *unixSocketPath)
{
- UNIXSOCK_PATH(sock_path, portNumber, unixSocketName);
-
/*
* Grab an interlock file associated with the socket file.
*
@@ -502,13 +515,19 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
* more portable, and second, it lets us remove any pre-existing socket
* file without race conditions.
*/
- CreateSocketLockFile(sock_path, true);
+ CreateSocketLockFile(unixSocketPath, true, unixSocketDir);
/*
* Once we have the interlock, we can safely delete any pre-existing
* socket file to avoid failure at bind() time.
*/
- unlink(sock_path);
+ unlink(unixSocketPath);
+
+ /*
+ * Add a new socket file to the list, so we always know which socket
+ * paths exist and should be removed in the end.
+ */
+ sock_paths = lappend(sock_paths, pstrdup(unixSocketPath));
return STATUS_OK;
}
@@ -518,7 +537,7 @@ Lock_AF_UNIX(unsigned short portNumber, char *unixSocketName)
* Setup_AF_UNIX -- configure unix socket permissions
*/
static int
-Setup_AF_UNIX(void)
+Setup_AF_UNIX(char *sock_path)
{
/* Arrange to unlink the socket file at exit */
on_proc_exit(StreamDoUnlink, 0);
@@ -707,17 +726,21 @@ StreamClose(pgsocket sock)
* TouchSocketFile -- mark socket file as recently accessed
*
* This routine should be called every so often to ensure that the socket
- * file has a recent mod date (ordinary operations on sockets usually won't
- * change the mod date). That saves it from being removed by
+ * files have a recent mod date (ordinary operations on sockets usually won't
+ * change the mod date). That saves them from being removed by
* overenthusiastic /tmp-directory-cleaner daemons. (Another reason we should
- * never have put the socket file in /tmp...)
+ * never have put the socket files in /tmp...)
*/
void
TouchSocketFile(void)
{
- /* Do nothing if we did not create a socket... */
- if (sock_path[0] != '\0')
+ ListCell *l;
+ char *cursocket;
+
+ /* Loop through all created sockets... */
+ foreach(l, sock_paths)
{
+ cursocket = (char *) lfirst(l);
/*
* utime() is POSIX standard, utimes() is a common alternative. If we
* have neither, there's no way to affect the mod or access time of
@@ -726,10 +749,10 @@ TouchSocketFile(void)
* In either path, we ignore errors; there's no point in complaining.
*/
#ifdef HAVE_UTIME
- utime(sock_path, NULL);
+ utime(cursocket, NULL);
#else /* !HAVE_UTIME */
#ifdef HAVE_UTIMES
- utimes(sock_path, NULL);
+ utimes(cursocket, NULL);
#endif /* HAVE_UTIMES */
#endif /* HAVE_UTIME */
}
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 45f6ac6..a89455f 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -156,7 +156,8 @@ static Backend *ShmemBackendArray;
/* The socket number we are listening for connections on */
int PostPortNumber;
-char *UnixSocketDir;
+char *UnixSocketDirs;
+List *UnixSocketDirList;
char *ListenAddresses;
/*
@@ -609,7 +610,7 @@ PostmasterMain(int argc, char *argv[])
break;
case 'k':
- SetConfigOption("unix_socket_directory", optarg, PGC_POSTMASTER, PGC_S_ARGV);
+ SetConfigOption("unix_socket_directories", optarg, PGC_POSTMASTER, PGC_S_ARGV);
break;
case 'l':
@@ -838,6 +839,47 @@ PostmasterMain(int argc, char *argv[])
for (i = 0; i < MAXLISTEN; i++)
ListenSocket[i] = PGINVALID_SOCKET;
+#ifdef HAVE_UNIX_SOCKETS
+ /*
+ * We can specify several directories for Unix sockets to listen on,
+ * separated with ','. Socket name itself is the same in all cases.
+ */
+ {
+ int success = 0;
+ bool listen_socket_saved = false;
+ ListCell *l;
+
+ foreach(l, UnixSocketDirList)
+ {
+ char *cursocket = (char *) lfirst(l);
+
+ status = StreamServerPort(AF_UNIX, NULL,
+ (unsigned short) PostPortNumber,
+ cursocket,
+ ListenSocket, MAXLISTEN);
+
+ if (status == STATUS_OK)
+ {
+ success++;
+ /* record the first successful unix socket in lockfile */
+ if (!listen_socket_saved)
+ {
+ AddToDataDirLockFile(LOCK_FILE_LINE_SOCKET_DIR, cursocket);
+ listen_socket_saved = true;
+ }
+ }
+ else
+ ereport(WARNING,
+ (errmsg("could not create Unix-domain socket at \"%s\"", cursocket)));
+
+ }
+
+ if (!success && list_length(UnixSocketDirList))
+ ereport(FATAL,
+ (errmsg("could not create any Unix-domain sockets")));
+ }
+#endif
+
if (ListenAddresses)
{
char *rawstring;
@@ -864,12 +906,12 @@ PostmasterMain(int argc, char *argv[])
if (strcmp(curhost, "*") == 0)
status = StreamServerPort(AF_UNSPEC, NULL,
(unsigned short) PostPortNumber,
- UnixSocketDir,
+ NULL,
ListenSocket, MAXLISTEN);
else
status = StreamServerPort(AF_UNSPEC, curhost,
(unsigned short) PostPortNumber,
- UnixSocketDir,
+ NULL,
ListenSocket, MAXLISTEN);
if (status == STATUS_OK)
@@ -934,16 +976,6 @@ PostmasterMain(int argc, char *argv[])
}
#endif
-#ifdef HAVE_UNIX_SOCKETS
- status = StreamServerPort(AF_UNIX, NULL,
- (unsigned short) PostPortNumber,
- UnixSocketDir,
- ListenSocket, MAXLISTEN);
- if (status != STATUS_OK)
- ereport(WARNING,
- (errmsg("could not create Unix-domain socket")));
-#endif
-
/*
* check that we have some socket to listen on
*/
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 9a5438f..265fad9 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3343,7 +3343,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx)
break;
case 'k':
- SetConfigOption("unix_socket_directory", optarg, ctx, gucsource);
+ SetConfigOption("unix_socket_directories", optarg, ctx, gucsource);
break;
case 'l':
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index e1b57ba..bddc972 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -2445,6 +2445,109 @@ SplitIdentifierString(char *rawstring, char separator,
return true;
}
+/*
+ * SplitDirectoriesString --- parse a string containing directories
+ *
+ * Inputs:
+ * rawstring: the input string; must be overwritable! On return, it's
+ * been modified to contain the separated directories.
+ * separator: the separator punctuation expected between directories
+ * (typically ',' or ';'). Whitespace may also appear around
+ * directories.
+ * Outputs:
+ * namelist: filled with a palloc'd list of pointers to directories within
+ * rawstring. Caller should list_free() this even on error return.
+ *
+ * Returns TRUE if okay, FALSE if there is a syntax error in the string.
+ *
+ * Note that an empty string is considered okay here.
+ */
+bool
+SplitDirectoriesString(char *rawstring, char separator,
+ List **namelist)
+{
+ char *nextp = rawstring;
+ bool done = false;
+ char *tmpname;
+
+ *namelist = NIL;
+
+ while (isspace((unsigned char) *nextp))
+ nextp++; /* skip leading whitespace */
+
+ if (*nextp == '\0')
+ return true; /* allow empty string */
+
+ /* At the top of the loop, we are at start of a new directories. */
+ do
+ {
+ char *curname;
+ char *endp;
+
+ if (*nextp == '\"')
+ {
+ /* Quoted name --- collapse quote-quote pairs */
+ curname = nextp + 1;
+ for (;;)
+ {
+ endp = strchr(nextp + 1, '\"');
+ if (endp == NULL)
+ return false; /* mismatched quotes */
+ if (endp[1] != '\"')
+ break; /* found end of quoted name */
+ /* Collapse adjacent quotes into one quote, and look again */
+ memmove(endp, endp + 1, strlen(endp));
+ nextp = endp;
+ }
+ /* endp now points at the terminating quote */
+ nextp = endp + 1;
+ }
+ else
+ {
+ /* Unquoted name --- extends to separator or whitespace */
+ curname = nextp;
+ while (*nextp && *nextp != separator &&
+ !isspace((unsigned char) *nextp))
+ nextp++;
+ endp = nextp;
+ if (curname == nextp)
+ return false; /* empty unquoted name not allowed */
+ }
+
+ while (isspace((unsigned char) *nextp))
+ nextp++; /* skip trailing whitespace */
+
+ if (*nextp == separator)
+ {
+ nextp++;
+ while (isspace((unsigned char) *nextp))
+ nextp++; /* skip leading whitespace for next */
+ /* we expect another name, so done remains false */
+ }
+ else if (*nextp == '\0')
+ done = true;
+ else
+ return false; /* invalid syntax */
+
+ /* Now safe to overwrite separator with a null */
+ *endp = '\0';
+
+ /* Truncate path if it's overlength */
+ if (strlen(curname) >= MAXPGPATH)
+ curname[MAXPGPATH-1] = '\0';
+
+ /*
+ * Finished isolating current name --- add it to list
+ */
+ tmpname = pstrdup(curname);
+ canonicalize_path(tmpname);
+ *namelist = lappend(*namelist, tmpname);
+
+ /* Loop back if we didn't reach end of string */
+ } while (!done);
+
+ return true;
+}
/*****************************************************************************
* Comparison Functions used for bytea
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index fb376a0..8620ee8 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -663,10 +663,11 @@ UnlinkLockFile(int status, Datum filename)
* filename is the name of the lockfile to create.
* amPostmaster is used to determine how to encode the output PID.
* isDDLock and refName are used to determine what error message to produce.
+ * socketPath is the path to the Unix socket we want to lock.
*/
static void
CreateLockFile(const char *filename, bool amPostmaster,
- bool isDDLock, const char *refName)
+ bool isDDLock, const char *refName, const char *socketPath)
{
int fd;
char buffer[MAXPGPATH * 2 + 256];
@@ -892,7 +893,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
(long) MyStartTime,
PostPortNumber,
#ifdef HAVE_UNIX_SOCKETS
- (*UnixSocketDir != '\0') ? UnixSocketDir : DEFAULT_PGSOCKET_DIR
+ (socketPath) ? socketPath : ""
#else
""
#endif
@@ -949,19 +950,20 @@ CreateLockFile(const char *filename, bool amPostmaster,
void
CreateDataDirLockFile(bool amPostmaster)
{
- CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, true, DataDir);
+ CreateLockFile(DIRECTORY_LOCK_FILE, amPostmaster, true, DataDir, NULL);
}
/*
* Create a lockfile for the specified Unix socket file.
*/
void
-CreateSocketLockFile(const char *socketfile, bool amPostmaster)
+CreateSocketLockFile(const char *socketfile, bool amPostmaster,
+ const char *socketDir)
{
char lockfile[MAXPGPATH];
snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile);
- CreateLockFile(lockfile, amPostmaster, false, socketfile);
+ CreateLockFile(lockfile, amPostmaster, false, socketfile, socketDir);
/* Save name of lockfile for TouchSocketLockFile */
strcpy(socketLockFile, lockfile);
}
@@ -1292,3 +1294,4 @@ pg_bindtextdomain(const char *domain)
}
#endif
}
+
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 087aaf9..5603ce4 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -207,6 +207,7 @@ static bool check_application_name(char **newval, void **extra, GucSource source
static void assign_application_name(const char *newval, void *extra);
static const char *show_unix_socket_permissions(void);
static const char *show_log_file_mode(void);
+static void assign_unix_socket_directories(const char *newval, void *extra);
static char *config_enum_get_options(struct config_enum * record,
const char *prefix, const char *suffix,
@@ -2895,14 +2896,18 @@ static struct config_string ConfigureNamesString[] =
},
{
- {"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
- gettext_noop("Sets the directory where the Unix-domain socket will be created."),
- NULL,
+ {"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
+ gettext_noop("Sets the directories where the Unix-domain socket will be created."),
+ gettext_noop("Directories are separated by \",\"."),
GUC_SUPERUSER_ONLY
},
- &UnixSocketDir,
+ &UnixSocketDirs,
+#ifdef HAVE_UNIX_SOCKETS
+ DEFAULT_PGSOCKET_DIR,
+#else
"",
- check_canonical_path, NULL, NULL
+#endif
+ NULL, assign_unix_socket_directories, NULL
},
{
@@ -8759,4 +8764,34 @@ show_log_file_mode(void)
return buf;
}
+static void
+assign_unix_socket_directories(const char *newval, void *extra)
+{
+#ifdef HAVE_UNIX_SOCKETS
+ char *rawSocketsString;
+ ListCell *l;
+
+ /* Clean previous UnixSocketDirList list if not empty */
+ if (UnixSocketDirList)
+ {
+ list_free(UnixSocketDirList);
+ UnixSocketDirList = NIL;
+ }
+
+ /* Need a modifiable copy of value */
+ rawSocketsString = pstrdup(newval);
+
+ /* Parse string into list of directories */
+ if (!SplitDirectoriesString(rawSocketsString, ',', &UnixSocketDirList))
+ {
+ /* syntax error in list */
+ ereport(FATAL,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid list syntax for \"unix_socket_directories\"")));
+ }
+
+ pfree(rawSocketsString);
+#endif
+}
+
#include "guc-file.c"
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index fa75d00..42b5e40 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -65,7 +65,8 @@
# Note: Increasing max_connections costs ~400 bytes of shared memory per
# connection slot, plus lock space (see max_locks_per_transaction).
#superuser_reserved_connections = 3 # (change requires restart)
-#unix_socket_directory = '' # (change requires restart)
+#unix_socket_directories = '' # comma-separated list of directories,
+ # (change requires restart)
#unix_socket_group = '' # (change requires restart)
#unix_socket_permissions = 0777 # begin with 0 to use octal notation
# (change requires restart)
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 72fc4c1..af8d8b2 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -521,7 +521,7 @@ test_postmaster_connection(bool do_checkpoint)
hostaddr = optlines[LOCK_FILE_LINE_LISTEN_ADDR - 1];
/*
- * While unix_socket_directory can accept relative
+ * While unix_socket_directories can accept relative
* directories, libpq's host parameter must have a
* leading slash to indicate a socket directory. So,
* ignore sockdir if it's relative, and try to use TCP
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index 7083cd8..a79200d 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -45,7 +45,7 @@ typedef struct
* prototypes for functions in pqcomm.c
*/
extern int StreamServerPort(int family, char *hostName,
- unsigned short portNumber, char *unixSocketName, pgsocket ListenSocket[],
+ unsigned short portNumber, char *unixSocketDir, pgsocket ListenSocket[],
int MaxListen);
extern int StreamConnection(pgsocket server_fd, Port *port);
extern void StreamClose(pgsocket sock);
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index b186eed..edfa161 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -399,7 +399,8 @@ extern char *local_preload_libraries_string;
#define LOCK_FILE_LINE_SHMEM_KEY 7
extern void CreateDataDirLockFile(bool amPostmaster);
-extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster);
+extern void CreateSocketLockFile(const char *socketfile, bool amPostmaster,
+ const char *socketDir);
extern void TouchSocketLockFile(void);
extern void AddToDataDirLockFile(int target_line, const char *str);
extern void ValidatePgVersion(const char *path);
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index 7d01d3d..aa549e6 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -13,13 +13,16 @@
#ifndef _POSTMASTER_H
#define _POSTMASTER_H
+#include "utils/builtins.h"
+
/* GUC options */
extern bool EnableSSL;
extern int ReservedBackends;
extern int PostPortNumber;
extern int Unix_socket_permissions;
extern char *Unix_socket_group;
-extern char *UnixSocketDir;
+extern char *UnixSocketDirs;
+extern List *UnixSocketDirList;
extern char *ListenAddresses;
extern bool ClientAuthInProgress;
extern int PreAuthDelay;
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 1063403..adab4ec 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -752,6 +752,8 @@ extern int varstr_cmp(char *arg1, int len1, char *arg2, int len2, Oid collid);
extern List *textToQualifiedNameList(text *textval);
extern bool SplitIdentifierString(char *rawstring, char separator,
List **namelist);
+extern bool SplitDirectoriesString(char *rawstring, char separator,
+ List **namelist);
extern Datum replace_text(PG_FUNCTION_ARGS);
extern text *replace_text_regexp(text *src_text, void *regexp,
text *replace_text, bool glob);
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers