diff --git a/contrib/README b/contrib/README
index 1988c068abe6e0849dd633b609b52cce22f139e2..79d95b2e3e18daa90c653289b88da25b481c3270 100644
--- a/contrib/README
+++ b/contrib/README
@@ -85,6 +85,10 @@ oid2name -
 	maps numeric files to table names
 	by B Palmer <bpalmer@crimelabs.net>
 
+pg_controldata -
+	Dump internal database site structures
+	by Oliver Elphick <olly@lfix.co.uk>
+
 pg_dumplo -
 	Dump large objects
 	by Karel Zak <zakkr@zf.jcu.cz>
diff --git a/contrib/pg_controldata/Makefile b/contrib/pg_controldata/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..fde5ab1e73be7d18dfba212e381d263fc567441b
--- /dev/null
+++ b/contrib/pg_controldata/Makefile
@@ -0,0 +1,36 @@
+#
+# $Header: /cvsroot/pgsql/contrib/pg_controldata/Attic/Makefile,v 1.1 2001/02/23 20:38:35 momjian Exp $
+#
+
+subdir = contrib/pg_controldata
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
+
+OBJS	= pg_controldata.o
+
+all: pg_controldata
+
+pg_controldata: $(OBJS) $(libpq_builddir)/libpq.a
+	$(CC) $(CFLAGS) $(OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@
+
+install: all installdirs
+	$(INSTALL_PROGRAM) pg_controldata$(X)	$(bindir)
+	$(INSTALL_DATA) README.pg_controldata	$(docdir)/contrib
+
+installdirs:
+	$(mkinstalldirs) $(bindir) $(docdir)/contrib
+
+uninstall:
+	rm -f $(bindir)/pg_controldata$(X) $(docdir)/contrib/README.pg_controldata
+
+clean distclean maintainer-clean:
+	rm -f pg_controldata$(X) $(OBJS)
+
+depend dep:
+	$(CC) -MM -MG $(CFLAGS) *.c > depend
+
+ifeq (depend,$(wildcard depend))
+include depend
+endif
diff --git a/contrib/pg_controldata/README.pg_controldata b/contrib/pg_controldata/README.pg_controldata
new file mode 100644
index 0000000000000000000000000000000000000000..e1c4192cfea90f01f627b9a63dfbbe4d5775edea
--- /dev/null
+++ b/contrib/pg_controldata/README.pg_controldata
@@ -0,0 +1,19 @@
+I had a need to read such things as the backend locale and the catalog
+version number from the current database, and couldn't find any existing
+program to do that.
+
+The attached utility produces this output:
+
+linda:~$ pg_controldata
+Log file id:                          0
+Log file segment:                     5
+Last modified:                        Wed Feb  7 19:35:47 2001
+Database block size:                  8192
+Blocks per segment of large relation: 131072
+Catalog version number:               200101061
+LC_COLLATE:                           en_GB
+LC_CTYPE:                             en_GB
+Log archive directory:                
+
+--
+Oliver Elphick                 <olly@lfix.co.uk>
diff --git a/contrib/pg_controldata/pg_controldata b/contrib/pg_controldata/pg_controldata
new file mode 100755
index 0000000000000000000000000000000000000000..59f2e4d14d0b877646722b816dbfb54fd0d1815a
Binary files /dev/null and b/contrib/pg_controldata/pg_controldata differ
diff --git a/contrib/pg_controldata/pg_controldata.c b/contrib/pg_controldata/pg_controldata.c
new file mode 100644
index 0000000000000000000000000000000000000000..9cd148f6f4863e2ff29f4fdc971ab8c0499da5aa
--- /dev/null
+++ b/contrib/pg_controldata/pg_controldata.c
@@ -0,0 +1,123 @@
+/* pg_controldata
+ *
+ * reads the data from $PGDATA/global/pg_control
+ *
+ * copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
+ * licence: BSD
+ *
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+typedef unsigned int uint32;
+
+#include "config.h"
+#include "access/xlogdefs.h"
+
+/*
+ * #include "access/xlog.h"
+ * #include "c.h"
+ */
+
+/* The following definitions are extracted from access/xlog.h and its
+ * recursive includes. There is too much initialisation needed if
+ * they are included direct. Perhaps someone more knowledgeable can
+ * fix that.
+ */
+typedef struct crc64
+{
+	uint32      crc1;
+	uint32      crc2;
+} crc64;
+
+#define LOCALE_NAME_BUFLEN  128
+
+typedef enum DBState
+{
+	DB_STARTUP = 0,
+	DB_SHUTDOWNED,
+	DB_SHUTDOWNING,
+	DB_IN_RECOVERY,
+	DB_IN_PRODUCTION
+} DBState;
+
+
+typedef struct ControlFileData
+{
+   crc64    crc;
+   uint32      logId;         /* current log file id */
+   uint32      logSeg;        /* current log file segment (1-based) */
+   struct 
+	XLogRecPtr	checkPoint;    /* last check point record ptr */
+   time_t      time;       /* time stamp of last modification */
+   DBState     state;         /* see enum above */
+
+   /*
+    * this data is used to make sure that configuration of this DB is
+    * compatible with the backend executable
+    */
+   uint32      blcksz;        /* block size for this DB */
+   uint32      relseg_size;   /* blocks per segment of large relation */
+   uint32      catalog_version_no;     /* internal version number */
+   /* active locales --- "C" if compiled without USE_LOCALE: */
+   char     lc_collate[LOCALE_NAME_BUFLEN];
+   char     lc_ctype[LOCALE_NAME_BUFLEN];
+
+   /*
+    * important directory locations
+    */
+   char     archdir[MAXPGPATH];     /* where to move offline log files */
+} ControlFileData;
+
+int main() {
+	ControlFileData ControlFile;
+	int fd;
+	char ControlFilePath[MAXPGPATH];
+	char *DataDir;
+	char tmdt[32];
+
+	DataDir = getenv("PGDATA");
+	if ( DataDir == NULL ) {
+		fprintf(stderr,"PGDATA is not defined\n");
+		exit(1);
+	}
+
+	snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
+
+	if ((fd = open(ControlFilePath, O_RDONLY)) == -1) {
+		perror("Failed to open $PGDATA/global/pg_control for reading");
+		exit(2);
+	}
+
+	read(fd, &ControlFile, sizeof(ControlFileData));
+	strftime(tmdt, 32, "%c", localtime(&(ControlFile.time)));
+
+	printf("Log file id:                          %u\n"
+	       "Log file segment:                     %u\n"
+			 "Last modified:                        %s\n"
+			 "Database block size:                  %u\n"
+			 "Blocks per segment of large relation: %u\n"
+			 "Catalog version number:               %u\n"
+			 "LC_COLLATE:                           %s\n"
+			 "LC_CTYPE:                             %s\n"
+			 "Log archive directory:                %s\n",
+			 ControlFile.logId,
+			 ControlFile.logSeg,
+			 tmdt,
+			 ControlFile.blcksz,
+			 ControlFile.relseg_size,
+			 ControlFile.catalog_version_no,
+			 ControlFile.lc_collate,
+			 ControlFile.lc_ctype,
+			 ControlFile.archdir);
+	
+	return (0);
+}
+
diff --git a/contrib/pg_controldata/pg_controldata.o b/contrib/pg_controldata/pg_controldata.o
new file mode 100644
index 0000000000000000000000000000000000000000..fd6b532b940f4cd363d9733eb1aac48e0702a0b5
Binary files /dev/null and b/contrib/pg_controldata/pg_controldata.o differ