>From 7218cd92b83288681bf670d910ab7fa3d1cb619e Mon Sep 17 00:00:00 2001
From: Petr Jelinek <pjmodos@pjmodos.net>
Date: Sat, 13 Jun 2015 16:14:31 +0200
Subject: [PATCH 1/4] Refactor pg_resetxlog to common API + the actual
 pg_resetxlog.

This will enable writing other similar less dangerous utilities.
---
 src/bin/pg_resetxlog/Makefile       |   6 +-
 src/bin/pg_resetxlog/common.c       | 683 ++++++++++++++++++++++++++++++++++++
 src/bin/pg_resetxlog/common.h       |  30 ++
 src/bin/pg_resetxlog/nls.mk         |   2 +-
 src/bin/pg_resetxlog/pg_resetxlog.c | 676 +----------------------------------
 5 files changed, 727 insertions(+), 670 deletions(-)
 create mode 100644 src/bin/pg_resetxlog/common.c
 create mode 100644 src/bin/pg_resetxlog/common.h

diff --git a/src/bin/pg_resetxlog/Makefile b/src/bin/pg_resetxlog/Makefile
index 2ed3adf..acaa3f7 100644
--- a/src/bin/pg_resetxlog/Makefile
+++ b/src/bin/pg_resetxlog/Makefile
@@ -15,11 +15,11 @@ subdir = src/bin/pg_resetxlog
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS= pg_resetxlog.o $(WIN32RES)
+OBJS= common.o $(WIN32RES)
 
 all: pg_resetxlog
 
-pg_resetxlog: $(OBJS) | submake-libpgport
+pg_resetxlog: $(OBJS) pg_resetxlog.o | submake-libpgport
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs
@@ -32,4 +32,4 @@ uninstall:
 	rm -f '$(DESTDIR)$(bindir)/pg_resetxlog$(X)'
 
 clean distclean maintainer-clean:
-	rm -f pg_resetxlog$(X) $(OBJS)
+	rm -f pg_resetxlog$(X) $(OBJS) pg_resetxlog.o
diff --git a/src/bin/pg_resetxlog/common.c b/src/bin/pg_resetxlog/common.c
new file mode 100644
index 0000000..d05e557
--- /dev/null
+++ b/src/bin/pg_resetxlog/common.c
@@ -0,0 +1,683 @@
+/*-------------------------------------------------------------------------
+ *
+ * common.c
+ *	  Common code for pg_resetxlog type of utilities.
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/bin/pg_resetxlog/common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "common.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "access/transam.h"
+#include "access/tuptoaster.h"
+#include "access/multixact.h"
+#include "catalog/catversion.h"
+#include "common/fe_memutils.h"
+#include "storage/large_object.h"
+#include "access/xlog.h"
+
+/*
+ * Create a new unique installation identifier.
+ *
+ * See notes in xlog.c about the algorithm.
+ */
+uint64
+GenerateSystemIdentifier(void)
+{
+	uint64			sysidentifier;
+	struct timeval	tv;
+
+	gettimeofday(&tv, NULL);
+	sysidentifier = ((uint64) tv.tv_sec) << 32;
+	sysidentifier |= ((uint64) tv.tv_usec) << 12;
+	sysidentifier |= getpid() & 0xFFF;
+
+	return sysidentifier;
+}
+
+/*
+ * Try to read the existing pg_control file.
+ *
+ * This routine is also responsible for updating old pg_control versions
+ * to the current format.  (Currently we don't do anything of the sort.)
+ */
+bool
+ReadControlFile(ControlFileData *ControlFile, bool *guessed)
+{
+	int			fd;
+	int			len;
+	char	   *buffer;
+	pg_crc32c	crc;
+
+	*guessed = false;
+
+	if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
+	{
+		/*
+		 * If pg_control is not there at all, or we can't read it, the odds
+		 * are we've been handed a bad DataDir path, so give up. User can do
+		 * "touch pg_control" to force us to proceed.
+		 */
+		fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+				progname, XLOG_CONTROL_FILE, strerror(errno));
+		if (errno == ENOENT)
+			fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
+							  "  touch %s\n"
+							  "and try again.\n"),
+					XLOG_CONTROL_FILE);
+		exit(1);
+	}
+
+	/* Use malloc to ensure we have a maxaligned buffer */
+	buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
+
+	len = read(fd, buffer, PG_CONTROL_SIZE);
+	if (len < 0)
+	{
+		fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
+				progname, XLOG_CONTROL_FILE, strerror(errno));
+		exit(1);
+	}
+	close(fd);
+
+	if (len >= sizeof(ControlFileData) &&
+	  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
+	{
+		/* Check the CRC. */
+		INIT_CRC32C(crc);
+		COMP_CRC32C(crc,
+					buffer,
+					offsetof(ControlFileData, crc));
+		FIN_CRC32C(crc);
+
+		if (EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
+		{
+			/* Valid data... */
+			memcpy(ControlFile, buffer, sizeof(ControlFileData));
+			return true;
+		}
+
+		fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
+				progname);
+		/* We will use the data anyway, but treat it as guessed. */
+		memcpy(ControlFile, buffer, sizeof(ControlFileData));
+		*guessed = true;
+		return true;
+	}
+
+	/* Looks like it's a mess. */
+	fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),
+			progname);
+	return false;
+}
+
+
+/*
+ * Guess at pg_control values when we can't read the old ones.
+ */
+void
+GuessControlValues(ControlFileData *ControlFile)
+{
+	/*
+	 * Set up a completely default set of pg_control values.
+	 */
+	memset(ControlFile, 0, sizeof(ControlFileData));
+
+	ControlFile->pg_control_version = PG_CONTROL_VERSION;
+	ControlFile->catalog_version_no = CATALOG_VERSION_NO;
+
+	/*
+	 * Create a new unique installation identifier, since we can no longer use
+	 * any old XLOG records.  See notes in xlog.c about the algorithm.
+	 */
+
+	ControlFile->system_identifier = GenerateSystemIdentifier();
+
+	ControlFile->checkPointCopy.redo = SizeOfXLogLongPHD;
+	ControlFile->checkPointCopy.ThisTimeLineID = 1;
+	ControlFile->checkPointCopy.PrevTimeLineID = 1;
+	ControlFile->checkPointCopy.fullPageWrites = false;
+	ControlFile->checkPointCopy.nextXidEpoch = 0;
+	ControlFile->checkPointCopy.nextXid = FirstNormalTransactionId;
+	ControlFile->checkPointCopy.nextOid = FirstBootstrapObjectId;
+	ControlFile->checkPointCopy.nextMulti = FirstMultiXactId;
+	ControlFile->checkPointCopy.nextMultiOffset = 0;
+	ControlFile->checkPointCopy.oldestXid = FirstNormalTransactionId;
+	ControlFile->checkPointCopy.oldestXidDB = InvalidOid;
+	ControlFile->checkPointCopy.oldestMulti = FirstMultiXactId;
+	ControlFile->checkPointCopy.oldestMultiDB = InvalidOid;
+	ControlFile->checkPointCopy.time = (pg_time_t) time(NULL);
+	ControlFile->checkPointCopy.oldestActiveXid = InvalidTransactionId;
+
+	ControlFile->state = DB_SHUTDOWNED;
+	ControlFile->time = (pg_time_t) time(NULL);
+	ControlFile->checkPoint = ControlFile->checkPointCopy.redo;
+	ControlFile->unloggedLSN = 1;
+
+	/* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
+
+	ControlFile->wal_level = WAL_LEVEL_MINIMAL;
+	ControlFile->wal_log_hints = false;
+	ControlFile->track_commit_timestamp = false;
+	ControlFile->MaxConnections = 100;
+	ControlFile->max_worker_processes = 8;
+	ControlFile->max_prepared_xacts = 0;
+	ControlFile->max_locks_per_xact = 64;
+
+	ControlFile->maxAlign = MAXIMUM_ALIGNOF;
+	ControlFile->floatFormat = FLOATFORMAT_VALUE;
+	ControlFile->blcksz = BLCKSZ;
+	ControlFile->relseg_size = RELSEG_SIZE;
+	ControlFile->xlog_blcksz = XLOG_BLCKSZ;
+	ControlFile->xlog_seg_size = XLOG_SEG_SIZE;
+	ControlFile->nameDataLen = NAMEDATALEN;
+	ControlFile->indexMaxKeys = INDEX_MAX_KEYS;
+	ControlFile->toast_max_chunk_size = TOAST_MAX_CHUNK_SIZE;
+	ControlFile->loblksize = LOBLKSIZE;
+#ifdef HAVE_INT64_TIMESTAMP
+	ControlFile->enableIntTimes = true;
+#else
+	ControlFile->enableIntTimes = false;
+#endif
+	ControlFile->float4ByVal = FLOAT4PASSBYVAL;
+	ControlFile->float8ByVal = FLOAT8PASSBYVAL;
+
+	/*
+	 * XXX eventually, should try to grovel through old XLOG to develop more
+	 * accurate values for TimeLineID, nextXID, etc.
+	 */
+}
+
+
+/*
+ * Print the guessed pg_control values when we had to guess.
+ *
+ * NB: this display should be just those fields that will not be
+ * reset by RewriteControlFile().
+ */
+void
+PrintControlValues(ControlFileData *ControlFile, bool guessed)
+{
+	char		sysident_str[32];
+
+	if (guessed)
+		printf(_("Guessed pg_control values:\n\n"));
+	else
+		printf(_("Current pg_control values:\n\n"));
+
+	/*
+	 * Format system_identifier separately to keep platform-dependent format
+	 * code out of the translatable message string.
+	 */
+	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
+			 ControlFile->system_identifier);
+
+	printf(_("pg_control version number:            %u\n"),
+		   ControlFile->pg_control_version);
+	printf(_("Catalog version number:               %u\n"),
+		   ControlFile->catalog_version_no);
+	printf(_("Database system identifier:           %s\n"),
+		   sysident_str);
+	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
+		   ControlFile->checkPointCopy.ThisTimeLineID);
+	printf(_("Latest checkpoint's full_page_writes: %s\n"),
+		   ControlFile->checkPointCopy.fullPageWrites ? _("on") : _("off"));
+	printf(_("Latest checkpoint's NextXID:          %u/%u\n"),
+		   ControlFile->checkPointCopy.nextXidEpoch,
+		   ControlFile->checkPointCopy.nextXid);
+	printf(_("Latest checkpoint's NextOID:          %u\n"),
+		   ControlFile->checkPointCopy.nextOid);
+	printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
+		   ControlFile->checkPointCopy.nextMulti);
+	printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
+		   ControlFile->checkPointCopy.nextMultiOffset);
+	printf(_("Latest checkpoint's oldestXID:        %u\n"),
+		   ControlFile->checkPointCopy.oldestXid);
+	printf(_("Latest checkpoint's oldestXID's DB:   %u\n"),
+		   ControlFile->checkPointCopy.oldestXidDB);
+	printf(_("Latest checkpoint's oldestActiveXID:  %u\n"),
+		   ControlFile->checkPointCopy.oldestActiveXid);
+	printf(_("Latest checkpoint's oldestMultiXid:   %u\n"),
+		   ControlFile->checkPointCopy.oldestMulti);
+	printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
+		   ControlFile->checkPointCopy.oldestMultiDB);
+	printf(_("Latest checkpoint's oldest CommitTs:  %u\n"),
+		   ControlFile->checkPointCopy.oldestCommitTs);
+	printf(_("Latest checkpoint's newest CommitTs:  %u\n"),
+		   ControlFile->checkPointCopy.newestCommitTs);
+	printf(_("Maximum data alignment:               %u\n"),
+		   ControlFile->maxAlign);
+	/* we don't print floatFormat since can't say much useful about it */
+	printf(_("Database block size:                  %u\n"),
+		   ControlFile->blcksz);
+	printf(_("Blocks per segment of large relation: %u\n"),
+		   ControlFile->relseg_size);
+	printf(_("WAL block size:                       %u\n"),
+		   ControlFile->xlog_blcksz);
+	printf(_("Bytes per WAL segment:                %u\n"),
+		   ControlFile->xlog_seg_size);
+	printf(_("Maximum length of identifiers:        %u\n"),
+		   ControlFile->nameDataLen);
+	printf(_("Maximum columns in an index:          %u\n"),
+		   ControlFile->indexMaxKeys);
+	printf(_("Maximum size of a TOAST chunk:        %u\n"),
+		   ControlFile->toast_max_chunk_size);
+	printf(_("Size of a large-object chunk:         %u\n"),
+		   ControlFile->loblksize);
+	printf(_("Date/time type storage:               %s\n"),
+		   (ControlFile->enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
+	printf(_("Float4 argument passing:              %s\n"),
+		   (ControlFile->float4ByVal ? _("by value") : _("by reference")));
+	printf(_("Float8 argument passing:              %s\n"),
+		   (ControlFile->float8ByVal ? _("by value") : _("by reference")));
+	printf(_("Data page checksum version:           %u\n"),
+		   ControlFile->data_checksum_version);
+}
+
+/*
+ * Write out the new pg_control file.
+ */
+void
+RewriteControlFile(ControlFileData *ControlFile)
+{
+	int			fd;
+	char		buffer[PG_CONTROL_SIZE];		/* need not be aligned */
+
+	/*
+	 * Adjust fields as needed to force an empty XLOG starting at
+	 * redo.
+	 */
+	ControlFile->checkPointCopy.time = (pg_time_t) time(NULL);
+
+	ControlFile->state = DB_SHUTDOWNED;
+	ControlFile->time = (pg_time_t) time(NULL);
+	ControlFile->checkPoint = ControlFile->checkPointCopy.redo;
+	ControlFile->prevCheckPoint = 0;
+	ControlFile->minRecoveryPoint = 0;
+	ControlFile->minRecoveryPointTLI = 0;
+	ControlFile->backupStartPoint = 0;
+	ControlFile->backupEndPoint = 0;
+	ControlFile->backupEndRequired = false;
+
+	/*
+	 * Force the defaults for max_* settings. The values don't really matter
+	 * as long as wal_level='minimal'; the postmaster will reset these fields
+	 * anyway at startup.
+	 */
+	ControlFile->wal_level = WAL_LEVEL_MINIMAL;
+	ControlFile->wal_log_hints = false;
+	ControlFile->track_commit_timestamp = false;
+	ControlFile->MaxConnections = 100;
+	ControlFile->max_worker_processes = 8;
+	ControlFile->max_prepared_xacts = 0;
+	ControlFile->max_locks_per_xact = 64;
+
+	/* Now we can force the recorded xlog seg size to the right thing. */
+	ControlFile->xlog_seg_size = XLogSegSize;
+
+	/* Contents are protected with a CRC */
+	INIT_CRC32C(ControlFile->crc);
+	COMP_CRC32C(ControlFile->crc,
+				(char *) ControlFile,
+				offsetof(ControlFileData, crc));
+	FIN_CRC32C(ControlFile->crc);
+
+	/*
+	 * We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
+	 * excess over sizeof(ControlFileData).  This reduces the odds of
+	 * premature-EOF errors when reading pg_control.  We'll still fail when we
+	 * check the contents of the file, but hopefully with a more specific
+	 * error than "couldn't read pg_control".
+	 */
+	if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
+	{
+		fprintf(stderr,
+				_("%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n"),
+				progname);
+		exit(1);
+	}
+
+	memset(buffer, 0, PG_CONTROL_SIZE);
+	memcpy(buffer, &ControlFile, sizeof(ControlFileData));
+
+	unlink(XLOG_CONTROL_FILE);
+
+	fd = open(XLOG_CONTROL_FILE,
+			  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
+			  S_IRUSR | S_IWUSR);
+	if (fd < 0)
+	{
+		fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
+				progname, strerror(errno));
+		exit(1);
+	}
+
+	errno = 0;
+	if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
+	{
+		/* if write didn't set errno, assume problem is no disk space */
+		if (errno == 0)
+			errno = ENOSPC;
+		fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
+				progname, strerror(errno));
+		exit(1);
+	}
+
+	if (fsync(fd) != 0)
+	{
+		fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
+		exit(1);
+	}
+
+	close(fd);
+}
+
+
+/*
+ * Scan existing XLOG files and determine the highest existing WAL address
+ *
+ * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
+ * are assumed valid (note that we allow the old xlog seg size to differ
+ * from what we're using).  On exit, newXlogId and newXlogSeg are set to
+ * suitable values for the beginning of replacement WAL (in our seg size).
+ */
+XLogSegNo
+FindEndOfXLOG(ControlFileData *ControlFile)
+{
+	DIR		   *xldir;
+	struct dirent *xlde;
+	uint64		segs_per_xlogid;
+	uint64		xlogbytepos;
+	XLogSegNo	newXlogSegNo;
+
+	/*
+	 * Initialize the max() computation using the last checkpoint address from
+	 * old pg_control.  Note that for the moment we are working with segment
+	 * numbering according to the old xlog seg size.
+	 */
+	segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile->xlog_seg_size);
+	newXlogSegNo = ControlFile->checkPointCopy.redo / ControlFile->xlog_seg_size;
+
+	/*
+	 * Scan the pg_xlog directory to find existing WAL segment files. We
+	 * assume any present have been used; in most scenarios this should be
+	 * conservative, because of xlog.c's attempts to pre-create files.
+	 */
+	xldir = opendir(XLOGDIR);
+	if (xldir == NULL)
+	{
+		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	while (errno = 0, (xlde = readdir(xldir)) != NULL)
+	{
+		if (IsXLogFileName(xlde->d_name))
+		{
+			unsigned int tli,
+						log,
+						seg;
+			XLogSegNo	segno;
+
+			/*
+			 * Note: We don't use XLogFromFileName here, because we want to
+			 * use the segment size from the control file, not the size the
+			 * pg_resetxlog binary was compiled with
+			 */
+			sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
+			segno = ((uint64) log) * segs_per_xlogid + seg;
+
+			/*
+			 * Note: we take the max of all files found, regardless of their
+			 * timelines.  Another possibility would be to ignore files of
+			 * timelines other than the target TLI, but this seems safer.
+			 * Better too large a result than too small...
+			 */
+			if (segno > newXlogSegNo)
+				newXlogSegNo = segno;
+		}
+	}
+
+	if (errno)
+	{
+		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	if (closedir(xldir))
+	{
+		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	/*
+	 * Finally, convert to new xlog seg size, and advance by one to ensure we
+	 * are in virgin territory.
+	 */
+	xlogbytepos = newXlogSegNo * ControlFile->xlog_seg_size;
+	newXlogSegNo = (xlogbytepos + XLogSegSize - 1) / XLogSegSize;
+	newXlogSegNo++;
+
+	return newXlogSegNo;
+}
+
+
+/*
+ * Remove existing XLOG files
+ */
+void
+KillExistingXLOG(void)
+{
+	DIR		   *xldir;
+	struct dirent *xlde;
+	char		path[MAXPGPATH];
+
+	xldir = opendir(XLOGDIR);
+	if (xldir == NULL)
+	{
+		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	while (errno = 0, (xlde = readdir(xldir)) != NULL)
+	{
+		if (strlen(xlde->d_name) == 24 &&
+			strspn(xlde->d_name, "0123456789ABCDEF") == 24)
+		{
+			snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name);
+			if (unlink(path) < 0)
+			{
+				fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
+						progname, path, strerror(errno));
+				exit(1);
+			}
+		}
+	}
+
+	if (errno)
+	{
+		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+
+	if (closedir(xldir))
+	{
+		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
+				progname, XLOGDIR, strerror(errno));
+		exit(1);
+	}
+}
+
+
+/*
+ * Remove existing archive status files
+ */
+void
+KillExistingArchiveStatus(void)
+{
+	DIR		   *xldir;
+	struct dirent *xlde;
+	char		path[MAXPGPATH];
+
+#define ARCHSTATDIR XLOGDIR "/archive_status"
+
+	xldir = opendir(ARCHSTATDIR);
+	if (xldir == NULL)
+	{
+		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
+				progname, ARCHSTATDIR, strerror(errno));
+		exit(1);
+	}
+
+	while (errno = 0, (xlde = readdir(xldir)) != NULL)
+	{
+		if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
+			(strcmp(xlde->d_name + 24, ".ready") == 0 ||
+			 strcmp(xlde->d_name + 24, ".done") == 0))
+		{
+			snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name);
+			if (unlink(path) < 0)
+			{
+				fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
+						progname, path, strerror(errno));
+				exit(1);
+			}
+		}
+	}
+
+	if (errno)
+	{
+		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
+				progname, ARCHSTATDIR, strerror(errno));
+		exit(1);
+	}
+
+	if (closedir(xldir))
+	{
+		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
+				progname, ARCHSTATDIR, strerror(errno));
+		exit(1);
+	}
+}
+
+
+/*
+ * Write an empty XLOG file, containing only the checkpoint record
+ * already set up in ControlFile.
+ */
+void
+WriteEmptyXLOG(ControlFileData *ControlFile)
+{
+	char	   *buffer;
+	XLogPageHeader page;
+	XLogLongPageHeader longpage;
+	XLogRecord *record;
+	pg_crc32c	crc;
+	char		path[MAXPGPATH];
+	int			fd;
+	int			nbytes;
+	char	   *recptr;
+
+	/* Use malloc() to ensure buffer is MAXALIGNED */
+	buffer = (char *) pg_malloc(XLOG_BLCKSZ);
+	page = (XLogPageHeader) buffer;
+	memset(buffer, 0, XLOG_BLCKSZ);
+
+	/* Set up the XLOG page header */
+	page->xlp_magic = XLOG_PAGE_MAGIC;
+	page->xlp_info = XLP_LONG_HEADER;
+	page->xlp_tli = ControlFile->checkPointCopy.ThisTimeLineID;
+	page->xlp_pageaddr = ControlFile->checkPointCopy.redo - SizeOfXLogLongPHD;
+	longpage = (XLogLongPageHeader) page;
+	longpage->xlp_sysid = ControlFile->system_identifier;
+	longpage->xlp_seg_size = XLogSegSize;
+	longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
+
+	/* Insert the initial checkpoint record */
+	recptr = (char *) page + SizeOfXLogLongPHD;
+	record = (XLogRecord *) recptr;
+	record->xl_prev = 0;
+	record->xl_xid = InvalidTransactionId;
+	record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(CheckPoint);
+	record->xl_info = XLOG_CHECKPOINT_SHUTDOWN;
+	record->xl_rmid = RM_XLOG_ID;
+
+	recptr += SizeOfXLogRecord;
+	*(recptr++) = XLR_BLOCK_ID_DATA_SHORT;
+	*(recptr++) = sizeof(CheckPoint);
+	memcpy(recptr, &ControlFile->checkPointCopy,
+		   sizeof(CheckPoint));
+
+	INIT_CRC32C(crc);
+	COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
+	COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
+	FIN_CRC32C(crc);
+	record->xl_crc = crc;
+
+	/* Write the first page */
+	XLogFilePath(path, ControlFile->checkPointCopy.ThisTimeLineID,
+				 ControlFile->checkPointCopy.redo);
+
+	unlink(path);
+
+	fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
+			  S_IRUSR | S_IWUSR);
+	if (fd < 0)
+	{
+		fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
+				progname, path, strerror(errno));
+		exit(1);
+	}
+
+	errno = 0;
+	if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+	{
+		/* if write didn't set errno, assume problem is no disk space */
+		if (errno == 0)
+			errno = ENOSPC;
+		fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+				progname, path, strerror(errno));
+		exit(1);
+	}
+
+	/* Fill the rest of the file with zeroes */
+	memset(buffer, 0, XLOG_BLCKSZ);
+	for (nbytes = XLOG_BLCKSZ; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
+	{
+		errno = 0;
+		if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+		{
+			if (errno == 0)
+				errno = ENOSPC;
+			fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+					progname, path, strerror(errno));
+			exit(1);
+		}
+	}
+
+	if (fsync(fd) != 0)
+	{
+		fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
+		exit(1);
+	}
+
+	close(fd);
+}
diff --git a/src/bin/pg_resetxlog/common.h b/src/bin/pg_resetxlog/common.h
new file mode 100644
index 0000000..74fe987
--- /dev/null
+++ b/src/bin/pg_resetxlog/common.h
@@ -0,0 +1,30 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+/*
+ * We have to use postgres.h not postgres_fe.h here, because there's so much
+ * backend-only stuff in the XLOG include files we need.  But we need a
+ * frontend-ish environment otherwise.  Hence this ugly hack.
+ */
+#define FRONTEND 1
+
+#include "postgres.h"
+
+#include "access/xlog_internal.h"
+
+#include "catalog/pg_control.h"
+
+/* For error messaging */
+extern const char *progname;
+
+extern uint64 GenerateSystemIdentifier(void);
+extern bool ReadControlFile(ControlFileData *ControlFile, bool *guessed);
+extern void GuessControlValues(ControlFileData *ControlFile);
+extern void PrintControlValues(ControlFileData *ControlFile, bool guessed);
+extern void RewriteControlFile(ControlFileData *ControlFile);
+extern XLogSegNo FindEndOfXLOG(ControlFileData *ControlFile);
+extern void KillExistingXLOG(void);
+extern void KillExistingArchiveStatus(void);
+extern void WriteEmptyXLOG(ControlFileData *ControlFile);
+
+#endif   /* COMMON_H */
diff --git a/src/bin/pg_resetxlog/nls.mk b/src/bin/pg_resetxlog/nls.mk
index cde0ed4..b753ace 100644
--- a/src/bin/pg_resetxlog/nls.mk
+++ b/src/bin/pg_resetxlog/nls.mk
@@ -1,4 +1,4 @@
 # src/bin/pg_resetxlog/nls.mk
 CATALOG_NAME     = pg_resetxlog
 AVAIL_LANGUAGES  = cs de es fr it ja pl pt_BR ru sv zh_CN
-GETTEXT_FILES    = pg_resetxlog.c ../../common/restricted_token.c
+GETTEXT_FILES    = common.c pg_resetxlog.c ../../common/restricted_token.c
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 6ffe795..2c061fa 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -28,14 +28,7 @@
  *-------------------------------------------------------------------------
  */
 
-/*
- * We have to use postgres.h not postgres_fe.h here, because there's so much
- * backend-only stuff in the XLOG include files we need.  But we need a
- * frontend-ish environment otherwise.  Hence this ugly hack.
- */
-#define FRONTEND 1
-
-#include "postgres.h"
+#include "common.h"
 
 #include <dirent.h>
 #include <fcntl.h>
@@ -48,10 +41,7 @@
 #include "access/transam.h"
 #include "access/tuptoaster.h"
 #include "access/multixact.h"
-#include "access/xlog.h"
-#include "access/xlog_internal.h"
 #include "catalog/catversion.h"
-#include "catalog/pg_control.h"
 #include "common/fe_memutils.h"
 #include "common/restricted_token.h"
 #include "storage/large_object.h"
@@ -60,10 +50,10 @@
 #include "replication/origin.h"
 
 
+const char *progname;
 static ControlFileData ControlFile;		/* pg_control values */
 static XLogSegNo newXlogSegNo;	/* new XLOG segment # */
 static bool guessed = false;	/* T if we had to guess at any values */
-static const char *progname;
 static uint32 set_xid_epoch = (uint32) -1;
 static TransactionId set_xid = 0;
 static TransactionId set_oldest_commit_ts = 0;
@@ -74,15 +64,7 @@ static MultiXactOffset set_mxoff = (MultiXactOffset) -1;
 static uint32 minXlogTli = 0;
 static XLogSegNo minXlogSegNo = 0;
 
-static bool ReadControlFile(void);
-static void GuessControlValues(void);
-static void PrintControlValues(bool guessed);
 static void PrintNewControlValues(void);
-static void RewriteControlFile(void);
-static void FindEndOfXLOG(void);
-static void KillExistingXLOG(void);
-static void KillExistingArchiveStatus(void);
-static void WriteEmptyXLOG(void);
 static void usage(void);
 
 
@@ -346,20 +328,20 @@ main(int argc, char *argv[])
 	/*
 	 * Attempt to read the existing pg_control file
 	 */
-	if (!ReadControlFile())
-		GuessControlValues();
+	if (!ReadControlFile(&ControlFile, &guessed))
+		GuessControlValues(&ControlFile);
 
 	/*
 	 * Also look at existing segment files to set up newXlogSegNo
 	 */
-	FindEndOfXLOG();
+	newXlogSegNo = FindEndOfXLOG(&ControlFile);
 
 	/*
 	 * If we're not going to proceed with the reset, print the current control
 	 * file parameters.
 	 */
 	if ((guessed && !force) || noupdate)
-		PrintControlValues(guessed);
+		PrintControlValues(&ControlFile, guessed);
 
 	/*
 	 * Adjust fields if required by switches.  (Do this now so that printout,
@@ -445,10 +427,12 @@ main(int argc, char *argv[])
 	/*
 	 * Else, do the dirty deed.
 	 */
-	RewriteControlFile();
+	XLogSegNoOffsetToRecPtr(newXlogSegNo, SizeOfXLogLongPHD,
+							ControlFile.checkPointCopy.redo);
+	RewriteControlFile(&ControlFile);
 	KillExistingXLOG();
 	KillExistingArchiveStatus();
-	WriteEmptyXLOG();
+	WriteEmptyXLOG(&ControlFile);
 
 	printf(_("Transaction log reset\n"));
 	return 0;
@@ -456,252 +440,6 @@ main(int argc, char *argv[])
 
 
 /*
- * Try to read the existing pg_control file.
- *
- * This routine is also responsible for updating old pg_control versions
- * to the current format.  (Currently we don't do anything of the sort.)
- */
-static bool
-ReadControlFile(void)
-{
-	int			fd;
-	int			len;
-	char	   *buffer;
-	pg_crc32c	crc;
-
-	if ((fd = open(XLOG_CONTROL_FILE, O_RDONLY | PG_BINARY, 0)) < 0)
-	{
-		/*
-		 * If pg_control is not there at all, or we can't read it, the odds
-		 * are we've been handed a bad DataDir path, so give up. User can do
-		 * "touch pg_control" to force us to proceed.
-		 */
-		fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
-				progname, XLOG_CONTROL_FILE, strerror(errno));
-		if (errno == ENOENT)
-			fprintf(stderr, _("If you are sure the data directory path is correct, execute\n"
-							  "  touch %s\n"
-							  "and try again.\n"),
-					XLOG_CONTROL_FILE);
-		exit(1);
-	}
-
-	/* Use malloc to ensure we have a maxaligned buffer */
-	buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
-
-	len = read(fd, buffer, PG_CONTROL_SIZE);
-	if (len < 0)
-	{
-		fprintf(stderr, _("%s: could not read file \"%s\": %s\n"),
-				progname, XLOG_CONTROL_FILE, strerror(errno));
-		exit(1);
-	}
-	close(fd);
-
-	if (len >= sizeof(ControlFileData) &&
-	  ((ControlFileData *) buffer)->pg_control_version == PG_CONTROL_VERSION)
-	{
-		/* Check the CRC. */
-		INIT_CRC32C(crc);
-		COMP_CRC32C(crc,
-					buffer,
-					offsetof(ControlFileData, crc));
-		FIN_CRC32C(crc);
-
-		if (EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
-		{
-			/* Valid data... */
-			memcpy(&ControlFile, buffer, sizeof(ControlFile));
-			return true;
-		}
-
-		fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
-				progname);
-		/* We will use the data anyway, but treat it as guessed. */
-		memcpy(&ControlFile, buffer, sizeof(ControlFile));
-		guessed = true;
-		return true;
-	}
-
-	/* Looks like it's a mess. */
-	fprintf(stderr, _("%s: pg_control exists but is broken or unknown version; ignoring it\n"),
-			progname);
-	return false;
-}
-
-
-/*
- * Guess at pg_control values when we can't read the old ones.
- */
-static void
-GuessControlValues(void)
-{
-	uint64		sysidentifier;
-	struct timeval tv;
-
-	/*
-	 * Set up a completely default set of pg_control values.
-	 */
-	guessed = true;
-	memset(&ControlFile, 0, sizeof(ControlFile));
-
-	ControlFile.pg_control_version = PG_CONTROL_VERSION;
-	ControlFile.catalog_version_no = CATALOG_VERSION_NO;
-
-	/*
-	 * Create a new unique installation identifier, since we can no longer use
-	 * any old XLOG records.  See notes in xlog.c about the algorithm.
-	 */
-	gettimeofday(&tv, NULL);
-	sysidentifier = ((uint64) tv.tv_sec) << 32;
-	sysidentifier |= ((uint64) tv.tv_usec) << 12;
-	sysidentifier |= getpid() & 0xFFF;
-
-	ControlFile.system_identifier = sysidentifier;
-
-	ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
-	ControlFile.checkPointCopy.ThisTimeLineID = 1;
-	ControlFile.checkPointCopy.PrevTimeLineID = 1;
-	ControlFile.checkPointCopy.fullPageWrites = false;
-	ControlFile.checkPointCopy.nextXidEpoch = 0;
-	ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
-	ControlFile.checkPointCopy.nextOid = FirstBootstrapObjectId;
-	ControlFile.checkPointCopy.nextMulti = FirstMultiXactId;
-	ControlFile.checkPointCopy.nextMultiOffset = 0;
-	ControlFile.checkPointCopy.oldestXid = FirstNormalTransactionId;
-	ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
-	ControlFile.checkPointCopy.oldestMulti = FirstMultiXactId;
-	ControlFile.checkPointCopy.oldestMultiDB = InvalidOid;
-	ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
-	ControlFile.checkPointCopy.oldestActiveXid = InvalidTransactionId;
-
-	ControlFile.state = DB_SHUTDOWNED;
-	ControlFile.time = (pg_time_t) time(NULL);
-	ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
-	ControlFile.unloggedLSN = 1;
-
-	/* minRecoveryPoint, backupStartPoint and backupEndPoint can be left zero */
-
-	ControlFile.wal_level = WAL_LEVEL_MINIMAL;
-	ControlFile.wal_log_hints = false;
-	ControlFile.track_commit_timestamp = false;
-	ControlFile.MaxConnections = 100;
-	ControlFile.max_worker_processes = 8;
-	ControlFile.max_prepared_xacts = 0;
-	ControlFile.max_locks_per_xact = 64;
-
-	ControlFile.maxAlign = MAXIMUM_ALIGNOF;
-	ControlFile.floatFormat = FLOATFORMAT_VALUE;
-	ControlFile.blcksz = BLCKSZ;
-	ControlFile.relseg_size = RELSEG_SIZE;
-	ControlFile.xlog_blcksz = XLOG_BLCKSZ;
-	ControlFile.xlog_seg_size = XLOG_SEG_SIZE;
-	ControlFile.nameDataLen = NAMEDATALEN;
-	ControlFile.indexMaxKeys = INDEX_MAX_KEYS;
-	ControlFile.toast_max_chunk_size = TOAST_MAX_CHUNK_SIZE;
-	ControlFile.loblksize = LOBLKSIZE;
-#ifdef HAVE_INT64_TIMESTAMP
-	ControlFile.enableIntTimes = true;
-#else
-	ControlFile.enableIntTimes = false;
-#endif
-	ControlFile.float4ByVal = FLOAT4PASSBYVAL;
-	ControlFile.float8ByVal = FLOAT8PASSBYVAL;
-
-	/*
-	 * XXX eventually, should try to grovel through old XLOG to develop more
-	 * accurate values for TimeLineID, nextXID, etc.
-	 */
-}
-
-
-/*
- * Print the guessed pg_control values when we had to guess.
- *
- * NB: this display should be just those fields that will not be
- * reset by RewriteControlFile().
- */
-static void
-PrintControlValues(bool guessed)
-{
-	char		sysident_str[32];
-
-	if (guessed)
-		printf(_("Guessed pg_control values:\n\n"));
-	else
-		printf(_("Current pg_control values:\n\n"));
-
-	/*
-	 * Format system_identifier separately to keep platform-dependent format
-	 * code out of the translatable message string.
-	 */
-	snprintf(sysident_str, sizeof(sysident_str), UINT64_FORMAT,
-			 ControlFile.system_identifier);
-
-	printf(_("pg_control version number:            %u\n"),
-		   ControlFile.pg_control_version);
-	printf(_("Catalog version number:               %u\n"),
-		   ControlFile.catalog_version_no);
-	printf(_("Database system identifier:           %s\n"),
-		   sysident_str);
-	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
-		   ControlFile.checkPointCopy.ThisTimeLineID);
-	printf(_("Latest checkpoint's full_page_writes: %s\n"),
-		   ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
-	printf(_("Latest checkpoint's NextXID:          %u/%u\n"),
-		   ControlFile.checkPointCopy.nextXidEpoch,
-		   ControlFile.checkPointCopy.nextXid);
-	printf(_("Latest checkpoint's NextOID:          %u\n"),
-		   ControlFile.checkPointCopy.nextOid);
-	printf(_("Latest checkpoint's NextMultiXactId:  %u\n"),
-		   ControlFile.checkPointCopy.nextMulti);
-	printf(_("Latest checkpoint's NextMultiOffset:  %u\n"),
-		   ControlFile.checkPointCopy.nextMultiOffset);
-	printf(_("Latest checkpoint's oldestXID:        %u\n"),
-		   ControlFile.checkPointCopy.oldestXid);
-	printf(_("Latest checkpoint's oldestXID's DB:   %u\n"),
-		   ControlFile.checkPointCopy.oldestXidDB);
-	printf(_("Latest checkpoint's oldestActiveXID:  %u\n"),
-		   ControlFile.checkPointCopy.oldestActiveXid);
-	printf(_("Latest checkpoint's oldestMultiXid:   %u\n"),
-		   ControlFile.checkPointCopy.oldestMulti);
-	printf(_("Latest checkpoint's oldestMulti's DB: %u\n"),
-		   ControlFile.checkPointCopy.oldestMultiDB);
-	printf(_("Latest checkpoint's oldest CommitTs:  %u\n"),
-		   ControlFile.checkPointCopy.oldestCommitTs);
-	printf(_("Latest checkpoint's newest CommitTs:  %u\n"),
-		   ControlFile.checkPointCopy.newestCommitTs);
-	printf(_("Maximum data alignment:               %u\n"),
-		   ControlFile.maxAlign);
-	/* we don't print floatFormat since can't say much useful about it */
-	printf(_("Database block size:                  %u\n"),
-		   ControlFile.blcksz);
-	printf(_("Blocks per segment of large relation: %u\n"),
-		   ControlFile.relseg_size);
-	printf(_("WAL block size:                       %u\n"),
-		   ControlFile.xlog_blcksz);
-	printf(_("Bytes per WAL segment:                %u\n"),
-		   ControlFile.xlog_seg_size);
-	printf(_("Maximum length of identifiers:        %u\n"),
-		   ControlFile.nameDataLen);
-	printf(_("Maximum columns in an index:          %u\n"),
-		   ControlFile.indexMaxKeys);
-	printf(_("Maximum size of a TOAST chunk:        %u\n"),
-		   ControlFile.toast_max_chunk_size);
-	printf(_("Size of a large-object chunk:         %u\n"),
-		   ControlFile.loblksize);
-	printf(_("Date/time type storage:               %s\n"),
-		   (ControlFile.enableIntTimes ? _("64-bit integers") : _("floating-point numbers")));
-	printf(_("Float4 argument passing:              %s\n"),
-		   (ControlFile.float4ByVal ? _("by value") : _("by reference")));
-	printf(_("Float8 argument passing:              %s\n"),
-		   (ControlFile.float8ByVal ? _("by value") : _("by reference")));
-	printf(_("Data page checksum version:           %u\n"),
-		   ControlFile.data_checksum_version);
-}
-
-
-/*
  * Print the values to be changed.
  */
 static void
@@ -766,400 +504,6 @@ PrintNewControlValues()
 }
 
 
-/*
- * Write out the new pg_control file.
- */
-static void
-RewriteControlFile(void)
-{
-	int			fd;
-	char		buffer[PG_CONTROL_SIZE];		/* need not be aligned */
-
-	/*
-	 * Adjust fields as needed to force an empty XLOG starting at
-	 * newXlogSegNo.
-	 */
-	XLogSegNoOffsetToRecPtr(newXlogSegNo, SizeOfXLogLongPHD,
-							ControlFile.checkPointCopy.redo);
-	ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
-
-	ControlFile.state = DB_SHUTDOWNED;
-	ControlFile.time = (pg_time_t) time(NULL);
-	ControlFile.checkPoint = ControlFile.checkPointCopy.redo;
-	ControlFile.prevCheckPoint = 0;
-	ControlFile.minRecoveryPoint = 0;
-	ControlFile.minRecoveryPointTLI = 0;
-	ControlFile.backupStartPoint = 0;
-	ControlFile.backupEndPoint = 0;
-	ControlFile.backupEndRequired = false;
-
-	/*
-	 * Force the defaults for max_* settings. The values don't really matter
-	 * as long as wal_level='minimal'; the postmaster will reset these fields
-	 * anyway at startup.
-	 */
-	ControlFile.wal_level = WAL_LEVEL_MINIMAL;
-	ControlFile.wal_log_hints = false;
-	ControlFile.track_commit_timestamp = false;
-	ControlFile.MaxConnections = 100;
-	ControlFile.max_worker_processes = 8;
-	ControlFile.max_prepared_xacts = 0;
-	ControlFile.max_locks_per_xact = 64;
-
-	/* Now we can force the recorded xlog seg size to the right thing. */
-	ControlFile.xlog_seg_size = XLogSegSize;
-
-	/* Contents are protected with a CRC */
-	INIT_CRC32C(ControlFile.crc);
-	COMP_CRC32C(ControlFile.crc,
-				(char *) &ControlFile,
-				offsetof(ControlFileData, crc));
-	FIN_CRC32C(ControlFile.crc);
-
-	/*
-	 * We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
-	 * excess over sizeof(ControlFileData).  This reduces the odds of
-	 * premature-EOF errors when reading pg_control.  We'll still fail when we
-	 * check the contents of the file, but hopefully with a more specific
-	 * error than "couldn't read pg_control".
-	 */
-	if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
-	{
-		fprintf(stderr,
-				_("%s: internal error -- sizeof(ControlFileData) is too large ... fix PG_CONTROL_SIZE\n"),
-				progname);
-		exit(1);
-	}
-
-	memset(buffer, 0, PG_CONTROL_SIZE);
-	memcpy(buffer, &ControlFile, sizeof(ControlFileData));
-
-	unlink(XLOG_CONTROL_FILE);
-
-	fd = open(XLOG_CONTROL_FILE,
-			  O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-			  S_IRUSR | S_IWUSR);
-	if (fd < 0)
-	{
-		fprintf(stderr, _("%s: could not create pg_control file: %s\n"),
-				progname, strerror(errno));
-		exit(1);
-	}
-
-	errno = 0;
-	if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		fprintf(stderr, _("%s: could not write pg_control file: %s\n"),
-				progname, strerror(errno));
-		exit(1);
-	}
-
-	if (fsync(fd) != 0)
-	{
-		fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
-		exit(1);
-	}
-
-	close(fd);
-}
-
-
-/*
- * Scan existing XLOG files and determine the highest existing WAL address
- *
- * On entry, ControlFile.checkPointCopy.redo and ControlFile.xlog_seg_size
- * are assumed valid (note that we allow the old xlog seg size to differ
- * from what we're using).  On exit, newXlogId and newXlogSeg are set to
- * suitable values for the beginning of replacement WAL (in our seg size).
- */
-static void
-FindEndOfXLOG(void)
-{
-	DIR		   *xldir;
-	struct dirent *xlde;
-	uint64		segs_per_xlogid;
-	uint64		xlogbytepos;
-
-	/*
-	 * Initialize the max() computation using the last checkpoint address from
-	 * old pg_control.  Note that for the moment we are working with segment
-	 * numbering according to the old xlog seg size.
-	 */
-	segs_per_xlogid = (UINT64CONST(0x0000000100000000) / ControlFile.xlog_seg_size);
-	newXlogSegNo = ControlFile.checkPointCopy.redo / ControlFile.xlog_seg_size;
-
-	/*
-	 * Scan the pg_xlog directory to find existing WAL segment files. We
-	 * assume any present have been used; in most scenarios this should be
-	 * conservative, because of xlog.c's attempts to pre-create files.
-	 */
-	xldir = opendir(XLOGDIR);
-	if (xldir == NULL)
-	{
-		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-
-	while (errno = 0, (xlde = readdir(xldir)) != NULL)
-	{
-		if (IsXLogFileName(xlde->d_name))
-		{
-			unsigned int tli,
-						log,
-						seg;
-			XLogSegNo	segno;
-
-			/*
-			 * Note: We don't use XLogFromFileName here, because we want to
-			 * use the segment size from the control file, not the size the
-			 * pg_resetxlog binary was compiled with
-			 */
-			sscanf(xlde->d_name, "%08X%08X%08X", &tli, &log, &seg);
-			segno = ((uint64) log) * segs_per_xlogid + seg;
-
-			/*
-			 * Note: we take the max of all files found, regardless of their
-			 * timelines.  Another possibility would be to ignore files of
-			 * timelines other than the target TLI, but this seems safer.
-			 * Better too large a result than too small...
-			 */
-			if (segno > newXlogSegNo)
-				newXlogSegNo = segno;
-		}
-	}
-
-	if (errno)
-	{
-		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-
-	if (closedir(xldir))
-	{
-		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-
-	/*
-	 * Finally, convert to new xlog seg size, and advance by one to ensure we
-	 * are in virgin territory.
-	 */
-	xlogbytepos = newXlogSegNo * ControlFile.xlog_seg_size;
-	newXlogSegNo = (xlogbytepos + XLogSegSize - 1) / XLogSegSize;
-	newXlogSegNo++;
-}
-
-
-/*
- * Remove existing XLOG files
- */
-static void
-KillExistingXLOG(void)
-{
-	DIR		   *xldir;
-	struct dirent *xlde;
-	char		path[MAXPGPATH];
-
-	xldir = opendir(XLOGDIR);
-	if (xldir == NULL)
-	{
-		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-
-	while (errno = 0, (xlde = readdir(xldir)) != NULL)
-	{
-		if (strlen(xlde->d_name) == 24 &&
-			strspn(xlde->d_name, "0123456789ABCDEF") == 24)
-		{
-			snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name);
-			if (unlink(path) < 0)
-			{
-				fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
-						progname, path, strerror(errno));
-				exit(1);
-			}
-		}
-	}
-
-	if (errno)
-	{
-		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-
-	if (closedir(xldir))
-	{
-		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
-				progname, XLOGDIR, strerror(errno));
-		exit(1);
-	}
-}
-
-
-/*
- * Remove existing archive status files
- */
-static void
-KillExistingArchiveStatus(void)
-{
-	DIR		   *xldir;
-	struct dirent *xlde;
-	char		path[MAXPGPATH];
-
-#define ARCHSTATDIR XLOGDIR "/archive_status"
-
-	xldir = opendir(ARCHSTATDIR);
-	if (xldir == NULL)
-	{
-		fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
-				progname, ARCHSTATDIR, strerror(errno));
-		exit(1);
-	}
-
-	while (errno = 0, (xlde = readdir(xldir)) != NULL)
-	{
-		if (strspn(xlde->d_name, "0123456789ABCDEF") == 24 &&
-			(strcmp(xlde->d_name + 24, ".ready") == 0 ||
-			 strcmp(xlde->d_name + 24, ".done") == 0))
-		{
-			snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name);
-			if (unlink(path) < 0)
-			{
-				fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"),
-						progname, path, strerror(errno));
-				exit(1);
-			}
-		}
-	}
-
-	if (errno)
-	{
-		fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
-				progname, ARCHSTATDIR, strerror(errno));
-		exit(1);
-	}
-
-	if (closedir(xldir))
-	{
-		fprintf(stderr, _("%s: could not close directory \"%s\": %s\n"),
-				progname, ARCHSTATDIR, strerror(errno));
-		exit(1);
-	}
-}
-
-
-/*
- * Write an empty XLOG file, containing only the checkpoint record
- * already set up in ControlFile.
- */
-static void
-WriteEmptyXLOG(void)
-{
-	char	   *buffer;
-	XLogPageHeader page;
-	XLogLongPageHeader longpage;
-	XLogRecord *record;
-	pg_crc32c	crc;
-	char		path[MAXPGPATH];
-	int			fd;
-	int			nbytes;
-	char	   *recptr;
-
-	/* Use malloc() to ensure buffer is MAXALIGNED */
-	buffer = (char *) pg_malloc(XLOG_BLCKSZ);
-	page = (XLogPageHeader) buffer;
-	memset(buffer, 0, XLOG_BLCKSZ);
-
-	/* Set up the XLOG page header */
-	page->xlp_magic = XLOG_PAGE_MAGIC;
-	page->xlp_info = XLP_LONG_HEADER;
-	page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
-	page->xlp_pageaddr = ControlFile.checkPointCopy.redo - SizeOfXLogLongPHD;
-	longpage = (XLogLongPageHeader) page;
-	longpage->xlp_sysid = ControlFile.system_identifier;
-	longpage->xlp_seg_size = XLogSegSize;
-	longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
-
-	/* Insert the initial checkpoint record */
-	recptr = (char *) page + SizeOfXLogLongPHD;
-	record = (XLogRecord *) recptr;
-	record->xl_prev = 0;
-	record->xl_xid = InvalidTransactionId;
-	record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(CheckPoint);
-	record->xl_info = XLOG_CHECKPOINT_SHUTDOWN;
-	record->xl_rmid = RM_XLOG_ID;
-
-	recptr += SizeOfXLogRecord;
-	*(recptr++) = XLR_BLOCK_ID_DATA_SHORT;
-	*(recptr++) = sizeof(CheckPoint);
-	memcpy(recptr, &ControlFile.checkPointCopy,
-		   sizeof(CheckPoint));
-
-	INIT_CRC32C(crc);
-	COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
-	COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
-	FIN_CRC32C(crc);
-	record->xl_crc = crc;
-
-	/* Write the first page */
-	XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID, newXlogSegNo);
-
-	unlink(path);
-
-	fd = open(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
-			  S_IRUSR | S_IWUSR);
-	if (fd < 0)
-	{
-		fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
-				progname, path, strerror(errno));
-		exit(1);
-	}
-
-	errno = 0;
-	if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
-				progname, path, strerror(errno));
-		exit(1);
-	}
-
-	/* Fill the rest of the file with zeroes */
-	memset(buffer, 0, XLOG_BLCKSZ);
-	for (nbytes = XLOG_BLCKSZ; nbytes < XLogSegSize; nbytes += XLOG_BLCKSZ)
-	{
-		errno = 0;
-		if (write(fd, buffer, XLOG_BLCKSZ) != XLOG_BLCKSZ)
-		{
-			if (errno == 0)
-				errno = ENOSPC;
-			fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
-					progname, path, strerror(errno));
-			exit(1);
-		}
-	}
-
-	if (fsync(fd) != 0)
-	{
-		fprintf(stderr, _("%s: fsync error: %s\n"), progname, strerror(errno));
-		exit(1);
-	}
-
-	close(fd);
-}
-
-
 static void
 usage(void)
 {
-- 
1.9.1

