From a80b8037cfc24a4fa75ba267b6d39cba105ad4d6 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 3 Sep 2012 22:15:09 -0400
Subject: [PATCH] In pg_upgrade, pull the port number from postmaster.pid, like
 we do for socket location.  Also, prevent putting the socket in the current
 directory for pre-9.1 servers in live check and non-live check mode, because
 pre-9.1 pg_ctl -w can't handle it.

Backpatch to 9.2.
---
 contrib/pg_upgrade/check.c      | 16 ++++---
 contrib/pg_upgrade/option.c     | 84 ++++++++++++++++++++-------------
 contrib/pg_upgrade/pg_upgrade.c |  3 +-
 3 files changed, 62 insertions(+), 41 deletions(-)

diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index d965fa81577..c89b2dfd0fd 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -58,12 +58,6 @@ output_check_banner(bool *live_check)
 	if (user_opts.check && is_server_running(old_cluster.pgdata))
 	{
 		*live_check = true;
-		if (old_cluster.port == DEF_PGUPORT)
-			pg_log(PG_FATAL, "When checking a live old server, "
-				   "you must specify the old server's port number.\n");
-		if (old_cluster.port == new_cluster.port)
-			pg_log(PG_FATAL, "When checking a live server, "
-				   "the old and new port numbers must be different.\n");
 		pg_log(PG_REPORT, "Performing Consistency Checks on Old Live Server\n");
 		pg_log(PG_REPORT, "------------------------------------------------\n");
 	}
@@ -320,6 +314,16 @@ check_cluster_compatibility(bool live_check)
 		new_cluster.controldata.cat_ver < TABLE_SPACE_SUBDIRS_CAT_VER)
 		pg_log(PG_FATAL, "This utility can only upgrade to PostgreSQL version 9.0 after 2010-01-11\n"
 			   "because of backend API changes made during development.\n");
+
+	/* We read the real port number for PG >= 9.1 */
+	if (live_check && GET_MAJOR_VERSION(old_cluster.major_version) < 901 &&
+		old_cluster.port == DEF_PGUPORT)
+			pg_log(PG_FATAL, "When checking a pre-PG 9.1 live old server, "
+				   "you must specify the old server's port number.\n");
+
+	if (live_check && old_cluster.port == new_cluster.port)
+		pg_log(PG_FATAL, "When checking a live server, "
+			   "the old and new port numbers must be different.\n");
 }
 
 
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index 6d5a93a0a56..19053fa9d08 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -392,49 +392,65 @@ void
 get_sock_dir(ClusterInfo *cluster, bool live_check)
 {
 #ifdef HAVE_UNIX_SOCKETS
-	if (!live_check)
-	{
-		/* 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
+	/*
+	 *	sockdir and port were added to postmaster.pid in PG 9.1.
+	 *	Pre-9.1 cannot process pg_ctl -w for sockets in non-default
+	 *	locations.
+	 */
+	if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
 	{
-		/*
-		 *	If we are doing a live check, we will use the old cluster's Unix
-		 *	domain socket directory so we can connect to the live server.
-		 */
-
-		/* sockdir was added to postmaster.pid in PG 9.1 */
-		if (GET_MAJOR_VERSION(cluster->major_version) >= 901)
+		if (!live_check)
 		{
-			char		filename[MAXPGPATH];
+			/* 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
+		{
+			/*
+			 *	If we are doing a live check, we will use the old cluster's Unix
+			 *	domain socket directory so we can connect to the live server.
+			 */
+			unsigned short orig_port = cluster->port;
+			char		filename[MAXPGPATH], line[MAXPGPATH];
 			FILE		*fp;
-			int			i;
-
+			int			lineno;
+	
 			snprintf(filename, sizeof(filename), "%s/postmaster.pid",
 					 cluster->pgdata);
 			if ((fp = fopen(filename, "r")) == NULL)
-				pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
-
-			cluster->sockdir = pg_malloc(MAXPGPATH);
-			for (i = 0; i < LOCK_FILE_LINE_SOCKET_DIR; i++)
-				if (fgets(cluster->sockdir, MAXPGPATH, fp) == NULL)
-					pg_log(PG_FATAL, "Could not get socket directory of the old server\n");
-
+				pg_log(PG_FATAL, "Cannot open file %s: %m\n", filename);
+	
+			for (lineno = 1;
+				 lineno <= Max(LOCK_FILE_LINE_PORT, LOCK_FILE_LINE_SOCKET_DIR);
+				 lineno++)
+			{
+				if (fgets(line, sizeof(line), fp) == NULL)
+					pg_log(PG_FATAL, "Cannot read line %d from %s: %m\n", lineno, filename);
+	
+				/* potentially overwrite user-supplied value */
+				if (lineno == LOCK_FILE_LINE_PORT)
+					sscanf(line, "%hu", &old_cluster.port);
+				if (lineno == LOCK_FILE_LINE_SOCKET_DIR)
+				{
+					cluster->sockdir = pg_malloc(MAXPGPATH);
+					/* strip off newline */
+					sscanf(line, "%s\n", cluster->sockdir);
+				}
+			}
 			fclose(fp);
-
-			/* Remove trailing newline */
-			if (strchr(cluster->sockdir, '\n') != NULL)
-				*strchr(cluster->sockdir, '\n') = '\0';
-		}
-		else
-		{
-			/* Can't get live sockdir, so assume the default is OK. */
-			cluster->sockdir = NULL;
+	
+			/* warn of port number correction */
+			if (orig_port != DEF_PGUPORT && old_cluster.port != orig_port)
+				pg_log(PG_WARNING, "User-supplied old port number %hu corrected to %hu\n",
+				orig_port, cluster->port);
 		}
 	}
+	else
+		/* Can't get sockdir and pg_ctl -w can't use a non-default, use default */
+		cluster->sockdir = NULL;
+
 #else /* !HAVE_UNIX_SOCKETS */
 	cluster->sockdir = NULL;
 #endif
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index ee3a1517f49..4d2e79cd486 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -86,11 +86,12 @@ main(int argc, char **argv)
 	setup(argv[0], live_check);
 
 	check_cluster_versions();
-	check_cluster_compatibility(live_check);
 
 	get_sock_dir(&old_cluster, live_check);
 	get_sock_dir(&new_cluster, false);
 
+	check_cluster_compatibility(live_check);
+
 	check_old_cluster(live_check, &sequence_script_file_name);
 
 
-- 
GitLab