From 96f77d9430383de96e3d81427d0f4a8811e1b7c8 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Wed, 25 Jun 2025 14:24:20 +0200
Subject: [PATCH v7 2/6] pg_dump compression API: write_func

Make write_func throw an error on all error conditions.  All callers of
write_func were already checking for success and calling pg_fatal on all
errors, so we might as well make the API support that case directly with
simpler errorhandling as a result.  Returns the number of bytes written
in case of success, which will match the size of the buffer passed in.
---
 src/bin/pg_dump/compress_gzip.c       | 11 +++++--
 src/bin/pg_dump/compress_io.h         |  5 ++--
 src/bin/pg_dump/compress_lz4.c        | 14 ++++-----
 src/bin/pg_dump/compress_none.c       | 10 ++++---
 src/bin/pg_dump/compress_zstd.c       | 14 ++++-----
 src/bin/pg_dump/pg_backup_archiver.c  |  4 +--
 src/bin/pg_dump/pg_backup_directory.c | 42 ++++-----------------------
 7 files changed, 35 insertions(+), 65 deletions(-)

diff --git a/src/bin/pg_dump/compress_gzip.c b/src/bin/pg_dump/compress_gzip.c
index 8db121b94a3..2edcbffdd8d 100644
--- a/src/bin/pg_dump/compress_gzip.c
+++ b/src/bin/pg_dump/compress_gzip.c
@@ -270,12 +270,19 @@ Gzip_read(void *ptr, size_t size, CompressFileHandle *CFH)
 	return (size_t) gzret;
 }
 
-static bool
+static void
 Gzip_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 {
 	gzFile		gzfp = (gzFile) CFH->private_data;
+	int			errnum;
+	const char *errmsg;
 
-	return gzwrite(gzfp, ptr, size) == size;
+	if (gzwrite(gzfp, ptr, size) != size)
+	{
+		errmsg = gzerror(gzfp, &errnum);
+		pg_fatal("could not write to file: %s",
+				 errnum == Z_ERRNO ? strerror(errno) : errmsg);
+	}
 }
 
 static int
diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h
index dad0c91fec5..e4d98ca08d7 100644
--- a/src/bin/pg_dump/compress_io.h
+++ b/src/bin/pg_dump/compress_io.h
@@ -135,10 +135,9 @@ struct CompressFileHandle
 	/*
 	 * Write 'size' bytes of data into the file from 'ptr'.
 	 *
-	 * Returns true on success and false on error (it is caller's
-	 * responsibility to deal with error conditions).
+	 * Returns nothing, exits via pg_fatal for all error conditions.
 	 */
-	bool		(*write_func) (const void *ptr, size_t size,
+	void		(*write_func) (const void *ptr, size_t size,
 							   CompressFileHandle *CFH);
 
 	/*
diff --git a/src/bin/pg_dump/compress_lz4.c b/src/bin/pg_dump/compress_lz4.c
index c94f9dcd4cf..3242c062acf 100644
--- a/src/bin/pg_dump/compress_lz4.c
+++ b/src/bin/pg_dump/compress_lz4.c
@@ -558,7 +558,7 @@ LZ4Stream_read_internal(LZ4State *state, void *ptr, int ptrsize, bool eol_flag)
 /*
  * Compress size bytes from ptr and write them to the stream.
  */
-static bool
+static void
 LZ4Stream_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 {
 	LZ4State   *state = (LZ4State *) CFH->private_data;
@@ -567,7 +567,8 @@ LZ4Stream_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 
 	/* Lazy init */
 	if (!LZ4Stream_init(state, size, true))
-		return false;
+		pg_fatal("unable to initialize LZ4 library: %s",
+				 LZ4F_getErrorName(state->errcode));
 
 	while (remaining > 0)
 	{
@@ -578,22 +579,17 @@ LZ4Stream_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 		status = LZ4F_compressUpdate(state->ctx, state->buffer, state->buflen,
 									 ptr, chunk, NULL);
 		if (LZ4F_isError(status))
-		{
-			state->errcode = status;
-			return false;
-		}
+			pg_fatal("error during writing: %s", LZ4F_getErrorName(status));
 
 		errno = 0;
 		if (fwrite(state->buffer, 1, status, state->fp) != status)
 		{
 			errno = (errno) ? errno : ENOSPC;
-			return false;
+			pg_fatal("error during writing: %m");
 		}
 
 		ptr = ((const char *) ptr) + chunk;
 	}
-
-	return true;
 }
 
 /*
diff --git a/src/bin/pg_dump/compress_none.c b/src/bin/pg_dump/compress_none.c
index 4924935a5bd..a5179c1050a 100644
--- a/src/bin/pg_dump/compress_none.c
+++ b/src/bin/pg_dump/compress_none.c
@@ -96,16 +96,18 @@ read_none(void *ptr, size_t size, CompressFileHandle *CFH)
 	return ret;
 }
 
-static bool
+static void
 write_none(const void *ptr, size_t size, CompressFileHandle *CFH)
 {
 	size_t		ret;
 
+	errno = 0;
 	ret = fwrite(ptr, 1, size, (FILE *) CFH->private_data);
 	if (ret != size)
-		return false;
-
-	return true;
+	{
+		errno = (errno) ? errno : ENOSPC;
+		pg_fatal("coud not write to file: %m");
+	}
 }
 
 static const char *
diff --git a/src/bin/pg_dump/compress_zstd.c b/src/bin/pg_dump/compress_zstd.c
index 8f718212d9f..9ca88386ddb 100644
--- a/src/bin/pg_dump/compress_zstd.c
+++ b/src/bin/pg_dump/compress_zstd.c
@@ -326,7 +326,7 @@ Zstd_read(void *ptr, size_t size, CompressFileHandle *CFH)
 	return output->pos;
 }
 
-static bool
+static void
 Zstd_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 {
 	ZstdCompressorState *zstdcs = (ZstdCompressorState *) CFH->private_data;
@@ -345,20 +345,16 @@ Zstd_write(const void *ptr, size_t size, CompressFileHandle *CFH)
 		output->pos = 0;
 		res = ZSTD_compressStream2(zstdcs->cstream, output, input, ZSTD_e_continue);
 		if (ZSTD_isError(res))
-		{
-			zstdcs->zstderror = ZSTD_getErrorName(res);
-			return false;
-		}
+			pg_fatal("could not write to file: %s", ZSTD_getErrorName(res));
 
+		errno = 0;
 		cnt = fwrite(output->dst, 1, output->pos, zstdcs->fp);
 		if (cnt != output->pos)
 		{
-			zstdcs->zstderror = strerror(errno);
-			return false;
+			errno = (errno) ? errno : ENOSPC;
+			pg_fatal("could not write to file: %m");
 		}
 	}
-
-	return true;
 }
 
 static int
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 197c1295d93..9145598ff33 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -1868,8 +1868,8 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
 	{
 		CompressFileHandle *CFH = (CompressFileHandle *) AH->OF;
 
-		if (CFH->write_func(ptr, size * nmemb, CFH))
-			bytes_written = size * nmemb;
+		CFH->write_func(ptr, size * nmemb, CFH);
+		bytes_written = size * nmemb;
 	}
 
 	if (bytes_written != size * nmemb)
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index eb2ce8d5a6c..94d401d8a4e 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -316,15 +316,9 @@ _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
 	lclContext *ctx = (lclContext *) AH->formatData;
 	CompressFileHandle *CFH = ctx->dataFH;
 
-	errno = 0;
-	if (dLen > 0 && !CFH->write_func(data, dLen, CFH))
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		pg_fatal("could not write to output file: %s",
-				 CFH->get_error_func(CFH));
-	}
+	if (dLen <= 0)
+		return;
+	CFH->write_func(data, dLen, CFH);
 }
 
 /*
@@ -470,16 +464,7 @@ _WriteByte(ArchiveHandle *AH, const int i)
 	lclContext *ctx = (lclContext *) AH->formatData;
 	CompressFileHandle *CFH = ctx->dataFH;
 
-	errno = 0;
-	if (!CFH->write_func(&c, 1, CFH))
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		pg_fatal("could not write to output file: %s",
-				 CFH->get_error_func(CFH));
-	}
-
+	CFH->write_func(&c, 1, CFH);
 	return 1;
 }
 
@@ -508,15 +493,7 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
 	lclContext *ctx = (lclContext *) AH->formatData;
 	CompressFileHandle *CFH = ctx->dataFH;
 
-	errno = 0;
-	if (!CFH->write_func(buf, len, CFH))
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		pg_fatal("could not write to output file: %s",
-				 CFH->get_error_func(CFH));
-	}
+	CFH->write_func(buf, len, CFH);
 }
 
 /*
@@ -677,14 +654,7 @@ _EndLO(ArchiveHandle *AH, TocEntry *te, Oid oid)
 
 	/* register the LO in blobs_NNN.toc */
 	len = snprintf(buf, sizeof(buf), "%u blob_%u.dat\n", oid, oid);
-	if (!CFH->write_func(buf, len, CFH))
-	{
-		/* if write didn't set errno, assume problem is no disk space */
-		if (errno == 0)
-			errno = ENOSPC;
-		pg_fatal("could not write to LOs TOC file: %s",
-				 CFH->get_error_func(CFH));
-	}
+	CFH->write_func(buf, len, CFH);
 }
 
 /*
-- 
2.39.3 (Apple Git-146)

