From 0857703de891ccd1ffb8c96ab35ae5e90929ddb4 Mon Sep 17 00:00:00 2001
From: Thomas Munro <tmunro@postgresql.org>
Date: Mon, 30 Nov 2020 18:32:32 +1300
Subject: [PATCH 2/2] Use truncate(2) instead of open+ftruncate+close.

When truncating files, use POSIX truncate(2).  Windows doesn't have
that, so provide a fallback.

Discussion: https://postgr.es/m/16663-fe97ccf9932fc800%40postgresql.org
---
 src/backend/storage/file/fd.c | 27 +++++++++++++++++++++++++++
 src/backend/storage/smgr/md.c | 13 +------------
 src/include/storage/fd.h      |  1 +
 3 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 05abcf72d6..046953022b 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -622,6 +622,33 @@ pg_flush_data(int fd, off_t offset, off_t nbytes)
 #endif
 }
 
+/*
+ * Truncate a file to a given length by name.
+ */
+int
+pg_truncate(const char *path, off_t length)
+{
+#ifdef WIN32
+	int		save_errno;
+	int		ret;
+	int		fd;
+
+	fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
+	if (fd >= 0)
+	{
+		ret = ftruncate(fd, 0);
+		save_errno = errno;
+		CloseTransientFile(fd);
+		errno = save_errno;
+	}
+	else
+		ret = -1;
+
+	return ret;
+#else
+	return truncate(path, length);
+#endif
+}
 
 /*
  * fsync_fname -- fsync a file or directory, handling errors properly
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index c697af00d9..9889ad6ad8 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -294,19 +294,8 @@ do_truncate(const char *path)
 {
 	int			save_errno;
 	int			ret;
-	int			fd;
 
-	/* truncate(2) would be easier here, but Windows hasn't got it */
-	fd = OpenTransientFile(path, O_RDWR | PG_BINARY);
-	if (fd >= 0)
-	{
-		ret = ftruncate(fd, 0);
-		save_errno = errno;
-		CloseTransientFile(fd);
-		errno = save_errno;
-	}
-	else
-		ret = -1;
+	ret = pg_truncate(path, 0);
 
 	/* Log a warning here to avoid repetition in callers. */
 	if (ret < 0 && errno != ENOENT)
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index e209f047e8..4e1cc12e23 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -153,6 +153,7 @@ extern int	pg_fsync_no_writethrough(int fd);
 extern int	pg_fsync_writethrough(int fd);
 extern int	pg_fdatasync(int fd);
 extern void pg_flush_data(int fd, off_t offset, off_t amount);
+extern int	pg_truncate(const char *path, off_t length);
 extern void fsync_fname(const char *fname, bool isdir);
 extern int	fsync_fname_ext(const char *fname, bool isdir, bool ignore_perm, int elevel);
 extern int	durable_rename(const char *oldfile, const char *newfile, int loglevel);
-- 
2.20.1

