From: Alvaro Herrera Date: Wed, 2 Aug 2017 22:26:26 +0000 (-0400) Subject: Fix pg_dump's errno checking for zlib I/O X-Git-Tag: REL9_6_4~14 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=060393f2a13651bf53c7626a3587baaf82942023;p=postgresql Fix pg_dump's errno checking for zlib I/O Some error reports were reporting strerror(errno), which for some error conditions coming from zlib are wrong, resulting in confusing reports such as pg_restore: [compress_io] could not read from input file: Success which makes no sense. To correctly extract the error message we need to use gzerror(), so let's do that. This isn't as comprehensive or as neat as I would like, but at least it should improve things in many common cases. The zlib abstraction in compress_io does not seem to be applied consistently enough; we could perhaps improve that, but it seems master-only material, not a bug fix for back-patching. This problem goes back all the way, but I decided to apply back to 9.4 only, because older branches don't contain commit 14ea89366 which this change depends on. Authors: Vladimir Kunschikov, Álvaro Herrera Discussion: https://postgr.es/m/1498120508308.9826@infotecs.ru --- diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index e0ef9cd60a..eb590c348c 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -592,8 +592,14 @@ cfread(void *ptr, int size, cfp *fp) { ret = gzread(fp->compressedfp, ptr, size); if (ret != size && !gzeof(fp->compressedfp)) + { + int errnum; + const char *errmsg = gzerror(fp->compressedfp, &errnum); + exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); + "could not read from input file: %s\n", + errnum == Z_ERRNO ? strerror(errno) : errmsg); + } } else #endif @@ -695,6 +701,22 @@ cfeof(cfp *fp) return feof(fp->uncompressedfp); } +const char * +get_cfp_error(cfp *fp) +{ +#ifdef HAVE_LIBZ + if (fp->compressedfp) + { + int errnum; + const char *errmsg = gzerror(fp->compressedfp, &errnum); + + if (errnum != Z_ERRNO) + return errmsg; + } +#endif + return strerror(errno); +} + #ifdef HAVE_LIBZ static int hasSuffix(const char *filename, const char *suffix) diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h index 2a45600943..89be583d45 100644 --- a/src/bin/pg_dump/compress_io.h +++ b/src/bin/pg_dump/compress_io.h @@ -65,5 +65,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_cfp_error(cfp *fp); #endif diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c index e52f12258a..6673d4a3cd 100644 --- a/src/bin/pg_dump/pg_backup_directory.c +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -357,7 +357,9 @@ _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) lclContext *ctx = (lclContext *) AH->formatData; if (dLen > 0 && cfwrite(data, dLen, ctx->dataFH) != dLen) - WRITE_ERROR_EXIT; + exit_horribly(modulename, "could not write to output file: %s\n", + get_cfp_error(ctx->dataFH)); + return; } @@ -495,7 +497,8 @@ _WriteByte(ArchiveHandle *AH, const int i) lclContext *ctx = (lclContext *) AH->formatData; if (cfwrite(&c, 1, ctx->dataFH) != 1) - WRITE_ERROR_EXIT; + exit_horribly(modulename, "could not write to output file: %s\n", + get_cfp_error(ctx->dataFH)); return 1; } @@ -524,7 +527,8 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) lclContext *ctx = (lclContext *) AH->formatData; if (cfwrite(buf, len, ctx->dataFH) != len) - WRITE_ERROR_EXIT; + exit_horribly(modulename, "could not write to output file: %s\n", + get_cfp_error(ctx->dataFH)); return; } diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 8dfc6a98de..befbb4ade4 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -557,8 +557,14 @@ _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)) + { + int errnum; + const char *errmsg = gzerror(th->zFH, &errnum); + exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); + "could not read from input file: %s\n", + errnum == Z_ERRNO ? strerror(errno) : errmsg); + } } else {