]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Move tar detection and compression logic to common.
authorAndrew Dunstan <andrew@dunslane.net>
Fri, 20 Mar 2026 19:31:35 +0000 (15:31 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Fri, 20 Mar 2026 19:31:35 +0000 (15:31 -0400)
Consolidate tar archive identification and compression-type detection
logic into a shared location. Currently used by pg_basebackup and
pg_verifybackup, this functionality is also required for upcoming
pg_waldump enhancements.

This change promotes code reuse and simplifies maintenance across
frontend tools.

Author: Amul Sul <sulamul@gmail.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Reviewed-by: Jakub Wartak <jakub.wartak@enterprisedb.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Euler Taveira <euler@eulerto.com>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
discussion: https://postgr.es/m/CAAJ_b94bqdWN3h2J-PzzzQ2Npbwct5ZQHggn_QoYGhC2rn-=WQ@mail.gmail.com

src/bin/pg_basebackup/pg_basebackup.c
src/bin/pg_verifybackup/pg_verifybackup.c
src/common/compression.c
src/include/common/compression.h

index fa169a8d6423b27e8cfd0f0d4463a8ad93d5889c..c1a4672aa6fd7758cd647497f984796f7cc2b01b 100644 (file)
@@ -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 whether it is a tar archive and its compression 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);
        }
 
index cbc9447384fa556596d0047515b18dc10a36d793..31f606c45b1b4125178c80071cc35147a739d9b5 100644 (file)
@@ -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",
index 92cd4ec7a0d78fa2ef07743e6f180f0244d39661..ae2089d9406d61586819ac8ab58198d138f34c7f 100644 (file)
@@ -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 extension is recognized. Otherwise returns false.
+ */
+bool
+parse_tar_compress_algorithm(const char *fname, pg_compress_algorithm *algorithm)
+{
+       size_t          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.
index 6c745b90066308de0d78a6b7e5365b5aa89d940d..f99c747cdd3fa7fad59ee1dc66c0356cfa0455ec 100644 (file)
@@ -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(const 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);