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, ©buf, 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, ©buf, 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(©buf[124], 12);
1484
1485 /* Set permissions on the file */
1486 filemode = read_tar_number(©buf[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(©buf[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