1 /*-------------------------------------------------------------------------
2  *
3  * pg_basebackup.c - receive a base backup using streaming replication protocol
4  *
5  * Author: Magnus Hagander <magnus@hagander.net>
6  *
7  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
8  *
9  * IDENTIFICATION
10  *		  src/bin/pg_basebackup/pg_basebackup.c
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "postgres_fe.h"
15 
16 #include <unistd.h>
17 #include <dirent.h>
18 #include <sys/stat.h>
19 #include <sys/wait.h>
20 #include <signal.h>
21 #include <time.h>
22 #ifdef HAVE_SYS_SELECT_H
23 #include <sys/select.h>
24 #endif
25 #ifdef HAVE_LIBZ
26 #include <zlib.h>
27 #endif
28 
29 #include "access/xlog_internal.h"
30 #include "common/file_perm.h"
31 #include "common/file_utils.h"
32 #include "common/logging.h"
33 #include "common/string.h"
34 #include "fe_utils/string_utils.h"
35 #include "getopt_long.h"
36 #include "libpq-fe.h"
37 #include "pqexpbuffer.h"
38 #include "pgtar.h"
39 #include "pgtime.h"
40 #include "receivelog.h"
41 #include "replication/basebackup.h"
42 #include "streamutil.h"
43 
44 #define ERRCODE_DATA_CORRUPTED	"XX001"
45 
46 typedef struct TablespaceListCell
47 {
48 	struct TablespaceListCell *next;
49 	char		old_dir[MAXPGPATH];
50 	char		new_dir[MAXPGPATH];
51 } TablespaceListCell;
52 
53 typedef struct TablespaceList
54 {
55 	TablespaceListCell *head;
56 	TablespaceListCell *tail;
57 } TablespaceList;
58 
59 /*
60  * pg_xlog has been renamed to pg_wal in version 10.  This version number
61  * should be compared with PQserverVersion().
62  */
63 #define MINIMUM_VERSION_FOR_PG_WAL	100000
64 
65 /*
66  * Temporary replication slots are supported from version 10.
67  */
68 #define MINIMUM_VERSION_FOR_TEMP_SLOTS 100000
69 
70 /*
71  * recovery.conf is integrated into postgresql.conf from version 12.
72  */
73 #define MINIMUM_VERSION_FOR_RECOVERY_GUC 120000
74 
75 /*
76  * Different ways to include WAL
77  */
78 typedef enum
79 {
80 	NO_WAL,
81 	FETCH_WAL,
82 	STREAM_WAL
83 } IncludeWal;
84 
85 /* Global options */
86 static char *basedir = NULL;
87 static TablespaceList tablespace_dirs = {NULL, NULL};
88 static char *xlog_dir = NULL;
89 static char format = 'p';		/* p(lain)/t(ar) */
90 static char *label = "pg_basebackup base backup";
91 static bool noclean = false;
92 static bool checksum_failure = false;
93 static bool showprogress = false;
94 static int	verbose = 0;
95 static int	compresslevel = 0;
96 static IncludeWal includewal = STREAM_WAL;
97 static bool fastcheckpoint = false;
98 static bool writerecoveryconf = false;
99 static bool do_sync = true;
100 static int	standby_message_timeout = 10 * 1000;	/* 10 sec = default */
101 static pg_time_t last_progress_report = 0;
102 static int32 maxrate = 0;		/* no limit by default */
103 static char *replication_slot = NULL;
104 static bool temp_replication_slot = true;
105 static bool create_slot = false;
106 static bool no_slot = false;
107 static bool verify_checksums = true;
108 
109 static bool success = false;
110 static bool made_new_pgdata = false;
111 static bool found_existing_pgdata = false;
112 static bool made_new_xlogdir = false;
113 static bool found_existing_xlogdir = false;
114 static bool made_tablespace_dirs = false;
115 static bool found_tablespace_dirs = false;
116 
117 /* Progress counters */
118 static uint64 totalsize;
119 static uint64 totaldone;
120 static int	tablespacecount;
121 
122 /* Pipe to communicate with background wal receiver process */
123 #ifndef WIN32
124 static int	bgpipe[2] = {-1, -1};
125 #endif
126 
127 /* Handle to child process */
128 static pid_t bgchild = -1;
129 static bool in_log_streamer = false;
130 
131 /* End position for xlog streaming, empty string if unknown yet */
132 static XLogRecPtr xlogendptr;
133 
134 #ifndef WIN32
135 static int	has_xlogendptr = 0;
136 #else
137 static volatile LONG has_xlogendptr = 0;
138 #endif
139 
140 /* Contents of configuration file to be generated */
141 static PQExpBuffer recoveryconfcontents = NULL;
142 
143 /* Function headers */
144 static void usage(void);
145 static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found);
146 static void progress_report(int tablespacenum, const char *filename, bool force,
147 							bool finished);
148 
149 static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum);
150 static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum);
151 static void GenerateRecoveryConf(PGconn *conn);
152 static void WriteRecoveryConf(void);
153 static void BaseBackup(void);
154 
155 static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline,
156 								 bool segment_finished);
157 
158 static const char *get_tablespace_mapping(const char *dir);
159 static void tablespace_list_append(const char *arg);
160 
161 
162 static void
cleanup_directories_atexit(void)163 cleanup_directories_atexit(void)
164 {
165 	if (success || in_log_streamer)
166 		return;
167 
168 	if (!noclean && !checksum_failure)
169 	{
170 		if (made_new_pgdata)
171 		{
172 			pg_log_info("removing data directory \"%s\"", basedir);
173 			if (!rmtree(basedir, true))
174 				pg_log_error("failed to remove data directory");
175 		}
176 		else if (found_existing_pgdata)
177 		{
178 			pg_log_info("removing contents of data directory \"%s\"", basedir);
179 			if (!rmtree(basedir, false))
180 				pg_log_error("failed to remove contents of data directory");
181 		}
182 
183 		if (made_new_xlogdir)
184 		{
185 			pg_log_info("removing WAL directory \"%s\"", xlog_dir);
186 			if (!rmtree(xlog_dir, true))
187 				pg_log_error("failed to remove WAL directory");
188 		}
189 		else if (found_existing_xlogdir)
190 		{
191 			pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir);
192 			if (!rmtree(xlog_dir, false))
193 				pg_log_error("failed to remove contents of WAL directory");
194 		}
195 	}
196 	else
197 	{
198 		if ((made_new_pgdata || found_existing_pgdata) && !checksum_failure)
199 			pg_log_info("data directory \"%s\" not removed at user's request", basedir);
200 
201 		if (made_new_xlogdir || found_existing_xlogdir)
202 			pg_log_info("WAL directory \"%s\" not removed at user's request", xlog_dir);
203 	}
204 
205 	if ((made_tablespace_dirs || found_tablespace_dirs) && !checksum_failure)
206 		pg_log_info("changes to tablespace directories will not be undone");
207 }
208 
209 static void
disconnect_atexit(void)210 disconnect_atexit(void)
211 {
212 	if (conn != NULL)
213 		PQfinish(conn);
214 }
215 
216 #ifndef WIN32
217 /*
218  * On windows, our background thread dies along with the process. But on
219  * Unix, if we have started a subprocess, we want to kill it off so it
220  * doesn't remain running trying to stream data.
221  */
222 static void
kill_bgchild_atexit(void)223 kill_bgchild_atexit(void)
224 {
225 	if (bgchild > 0)
226 		kill(bgchild, SIGTERM);
227 }
228 #endif
229 
230 /*
231  * Split argument into old_dir and new_dir and append to tablespace mapping
232  * list.
233  */
234 static void
tablespace_list_append(const char * arg)235 tablespace_list_append(const char *arg)
236 {
237 	TablespaceListCell *cell = (TablespaceListCell *) pg_malloc0(sizeof(TablespaceListCell));
238 	char	   *dst;
239 	char	   *dst_ptr;
240 	const char *arg_ptr;
241 
242 	dst_ptr = dst = cell->old_dir;
243 	for (arg_ptr = arg; *arg_ptr; arg_ptr++)
244 	{
245 		if (dst_ptr - dst >= MAXPGPATH)
246 		{
247 			pg_log_error("directory name too long");
248 			exit(1);
249 		}
250 
251 		if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
252 			;					/* skip backslash escaping = */
253 		else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
254 		{
255 			if (*cell->new_dir)
256 			{
257 				pg_log_error("multiple \"=\" signs in tablespace mapping");
258 				exit(1);
259 			}
260 			else
261 				dst = dst_ptr = cell->new_dir;
262 		}
263 		else
264 			*dst_ptr++ = *arg_ptr;
265 	}
266 
267 	if (!*cell->old_dir || !*cell->new_dir)
268 	{
269 		pg_log_error("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"", arg);
270 		exit(1);
271 	}
272 
273 	/*
274 	 * This check isn't absolutely necessary.  But all tablespaces are created
275 	 * with absolute directories, so specifying a non-absolute path here would
276 	 * just never match, possibly confusing users.  It's also good to be
277 	 * consistent with the new_dir check.
278 	 */
279 	if (!is_absolute_path(cell->old_dir))
280 	{
281 		pg_log_error("old directory is not an absolute path in tablespace mapping: %s",
282 					 cell->old_dir);
283 		exit(1);
284 	}
285 
286 	if (!is_absolute_path(cell->new_dir))
287 	{
288 		pg_log_error("new directory is not an absolute path in tablespace mapping: %s",
289 					 cell->new_dir);
290 		exit(1);
291 	}
292 
293 	/*
294 	 * Comparisons done with these values should involve similarly
295 	 * canonicalized path values.  This is particularly sensitive on Windows
296 	 * where path values may not necessarily use Unix slashes.
297 	 */
298 	canonicalize_path(cell->old_dir);
299 	canonicalize_path(cell->new_dir);
300 
301 	if (tablespace_dirs.tail)
302 		tablespace_dirs.tail->next = cell;
303 	else
304 		tablespace_dirs.head = cell;
305 	tablespace_dirs.tail = cell;
306 }
307 
308 
309 #ifdef HAVE_LIBZ
310 static const char *
get_gz_error(gzFile gzf)311 get_gz_error(gzFile gzf)
312 {
313 	int			errnum;
314 	const char *errmsg;
315 
316 	errmsg = gzerror(gzf, &errnum);
317 	if (errnum == Z_ERRNO)
318 		return strerror(errno);
319 	else
320 		return errmsg;
321 }
322 #endif
323 
324 static void
usage(void)325 usage(void)
326 {
327 	printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
328 		   progname);
329 	printf(_("Usage:\n"));
330 	printf(_("  %s [OPTION]...\n"), progname);
331 	printf(_("\nOptions controlling the output:\n"));
332 	printf(_("  -D, --pgdata=DIRECTORY receive base backup into directory\n"));
333 	printf(_("  -F, --format=p|t       output format (plain (default), tar)\n"));
334 	printf(_("  -r, --max-rate=RATE    maximum transfer rate to transfer data directory\n"
335 			 "                         (in kB/s, or use suffix \"k\" or \"M\")\n"));
336 	printf(_("  -R, --write-recovery-conf\n"
337 			 "                         write configuration for replication\n"));
338 	printf(_("  -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
339 			 "                         relocate tablespace in OLDDIR to NEWDIR\n"));
340 	printf(_("      --waldir=WALDIR    location for the write-ahead log directory\n"));
341 	printf(_("  -X, --wal-method=none|fetch|stream\n"
342 			 "                         include required WAL files with specified method\n"));
343 	printf(_("  -z, --gzip             compress tar output\n"));
344 	printf(_("  -Z, --compress=0-9     compress tar output with given compression level\n"));
345 	printf(_("\nGeneral options:\n"));
346 	printf(_("  -c, --checkpoint=fast|spread\n"
347 			 "                         set fast or spread checkpointing\n"));
348 	printf(_("  -C, --create-slot      create replication slot\n"));
349 	printf(_("  -l, --label=LABEL      set backup label\n"));
350 	printf(_("  -n, --no-clean         do not clean up after errors\n"));
351 	printf(_("  -N, --no-sync          do not wait for changes to be written safely to disk\n"));
352 	printf(_("  -P, --progress         show progress information\n"));
353 	printf(_("  -S, --slot=SLOTNAME    replication slot to use\n"));
354 	printf(_("  -v, --verbose          output verbose messages\n"));
355 	printf(_("  -V, --version          output version information, then exit\n"));
356 	printf(_("      --no-slot          prevent creation of temporary replication slot\n"));
357 	printf(_("      --no-verify-checksums\n"
358 			 "                         do not verify checksums\n"));
359 	printf(_("  -?, --help             show this help, then exit\n"));
360 	printf(_("\nConnection options:\n"));
361 	printf(_("  -d, --dbname=CONNSTR   connection string\n"));
362 	printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
363 	printf(_("  -p, --port=PORT        database server port number\n"));
364 	printf(_("  -s, --status-interval=INTERVAL\n"
365 			 "                         time between status packets sent to server (in seconds)\n"));
366 	printf(_("  -U, --username=NAME    connect as specified database user\n"));
367 	printf(_("  -w, --no-password      never prompt for password\n"));
368 	printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
369 	printf(_("\nReport bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
370 }
371 
372 
373 /*
374  * Called in the background process every time data is received.
375  * On Unix, we check to see if there is any data on our pipe
376  * (which would mean we have a stop position), and if it is, check if
377  * it is time to stop.
378  * On Windows, we are in a single process, so we can just check if it's
379  * time to stop.
380  */
381 static bool
reached_end_position(XLogRecPtr segendpos,uint32 timeline,bool segment_finished)382 reached_end_position(XLogRecPtr segendpos, uint32 timeline,
383 					 bool segment_finished)
384 {
385 	if (!has_xlogendptr)
386 	{
387 #ifndef WIN32
388 		fd_set		fds;
389 		struct timeval tv;
390 		int			r;
391 
392 		/*
393 		 * Don't have the end pointer yet - check our pipe to see if it has
394 		 * been sent yet.
395 		 */
396 		FD_ZERO(&fds);
397 		FD_SET(bgpipe[0], &fds);
398 
399 		MemSet(&tv, 0, sizeof(tv));
400 
401 		r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
402 		if (r == 1)
403 		{
404 			char		xlogend[64];
405 			uint32		hi,
406 						lo;
407 
408 			MemSet(xlogend, 0, sizeof(xlogend));
409 			r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
410 			if (r < 0)
411 			{
412 				pg_log_error("could not read from ready pipe: %m");
413 				exit(1);
414 			}
415 
416 			if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
417 			{
418 				pg_log_error("could not parse write-ahead log location \"%s\"",
419 							 xlogend);
420 				exit(1);
421 			}
422 			xlogendptr = ((uint64) hi) << 32 | lo;
423 			has_xlogendptr = 1;
424 
425 			/*
426 			 * Fall through to check if we've reached the point further
427 			 * already.
428 			 */
429 		}
430 		else
431 		{
432 			/*
433 			 * No data received on the pipe means we don't know the end
434 			 * position yet - so just say it's not time to stop yet.
435 			 */
436 			return false;
437 		}
438 #else
439 
440 		/*
441 		 * On win32, has_xlogendptr is set by the main thread, so if it's not
442 		 * set here, we just go back and wait until it shows up.
443 		 */
444 		return false;
445 #endif
446 	}
447 
448 	/*
449 	 * At this point we have an end pointer, so compare it to the current
450 	 * position to figure out if it's time to stop.
451 	 */
452 	if (segendpos >= xlogendptr)
453 		return true;
454 
455 	/*
456 	 * Have end pointer, but haven't reached it yet - so tell the caller to
457 	 * keep streaming.
458 	 */
459 	return false;
460 }
461 
462 typedef struct
463 {
464 	PGconn	   *bgconn;
465 	XLogRecPtr	startptr;
466 	char		xlog[MAXPGPATH];	/* directory or tarfile depending on mode */
467 	char	   *sysidentifier;
468 	int			timeline;
469 } logstreamer_param;
470 
471 static int
LogStreamerMain(logstreamer_param * param)472 LogStreamerMain(logstreamer_param *param)
473 {
474 	StreamCtl	stream;
475 
476 	in_log_streamer = true;
477 
478 	MemSet(&stream, 0, sizeof(stream));
479 	stream.startpos = param->startptr;
480 	stream.timeline = param->timeline;
481 	stream.sysidentifier = param->sysidentifier;
482 	stream.stream_stop = reached_end_position;
483 #ifndef WIN32
484 	stream.stop_socket = bgpipe[0];
485 #else
486 	stream.stop_socket = PGINVALID_SOCKET;
487 #endif
488 	stream.standby_message_timeout = standby_message_timeout;
489 	stream.synchronous = false;
490 	/* fsync happens at the end of pg_basebackup for all data */
491 	stream.do_sync = false;
492 	stream.mark_done = true;
493 	stream.partial_suffix = NULL;
494 	stream.replication_slot = replication_slot;
495 
496 	if (format == 'p')
497 		stream.walmethod = CreateWalDirectoryMethod(param->xlog, 0,
498 													stream.do_sync);
499 	else
500 		stream.walmethod = CreateWalTarMethod(param->xlog, compresslevel,
501 											  stream.do_sync);
502 
503 	if (!ReceiveXlogStream(param->bgconn, &stream))
504 
505 		/*
506 		 * Any errors will already have been reported in the function process,
507 		 * but we need to tell the parent that we didn't shutdown in a nice
508 		 * way.
509 		 */
510 		return 1;
511 
512 	if (!stream.walmethod->finish())
513 	{
514 		pg_log_error("could not finish writing WAL files: %m");
515 		return 1;
516 	}
517 
518 	PQfinish(param->bgconn);
519 
520 	if (format == 'p')
521 		FreeWalDirectoryMethod();
522 	else
523 		FreeWalTarMethod();
524 	pg_free(stream.walmethod);
525 
526 	return 0;
527 }
528 
529 /*
530  * Initiate background process for receiving xlog during the backup.
531  * The background stream will use its own database connection so we can
532  * stream the logfile in parallel with the backups.
533  */
534 static void
StartLogStreamer(char * startpos,uint32 timeline,char * sysidentifier)535 StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
536 {
537 	logstreamer_param *param;
538 	uint32		hi,
539 				lo;
540 	char		statusdir[MAXPGPATH];
541 
542 	param = pg_malloc0(sizeof(logstreamer_param));
543 	param->timeline = timeline;
544 	param->sysidentifier = sysidentifier;
545 
546 	/* Convert the starting position */
547 	if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
548 	{
549 		pg_log_error("could not parse write-ahead log location \"%s\"",
550 					 startpos);
551 		exit(1);
552 	}
553 	param->startptr = ((uint64) hi) << 32 | lo;
554 	/* Round off to even segment position */
555 	param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
556 
557 #ifndef WIN32
558 	/* Create our background pipe */
559 	if (pipe(bgpipe) < 0)
560 	{
561 		pg_log_error("could not create pipe for background process: %m");
562 		exit(1);
563 	}
564 #endif
565 
566 	/* Get a second connection */
567 	param->bgconn = GetConnection();
568 	if (!param->bgconn)
569 		/* Error message already written in GetConnection() */
570 		exit(1);
571 
572 	/* In post-10 cluster, pg_xlog has been renamed to pg_wal */
573 	snprintf(param->xlog, sizeof(param->xlog), "%s/%s",
574 			 basedir,
575 			 PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
576 			 "pg_xlog" : "pg_wal");
577 
578 	/* Temporary replication slots are only supported in 10 and newer */
579 	if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_TEMP_SLOTS)
580 		temp_replication_slot = false;
581 
582 	/*
583 	 * Create replication slot if requested
584 	 */
585 	if (temp_replication_slot && !replication_slot)
586 		replication_slot = psprintf("pg_basebackup_%d", (int) PQbackendPID(param->bgconn));
587 	if (temp_replication_slot || create_slot)
588 	{
589 		if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
590 								   temp_replication_slot, true, true, false))
591 			exit(1);
592 
593 		if (verbose)
594 		{
595 			if (temp_replication_slot)
596 				pg_log_info("created temporary replication slot \"%s\"",
597 							replication_slot);
598 			else
599 				pg_log_info("created replication slot \"%s\"",
600 							replication_slot);
601 		}
602 	}
603 
604 	if (format == 'p')
605 	{
606 		/*
607 		 * Create pg_wal/archive_status or pg_xlog/archive_status (and thus
608 		 * pg_wal or pg_xlog) depending on the target server so we can write
609 		 * to basedir/pg_wal or basedir/pg_xlog as the directory entry in the
610 		 * tar file may arrive later.
611 		 */
612 		snprintf(statusdir, sizeof(statusdir), "%s/%s/archive_status",
613 				 basedir,
614 				 PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
615 				 "pg_xlog" : "pg_wal");
616 
617 		if (pg_mkdir_p(statusdir, pg_dir_create_mode) != 0 && errno != EEXIST)
618 		{
619 			pg_log_error("could not create directory \"%s\": %m", statusdir);
620 			exit(1);
621 		}
622 	}
623 
624 	/*
625 	 * Start a child process and tell it to start streaming. On Unix, this is
626 	 * a fork(). On Windows, we create a thread.
627 	 */
628 #ifndef WIN32
629 	bgchild = fork();
630 	if (bgchild == 0)
631 	{
632 		/* in child process */
633 		exit(LogStreamerMain(param));
634 	}
635 	else if (bgchild < 0)
636 	{
637 		pg_log_error("could not create background process: %m");
638 		exit(1);
639 	}
640 
641 	/*
642 	 * Else we are in the parent process and all is well.
643 	 */
644 	atexit(kill_bgchild_atexit);
645 #else							/* WIN32 */
646 	bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
647 	if (bgchild == 0)
648 	{
649 		pg_log_error("could not create background thread: %m");
650 		exit(1);
651 	}
652 #endif
653 }
654 
655 /*
656  * Verify that the given directory exists and is empty. If it does not
657  * exist, it is created. If it exists but is not empty, an error will
658  * be given and the process ended.
659  */
660 static void
verify_dir_is_empty_or_create(char * dirname,bool * created,bool * found)661 verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
662 {
663 	switch (pg_check_dir(dirname))
664 	{
665 		case 0:
666 
667 			/*
668 			 * Does not exist, so create
669 			 */
670 			if (pg_mkdir_p(dirname, pg_dir_create_mode) == -1)
671 			{
672 				pg_log_error("could not create directory \"%s\": %m", dirname);
673 				exit(1);
674 			}
675 			if (created)
676 				*created = true;
677 			return;
678 		case 1:
679 
680 			/*
681 			 * Exists, empty
682 			 */
683 			if (found)
684 				*found = true;
685 			return;
686 		case 2:
687 		case 3:
688 		case 4:
689 
690 			/*
691 			 * Exists, not empty
692 			 */
693 			pg_log_error("directory \"%s\" exists but is not empty", dirname);
694 			exit(1);
695 		case -1:
696 
697 			/*
698 			 * Access problem
699 			 */
700 			pg_log_error("could not access directory \"%s\": %m", dirname);
701 			exit(1);
702 	}
703 }
704 
705 
706 /*
707  * Print a progress report based on the global variables. If verbose output
708  * is enabled, also print the current file name.
709  *
710  * Progress report is written at maximum once per second, unless the force
711  * parameter is set to true.
712  *
713  * If finished is set to true, this is the last progress report. The cursor
714  * is moved to the next line.
715  */
716 static void
progress_report(int tablespacenum,const char * filename,bool force,bool finished)717 progress_report(int tablespacenum, const char *filename,
718 				bool force, bool finished)
719 {
720 	int			percent;
721 	char		totaldone_str[32];
722 	char		totalsize_str[32];
723 	pg_time_t	now;
724 
725 	if (!showprogress)
726 		return;
727 
728 	now = time(NULL);
729 	if (now == last_progress_report && !force && !finished)
730 		return;					/* Max once per second */
731 
732 	last_progress_report = now;
733 	percent = totalsize ? (int) ((totaldone / 1024) * 100 / totalsize) : 0;
734 
735 	/*
736 	 * Avoid overflowing past 100% or the full size. This may make the total
737 	 * size number change as we approach the end of the backup (the estimate
738 	 * will always be wrong if WAL is included), but that's better than having
739 	 * the done column be bigger than the total.
740 	 */
741 	if (percent > 100)
742 		percent = 100;
743 	if (totaldone / 1024 > totalsize)
744 		totalsize = totaldone / 1024;
745 
746 	/*
747 	 * Separate step to keep platform-dependent format code out of
748 	 * translatable strings.  And we only test for INT64_FORMAT availability
749 	 * in snprintf, not fprintf.
750 	 */
751 	snprintf(totaldone_str, sizeof(totaldone_str), INT64_FORMAT,
752 			 totaldone / 1024);
753 	snprintf(totalsize_str, sizeof(totalsize_str), INT64_FORMAT, totalsize);
754 
755 #define VERBOSE_FILENAME_LENGTH 35
756 	if (verbose)
757 	{
758 		if (!filename)
759 
760 			/*
761 			 * No filename given, so clear the status line (used for last
762 			 * call)
763 			 */
764 			fprintf(stderr,
765 					ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
766 							 "%*s/%s kB (100%%), %d/%d tablespaces %*s",
767 							 tablespacecount),
768 					(int) strlen(totalsize_str),
769 					totaldone_str, totalsize_str,
770 					tablespacenum, tablespacecount,
771 					VERBOSE_FILENAME_LENGTH + 5, "");
772 		else
773 		{
774 			bool		truncate = (strlen(filename) > VERBOSE_FILENAME_LENGTH);
775 
776 			fprintf(stderr,
777 					ngettext("%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)",
778 							 "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)",
779 							 tablespacecount),
780 					(int) strlen(totalsize_str),
781 					totaldone_str, totalsize_str, percent,
782 					tablespacenum, tablespacecount,
783 			/* Prefix with "..." if we do leading truncation */
784 					truncate ? "..." : "",
785 					truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
786 					truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
787 			/* Truncate filename at beginning if it's too long */
788 					truncate ? filename + strlen(filename) - VERBOSE_FILENAME_LENGTH + 3 : filename);
789 		}
790 	}
791 	else
792 		fprintf(stderr,
793 				ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
794 						 "%*s/%s kB (%d%%), %d/%d tablespaces",
795 						 tablespacecount),
796 				(int) strlen(totalsize_str),
797 				totaldone_str, totalsize_str, percent,
798 				tablespacenum, tablespacecount);
799 
800 	/*
801 	 * Stay on the same line if reporting to a terminal and we're not done
802 	 * yet.
803 	 */
804 	fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
805 }
806 
807 static int32
parse_max_rate(char * src)808 parse_max_rate(char *src)
809 {
810 	double		result;
811 	char	   *after_num;
812 	char	   *suffix = NULL;
813 
814 	errno = 0;
815 	result = strtod(src, &after_num);
816 	if (src == after_num)
817 	{
818 		pg_log_error("transfer rate \"%s\" is not a valid value", src);
819 		exit(1);
820 	}
821 	if (errno != 0)
822 	{
823 		pg_log_error("invalid transfer rate \"%s\": %m", src);
824 		exit(1);
825 	}
826 
827 	if (result <= 0)
828 	{
829 		/*
830 		 * Reject obviously wrong values here.
831 		 */
832 		pg_log_error("transfer rate must be greater than zero");
833 		exit(1);
834 	}
835 
836 	/*
837 	 * Evaluate suffix, after skipping over possible whitespace. Lack of
838 	 * suffix means kilobytes.
839 	 */
840 	while (*after_num != '\0' && isspace((unsigned char) *after_num))
841 		after_num++;
842 
843 	if (*after_num != '\0')
844 	{
845 		suffix = after_num;
846 		if (*after_num == 'k')
847 		{
848 			/* kilobyte is the expected unit. */
849 			after_num++;
850 		}
851 		else if (*after_num == 'M')
852 		{
853 			after_num++;
854 			result *= 1024.0;
855 		}
856 	}
857 
858 	/* The rest can only consist of white space. */
859 	while (*after_num != '\0' && isspace((unsigned char) *after_num))
860 		after_num++;
861 
862 	if (*after_num != '\0')
863 	{
864 		pg_log_error("invalid --max-rate unit: \"%s\"", suffix);
865 		exit(1);
866 	}
867 
868 	/* Valid integer? */
869 	if ((uint64) result != (uint64) ((uint32) result))
870 	{
871 		pg_log_error("transfer rate \"%s\" exceeds integer range", src);
872 		exit(1);
873 	}
874 
875 	/*
876 	 * The range is checked on the server side too, but avoid the server
877 	 * connection if a nonsensical value was passed.
878 	 */
879 	if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
880 	{
881 		pg_log_error("transfer rate \"%s\" is out of range", src);
882 		exit(1);
883 	}
884 
885 	return (int32) result;
886 }
887 
888 /*
889  * Write a piece of tar data
890  */
891 static void
writeTarData(gzFile ztarfile,FILE * tarfile,char * buf,int r,char * current_file)892 writeTarData(
893 #ifdef HAVE_LIBZ
894 			 gzFile ztarfile,
895 #endif
896 			 FILE *tarfile, char *buf, int r, char *current_file)
897 {
898 #ifdef HAVE_LIBZ
899 	if (ztarfile != NULL)
900 	{
901 		errno = 0;
902 		if (gzwrite(ztarfile, buf, r) != r)
903 		{
904 			/* if write didn't set errno, assume problem is no disk space */
905 			if (errno == 0)
906 				errno = ENOSPC;
907 			pg_log_error("could not write to compressed file \"%s\": %s",
908 						 current_file, get_gz_error(ztarfile));
909 			exit(1);
910 		}
911 	}
912 	else
913 #endif
914 	{
915 		errno = 0;
916 		if (fwrite(buf, r, 1, tarfile) != 1)
917 		{
918 			/* if write didn't set errno, assume problem is no disk space */
919 			if (errno == 0)
920 				errno = ENOSPC;
921 			pg_log_error("could not write to file \"%s\": %m", current_file);
922 			exit(1);
923 		}
924 	}
925 }
926 
927 #ifdef HAVE_LIBZ
928 #define WRITE_TAR_DATA(buf, sz) writeTarData(ztarfile, tarfile, buf, sz, filename)
929 #else
930 #define WRITE_TAR_DATA(buf, sz) writeTarData(tarfile, buf, sz, filename)
931 #endif
932 
933 /*
934  * Receive a tar format file from the connection to the server, and write
935  * the data from this file directly into a tar file. If compression is
936  * enabled, the data will be compressed while written to the file.
937  *
938  * The file will be named base.tar[.gz] if it's for the main data directory
939  * or <tablespaceoid>.tar[.gz] if it's for another tablespace.
940  *
941  * No attempt to inspect or validate the contents of the file is done.
942  */
943 static void
ReceiveTarFile(PGconn * conn,PGresult * res,int rownum)944 ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
945 {
946 	char		filename[MAXPGPATH];
947 	char	   *copybuf = NULL;
948 	FILE	   *tarfile = NULL;
949 	char		tarhdr[512];
950 	bool		basetablespace = PQgetisnull(res, rownum, 0);
951 	bool		in_tarhdr = true;
952 	bool		skip_file = false;
953 	bool		is_recovery_guc_supported = true;
954 	bool		is_postgresql_auto_conf = false;
955 	bool		found_postgresql_auto_conf = false;
956 	int			file_padding_len = 0;
957 	size_t		tarhdrsz = 0;
958 	pgoff_t		filesz = 0;
959 
960 #ifdef HAVE_LIBZ
961 	gzFile		ztarfile = NULL;
962 #endif
963 
964 	/* recovery.conf is integrated into postgresql.conf in 12 and newer */
965 	if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
966 		is_recovery_guc_supported = false;
967 
968 	if (basetablespace)
969 	{
970 		/*
971 		 * Base tablespaces
972 		 */
973 		if (strcmp(basedir, "-") == 0)
974 		{
975 #ifdef WIN32
976 			_setmode(fileno(stdout), _O_BINARY);
977 #endif
978 
979 #ifdef HAVE_LIBZ
980 			if (compresslevel != 0)
981 			{
982 				ztarfile = gzdopen(dup(fileno(stdout)), "wb");
983 				if (gzsetparams(ztarfile, compresslevel,
984 								Z_DEFAULT_STRATEGY) != Z_OK)
985 				{
986 					pg_log_error("could not set compression level %d: %s",
987 								 compresslevel, get_gz_error(ztarfile));
988 					exit(1);
989 				}
990 			}
991 			else
992 #endif
993 				tarfile = stdout;
994 			strcpy(filename, "-");
995 		}
996 		else
997 		{
998 #ifdef HAVE_LIBZ
999 			if (compresslevel != 0)
1000 			{
1001 				snprintf(filename, sizeof(filename), "%s/base.tar.gz", basedir);
1002 				ztarfile = gzopen(filename, "wb");
1003 				if (gzsetparams(ztarfile, compresslevel,
1004 								Z_DEFAULT_STRATEGY) != Z_OK)
1005 				{
1006 					pg_log_error("could not set compression level %d: %s",
1007 								 compresslevel, get_gz_error(ztarfile));
1008 					exit(1);
1009 				}
1010 			}
1011 			else
1012 #endif
1013 			{
1014 				snprintf(filename, sizeof(filename), "%s/base.tar", basedir);
1015 				tarfile = fopen(filename, "wb");
1016 			}
1017 		}
1018 	}
1019 	else
1020 	{
1021 		/*
1022 		 * Specific tablespace
1023 		 */
1024 #ifdef HAVE_LIBZ
1025 		if (compresslevel != 0)
1026 		{
1027 			snprintf(filename, sizeof(filename), "%s/%s.tar.gz", basedir,
1028 					 PQgetvalue(res, rownum, 0));
1029 			ztarfile = gzopen(filename, "wb");
1030 			if (gzsetparams(ztarfile, compresslevel,
1031 							Z_DEFAULT_STRATEGY) != Z_OK)
1032 			{
1033 				pg_log_error("could not set compression level %d: %s",
1034 							 compresslevel, get_gz_error(ztarfile));
1035 				exit(1);
1036 			}
1037 		}
1038 		else
1039 #endif
1040 		{
1041 			snprintf(filename, sizeof(filename), "%s/%s.tar", basedir,
1042 					 PQgetvalue(res, rownum, 0));
1043 			tarfile = fopen(filename, "wb");
1044 		}
1045 	}
1046 
1047 #ifdef HAVE_LIBZ
1048 	if (compresslevel != 0)
1049 	{
1050 		if (!ztarfile)
1051 		{
1052 			/* Compression is in use */
1053 			pg_log_error("could not create compressed file \"%s\": %s",
1054 						 filename, get_gz_error(ztarfile));
1055 			exit(1);
1056 		}
1057 	}
1058 	else
1059 #endif
1060 	{
1061 		/* Either no zlib support, or zlib support but compresslevel = 0 */
1062 		if (!tarfile)
1063 		{
1064 			pg_log_error("could not create file \"%s\": %m", filename);
1065 			exit(1);
1066 		}
1067 	}
1068 
1069 	/*
1070 	 * Get the COPY data stream
1071 	 */
1072 	res = PQgetResult(conn);
1073 	if (PQresultStatus(res) != PGRES_COPY_OUT)
1074 	{
1075 		pg_log_error("could not get COPY data stream: %s",
1076 					 PQerrorMessage(conn));
1077 		exit(1);
1078 	}
1079 
1080 	while (1)
1081 	{
1082 		int			r;
1083 
1084 		if (copybuf != NULL)
1085 		{
1086 			PQfreemem(copybuf);
1087 			copybuf = NULL;
1088 		}
1089 
1090 		r = PQgetCopyData(conn, &copybuf, 0);
1091 		if (r == -1)
1092 		{
1093 			/*
1094 			 * End of chunk. If requested, and this is the base tablespace,
1095 			 * write configuration file into the tarfile. When done, close the
1096 			 * file (but not stdout).
1097 			 *
1098 			 * Also, write two completely empty blocks at the end of the tar
1099 			 * file, as required by some tar programs.
1100 			 */
1101 			char		zerobuf[1024];
1102 
1103 			MemSet(zerobuf, 0, sizeof(zerobuf));
1104 
1105 			if (basetablespace && writerecoveryconf)
1106 			{
1107 				char		header[512];
1108 
1109 				/*
1110 				 * If postgresql.auto.conf has not been found in the streamed
1111 				 * data, add recovery configuration to postgresql.auto.conf if
1112 				 * recovery parameters are GUCs.  If the instance connected to
1113 				 * is older than 12, create recovery.conf with this data
1114 				 * otherwise.
1115 				 */
1116 				if (!found_postgresql_auto_conf || !is_recovery_guc_supported)
1117 				{
1118 					int			padding;
1119 
1120 					tarCreateHeader(header,
1121 									is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf",
1122 									NULL,
1123 									recoveryconfcontents->len,
1124 									pg_file_create_mode, 04000, 02000,
1125 									time(NULL));
1126 
1127 					padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
1128 
1129 					WRITE_TAR_DATA(header, sizeof(header));
1130 					WRITE_TAR_DATA(recoveryconfcontents->data,
1131 								   recoveryconfcontents->len);
1132 					if (padding)
1133 						WRITE_TAR_DATA(zerobuf, padding);
1134 				}
1135 
1136 				/*
1137 				 * standby.signal is supported only if recovery parameters are
1138 				 * GUCs.
1139 				 */
1140 				if (is_recovery_guc_supported)
1141 				{
1142 					tarCreateHeader(header, "standby.signal", NULL,
1143 									0,	/* zero-length file */
1144 									pg_file_create_mode, 04000, 02000,
1145 									time(NULL));
1146 
1147 					WRITE_TAR_DATA(header, sizeof(header));
1148 
1149 					/*
1150 					 * we don't need to pad out to a multiple of the tar block
1151 					 * size here, because the file is zero length, which is a
1152 					 * multiple of any block size.
1153 					 */
1154 				}
1155 			}
1156 
1157 			/* 2 * 512 bytes empty data at end of file */
1158 			WRITE_TAR_DATA(zerobuf, sizeof(zerobuf));
1159 
1160 #ifdef HAVE_LIBZ
1161 			if (ztarfile != NULL)
1162 			{
1163 				if (gzclose(ztarfile) != 0)
1164 				{
1165 					pg_log_error("could not close compressed file \"%s\": %s",
1166 								 filename, get_gz_error(ztarfile));
1167 					exit(1);
1168 				}
1169 			}
1170 			else
1171 #endif
1172 			{
1173 				if (strcmp(basedir, "-") != 0)
1174 				{
1175 					if (fclose(tarfile) != 0)
1176 					{
1177 						pg_log_error("could not close file \"%s\": %m",
1178 									 filename);
1179 						exit(1);
1180 					}
1181 				}
1182 			}
1183 
1184 			break;
1185 		}
1186 		else if (r == -2)
1187 		{
1188 			pg_log_error("could not read COPY data: %s",
1189 						 PQerrorMessage(conn));
1190 			exit(1);
1191 		}
1192 
1193 		if (!writerecoveryconf || !basetablespace)
1194 		{
1195 			/*
1196 			 * When not writing config file, or when not working on the base
1197 			 * tablespace, we never have to look for an existing configuration
1198 			 * file in the stream.
1199 			 */
1200 			WRITE_TAR_DATA(copybuf, r);
1201 		}
1202 		else
1203 		{
1204 			/*
1205 			 * Look for a config file in the existing tar stream. If it's
1206 			 * there, we must skip it so we can later overwrite it with our
1207 			 * own version of the file.
1208 			 *
1209 			 * To do this, we have to process the individual files inside the
1210 			 * TAR stream. The stream consists of a header and zero or more
1211 			 * chunks, all 512 bytes long. The stream from the server is
1212 			 * broken up into smaller pieces, so we have to track the size of
1213 			 * the files to find the next header structure.
1214 			 */
1215 			int			rr = r;
1216 			int			pos = 0;
1217 
1218 			while (rr > 0)
1219 			{
1220 				if (in_tarhdr)
1221 				{
1222 					/*
1223 					 * We're currently reading a header structure inside the
1224 					 * TAR stream, i.e. the file metadata.
1225 					 */
1226 					if (tarhdrsz < 512)
1227 					{
1228 						/*
1229 						 * Copy the header structure into tarhdr in case the
1230 						 * header is not aligned to 512 bytes or it's not
1231 						 * returned in whole by the last PQgetCopyData call.
1232 						 */
1233 						int			hdrleft;
1234 						int			bytes2copy;
1235 
1236 						hdrleft = 512 - tarhdrsz;
1237 						bytes2copy = (rr > hdrleft ? hdrleft : rr);
1238 
1239 						memcpy(&tarhdr[tarhdrsz], copybuf + pos, bytes2copy);
1240 
1241 						rr -= bytes2copy;
1242 						pos += bytes2copy;
1243 						tarhdrsz += bytes2copy;
1244 					}
1245 					else
1246 					{
1247 						/*
1248 						 * We have the complete header structure in tarhdr,
1249 						 * look at the file metadata: we may want append
1250 						 * recovery info into postgresql.auto.conf and skip
1251 						 * standby.signal file if recovery parameters are
1252 						 * integrated as GUCs, and recovery.conf otherwise. In
1253 						 * both cases we must calculate tar padding.
1254 						 */
1255 						if (is_recovery_guc_supported)
1256 						{
1257 							skip_file = (strcmp(&tarhdr[0], "standby.signal") == 0);
1258 							is_postgresql_auto_conf = (strcmp(&tarhdr[0], "postgresql.auto.conf") == 0);
1259 						}
1260 						else
1261 							skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
1262 
1263 						filesz = read_tar_number(&tarhdr[124], 12);
1264 						file_padding_len = ((filesz + 511) & ~511) - filesz;
1265 
1266 						if (is_recovery_guc_supported &&
1267 							is_postgresql_auto_conf &&
1268 							writerecoveryconf)
1269 						{
1270 							/* replace tar header */
1271 							char		header[512];
1272 
1273 							tarCreateHeader(header, "postgresql.auto.conf", NULL,
1274 											filesz + recoveryconfcontents->len,
1275 											pg_file_create_mode, 04000, 02000,
1276 											time(NULL));
1277 
1278 							WRITE_TAR_DATA(header, sizeof(header));
1279 						}
1280 						else
1281 						{
1282 							/* copy stream with padding */
1283 							filesz += file_padding_len;
1284 
1285 							if (!skip_file)
1286 							{
1287 								/*
1288 								 * If we're not skipping the file, write the
1289 								 * tar header unmodified.
1290 								 */
1291 								WRITE_TAR_DATA(tarhdr, 512);
1292 							}
1293 						}
1294 
1295 						/* Next part is the file, not the header */
1296 						in_tarhdr = false;
1297 					}
1298 				}
1299 				else
1300 				{
1301 					/*
1302 					 * We're processing a file's contents.
1303 					 */
1304 					if (filesz > 0)
1305 					{
1306 						/*
1307 						 * We still have data to read (and possibly write).
1308 						 */
1309 						int			bytes2write;
1310 
1311 						bytes2write = (filesz > rr ? rr : filesz);
1312 
1313 						if (!skip_file)
1314 							WRITE_TAR_DATA(copybuf + pos, bytes2write);
1315 
1316 						rr -= bytes2write;
1317 						pos += bytes2write;
1318 						filesz -= bytes2write;
1319 					}
1320 					else if (is_recovery_guc_supported &&
1321 							 is_postgresql_auto_conf &&
1322 							 writerecoveryconf)
1323 					{
1324 						/* append recovery config to postgresql.auto.conf */
1325 						int			padding;
1326 						int			tailsize;
1327 
1328 						tailsize = (512 - file_padding_len) + recoveryconfcontents->len;
1329 						padding = ((tailsize + 511) & ~511) - tailsize;
1330 
1331 						WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
1332 
1333 						if (padding)
1334 						{
1335 							char		zerobuf[512];
1336 
1337 							MemSet(zerobuf, 0, sizeof(zerobuf));
1338 							WRITE_TAR_DATA(zerobuf, padding);
1339 						}
1340 
1341 						/* skip original file padding */
1342 						is_postgresql_auto_conf = false;
1343 						skip_file = true;
1344 						filesz += file_padding_len;
1345 
1346 						found_postgresql_auto_conf = true;
1347 					}
1348 					else
1349 					{
1350 						/*
1351 						 * No more data in the current file, the next piece of
1352 						 * data (if any) will be a new file header structure.
1353 						 */
1354 						in_tarhdr = true;
1355 						skip_file = false;
1356 						is_postgresql_auto_conf = false;
1357 						tarhdrsz = 0;
1358 						filesz = 0;
1359 					}
1360 				}
1361 			}
1362 		}
1363 		totaldone += r;
1364 		progress_report(rownum, filename, false, false);
1365 	}							/* while (1) */
1366 	progress_report(rownum, filename, true, false);
1367 
1368 	if (copybuf != NULL)
1369 		PQfreemem(copybuf);
1370 
1371 	/*
1372 	 * Do not sync the resulting tar file yet, all files are synced once at
1373 	 * the end.
1374 	 */
1375 }
1376 
1377 
1378 /*
1379  * Retrieve tablespace path, either relocated or original depending on whether
1380  * -T was passed or not.
1381  */
1382 static const char *
get_tablespace_mapping(const char * dir)1383 get_tablespace_mapping(const char *dir)
1384 {
1385 	TablespaceListCell *cell;
1386 	char		canon_dir[MAXPGPATH];
1387 
1388 	/* Canonicalize path for comparison consistency */
1389 	strlcpy(canon_dir, dir, sizeof(canon_dir));
1390 	canonicalize_path(canon_dir);
1391 
1392 	for (cell = tablespace_dirs.head; cell; cell = cell->next)
1393 		if (strcmp(canon_dir, cell->old_dir) == 0)
1394 			return cell->new_dir;
1395 
1396 	return dir;
1397 }
1398 
1399 
1400 /*
1401  * Receive a tar format stream from the connection to the server, and unpack
1402  * the contents of it into a directory. Only files, directories and
1403  * symlinks are supported, no other kinds of special files.
1404  *
1405  * If the data is for the main data directory, it will be restored in the
1406  * specified directory. If it's for another tablespace, it will be restored
1407  * in the original or mapped directory.
1408  */
1409 static void
ReceiveAndUnpackTarFile(PGconn * conn,PGresult * res,int rownum)1410 ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
1411 {
1412 	char		current_path[MAXPGPATH];
1413 	char		filename[MAXPGPATH];
1414 	const char *mapped_tblspc_path;
1415 	pgoff_t		current_len_left = 0;
1416 	int			current_padding = 0;
1417 	bool		basetablespace;
1418 	char	   *copybuf = NULL;
1419 	FILE	   *file = NULL;
1420 
1421 	basetablespace = PQgetisnull(res, rownum, 0);
1422 	if (basetablespace)
1423 		strlcpy(current_path, basedir, sizeof(current_path));
1424 	else
1425 		strlcpy(current_path,
1426 				get_tablespace_mapping(PQgetvalue(res, rownum, 1)),
1427 				sizeof(current_path));
1428 
1429 	/*
1430 	 * Get the COPY data
1431 	 */
1432 	res = PQgetResult(conn);
1433 	if (PQresultStatus(res) != PGRES_COPY_OUT)
1434 	{
1435 		pg_log_error("could not get COPY data stream: %s",
1436 					 PQerrorMessage(conn));
1437 		exit(1);
1438 	}
1439 
1440 	while (1)
1441 	{
1442 		int			r;
1443 
1444 		if (copybuf != NULL)
1445 		{
1446 			PQfreemem(copybuf);
1447 			copybuf = NULL;
1448 		}
1449 
1450 		r = PQgetCopyData(conn, &copybuf, 0);
1451 
1452 		if (r == -1)
1453 		{
1454 			/*
1455 			 * End of chunk
1456 			 */
1457 			if (file)
1458 				fclose(file);
1459 
1460 			break;
1461 		}
1462 		else if (r == -2)
1463 		{
1464 			pg_log_error("could not read COPY data: %s",
1465 						 PQerrorMessage(conn));
1466 			exit(1);
1467 		}
1468 
1469 		if (file == NULL)
1470 		{
1471 			int			filemode;
1472 
1473 			/*
1474 			 * No current file, so this must be the header for a new file
1475 			 */
1476 			if (r != 512)
1477 			{
1478 				pg_log_error("invalid tar block header size: %d", r);
1479 				exit(1);
1480 			}
1481 			totaldone += 512;
1482 
1483 			current_len_left = read_tar_number(&copybuf[124], 12);
1484 
1485 			/* Set permissions on the file */
1486 			filemode = read_tar_number(&copybuf[100], 8);
1487 
1488 			/*
1489 			 * All files are padded up to 512 bytes
1490 			 */
1491 			current_padding =
1492 				((current_len_left + 511) & ~511) - current_len_left;
1493 
1494 			/*
1495 			 * First part of header is zero terminated filename
1496 			 */
1497 			snprintf(filename, sizeof(filename), "%s/%s", current_path,
1498 					 copybuf);
1499 			if (filename[strlen(filename) - 1] == '/')
1500 			{
1501 				/*
1502 				 * Ends in a slash means directory or symlink to directory
1503 				 */
1504 				if (copybuf[156] == '5')
1505 				{
1506 					/*
1507 					 * Directory
1508 					 */
1509 					filename[strlen(filename) - 1] = '\0';	/* Remove trailing slash */
1510 					if (mkdir(filename, pg_dir_create_mode) != 0)
1511 					{
1512 						/*
1513 						 * When streaming WAL, pg_wal (or pg_xlog for pre-9.6
1514 						 * clusters) will have been created by the wal
1515 						 * receiver process. Also, when the WAL directory
1516 						 * location was specified, pg_wal (or pg_xlog) has
1517 						 * already been created as a symbolic link before
1518 						 * starting the actual backup. So just ignore creation
1519 						 * failures on related directories.
1520 						 */
1521 						if (!((pg_str_endswith(filename, "/pg_wal") ||
1522 							   pg_str_endswith(filename, "/pg_xlog") ||
1523 							   pg_str_endswith(filename, "/archive_status")) &&
1524 							  errno == EEXIST))
1525 						{
1526 							pg_log_error("could not create directory \"%s\": %m",
1527 										 filename);
1528 							exit(1);
1529 						}
1530 					}
1531 #ifndef WIN32
1532 					if (chmod(filename, (mode_t) filemode))
1533 						pg_log_error("could not set permissions on directory \"%s\": %m",
1534 									 filename);
1535 #endif
1536 				}
1537 				else if (copybuf[156] == '2')
1538 				{
1539 					/*
1540 					 * Symbolic link
1541 					 *
1542 					 * It's most likely a link in pg_tblspc directory, to the
1543 					 * location of a tablespace. Apply any tablespace mapping
1544 					 * given on the command line (--tablespace-mapping). (We
1545 					 * blindly apply the mapping without checking that the
1546 					 * link really is inside pg_tblspc. We don't expect there
1547 					 * to be other symlinks in a data directory, but if there
1548 					 * are, you can call it an undocumented feature that you
1549 					 * can map them too.)
1550 					 */
1551 					filename[strlen(filename) - 1] = '\0';	/* Remove trailing slash */
1552 
1553 					mapped_tblspc_path = get_tablespace_mapping(&copybuf[157]);
1554 					if (symlink(mapped_tblspc_path, filename) != 0)
1555 					{
1556 						pg_log_error("could not create symbolic link from \"%s\" to \"%s\": %m",
1557 									 filename, mapped_tblspc_path);
1558 						exit(1);
1559 					}
1560 				}
1561 				else
1562 				{
1563 					pg_log_error("unrecognized link indicator \"%c\"",
1564 								 copybuf[156]);
1565 					exit(1);
1566 				}
1567 				continue;		/* directory or link handled */
1568 			}
1569 
1570 			/*
1571 			 * regular file
1572 			 */
1573 			file = fopen(filename, "wb");
1574 			if (!file)
1575 			{
1576 				pg_log_error("could not create file \"%s\": %m", filename);
1577 				exit(1);
1578 			}
1579 
1580 #ifndef WIN32
1581 			if (chmod(filename, (mode_t) filemode))
1582 				pg_log_error("could not set permissions on file \"%s\": %m",
1583 							 filename);
1584 #endif
1585 
1586 			if (current_len_left == 0)
1587 			{
1588 				/*
1589 				 * Done with this file, next one will be a new tar header
1590 				 */
1591 				fclose(file);
1592 				file = NULL;
1593 				continue;
1594 			}
1595 		}						/* new file */
1596 		else
1597 		{
1598 			/*
1599 			 * Continuing blocks in existing file
1600 			 */
1601 			if (current_len_left == 0 && r == current_padding)
1602 			{
1603 				/*
1604 				 * Received the padding block for this file, ignore it and
1605 				 * close the file, then move on to the next tar header.
1606 				 */
1607 				fclose(file);
1608 				file = NULL;
1609 				totaldone += r;
1610 				continue;
1611 			}
1612 
1613 			errno = 0;
1614 			if (fwrite(copybuf, r, 1, file) != 1)
1615 			{
1616 				/* if write didn't set errno, assume problem is no disk space */
1617 				if (errno == 0)
1618 					errno = ENOSPC;
1619 				pg_log_error("could not write to file \"%s\": %m", filename);
1620 				exit(1);
1621 			}
1622 			totaldone += r;
1623 			progress_report(rownum, filename, false, false);
1624 
1625 			current_len_left -= r;
1626 			if (current_len_left == 0 && current_padding == 0)
1627 			{
1628 				/*
1629 				 * Received the last block, and there is no padding to be
1630 				 * expected. Close the file and move on to the next tar
1631 				 * header.
1632 				 */
1633 				fclose(file);
1634 				file = NULL;
1635 				continue;
1636 			}
1637 		}						/* continuing data in existing file */
1638 	}							/* loop over all data blocks */
1639 	progress_report(rownum, filename, true, false);
1640 
1641 	if (file != NULL)
1642 	{
1643 		pg_log_error("COPY stream ended before last file was finished");
1644 		exit(1);
1645 	}
1646 
1647 	if (copybuf != NULL)
1648 		PQfreemem(copybuf);
1649 
1650 	if (basetablespace && writerecoveryconf)
1651 		WriteRecoveryConf();
1652 
1653 	/*
1654 	 * No data is synced here, everything is done for all tablespaces at the
1655 	 * end.
1656 	 */
1657 }
1658 
1659 /*
1660  * Escape a string so that it can be used as a value in a key-value pair
1661  * a configuration file.
1662  */
1663 static char *
escape_quotes(const char * src)1664 escape_quotes(const char *src)
1665 {
1666 	char	   *result = escape_single_quotes_ascii(src);
1667 
1668 	if (!result)
1669 	{
1670 		pg_log_error("out of memory");
1671 		exit(1);
1672 	}
1673 	return result;
1674 }
1675 
1676 /*
1677  * Create a configuration file in memory using a PQExpBuffer
1678  */
1679 static void
GenerateRecoveryConf(PGconn * conn)1680 GenerateRecoveryConf(PGconn *conn)
1681 {
1682 	PQconninfoOption *connOptions;
1683 	PQconninfoOption *option;
1684 	PQExpBufferData conninfo_buf;
1685 	char	   *escaped;
1686 
1687 	recoveryconfcontents = createPQExpBuffer();
1688 	if (!recoveryconfcontents)
1689 	{
1690 		pg_log_error("out of memory");
1691 		exit(1);
1692 	}
1693 
1694 	/*
1695 	 * In PostgreSQL 12 and newer versions, standby_mode is gone, replaced by
1696 	 * standby.signal to trigger a standby state at recovery.
1697 	 */
1698 	if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
1699 		appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");
1700 
1701 	connOptions = PQconninfo(conn);
1702 	if (connOptions == NULL)
1703 	{
1704 		pg_log_error("out of memory");
1705 		exit(1);
1706 	}
1707 
1708 	initPQExpBuffer(&conninfo_buf);
1709 	for (option = connOptions; option && option->keyword; option++)
1710 	{
1711 		/* Omit empty settings and those libpqwalreceiver overrides. */
1712 		if (strcmp(option->keyword, "replication") == 0 ||
1713 			strcmp(option->keyword, "dbname") == 0 ||
1714 			strcmp(option->keyword, "fallback_application_name") == 0 ||
1715 			(option->val == NULL) ||
1716 			(option->val != NULL && option->val[0] == '\0'))
1717 			continue;
1718 
1719 		/* Separate key-value pairs with spaces */
1720 		if (conninfo_buf.len != 0)
1721 			appendPQExpBufferChar(&conninfo_buf, ' ');
1722 
1723 		/*
1724 		 * Write "keyword=value" pieces, the value string is escaped and/or
1725 		 * quoted if necessary.
1726 		 */
1727 		appendPQExpBuffer(&conninfo_buf, "%s=", option->keyword);
1728 		appendConnStrVal(&conninfo_buf, option->val);
1729 	}
1730 
1731 	/*
1732 	 * Escape the connection string, so that it can be put in the config file.
1733 	 * Note that this is different from the escaping of individual connection
1734 	 * options above!
1735 	 */
1736 	escaped = escape_quotes(conninfo_buf.data);
1737 	appendPQExpBuffer(recoveryconfcontents, "primary_conninfo = '%s'\n", escaped);
1738 	free(escaped);
1739 
1740 	if (replication_slot)
1741 	{
1742 		/* unescaped: ReplicationSlotValidateName allows [a-z0-9_] only */
1743 		appendPQExpBuffer(recoveryconfcontents, "primary_slot_name = '%s'\n",
1744 						  replication_slot);
1745 	}
1746 
1747 	if (PQExpBufferBroken(recoveryconfcontents) ||
1748 		PQExpBufferDataBroken(conninfo_buf))
1749 	{
1750 		pg_log_error("out of memory");
1751 		exit(1);
1752 	}
1753 
1754 	termPQExpBuffer(&conninfo_buf);
1755 
1756 	PQconninfoFree(connOptions);
1757 }
1758 
1759 
1760 /*
1761  * Write the configuration file into the directory specified in basedir,
1762  * with the contents already collected in memory appended.  Then write
1763  * the signal file into the basedir.  If the server does not support
1764  * recovery parameters as GUCs, the signal file is not necessary, and
1765  * configuration is written to recovery.conf.
1766  */
1767 static void
WriteRecoveryConf(void)1768 WriteRecoveryConf(void)
1769 {
1770 	char		filename[MAXPGPATH];
1771 	FILE	   *cf;
1772 	bool		is_recovery_guc_supported = true;
1773 
1774 	if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_RECOVERY_GUC)
1775 		is_recovery_guc_supported = false;
1776 
1777 	snprintf(filename, MAXPGPATH, "%s/%s", basedir,
1778 			 is_recovery_guc_supported ? "postgresql.auto.conf" : "recovery.conf");
1779 
1780 	cf = fopen(filename, is_recovery_guc_supported ? "a" : "w");
1781 	if (cf == NULL)
1782 	{
1783 		pg_log_error("could not open file \"%s\": %m", filename);
1784 		exit(1);
1785 	}
1786 
1787 	if (fwrite(recoveryconfcontents->data, recoveryconfcontents->len, 1, cf) != 1)
1788 	{
1789 		pg_log_error("could not write to file \"%s\": %m", filename);
1790 		exit(1);
1791 	}
1792 
1793 	fclose(cf);
1794 
1795 	if (is_recovery_guc_supported)
1796 	{
1797 		snprintf(filename, MAXPGPATH, "%s/%s", basedir, "standby.signal");
1798 		cf = fopen(filename, "w");
1799 		if (cf == NULL)
1800 		{
1801 			pg_log_error("could not create file \"%s\": %m", filename);
1802 			exit(1);
1803 		}
1804 
1805 		fclose(cf);
1806 	}
1807 }
1808 
1809 
1810 static void
BaseBackup(void)1811 BaseBackup(void)
1812 {
1813 	PGresult   *res;
1814 	char	   *sysidentifier;
1815 	TimeLineID	latesttli;
1816 	TimeLineID	starttli;
1817 	char	   *basebkp;
1818 	char		escaped_label[MAXPGPATH];
1819 	char	   *maxrate_clause = NULL;
1820 	int			i;
1821 	char		xlogstart[64];
1822 	char		xlogend[64];
1823 	int			minServerMajor,
1824 				maxServerMajor;
1825 	int			serverVersion,
1826 				serverMajor;
1827 
1828 	Assert(conn != NULL);
1829 
1830 	/*
1831 	 * Check server version. BASE_BACKUP command was introduced in 9.1, so we
1832 	 * can't work with servers older than 9.1.
1833 	 */
1834 	minServerMajor = 901;
1835 	maxServerMajor = PG_VERSION_NUM / 100;
1836 	serverVersion = PQserverVersion(conn);
1837 	serverMajor = serverVersion / 100;
1838 	if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
1839 	{
1840 		const char *serverver = PQparameterStatus(conn, "server_version");
1841 
1842 		pg_log_error("incompatible server version %s",
1843 					 serverver ? serverver : "'unknown'");
1844 		exit(1);
1845 	}
1846 
1847 	/*
1848 	 * If WAL streaming was requested, also check that the server is new
1849 	 * enough for that.
1850 	 */
1851 	if (includewal == STREAM_WAL && !CheckServerVersionForStreaming(conn))
1852 	{
1853 		/*
1854 		 * Error message already written in CheckServerVersionForStreaming(),
1855 		 * but add a hint about using -X none.
1856 		 */
1857 		pg_log_info("HINT: use -X none or -X fetch to disable log streaming");
1858 		exit(1);
1859 	}
1860 
1861 	/*
1862 	 * Build contents of configuration file if requested
1863 	 */
1864 	if (writerecoveryconf)
1865 		GenerateRecoveryConf(conn);
1866 
1867 	/*
1868 	 * Run IDENTIFY_SYSTEM so we can get the timeline
1869 	 */
1870 	if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
1871 		exit(1);
1872 
1873 	/*
1874 	 * Start the actual backup
1875 	 */
1876 	PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
1877 
1878 	if (maxrate > 0)
1879 		maxrate_clause = psprintf("MAX_RATE %u", maxrate);
1880 
1881 	if (verbose)
1882 		pg_log_info("initiating base backup, waiting for checkpoint to complete");
1883 
1884 	if (showprogress && !verbose)
1885 	{
1886 		fprintf(stderr, "waiting for checkpoint");
1887 		if (isatty(fileno(stderr)))
1888 			fprintf(stderr, "\r");
1889 		else
1890 			fprintf(stderr, "\n");
1891 	}
1892 
1893 	basebkp =
1894 		psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s %s",
1895 				 escaped_label,
1896 				 showprogress ? "PROGRESS" : "",
1897 				 includewal == FETCH_WAL ? "WAL" : "",
1898 				 fastcheckpoint ? "FAST" : "",
1899 				 includewal == NO_WAL ? "" : "NOWAIT",
1900 				 maxrate_clause ? maxrate_clause : "",
1901 				 format == 't' ? "TABLESPACE_MAP" : "",
1902 				 verify_checksums ? "" : "NOVERIFY_CHECKSUMS");
1903 
1904 	if (PQsendQuery(conn, basebkp) == 0)
1905 	{
1906 		pg_log_error("could not send replication command \"%s\": %s",
1907 					 "BASE_BACKUP", PQerrorMessage(conn));
1908 		exit(1);
1909 	}
1910 
1911 	/*
1912 	 * Get the starting WAL location
1913 	 */
1914 	res = PQgetResult(conn);
1915 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
1916 	{
1917 		pg_log_error("could not initiate base backup: %s",
1918 					 PQerrorMessage(conn));
1919 		exit(1);
1920 	}
1921 	if (PQntuples(res) != 1)
1922 	{
1923 		pg_log_error("server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields",
1924 					 PQntuples(res), PQnfields(res), 1, 2);
1925 		exit(1);
1926 	}
1927 
1928 	strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
1929 
1930 	if (verbose)
1931 		pg_log_info("checkpoint completed");
1932 
1933 	/*
1934 	 * 9.3 and later sends the TLI of the starting point. With older servers,
1935 	 * assume it's the same as the latest timeline reported by
1936 	 * IDENTIFY_SYSTEM.
1937 	 */
1938 	if (PQnfields(res) >= 2)
1939 		starttli = atoi(PQgetvalue(res, 0, 1));
1940 	else
1941 		starttli = latesttli;
1942 	PQclear(res);
1943 	MemSet(xlogend, 0, sizeof(xlogend));
1944 
1945 	if (verbose && includewal != NO_WAL)
1946 		pg_log_info("write-ahead log start point: %s on timeline %u",
1947 					xlogstart, starttli);
1948 
1949 	/*
1950 	 * Get the header
1951 	 */
1952 	res = PQgetResult(conn);
1953 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
1954 	{
1955 		pg_log_error("could not get backup header: %s",
1956 					 PQerrorMessage(conn));
1957 		exit(1);
1958 	}
1959 	if (PQntuples(res) < 1)
1960 	{
1961 		pg_log_error("no data returned from server");
1962 		exit(1);
1963 	}
1964 
1965 	/*
1966 	 * Sum up the total size, for progress reporting
1967 	 */
1968 	totalsize = totaldone = 0;
1969 	tablespacecount = PQntuples(res);
1970 	for (i = 0; i < PQntuples(res); i++)
1971 	{
1972 		totalsize += atol(PQgetvalue(res, i, 2));
1973 
1974 		/*
1975 		 * Verify tablespace directories are empty. Don't bother with the
1976 		 * first once since it can be relocated, and it will be checked before
1977 		 * we do anything anyway.
1978 		 */
1979 		if (format == 'p' && !PQgetisnull(res, i, 1))
1980 		{
1981 			char	   *path = unconstify(char *, get_tablespace_mapping(PQgetvalue(res, i, 1)));
1982 
1983 			verify_dir_is_empty_or_create(path, &made_tablespace_dirs, &found_tablespace_dirs);
1984 		}
1985 	}
1986 
1987 	/*
1988 	 * When writing to stdout, require a single tablespace
1989 	 */
1990 	if (format == 't' && strcmp(basedir, "-") == 0 && PQntuples(res) > 1)
1991 	{
1992 		pg_log_error("can only write single tablespace to stdout, database has %d",
1993 					 PQntuples(res));
1994 		exit(1);
1995 	}
1996 
1997 	/*
1998 	 * If we're streaming WAL, start the streaming session before we start
1999 	 * receiving the actual data chunks.
2000 	 */
2001 	if (includewal == STREAM_WAL)
2002 	{
2003 		if (verbose)
2004 			pg_log_info("starting background WAL receiver");
2005 		StartLogStreamer(xlogstart, starttli, sysidentifier);
2006 	}
2007 
2008 	/*
2009 	 * Start receiving chunks
2010 	 */
2011 	for (i = 0; i < PQntuples(res); i++)
2012 	{
2013 		if (format == 't')
2014 			ReceiveTarFile(conn, res, i);
2015 		else
2016 			ReceiveAndUnpackTarFile(conn, res, i);
2017 	}							/* Loop over all tablespaces */
2018 
2019 	if (showprogress)
2020 		progress_report(PQntuples(res), NULL, true, true);
2021 
2022 	PQclear(res);
2023 
2024 	/*
2025 	 * Get the stop position
2026 	 */
2027 	res = PQgetResult(conn);
2028 	if (PQresultStatus(res) != PGRES_TUPLES_OK)
2029 	{
2030 		pg_log_error("could not get write-ahead log end position from server: %s",
2031 					 PQerrorMessage(conn));
2032 		exit(1);
2033 	}
2034 	if (PQntuples(res) != 1)
2035 	{
2036 		pg_log_error("no write-ahead log end position returned from server");
2037 		exit(1);
2038 	}
2039 	strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
2040 	if (verbose && includewal != NO_WAL)
2041 		pg_log_info("write-ahead log end point: %s", xlogend);
2042 	PQclear(res);
2043 
2044 	res = PQgetResult(conn);
2045 	if (PQresultStatus(res) != PGRES_COMMAND_OK)
2046 	{
2047 		const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
2048 
2049 		if (sqlstate &&
2050 			strcmp(sqlstate, ERRCODE_DATA_CORRUPTED) == 0)
2051 		{
2052 			pg_log_error("checksum error occurred");
2053 			checksum_failure = true;
2054 		}
2055 		else
2056 		{
2057 			pg_log_error("final receive failed: %s",
2058 						 PQerrorMessage(conn));
2059 		}
2060 		exit(1);
2061 	}
2062 
2063 	if (bgchild > 0)
2064 	{
2065 #ifndef WIN32
2066 		int			status;
2067 		pid_t		r;
2068 #else
2069 		DWORD		status;
2070 
2071 		/*
2072 		 * get a pointer sized version of bgchild to avoid warnings about
2073 		 * casting to a different size on WIN64.
2074 		 */
2075 		intptr_t	bgchild_handle = bgchild;
2076 		uint32		hi,
2077 					lo;
2078 #endif
2079 
2080 		if (verbose)
2081 			pg_log_info("waiting for background process to finish streaming ...");
2082 
2083 #ifndef WIN32
2084 		if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
2085 		{
2086 			pg_log_info("could not send command to background pipe: %m");
2087 			exit(1);
2088 		}
2089 
2090 		/* Just wait for the background process to exit */
2091 		r = waitpid(bgchild, &status, 0);
2092 		if (r == (pid_t) -1)
2093 		{
2094 			pg_log_error("could not wait for child process: %m");
2095 			exit(1);
2096 		}
2097 		if (r != bgchild)
2098 		{
2099 			pg_log_error("child %d died, expected %d", (int) r, (int) bgchild);
2100 			exit(1);
2101 		}
2102 		if (status != 0)
2103 		{
2104 			pg_log_error("%s", wait_result_to_str(status));
2105 			exit(1);
2106 		}
2107 		/* Exited normally, we're happy! */
2108 #else							/* WIN32 */
2109 
2110 		/*
2111 		 * On Windows, since we are in the same process, we can just store the
2112 		 * value directly in the variable, and then set the flag that says
2113 		 * it's there.
2114 		 */
2115 		if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
2116 		{
2117 			pg_log_error("could not parse write-ahead log location \"%s\"",
2118 						 xlogend);
2119 			exit(1);
2120 		}
2121 		xlogendptr = ((uint64) hi) << 32 | lo;
2122 		InterlockedIncrement(&has_xlogendptr);
2123 
2124 		/* First wait for the thread to exit */
2125 		if (WaitForSingleObjectEx((HANDLE) bgchild_handle, INFINITE, FALSE) !=
2126 			WAIT_OBJECT_0)
2127 		{
2128 			_dosmaperr(GetLastError());
2129 			pg_log_error("could not wait for child thread: %m");
2130 			exit(1);
2131 		}
2132 		if (GetExitCodeThread((HANDLE) bgchild_handle, &status) == 0)
2133 		{
2134 			_dosmaperr(GetLastError());
2135 			pg_log_error("could not get child thread exit status: %m");
2136 			exit(1);
2137 		}
2138 		if (status != 0)
2139 		{
2140 			pg_log_error("child thread exited with error %u",
2141 						 (unsigned int) status);
2142 			exit(1);
2143 		}
2144 		/* Exited normally, we're happy */
2145 #endif
2146 	}
2147 
2148 	/* Free the configuration file contents */
2149 	destroyPQExpBuffer(recoveryconfcontents);
2150 
2151 	/*
2152 	 * End of copy data. Final result is already checked inside the loop.
2153 	 */
2154 	PQclear(res);
2155 	PQfinish(conn);
2156 	conn = NULL;
2157 
2158 	/*
2159 	 * Make data persistent on disk once backup is completed. For tar format
2160 	 * sync the parent directory and all its contents as each tar file was not
2161 	 * synced after being completed.  In plain format, all the data of the
2162 	 * base directory is synced, taking into account all the tablespaces.
2163 	 * Errors are not considered fatal.
2164 	 */
2165 	if (do_sync)
2166 	{
2167 		if (verbose)
2168 			pg_log_info("syncing data to disk ...");
2169 		if (format == 't')
2170 		{
2171 			if (strcmp(basedir, "-") != 0)
2172 				(void) fsync_dir_recurse(basedir);
2173 		}
2174 		else
2175 		{
2176 			(void) fsync_pgdata(basedir, serverVersion);
2177 		}
2178 	}
2179 
2180 	if (verbose)
2181 		pg_log_info("base backup completed");
2182 }
2183 
2184 
2185 int
main(int argc,char ** argv)2186 main(int argc, char **argv)
2187 {
2188 	static struct option long_options[] = {
2189 		{"help", no_argument, NULL, '?'},
2190 		{"version", no_argument, NULL, 'V'},
2191 		{"pgdata", required_argument, NULL, 'D'},
2192 		{"format", required_argument, NULL, 'F'},
2193 		{"checkpoint", required_argument, NULL, 'c'},
2194 		{"create-slot", no_argument, NULL, 'C'},
2195 		{"max-rate", required_argument, NULL, 'r'},
2196 		{"write-recovery-conf", no_argument, NULL, 'R'},
2197 		{"slot", required_argument, NULL, 'S'},
2198 		{"tablespace-mapping", required_argument, NULL, 'T'},
2199 		{"wal-method", required_argument, NULL, 'X'},
2200 		{"gzip", no_argument, NULL, 'z'},
2201 		{"compress", required_argument, NULL, 'Z'},
2202 		{"label", required_argument, NULL, 'l'},
2203 		{"no-clean", no_argument, NULL, 'n'},
2204 		{"no-sync", no_argument, NULL, 'N'},
2205 		{"dbname", required_argument, NULL, 'd'},
2206 		{"host", required_argument, NULL, 'h'},
2207 		{"port", required_argument, NULL, 'p'},
2208 		{"username", required_argument, NULL, 'U'},
2209 		{"no-password", no_argument, NULL, 'w'},
2210 		{"password", no_argument, NULL, 'W'},
2211 		{"status-interval", required_argument, NULL, 's'},
2212 		{"verbose", no_argument, NULL, 'v'},
2213 		{"progress", no_argument, NULL, 'P'},
2214 		{"waldir", required_argument, NULL, 1},
2215 		{"no-slot", no_argument, NULL, 2},
2216 		{"no-verify-checksums", no_argument, NULL, 3},
2217 		{NULL, 0, NULL, 0}
2218 	};
2219 	int			c;
2220 
2221 	int			option_index;
2222 
2223 	pg_logging_init(argv[0]);
2224 	progname = get_progname(argv[0]);
2225 	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
2226 
2227 	if (argc > 1)
2228 	{
2229 		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2230 		{
2231 			usage();
2232 			exit(0);
2233 		}
2234 		else if (strcmp(argv[1], "-V") == 0
2235 				 || strcmp(argv[1], "--version") == 0)
2236 		{
2237 			puts("pg_basebackup (PostgreSQL) " PG_VERSION);
2238 			exit(0);
2239 		}
2240 	}
2241 
2242 	atexit(cleanup_directories_atexit);
2243 
2244 	while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNzZ:d:c:h:p:U:s:wWkvP",
2245 							long_options, &option_index)) != -1)
2246 	{
2247 		switch (c)
2248 		{
2249 			case 'C':
2250 				create_slot = true;
2251 				break;
2252 			case 'D':
2253 				basedir = pg_strdup(optarg);
2254 				break;
2255 			case 'F':
2256 				if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
2257 					format = 'p';
2258 				else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
2259 					format = 't';
2260 				else
2261 				{
2262 					pg_log_error("invalid output format \"%s\", must be \"plain\" or \"tar\"",
2263 								 optarg);
2264 					exit(1);
2265 				}
2266 				break;
2267 			case 'r':
2268 				maxrate = parse_max_rate(optarg);
2269 				break;
2270 			case 'R':
2271 				writerecoveryconf = true;
2272 				break;
2273 			case 'S':
2274 
2275 				/*
2276 				 * When specifying replication slot name, use a permanent
2277 				 * slot.
2278 				 */
2279 				replication_slot = pg_strdup(optarg);
2280 				temp_replication_slot = false;
2281 				break;
2282 			case 2:
2283 				no_slot = true;
2284 				break;
2285 			case 'T':
2286 				tablespace_list_append(optarg);
2287 				break;
2288 			case 'X':
2289 				if (strcmp(optarg, "n") == 0 ||
2290 					strcmp(optarg, "none") == 0)
2291 				{
2292 					includewal = NO_WAL;
2293 				}
2294 				else if (strcmp(optarg, "f") == 0 ||
2295 						 strcmp(optarg, "fetch") == 0)
2296 				{
2297 					includewal = FETCH_WAL;
2298 				}
2299 				else if (strcmp(optarg, "s") == 0 ||
2300 						 strcmp(optarg, "stream") == 0)
2301 				{
2302 					includewal = STREAM_WAL;
2303 				}
2304 				else
2305 				{
2306 					pg_log_error("invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"",
2307 								 optarg);
2308 					exit(1);
2309 				}
2310 				break;
2311 			case 1:
2312 				xlog_dir = pg_strdup(optarg);
2313 				break;
2314 			case 'l':
2315 				label = pg_strdup(optarg);
2316 				break;
2317 			case 'n':
2318 				noclean = true;
2319 				break;
2320 			case 'N':
2321 				do_sync = false;
2322 				break;
2323 			case 'z':
2324 #ifdef HAVE_LIBZ
2325 				compresslevel = Z_DEFAULT_COMPRESSION;
2326 #else
2327 				compresslevel = 1;	/* will be rejected below */
2328 #endif
2329 				break;
2330 			case 'Z':
2331 				compresslevel = atoi(optarg);
2332 				if (compresslevel < 0 || compresslevel > 9)
2333 				{
2334 					pg_log_error("invalid compression level \"%s\"", optarg);
2335 					exit(1);
2336 				}
2337 				break;
2338 			case 'c':
2339 				if (pg_strcasecmp(optarg, "fast") == 0)
2340 					fastcheckpoint = true;
2341 				else if (pg_strcasecmp(optarg, "spread") == 0)
2342 					fastcheckpoint = false;
2343 				else
2344 				{
2345 					pg_log_error("invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"",
2346 								 optarg);
2347 					exit(1);
2348 				}
2349 				break;
2350 			case 'd':
2351 				connection_string = pg_strdup(optarg);
2352 				break;
2353 			case 'h':
2354 				dbhost = pg_strdup(optarg);
2355 				break;
2356 			case 'p':
2357 				dbport = pg_strdup(optarg);
2358 				break;
2359 			case 'U':
2360 				dbuser = pg_strdup(optarg);
2361 				break;
2362 			case 'w':
2363 				dbgetpassword = -1;
2364 				break;
2365 			case 'W':
2366 				dbgetpassword = 1;
2367 				break;
2368 			case 's':
2369 				standby_message_timeout = atoi(optarg) * 1000;
2370 				if (standby_message_timeout < 0)
2371 				{
2372 					pg_log_error("invalid status interval \"%s\"", optarg);
2373 					exit(1);
2374 				}
2375 				break;
2376 			case 'v':
2377 				verbose++;
2378 				break;
2379 			case 'P':
2380 				showprogress = true;
2381 				break;
2382 			case 3:
2383 				verify_checksums = false;
2384 				break;
2385 			default:
2386 
2387 				/*
2388 				 * getopt_long already emitted a complaint
2389 				 */
2390 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2391 						progname);
2392 				exit(1);
2393 		}
2394 	}
2395 
2396 	/*
2397 	 * Any non-option arguments?
2398 	 */
2399 	if (optind < argc)
2400 	{
2401 		pg_log_error("too many command-line arguments (first is \"%s\")",
2402 					 argv[optind]);
2403 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2404 				progname);
2405 		exit(1);
2406 	}
2407 
2408 	/*
2409 	 * Required arguments
2410 	 */
2411 	if (basedir == NULL)
2412 	{
2413 		pg_log_error("no target directory specified");
2414 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2415 				progname);
2416 		exit(1);
2417 	}
2418 
2419 	/*
2420 	 * Mutually exclusive arguments
2421 	 */
2422 	if (format == 'p' && compresslevel != 0)
2423 	{
2424 		pg_log_error("only tar mode backups can be compressed");
2425 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2426 				progname);
2427 		exit(1);
2428 	}
2429 
2430 	if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
2431 	{
2432 		pg_log_error("cannot stream write-ahead logs in tar mode to stdout");
2433 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2434 				progname);
2435 		exit(1);
2436 	}
2437 
2438 	if (replication_slot && includewal != STREAM_WAL)
2439 	{
2440 		pg_log_error("replication slots can only be used with WAL streaming");
2441 		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2442 				progname);
2443 		exit(1);
2444 	}
2445 
2446 	if (no_slot)
2447 	{
2448 		if (replication_slot)
2449 		{
2450 			pg_log_error("--no-slot cannot be used with slot name");
2451 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2452 					progname);
2453 			exit(1);
2454 		}
2455 		temp_replication_slot = false;
2456 	}
2457 
2458 	if (create_slot)
2459 	{
2460 		if (!replication_slot)
2461 		{
2462 			pg_log_error("%s needs a slot to be specified using --slot",
2463 						 "--create-slot");
2464 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2465 					progname);
2466 			exit(1);
2467 		}
2468 
2469 		if (no_slot)
2470 		{
2471 			pg_log_error("--create-slot and --no-slot are incompatible options");
2472 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2473 					progname);
2474 			exit(1);
2475 		}
2476 	}
2477 
2478 	if (xlog_dir)
2479 	{
2480 		if (format != 'p')
2481 		{
2482 			pg_log_error("WAL directory location can only be specified in plain mode");
2483 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2484 					progname);
2485 			exit(1);
2486 		}
2487 
2488 		/* clean up xlog directory name, check it's absolute */
2489 		canonicalize_path(xlog_dir);
2490 		if (!is_absolute_path(xlog_dir))
2491 		{
2492 			pg_log_error("WAL directory location must be an absolute path");
2493 			fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2494 					progname);
2495 			exit(1);
2496 		}
2497 	}
2498 
2499 #ifndef HAVE_LIBZ
2500 	if (compresslevel != 0)
2501 	{
2502 		pg_log_error("this build does not support compression");
2503 		exit(1);
2504 	}
2505 #endif
2506 
2507 	/* connection in replication mode to server */
2508 	conn = GetConnection();
2509 	if (!conn)
2510 	{
2511 		/* Error message already written in GetConnection() */
2512 		exit(1);
2513 	}
2514 	atexit(disconnect_atexit);
2515 
2516 	/*
2517 	 * Set umask so that directories/files are created with the same
2518 	 * permissions as directories/files in the source data directory.
2519 	 *
2520 	 * pg_mode_mask is set to owner-only by default and then updated in
2521 	 * GetConnection() where we get the mode from the server-side with
2522 	 * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
2523 	 */
2524 	umask(pg_mode_mask);
2525 
2526 	/*
2527 	 * Verify that the target directory exists, or create it. For plaintext
2528 	 * backups, always require the directory. For tar backups, require it
2529 	 * unless we are writing to stdout.
2530 	 */
2531 	if (format == 'p' || strcmp(basedir, "-") != 0)
2532 		verify_dir_is_empty_or_create(basedir, &made_new_pgdata, &found_existing_pgdata);
2533 
2534 	/* determine remote server's xlog segment size */
2535 	if (!RetrieveWalSegSize(conn))
2536 		exit(1);
2537 
2538 	/* Create pg_wal symlink, if required */
2539 	if (xlog_dir)
2540 	{
2541 		char	   *linkloc;
2542 
2543 		verify_dir_is_empty_or_create(xlog_dir, &made_new_xlogdir, &found_existing_xlogdir);
2544 
2545 		/*
2546 		 * Form name of the place where the symlink must go. pg_xlog has been
2547 		 * renamed to pg_wal in post-10 clusters.
2548 		 */
2549 		linkloc = psprintf("%s/%s", basedir,
2550 						   PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
2551 						   "pg_xlog" : "pg_wal");
2552 
2553 #ifdef HAVE_SYMLINK
2554 		if (symlink(xlog_dir, linkloc) != 0)
2555 		{
2556 			pg_log_error("could not create symbolic link \"%s\": %m", linkloc);
2557 			exit(1);
2558 		}
2559 #else
2560 		pg_log_error("symlinks are not supported on this platform");
2561 		exit(1);
2562 #endif
2563 		free(linkloc);
2564 	}
2565 
2566 	BaseBackup();
2567 
2568 	success = true;
2569 	return 0;
2570 }
2571