v13-0001-Refactor-Move-tar-archive-parsing-into-a-common-.patch
application/x-patch
Filename: v13-0001-Refactor-Move-tar-archive-parsing-into-a-common-.patch
Type: application/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v13-0001
Subject: Refactor: Move tar archive parsing into a common location.
| File | + | − |
|---|---|---|
| src/bin/pg_basebackup/pg_basebackup.c | 11 | 25 |
| src/bin/pg_verifybackup/pg_verifybackup.c | 1 | 11 |
| src/common/compression.c | 30 | 0 |
| src/include/common/compression.h | 2 | 0 |
From 6e4331bcbb98160365fe02502ae0a5cd2aea1726 Mon Sep 17 00:00:00 2001
From: Amul Sul <sulamul@gmail.com>
Date: Tue, 17 Feb 2026 14:51:11 +0530
Subject: [PATCH v13 01/10] Refactor: Move tar archive parsing into a common
location.
pg_basebackup and pg_verifybackup both require logic to identify tar
files and determine their compression types. Similar functionality
will be needed for pg_waldump when it gets the capability to decode
WAL files from tar archives. Moving this logic to a common location
allows for reuse and prevents code duplication.
---
src/bin/pg_basebackup/pg_basebackup.c | 36 +++++++----------------
src/bin/pg_verifybackup/pg_verifybackup.c | 12 +-------
src/common/compression.c | 30 +++++++++++++++++++
src/include/common/compression.h | 2 ++
4 files changed, 44 insertions(+), 36 deletions(-)
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 1e3a8203f77..8911b8b921d 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1070,12 +1070,9 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
astreamer *manifest_inject_streamer = NULL;
bool inject_manifest;
bool is_tar,
- is_tar_gz,
- is_tar_lz4,
- is_tar_zstd,
is_compressed_tar;
+ pg_compress_algorithm compressed_tar_algorithm;
bool must_parse_archive;
- int archive_name_len = strlen(archive_name);
/*
* Normally, we emit the backup manifest as a separate file, but when
@@ -1084,24 +1081,13 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
*/
inject_manifest = (format == 't' && strcmp(basedir, "-") == 0 && manifest);
- /* Is this a tar archive? */
- is_tar = (archive_name_len > 4 &&
- strcmp(archive_name + archive_name_len - 4, ".tar") == 0);
-
- /* Is this a .tar.gz archive? */
- is_tar_gz = (archive_name_len > 7 &&
- strcmp(archive_name + archive_name_len - 7, ".tar.gz") == 0);
-
- /* Is this a .tar.lz4 archive? */
- is_tar_lz4 = (archive_name_len > 8 &&
- strcmp(archive_name + archive_name_len - 8, ".tar.lz4") == 0);
-
- /* Is this a .tar.zst archive? */
- is_tar_zstd = (archive_name_len > 8 &&
- strcmp(archive_name + archive_name_len - 8, ".tar.zst") == 0);
+ /* Check weather it is tar archive and its compress type */
+ is_tar = parse_tar_compress_algorithm(archive_name,
+ &compressed_tar_algorithm);
/* Is this any kind of compressed tar? */
- is_compressed_tar = is_tar_gz || is_tar_lz4 || is_tar_zstd;
+ is_compressed_tar = (is_tar &&
+ compressed_tar_algorithm != PG_COMPRESSION_NONE);
/*
* Injecting the manifest into a compressed tar file would be possible if
@@ -1128,7 +1114,7 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
(spclocation == NULL && writerecoveryconf));
/* At present, we only know how to parse tar archives. */
- if (must_parse_archive && !is_tar && !is_compressed_tar)
+ if (must_parse_archive && !is_tar)
{
pg_log_error("cannot parse archive \"%s\"", archive_name);
pg_log_error_detail("Only tar archives can be parsed.");
@@ -1263,13 +1249,13 @@ CreateBackupStreamer(char *archive_name, char *spclocation,
* If the user has requested a server compressed archive along with
* archive extraction at client then we need to decompress it.
*/
- if (format == 'p')
+ if (format == 'p' && is_compressed_tar)
{
- if (is_tar_gz)
+ if (compressed_tar_algorithm == PG_COMPRESSION_GZIP)
streamer = astreamer_gzip_decompressor_new(streamer);
- else if (is_tar_lz4)
+ else if (compressed_tar_algorithm == PG_COMPRESSION_LZ4)
streamer = astreamer_lz4_decompressor_new(streamer);
- else if (is_tar_zstd)
+ else if (compressed_tar_algorithm == PG_COMPRESSION_ZSTD)
streamer = astreamer_zstd_decompressor_new(streamer);
}
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index f9f2d457f2f..5ddc4c33feb 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -941,17 +941,7 @@ precheck_tar_backup_file(verifier_context *context, char *relpath,
}
/* Now, check the compression type of the tar */
- if (strcmp(suffix, ".tar") == 0)
- compress_algorithm = PG_COMPRESSION_NONE;
- else if (strcmp(suffix, ".tgz") == 0)
- compress_algorithm = PG_COMPRESSION_GZIP;
- else if (strcmp(suffix, ".tar.gz") == 0)
- compress_algorithm = PG_COMPRESSION_GZIP;
- else if (strcmp(suffix, ".tar.lz4") == 0)
- compress_algorithm = PG_COMPRESSION_LZ4;
- else if (strcmp(suffix, ".tar.zst") == 0)
- compress_algorithm = PG_COMPRESSION_ZSTD;
- else
+ if (!parse_tar_compress_algorithm(suffix, &compress_algorithm))
{
report_backup_error(context,
"file \"%s\" is not expected in a tar format backup",
diff --git a/src/common/compression.c b/src/common/compression.c
index 92cd4ec7a0d..f117e21237f 100644
--- a/src/common/compression.c
+++ b/src/common/compression.c
@@ -41,6 +41,36 @@ static int expect_integer_value(char *keyword, char *value,
static bool expect_boolean_value(char *keyword, char *value,
pg_compress_specification *result);
+/*
+ * Look up a compression algorithm by archive file extension. Returns true and
+ * sets *algorithm if the name is recognized. Otherwise returns false.
+ */
+bool
+parse_tar_compress_algorithm(char *fname, pg_compress_algorithm *algorithm)
+{
+ int fname_len = strlen(fname);
+
+ if (fname_len >= 4 &&
+ strcmp(fname + fname_len - 4, ".tar") == 0)
+ *algorithm = PG_COMPRESSION_NONE;
+ else if (fname_len >= 4 &&
+ strcmp(fname + fname_len - 4, ".tgz") == 0)
+ *algorithm = PG_COMPRESSION_GZIP;
+ else if (fname_len >= 7 &&
+ strcmp(fname + fname_len - 7, ".tar.gz") == 0)
+ *algorithm = PG_COMPRESSION_GZIP;
+ else if (fname_len >= 8 &&
+ strcmp(fname + fname_len - 8, ".tar.lz4") == 0)
+ *algorithm = PG_COMPRESSION_LZ4;
+ else if (fname_len >= 8 &&
+ strcmp(fname + fname_len - 8, ".tar.zst") == 0)
+ *algorithm = PG_COMPRESSION_ZSTD;
+ else
+ return false;
+
+ return true;
+}
+
/*
* Look up a compression algorithm by name. Returns true and sets *algorithm
* if the name is recognized. Otherwise returns false.
diff --git a/src/include/common/compression.h b/src/include/common/compression.h
index 6c745b90066..50f21656b88 100644
--- a/src/include/common/compression.h
+++ b/src/include/common/compression.h
@@ -41,6 +41,8 @@ typedef struct pg_compress_specification
extern void parse_compress_options(const char *option, char **algorithm,
char **detail);
+extern bool parse_tar_compress_algorithm(char *fname,
+ pg_compress_algorithm *algorithm);
extern bool parse_compress_algorithm(char *name, pg_compress_algorithm *algorithm);
extern const char *get_compress_algorithm_name(pg_compress_algorithm algorithm);
--
2.47.1