Hi Alvaro, On Thu, Mar 01, 2018 at 04:00:52PM -0300, Alvaro Herrera wrote: > strdup -> pg_strdup()
Fixed. > I wonder if, instead of doing strcmp() all over the place, we should > give this behavior a separate boolean flag in lclContext. I mused a bit about what to name that flag and came up with `discard', but maybe somebody has a better idea? In any case, new patch attached which does this. Michael -- Michael Banck Projektleiter / Senior Berater Tel.: +49 2166 9901-171 Fax: +49 2166 9901-100 Email: michael.ba...@credativ.de credativ GmbH, HRB Mönchengladbach 12080 USt-ID-Nummer: DE204566209 Trompeterallee 108, 41189 Mönchengladbach Geschäftsführung: Dr. Michael Meskes, Jörg Folz, Sascha Heuer
diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c index a96da15dc1..8657ac30e6 100644 --- a/src/bin/pg_dump/compress_io.c +++ b/src/bin/pg_dump/compress_io.c @@ -512,7 +512,10 @@ cfopen_write(const char *path, const char *mode, int compression) #ifdef HAVE_LIBZ char *fname; - fname = psprintf("%s.gz", path); + if (strcmp(path, NULL_DEVICE) != 0) + fname = psprintf("%s.gz", path); + else + fname = pg_strdup(path); fp = cfopen(fname, mode, compression); free_keep_errno(fname); #else diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 8dd1915998..ab17adbc62 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -62,6 +62,13 @@ typedef struct _z_stream typedef z_stream *z_streamp; #endif +/* Null device */ +#ifdef WIN32 +#define NULL_DEVICE "NUL" +#else +#define NULL_DEVICE "/dev/null" +#endif + /* Data block types */ #define BLK_DATA 1 #define BLK_BLOBS 3 diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c index 4aabb40f59..5936a799c7 100644 --- a/src/bin/pg_dump/pg_backup_directory.c +++ b/src/bin/pg_dump/pg_backup_directory.c @@ -54,6 +54,7 @@ typedef struct cfp *blobsTocFH; /* file handle for blobs.toc */ ParallelState *pstate; /* for parallel backup / restore */ + int discard; /* target is NULL_DEVICE */ } lclContext; typedef struct @@ -158,6 +159,11 @@ InitArchiveFmt_Directory(ArchiveHandle *AH) ctx->directory = AH->fSpec; + if (strcmp(ctx->directory, NULL_DEVICE) == 0) + ctx->discard = 1; + else + ctx->discard = 0; + if (AH->mode == archModeWrite) { struct stat st; @@ -192,9 +198,15 @@ InitArchiveFmt_Directory(ArchiveHandle *AH) } } - if (!is_empty && mkdir(ctx->directory, 0700) < 0) - exit_horribly(modulename, "could not create directory \"%s\": %s\n", - ctx->directory, strerror(errno)); + /* + * Create the output directory, unless it exists already and is empty. + * If we are discarding output to the null device, we must not + * create it. + */ + if (!is_empty && !ctx->discard) + if (mkdir(ctx->directory, 0711) < 0) + exit_horribly(modulename, "could not create directory \"%s\": %s\n", + ctx->directory, strerror(errno)); } else { /* Read Mode */ @@ -602,8 +614,10 @@ _CloseArchive(ArchiveHandle *AH) /* * In directory mode, there is no need to sync all the entries * individually. Just recurse once through all the files generated. + * If we are discarding output to the null device, it does not + * need syncing and would emit a warning if we did. */ - if (AH->dosync) + if (AH->dosync && !ctx->discard) fsync_dir_recurse(ctx->directory, progname); } AH->FH = NULL; @@ -659,7 +673,14 @@ _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid) lclContext *ctx = (lclContext *) AH->formatData; char fname[MAXPGPATH]; - snprintf(fname, MAXPGPATH, "%s/blob_%u.dat", ctx->directory, oid); + /* + * If we are discarding output to the null device, just use that as + * fname. + */ + if (ctx->discard) + snprintf(fname, MAXPGPATH, NULL_DEVICE); + else + snprintf(fname, MAXPGPATH, "%s/blob_%u.dat", ctx->directory, oid); ctx->dataFH = cfopen_write(fname, PG_BINARY_W, AH->compression); @@ -721,9 +742,18 @@ setFilePath(ArchiveHandle *AH, char *buf, const char *relativeFilename) if (strlen(dname) + 1 + strlen(relativeFilename) + 1 > MAXPGPATH) exit_horribly(modulename, "file name too long: \"%s\"\n", dname); - strcpy(buf, dname); - strcat(buf, "/"); - strcat(buf, relativeFilename); + /* + * If we are discarding output to the null device, we cannot set a file + * path and just set the buffer to the null device. + */ + if (ctx->discard) + { + strcpy(buf, NULL_DEVICE); + } else { + strcpy(buf, dname); + strcat(buf, "/"); + strcat(buf, relativeFilename); + } } /*