From c673efa07f290f9781af3b0ba1399534da762b66 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@enterprisedb.com>
Date: Tue, 5 Dec 2017 17:14:51 +1300
Subject: [PATCH 1/5] Add defenses against pre-crash files to
 BufFileOpenShared().

Crash restarts currently don't clean up temporary files, as a debugging aid.
If a left-over file happens to have the same name as a segment file we're
trying to create, we'll just truncate and reuse it, but there is a problem:
BufFileOpenShared() determines how many segment files exist by trying to open
.0, .1, .2, ... until it finds no more files.  It might be confused by a junk
file that has the next segment number.  To defend against that, make sure we
always create a gap after the end file by unlinking the following name if it
exists.  Also make it an error to try to open a BufFile that doesn't exist
(has no segment 0), so as not to encourage the development of client code
that depends on an interface that we can't reliably provide.

Author: Thomas Munro
Reviewed-By: Andres Freund
Discussion: https://postgr.es/m/CAEepm%3D2jhCbC_GFQJaaDhWxLB4EXtT3vVd5czuRNaqF5CWSTog%40mail.gmail.com
---
 src/backend/storage/file/buffile.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index fa9940da9b3..c6b210d1379 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -211,6 +211,16 @@ MakeNewSharedSegment(BufFile *buffile, int segment)
 	char		name[MAXPGPATH];
 	File		file;
 
+	/*
+	 * It is possible that there are files left over from before a crash
+	 * restart with the same name.  In order for BufFileOpenShared()
+	 * not to get confused about how many segments there are, we'll unlink
+	 * the next segment number if it already exists.
+	 */
+	SharedSegmentName(name, buffile->name, segment + 1);
+	SharedFileSetDelete(buffile->fileset, name, true);
+
+	/* Create the new segment. */
 	SharedSegmentName(name, buffile->name, segment);
 	file = SharedFileSetCreate(buffile->fileset, name);
 
@@ -303,7 +313,9 @@ BufFileOpenShared(SharedFileSet *fileset, const char *name)
 	 * name.
 	 */
 	if (nfiles == 0)
-		return NULL;
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not open BufFile \"%s\"", name)));
 
 	file->numFiles = nfiles;
 	file->files = files;
-- 
2.15.0

