diff --git a/doc/src/sgml/ref/pg_resetxlog.sgml b/doc/src/sgml/ref/pg_resetxlog.sgml
index fd9d0be6f44..9758fa652a2 100644
--- a/doc/src/sgml/ref/pg_resetxlog.sgml
+++ b/doc/src/sgml/ref/pg_resetxlog.sgml
@@ -281,6 +281,11 @@ PostgreSQL documentation
pg_resetxlog to run. But before you do
so, make doubly certain that there is no server process still alive.
+
+
+ pg_resetxlog works only with servers of the same
+ major version.
+
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 3ffff22daab..fdd75044de8 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -72,6 +72,7 @@ static MultiXactOffset set_mxoff = (MultiXactOffset) -1;
static uint32 minXlogTli = 0;
static XLogSegNo minXlogSegNo = 0;
+static void CheckDataVersion(void);
static bool ReadControlFile(void);
static void GuessControlValues(void);
static void PrintControlValues(bool guessed);
@@ -320,6 +321,9 @@ main(int argc, char *argv[])
exit(1);
}
+ /* Check that data directory matches our server version */
+ CheckDataVersion();
+
/*
* Check for a postmaster lock file --- if there is one, refuse to
* proceed, on grounds we might be interfering with a live installation.
@@ -453,6 +457,70 @@ main(int argc, char *argv[])
}
+/*
+ * Look at the version string stored in PG_VERSION and decide if this utility
+ * can be run safely or not.
+ *
+ * We don't want to inject pg_control and WAL files that are for a different
+ * major version; that can't do anything good. Note that we don't treat
+ * mismatching version info in pg_control as a reason to bail out, because
+ * recovering from a corrupted pg_control is one of the main reasons for this
+ * program to exist at all. However, PG_VERSION is unlikely to get corrupted,
+ * and if it were it would be easy to fix by hand. So let's make this check
+ * to prevent simple user errors.
+ */
+static void
+CheckDataVersion(void)
+{
+ const char *ver_file = "PG_VERSION";
+ FILE *ver_fd;
+ char rawline[64];
+ int len;
+
+ if ((ver_fd = fopen(ver_file, "r")) == NULL)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+ progname, ver_file, strerror(errno));
+ exit(1);
+ }
+
+ /* version number has to be the first line read */
+ if (!fgets(rawline, sizeof(rawline), ver_fd))
+ {
+ if (!ferror(ver_fd))
+ {
+ fprintf(stderr, _("%s: unexpected empty file \"%s\"\n"),
+ progname, ver_file);
+ }
+ else
+ {
+ fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
+ progname, ver_file, strerror(errno));
+ }
+ exit(1);
+ }
+
+ /* remove trailing newline, handling Windows newlines as well */
+ len = strlen(rawline);
+ if (len > 0 && rawline[len - 1] == '\n')
+ {
+ rawline[--len] = '\0';
+ if (len > 0 && rawline[len - 1] == '\r')
+ rawline[--len] = '\0';
+ }
+
+ if (strcmp(rawline, PG_MAJORVERSION) != 0)
+ {
+ fprintf(stderr, _("%s: data directory is of wrong version\n"
+ "File \"%s\" contains \"%s\", which is not compatible with this program's version \"%s\".\n"),
+ progname, ver_file, rawline, PG_MAJORVERSION);
+ exit(1);
+ }
+
+ fclose(ver_fd);
+}
+
+
/*
* Try to read the existing pg_control file.
*
@@ -522,7 +590,7 @@ ReadControlFile(void)
}
/* Looks like it's a mess. */
- fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),
+ fprintf(stderr, _("%s: pg_control exists but is broken or wrong version; ignoring it\n"),
progname);
return false;
}