diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 80dc3bbc8da..00408f1de49 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -1082,8 +1082,8 @@ CreateBackupStreamer(char *archive_name, char *spclocation, inject_manifest = (format == 't' && strcmp(basedir, "-") == 0 && manifest); /* Check whether it is a tar archive and its compression type */ - is_tar = parse_tar_compress_algorithm(archive_name, - &compressed_tar_algorithm); + is_tar = (parse_tar_compress_algorithm(archive_name, + &compressed_tar_algorithm) > 0); /* Is this any kind of compressed tar? */ is_compressed_tar = (is_tar && diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c index bd4fe635c6f..a972dae3070 100644 --- a/src/bin/pg_verifybackup/pg_verifybackup.c +++ b/src/bin/pg_verifybackup/pg_verifybackup.c @@ -967,8 +967,12 @@ precheck_tar_backup_file(verifier_context *context, char *relpath, tblspc_oid = (Oid) num; } - /* Now, check the compression type of the tar */ - if (!parse_tar_compress_algorithm(suffix, &compress_algorithm)) + /* + * If parse_tar_compress_algorithm returns exactly 0, there are no + * characters between the prefix we already checked and the detected + * suffix. Any other case is unexpected. + */ + if (parse_tar_compress_algorithm(suffix, &compress_algorithm) != 0) { report_backup_error(context, "file \"%s\" is not expected in a tar format backup", diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index c777e6763e5..d6b2a7adcbf 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -1242,7 +1242,7 @@ main(int argc, char **argv) if (waldir != NULL) { /* Check whether the path looks like a tar archive by its extension */ - if (parse_tar_compress_algorithm(waldir, &compression)) + if (parse_tar_compress_algorithm(waldir, &compression) >= 0) { split_path(waldir, &private.archive_dir, &private.archive_name); } @@ -1286,7 +1286,8 @@ main(int argc, char **argv) pg_fatal("could not open directory \"%s\": %m", waldir); } - if (fname != NULL && parse_tar_compress_algorithm(fname, &compression)) + if (fname != NULL && + parse_tar_compress_algorithm(fname, &compression) >= 0) { private.archive_dir = waldir; private.archive_name = fname; diff --git a/src/common/compression.c b/src/common/compression.c index ae2089d9406..e78913ad9dc 100644 --- a/src/common/compression.c +++ b/src/common/compression.c @@ -42,33 +42,47 @@ 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. + * Look up a compression algorithm by archive file extension. Sets *algorithm + * and returns the length of the non-extension portion of the filename, or -1 + * if the filename does not end with a recognized tar extension. */ -bool +int parse_tar_compress_algorithm(const char *fname, pg_compress_algorithm *algorithm) { - size_t fname_len = strlen(fname); + int fname_len = strlen(fname); if (fname_len >= 4 && strcmp(fname + fname_len - 4, ".tar") == 0) + { *algorithm = PG_COMPRESSION_NONE; + return fname_len - 4; + } else if (fname_len >= 4 && strcmp(fname + fname_len - 4, ".tgz") == 0) + { *algorithm = PG_COMPRESSION_GZIP; + return fname_len - 4; + } else if (fname_len >= 7 && strcmp(fname + fname_len - 7, ".tar.gz") == 0) + { *algorithm = PG_COMPRESSION_GZIP; + return fname_len - 7; + } else if (fname_len >= 8 && strcmp(fname + fname_len - 8, ".tar.lz4") == 0) + { *algorithm = PG_COMPRESSION_LZ4; + return fname_len - 8; + } else if (fname_len >= 8 && strcmp(fname + fname_len - 8, ".tar.zst") == 0) + { *algorithm = PG_COMPRESSION_ZSTD; - else - return false; + return fname_len - 8; + } - return true; + return -1; } /* diff --git a/src/include/common/compression.h b/src/include/common/compression.h index f99c747cdd3..adbe668a105 100644 --- a/src/include/common/compression.h +++ b/src/include/common/compression.h @@ -41,7 +41,7 @@ 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, +extern int 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);