From b5f496c2ee05266909bd9952bcac819377850083 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 7 Aug 2019 15:44:19 +0200 Subject: [PATCH v3 5/7] initdb: Detect Unix-domain socket support dynamically On Windows we now have to support the situation where a binary built with Unix-domain socket support could be used on a system that doesn't support it at run time. So in initdb, for setting up the default pg_hba.conf and postgresql.conf, do a run-time check for support instead of relying on compile-time decisions. This is very similar to what we already do for IPv6, so similar code can be used. A change is that now if Unix-domain socket support is not found, the "local" lines in pg_hba.conf are commented out instead of removed, again similar to IPv6 support. --- src/backend/libpq/pg_hba.conf.sample | 6 +- src/bin/initdb/initdb.c | 170 +++++++++++++-------------- 2 files changed, 84 insertions(+), 92 deletions(-) diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index c853e36232..0c163d2c6d 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -76,14 +76,14 @@ # TYPE DATABASE USER ADDRESS METHOD -@remove-line-for-nolocal@# "local" is for Unix domain socket connections only -@remove-line-for-nolocal@local all all @authmethodlocal@ +# "local" is for Unix domain socket connections only +local all all @authmethodlocal@ # IPv4 local connections: host all all 127.0.0.1/32 @authmethodhost@ # IPv6 local connections: host all all ::1/128 @authmethodhost@ # Allow replication connections from localhost, by a user with the # replication privilege. -@remove-line-for-nolocal@local replication all @authmethodlocal@ +local replication all @authmethodlocal@ host replication all 127.0.0.1/32 @authmethodhost@ host replication all ::1/128 @authmethodhost@ diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 88a261d9bd..ffbcf685d5 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -233,9 +233,6 @@ static char backend_exec[MAXPGPATH]; static char **replace_token(char **lines, const char *token, const char *replacement); -#ifndef HAVE_UNIX_SOCKETS -static char **filter_lines_with_token(char **lines, const char *token); -#endif static char **readfile(const char *path); static void writefile(char *path, char **lines); static FILE *popen_check(const char *command, const char *mode); @@ -433,36 +430,6 @@ replace_token(char **lines, const char *token, const char *replacement) return result; } -/* - * make a copy of lines without any that contain the token - * - * a sort of poor man's grep -v - */ -#ifndef HAVE_UNIX_SOCKETS -static char ** -filter_lines_with_token(char **lines, const char *token) -{ - int numlines = 1; - int i, - src, - dst; - char **result; - - for (i = 0; lines[i]; i++) - numlines++; - - result = (char **) pg_malloc(numlines * sizeof(char *)); - - for (src = 0, dst = 0; src < numlines; src++) - { - if (lines[src] == NULL || strstr(lines[src], token) == NULL) - result[dst++] = lines[src]; - } - - return result; -} -#endif - /* * get the lines from a text file */ @@ -1072,10 +1039,70 @@ setup_config(void) char repltok[MAXPGPATH]; char path[MAXPGPATH]; char *autoconflines[3]; + bool unix_sockets_work = false; + bool ipv6_works = false; fputs(_("creating configuration files ... "), stdout); fflush(stdout); +#ifdef WIN32 + { + /* need to call WSAStartup before calling socket or getaddrinfo */ + int err = 0; + WSADATA wsaData; + + err = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (err != 0) + { + pg_log_error("WSAStartup failed: %d", err); + exit(1); + } + } +#endif + +#ifdef HAVE_UNIX_SOCKETS + /* + * Probe to see whether Unix-domain sockets are working. + */ + { + pgsocket tmpsock; + + tmpsock = socket(AF_UNIX, SOCK_STREAM, 0); + if (tmpsock != PGINVALID_SOCKET) + { + unix_sockets_work = true; + closesocket(tmpsock); + } + } +#endif + +#ifdef HAVE_IPV6 + /* + * Probe to see if there is really any platform support for IPv6, and + * comment out the relevant pg_hba line if not. This avoids runtime + * warnings if getaddrinfo doesn't actually cope with IPv6. Particularly + * useful on Windows, where executables built on a machine with IPv6 may + * have to run on a machine without. + */ + { + struct addrinfo *gai_result; + struct addrinfo hints; + + /* for best results, this code should match parse_hba_line() */ + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + if (getaddrinfo("::1", NULL, &hints, &gai_result) == 0) + ipv6_works = true; + } +#endif /* !HAVE_IPV6 */ + /* postgresql.conf */ conflines = readfile(conf_file); @@ -1092,8 +1119,11 @@ setup_config(void) conflines = replace_token(conflines, "#shared_buffers = 32MB", repltok); #ifdef HAVE_UNIX_SOCKETS - snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'", - DEFAULT_PGSOCKET_DIR); + if (unix_sockets_work) + snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'", + DEFAULT_PGSOCKET_DIR); + else + snprintf(repltok, sizeof(repltok), "unix_socket_directories = ''"); #else snprintf(repltok, sizeof(repltok), "#unix_socket_directories = ''"); #endif @@ -1256,63 +1286,25 @@ setup_config(void) conflines = readfile(hba_file); -#ifndef HAVE_UNIX_SOCKETS - conflines = filter_lines_with_token(conflines, "@remove-line-for-nolocal@"); -#else - conflines = replace_token(conflines, "@remove-line-for-nolocal@", ""); -#endif - -#ifdef HAVE_IPV6 - - /* - * Probe to see if there is really any platform support for IPv6, and - * comment out the relevant pg_hba line if not. This avoids runtime - * warnings if getaddrinfo doesn't actually cope with IPv6. Particularly - * useful on Windows, where executables built on a machine with IPv6 may - * have to run on a machine without. - */ + if (!unix_sockets_work) { - struct addrinfo *gai_result; - struct addrinfo hints; - int err = 0; - -#ifdef WIN32 - /* need to call WSAStartup before calling getaddrinfo */ - WSADATA wsaData; - - err = WSAStartup(MAKEWORD(2, 2), &wsaData); -#endif - - /* for best results, this code should match parse_hba_line() */ - hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = 0; - hints.ai_protocol = 0; - hints.ai_addrlen = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; + conflines = replace_token(conflines, + "local all", + "#local all"); + conflines = replace_token(conflines, + "local replication", + "#local replication"); + } - if (err != 0 || - getaddrinfo("::1", NULL, &hints, &gai_result) != 0) - { - conflines = replace_token(conflines, - "host all all ::1", - "#host all all ::1"); - conflines = replace_token(conflines, - "host replication all ::1", - "#host replication all ::1"); - } + if (!ipv6_works) + { + conflines = replace_token(conflines, + "host all all ::1", + "#host all all ::1"); + conflines = replace_token(conflines, + "host replication all ::1", + "#host replication all ::1"); } -#else /* !HAVE_IPV6 */ - /* If we didn't compile IPV6 support at all, always comment it out */ - conflines = replace_token(conflines, - "host all all ::1", - "#host all all ::1"); - conflines = replace_token(conflines, - "host replication all ::1", - "#host replication all ::1"); -#endif /* HAVE_IPV6 */ /* Replace default authentication methods */ conflines = replace_token(conflines, -- 2.22.0