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