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: [email protected]
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);
+ }
}
/*