Hello, our testing team has noticed apparently wrong backup/restore error messages like this:
pg_restore: [compress_io] could not read from input file: success pg_dump: [directory archiver] could not write to output file: success Such "success" messages are caused by calling strerror() after gzread()/gzwrite() failures. In order to properly decode errors, there should be used gzerror() instead of strerror(): http://refspecs.linuxbase.org/LSB_2.1.0/LSB-generic/LSB-generic/zlib-gzerror-1.html Errors should be like this: pg_restore: [compress_io] could not read from input file: d3/2811.dat.gz: invalid distance too far back Attached small fix for this issue. You can view that patch online on our github: https://github.com/Infotecs/postgres/commit/1578f5011ad22d78ae059a4ef0924426fd6db762 -- Best regards, Vladimir Kunschikov Lead software developer IDS project InfoTeCS JSC <http://portal.infotecs.int/company/structure/Pages/detailsDepartment.aspx?idDepartment=235&idCompany=17>
commit 1578f5011ad22d78ae059a4ef0924426fd6db762 Author: Kunshchikov Vladimir <kunshchikov....@infotecs.ru> Date: Wed Jun 21 11:33:47 2017 +0300 fixed gz_error/strerror mishap diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index 631fa337e6..6e48d9d765 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -422,23 +422,6 @@ WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, } -/*---------------------- - * Compressed stream API - *---------------------- - */ - -/* - * cfp represents an open stream, wrapping the underlying FILE or gzFile - * pointer. This is opaque to the callers. - */ -struct cfp -{ - FILE *uncompressedfp; -#ifdef HAVE_LIBZ - gzFile compressedfp; -#endif -}; - #ifdef HAVE_LIBZ static int hasSuffix(const char *filename, const char *suffix); #endif @@ -593,7 +576,7 @@ cfread(void *ptr, int size, cfp *fp) ret = gzread(fp->compressedfp, ptr, size); if (ret != size && !gzeof(fp->compressedfp)) exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); + "could not read from input file: %s\n", get_gz_error(fp->compressedfp)); } else #endif @@ -629,7 +612,7 @@ cfgetc(cfp *fp) { if (!gzeof(fp->compressedfp)) exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); + "could not read from input file: %s\n", get_gz_error(fp->compressedfp)); else exit_horribly(modulename, "could not read from input file: end of file\n"); @@ -710,4 +693,16 @@ hasSuffix(const char *filename, const char *suffix) suffixlen) == 0; } +const char * +get_gz_error(gzFile gzf) +{ + int errnum; + static const char fallback[] = "Zlib error"; + const int maxlen = 255; + const char *errmsg = gzerror(gzf, &errnum); + if(!errmsg || !memchr(errmsg, 0, maxlen)) + errmsg = fallback; + + return errnum == Z_ERRNO ? strerror(errno) : errmsg; +} #endif diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h index 8f2e752cba..91007b042b 100644 --- a/src/bin/pg_dump/compress_io.h +++ b/src/bin/pg_dump/compress_io.h @@ -27,6 +27,24 @@ typedef enum COMPR_ALG_LIBZ } CompressionAlgorithm; +/*---------------------- + * Compressed stream API + *---------------------- + */ + +/* + * cfp represents an open stream, wrapping the underlying FILE or gzFile + * pointer. This is opaque to the callers. + */ +typedef struct +{ + FILE *uncompressedfp; +#ifdef HAVE_LIBZ + gzFile compressedfp; +#endif +} cfp; + + /* Prototype for callback function to WriteDataToArchive() */ typedef void (*WriteFunc) (ArchiveHandle *AH, const char *buf, size_t len); @@ -52,10 +70,6 @@ extern void ReadDataFromArchive(ArchiveHandle *AH, int compression, extern void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, const void *data, size_t dLen); extern void EndCompressor(ArchiveHandle *AH, CompressorState *cs); - - -typedef struct cfp cfp; - extern cfp *cfopen(const char *path, const char *mode, int compression); extern cfp *cfopen_read(const char *path, const char *mode); extern cfp *cfopen_write(const char *path, const char *mode, int compression); @@ -65,5 +79,6 @@ extern int cfgetc(cfp *fp); extern char *cfgets(cfp *fp, char *buf, int len); extern int cfclose(cfp *fp); extern int cfeof(cfp *fp); +extern const char * get_gz_error(gzFile gzf); #endif diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c index 79922da8ba..6196227a04 100644 --- a/src/bin/pg_dump/pg_backup_directory.c +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -42,6 +42,15 @@ #include <dirent.h> #include <sys/stat.h> +#ifdef WRITE_ERROR_EXIT +#undef WRITE_ERROR_EXIT +#endif +#define WRITE_ERROR_EXIT \ + do { \ + exit_horribly(modulename, "could not write to output file: %s\n", \ + ctx && ctx->dataFH && ctx->dataFH->compressedfp? get_gz_error(ctx->dataFH->compressedfp) : strerror(errno)); \ + } while (0) + typedef struct { /* diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index a2b320f371..0b7f651537 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -35,6 +35,7 @@ #include "pgtar.h" #include "common/file_utils.h" #include "fe_utils/string_utils.h" +#include "compress_io.h" #include <sys/stat.h> #include <ctype.h> @@ -556,7 +557,7 @@ _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh) res = GZREAD(&((char *) buf)[used], 1, len, th->zFH); if (res != len && !GZEOF(th->zFH)) exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); + "could not read from input file: %s\n", get_gz_error(th->zFH)); } else {
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers