From bd7c4252fc907c7406aa4ca0438e74f494b2d3c3 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Tue, 9 Oct 2018 15:01:30 +0200
Subject: [PATCH] Support custom socket directory during upgrades

The upgrade process will use CWD as the location for sockets dir, which
is limited by the sockaddr_un structure to around 100 bytes. In order to
avoid hitting the limit, support an optional command line parameter for
overriding the socket directory.
---
 doc/src/sgml/ref/pgupgrade.sgml |  8 ++++++++
 src/bin/pg_upgrade/option.c     | 26 +++++++++++++++++++++-----
 src/bin/pg_upgrade/pg_upgrade.h |  2 ++
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/doc/src/sgml/ref/pgupgrade.sgml b/doc/src/sgml/ref/pgupgrade.sgml
index d51146d641..750f080282 100644
--- a/doc/src/sgml/ref/pgupgrade.sgml
+++ b/doc/src/sgml/ref/pgupgrade.sgml
@@ -163,6 +163,14 @@
       </para></listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-s</option></term>
+      <term><option>--socketdir=</option><replaceable>dir</replaceable></term>
+      <listitem><para>directory to use for sockets during upgrade, default is
+	  current working directory
+      </para></listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-U</option> <replaceable>username</replaceable></term>
       <term><option>--username=</option><replaceable>username</replaceable></term>
diff --git a/src/bin/pg_upgrade/option.c b/src/bin/pg_upgrade/option.c
index 9dbc9225a6..84ee7edab8 100644
--- a/src/bin/pg_upgrade/option.c
+++ b/src/bin/pg_upgrade/option.c
@@ -52,6 +52,7 @@ parseCommandLine(int argc, char *argv[])
 		{"link", no_argument, NULL, 'k'},
 		{"retain", no_argument, NULL, 'r'},
 		{"jobs", required_argument, NULL, 'j'},
+		{"socketdir", required_argument, NULL, 's'},
 		{"verbose", no_argument, NULL, 'v'},
 		{NULL, 0, NULL, 0}
 	};
@@ -64,6 +65,8 @@ parseCommandLine(int argc, char *argv[])
 
 	user_opts.transfer_mode = TRANSFER_MODE_COPY;
 
+	user_opts.socketdir = NULL;
+
 	os_info.progname = get_progname(argv[0]);
 
 	/* Process libpq env. variables; load values here for usage() output */
@@ -100,7 +103,7 @@ parseCommandLine(int argc, char *argv[])
 	if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
 		pg_fatal("could not write to log file \"%s\"\n", INTERNAL_LOG_FILE);
 
-	while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rU:v",
+	while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rs:U:v",
 								 long_options, &optindex)) != -1)
 	{
 		switch (option)
@@ -186,6 +189,10 @@ parseCommandLine(int argc, char *argv[])
 				log_opts.retain = true;
 				break;
 
+			case 's':
+				user_opts.socketdir = pg_strdup(optarg);
+				break;
+
 			case 'U':
 				pg_free(os_info.user);
 				os_info.user = pg_strdup(optarg);
@@ -291,6 +298,7 @@ usage(void)
 	printf(_("  -P, --new-port=PORT           new cluster port number (default %d)\n"), new_cluster.port);
 	printf(_("  -r, --retain                  retain SQL and log files after success\n"));
 	printf(_("  -U, --username=NAME           cluster superuser (default \"%s\")\n"), os_info.user);
+	printf(_("  -s, --socketdir=DIR           socket directory during upgrades (default CWD)\n"));
 	printf(_("  -v, --verbose                 enable verbose internal logging\n"));
 	printf(_("  -V, --version                 display version information, then exit\n"));
 	printf(_("  -?, --help                    show this help, then exit\n"));
@@ -456,10 +464,18 @@ get_sock_dir(ClusterInfo *cluster, bool live_check)
 	{
 		if (!live_check)
 		{
-			/* Use the current directory for the socket */
-			cluster->sockdir = pg_malloc(MAXPGPATH);
-			if (!getcwd(cluster->sockdir, MAXPGPATH))
-				pg_fatal("could not determine current directory\n");
+			if (user_opts.socketdir)
+				cluster->sockdir = user_opts.socketdir;
+			else
+			{
+				/*
+				 * If the user hasn't requested a specific path, use the
+				 * current directory for the socket
+				 */
+				cluster->sockdir = pg_malloc(MAXPGPATH);
+				if (!getcwd(cluster->sockdir, MAXPGPATH))
+					pg_log(PG_FATAL, "cannot find current directory\n");
+			}
 		}
 		else
 		{
diff --git a/src/bin/pg_upgrade/pg_upgrade.h b/src/bin/pg_upgrade/pg_upgrade.h
index f83a3eeb67..d745ee101c 100644
--- a/src/bin/pg_upgrade/pg_upgrade.h
+++ b/src/bin/pg_upgrade/pg_upgrade.h
@@ -298,6 +298,8 @@ typedef struct
 								 * changes */
 	transferMode transfer_mode; /* copy files or link them? */
 	int			jobs;
+	char	   *socketdir;		/* directory to use for sockets, NULL means
+								 * using the default of CWD */
 } UserOpts;
 
 typedef struct
-- 
2.14.1.145.gb3622a4ee

