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