From 14ea89366fe321609afc5838ff9fe2ded1cd707d Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 5 May 2014 20:27:16 -0400 Subject: [PATCH] Properly detect read and write errors in pg_dump/dumpall, and pg_restore Previously some I/O errors were ignored. --- src/bin/pg_dump/compress_io.c | 82 ++++++++++++++++--------- src/bin/pg_dump/compress_io.h | 4 +- src/bin/pg_dump/pg_backup.h | 4 +- src/bin/pg_dump/pg_backup_archiver.c | 83 ++++++++++++------------- src/bin/pg_dump/pg_backup_archiver.h | 26 ++++++-- src/bin/pg_dump/pg_backup_custom.c | 88 ++++++++++++--------------- src/bin/pg_dump/pg_backup_db.c | 2 +- src/bin/pg_dump/pg_backup_directory.c | 51 ++++++++-------- src/bin/pg_dump/pg_backup_null.c | 21 +++---- src/bin/pg_dump/pg_backup_tar.c | 83 ++++++++++++++----------- 10 files changed, 237 insertions(+), 207 deletions(-) diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index 10bc3f048d..06056b1c34 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -86,14 +86,14 @@ static void InitCompressorZlib(CompressorState *cs, int level); static void DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush); static void ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF); -static size_t WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, +static void WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, const char *data, size_t dLen); static void EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs); #endif /* Routines that support uncompressed data I/O */ static void ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF); -static size_t WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, +static void WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, const char *data, size_t dLen); /* @@ -179,7 +179,7 @@ ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF) /* * Compress and write data to the output stream (via writeF). */ -size_t +void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, const void *data, size_t dLen) { @@ -190,14 +190,16 @@ WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, { case COMPR_ALG_LIBZ: #ifdef HAVE_LIBZ - return WriteDataToArchiveZlib(AH, cs, data, dLen); + WriteDataToArchiveZlib(AH, cs, data, dLen); #else exit_horribly(modulename, "not built with zlib support\n"); #endif + break; case COMPR_ALG_NONE: - return WriteDataToArchiveNone(AH, cs, data, dLen); + WriteDataToArchiveNone(AH, cs, data, dLen); + break; } - return 0; /* keep compiler quiet */ + return; } /* @@ -298,10 +300,7 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) */ size_t len = cs->zlibOutSize - zp->avail_out; - if (cs->writeF(AH, out, len) != len) - exit_horribly(modulename, - "could not write to output file: %s\n", - strerror(errno)); + cs->writeF(AH, out, len); } zp->next_out = (void *) out; zp->avail_out = cs->zlibOutSize; @@ -312,7 +311,7 @@ DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush) } } -static size_t +static void WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, const char *data, size_t dLen) { @@ -320,11 +319,7 @@ WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs, cs->zp->avail_in = dLen; DeflateCompressorZlib(AH, cs, false); - /* - * we have either succeeded in writing dLen bytes or we have called - * exit_horribly() - */ - return dLen; + return; } static void @@ -427,19 +422,12 @@ ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF) free(buf); } -static size_t +static void WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs, const char *data, size_t dLen) { - /* - * Any write function should do its own error checking but to make sure we - * do a check here as well... - */ - if (cs->writeF(AH, data, dLen) != dLen) - exit_horribly(modulename, - "could not write to output file: %s\n", - strerror(errno)); - return dLen; + cs->writeF(AH, data, dLen); + return; } @@ -573,12 +561,27 @@ cfopen(const char *path, const char *mode, int compression) int cfread(void *ptr, int size, cfp *fp) { + int ret; + + if (size == 0) + return 0; + #ifdef HAVE_LIBZ if (fp->compressedfp) - return gzread(fp->compressedfp, ptr, size); + { + 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)); + } else #endif - return fread(ptr, 1, size, fp->uncompressedfp); + { + ret = fread(ptr, 1, size, fp->uncompressedfp); + if (ret != size && !feof(fp->uncompressedfp)) + READ_ERROR_EXIT(fp->uncompressedfp); + } + return ret; } int @@ -595,12 +598,31 @@ cfwrite(const void *ptr, int size, cfp *fp) int cfgetc(cfp *fp) { + int ret; + #ifdef HAVE_LIBZ if (fp->compressedfp) - return gzgetc(fp->compressedfp); + { + ret = gzgetc(fp->compressedfp); + if (ret == EOF) + { + if (!gzeof(fp->compressedfp)) + exit_horribly(modulename, + "could not read from input file: %s\n", strerror(errno)); + else + exit_horribly(modulename, + "could not read from input file: end of file\n"); + } + } else #endif - return fgetc(fp->uncompressedfp); + { + ret = fgetc(fp->uncompressedfp); + if (ret == EOF) + READ_ERROR_EXIT(fp->uncompressedfp); + } + + return ret; } char * diff --git a/src/bin/pg_dump/compress_io.h b/src/bin/pg_dump/compress_io.h index aecfba5937..713c78b8a7 100644 --- a/src/bin/pg_dump/compress_io.h +++ b/src/bin/pg_dump/compress_io.h @@ -29,7 +29,7 @@ typedef enum } CompressionAlgorithm; /* Prototype for callback function to WriteDataToArchive() */ -typedef size_t (*WriteFunc) (ArchiveHandle *AH, const char *buf, size_t len); +typedef void (*WriteFunc) (ArchiveHandle *AH, const char *buf, size_t len); /* * Prototype for callback function to ReadDataFromArchive() @@ -50,7 +50,7 @@ typedef struct CompressorState CompressorState; extern CompressorState *AllocateCompressor(int compression, WriteFunc writeF); extern void ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF); -extern size_t WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, +extern void WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs, const void *data, size_t dLen); extern void EndCompressor(ArchiveHandle *AH, CompressorState *cs); diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 83f7216d50..08ace67db4 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -180,7 +180,7 @@ extern void ArchiveEntry(Archive *AHX, DataDumperPtr dumpFn, void *dumpArg); /* Called to write *data* to the archive */ -extern size_t WriteData(Archive *AH, const void *data, size_t dLen); +extern void WriteData(Archive *AH, const void *data, size_t dLen); extern int StartBlob(Archive *AH, Oid oid); extern int EndBlob(Archive *AH, Oid oid); @@ -208,7 +208,7 @@ extern RestoreOptions *NewRestoreOptions(void); extern void SortTocFromFile(Archive *AHX, RestoreOptions *ropt); /* Convenience functions used only when writing DATA */ -extern int archputs(const char *s, Archive *AH); +extern void archputs(const char *s, Archive *AH); extern int archprintf(Archive *AH, const char *fmt,...) /* This extension allows gcc to check the format string */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 946454019b..adf91e1697 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -855,7 +855,7 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt */ /* Public */ -size_t +void WriteData(Archive *AHX, const void *data, size_t dLen) { ArchiveHandle *AH = (ArchiveHandle *) AHX; @@ -863,7 +863,9 @@ WriteData(Archive *AHX, const void *data, size_t dLen) if (!AH->currToc) exit_horribly(modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n"); - return (*AH->WriteDataPtr) (AH, data, dLen); + (*AH->WriteDataPtr) (AH, data, dLen); + + return; } /* @@ -1246,10 +1248,11 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt) **********************/ /* Public */ -int +void archputs(const char *s, Archive *AH) { - return WriteData(AH, s, strlen(s)); + WriteData(AH, s, strlen(s)); + return; } /* Public */ @@ -1486,11 +1489,11 @@ dump_lo_buf(ArchiveHandle *AH) * format to create a custom output routine to 'fake' a restore if it * wants to generate a script (see TAR output). */ -int +void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH) { - size_t res; - + int bytes_written = 0; + if (AH->writingBlob) { size_t remaining = size * nmemb; @@ -1509,23 +1512,12 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH) memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining); AH->lo_buf_used += remaining; - return size * nmemb; + bytes_written = size * nmemb; } else if (AH->gzOut) - { - res = GZWRITE(ptr, size, nmemb, AH->OF); - if (res != (nmemb * size)) - exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno)); - return res; - } + bytes_written = GZWRITE(ptr, size, nmemb, AH->OF); else if (AH->CustomOutPtr) - { - res = AH->CustomOutPtr (AH, ptr, size * nmemb); - - if (res != (nmemb * size)) - exit_horribly(modulename, "could not write to custom output routine\n"); - return res; - } + bytes_written = AH->CustomOutPtr (AH, ptr, size * nmemb); else { /* @@ -1533,16 +1525,15 @@ ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH) * connected then send it to the DB. */ if (RestoringToDB(AH)) - return ExecuteSqlCommandBuf(AH, (const char *) ptr, size * nmemb); + bytes_written = ExecuteSqlCommandBuf(AH, (const char *) ptr, size * nmemb); else - { - res = fwrite(ptr, size, nmemb, AH->OF); - if (res != nmemb) - exit_horribly(modulename, "could not write to output file: %s\n", - strerror(errno)); - return res; - } + bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size; } + + if (bytes_written != size * nmemb) + WRITE_ERROR_EXIT; + + return; } /* on some error, we may decide to go on... */ @@ -1847,8 +1838,11 @@ WriteStr(ArchiveHandle *AH, const char *c) if (c) { - res = WriteInt(AH, strlen(c)); - res += (*AH->WriteBufPtr) (AH, c, strlen(c)); + int len = strlen(c); + + res = WriteInt(AH, len); + (*AH->WriteBufPtr) (AH, c, len); + res += len; } else res = WriteInt(AH, -1); @@ -1868,8 +1862,7 @@ ReadStr(ArchiveHandle *AH) else { buf = (char *) pg_malloc(l + 1); - if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l) - exit_horribly(modulename, "unexpected end of file\n"); + (*AH->ReadBufPtr) (AH, (void *) buf, l); buf[l] = '\0'; } @@ -1950,9 +1943,7 @@ _discoverArchiveFormat(ArchiveHandle *AH) strerror(errno)); } - cnt = fread(sig, 1, 5, fh); - - if (cnt != 5) + if ((cnt = fread(sig, 1, 5, fh)) != 5) { if (ferror(fh)) exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); @@ -1975,12 +1966,12 @@ _discoverArchiveFormat(ArchiveHandle *AH) * NB: this code must agree with ReadHead(). */ if ((byteread = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->vmaj = byteread; if ((byteread = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->vmin = byteread; @@ -1992,7 +1983,7 @@ _discoverArchiveFormat(ArchiveHandle *AH) if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0))) /* Version > 1.0 */ { if ((byteread = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->vrev = byteread; AH->lookahead[AH->lookaheadLen++] = AH->vrev; @@ -2004,20 +1995,20 @@ _discoverArchiveFormat(ArchiveHandle *AH) AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0; if ((AH->intSize = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->lookahead[AH->lookaheadLen++] = AH->intSize; if (AH->version >= K_VERS_1_7) { if ((AH->offSize = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->lookahead[AH->lookaheadLen++] = AH->offSize; } else AH->offSize = AH->intSize; if ((byteread = fgetc(fh)) == EOF) - exit_horribly(modulename, "could not read input file: %s\n", strerror(errno)); + READ_ERROR_EXIT(fh); AH->format = byteread; AH->lookahead[AH->lookaheadLen++] = AH->format; @@ -2029,6 +2020,7 @@ _discoverArchiveFormat(ArchiveHandle *AH) * read first 512 byte header... */ cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh); + /* read failure is checked below */ AH->lookaheadLen += cnt; if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) && @@ -2042,8 +2034,10 @@ _discoverArchiveFormat(ArchiveHandle *AH) exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n"); } - if (AH->lookaheadLen != 512) + if (AH->lookaheadLen != 512 && feof(fh)) exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n"); + else + READ_ERROR_EXIT(fh); if (!isValidTarHeader(AH->lookahead)) exit_horribly(modulename, "input file does not appear to be a valid archive\n"); @@ -3318,8 +3312,7 @@ ReadHead(ArchiveHandle *AH) */ if (!AH->readHeader) { - if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5) - exit_horribly(modulename, "unexpected end of file\n"); + (*AH->ReadBufPtr) (AH, tmpMag, 5); if (strncmp(tmpMag, "PGDMP", 5) != 0) exit_horribly(modulename, "did not find magic string in file header\n"); diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 25aa158e5d..92ec1d89c6 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -45,10 +45,12 @@ #define GZCLOSE(fh) gzclose(fh) #define GZWRITE(p, s, n, fh) gzwrite(fh, p, (n) * (s)) #define GZREAD(p, s, n, fh) gzread(fh, p, (n) * (s)) +#define GZEOF(fh) gzeof(fh) #else #define GZCLOSE(fh) fclose(fh) #define GZWRITE(p, s, n, fh) (fwrite(p, s, n, fh) * (s)) #define GZREAD(p, s, n, fh) fread(p, s, n, fh) +#define GZEOF(fh) feof(fh) /* this is just the redefinition of a libz constant */ #define Z_DEFAULT_COMPRESSION (-1) @@ -115,6 +117,22 @@ struct _restoreList; struct ParallelArgs; struct ParallelState; +#define READ_ERROR_EXIT(fd) \ + do { \ + if (feof(fd)) \ + exit_horribly(modulename, \ + "could not read from input file: end of file\n"); \ + else \ + exit_horribly(modulename, \ + "could not read from input file: %s\n", strerror(errno)); \ + } while (0) + +#define WRITE_ERROR_EXIT \ + do { \ + exit_horribly(modulename, "could not write to output file: %s\n", \ + strerror(errno)); \ + } while (0) + typedef enum T_Action { ACT_DUMP, @@ -126,7 +144,7 @@ typedef void (*ReopenPtr) (struct _archiveHandle * AH); typedef void (*ArchiveEntryPtr) (struct _archiveHandle * AH, struct _tocEntry * te); typedef void (*StartDataPtr) (struct _archiveHandle * AH, struct _tocEntry * te); -typedef size_t (*WriteDataPtr) (struct _archiveHandle * AH, const void *data, size_t dLen); +typedef void (*WriteDataPtr) (struct _archiveHandle * AH, const void *data, size_t dLen); typedef void (*EndDataPtr) (struct _archiveHandle * AH, struct _tocEntry * te); typedef void (*StartBlobsPtr) (struct _archiveHandle * AH, struct _tocEntry * te); @@ -136,8 +154,8 @@ typedef void (*EndBlobsPtr) (struct _archiveHandle * AH, struct _tocEntry * te); typedef int (*WriteBytePtr) (struct _archiveHandle * AH, const int i); typedef int (*ReadBytePtr) (struct _archiveHandle * AH); -typedef size_t (*WriteBufPtr) (struct _archiveHandle * AH, const void *c, size_t len); -typedef size_t (*ReadBufPtr) (struct _archiveHandle * AH, void *buf, size_t len); +typedef void (*WriteBufPtr) (struct _archiveHandle * AH, const void *c, size_t len); +typedef void (*ReadBufPtr) (struct _archiveHandle * AH, void *buf, size_t len); typedef void (*SaveArchivePtr) (struct _archiveHandle * AH); typedef void (*WriteExtraTocPtr) (struct _archiveHandle * AH, struct _tocEntry * te); typedef void (*ReadExtraTocPtr) (struct _archiveHandle * AH, struct _tocEntry * te); @@ -413,7 +431,7 @@ extern bool isValidTarHeader(char *header); extern int ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser); extern void DropBlobIfExists(ArchiveHandle *AH, Oid oid); -int ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH); +void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH); int ahprintf(ArchiveHandle *AH, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); void ahlog(ArchiveHandle *AH, int level, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c index de4f023fa7..5f3a910089 100644 --- a/src/bin/pg_dump/pg_backup_custom.c +++ b/src/bin/pg_dump/pg_backup_custom.c @@ -35,12 +35,12 @@ static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); static void _StartData(ArchiveHandle *AH, TocEntry *te); -static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); static void _EndData(ArchiveHandle *AH, TocEntry *te); static int _WriteByte(ArchiveHandle *AH, const int i); static int _ReadByte(ArchiveHandle *); -static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); -static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); static void _CloseArchive(ArchiveHandle *AH); static void _ReopenArchive(ArchiveHandle *AH); static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -86,7 +86,7 @@ typedef struct static void _readBlockHeader(ArchiveHandle *AH, int *type, int *id); static pgoff_t _getFilePos(ArchiveHandle *AH, lclContext *ctx); -static size_t _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len); +static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len); static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen); /* translator: this is a module name */ @@ -315,16 +315,17 @@ _StartData(ArchiveHandle *AH, TocEntry *te) * * Mandatory. */ -static size_t +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) { lclContext *ctx = (lclContext *) AH->formatData; CompressorState *cs = ctx->cs; - if (dLen == 0) - return 0; + if (dLen > 0) + /* WriteDataToArchive() internally throws write errors */ + WriteDataToArchive(AH, cs, data, dLen); - return WriteDataToArchive(AH, cs, data, dLen); + return; } /* @@ -579,8 +580,7 @@ _skipData(ArchiveHandle *AH) buf = (char *) pg_malloc(blkLen); buflen = blkLen; } - cnt = fread(buf, 1, blkLen, AH->FH); - if (cnt != blkLen) + if ((cnt = fread(buf, 1, blkLen, AH->FH)) != blkLen) { if (feof(AH->FH)) exit_horribly(modulename, @@ -610,14 +610,13 @@ static int _WriteByte(ArchiveHandle *AH, const int i) { lclContext *ctx = (lclContext *) AH->formatData; - int res; + int res; - res = fputc(i, AH->FH); - if (res != EOF) - ctx->filePos += 1; - else - exit_horribly(modulename, "could not write byte: %s\n", strerror(errno)); - return res; + if ((res = fputc(i, AH->FH)) == EOF) + WRITE_ERROR_EXIT; + ctx->filePos += 1; + + return 1; } /* @@ -636,7 +635,7 @@ _ReadByte(ArchiveHandle *AH) res = getc(AH->FH); if (res == EOF) - exit_horribly(modulename, "unexpected end of file\n"); + READ_ERROR_EXIT(AH->FH); ctx->filePos += 1; return res; } @@ -648,20 +647,16 @@ _ReadByte(ArchiveHandle *AH) * * Called by the archiver to write a block of bytes to the archive. */ -static size_t +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; - res = fwrite(buf, 1, len, AH->FH); + if (fwrite(buf, 1, len, AH->FH) != len) + WRITE_ERROR_EXIT; + ctx->filePos += len; - if (res != len) - exit_horribly(modulename, - "could not write to output file: %s\n", strerror(errno)); - - ctx->filePos += res; - return res; + return; } /* @@ -671,16 +666,16 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) * * Called by the archiver to read a block of bytes from the archive */ -static size_t +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; - res = fread(buf, 1, len, AH->FH); - ctx->filePos += res; + if (fread(buf, 1, len, AH->FH) != len) + READ_ERROR_EXIT(AH->FH); + ctx->filePos += len; - return res; + return; } /* @@ -959,15 +954,16 @@ _readBlockHeader(ArchiveHandle *AH, int *type, int *id) * Callback function for WriteDataToArchive. Writes one block of (compressed) * data to the archive. */ -static size_t +static void _CustomWriteFunc(ArchiveHandle *AH, const char *buf, size_t len) { /* never write 0-byte blocks (this should not happen) */ - if (len == 0) - return 0; - - WriteInt(AH, len); - return _WriteBuf(AH, buf, len); + if (len > 0) + { + WriteInt(AH, len); + _WriteBuf(AH, buf, len); + } + return; } /* @@ -978,7 +974,6 @@ static size_t _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen) { size_t blkLen; - size_t cnt; /* Read length */ blkLen = ReadInt(AH); @@ -993,15 +988,8 @@ _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen) *buflen = blkLen; } - cnt = _ReadBuf(AH, *buf, blkLen); - if (cnt != blkLen) - { - if (feof(AH->FH)) - exit_horribly(modulename, - "could not read from input file: end of file\n"); - else - exit_horribly(modulename, - "could not read from input file: %s\n", strerror(errno)); - } - return cnt; + /* exits app on read errors */ + _ReadBuf(AH, *buf, blkLen); + + return blkLen; } diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index cd2ddedada..980d68fdab 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -540,7 +540,7 @@ ExecuteSqlCommandBuf(ArchiveHandle *AH, const char *buf, size_t bufLen) } } - return 1; + return bufLen; } /* diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c index 0fae53b346..2cd9b7e9f8 100644 --- a/src/bin/pg_dump/pg_backup_directory.c +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -66,11 +66,11 @@ static const char *modulename = gettext_noop("directory archiver"); static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); static void _StartData(ArchiveHandle *AH, TocEntry *te); static void _EndData(ArchiveHandle *AH, TocEntry *te); -static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); static int _WriteByte(ArchiveHandle *AH, const int i); static int _ReadByte(ArchiveHandle *); -static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); -static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); static void _CloseArchive(ArchiveHandle *AH); static void _ReopenArchive(ArchiveHandle *AH); static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -350,18 +350,18 @@ _StartData(ArchiveHandle *AH, TocEntry *te) * * We write the data to the open data file. */ -static size_t +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) { lclContext *ctx = (lclContext *) AH->formatData; - if (dLen == 0) - return 0; - /* Are we aborting? */ checkAborting(AH); + + if (dLen > 0 && cfwrite(data, dLen, ctx->dataFH) != dLen) + WRITE_ERROR_EXIT; - return cfwrite(data, dLen, ctx->dataFH); + return; } /* @@ -408,7 +408,7 @@ _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt) ahwrite(buf, 1, cnt, AH); free(buf); - if (cfclose(cfp) !=0) + if (cfclose(cfp) != 0) exit_horribly(modulename, "could not close data file: %s\n", strerror(errno)); } @@ -495,7 +495,7 @@ _WriteByte(ArchiveHandle *AH, const int i) lclContext *ctx = (lclContext *) AH->formatData; if (cfwrite(&c, 1, ctx->dataFH) != 1) - exit_horribly(modulename, "could not write byte\n"); + WRITE_ERROR_EXIT; return 1; } @@ -510,34 +510,26 @@ static int _ReadByte(ArchiveHandle *AH) { lclContext *ctx = (lclContext *) AH->formatData; - int res; - res = cfgetc(ctx->dataFH); - if (res == EOF) - exit_horribly(modulename, "unexpected end of file\n"); - - return res; + return cfgetc(ctx->dataFH); } /* * Write a buffer of data to the archive. * Called by the archiver to write a block of bytes to the TOC or a data file. */ -static size_t +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; /* Are we aborting? */ checkAborting(AH); - res = cfwrite(buf, len, ctx->dataFH); - if (res != len) - exit_horribly(modulename, "could not write to output file: %s\n", - strerror(errno)); + if (cfwrite(buf, len, ctx->dataFH) != len) + WRITE_ERROR_EXIT; - return res; + return; } /* @@ -545,15 +537,20 @@ _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) * * Called by the archiver to read a block of bytes from the archive */ -static size_t +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; - res = cfread(buf, len, ctx->dataFH); + /* + * If there was an I/O error, we already exited in cfread(), + * so here we exit on short reads. + */ + if (cfread(buf, len, ctx->dataFH) != len) + exit_horribly(modulename, + "could not read from input file: end of file\n"); - return res; + return; } /* diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c index c321068b4e..3bce5885d0 100644 --- a/src/bin/pg_dump/pg_backup_null.c +++ b/src/bin/pg_dump/pg_backup_null.c @@ -30,12 +30,11 @@ #include "libpq/libpq-fs.h" - -static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); -static size_t _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen); static void _EndData(ArchiveHandle *AH, TocEntry *te); static int _WriteByte(ArchiveHandle *AH, const int i); -static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); static void _CloseArchive(ArchiveHandle *AH); static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _StartBlobs(ArchiveHandle *AH, TocEntry *te); @@ -84,19 +83,19 @@ InitArchiveFmt_Null(ArchiveHandle *AH) /* * Called by dumper via archiver from within a data dump routine */ -static size_t +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) { - /* Just send it to output */ + /* Just send it to output, ahwrite() already errors on failure */ ahwrite(data, 1, dLen, AH); - return dLen; + return; } /* * Called by dumper via archiver from within a data dump routine * We substitute this for _WriteData while emitting a BLOB */ -static size_t +static void _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen) { if (dLen > 0) @@ -112,7 +111,7 @@ _WriteBlobData(ArchiveHandle *AH, const void *data, size_t dLen) destroyPQExpBuffer(buf); } - return dLen; + return; } static void @@ -220,11 +219,11 @@ _WriteByte(ArchiveHandle *AH, const int i) return 0; } -static size_t +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) { /* Don't do anything */ - return len; + return; } static void diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 3bdbf86818..f505393057 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -42,12 +42,12 @@ static void _ArchiveEntry(ArchiveHandle *AH, TocEntry *te); static void _StartData(ArchiveHandle *AH, TocEntry *te); -static size_t _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen); static void _EndData(ArchiveHandle *AH, TocEntry *te); static int _WriteByte(ArchiveHandle *AH, const int i); static int _ReadByte(ArchiveHandle *); -static size_t _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); -static size_t _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len); +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len); static void _CloseArchive(ArchiveHandle *AH); static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te); @@ -548,13 +548,26 @@ _tarReadRaw(ArchiveHandle *AH, void *buf, size_t len, TAR_MEMBER *th, FILE *fh) if (len > 0) { if (fh) + { res = fread(&((char *) buf)[used], 1, len, fh); + if (res != len && !feof(fh)) + READ_ERROR_EXIT(fh); + } else if (th) { if (th->zFH) + { res = GZREAD(&((char *) buf)[used], 1, len, th->zFH); + if (res != len && !GZEOF(fh)) + exit_horribly(modulename, + "could not read from input file: %s\n", strerror(errno)); + } else + { res = fread(&((char *) buf)[used], 1, len, th->nFH); + if (res != len && !feof(fh)) + READ_ERROR_EXIT(fh); + } } else exit_horribly(modulename, "internal error -- neither th nor fh specified in tarReadRaw()\n"); @@ -593,22 +606,19 @@ tarWrite(const void *buf, size_t len, TAR_MEMBER *th) else res = fwrite(buf, 1, len, th->nFH); - if (res != len) - exit_horribly(modulename, - "could not write to output file: %s\n", strerror(errno)); - th->pos += res; return res; } -static size_t +static void _WriteData(ArchiveHandle *AH, const void *data, size_t dLen) { lclTocEntry *tctx = (lclTocEntry *) AH->currToc->formatData; - dLen = tarWrite(data, dLen, tctx->TH); + if (tarWrite(data, dLen, tctx->TH) != dLen) + WRITE_ERROR_EXIT; - return dLen; + return; } static void @@ -766,13 +776,13 @@ static int _WriteByte(ArchiveHandle *AH, const int i) { lclContext *ctx = (lclContext *) AH->formatData; - int res; char b = i; /* Avoid endian problems */ - res = tarWrite(&b, 1, ctx->FH); - if (res != EOF) - ctx->filePos += res; - return res; + if (tarWrite(&b, 1, ctx->FH) != 1) + WRITE_ERROR_EXIT; + + ctx->filePos += 1; + return 1; } static int @@ -784,31 +794,36 @@ _ReadByte(ArchiveHandle *AH) res = tarRead(&c, 1, ctx->FH); if (res != 1) - exit_horribly(modulename, "unexpected end of file\n"); + /* We already would have exited for errors on reads, must be EOF */ + exit_horribly(modulename, + "could not read from input file: end of file\n"); ctx->filePos += 1; return c; } -static size_t +static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; - res = tarWrite(buf, len, ctx->FH); - ctx->filePos += res; - return res; + if (tarWrite(buf, len, ctx->FH) != len) + WRITE_ERROR_EXIT; + + ctx->filePos += len; } -static size_t +static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len) { lclContext *ctx = (lclContext *) AH->formatData; - size_t res; - res = tarRead(buf, len, ctx->FH); - ctx->filePos += res; - return res; + if (tarRead(buf, len, ctx->FH) != len) + /* We already would have exited for errors on reads, must be EOF */ + exit_horribly(modulename, + "could not read from input file: end of file\n"); + + ctx->filePos += len; + return; } static void @@ -885,8 +900,7 @@ _CloseArchive(ArchiveHandle *AH) for (i = 0; i < 512 * 2; i++) { if (fputc(0, ctx->tarFH) == EOF) - exit_horribly(modulename, - "could not write null block at end of tar archive\n"); + WRITE_ERROR_EXIT; } } @@ -1084,13 +1098,12 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th) while ((cnt = fread(buf, 1, sizeof(buf), tmp)) > 0) { - res = fwrite(buf, 1, cnt, th->tarFH); - if (res != cnt) - exit_horribly(modulename, - "could not write to output file: %s\n", - strerror(errno)); + if ((res = fwrite(buf, 1, cnt, th->tarFH)) != cnt) + WRITE_ERROR_EXIT; len += res; } + if (!feof(tmp)) + READ_ERROR_EXIT(tmp); if (fclose(tmp) != 0) /* This *should* delete it... */ exit_horribly(modulename, "could not close temporary file: %s\n", @@ -1111,7 +1124,7 @@ _tarAddFile(ArchiveHandle *AH, TAR_MEMBER *th) for (i = 0; i < pad; i++) { if (fputc('\0', th->tarFH) == EOF) - exit_horribly(modulename, "could not output padding at end of tar member\n"); + WRITE_ERROR_EXIT; } ctx->tarFHpos += len + pad; @@ -1294,5 +1307,5 @@ _tarWriteHeader(TAR_MEMBER *th) /* Now write the completed header. */ if (fwrite(h, 1, 512, th->tarFH) != 512) - exit_horribly(modulename, "could not write to output file: %s\n", strerror(errno)); + WRITE_ERROR_EXIT; } -- 2.40.0