1 /*-------------------------------------------------------------------------
2 *
3 * archive.c
4 * Common WAL archive routines
5 *
6 * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/common/archive.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16 #ifndef FRONTEND
17 #include "postgres.h"
18 #else
19 #include "postgres_fe.h"
20 #endif
21
22 #include "common/archive.h"
23 #include "lib/stringinfo.h"
24
25 /*
26 * BuildRestoreCommand
27 *
28 * Builds a restore command to retrieve a file from WAL archives, replacing
29 * the supported aliases with values supplied by the caller as defined by
30 * the GUC parameter restore_command: xlogpath for %p, xlogfname for %f and
31 * lastRestartPointFname for %r.
32 *
33 * The result is a palloc'd string for the restore command built. The
34 * caller is responsible for freeing it. If any of the required arguments
35 * is NULL and that the corresponding alias is found in the command given
36 * by the caller, then NULL is returned.
37 */
38 char *
BuildRestoreCommand(const char * restoreCommand,const char * xlogpath,const char * xlogfname,const char * lastRestartPointFname)39 BuildRestoreCommand(const char *restoreCommand,
40 const char *xlogpath,
41 const char *xlogfname,
42 const char *lastRestartPointFname)
43 {
44 StringInfoData result;
45 const char *sp;
46
47 /*
48 * Build the command to be executed.
49 */
50 initStringInfo(&result);
51
52 for (sp = restoreCommand; *sp; sp++)
53 {
54 if (*sp == '%')
55 {
56 switch (sp[1])
57 {
58 case 'p':
59 {
60 char *nativePath;
61
62 /* %p: relative path of target file */
63 if (xlogpath == NULL)
64 {
65 pfree(result.data);
66 return NULL;
67 }
68 sp++;
69
70 /*
71 * This needs to use a placeholder to not modify the
72 * input with the conversion done via
73 * make_native_path().
74 */
75 nativePath = pstrdup(xlogpath);
76 make_native_path(nativePath);
77 appendStringInfoString(&result,
78 nativePath);
79 pfree(nativePath);
80 break;
81 }
82 case 'f':
83 /* %f: filename of desired file */
84 if (xlogfname == NULL)
85 {
86 pfree(result.data);
87 return NULL;
88 }
89 sp++;
90 appendStringInfoString(&result, xlogfname);
91 break;
92 case 'r':
93 /* %r: filename of last restartpoint */
94 if (lastRestartPointFname == NULL)
95 {
96 pfree(result.data);
97 return NULL;
98 }
99 sp++;
100 appendStringInfoString(&result,
101 lastRestartPointFname);
102 break;
103 case '%':
104 /* convert %% to a single % */
105 sp++;
106 appendStringInfoChar(&result, *sp);
107 break;
108 default:
109 /* otherwise treat the % as not special */
110 appendStringInfoChar(&result, *sp);
111 break;
112 }
113 }
114 else
115 {
116 appendStringInfoChar(&result, *sp);
117 }
118 }
119
120 return result.data;
121 }
122