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
This commit is contained in:
Alvaro Herrera 2017-08-02 18:26:26 -04:00
parent e5c87d5e1d
commit 060393f2a1
4 changed files with 38 additions and 5 deletions

View File

@ -592,8 +592,14 @@ cfread(void *ptr, int size, cfp *fp)
{ {
ret = gzread(fp->compressedfp, ptr, size); ret = gzread(fp->compressedfp, ptr, size);
if (ret != size && !gzeof(fp->compressedfp)) if (ret != size && !gzeof(fp->compressedfp))
{
int errnum;
const char *errmsg = gzerror(fp->compressedfp, &errnum);
exit_horribly(modulename, 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 else
#endif #endif
@ -695,6 +701,22 @@ cfeof(cfp *fp)
return feof(fp->uncompressedfp); 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 #ifdef HAVE_LIBZ
static int static int
hasSuffix(const char *filename, const char *suffix) hasSuffix(const char *filename, const char *suffix)

View File

@ -65,5 +65,6 @@ extern int cfgetc(cfp *fp);
extern char *cfgets(cfp *fp, char *buf, int len); extern char *cfgets(cfp *fp, char *buf, int len);
extern int cfclose(cfp *fp); extern int cfclose(cfp *fp);
extern int cfeof(cfp *fp); extern int cfeof(cfp *fp);
extern const char *get_cfp_error(cfp *fp);
#endif #endif

View File

@ -357,7 +357,9 @@ _WriteData(ArchiveHandle *AH, const void *data, size_t dLen)
lclContext *ctx = (lclContext *) AH->formatData; lclContext *ctx = (lclContext *) AH->formatData;
if (dLen > 0 && cfwrite(data, dLen, ctx->dataFH) != dLen) 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; return;
} }
@ -495,7 +497,8 @@ _WriteByte(ArchiveHandle *AH, const int i)
lclContext *ctx = (lclContext *) AH->formatData; lclContext *ctx = (lclContext *) AH->formatData;
if (cfwrite(&c, 1, ctx->dataFH) != 1) 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; return 1;
} }
@ -524,7 +527,8 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len)
lclContext *ctx = (lclContext *) AH->formatData; lclContext *ctx = (lclContext *) AH->formatData;
if (cfwrite(buf, len, ctx->dataFH) != len) 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; return;
} }

View File

@ -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); res = GZREAD(&((char *) buf)[used], 1, len, th->zFH);
if (res != len && !GZEOF(th->zFH)) if (res != len && !GZEOF(th->zFH))
{
int errnum;
const char *errmsg = gzerror(th->zFH, &errnum);
exit_horribly(modulename, 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 else
{ {