Skip to content

Commit f831d4a

Browse files
committed
Add ArchiveOpts to pass options to ArchiveEntry
The ArchiveEntry function has a number of arguments that can be considered optional. Split them out into a separate struct, to make the API more flexible for changes. Author: Dmitry Dolgov Discussion: https://postgr.es/m/CA+q6zcXRxPE+qp6oerQWJ3zS061WPOhdxeMrdc-Yf-2V5vsrEw@mail.gmail.com
1 parent 456e371 commit f831d4a

File tree

3 files changed

+522
-577
lines changed

3 files changed

+522
-577
lines changed

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 50 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
7777
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
7878
ArchiveHandle *AH);
7979
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData);
80-
static char *replace_line_endings(const char *str);
80+
static char *sanitize_line(const char *str, bool want_hyphen);
8181
static void _doSetFixedOutputState(ArchiveHandle *AH);
8282
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
8383
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
@@ -1066,17 +1066,8 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
10661066

10671067
/* Public */
10681068
TocEntry *
1069-
ArchiveEntry(Archive *AHX,
1070-
CatalogId catalogId, DumpId dumpId,
1071-
const char *tag,
1072-
const char *namespace,
1073-
const char *tablespace,
1074-
const char *owner,
1075-
const char *desc, teSection section,
1076-
const char *defn,
1077-
const char *dropStmt, const char *copyStmt,
1078-
const DumpId *deps, int nDeps,
1079-
DataDumperPtr dumpFn, void *dumpArg)
1069+
ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId,
1070+
ArchiveOpts *opts)
10801071
{
10811072
ArchiveHandle *AH = (ArchiveHandle *) AHX;
10821073
TocEntry *newToc;
@@ -1094,32 +1085,32 @@ ArchiveEntry(Archive *AHX,
10941085

10951086
newToc->catalogId = catalogId;
10961087
newToc->dumpId = dumpId;
1097-
newToc->section = section;
1098-
1099-
newToc->tag = pg_strdup(tag);
1100-
newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
1101-
newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
1102-
newToc->owner = pg_strdup(owner);
1103-
newToc->desc = pg_strdup(desc);
1104-
newToc->defn = pg_strdup(defn);
1105-
newToc->dropStmt = pg_strdup(dropStmt);
1106-
newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
1107-
1108-
if (nDeps > 0)
1088+
newToc->section = opts->section;
1089+
1090+
newToc->tag = pg_strdup(opts->tag);
1091+
newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1092+
newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1093+
newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1094+
newToc->desc = pg_strdup(opts->description);
1095+
newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1096+
newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1097+
newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1098+
1099+
if (opts->nDeps > 0)
11091100
{
1110-
newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
1111-
memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
1112-
newToc->nDeps = nDeps;
1101+
newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
1102+
memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1103+
newToc->nDeps = opts->nDeps;
11131104
}
11141105
else
11151106
{
11161107
newToc->dependencies = NULL;
11171108
newToc->nDeps = 0;
11181109
}
11191110

1120-
newToc->dataDumper = dumpFn;
1121-
newToc->dataDumperArg = dumpArg;
1122-
newToc->hadDumper = dumpFn ? true : false;
1111+
newToc->dataDumper = opts->dumpFn;
1112+
newToc->dataDumperArg = opts->dumpArg;
1113+
newToc->hadDumper = opts->dumpFn ? true : false;
11231114

11241115
newToc->formatData = NULL;
11251116
newToc->dataLength = 0;
@@ -1152,7 +1143,7 @@ PrintTOCSummary(Archive *AHX)
11521143

11531144
ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
11541145
ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
1155-
replace_line_endings(AH->archdbname),
1146+
sanitize_line(AH->archdbname, false),
11561147
AH->tocCount, AH->compression);
11571148

11581149
switch (AH->format)
@@ -1197,21 +1188,10 @@ PrintTOCSummary(Archive *AHX)
11971188
char *sanitized_owner;
11981189

11991190
/*
1200-
* As in _printTocEntry(), sanitize strings that might contain
1201-
* newlines, to ensure that each logical output line is in fact
1202-
* one physical output line. This prevents confusion when the
1203-
* file is read by "pg_restore -L". Note that we currently don't
1204-
* bother to quote names, meaning that the name fields aren't
1205-
* automatically parseable. "pg_restore -L" doesn't care because
1206-
* it only examines the dumpId field, but someday we might want to
1207-
* try harder.
12081191
*/
1209-
sanitized_name = replace_line_endings(te->tag);
1210-
if (te->namespace)
1211-
sanitized_schema = replace_line_endings(te->namespace);
1212-
else
1213-
sanitized_schema = pg_strdup("-");
1214-
sanitized_owner = replace_line_endings(te->owner);
1192+
sanitized_name = sanitize_line(te->tag, false);
1193+
sanitized_schema = sanitize_line(te->namespace, true);
1194+
sanitized_owner = sanitize_line(te->owner, false);
12151195

12161196
ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
12171197
te->catalogId.tableoid, te->catalogId.oid,
@@ -3577,21 +3557,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
35773557
}
35783558
}
35793559

3580-
/*
3581-
* Zap any line endings embedded in user-supplied fields, to prevent
3582-
* corruption of the dump (which could, in the worst case, present an
3583-
* SQL injection vulnerability if someone were to incautiously load a
3584-
* dump containing objects with maliciously crafted names).
3585-
*/
3586-
sanitized_name = replace_line_endings(te->tag);
3587-
if (te->namespace)
3588-
sanitized_schema = replace_line_endings(te->namespace);
3589-
else
3590-
sanitized_schema = pg_strdup("-");
3591-
if (!ropt->noOwner)
3592-
sanitized_owner = replace_line_endings(te->owner);
3593-
else
3594-
sanitized_owner = pg_strdup("-");
3560+
sanitized_name = sanitize_line(te->tag, false);
3561+
sanitized_schema = sanitize_line(te->namespace, true);
3562+
sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
35953563

35963564
ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
35973565
pfx, sanitized_name, te->desc, sanitized_schema,
@@ -3605,7 +3573,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
36053573
{
36063574
char *sanitized_tablespace;
36073575

3608-
sanitized_tablespace = replace_line_endings(te->tablespace);
3576+
sanitized_tablespace = sanitize_line(te->tablespace, false);
36093577
ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
36103578
free(sanitized_tablespace);
36113579
}
@@ -3629,7 +3597,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
36293597
}
36303598
else
36313599
{
3632-
if (strlen(te->defn) > 0)
3600+
if (te->defn && strlen(te->defn) > 0)
36333601
ahprintf(AH, "%s\n\n", te->defn);
36343602
}
36353603

@@ -3640,7 +3608,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
36403608
* with DROP commands must appear in one list or the other.
36413609
*/
36423610
if (!ropt->noOwner && !ropt->use_setsessauth &&
3643-
strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
3611+
te->owner && strlen(te->owner) > 0 &&
3612+
te->dropStmt && strlen(te->dropStmt) > 0)
36443613
{
36453614
if (strcmp(te->desc, "AGGREGATE") == 0 ||
36463615
strcmp(te->desc, "BLOB") == 0 ||
@@ -3713,16 +3682,30 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
37133682
}
37143683

37153684
/*
3716-
* Sanitize a string to be included in an SQL comment or TOC listing,
3717-
* by replacing any newlines with spaces.
3718-
* The result is a freshly malloc'd string.
3685+
* Sanitize a string to be included in an SQL comment or TOC listing, by
3686+
* replacing any newlines with spaces. This ensures each logical output line
3687+
* is in fact one physical output line, to prevent corruption of the dump
3688+
* (which could, in the worst case, present an SQL injection vulnerability
3689+
* if someone were to incautiously load a dump containing objects with
3690+
* maliciously crafted names).
3691+
*
3692+
* The result is a freshly malloc'd string. If the input string is NULL,
3693+
* return a malloc'ed empty string, unless want_hyphen, in which case return a
3694+
* malloc'ed hyphen.
3695+
*
3696+
* Note that we currently don't bother to quote names, meaning that the name
3697+
* fields aren't automatically parseable. "pg_restore -L" doesn't care because
3698+
* it only examines the dumpId field, but someday we might want to try harder.
37193699
*/
37203700
static char *
3721-
replace_line_endings(const char *str)
3701+
sanitize_line(const char *str, bool want_hyphen)
37223702
{
37233703
char *result;
37243704
char *s;
37253705

3706+
if (!str)
3707+
return pg_strdup(want_hyphen ? "-" : "");
3708+
37263709
result = pg_strdup(str);
37273710

37283711
for (s = result; *s != '\0'; s++)

src/bin/pg_dump/pg_backup_archiver.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -405,17 +405,27 @@ extern void on_exit_close_archive(Archive *AHX);
405405

406406
extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) pg_attribute_printf(3, 4);
407407

408+
/* Options for ArchiveEntry */
409+
typedef struct _archiveOpts
410+
{
411+
const char *tag;
412+
const char *namespace;
413+
const char *tablespace;
414+
const char *owner;
415+
const char *description;
416+
teSection section;
417+
const char *createStmt;
418+
const char *dropStmt;
419+
const char *copyStmt;
420+
const DumpId *deps;
421+
int nDeps;
422+
DataDumperPtr dumpFn;
423+
void *dumpArg;
424+
} ArchiveOpts;
425+
#define ARCHIVE_OPTS(...) &(ArchiveOpts){__VA_ARGS__}
408426
/* Called to add a TOC entry */
409-
extern TocEntry *ArchiveEntry(Archive *AHX,
410-
CatalogId catalogId, DumpId dumpId,
411-
const char *tag,
412-
const char *namespace, const char *tablespace,
413-
const char *owner,
414-
const char *desc, teSection section,
415-
const char *defn,
416-
const char *dropStmt, const char *copyStmt,
417-
const DumpId *deps, int nDeps,
418-
DataDumperPtr dumpFn, void *dumpArg);
427+
extern TocEntry *ArchiveEntry(Archive *AHX, CatalogId catalogId,
428+
DumpId dumpId, ArchiveOpts *opts);
419429

420430
extern void WriteTOC(ArchiveHandle *AH);
421431
extern void ReadTOC(ArchiveHandle *AH);

0 commit comments

Comments
 (0)