aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/transam/xlogarchive.c66
-rw-r--r--src/common/Makefile1
-rw-r--r--src/common/archive.c121
-rw-r--r--src/include/common/archive.h21
-rw-r--r--src/tools/msvc/Mkvcbuild.pm1
5 files changed, 154 insertions, 56 deletions
diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c
index 188b73e7526..914ad340eae 100644
--- a/src/backend/access/transam/xlogarchive.c
+++ b/src/backend/access/transam/xlogarchive.c
@@ -21,6 +21,7 @@
#include "access/xlog.h"
#include "access/xlog_internal.h"
+#include "common/archive.h"
#include "miscadmin.h"
#include "postmaster/startup.h"
#include "replication/walsender.h"
@@ -53,11 +54,8 @@ RestoreArchivedFile(char *path, const char *xlogfname,
bool cleanupEnabled)
{
char xlogpath[MAXPGPATH];
- char xlogRestoreCmd[MAXPGPATH];
+ char *xlogRestoreCmd;
char lastRestartPointFname[MAXPGPATH];
- char *dp;
- char *endp;
- const char *sp;
int rc;
struct stat stat_buf;
XLogSegNo restartSegNo;
@@ -149,58 +147,13 @@ RestoreArchivedFile(char *path, const char *xlogfname,
else
XLogFileName(lastRestartPointFname, 0, 0L, wal_segment_size);
- /*
- * construct the command to be executed
- */
- dp = xlogRestoreCmd;
- endp = xlogRestoreCmd + MAXPGPATH - 1;
- *endp = '\0';
-
- for (sp = recoveryRestoreCommand; *sp; sp++)
- {
- if (*sp == '%')
- {
- switch (sp[1])
- {
- case 'p':
- /* %p: relative path of target file */
- sp++;
- StrNCpy(dp, xlogpath, endp - dp);
- make_native_path(dp);
- dp += strlen(dp);
- break;
- case 'f':
- /* %f: filename of desired file */
- sp++;
- StrNCpy(dp, xlogfname, endp - dp);
- dp += strlen(dp);
- break;
- case 'r':
- /* %r: filename of last restartpoint */
- sp++;
- StrNCpy(dp, lastRestartPointFname, endp - dp);
- dp += strlen(dp);
- break;
- case '%':
- /* convert %% to a single % */
- sp++;
- if (dp < endp)
- *dp++ = *sp;
- break;
- default:
- /* otherwise treat the % as not special */
- if (dp < endp)
- *dp++ = *sp;
- break;
- }
- }
- else
- {
- if (dp < endp)
- *dp++ = *sp;
- }
- }
- *dp = '\0';
+ /* Build the restore command to execute */
+ xlogRestoreCmd = BuildRestoreCommand(recoveryRestoreCommand,
+ xlogpath, xlogfname,
+ lastRestartPointFname);
+ if (xlogRestoreCmd == NULL)
+ elog(ERROR, "could not build restore command \"%s\"",
+ recoveryRestoreCommand);
ereport(DEBUG3,
(errmsg_internal("executing restore command \"%s\"",
@@ -217,6 +170,7 @@ RestoreArchivedFile(char *path, const char *xlogfname,
rc = system(xlogRestoreCmd);
PostRestoreCommand();
+ pfree(xlogRestoreCmd);
if (rc == 0)
{
diff --git a/src/common/Makefile b/src/common/Makefile
index ce01df68b97..6939b9d0874 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -46,6 +46,7 @@ LIBS += $(PTHREAD_LIBS)
# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
OBJS_COMMON = \
+ archive.o \
base64.o \
config_info.o \
controldata_utils.o \
diff --git a/src/common/archive.c b/src/common/archive.c
new file mode 100644
index 00000000000..a94e4d0a5eb
--- /dev/null
+++ b/src/common/archive.c
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.c
+ * Common WAL archive routines
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/archive.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/archive.h"
+#include "lib/stringinfo.h"
+
+/*
+ * BuildRestoreCommand
+ *
+ * Builds a restore command to retrieve a file from WAL archives, replacing
+ * the supported aliases with values supplied by the caller as defined by
+ * the GUC parameter restore_command: xlogpath for %p, xlogfname for %f and
+ * lastRestartPointFname for %r.
+ *
+ * The result is a palloc'd string for the restore command built. The
+ * caller is responsible for freeing it. If any of the required arguments
+ * is NULL and that the corresponding alias is found in the command given
+ * by the caller, then NULL is returned.
+ */
+char *
+BuildRestoreCommand(const char *restoreCommand,
+ const char *xlogpath,
+ const char *xlogfname,
+ const char *lastRestartPointFname)
+{
+ StringInfoData result;
+ const char *sp;
+
+ /*
+ * Build the command to be executed.
+ */
+ initStringInfo(&result);
+
+ for (sp = restoreCommand; *sp; sp++)
+ {
+ if (*sp == '%')
+ {
+ switch (sp[1])
+ {
+ case 'p':
+ {
+ char *nativePath;
+
+ /* %p: relative path of target file */
+ if (xlogpath == NULL)
+ {
+ pfree(result.data);
+ return NULL;
+ }
+ sp++;
+
+ /*
+ * This needs to use a placeholder to not modify the
+ * input with the conversion done via
+ * make_native_path().
+ */
+ nativePath = pstrdup(xlogpath);
+ make_native_path(nativePath);
+ appendStringInfoString(&result,
+ nativePath);
+ pfree(nativePath);
+ break;
+ }
+ case 'f':
+ /* %f: filename of desired file */
+ if (xlogfname == NULL)
+ {
+ pfree(result.data);
+ return NULL;
+ }
+ sp++;
+ appendStringInfoString(&result, xlogfname);
+ break;
+ case 'r':
+ /* %r: filename of last restartpoint */
+ if (lastRestartPointFname == NULL)
+ {
+ pfree(result.data);
+ return NULL;
+ }
+ sp++;
+ appendStringInfoString(&result,
+ lastRestartPointFname);
+ break;
+ case '%':
+ /* convert %% to a single % */
+ sp++;
+ appendStringInfoChar(&result, *sp);
+ break;
+ default:
+ /* otherwise treat the % as not special */
+ appendStringInfoChar(&result, *sp);
+ break;
+ }
+ }
+ else
+ {
+ appendStringInfoChar(&result, *sp);
+ }
+ }
+
+ return result.data;
+}
diff --git a/src/include/common/archive.h b/src/include/common/archive.h
new file mode 100644
index 00000000000..b269910f03c
--- /dev/null
+++ b/src/include/common/archive.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * archive.h
+ * Common WAL archive routines
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/archive.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ARCHIVE_H
+#define ARCHIVE_H
+
+extern char *BuildRestoreCommand(const char *restoreCommand,
+ const char *xlogpath, /* %p */
+ const char *xlogfname, /* %f */
+ const char *lastRestartPointFname); /* %r */
+
+#endif /* ARCHIVE_H */
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index f89a8a4fdb7..636428b0448 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -120,6 +120,7 @@ sub mkvcbuild
}
our @pgcommonallfiles = qw(
+ archive.c
base64.c config_info.c controldata_utils.c d2s.c encnames.c exec.c
f2s.c file_perm.c hashfn.c ip.c jsonapi.c
keywords.c kwlookup.c link-canary.c md5.c