LCOV - differential code coverage report
Current view: top level - src/bin/pg_basebackup - pg_basebackup.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 70.1 % 980 687 24 54 180 35 80 365 36 206 167 379 11 48
Current Date: 2023-04-08 17:13:01 Functions: 78.1 % 32 25 7 24 1 7 24 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 54.0 % 50 27 23 27
Legend: Lines: hit not hit (120,180] days: 100.0 % 5 5 1 3 1 1
(180,240] days: 40.0 % 10 4 1 5 1 2 1
(240..) days: 71.1 % 915 651 1 53 175 35 79 364 4 204 167 378
Function coverage date bins:
(120,180] days: 100.0 % 1 1 1
(240..) days: 38.7 % 62 24 7 24 7 24

 Age         Owner                  TLA  Line data    Source code
                                  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-2023, 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 <limits.h>
                                 19                 : #include <sys/select.h>
                                 20                 : #include <sys/stat.h>
                                 21                 : #include <sys/wait.h>
                                 22                 : #include <signal.h>
                                 23                 : #include <time.h>
                                 24                 : #ifdef HAVE_LIBZ
                                 25                 : #include <zlib.h>
                                 26                 : #endif
                                 27                 : 
                                 28                 : #include "access/xlog_internal.h"
                                 29                 : #include "backup/basebackup.h"
                                 30                 : #include "bbstreamer.h"
                                 31                 : #include "common/compression.h"
                                 32                 : #include "common/file_perm.h"
                                 33                 : #include "common/file_utils.h"
                                 34                 : #include "common/logging.h"
                                 35                 : #include "fe_utils/option_utils.h"
                                 36                 : #include "fe_utils/recovery_gen.h"
                                 37                 : #include "getopt_long.h"
                                 38                 : #include "receivelog.h"
                                 39                 : #include "streamutil.h"
                                 40                 : 
                                 41                 : #define ERRCODE_DATA_CORRUPTED  "XX001"
                                 42                 : 
                                 43                 : typedef struct TablespaceListCell
                                 44                 : {
                                 45                 :     struct TablespaceListCell *next;
                                 46                 :     char        old_dir[MAXPGPATH];
                                 47                 :     char        new_dir[MAXPGPATH];
                                 48                 : } TablespaceListCell;
                                 49                 : 
                                 50                 : typedef struct TablespaceList
                                 51                 : {
                                 52                 :     TablespaceListCell *head;
                                 53                 :     TablespaceListCell *tail;
                                 54                 : } TablespaceList;
                                 55                 : 
                                 56                 : typedef struct ArchiveStreamState
                                 57                 : {
                                 58                 :     int         tablespacenum;
                                 59                 :     pg_compress_specification *compress;
                                 60                 :     bbstreamer *streamer;
                                 61                 :     bbstreamer *manifest_inject_streamer;
                                 62                 :     PQExpBuffer manifest_buffer;
                                 63                 :     char        manifest_filename[MAXPGPATH];
                                 64                 :     FILE       *manifest_file;
                                 65                 : } ArchiveStreamState;
                                 66                 : 
                                 67                 : typedef struct WriteTarState
                                 68                 : {
                                 69                 :     int         tablespacenum;
                                 70                 :     bbstreamer *streamer;
                                 71                 : } WriteTarState;
                                 72                 : 
                                 73                 : typedef struct WriteManifestState
                                 74                 : {
                                 75                 :     char        filename[MAXPGPATH];
                                 76                 :     FILE       *file;
                                 77                 : } WriteManifestState;
                                 78                 : 
                                 79                 : typedef void (*WriteDataCallback) (size_t nbytes, char *buf,
                                 80                 :                                    void *callback_data);
                                 81                 : 
                                 82                 : /*
                                 83                 :  * pg_xlog has been renamed to pg_wal in version 10.  This version number
                                 84                 :  * should be compared with PQserverVersion().
                                 85                 :  */
                                 86                 : #define MINIMUM_VERSION_FOR_PG_WAL  100000
                                 87                 : 
                                 88                 : /*
                                 89                 :  * Temporary replication slots are supported from version 10.
                                 90                 :  */
                                 91                 : #define MINIMUM_VERSION_FOR_TEMP_SLOTS 100000
                                 92                 : 
                                 93                 : /*
                                 94                 :  * Backup manifests are supported from version 13.
                                 95                 :  */
                                 96                 : #define MINIMUM_VERSION_FOR_MANIFESTS   130000
                                 97                 : 
                                 98                 : /*
                                 99                 :  * Before v15, tar files received from the server will be improperly
                                100                 :  * terminated.
                                101                 :  */
                                102                 : #define MINIMUM_VERSION_FOR_TERMINATED_TARFILE 150000
                                103                 : 
                                104                 : /*
                                105                 :  * Different ways to include WAL
                                106                 :  */
                                107                 : typedef enum
                                108                 : {
                                109                 :     NO_WAL,
                                110                 :     FETCH_WAL,
                                111                 :     STREAM_WAL
                                112                 : } IncludeWal;
                                113                 : 
                                114                 : /*
                                115                 :  * Different places to perform compression
                                116                 :  */
                                117                 : typedef enum
                                118                 : {
                                119                 :     COMPRESS_LOCATION_UNSPECIFIED,
                                120                 :     COMPRESS_LOCATION_CLIENT,
                                121                 :     COMPRESS_LOCATION_SERVER
                                122                 : } CompressionLocation;
                                123                 : 
                                124                 : /* Global options */
                                125                 : static char *basedir = NULL;
                                126                 : static TablespaceList tablespace_dirs = {NULL, NULL};
                                127                 : static char *xlog_dir = NULL;
                                128                 : static char format = '\0';      /* p(lain)/t(ar) */
                                129                 : static char *label = "pg_basebackup base backup";
                                130                 : static bool noclean = false;
                                131                 : static bool checksum_failure = false;
                                132                 : static bool showprogress = false;
                                133                 : static bool estimatesize = true;
                                134                 : static int  verbose = 0;
                                135                 : static IncludeWal includewal = STREAM_WAL;
                                136                 : static bool fastcheckpoint = false;
                                137                 : static bool writerecoveryconf = false;
                                138                 : static bool do_sync = true;
                                139                 : static int  standby_message_timeout = 10 * 1000;    /* 10 sec = default */
                                140                 : static pg_time_t last_progress_report = 0;
                                141                 : static int32 maxrate = 0;       /* no limit by default */
                                142                 : static char *replication_slot = NULL;
                                143                 : static bool temp_replication_slot = true;
                                144                 : static char *backup_target = NULL;
                                145                 : static bool create_slot = false;
                                146                 : static bool no_slot = false;
                                147                 : static bool verify_checksums = true;
                                148                 : static bool manifest = true;
                                149                 : static bool manifest_force_encode = false;
                                150                 : static char *manifest_checksums = NULL;
                                151                 : 
                                152                 : static bool success = false;
                                153                 : static bool made_new_pgdata = false;
                                154                 : static bool found_existing_pgdata = false;
                                155                 : static bool made_new_xlogdir = false;
                                156                 : static bool found_existing_xlogdir = false;
                                157                 : static bool made_tablespace_dirs = false;
                                158                 : static bool found_tablespace_dirs = false;
                                159                 : 
                                160                 : /* Progress indicators */
                                161                 : static uint64 totalsize_kb;
                                162                 : static uint64 totaldone;
                                163                 : static int  tablespacecount;
                                164                 : static char *progress_filename = NULL;
                                165                 : 
                                166                 : /* Pipe to communicate with background wal receiver process */
                                167                 : #ifndef WIN32
                                168                 : static int  bgpipe[2] = {-1, -1};
                                169                 : #endif
                                170                 : 
                                171                 : /* Handle to child process */
                                172                 : static pid_t bgchild = -1;
                                173                 : static bool in_log_streamer = false;
                                174                 : 
                                175                 : /* Flag to indicate if child process exited unexpectedly */
                                176                 : static volatile sig_atomic_t bgchild_exited = false;
                                177                 : 
                                178                 : /* End position for xlog streaming, empty string if unknown yet */
                                179                 : static XLogRecPtr xlogendptr;
                                180                 : 
                                181                 : #ifndef WIN32
                                182                 : static int  has_xlogendptr = 0;
                                183                 : #else
                                184                 : static volatile LONG has_xlogendptr = 0;
                                185                 : #endif
                                186                 : 
                                187                 : /* Contents of configuration file to be generated */
                                188                 : static PQExpBuffer recoveryconfcontents = NULL;
                                189                 : 
                                190                 : /* Function headers */
                                191                 : static void usage(void);
                                192                 : static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found);
                                193                 : static void progress_update_filename(const char *filename);
                                194                 : static void progress_report(int tablespacenum, bool force, bool finished);
                                195                 : 
                                196                 : static bbstreamer *CreateBackupStreamer(char *archive_name, char *spclocation,
                                197                 :                                         bbstreamer **manifest_inject_streamer_p,
                                198                 :                                         bool is_recovery_guc_supported,
                                199                 :                                         bool expect_unterminated_tarfile,
                                200                 :                                         pg_compress_specification *compress);
                                201                 : static void ReceiveArchiveStreamChunk(size_t r, char *copybuf,
                                202                 :                                       void *callback_data);
                                203                 : static char GetCopyDataByte(size_t r, char *copybuf, size_t *cursor);
                                204                 : static char *GetCopyDataString(size_t r, char *copybuf, size_t *cursor);
                                205                 : static uint64 GetCopyDataUInt64(size_t r, char *copybuf, size_t *cursor);
                                206                 : static void GetCopyDataEnd(size_t r, char *copybuf, size_t cursor);
                                207                 : static void ReportCopyDataParseError(size_t r, char *copybuf);
                                208                 : static void ReceiveTarFile(PGconn *conn, char *archive_name, char *spclocation,
                                209                 :                            bool tablespacenum, pg_compress_specification *compress);
                                210                 : static void ReceiveTarCopyChunk(size_t r, char *copybuf, void *callback_data);
                                211                 : static void ReceiveBackupManifest(PGconn *conn);
                                212                 : static void ReceiveBackupManifestChunk(size_t r, char *copybuf,
                                213                 :                                        void *callback_data);
                                214                 : static void ReceiveBackupManifestInMemory(PGconn *conn, PQExpBuffer buf);
                                215                 : static void ReceiveBackupManifestInMemoryChunk(size_t r, char *copybuf,
                                216                 :                                                void *callback_data);
                                217                 : static void BaseBackup(char *compression_algorithm, char *compression_detail,
                                218                 :                        CompressionLocation compressloc,
                                219                 :                        pg_compress_specification *client_compress);
                                220                 : 
                                221                 : static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline,
                                222                 :                                  bool segment_finished);
                                223                 : 
                                224                 : static const char *get_tablespace_mapping(const char *dir);
                                225                 : static void tablespace_list_append(const char *arg);
                                226                 : 
 3346 magnus                    227 ECB             : 
                                228                 : static void
 2400 peter_e                   229 CBC         268 : cleanup_directories_atexit(void)
 2400 peter_e                   230 ECB             : {
 2400 peter_e                   231 GIC         268 :     if (success || in_log_streamer)
 2400 peter_e                   232 CBC         211 :         return;
                                233                 : 
 1832 magnus                    234              57 :     if (!noclean && !checksum_failure)
                                235                 :     {
 2400 peter_e                   236              53 :         if (made_new_pgdata)
 2400 peter_e                   237 ECB             :         {
 1469 peter                     238 GBC          17 :             pg_log_info("removing data directory \"%s\"", basedir);
 2400 peter_e                   239 GIC          17 :             if (!rmtree(basedir, true))
 1469 peter                     240 LBC           0 :                 pg_log_error("failed to remove data directory");
                                241                 :         }
 2400 peter_e                   242 GBC          36 :         else if (found_existing_pgdata)
 2400 peter_e                   243 EUB             :         {
 1469 peter                     244 UBC           0 :             pg_log_info("removing contents of data directory \"%s\"", basedir);
 2400 peter_e                   245 UIC           0 :             if (!rmtree(basedir, false))
 1469 peter                     246               0 :                 pg_log_error("failed to remove contents of data directory");
 2400 peter_e                   247 ECB             :         }
                                248                 : 
 2400 peter_e                   249 GBC          53 :         if (made_new_xlogdir)
 2400 peter_e                   250 EUB             :         {
 1469 peter                     251 UBC           0 :             pg_log_info("removing WAL directory \"%s\"", xlog_dir);
 2400 peter_e                   252 UIC           0 :             if (!rmtree(xlog_dir, true))
 1469 peter                     253 LBC           0 :                 pg_log_error("failed to remove WAL directory");
                                254                 :         }
 2400 peter_e                   255 GBC          53 :         else if (found_existing_xlogdir)
 2400 peter_e                   256 EUB             :         {
 1469 peter                     257 UBC           0 :             pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir);
 2400 peter_e                   258 UIC           0 :             if (!rmtree(xlog_dir, false))
 1469 peter                     259               0 :                 pg_log_error("failed to remove contents of WAL directory");
                                260                 :         }
                                261                 :     }
 2400 peter_e                   262 ECB             :     else
 2400 peter_e                   263 EUB             :     {
 1832 magnus                    264 GIC           4 :         if ((made_new_pgdata || found_existing_pgdata) && !checksum_failure)
 1469 peter                     265 LBC           0 :             pg_log_info("data directory \"%s\" not removed at user's request", basedir);
 2400 peter_e                   266 EUB             : 
 2400 peter_e                   267 GIC           4 :         if (made_new_xlogdir || found_existing_xlogdir)
 1469 peter                     268 UIC           0 :             pg_log_info("WAL directory \"%s\" not removed at user's request", xlog_dir);
 2400 peter_e                   269 ECB             :     }
 2400 peter_e                   270 EUB             : 
 1832 magnus                    271 GIC          57 :     if ((made_tablespace_dirs || found_tablespace_dirs) && !checksum_failure)
 1469 peter                     272 UIC           0 :         pg_log_info("changes to tablespace directories will not be undone");
                                273                 : }
 2400 peter_e                   274 ECB             : 
                                275                 : static void
 1562 peter                     276 CBC         236 : disconnect_atexit(void)
 3346 magnus                    277 ECB             : {
 3346 magnus                    278 CBC         236 :     if (conn != NULL)
 3346 magnus                    279 GIC         119 :         PQfinish(conn);
 1562 peter                     280             236 : }
                                281                 : 
                                282                 : #ifndef WIN32
                                283                 : /*
                                284                 :  * If the bgchild exits prematurely and raises a SIGCHLD signal, we can abort
                                285                 :  * processing rather than wait until the backup has finished and error out at
                                286                 :  * that time. On Windows, we use a background thread which can communicate
                                287                 :  * without the need for a signal handler.
  410 dgustafsson               288 ECB             :  */
                                289                 : static void
  410 dgustafsson               290 CBC          96 : sigchld_handler(SIGNAL_ARGS)
  410 dgustafsson               291 ECB             : {
  410 dgustafsson               292 GIC          96 :     bgchild_exited = true;
                                293              96 : }
                                294                 : 
                                295                 : /*
                                296                 :  * On windows, our background thread dies along with the process. But on
                                297                 :  * Unix, if we have started a subprocess, we want to kill it off so it
                                298                 :  * doesn't remain running trying to stream data.
 1562 peter                     299 ECB             :  */
                                300                 : static void
 1562 peter                     301 CBC          98 : kill_bgchild_atexit(void)
 1562 peter                     302 ECB             : {
  410 dgustafsson               303 CBC          98 :     if (bgchild > 0 && !bgchild_exited)
 3346 magnus                    304 GIC           4 :         kill(bgchild, SIGTERM);
                                305              98 : }
                                306                 : #endif
                                307                 : 
                                308                 : /*
                                309                 :  * Split argument into old_dir and new_dir and append to tablespace mapping
                                310                 :  * list.
 3333 peter_e                   311 ECB             :  */
                                312                 : static void
 3333 peter_e                   313 CBC          19 : tablespace_list_append(const char *arg)
                                314                 : {
 3333 peter_e                   315 GIC          19 :     TablespaceListCell *cell = (TablespaceListCell *) pg_malloc0(sizeof(TablespaceListCell));
                                316                 :     char       *dst;
                                317                 :     char       *dst_ptr;
 3260 bruce                     318 ECB             :     const char *arg_ptr;
 3333 peter_e                   319                 : 
 3333 peter_e                   320 GIC          19 :     dst_ptr = dst = cell->old_dir;
 3333 peter_e                   321 CBC         634 :     for (arg_ptr = arg; *arg_ptr; arg_ptr++)
 3333 peter_e                   322 EUB             :     {
 3333 peter_e                   323 GIC         616 :         if (dst_ptr - dst >= MAXPGPATH)
  366 tgl                       324 LBC           0 :             pg_fatal("directory name too long");
                                325                 : 
 3333 peter_e                   326 CBC         616 :         if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
                                327                 :             ;                   /* skip backslash escaping = */
                                328             614 :         else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
 3333 peter_e                   329 ECB             :         {
 3333 peter_e                   330 GIC          19 :             if (*cell->new_dir)
  366 tgl                       331 CBC           1 :                 pg_fatal("multiple \"=\" signs in tablespace mapping");
                                332                 :             else
 3333 peter_e                   333 GIC          18 :                 dst = dst_ptr = cell->new_dir;
 3333 peter_e                   334 ECB             :         }
                                335                 :         else
 3333 peter_e                   336 GIC         595 :             *dst_ptr++ = *arg_ptr;
 3333 peter_e                   337 ECB             :     }
                                338                 : 
 3333 peter_e                   339 GIC          18 :     if (!*cell->old_dir || !*cell->new_dir)
  366 tgl                       340               3 :         pg_fatal("invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"", arg);
                                341                 : 
                                342                 :     /*
                                343                 :      * All tablespaces are created with absolute directories, so specifying a
                                344                 :      * non-absolute path here would just never match, possibly confusing users.
                                345                 :      * Since we don't know whether the remote side is Windows or not, and it
                                346                 :      * might be different than the local side, permit any path that could be
                                347                 :      * absolute under either set of rules.
                                348                 :      *
                                349                 :      * (There is little practical risk of confusion here, because someone
                                350                 :      * running entirely on Linux isn't likely to have a relative path that
                                351                 :      * begins with a backslash or something that looks like a drive
                                352                 :      * specification. If they do, and they also incorrectly believe that
                                353                 :      * a relative path is acceptable here, we'll silently fail to warn them
                                354                 :      * of their mistake, and the -T option will just not get applied, same
  170 rhaas                     355 ECB             :      * as if they'd specified -T for a nonexistent tablespace.)
 3260 bruce                     356                 :      */
  170 rhaas                     357 CBC          15 :     if (!is_nonwindows_absolute_path(cell->old_dir) &&
  170 rhaas                     358 GIC           1 :         !is_windows_absolute_path(cell->old_dir))
  366 tgl                       359               1 :         pg_fatal("old directory is not an absolute path in tablespace mapping: %s",
  366 tgl                       360 ECB             :                  cell->old_dir);
 3333 peter_e                   361                 : 
 3333 peter_e                   362 GIC          14 :     if (!is_absolute_path(cell->new_dir))
  366 tgl                       363               1 :         pg_fatal("new directory is not an absolute path in tablespace mapping: %s",
                                364                 :                  cell->new_dir);
                                365                 : 
                                366                 :     /*
                                367                 :      * Comparisons done with these values should involve similarly
                                368                 :      * canonicalized path values.  This is particularly sensitive on Windows
 1985 peter_e                   369 ECB             :      * where path values may not necessarily use Unix slashes.
                                370                 :      */
 2903 bruce                     371 GIC          13 :     canonicalize_path(cell->old_dir);
 2903 bruce                     372 CBC          13 :     canonicalize_path(cell->new_dir);
 2903 bruce                     373 EUB             : 
 3333 peter_e                   374 GIC          13 :     if (tablespace_dirs.tail)
 3333 peter_e                   375 LBC           0 :         tablespace_dirs.tail->next = cell;
 3333 peter_e                   376 ECB             :     else
 3333 peter_e                   377 CBC          13 :         tablespace_dirs.head = cell;
 3333 peter_e                   378 GIC          13 :     tablespace_dirs.tail = cell;
                                379              13 : }
                                380                 : 
 3333 peter_e                   381 ECB             : 
                                382                 : static void
 4459 magnus                    383 CBC           1 : usage(void)
                                384                 : {
 4358 peter_e                   385               1 :     printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
 4459 magnus                    386 ECB             :            progname);
 4459 magnus                    387 CBC           1 :     printf(_("Usage:\n"));
                                388               1 :     printf(_("  %s [OPTION]...\n"), progname);
                                389               1 :     printf(_("\nOptions controlling the output:\n"));
 3904 alvherre                  390               1 :     printf(_("  -D, --pgdata=DIRECTORY receive base backup into directory\n"));
 3904 alvherre                  391 GIC           1 :     printf(_("  -F, --format=p|t       output format (plain (default), tar)\n"));
 2153 tgl                       392 CBC           1 :     printf(_("  -r, --max-rate=RATE    maximum transfer rate to transfer data directory\n"
                                393                 :              "                         (in kB/s, or use suffix \"k\" or \"M\")\n"));
                                394               1 :     printf(_("  -R, --write-recovery-conf\n"
                                395                 :              "                         write configuration for replication\n"));
  363 peter                     396               1 :     printf(_("  -t, --target=TARGET[:DETAIL]\n"
                                397                 :              "                         backup target (if other than client)\n"));
 2153 tgl                       398               1 :     printf(_("  -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
 2118 tgl                       399 ECB             :              "                         relocate tablespace in OLDDIR to NEWDIR\n"));
 2021 peter_e                   400 GIC           1 :     printf(_("      --waldir=WALDIR    location for the write-ahead log directory\n"));
 2153 tgl                       401 CBC           1 :     printf(_("  -X, --wal-method=none|fetch|stream\n"
 2153 tgl                       402 ECB             :              "                         include required WAL files with specified method\n"));
 3904 alvherre                  403 GIC           1 :     printf(_("  -z, --gzip             compress tar output\n"));
  382 rhaas                     404 CBC           1 :     printf(_("  -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n"
  382 rhaas                     405 ECB             :              "                         compress on client or server as specified\n"));
  398 rhaas                     406 CBC           1 :     printf(_("  -Z, --compress=none    do not compress tar output\n"));
 4459 magnus                    407 GIC           1 :     printf(_("\nGeneral options:\n"));
 2153 tgl                       408 CBC           1 :     printf(_("  -c, --checkpoint=fast|spread\n"
 2153 tgl                       409 ECB             :              "                         set fast or spread checkpointing\n"));
 2021 peter_e                   410 CBC           1 :     printf(_("  -C, --create-slot      create replication slot\n"));
 3904 alvherre                  411               1 :     printf(_("  -l, --label=LABEL      set backup label\n"));
 2363 peter_e                   412               1 :     printf(_("  -n, --no-clean         do not clean up after errors\n"));
                                413               1 :     printf(_("  -N, --no-sync          do not wait for changes to be written safely to disk\n"));
 3904 alvherre                  414               1 :     printf(_("  -P, --progress         show progress information\n"));
 2021 peter_e                   415               1 :     printf(_("  -S, --slot=SLOTNAME    replication slot to use\n"));
 3904 alvherre                  416               1 :     printf(_("  -v, --verbose          output verbose messages\n"));
 3904 alvherre                  417 GIC           1 :     printf(_("  -V, --version          output version information, then exit\n"));
 1073 peter                     418 CBC           1 :     printf(_("      --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n"
                                419                 :              "                         use algorithm for manifest checksums\n"));
                                420               1 :     printf(_("      --manifest-force-encode\n"
 1073 peter                     421 ECB             :              "                         hex encode all file names in manifest\n"));
 1073 peter                     422 CBC           1 :     printf(_("      --no-estimate-size do not estimate backup size in server side\n"));
                                423               1 :     printf(_("      --no-manifest      suppress generation of backup manifest\n"));
 1784 peter_e                   424 GIC           1 :     printf(_("      --no-slot          prevent creation of temporary replication slot\n"));
 1784 peter_e                   425 CBC           1 :     printf(_("      --no-verify-checksums\n"
 1784 peter_e                   426 ECB             :              "                         do not verify checksums\n"));
 3904 alvherre                  427 CBC           1 :     printf(_("  -?, --help             show this help, then exit\n"));
 4459 magnus                    428               1 :     printf(_("\nConnection options:\n"));
 3695 heikki.linnakangas        429               1 :     printf(_("  -d, --dbname=CONNSTR   connection string\n"));
 3904 alvherre                  430               1 :     printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
 3904 alvherre                  431 GIC           1 :     printf(_("  -p, --port=PORT        database server port number\n"));
 2153 tgl                       432 CBC           1 :     printf(_("  -s, --status-interval=INTERVAL\n"
 2153 tgl                       433 ECB             :              "                         time between status packets sent to server (in seconds)\n"));
 3904 alvherre                  434 CBC           1 :     printf(_("  -U, --username=NAME    connect as specified database user\n"));
                                435               1 :     printf(_("  -w, --no-password      never prompt for password\n"));
                                436               1 :     printf(_("  -W, --password         force password prompt (should happen automatically)\n"));
 1136 peter                     437               1 :     printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
 1136 peter                     438 GIC           1 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
 4459 magnus                    439               1 : }
                                440                 : 
                                441                 : 
                                442                 : /*
                                443                 :  * Called in the background process every time data is received.
                                444                 :  * On Unix, we check to see if there is any data on our pipe
                                445                 :  * (which would mean we have a stop position), and if it is, check if
                                446                 :  * it is time to stop.
                                447                 :  * On Windows, we are in a single process, so we can just check if it's
                                448                 :  * time to stop.
 4183 magnus                    449 ECB             :  */
                                450                 : static bool
 3904 alvherre                  451 GIC       10313 : reached_end_position(XLogRecPtr segendpos, uint32 timeline,
 3904 alvherre                  452 ECB             :                      bool segment_finished)
                                453                 : {
 4183 magnus                    454 GIC       10313 :     if (!has_xlogendptr)
                                455                 :     {
 4183 magnus                    456 ECB             : #ifndef WIN32
                                457                 :         fd_set      fds;
  267 peter                     458 GNC       10221 :         struct timeval tv = {0};
                                459                 :         int         r;
                                460                 : 
                                461                 :         /*
                                462                 :          * Don't have the end pointer yet - check our pipe to see if it has
 4183 magnus                    463 ECB             :          * been sent yet.
                                464                 :          */
 4183 magnus                    465 GIC      173757 :         FD_ZERO(&fds);
 4183 magnus                    466 CBC       10221 :         FD_SET(bgpipe[0], &fds);
 4183 magnus                    467 ECB             : 
 4183 magnus                    468 GIC       10221 :         r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
                                469           10221 :         if (r == 1)
                                470                 :         {
  267 peter                     471 GNC          91 :             char        xlogend[64] = {0};
 3941 heikki.linnakangas        472 ECB             :             uint32      hi,
 3941 heikki.linnakangas        473 EUB             :                         lo;
                                474                 : 
 3260 bruce                     475 GBC          91 :             r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
 4183 magnus                    476 GIC          91 :             if (r < 0)
  366 tgl                       477 LBC           0 :                 pg_fatal("could not read from ready pipe: %m");
 4183 magnus                    478 ECB             : 
 3941 heikki.linnakangas        479 GIC          91 :             if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
  366 tgl                       480 UIC           0 :                 pg_fatal("could not parse write-ahead log location \"%s\"",
                                481                 :                          xlogend);
 3941 heikki.linnakangas        482 GIC          91 :             xlogendptr = ((uint64) hi) << 32 | lo;
 4183 magnus                    483              91 :             has_xlogendptr = 1;
                                484                 : 
                                485                 :             /*
                                486                 :              * Fall through to check if we've reached the point further
                                487                 :              * already.
                                488                 :              */
                                489                 :         }
                                490                 :         else
 4183 magnus                    491 ECB             :         {
                                492                 :             /*
                                493                 :              * No data received on the pipe means we don't know the end
                                494                 :              * position yet - so just say it's not time to stop yet.
                                495                 :              */
 4183 magnus                    496 GIC       10130 :             return false;
                                497                 :         }
                                498                 : #else
                                499                 : 
                                500                 :         /*
                                501                 :          * On win32, has_xlogendptr is set by the main thread, so if it's not
                                502                 :          * set here, we just go back and wait until it shows up.
                                503                 :          */
                                504                 :         return false;
                                505                 : #endif
                                506                 :     }
 4183 magnus                    507 ECB             : 
                                508                 :     /*
                                509                 :      * At this point we have an end pointer, so compare it to the current
                                510                 :      * position to figure out if it's time to stop.
                                511                 :      */
 3941 heikki.linnakangas        512 GIC         183 :     if (segendpos >= xlogendptr)
 4183 magnus                    513             182 :         return true;
 4183 magnus                    514 ECB             : 
                                515                 :     /*
                                516                 :      * Have end pointer, but haven't reached it yet - so tell the caller to
                                517                 :      * keep streaming.
                                518                 :      */
 4183 magnus                    519 GIC           1 :     return false;
                                520                 : }
                                521                 : 
                                522                 : typedef struct
                                523                 : {
                                524                 :     PGconn     *bgconn;
                                525                 :     XLogRecPtr  startptr;
                                526                 :     char        xlog[MAXPGPATH];    /* directory or tarfile depending on mode */
                                527                 :     char       *sysidentifier;
                                528                 :     int         timeline;
  362 michael                   529 ECB             :     pg_compress_algorithm wal_compress_algorithm;
                                530                 :     int         wal_compress_level;
 3955 bruce                     531                 : } logstreamer_param;
                                532                 : 
 4183 magnus                    533                 : static int
  382 rhaas                     534 GIC          94 : LogStreamerMain(logstreamer_param *param)
 4183 magnus                    535 ECB             : {
  267 peter                     536 GNC          94 :     StreamCtl   stream = {0};
 2585 magnus                    537 ECB             : 
 2400 peter_e                   538 CBC          94 :     in_log_streamer = true;
                                539                 : 
 2585 magnus                    540 GIC          94 :     stream.startpos = param->startptr;
                                541              94 :     stream.timeline = param->timeline;
                                542              94 :     stream.sysidentifier = param->sysidentifier;
 2585 magnus                    543 CBC          94 :     stream.stream_stop = reached_end_position;
 2173 tgl                       544 ECB             : #ifndef WIN32
 2173 tgl                       545 GIC          94 :     stream.stop_socket = bgpipe[0];
 2173 tgl                       546 ECB             : #else
                                547                 :     stream.stop_socket = PGINVALID_SOCKET;
                                548                 : #endif
 2585 magnus                    549 CBC          94 :     stream.standby_message_timeout = standby_message_timeout;
                                550              94 :     stream.synchronous = false;
 1313 michael                   551 ECB             :     /* fsync happens at the end of pg_basebackup for all data */
 1313 michael                   552 GIC          94 :     stream.do_sync = false;
 2585 magnus                    553 CBC          94 :     stream.mark_done = true;
 2585 magnus                    554 GIC          94 :     stream.partial_suffix = NULL;
 2274 magnus                    555 CBC          94 :     stream.replication_slot = replication_slot;
 2359 magnus                    556 GIC          94 :     if (format == 'p')
  521 michael                   557              87 :         stream.walmethod = CreateWalDirectoryMethod(param->xlog,
  362 michael                   558 ECB             :                                                     PG_COMPRESSION_NONE, 0,
 1313 michael                   559 GIC          87 :                                                     stream.do_sync);
  422 rhaas                     560 ECB             :     else
  422 rhaas                     561 GIC           7 :         stream.walmethod = CreateWalTarMethod(param->xlog,
                                562                 :                                               param->wal_compress_algorithm,
                                563                 :                                               param->wal_compress_level,
                                564               7 :                                               stream.do_sync);
                                565                 : 
 2585 magnus                    566              94 :     if (!ReceiveXlogStream(param->bgconn, &stream))
                                567                 :     {
                                568                 :         /*
                                569                 :          * Any errors will already have been reported in the function process,
                                570                 :          * but we need to tell the parent that we didn't shutdown in a nice
                                571                 :          * way.
                                572                 :          */
                                573                 : #ifdef WIN32
  410 dgustafsson               574 ECB             :         /*
                                575                 :          * In order to signal the main thread of an ungraceful exit we set the
                                576                 :          * same flag that we use on Unix to signal SIGCHLD.
                                577                 :          */
                                578                 :         bgchild_exited = true;
  410 dgustafsson               579 EUB             : #endif
 4183 magnus                    580 GIC           3 :         return 1;
                                581                 :     }
                                582                 : 
  202 rhaas                     583 GNC          91 :     if (!stream.walmethod->ops->finish(stream.walmethod))
                                584                 :     {
 1469 peter                     585 UIC           0 :         pg_log_error("could not finish writing WAL files: %m");
  410 dgustafsson               586 ECB             : #ifdef WIN32
                                587                 :         bgchild_exited = true;
                                588                 : #endif
 2359 magnus                    589 UIC           0 :         return 1;
 2359 magnus                    590 ECB             :     }
                                591                 : 
 4183 magnus                    592 GIC          91 :     PQfinish(param->bgconn);
                                593                 : 
  202 rhaas                     594 GNC          91 :     stream.walmethod->ops->free(stream.walmethod);
 2357 magnus                    595 ECB             : 
 4183 magnus                    596 GIC          91 :     return 0;
                                597                 : }
                                598                 : 
                                599                 : /*
                                600                 :  * Initiate background process for receiving xlog during the backup.
                                601                 :  * The background stream will use its own database connection so we can
                                602                 :  * stream the logfile in parallel with the backups.
                                603                 :  */
 4183 magnus                    604 ECB             : static void
  382 rhaas                     605 CBC          99 : StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier,
  362 michael                   606 ECB             :                  pg_compress_algorithm wal_compress_algorithm,
  382 rhaas                     607                 :                  int wal_compress_level)
 4183 magnus                    608                 : {
                                609                 :     logstreamer_param *param;
                                610                 :     uint32      hi,
 3941 heikki.linnakangas        611                 :                 lo;
 3018 andres                    612 EUB             :     char        statusdir[MAXPGPATH];
                                613                 : 
 3841 tgl                       614 CBC          99 :     param = pg_malloc0(sizeof(logstreamer_param));
 4183 magnus                    615 GIC          99 :     param->timeline = timeline;
 4183 magnus                    616 CBC          99 :     param->sysidentifier = sysidentifier;
  362 michael                   617 GIC          99 :     param->wal_compress_algorithm = wal_compress_algorithm;
  382 rhaas                     618              99 :     param->wal_compress_level = wal_compress_level;
                                619                 : 
 4183 magnus                    620 ECB             :     /* Convert the starting position */
 3941 heikki.linnakangas        621 GBC          99 :     if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
  366 tgl                       622 UIC           0 :         pg_fatal("could not parse write-ahead log location \"%s\"",
                                623                 :                  startpos);
 3941 heikki.linnakangas        624 GIC          99 :     param->startptr = ((uint64) hi) << 32 | lo;
 4183 magnus                    625 ECB             :     /* Round off to even segment position */
 2028 andres                    626 CBC          99 :     param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
                                627                 : 
 4183 magnus                    628 EUB             : #ifndef WIN32
                                629                 :     /* Create our background pipe */
 4029 andrew                    630 GIC          99 :     if (pipe(bgpipe) < 0)
  366 tgl                       631 LBC           0 :         pg_fatal("could not create pipe for background process: %m");
                                632                 : #endif
 4183 magnus                    633 ECB             : 
                                634                 :     /* Get a second connection */
 4183 magnus                    635 GIC          99 :     param->bgconn = GetConnection();
 3969                           636              99 :     if (!param->bgconn)
 3969 magnus                    637 ECB             :         /* Error message already written in GetConnection() */
 3969 magnus                    638 UBC           0 :         exit(1);
                                639                 : 
                                640                 :     /* In post-10 cluster, pg_xlog has been renamed to pg_wal */
 2359 magnus                    641 GIC          99 :     snprintf(param->xlog, sizeof(param->xlog), "%s/%s",
                                642                 :              basedir,
 2362 rhaas                     643 CBC          99 :              PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
 2153 bruce                     644 ECB             :              "pg_xlog" : "pg_wal");
 3018 andres                    645                 : 
                                646                 :     /* Temporary replication slots are only supported in 10 and newer */
 2274 magnus                    647 CBC          99 :     if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_TEMP_SLOTS)
 2021 peter_e                   648 UIC           0 :         temp_replication_slot = false;
 2021 peter_e                   649 ECB             : 
                                650                 :     /*
                                651                 :      * Create replication slot if requested
                                652                 :      */
 2021 peter_e                   653 GBC          99 :     if (temp_replication_slot && !replication_slot)
                                654              92 :         replication_slot = psprintf("pg_basebackup_%d", (int) PQbackendPID(param->bgconn));
 2021 peter_e                   655 GIC          99 :     if (temp_replication_slot || create_slot)
                                656                 :     {
 2021 peter_e                   657 GBC          94 :         if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
                                658                 :                                    temp_replication_slot, true, true, false, false))
 1562 peter                     659 GIC           1 :             exit(1);
                                660                 : 
 2021 peter_e                   661              93 :         if (verbose)
 2021 peter_e                   662 ECB             :         {
 2021 peter_e                   663 UIC           0 :             if (temp_replication_slot)
 1469 peter                     664               0 :                 pg_log_info("created temporary replication slot \"%s\"",
                                665                 :                             replication_slot);
                                666                 :             else
                                667               0 :                 pg_log_info("created replication slot \"%s\"",
                                668                 :                             replication_slot);
                                669                 :         }
 2021 peter_e                   670 ECB             :     }
                                671                 : 
 2359 magnus                    672 CBC          98 :     if (format == 'p')
                                673                 :     {
                                674                 :         /*
 2359 magnus                    675 ECB             :          * Create pg_wal/archive_status or pg_xlog/archive_status (and thus
 2153 bruce                     676 EUB             :          * pg_wal or pg_xlog) depending on the target server so we can write
                                677                 :          * to basedir/pg_wal or basedir/pg_xlog as the directory entry in the
                                678                 :          * tar file may arrive later.
                                679                 :          */
 2359 magnus                    680 GIC          90 :         snprintf(statusdir, sizeof(statusdir), "%s/%s/archive_status",
                                681                 :                  basedir,
                                682              90 :                  PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
                                683                 :                  "pg_xlog" : "pg_wal");
 2359 magnus                    684 ECB             : 
 1828 sfrost                    685 CBC          90 :         if (pg_mkdir_p(statusdir, pg_dir_create_mode) != 0 && errno != EEXIST)
  366 tgl                       686 UIC           0 :             pg_fatal("could not create directory \"%s\": %m", statusdir);
                                687                 :     }
 4183 magnus                    688 ECB             : 
                                689                 :     /*
                                690                 :      * Start a child process and tell it to start streaming. On Unix, this is
 4183 magnus                    691 EUB             :      * a fork(). On Windows, we create a thread.
                                692                 :      */
                                693                 : #ifndef WIN32
 4183 magnus                    694 GIC          98 :     bgchild = fork();
                                695             192 :     if (bgchild == 0)
 4183 magnus                    696 ECB             :     {
                                697                 :         /* in child process */
  278 andres                    698 GIC          94 :         exit(LogStreamerMain(param));
                                699                 :     }
 4183 magnus                    700              98 :     else if (bgchild < 0)
  366 tgl                       701 UIC           0 :         pg_fatal("could not create background process: %m");
 4183 magnus                    702 ECB             : 
                                703                 :     /*
                                704                 :      * Else we are in the parent process and all is well.
                                705                 :      */
 1562 peter                     706 GIC          98 :     atexit(kill_bgchild_atexit);
                                707                 : #else                           /* WIN32 */
                                708                 :     bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
                                709                 :     if (bgchild == 0)
  366 tgl                       710 ECB             :         pg_fatal("could not create background thread: %m");
                                711                 : #endif
 4183 magnus                    712 CBC          98 : }
                                713                 : 
 4459 magnus                    714 ECB             : /*
                                715                 :  * Verify that the given directory exists and is empty. If it does not
                                716                 :  * exist, it is created. If it exists but is not empty, an error will
                                717                 :  * be given and the process ended.
                                718                 :  */
                                719                 : static void
 2400 peter_e                   720 GBC         142 : verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
 4459 magnus                    721 ECB             : {
 4459 magnus                    722 CBC         142 :     switch (pg_check_dir(dirname))
 4459 magnus                    723 ECB             :     {
 4459 magnus                    724 CBC         130 :         case 0:
                                725                 : 
                                726                 :             /*
                                727                 :              * Does not exist, so create
                                728                 :              */
 1828 sfrost                    729             130 :             if (pg_mkdir_p(dirname, pg_dir_create_mode) == -1)
  366 tgl                       730 LBC           0 :                 pg_fatal("could not create directory \"%s\": %m", dirname);
 2400 peter_e                   731 CBC         130 :             if (created)
                                732             130 :                 *created = true;
 4459 magnus                    733 GIC         130 :             return;
                                734              11 :         case 1:
                                735                 : 
                                736                 :             /*
                                737                 :              * Exists, empty
                                738                 :              */
 2400 peter_e                   739 CBC          11 :             if (found)
 2400 peter_e                   740 GBC          11 :                 *found = true;
 4459 magnus                    741 GIC          11 :             return;
                                742               1 :         case 2:
                                743                 :         case 3:
                                744                 :         case 4:
 4459 magnus                    745 EUB             : 
                                746                 :             /*
                                747                 :              * Exists, not empty
                                748                 :              */
  366 tgl                       749 GIC           1 :             pg_fatal("directory \"%s\" exists but is not empty", dirname);
 4459 magnus                    750 UIC           0 :         case -1:
                                751                 : 
                                752                 :             /*
                                753                 :              * Access problem
                                754                 :              */
  366 tgl                       755 LBC           0 :             pg_fatal("could not access directory \"%s\": %m", dirname);
                                756                 :     }
                                757                 : }
 4459 magnus                    758 ECB             : 
                                759                 : /*
  520 rhaas                     760 EUB             :  * Callback to update our notion of the current filename.
  416 tgl                       761                 :  *
                                762                 :  * No other code should modify progress_filename!
                                763                 :  */
  520 rhaas                     764                 : static void
  520 rhaas                     765 GIC       98801 : progress_update_filename(const char *filename)
  520 rhaas                     766 ECB             : {
                                767                 :     /* We needn't maintain this variable if not doing verbose reports. */
  416 tgl                       768 GIC       98801 :     if (showprogress && verbose)
                                769                 :     {
  297 peter                     770 UNC           0 :         free(progress_filename);
  416 tgl                       771 UIC           0 :         if (filename)
                                772               0 :             progress_filename = pg_strdup(filename);
                                773                 :         else
                                774               0 :             progress_filename = NULL;
                                775                 :     }
  520 rhaas                     776 GIC       98801 : }
                                777                 : 
 4459 magnus                    778 ECB             : /*
                                779                 :  * Print a progress report based on the global variables. If verbose output
                                780                 :  * is enabled, also print the current file name.
                                781                 :  *
                                782                 :  * Progress report is written at maximum once per second, unless the force
                                783                 :  * parameter is set to true.
                                784                 :  *
  965 heikki.linnakangas        785                 :  * If finished is set to true, this is the last progress report. The cursor
                                786                 :  * is moved to the next line.
                                787                 :  */
 4459 magnus                    788 EUB             : static void
  520 rhaas                     789 GBC         172 : progress_report(int tablespacenum, bool force, bool finished)
 4459 magnus                    790 EUB             : {
                                791                 :     int         percent;
 4254 peter_e                   792                 :     char        totaldone_str[32];
                                793                 :     char        totalsize_str[32];
                                794                 :     pg_time_t   now;
                                795                 : 
 3346 magnus                    796 GIC         172 :     if (!showprogress)
                                797             172 :         return;
                                798                 : 
 3346 magnus                    799 UIC           0 :     now = time(NULL);
  965 heikki.linnakangas        800               0 :     if (now == last_progress_report && !force && !finished)
 3260 bruce                     801 UBC           0 :         return;                 /* Max once per second */
 3346 magnus                    802 EUB             : 
 3346 magnus                    803 UBC           0 :     last_progress_report = now;
 1314 peter                     804               0 :     percent = totalsize_kb ? (int) ((totaldone / 1024) * 100 / totalsize_kb) : 0;
                                805                 : 
 4254 magnus                    806 EUB             :     /*
                                807                 :      * Avoid overflowing past 100% or the full size. This may make the total
 4183 bruce                     808                 :      * size number change as we approach the end of the backup (the estimate
                                809                 :      * will always be wrong if WAL is included), but that's better than having
                                810                 :      * the done column be bigger than the total.
 4254 magnus                    811                 :      */
 4452 magnus                    812 UIC           0 :     if (percent > 100)
 4452 magnus                    813 UBC           0 :         percent = 100;
 1314 peter                     814 UIC           0 :     if (totaldone / 1024 > totalsize_kb)
                                815               0 :         totalsize_kb = totaldone / 1024;
                                816                 : 
  571                           817               0 :     snprintf(totaldone_str, sizeof(totaldone_str), UINT64_FORMAT,
                                818                 :              totaldone / 1024);
  571 peter                     819 UBC           0 :     snprintf(totalsize_str, sizeof(totalsize_str), UINT64_FORMAT, totalsize_kb);
 4254 peter_e                   820 EUB             : 
                                821                 : #define VERBOSE_FILENAME_LENGTH 35
 4459 magnus                    822 UIC           0 :     if (verbose)
 4404 magnus                    823 EUB             :     {
  520 rhaas                     824 UIC           0 :         if (!progress_filename)
                                825                 : 
                                826                 :             /*
                                827                 :              * No filename given, so clear the status line (used for last
                                828                 :              * call)
 4404 magnus                    829 EUB             :              */
 4404 magnus                    830 UIC           0 :             fprintf(stderr,
 3734 magnus                    831 UBC           0 :                     ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
 3734 magnus                    832 EUB             :                              "%*s/%s kB (100%%), %d/%d tablespaces %*s",
                                833                 :                              tablespacecount),
 3734 magnus                    834 UIC           0 :                     (int) strlen(totalsize_str),
 3904 alvherre                  835 EUB             :                     totaldone_str, totalsize_str,
                                836                 :                     tablespacenum, tablespacecount,
                                837                 :                     VERBOSE_FILENAME_LENGTH + 5, "");
                                838                 :         else
                                839                 :         {
  520 rhaas                     840 UIC           0 :             bool        truncate = (strlen(progress_filename) > VERBOSE_FILENAME_LENGTH);
                                841                 : 
 4404 magnus                    842               0 :             fprintf(stderr,
 3734 magnus                    843 UBC           0 :                     ngettext("%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)",
                                844                 :                              "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)",
                                845                 :                              tablespacecount),
 3734 magnus                    846 UIC           0 :                     (int) strlen(totalsize_str),
 3904 alvherre                  847 EUB             :                     totaldone_str, totalsize_str, percent,
 3734 magnus                    848                 :                     tablespacenum, tablespacecount,
                                849                 :             /* Prefix with "..." if we do leading truncation */
                                850                 :                     truncate ? "..." : "",
 2118 tgl                       851                 :                     truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
                                852                 :                     truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
                                853                 :             /* Truncate filename at beginning if it's too long */
  520 rhaas                     854 UIC           0 :                     truncate ? progress_filename + strlen(progress_filename) - VERBOSE_FILENAME_LENGTH + 3 : progress_filename);
                                855                 :         }
                                856                 :     }
                                857                 :     else
 4254 peter_e                   858               0 :         fprintf(stderr,
 3734 magnus                    859 UBC           0 :                 ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
                                860                 :                          "%*s/%s kB (%d%%), %d/%d tablespaces",
                                861                 :                          tablespacecount),
 3734 magnus                    862 UIC           0 :                 (int) strlen(totalsize_str),
 3904 alvherre                  863 ECB             :                 totaldone_str, totalsize_str, percent,
                                864                 :                 tablespacenum, tablespacecount);
                                865                 : 
                                866                 :     /*
  965 heikki.linnakangas        867                 :      * Stay on the same line if reporting to a terminal and we're not done
                                868                 :      * yet.
                                869                 :      */
  964 heikki.linnakangas        870 LBC           0 :     fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
 4459 magnus                    871 ECB             : }
 4459 magnus                    872 EUB             : 
 3328 alvherre                  873 ECB             : static int32
 3328 alvherre                  874 GBC           1 : parse_max_rate(char *src)
                                875                 : {
 3328 alvherre                  876 ECB             :     double      result;
                                877                 :     char       *after_num;
 3260 bruce                     878 GIC           1 :     char       *suffix = NULL;
                                879                 : 
 3328 alvherre                  880               1 :     errno = 0;
 3328 alvherre                  881 GBC           1 :     result = strtod(src, &after_num);
 3328 alvherre                  882 GIC           1 :     if (src == after_num)
  366 tgl                       883 UIC           0 :         pg_fatal("transfer rate \"%s\" is not a valid value", src);
 3328 alvherre                  884 GIC           1 :     if (errno != 0)
  366 tgl                       885 UIC           0 :         pg_fatal("invalid transfer rate \"%s\": %m", src);
                                886                 : 
 3328 alvherre                  887 GIC           1 :     if (result <= 0)
 3328 alvherre                  888 ECB             :     {
 3328 alvherre                  889 EUB             :         /*
                                890                 :          * Reject obviously wrong values here.
 3328 alvherre                  891 ECB             :          */
  366 tgl                       892 UIC           0 :         pg_fatal("transfer rate must be greater than zero");
 3328 alvherre                  893 EUB             :     }
                                894                 : 
                                895                 :     /*
                                896                 :      * Evaluate suffix, after skipping over possible whitespace. Lack of
 3260 bruce                     897                 :      * suffix means kilobytes.
                                898                 :      */
 3328 alvherre                  899 GBC           1 :     while (*after_num != '\0' && isspace((unsigned char) *after_num))
 3328 alvherre                  900 UIC           0 :         after_num++;
 3328 alvherre                  901 EUB             : 
 3328 alvherre                  902 GBC           1 :     if (*after_num != '\0')
                                903                 :     {
 3328 alvherre                  904 UIC           0 :         suffix = after_num;
                                905               0 :         if (*after_num == 'k')
                                906                 :         {
 3328 alvherre                  907 ECB             :             /* kilobyte is the expected unit. */
 3328 alvherre                  908 UBC           0 :             after_num++;
                                909                 :         }
 3328 alvherre                  910 LBC           0 :         else if (*after_num == 'M')
 3328 alvherre                  911 EUB             :         {
 3328 alvherre                  912 UIC           0 :             after_num++;
                                913               0 :             result *= 1024.0;
 3328 alvherre                  914 ECB             :         }
 3328 alvherre                  915 EUB             :     }
                                916                 : 
                                917                 :     /* The rest can only consist of white space. */
 3328 alvherre                  918 GIC           1 :     while (*after_num != '\0' && isspace((unsigned char) *after_num))
 3328 alvherre                  919 UIC           0 :         after_num++;
                                920                 : 
 3328 alvherre                  921 CBC           1 :     if (*after_num != '\0')
  366 tgl                       922 UBC           0 :         pg_fatal("invalid --max-rate unit: \"%s\"", suffix);
                                923                 : 
 3328 alvherre                  924 ECB             :     /* Valid integer? */
 3328 alvherre                  925 GIC           1 :     if ((uint64) result != (uint64) ((uint32) result))
  366 tgl                       926 UIC           0 :         pg_fatal("transfer rate \"%s\" exceeds integer range", src);
                                927                 : 
                                928                 :     /*
                                929                 :      * The range is checked on the server side too, but avoid the server
                                930                 :      * connection if a nonsensical value was passed.
                                931                 :      */
 3328 alvherre                  932 GIC           1 :     if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
  366 tgl                       933 UIC           0 :         pg_fatal("transfer rate \"%s\" is out of range", src);
                                934                 : 
 3328 alvherre                  935 GIC           1 :     return (int32) result;
                                936                 : }
                                937                 : 
                                938                 : /*
                                939                 :  * Basic parsing of a value specified for -Z/--compress.
                                940                 :  *
                                941                 :  * We're not concerned here with understanding exactly what behavior the
                                942                 :  * user wants, but we do need to know whether the user is requesting client
                                943                 :  * or server side compression or leaving it unspecified, and we need to
                                944                 :  * separate the name of the compression algorithm from the detail string.
                                945                 :  *
                                946                 :  * For instance, if the user writes --compress client-lz4:6, we want to
                                947                 :  * separate that into (a) client-side compression, (b) algorithm "lz4",
  382 rhaas                     948 ECB             :  * and (c) detail "6". Note, however, that all the client/server prefix is
                                949                 :  * optional, and so is the detail. The algorithm name is required, unless
                                950                 :  * the whole string is an integer, in which case we assume "gzip" as the
                                951                 :  * algorithm and use the integer as the detail.
                                952                 :  *
                                953                 :  * We're not concerned with validation at this stage, so if the user writes
                                954                 :  * --compress client-turkey:sandwich, the requested algorithm is "turkey"
                                955                 :  * and the detail string is "sandwich". We'll sort out whether that's legal
                                956                 :  * at a later stage.
  443 michael                   957                 :  */
                                958                 : static void
  130 michael                   959 GNC          37 : backup_parse_compress_options(char *option, char **algorithm, char **detail,
                                960                 :                               CompressionLocation *locationres)
  443 michael                   961 ECB             : {
  436 rhaas                     962                 :     /*
                                963                 :      * Strip off any "client-" or "server-" prefix, calculating the location.
  443 michael                   964                 :      */
  382 rhaas                     965 GIC          37 :     if (strncmp(option, "server-", 7) == 0)
                                966                 :     {
  440 rhaas                     967 CBC          18 :         *locationres = COMPRESS_LOCATION_SERVER;
  382                           968              18 :         option += 7;
  440 rhaas                     969 EUB             :     }
  382 rhaas                     970 GIC          19 :     else if (strncmp(option, "client-", 7) == 0)
  422 rhaas                     971 ECB             :     {
  422 rhaas                     972 GIC           5 :         *locationres = COMPRESS_LOCATION_CLIENT;
  382                           973               5 :         option += 7;
                                974                 :     }
  443 michael                   975 ECB             :     else
  440 rhaas                     976 GIC          14 :         *locationres = COMPRESS_LOCATION_UNSPECIFIED;
                                977                 : 
                                978                 :     /* fallback to the common parsing for the algorithm and detail */
  130 michael                   979 GNC          37 :     parse_compress_options(option, algorithm, detail);
  443 michael                   980 GIC          37 : }
                                981                 : 
                                982                 : /*
                                983                 :  * Read a stream of COPY data and invoke the provided callback for each
                                984                 :  * chunk.
                                985                 :  */
                                986                 : static void
 1221 rhaas                     987             124 : ReceiveCopyData(PGconn *conn, WriteDataCallback callback,
                                988                 :                 void *callback_data)
 1221 rhaas                     989 ECB             : {
                                990                 :     PGresult   *res;
                                991                 : 
                                992                 :     /* Get the COPY data stream. */
 1221 rhaas                     993 GIC         124 :     res = PQgetResult(conn);
                                994             124 :     if (PQresultStatus(res) != PGRES_COPY_OUT)
  366 tgl                       995 LBC           0 :         pg_fatal("could not get COPY data stream: %s",
  366 tgl                       996 ECB             :                  PQerrorMessage(conn));
 1221 rhaas                     997 GIC         124 :     PQclear(res);
                                998                 : 
                                999                 :     /* Loop over chunks until done. */
                               1000                 :     while (1)
                               1001          246055 :     {
                               1002                 :         int         r;
                               1003                 :         char       *copybuf;
 1221 rhaas                    1004 ECB             : 
 1221 rhaas                    1005 GIC      246179 :         r = PQgetCopyData(conn, &copybuf, 0);
                               1006          246179 :         if (r == -1)
                               1007                 :         {
                               1008                 :             /* End of chunk. */
                               1009             121 :             break;
                               1010                 :         }
 1221 rhaas                    1011 CBC      246058 :         else if (r == -2)
  366 tgl                      1012 UIC           0 :             pg_fatal("could not read COPY data: %s",
                               1013                 :                      PQerrorMessage(conn));
 1221 rhaas                    1014 ECB             : 
  410 dgustafsson              1015 CBC      246058 :         if (bgchild_exited)
  366 tgl                      1016 GIC           3 :             pg_fatal("background process terminated unexpectedly");
                               1017                 : 
 1221 rhaas                    1018 CBC      246055 :         (*callback) (r, copybuf, callback_data);
 1221 rhaas                    1019 ECB             : 
 1221 rhaas                    1020 GIC      246055 :         PQfreemem(copybuf);
                               1021                 :     }
 1221 rhaas                    1022 CBC         121 : }
 1221 rhaas                    1023 ECB             : 
                               1024                 : /*
                               1025                 :  * Figure out what to do with an archive received from the server based on
  520                          1026                 :  * the options selected by the user.  We may just write the results directly
                               1027                 :  * to a file, or we might compress first, or we might extract the tar file
                               1028                 :  * and write each member separately. This function doesn't do any of that
                               1029                 :  * directly, but it works out what kind of bbstreamer we need to create so
                               1030                 :  * that the right stuff happens when, down the road, we actually receive
                               1031                 :  * the data.
                               1032                 :  */
                               1033                 : static bbstreamer *
  520 rhaas                    1034 GIC         129 : CreateBackupStreamer(char *archive_name, char *spclocation,
                               1035                 :                      bbstreamer **manifest_inject_streamer_p,
                               1036                 :                      bool is_recovery_guc_supported,
                               1037                 :                      bool expect_unterminated_tarfile,
                               1038                 :                      pg_compress_specification *compress)
                               1039                 : {
  443 michael                  1040 CBC         129 :     bbstreamer *streamer = NULL;
  520 rhaas                    1041 GIC         129 :     bbstreamer *manifest_inject_streamer = NULL;
  520 rhaas                    1042 EUB             :     bool        inject_manifest;
  436                          1043                 :     bool        is_tar,
                               1044                 :                 is_tar_gz,
  398                          1045                 :                 is_tar_lz4,
                               1046                 :                 is_tar_zstd,
                               1047                 :                 is_compressed_tar;
                               1048                 :     bool        must_parse_archive;
  440 rhaas                    1049 GIC         129 :     int         archive_name_len = strlen(archive_name);
                               1050                 : 
                               1051                 :     /*
                               1052                 :      * Normally, we emit the backup manifest as a separate file, but when
  520 rhaas                    1053 ECB             :      * we're writing a tarfile to stdout, we don't have that option, so
                               1054                 :      * include it in the one tarfile we've got.
                               1055                 :      */
  520 rhaas                    1056 GIC         129 :     inject_manifest = (format == 't' && strcmp(basedir, "-") == 0 && manifest);
 4459 magnus                   1057 ECB             : 
                               1058                 :     /* Is this a tar archive? */
  440 rhaas                    1059 GBC         258 :     is_tar = (archive_name_len > 4 &&
                               1060             129 :               strcmp(archive_name + archive_name_len - 4, ".tar") == 0);
  440 rhaas                    1061 EUB             : 
  394                          1062                 :     /* Is this a .tar.gz archive? */
  394 rhaas                    1063 GBC         258 :     is_tar_gz = (archive_name_len > 7 &&
                               1064             129 :                  strcmp(archive_name + archive_name_len - 7, ".tar.gz") == 0);
  436 rhaas                    1065 EUB             : 
  394                          1066                 :     /* Is this a .tar.lz4 archive? */
  422 rhaas                    1067 GBC         148 :     is_tar_lz4 = (archive_name_len > 8 &&
  394 rhaas                    1068 GIC          19 :                   strcmp(archive_name + archive_name_len - 8, ".tar.lz4") == 0);
                               1069                 : 
  394 rhaas                    1070 ECB             :     /* Is this a .tar.zst archive? */
  398 rhaas                    1071 GIC         148 :     is_tar_zstd = (archive_name_len > 8 &&
  394                          1072              19 :                    strcmp(archive_name + archive_name_len - 8, ".tar.zst") == 0);
                               1073                 : 
                               1074                 :     /* Is this any kind of compressed tar? */
                               1075             129 :     is_compressed_tar = is_tar_gz || is_tar_lz4 || is_tar_zstd;
                               1076                 : 
                               1077                 :     /*
                               1078                 :      * Injecting the manifest into a compressed tar file would be possible if
                               1079                 :      * we decompressed it, parsed the tarfile, generated a new tarfile, and
                               1080                 :      * recompressed it, but compressing and decompressing multiple times just
  394 rhaas                    1081 ECB             :      * to inject the manifest seems inefficient enough that it's probably not
                               1082                 :      * what the user wants. So, instead, reject the request and tell the user
                               1083                 :      * to specify something more reasonable.
                               1084                 :      */
  394 rhaas                    1085 GIC         129 :     if (inject_manifest && is_compressed_tar)
                               1086                 :     {
  197 peter                    1087 UIC           0 :         pg_log_error("cannot inject manifest into a compressed tar file");
                               1088               0 :         pg_log_error_hint("Use client-side compression, send the output to a directory rather than standard output, or use %s.",
                               1089                 :                           "--no-manifest");
  394 rhaas                    1090               0 :         exit(1);
                               1091                 :     }
                               1092                 : 
                               1093                 :     /*
                               1094                 :      * We have to parse the archive if (1) we're suppose to extract it, or if
                               1095                 :      * (2) we need to inject backup_manifest or recovery configuration into
                               1096                 :      * it. However, we only know how to parse tar archives.
                               1097                 :      */
  520 rhaas                    1098 CBC         143 :     must_parse_archive = (format == 'p' || inject_manifest ||
  332 tgl                      1099 GIC          14 :                           (spclocation == NULL && writerecoveryconf));
 1493 michael                  1100 EUB             : 
  440 rhaas                    1101                 :     /* At present, we only know how to parse tar archives. */
  394 rhaas                    1102 GIC         129 :     if (must_parse_archive && !is_tar && !is_compressed_tar)
                               1103                 :     {
  197 peter                    1104 UIC           0 :         pg_log_error("cannot parse archive \"%s\"", archive_name);
  366 tgl                      1105 LBC           0 :         pg_log_error_detail("Only tar archives can be parsed.");
  440 rhaas                    1106 UIC           0 :         if (format == 'p')
  366 tgl                      1107 LBC           0 :             pg_log_error_detail("Plain format requires pg_basebackup to parse the archive.");
  440 rhaas                    1108 UIC           0 :         if (inject_manifest)
  366 tgl                      1109               0 :             pg_log_error_detail("Using - as the output directory requires pg_basebackup to parse the archive.");
  440 rhaas                    1110 LBC           0 :         if (writerecoveryconf)
  366 tgl                      1111               0 :             pg_log_error_detail("The -R option requires pg_basebackup to parse the archive.");
  440 rhaas                    1112 UIC           0 :         exit(1);
  440 rhaas                    1113 ECB             :     }
                               1114                 : 
  520 rhaas                    1115 CBC         129 :     if (format == 'p')
 3904 alvherre                 1116 ECB             :     {
                               1117                 :         const char *directory;
                               1118                 : 
 4459 magnus                   1119                 :         /*
                               1120                 :          * In plain format, we must extract the archive. The data for the main
  520 rhaas                    1121                 :          * tablespace will be written to the base directory, and the data for
                               1122                 :          * other tablespaces will be written to the directory where they're
                               1123                 :          * located on the server, after applying any user-specified tablespace
                               1124                 :          * mappings.
                               1125                 :          */
  520 rhaas                    1126 CBC         113 :         directory = spclocation == NULL ? basedir
  520 rhaas                    1127 GIC         113 :             : get_tablespace_mapping(spclocation);
  520 rhaas                    1128 CBC         113 :         streamer = bbstreamer_extractor_new(directory,
  520 rhaas                    1129 ECB             :                                             get_tablespace_mapping,
                               1130                 :                                             progress_update_filename);
 3904 alvherre                 1131                 :     }
                               1132                 :     else
                               1133                 :     {
                               1134                 :         FILE       *archive_file;
  520 rhaas                    1135 EUB             :         char        archive_filename[MAXPGPATH];
                               1136                 : 
                               1137                 :         /*
                               1138                 :          * In tar format, we just write the archive without extracting it.
                               1139                 :          * Normally, we write it to the archive name provided by the caller,
                               1140                 :          * but when the base directory is "-" that means we need to write to
                               1141                 :          * standard output.
                               1142                 :          */
  520 rhaas                    1143 GIC          16 :         if (strcmp(basedir, "-") == 0)
 4459 magnus                   1144 ECB             :         {
  520 rhaas                    1145 UBC           0 :             snprintf(archive_filename, sizeof(archive_filename), "-");
  520 rhaas                    1146 LBC           0 :             archive_file = stdout;
                               1147                 :         }
                               1148                 :         else
                               1149                 :         {
  520 rhaas                    1150 GIC          16 :             snprintf(archive_filename, sizeof(archive_filename),
                               1151                 :                      "%s/%s", basedir, archive_name);
                               1152              16 :             archive_file = NULL;
                               1153                 :         }
 4459 magnus                   1154 ECB             : 
  362 michael                  1155 GBC          16 :         if (compress->algorithm == PG_COMPRESSION_NONE)
  443 michael                  1156 GIC           8 :             streamer = bbstreamer_plain_writer_new(archive_filename,
                               1157                 :                                                    archive_file);
  362                          1158               8 :         else if (compress->algorithm == PG_COMPRESSION_GZIP)
                               1159                 :         {
  520 rhaas                    1160               4 :             strlcat(archive_filename, ".gz", sizeof(archive_filename));
  520 rhaas                    1161 CBC           4 :             streamer = bbstreamer_gzip_writer_new(archive_filename,
                               1162                 :                                                   archive_file, compress);
 4459 magnus                   1163 ECB             :         }
  362 michael                  1164 CBC           4 :         else if (compress->algorithm == PG_COMPRESSION_LZ4)
                               1165                 :         {
  422 rhaas                    1166 GIC           1 :             strlcat(archive_filename, ".lz4", sizeof(archive_filename));
                               1167               1 :             streamer = bbstreamer_plain_writer_new(archive_filename,
                               1168                 :                                                    archive_file);
  382                          1169               1 :             streamer = bbstreamer_lz4_compressor_new(streamer, compress);
                               1170                 :         }
  362 michael                  1171               3 :         else if (compress->algorithm == PG_COMPRESSION_ZSTD)
                               1172                 :         {
  398 rhaas                    1173               3 :             strlcat(archive_filename, ".zst", sizeof(archive_filename));
                               1174               3 :             streamer = bbstreamer_plain_writer_new(archive_filename,
  398 rhaas                    1175 ECB             :                                                    archive_file);
  382 rhaas                    1176 CBC           3 :             streamer = bbstreamer_zstd_compressor_new(streamer, compress);
  398 rhaas                    1177 ECB             :         }
  443 michael                  1178 EUB             :         else
                               1179                 :         {
  443 michael                  1180 UIC           0 :             Assert(false);      /* not reachable */
                               1181                 :         }
                               1182                 : 
                               1183                 :         /*
  520 rhaas                    1184 ECB             :          * If we need to parse the archive for whatever reason, then we'll
                               1185                 :          * also need to re-archive, because, if the output format is tar, the
                               1186                 :          * only point of parsing the archive is to be able to inject stuff
                               1187                 :          * into it.
                               1188                 :          */
  520 rhaas                    1189 CBC          16 :         if (must_parse_archive)
  520 rhaas                    1190 LBC           0 :             streamer = bbstreamer_tar_archiver_new(streamer);
  416 tgl                      1191 CBC          16 :         progress_update_filename(archive_filename);
                               1192                 :     }
                               1193                 : 
                               1194                 :     /*
  332 tgl                      1195 ECB             :      * If we're supposed to inject the backup manifest into the results, it
                               1196                 :      * should be done here, so that the file content can be injected directly,
                               1197                 :      * without worrying about the details of the tar format.
                               1198                 :      */
  520 rhaas                    1199 GIC         129 :     if (inject_manifest)
  520 rhaas                    1200 UIC           0 :         manifest_inject_streamer = streamer;
                               1201                 : 
                               1202                 :     /*
                               1203                 :      * If this is the main tablespace and we're supposed to write recovery
  332 tgl                      1204 ECB             :      * information, arrange to do that.
                               1205                 :      */
  520 rhaas                    1206 GIC         129 :     if (spclocation == NULL && writerecoveryconf)
                               1207                 :     {
                               1208               2 :         Assert(must_parse_archive);
  520 rhaas                    1209 CBC           2 :         streamer = bbstreamer_recovery_injector_new(streamer,
  520 rhaas                    1210 ECB             :                                                     is_recovery_guc_supported,
                               1211                 :                                                     recoveryconfcontents);
                               1212                 :     }
                               1213                 : 
                               1214                 :     /*
                               1215                 :      * If we're doing anything that involves understanding the contents of the
                               1216                 :      * archive, we'll need to parse it. If not, we can skip parsing it, but
  332 tgl                      1217                 :      * old versions of the server send improperly terminated tarfiles, so if
                               1218                 :      * we're talking to such a server we'll need to add the terminator here.
  520 rhaas                    1219                 :      */
  520 rhaas                    1220 CBC         129 :     if (must_parse_archive)
  520 rhaas                    1221 GIC         113 :         streamer = bbstreamer_tar_parser_new(streamer);
  516                          1222              16 :     else if (expect_unterminated_tarfile)
  517 rhaas                    1223 UIC           0 :         streamer = bbstreamer_tar_terminator_new(streamer);
                               1224                 : 
                               1225                 :     /*
                               1226                 :      * If the user has requested a server compressed archive along with
  332 tgl                      1227 ECB             :      * archive extraction at client then we need to decompress it.
  436 rhaas                    1228 EUB             :      */
  382 rhaas                    1229 GIC         129 :     if (format == 'p')
  422 rhaas                    1230 EUB             :     {
  382 rhaas                    1231 GIC         113 :         if (is_tar_gz)
  422 rhaas                    1232 GBC           1 :             streamer = bbstreamer_gzip_decompressor_new(streamer);
  382                          1233             112 :         else if (is_tar_lz4)
  422                          1234               1 :             streamer = bbstreamer_lz4_decompressor_new(streamer);
  382                          1235             111 :         else if (is_tar_zstd)
  398 rhaas                    1236 GIC           2 :             streamer = bbstreamer_zstd_decompressor_new(streamer);
                               1237                 :     }
                               1238                 : 
  520 rhaas                    1239 ECB             :     /* Return the results. */
  520 rhaas                    1240 GIC         129 :     *manifest_inject_streamer_p = manifest_inject_streamer;
  520 rhaas                    1241 CBC         129 :     return streamer;
  520 rhaas                    1242 ECB             : }
 4459 magnus                   1243                 : 
                               1244                 : /*
  446 rhaas                    1245                 :  * Receive all of the archives the server wants to send - and the backup
                               1246                 :  * manifest if present - as a single COPY stream.
                               1247                 :  */
                               1248                 : static void
  362 michael                  1249 GIC         124 : ReceiveArchiveStream(PGconn *conn, pg_compress_specification *compress)
                               1250                 : {
                               1251                 :     ArchiveStreamState state;
  446 rhaas                    1252 ECB             : 
                               1253                 :     /* Set up initial state. */
  446 rhaas                    1254 CBC         124 :     memset(&state, 0, sizeof(state));
                               1255             124 :     state.tablespacenum = -1;
  382 rhaas                    1256 GIC         124 :     state.compress = compress;
                               1257                 : 
  446 rhaas                    1258 ECB             :     /* All the real work happens in ReceiveArchiveStreamChunk. */
  446 rhaas                    1259 GIC         124 :     ReceiveCopyData(conn, ReceiveArchiveStreamChunk, &state);
  446 rhaas                    1260 ECB             : 
                               1261                 :     /* If we wrote the backup manifest to a file, close the file. */
  446 rhaas                    1262 GIC         121 :     if (state.manifest_file !=NULL)
                               1263                 :     {
                               1264             109 :         fclose(state.manifest_file);
                               1265             109 :         state.manifest_file = NULL;
                               1266                 :     }
                               1267                 : 
                               1268                 :     /*
                               1269                 :      * If we buffered the backup manifest in order to inject it into the
                               1270                 :      * output tarfile, do that now.
  446 rhaas                    1271 ECB             :      */
  446 rhaas                    1272 CBC         121 :     if (state.manifest_inject_streamer != NULL &&
  446 rhaas                    1273 UIC           0 :         state.manifest_buffer != NULL)
                               1274                 :     {
  446 rhaas                    1275 LBC           0 :         bbstreamer_inject_file(state.manifest_inject_streamer,
  446 rhaas                    1276 ECB             :                                "backup_manifest",
  446 rhaas                    1277 UBC           0 :                                state.manifest_buffer->data,
  446 rhaas                    1278 UIC           0 :                                state.manifest_buffer->len);
                               1279               0 :         destroyPQExpBuffer(state.manifest_buffer);
  446 rhaas                    1280 LBC           0 :         state.manifest_buffer = NULL;
  446 rhaas                    1281 ECB             :     }
                               1282                 : 
                               1283                 :     /* If there's still an archive in progress, end processing. */
  446 rhaas                    1284 GIC         121 :     if (state.streamer != NULL)
                               1285                 :     {
                               1286             111 :         bbstreamer_finalize(state.streamer);
                               1287             111 :         bbstreamer_free(state.streamer);
                               1288             111 :         state.streamer = NULL;
  446 rhaas                    1289 ECB             :     }
  446 rhaas                    1290 CBC         121 : }
  446 rhaas                    1291 ECB             : 
  446 rhaas                    1292 EUB             : /*
                               1293                 :  * Receive one chunk of data sent by the server as part of a single COPY
                               1294                 :  * stream that includes all archives and the manifest.
                               1295                 :  */
                               1296                 : static void
  446 rhaas                    1297 GIC      246055 : ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
                               1298                 : {
                               1299          246055 :     ArchiveStreamState *state = callback_data;
  446 rhaas                    1300 CBC      246055 :     size_t      cursor = 0;
  446 rhaas                    1301 ECB             : 
                               1302                 :     /* Each CopyData message begins with a type byte. */
  446 rhaas                    1303 GIC      246055 :     switch (GetCopyDataByte(r, copybuf, &cursor))
  446 rhaas                    1304 ECB             :     {
  446 rhaas                    1305 GIC         139 :         case 'n':
  446 rhaas                    1306 ECB             :             {
                               1307                 :                 /* New archive. */
                               1308                 :                 char       *archive_name;
                               1309                 :                 char       *spclocation;
                               1310                 : 
                               1311                 :                 /*
                               1312                 :                  * We force a progress report at the end of each tablespace. A
                               1313                 :                  * new tablespace starts when the previous one ends, except in
                               1314                 :                  * the case of the very first one.
                               1315                 :                  */
  446 rhaas                    1316 CBC         139 :                 if (++state->tablespacenum > 0)
  446 rhaas                    1317 GIC          15 :                     progress_report(state->tablespacenum, true, false);
                               1318                 : 
                               1319                 :                 /* Sanity check. */
                               1320             139 :                 if (state->manifest_buffer != NULL ||
                               1321             139 :                     state->manifest_file !=NULL)
  197 peter                    1322 LBC           0 :                     pg_fatal("archives must precede manifest");
  446 rhaas                    1323 ECB             : 
                               1324                 :                 /* Parse the rest of the CopyData message. */
  446 rhaas                    1325 GIC         139 :                 archive_name = GetCopyDataString(r, copybuf, &cursor);
                               1326             139 :                 spclocation = GetCopyDataString(r, copybuf, &cursor);
                               1327             139 :                 GetCopyDataEnd(r, copybuf, cursor);
                               1328                 : 
  446 rhaas                    1329 ECB             :                 /*
                               1330                 :                  * Basic sanity checks on the archive name: it shouldn't be
                               1331                 :                  * empty, it shouldn't start with a dot, and it shouldn't
                               1332                 :                  * contain a path separator.
                               1333                 :                  */
  446 rhaas                    1334 GIC         139 :                 if (archive_name[0] == '\0' || archive_name[0] == '.' ||
  446 rhaas                    1335 CBC         139 :                     strchr(archive_name, '/') != NULL ||
  446 rhaas                    1336 GIC         139 :                     strchr(archive_name, '\\') != NULL)
  366 tgl                      1337 UIC           0 :                     pg_fatal("invalid archive name: \"%s\"",
  366 tgl                      1338 EUB             :                              archive_name);
                               1339                 : 
                               1340                 :                 /*
  446 rhaas                    1341 ECB             :                  * An empty spclocation is treated as NULL. We expect this
                               1342                 :                  * case to occur for the data directory itself, but not for
                               1343                 :                  * any archives that correspond to tablespaces.
                               1344                 :                  */
  446 rhaas                    1345 GIC         139 :                 if (spclocation[0] == '\0')
                               1346             124 :                     spclocation = NULL;
                               1347                 : 
                               1348                 :                 /* End processing of any prior archive. */
                               1349             139 :                 if (state->streamer != NULL)
                               1350                 :                 {
  446 rhaas                    1351 GBC          15 :                     bbstreamer_finalize(state->streamer);
                               1352              15 :                     bbstreamer_free(state->streamer);
                               1353              15 :                     state->streamer = NULL;
                               1354                 :                 }
                               1355                 : 
                               1356                 :                 /*
  509 rhaas                    1357 ECB             :                  * Create an appropriate backup streamer, unless a backup
                               1358                 :                  * target was specified. In that case, it's up to the server
                               1359                 :                  * to put the backup wherever it needs to go.
  446                          1360                 :                  */
  509 rhaas                    1361 CBC         139 :                 if (backup_target == NULL)
                               1362                 :                 {
                               1363                 :                     /*
  509 rhaas                    1364 EUB             :                      * We know that recovery GUCs are supported, because this
  509 rhaas                    1365 ECB             :                      * protocol can only be used on v15+.
                               1366                 :                      */
  509 rhaas                    1367 GIC         129 :                     state->streamer =
  509 rhaas                    1368 CBC         129 :                         CreateBackupStreamer(archive_name,
                               1369                 :                                              spclocation,
                               1370                 :                                              &state->manifest_inject_streamer,
                               1371                 :                                              true, false,
                               1372                 :                                              state->compress);
                               1373                 :                 }
  446 rhaas                    1374 GIC         139 :                 break;
                               1375                 :             }
  446 rhaas                    1376 ECB             : 
  446 rhaas                    1377 CBC      245640 :         case 'd':
                               1378                 :             {
                               1379                 :                 /* Archive or manifest data. */
  446 rhaas                    1380 GIC      245640 :                 if (state->manifest_buffer != NULL)
                               1381                 :                 {
                               1382                 :                     /* Manifest data, buffer in memory. */
  446 rhaas                    1383 LBC           0 :                     appendPQExpBuffer(state->manifest_buffer, copybuf + 1,
  446 rhaas                    1384 ECB             :                                       r - 1);
                               1385                 :                 }
  446 rhaas                    1386 GIC      245640 :                 else if (state->manifest_file !=NULL)
  446 rhaas                    1387 ECB             :                 {
                               1388                 :                     /* Manifest data, write to disk. */
  446 rhaas                    1389 GIC         557 :                     if (fwrite(copybuf + 1, r - 1, 1,
                               1390                 :                                state->manifest_file) != 1)
                               1391                 :                     {
                               1392                 :                         /*
  446 rhaas                    1393 ECB             :                          * If fwrite() didn't set errno, assume that the
                               1394                 :                          * problem is that we're out of disk space.
                               1395                 :                          */
  446 rhaas                    1396 UIC           0 :                         if (errno == 0)
                               1397               0 :                             errno = ENOSPC;
  366 tgl                      1398               0 :                         pg_fatal("could not write to file \"%s\": %m",
                               1399                 :                                  state->manifest_filename);
  446 rhaas                    1400 ECB             :                     }
                               1401                 :                 }
  446 rhaas                    1402 GIC      245083 :                 else if (state->streamer != NULL)
                               1403                 :                 {
                               1404                 :                     /* Archive data. */
                               1405          245083 :                     bbstreamer_content(state->streamer, NULL, copybuf + 1,
                               1406          245083 :                                        r - 1, BBSTREAMER_UNKNOWN);
  446 rhaas                    1407 ECB             :                 }
  446 rhaas                    1408 EUB             :                 else
  366 tgl                      1409 UIC           0 :                     pg_fatal("unexpected payload data");
  446 rhaas                    1410 GIC      245640 :                 break;
  446 rhaas                    1411 ECB             :             }
                               1412                 : 
  446 rhaas                    1413 GIC         157 :         case 'p':
  446 rhaas                    1414 ECB             :             {
                               1415                 :                 /*
                               1416                 :                  * Progress report.
  446 rhaas                    1417 EUB             :                  *
                               1418                 :                  * The remainder of the message is expected to be an 8-byte
                               1419                 :                  * count of bytes completed.
                               1420                 :                  */
  446 rhaas                    1421 CBC         157 :                 totaldone = GetCopyDataUInt64(r, copybuf, &cursor);
  446 rhaas                    1422 GIC         157 :                 GetCopyDataEnd(r, copybuf, cursor);
                               1423                 : 
  446 rhaas                    1424 EUB             :                 /*
  363 drowley                  1425                 :                  * The server shouldn't send progress report messages too
  446 rhaas                    1426                 :                  * often, so we force an update each time we receive one.
                               1427                 :                  */
  446 rhaas                    1428 CBC         157 :                 progress_report(state->tablespacenum, true, false);
  446 rhaas                    1429 GIC         157 :                 break;
                               1430                 :             }
                               1431                 : 
                               1432             119 :         case 'm':
                               1433                 :             {
                               1434                 :                 /*
                               1435                 :                  * Manifest data will be sent next. This message is not
  446 rhaas                    1436 ECB             :                  * expected to have any further payload data.
                               1437                 :                  */
  446 rhaas                    1438 CBC         119 :                 GetCopyDataEnd(r, copybuf, cursor);
  446 rhaas                    1439 EUB             : 
                               1440                 :                 /*
  509 rhaas                    1441 ECB             :                  * If a backup target was specified, figuring out where to put
                               1442                 :                  * the manifest is the server's problem. Otherwise, we need to
                               1443                 :                  * deal with it.
                               1444                 :                  */
  509 rhaas                    1445 GIC         119 :                 if (backup_target == NULL)
                               1446                 :                 {
                               1447                 :                     /*
                               1448                 :                      * If we're supposed inject the manifest into the archive,
                               1449                 :                      * we prepare to buffer it in memory; otherwise, we
  509 rhaas                    1450 ECB             :                      * prepare to write it to a temporary file.
                               1451                 :                      */
  509 rhaas                    1452 CBC         109 :                     if (state->manifest_inject_streamer != NULL)
  509 rhaas                    1453 LBC           0 :                         state->manifest_buffer = createPQExpBuffer();
                               1454                 :                     else
                               1455                 :                     {
  509 rhaas                    1456 GIC         109 :                         snprintf(state->manifest_filename,
  509 rhaas                    1457 ECB             :                                  sizeof(state->manifest_filename),
  509 rhaas                    1458 EUB             :                                  "%s/backup_manifest.tmp", basedir);
  509 rhaas                    1459 CBC         109 :                         state->manifest_file =
                               1460             109 :                             fopen(state->manifest_filename, "wb");
                               1461             109 :                         if (state->manifest_file == NULL)
  366 tgl                      1462 UIC           0 :                             pg_fatal("could not create file \"%s\": %m",
                               1463                 :                                      state->manifest_filename);
  446 rhaas                    1464 ECB             :                     }
                               1465                 :                 }
  446 rhaas                    1466 GIC         119 :                 break;
                               1467                 :             }
                               1468                 : 
  446 rhaas                    1469 UIC           0 :         default:
                               1470               0 :             ReportCopyDataParseError(r, copybuf);
                               1471               0 :             break;
                               1472                 :     }
  446 rhaas                    1473 GIC      246055 : }
  446 rhaas                    1474 ECB             : 
                               1475                 : /*
                               1476                 :  * Get a single byte from a CopyData message.
                               1477                 :  *
                               1478                 :  * Bail out if none remain.
  446 rhaas                    1479 EUB             :  */
  446 rhaas                    1480 ECB             : static char
  446 rhaas                    1481 CBC      246055 : GetCopyDataByte(size_t r, char *copybuf, size_t *cursor)
  446 rhaas                    1482 ECB             : {
  446 rhaas                    1483 GIC      246055 :     if (*cursor >= r)
  446 rhaas                    1484 UIC           0 :         ReportCopyDataParseError(r, copybuf);
                               1485                 : 
  446 rhaas                    1486 GIC      246055 :     return copybuf[(*cursor)++];
                               1487                 : }
                               1488                 : 
  446 rhaas                    1489 ECB             : /*
                               1490                 :  * Get a NUL-terminated string from a CopyData message.
                               1491                 :  *
  446 rhaas                    1492 EUB             :  * Bail out if the terminating NUL cannot be found.
  446 rhaas                    1493 ECB             :  */
                               1494                 : static char *
  446 rhaas                    1495 GIC         278 : GetCopyDataString(size_t r, char *copybuf, size_t *cursor)
                               1496                 : {
                               1497             278 :     size_t      startpos = *cursor;
                               1498             278 :     size_t      endpos = startpos;
                               1499                 : 
                               1500                 :     while (1)
                               1501                 :     {
                               1502            1832 :         if (endpos >= r)
  446 rhaas                    1503 UIC           0 :             ReportCopyDataParseError(r, copybuf);
  446 rhaas                    1504 GBC        1832 :         if (copybuf[endpos] == '\0')
  446 rhaas                    1505 GIC         278 :             break;
  446 rhaas                    1506 GBC        1554 :         ++endpos;
  446 rhaas                    1507 EUB             :     }
                               1508                 : 
  446 rhaas                    1509 GBC         278 :     *cursor = endpos + 1;
  446 rhaas                    1510 GIC         278 :     return &copybuf[startpos];
                               1511                 : }
                               1512                 : 
                               1513                 : /*
                               1514                 :  * Get an unsigned 64-bit integer from a CopyData message.
                               1515                 :  *
                               1516                 :  * Bail out if there are not at least 8 bytes remaining.
                               1517                 :  */
                               1518                 : static uint64
  446 rhaas                    1519 GBC         157 : GetCopyDataUInt64(size_t r, char *copybuf, size_t *cursor)
                               1520                 : {
                               1521                 :     uint64      result;
                               1522                 : 
  446 rhaas                    1523 GIC         157 :     if (*cursor + sizeof(uint64) > r)
  446 rhaas                    1524 UIC           0 :         ReportCopyDataParseError(r, copybuf);
  446 rhaas                    1525 GIC         157 :     memcpy(&result, &copybuf[*cursor], sizeof(uint64));
                               1526             157 :     *cursor += sizeof(uint64);
                               1527             157 :     return pg_ntoh64(result);
  446 rhaas                    1528 EUB             : }
                               1529                 : 
                               1530                 : /*
                               1531                 :  * Bail out if we didn't parse the whole message.
                               1532                 :  */
                               1533                 : static void
  446 rhaas                    1534 GIC         415 : GetCopyDataEnd(size_t r, char *copybuf, size_t cursor)
                               1535                 : {
                               1536             415 :     if (r != cursor)
  446 rhaas                    1537 UIC           0 :         ReportCopyDataParseError(r, copybuf);
  446 rhaas                    1538 GBC         415 : }
  446 rhaas                    1539 EUB             : 
                               1540                 : /*
                               1541                 :  * Report failure to parse a CopyData message from the server. Then exit.
                               1542                 :  *
                               1543                 :  * As a debugging aid, we try to give some hint about what kind of message
                               1544                 :  * provoked the failure. Perhaps this is not detailed enough, but it's not
                               1545                 :  * clear that it's worth expending any more code on what should be a
                               1546                 :  * can't-happen case.
                               1547                 :  */
                               1548                 : static void
  446 rhaas                    1549 UIC           0 : ReportCopyDataParseError(size_t r, char *copybuf)
                               1550                 : {
                               1551               0 :     if (r == 0)
  366 tgl                      1552               0 :         pg_fatal("empty COPY message");
  446 rhaas                    1553 EUB             :     else
  366 tgl                      1554 UBC           0 :         pg_fatal("malformed COPY message of type %d, length %zu",
  366 tgl                      1555 EUB             :                  copybuf[0], r);
  446 rhaas                    1556                 : }
                               1557                 : 
                               1558                 : /*
  520                          1559                 :  * Receive raw tar data from the server, and stream it to the appropriate
                               1560                 :  * location. If we're writing a single tarfile to standard output, also
                               1561                 :  * receive the backup manifest and inject it into that tarfile.
                               1562                 :  */
                               1563                 : static void
  520 rhaas                    1564 UIC           0 : ReceiveTarFile(PGconn *conn, char *archive_name, char *spclocation,
                               1565                 :                bool tablespacenum, pg_compress_specification *compress)
                               1566                 : {
  520 rhaas                    1567 EUB             :     WriteTarState state;
                               1568                 :     bbstreamer *manifest_inject_streamer;
                               1569                 :     bool        is_recovery_guc_supported;
  516                          1570                 :     bool        expect_unterminated_tarfile;
                               1571                 : 
                               1572                 :     /* Pass all COPY data through to the backup streamer. */
  520 rhaas                    1573 UIC           0 :     memset(&state, 0, sizeof(state));
                               1574               0 :     is_recovery_guc_supported =
                               1575               0 :         PQserverVersion(conn) >= MINIMUM_VERSION_FOR_RECOVERY_GUC;
  516 rhaas                    1576 UBC           0 :     expect_unterminated_tarfile =
  516 rhaas                    1577 UIC           0 :         PQserverVersion(conn) < MINIMUM_VERSION_FOR_TERMINATED_TARFILE;
  520                          1578               0 :     state.streamer = CreateBackupStreamer(archive_name, spclocation,
                               1579                 :                                           &manifest_inject_streamer,
                               1580                 :                                           is_recovery_guc_supported,
                               1581                 :                                           expect_unterminated_tarfile,
  382 rhaas                    1582 EUB             :                                           compress);
  520 rhaas                    1583 UIC           0 :     state.tablespacenum = tablespacenum;
  520 rhaas                    1584 UBC           0 :     ReceiveCopyData(conn, ReceiveTarCopyChunk, &state);
  416 tgl                      1585 UIC           0 :     progress_update_filename(NULL);
 3746 magnus                   1586 EUB             : 
                               1587                 :     /*
  520 rhaas                    1588                 :      * The decision as to whether we need to inject the backup manifest into
                               1589                 :      * the output at this stage is made by CreateBackupStreamer; if that is
                               1590                 :      * needed, manifest_inject_streamer will be non-NULL; otherwise, it will
                               1591                 :      * be NULL.
                               1592                 :      */
  520 rhaas                    1593 UIC           0 :     if (manifest_inject_streamer != NULL)
                               1594                 :     {
                               1595                 :         PQExpBufferData buf;
                               1596                 : 
                               1597                 :         /* Slurp the entire backup manifest into a buffer. */
 1101 rhaas                    1598 LBC           0 :         initPQExpBuffer(&buf);
 1101 rhaas                    1599 UIC           0 :         ReceiveBackupManifestInMemory(conn, &buf);
                               1600               0 :         if (PQExpBufferDataBroken(buf))
  366 tgl                      1601               0 :             pg_fatal("out of memory");
                               1602                 : 
                               1603                 :         /* Inject it into the output tarfile. */
  520 rhaas                    1604 LBC           0 :         bbstreamer_inject_file(manifest_inject_streamer, "backup_manifest",
                               1605               0 :                                buf.data, buf.len);
                               1606                 : 
  520 rhaas                    1607 ECB             :         /* Free memory. */
  520 rhaas                    1608 LBC           0 :         termPQExpBuffer(&buf);
 1221 rhaas                    1609 ECB             :     }
                               1610                 : 
  520                          1611                 :     /* Cleanup. */
  520 rhaas                    1612 UIC           0 :     bbstreamer_finalize(state.streamer);
                               1613               0 :     bbstreamer_free(state.streamer);
                               1614                 : 
                               1615               0 :     progress_report(tablespacenum, true, false);
                               1616                 : 
                               1617                 :     /*
 1221 rhaas                    1618 EUB             :      * Do not sync the resulting tar file yet, all files are synced once at
                               1619                 :      * the end.
                               1620                 :      */
 1221 rhaas                    1621 UIC           0 : }
 1596 peter_e                  1622 EUB             : 
                               1623                 : /*
 1221 rhaas                    1624                 :  * Receive one chunk of tar-format data from the server.
                               1625                 :  */
                               1626                 : static void
 1221 rhaas                    1627 UIC           0 : ReceiveTarCopyChunk(size_t r, char *copybuf, void *callback_data)
 1221 rhaas                    1628 EUB             : {
 1221 rhaas                    1629 UIC           0 :     WriteTarState *state = callback_data;
 1596 peter_e                  1630 EUB             : 
  520 rhaas                    1631 UBC           0 :     bbstreamer_content(state->streamer, NULL, copybuf, r, BBSTREAMER_UNKNOWN);
                               1632                 : 
 1221 rhaas                    1633 UIC           0 :     totaldone += r;
  520                          1634               0 :     progress_report(state->tablespacenum, false, false);
 4459 magnus                   1635               0 : }
                               1636                 : 
 3333 peter_e                  1637 EUB             : 
                               1638                 : /*
                               1639                 :  * Retrieve tablespace path, either relocated or original depending on whether
                               1640                 :  * -T was passed or not.
                               1641                 :  */
                               1642                 : static const char *
 3333 peter_e                  1643 GIC          40 : get_tablespace_mapping(const char *dir)
                               1644                 : {
 3333 peter_e                  1645 EUB             :     TablespaceListCell *cell;
 1985                          1646                 :     char        canon_dir[MAXPGPATH];
                               1647                 : 
                               1648                 :     /* Canonicalize path for comparison consistency */
 1985 peter_e                  1649 GBC          40 :     strlcpy(canon_dir, dir, sizeof(canon_dir));
 1985 peter_e                  1650 GIC          40 :     canonicalize_path(canon_dir);
                               1651                 : 
 3333                          1652              40 :     for (cell = tablespace_dirs.head; cell; cell = cell->next)
 1985                          1653              39 :         if (strcmp(canon_dir, cell->old_dir) == 0)
 3333                          1654              39 :             return cell->new_dir;
 3333 peter_e                  1655 EUB             : 
 3333 peter_e                  1656 GIC           1 :     return dir;
 3333 peter_e                  1657 EUB             : }
                               1658                 : 
                               1659                 : /*
                               1660                 :  * Receive the backup manifest file and write it out to a file.
                               1661                 :  */
                               1662                 : static void
 1101 rhaas                    1663 UIC           0 : ReceiveBackupManifest(PGconn *conn)
 1101 rhaas                    1664 EUB             : {
                               1665                 :     WriteManifestState state;
                               1666                 : 
 1101 rhaas                    1667 UBC           0 :     snprintf(state.filename, sizeof(state.filename),
                               1668                 :              "%s/backup_manifest.tmp", basedir);
                               1669               0 :     state.file = fopen(state.filename, "wb");
                               1670               0 :     if (state.file == NULL)
  366 tgl                      1671 UIC           0 :         pg_fatal("could not create file \"%s\": %m", state.filename);
                               1672                 : 
 1101 rhaas                    1673 LBC           0 :     ReceiveCopyData(conn, ReceiveBackupManifestChunk, &state);
                               1674                 : 
 1101 rhaas                    1675 UIC           0 :     fclose(state.file);
                               1676               0 : }
                               1677                 : 
                               1678                 : /*
                               1679                 :  * Receive one chunk of the backup manifest file and write it out to a file.
                               1680                 :  */
                               1681                 : static void
                               1682               0 : ReceiveBackupManifestChunk(size_t r, char *copybuf, void *callback_data)
 1101 rhaas                    1683 ECB             : {
 1101 rhaas                    1684 UIC           0 :     WriteManifestState *state = callback_data;
                               1685                 : 
 1024 alvherre                 1686               0 :     errno = 0;
 1101 rhaas                    1687               0 :     if (fwrite(copybuf, r, 1, state->file) != 1)
                               1688                 :     {
 1024 alvherre                 1689 ECB             :         /* if write didn't set errno, assume problem is no disk space */
 1024 alvherre                 1690 UIC           0 :         if (errno == 0)
                               1691               0 :             errno = ENOSPC;
  366 tgl                      1692 LBC           0 :         pg_fatal("could not write to file \"%s\": %m", state->filename);
 1101 rhaas                    1693 ECB             :     }
 1101 rhaas                    1694 UIC           0 : }
                               1695                 : 
                               1696                 : /*
                               1697                 :  * Receive the backup manifest file and write it out to a file.
                               1698                 :  */
 1101 rhaas                    1699 ECB             : static void
 1101 rhaas                    1700 LBC           0 : ReceiveBackupManifestInMemory(PGconn *conn, PQExpBuffer buf)
 1101 rhaas                    1701 ECB             : {
 1101 rhaas                    1702 LBC           0 :     ReceiveCopyData(conn, ReceiveBackupManifestInMemoryChunk, buf);
                               1703               0 : }
                               1704                 : 
 1101 rhaas                    1705 EUB             : /*
                               1706                 :  * Receive one chunk of the backup manifest file and write it out to a file.
                               1707                 :  */
                               1708                 : static void
 1101 rhaas                    1709 UIC           0 : ReceiveBackupManifestInMemoryChunk(size_t r, char *copybuf,
 1101 rhaas                    1710 ECB             :                                    void *callback_data)
                               1711                 : {
 1101 rhaas                    1712 UIC           0 :     PQExpBuffer buf = callback_data;
                               1713                 : 
                               1714               0 :     appendPQExpBuffer(buf, copybuf, r);
                               1715               0 : }
                               1716                 : 
 4459 magnus                   1717 ECB             : static void
  382 rhaas                    1718 GIC         142 : BaseBackup(char *compression_algorithm, char *compression_detail,
                               1719                 :            CompressionLocation compressloc, pg_compress_specification *client_compress)
                               1720                 : {
                               1721                 :     PGresult   *res;
                               1722                 :     char       *sysidentifier;
 3112 andres                   1723 EUB             :     TimeLineID  latesttli;
                               1724                 :     TimeLineID  starttli;
                               1725                 :     char       *basebkp;
                               1726                 :     int         i;
                               1727                 :     char        xlogstart[64];
  267 peter                    1728 GNC         142 :     char        xlogend[64] = {0};
                               1729                 :     int         minServerMajor,
 3670 heikki.linnakangas       1730 ECB             :                 maxServerMajor;
 2362 rhaas                    1731                 :     int         serverVersion,
                               1732                 :                 serverMajor;
                               1733                 :     int         writing_to_stdout;
  551 rhaas                    1734 GIC         142 :     bool        use_new_option_syntax = false;
                               1735                 :     PQExpBufferData buf;
 4459 magnus                   1736 ECB             : 
 2362 rhaas                    1737 GBC         142 :     Assert(conn != NULL);
  551 rhaas                    1738 GIC         142 :     initPQExpBuffer(&buf);
                               1739                 : 
                               1740                 :     /*
                               1741                 :      * Check server version. BASE_BACKUP command was introduced in 9.1, so we
 3602 bruce                    1742 ECB             :      * can't work with servers older than 9.1.
 3670 heikki.linnakangas       1743                 :      */
 3670 heikki.linnakangas       1744 CBC         142 :     minServerMajor = 901;
                               1745             142 :     maxServerMajor = PG_VERSION_NUM / 100;
 2362 rhaas                    1746             142 :     serverVersion = PQserverVersion(conn);
                               1747             142 :     serverMajor = serverVersion / 100;
 3670 heikki.linnakangas       1748 GIC         142 :     if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
 3670 heikki.linnakangas       1749 ECB             :     {
 3670 heikki.linnakangas       1750 LBC           0 :         const char *serverver = PQparameterStatus(conn, "server_version");
                               1751                 : 
  366 tgl                      1752 UIC           0 :         pg_fatal("incompatible server version %s",
  366 tgl                      1753 EUB             :                  serverver ? serverver : "'unknown'");
                               1754                 :     }
  551 rhaas                    1755 CBC         142 :     if (serverMajor >= 1500)
  551 rhaas                    1756 GIC         142 :         use_new_option_syntax = true;
 3670 heikki.linnakangas       1757 ECB             : 
                               1758                 :     /*
                               1759                 :      * If WAL streaming was requested, also check that the server is new
 3670 heikki.linnakangas       1760 EUB             :      * enough for that.
                               1761                 :      */
 2281 magnus                   1762 CBC         142 :     if (includewal == STREAM_WAL && !CheckServerVersionForStreaming(conn))
 3670 heikki.linnakangas       1763 ECB             :     {
                               1764                 :         /*
 2286 magnus                   1765                 :          * Error message already written in CheckServerVersionForStreaming(),
                               1766                 :          * but add a hint about using -X none.
                               1767                 :          */
  197 peter                    1768 UIC           0 :         pg_log_error_hint("Use -X none or -X fetch to disable log streaming.");
 1562 peter                    1769 LBC           0 :         exit(1);
 3670 heikki.linnakangas       1770 ECB             :     }
                               1771                 : 
                               1772                 :     /*
 1596 peter_e                  1773 EUB             :      * Build contents of configuration file if requested
                               1774                 :      */
 3746 magnus                   1775 GIC         142 :     if (writerecoveryconf)
 1292 alvherre                 1776               2 :         recoveryconfcontents = GenerateRecoveryConfig(conn, replication_slot);
 3746 magnus                   1777 ECB             : 
                               1778                 :     /*
 4183                          1779                 :      * Run IDENTIFY_SYSTEM so we can get the timeline
                               1780                 :      */
 3112 andres                   1781 CBC         142 :     if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
 1562 peter                    1782 LBC           0 :         exit(1);
                               1783                 : 
                               1784                 :     /*
                               1785                 :      * Start the actual backup
 4448 magnus                   1786 ECB             :      */
  551 rhaas                    1787 GIC         142 :     AppendStringCommandOption(&buf, use_new_option_syntax, "LABEL", label);
                               1788             142 :     if (estimatesize)
                               1789             142 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "PROGRESS");
  551 rhaas                    1790 CBC         142 :     if (includewal == FETCH_WAL)
  551 rhaas                    1791 GBC          24 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "WAL");
  551 rhaas                    1792 GIC         142 :     if (fastcheckpoint)
  551 rhaas                    1793 ECB             :     {
  551 rhaas                    1794 GBC         132 :         if (use_new_option_syntax)
  551 rhaas                    1795 GIC         132 :             AppendStringCommandOption(&buf, use_new_option_syntax,
  551 rhaas                    1796 ECB             :                                       "CHECKPOINT", "fast");
                               1797                 :         else
  551 rhaas                    1798 LBC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax, "FAST");
                               1799                 :     }
  551 rhaas                    1800 CBC         142 :     if (includewal != NO_WAL)
                               1801                 :     {
  551 rhaas                    1802 GIC         135 :         if (use_new_option_syntax)
                               1803             135 :             AppendIntegerCommandOption(&buf, use_new_option_syntax, "WAIT", 0);
                               1804                 :         else
  551 rhaas                    1805 UIC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax, "NOWAIT");
                               1806                 :     }
 3328 alvherre                 1807 CBC         142 :     if (maxrate > 0)
  551 rhaas                    1808               1 :         AppendIntegerCommandOption(&buf, use_new_option_syntax, "MAX_RATE",
                               1809                 :                                    maxrate);
                               1810             142 :     if (format == 't')
  551 rhaas                    1811 GIC          14 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "TABLESPACE_MAP");
                               1812             142 :     if (!verify_checksums)
                               1813                 :     {
  551 rhaas                    1814 CBC           1 :         if (use_new_option_syntax)
                               1815               1 :             AppendIntegerCommandOption(&buf, use_new_option_syntax,
                               1816                 :                                        "VERIFY_CHECKSUMS", 0);
                               1817                 :         else
  551 rhaas                    1818 LBC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax,
                               1819                 :                                      "NOVERIFY_CHECKSUMS");
  551 rhaas                    1820 ECB             :     }
 3328 alvherre                 1821 EUB             : 
 1101 rhaas                    1822 CBC         142 :     if (manifest)
                               1823                 :     {
  551                          1824             141 :         AppendStringCommandOption(&buf, use_new_option_syntax, "MANIFEST",
  509                          1825             141 :                                   manifest_force_encode ? "force-encode" : "yes");
 1101 rhaas                    1826 GIC         141 :         if (manifest_checksums != NULL)
  551                          1827               7 :             AppendStringCommandOption(&buf, use_new_option_syntax,
                               1828                 :                                       "MANIFEST_CHECKSUMS", manifest_checksums);
                               1829                 :     }
 1101 rhaas                    1830 ECB             : 
  509 rhaas                    1831 GBC         142 :     if (backup_target != NULL)
                               1832                 :     {
  509 rhaas                    1833 ECB             :         char       *colon;
                               1834                 : 
  509 rhaas                    1835 GBC          15 :         if (serverMajor < 1500)
  366 tgl                      1836 UBC           0 :             pg_fatal("backup targets are not supported by this server version");
  509 rhaas                    1837 EUB             : 
  437 rhaas                    1838 GIC          15 :         if (writerecoveryconf)
  366 tgl                      1839 UBC           0 :             pg_fatal("recovery configuration cannot be written when a backup target is used");
                               1840                 : 
  509 rhaas                    1841 GIC          15 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "TABLESPACE_MAP");
  509 rhaas                    1842 ECB             : 
  509 rhaas                    1843 CBC          15 :         if ((colon = strchr(backup_target, ':')) == NULL)
                               1844                 :         {
  509 rhaas                    1845 GBC           6 :             AppendStringCommandOption(&buf, use_new_option_syntax,
                               1846                 :                                       "TARGET", backup_target);
  509 rhaas                    1847 ECB             :         }
  509 rhaas                    1848 EUB             :         else
                               1849                 :         {
                               1850                 :             char       *target;
                               1851                 : 
  509 rhaas                    1852 GIC           9 :             target = pnstrdup(backup_target, colon - backup_target);
                               1853               9 :             AppendStringCommandOption(&buf, use_new_option_syntax,
  509 rhaas                    1854 ECB             :                                       "TARGET", target);
  509 rhaas                    1855 CBC           9 :             AppendStringCommandOption(&buf, use_new_option_syntax,
  509 rhaas                    1856 ECB             :                                       "TARGET_DETAIL", colon + 1);
                               1857                 :         }
                               1858                 :     }
  509 rhaas                    1859 GBC         127 :     else if (serverMajor >= 1500)
  446 rhaas                    1860 GIC         127 :         AppendStringCommandOption(&buf, use_new_option_syntax,
                               1861                 :                                   "TARGET", "client");
  446 rhaas                    1862 ECB             : 
  440 rhaas                    1863 GIC         142 :     if (compressloc == COMPRESS_LOCATION_SERVER)
  440 rhaas                    1864 ECB             :     {
  440 rhaas                    1865 GBC          29 :         if (!use_new_option_syntax)
  366 tgl                      1866 UIC           0 :             pg_fatal("server does not support server-side compression");
  440 rhaas                    1867 GIC          29 :         AppendStringCommandOption(&buf, use_new_option_syntax,
                               1868                 :                                   "COMPRESSION", compression_algorithm);
  382                          1869              29 :         if (compression_detail != NULL)
                               1870              14 :             AppendStringCommandOption(&buf, use_new_option_syntax,
                               1871                 :                                       "COMPRESSION_DETAIL",
  382 rhaas                    1872 ECB             :                                       compression_detail);
  440                          1873                 :     }
                               1874                 : 
 2233 magnus                   1875 GBC         142 :     if (verbose)
 1469 peter                    1876 LBC           0 :         pg_log_info("initiating base backup, waiting for checkpoint to complete");
                               1877                 : 
 2233 magnus                   1878 CBC         142 :     if (showprogress && !verbose)
 1955 peter_e                  1879 EUB             :     {
  197 peter                    1880 UIC           0 :         fprintf(stderr, _("waiting for checkpoint"));
 1955 peter_e                  1881               0 :         if (isatty(fileno(stderr)))
                               1882               0 :             fprintf(stderr, "\r");
                               1883                 :         else
                               1884               0 :             fprintf(stderr, "\n");
 1955 peter_e                  1885 ECB             :     }
 2233 magnus                   1886                 : 
  551 rhaas                    1887 GBC         142 :     if (use_new_option_syntax && buf.len > 0)
  551 rhaas                    1888 GIC         142 :         basebkp = psprintf("BASE_BACKUP (%s)", buf.data);
  551 rhaas                    1889 ECB             :     else
  551 rhaas                    1890 UBC           0 :         basebkp = psprintf("BASE_BACKUP %s", buf.data);
                               1891                 : 
 3328 alvherre                 1892 GIC         142 :     if (PQsendQuery(conn, basebkp) == 0)
  366 tgl                      1893 UIC           0 :         pg_fatal("could not send replication command \"%s\": %s",
                               1894                 :                  "BASE_BACKUP", PQerrorMessage(conn));
 4459 magnus                   1895 ECB             : 
                               1896                 :     /*
 2158 peter_e                  1897                 :      * Get the starting WAL location
                               1898                 :      */
 4459 magnus                   1899 CBC         142 :     res = PQgetResult(conn);
 4459 magnus                   1900 GIC         142 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
  366 tgl                      1901              16 :         pg_fatal("could not initiate base backup: %s",
                               1902                 :                  PQerrorMessage(conn));
 3670 heikki.linnakangas       1903             126 :     if (PQntuples(res) != 1)
  366 tgl                      1904 UIC           0 :         pg_fatal("server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields",
                               1905                 :                  PQntuples(res), PQnfields(res), 1, 2);
                               1906                 : 
 3338 tgl                      1907 GIC         126 :     strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
                               1908                 : 
 2233 magnus                   1909             126 :     if (verbose)
 1469 peter                    1910 UIC           0 :         pg_log_info("checkpoint completed");
 2233 magnus                   1911 ECB             : 
                               1912                 :     /*
 3670 heikki.linnakangas       1913                 :      * 9.3 and later sends the TLI of the starting point. With older servers,
                               1914                 :      * assume it's the same as the latest timeline reported by
 3602 bruce                    1915                 :      * IDENTIFY_SYSTEM.
                               1916                 :      */
 3670 heikki.linnakangas       1917 GIC         126 :     if (PQnfields(res) >= 2)
                               1918             126 :         starttli = atoi(PQgetvalue(res, 0, 1));
                               1919                 :     else
 3670 heikki.linnakangas       1920 UIC           0 :         starttli = latesttli;
 4448 magnus                   1921 GIC         126 :     PQclear(res);
 4448 magnus                   1922 ECB             : 
 2281 magnus                   1923 CBC         126 :     if (verbose && includewal != NO_WAL)
 1469 peter                    1924 UBC           0 :         pg_log_info("write-ahead log start point: %s on timeline %u",
                               1925                 :                     xlogstart, starttli);
                               1926                 : 
                               1927                 :     /*
                               1928                 :      * Get the header
                               1929                 :      */
 4448 magnus                   1930 GIC         126 :     res = PQgetResult(conn);
 4448 magnus                   1931 CBC         126 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
  366 tgl                      1932 UIC           0 :         pg_fatal("could not get backup header: %s",
                               1933                 :                  PQerrorMessage(conn));
 4459 magnus                   1934 GIC         126 :     if (PQntuples(res) < 1)
  366 tgl                      1935 UIC           0 :         pg_fatal("no data returned from server");
 4459 magnus                   1936 ECB             : 
 4459 magnus                   1937 EUB             :     /*
                               1938                 :      * Sum up the total size, for progress reporting
 4459 magnus                   1939 ECB             :      */
 1314 peter                    1940 GIC         126 :     totalsize_kb = totaldone = 0;
 4459 magnus                   1941 CBC         126 :     tablespacecount = PQntuples(res);
                               1942             266 :     for (i = 0; i < PQntuples(res); i++)
                               1943                 :     {
 1314 peter                    1944 GIC         141 :         totalsize_kb += atol(PQgetvalue(res, i, 2));
                               1945                 : 
 4459 magnus                   1946 ECB             :         /*
                               1947                 :          * Verify tablespace directories are empty. Don't bother with the
                               1948                 :          * first once since it can be relocated, and it will be checked before
                               1949                 :          * we do anything anyway.
  509 rhaas                    1950                 :          *
                               1951                 :          * Note that this is skipped for tar format backups and backups that
                               1952                 :          * the server is storing to a target location, since in that case we
                               1953                 :          * won't be storing anything into these directories and thus should
                               1954                 :          * not create them.
 4459 magnus                   1955                 :          */
  509 rhaas                    1956 GIC         141 :         if (backup_target == NULL && format == 'p' && !PQgetisnull(res, i, 1))
                               1957                 :         {
 1531 peter                    1958 CBC          14 :             char       *path = unconstify(char *, get_tablespace_mapping(PQgetvalue(res, i, 1)));
                               1959                 : 
 2400 peter_e                  1960 GIC          14 :             verify_dir_is_empty_or_create(path, &made_tablespace_dirs, &found_tablespace_dirs);
                               1961                 :         }
                               1962                 :     }
 4459 magnus                   1963 EUB             : 
                               1964                 :     /*
                               1965                 :      * When writing to stdout, require a single tablespace
                               1966                 :      */
  509 rhaas                    1967 GIC         139 :     writing_to_stdout = format == 't' && basedir != NULL &&
                               1968              14 :         strcmp(basedir, "-") == 0;
 1101                          1969             125 :     if (writing_to_stdout && PQntuples(res) > 1)
  366 tgl                      1970 UIC           0 :         pg_fatal("can only write single tablespace to stdout, database has %d",
                               1971                 :                  PQntuples(res));
                               1972                 : 
                               1973                 :     /*
                               1974                 :      * If we're streaming WAL, start the streaming session before we start
                               1975                 :      * receiving the actual data chunks.
 4183 magnus                   1976 EUB             :      */
 2281 magnus                   1977 GIC         125 :     if (includewal == STREAM_WAL)
 4183 magnus                   1978 EUB             :     {
  332 tgl                      1979                 :         pg_compress_algorithm wal_compress_algorithm;
                               1980                 :         int         wal_compress_level;
                               1981                 : 
 4183 magnus                   1982 GIC          99 :         if (verbose)
 1469 peter                    1983 UBC           0 :             pg_log_info("starting background WAL receiver");
                               1984                 : 
  362 michael                  1985 GBC          99 :         if (client_compress->algorithm == PG_COMPRESSION_GZIP)
                               1986                 :         {
  362 michael                  1987 GIC           3 :             wal_compress_algorithm = PG_COMPRESSION_GZIP;
  207 michael                  1988 GBC           3 :             wal_compress_level = client_compress->level;
                               1989                 :         }
                               1990                 :         else
                               1991                 :         {
  362 michael                  1992 GIC          96 :             wal_compress_algorithm = PG_COMPRESSION_NONE;
  382 rhaas                    1993              96 :             wal_compress_level = 0;
                               1994                 :         }
                               1995                 : 
                               1996              99 :         StartLogStreamer(xlogstart, starttli, sysidentifier,
                               1997                 :                          wal_compress_algorithm,
                               1998                 :                          wal_compress_level);
                               1999                 :     }
                               2000                 : 
  446                          2001             124 :     if (serverMajor >= 1500)
                               2002                 :     {
  446 rhaas                    2003 EUB             :         /* Receive a single tar stream with everything. */
  382 rhaas                    2004 GBC         124 :         ReceiveArchiveStream(conn, client_compress);
                               2005                 :     }
                               2006                 :     else
  446 rhaas                    2007 ECB             :     {
                               2008                 :         /* Receive a tar file for each tablespace in turn */
  446 rhaas                    2009 UBC           0 :         for (i = 0; i < PQntuples(res); i++)
  520 rhaas                    2010 EUB             :         {
                               2011                 :             char        archive_name[MAXPGPATH];
                               2012                 :             char       *spclocation;
  446 rhaas                    2013 ECB             : 
                               2014                 :             /*
                               2015                 :              * If we write the data out to a tar file, it will be named
                               2016                 :              * base.tar if it's the main data directory or <tablespaceoid>.tar
                               2017                 :              * if it's for another tablespace. CreateBackupStreamer() will
                               2018                 :              * arrange to add an extension to the archive name if
                               2019                 :              * pg_basebackup is performing compression, depending on the
                               2020                 :              * compression type.
                               2021                 :              */
  446 rhaas                    2022 UIC           0 :             if (PQgetisnull(res, i, 0))
  446 rhaas                    2023 ECB             :             {
  446 rhaas                    2024 UBC           0 :                 strlcpy(archive_name, "base.tar", sizeof(archive_name));
  446 rhaas                    2025 LBC           0 :                 spclocation = NULL;
  446 rhaas                    2026 ECB             :             }
  446 rhaas                    2027 EUB             :             else
  446 rhaas                    2028 ECB             :             {
  446 rhaas                    2029 UIC           0 :                 snprintf(archive_name, sizeof(archive_name),
  446 rhaas                    2030 ECB             :                          "%s.tar", PQgetvalue(res, i, 0));
  446 rhaas                    2031 LBC           0 :                 spclocation = PQgetvalue(res, i, 1);
                               2032                 :             }
  446 rhaas                    2033 ECB             : 
  382 rhaas                    2034 UIC           0 :             ReceiveTarFile(conn, archive_name, spclocation, i,
  382 rhaas                    2035 ECB             :                            client_compress);
  520                          2036                 :         }
                               2037                 : 
  446                          2038                 :         /*
                               2039                 :          * Now receive backup manifest, if appropriate.
                               2040                 :          *
                               2041                 :          * If we're writing a tarfile to stdout, ReceiveTarFile will have
                               2042                 :          * already processed the backup manifest and included it in the output
  446 rhaas                    2043 EUB             :          * tarfile.  Such a configuration doesn't allow for writing multiple
                               2044                 :          * files.
                               2045                 :          *
  446 rhaas                    2046 ECB             :          * If we're talking to an older server, it won't send a backup
                               2047                 :          * manifest, so don't try to receive one.
                               2048                 :          */
  446 rhaas                    2049 LBC           0 :         if (!writing_to_stdout && manifest)
  446 rhaas                    2050 UIC           0 :             ReceiveBackupManifest(conn);
                               2051                 :     }
                               2052                 : 
 4459 magnus                   2053 GIC         121 :     if (showprogress)
                               2054                 :     {
  416 tgl                      2055 UIC           0 :         progress_update_filename(NULL);
  520 rhaas                    2056               0 :         progress_report(PQntuples(res), true, true);
                               2057                 :     }
                               2058                 : 
 4459 magnus                   2059 GIC         121 :     PQclear(res);
                               2060                 : 
                               2061                 :     /*
                               2062                 :      * Get the stop position
                               2063                 :      */
 4448                          2064             121 :     res = PQgetResult(conn);
                               2065             121 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
  366 tgl                      2066 CBC           1 :         pg_fatal("backup failed: %s",
  366 tgl                      2067 EUB             :                  PQerrorMessage(conn));
 4448 magnus                   2068 GIC         120 :     if (PQntuples(res) != 1)
  366 tgl                      2069 UIC           0 :         pg_fatal("no write-ahead log end position returned from server");
 3338 tgl                      2070 CBC         120 :     strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
 2281 magnus                   2071 GBC         120 :     if (verbose && includewal != NO_WAL)
 1469 peter                    2072 UIC           0 :         pg_log_info("write-ahead log end point: %s", xlogend);
 4448 magnus                   2073 GIC         120 :     PQclear(res);
 4448 magnus                   2074 ECB             : 
 4459 magnus                   2075 CBC         120 :     res = PQgetResult(conn);
 4459 magnus                   2076 GBC         120 :     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 4459 magnus                   2077 ECB             :     {
 1832 magnus                   2078 GBC           3 :         const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
 1832 magnus                   2079 ECB             : 
 1832 magnus                   2080 GBC           3 :         if (sqlstate &&
 1832 magnus                   2081 GIC           3 :             strcmp(sqlstate, ERRCODE_DATA_CORRUPTED) == 0)
                               2082                 :         {
 1469 peter                    2083               3 :             pg_log_error("checksum error occurred");
 1832 magnus                   2084               3 :             checksum_failure = true;
                               2085                 :         }
                               2086                 :         else
                               2087                 :         {
 1469 peter                    2088 UIC           0 :             pg_log_error("final receive failed: %s",
                               2089                 :                          PQerrorMessage(conn));
                               2090                 :         }
 1562 peter                    2091 GIC           3 :         exit(1);
                               2092                 :     }
                               2093                 : 
 4183 magnus                   2094             117 :     if (bgchild > 0)
                               2095                 :     {
                               2096                 : #ifndef WIN32
                               2097                 :         int         status;
                               2098                 :         pid_t       r;
                               2099                 : #else
                               2100                 :         DWORD       status;
                               2101                 : 
                               2102                 :         /*
                               2103                 :          * get a pointer sized version of bgchild to avoid warnings about
                               2104                 :          * casting to a different size on WIN64.
                               2105                 :          */
                               2106                 :         intptr_t    bgchild_handle = bgchild;
                               2107                 :         uint32      hi,
                               2108                 :                     lo;
                               2109                 : #endif
                               2110                 : 
                               2111              91 :         if (verbose)
 1469 peter                    2112 UIC           0 :             pg_log_info("waiting for background process to finish streaming ...");
                               2113                 : 
                               2114                 : #ifndef WIN32
 4029 andrew                   2115 CBC          91 :         if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
  366 tgl                      2116 UIC           0 :             pg_fatal("could not send command to background pipe: %m");
                               2117                 : 
                               2118                 :         /* Just wait for the background process to exit */
 4183 magnus                   2119 GIC          91 :         r = waitpid(bgchild, &status, 0);
 1575 tgl                      2120 CBC          91 :         if (r == (pid_t) -1)
  366 tgl                      2121 LBC           0 :             pg_fatal("could not wait for child process: %m");
 4183 magnus                   2122 CBC          91 :         if (r != bgchild)
  366 tgl                      2123 UIC           0 :             pg_fatal("child %d died, expected %d", (int) r, (int) bgchild);
 1575 tgl                      2124 GIC          91 :         if (status != 0)
  366 tgl                      2125 UIC           0 :             pg_fatal("%s", wait_result_to_str(status));
                               2126                 :         /* Exited normally, we're happy! */
                               2127                 : #else                           /* WIN32 */
                               2128                 : 
                               2129                 :         /*
                               2130                 :          * On Windows, since we are in the same process, we can just store the
                               2131                 :          * value directly in the variable, and then set the flag that says
                               2132                 :          * it's there.
                               2133                 :          */
 3941 heikki.linnakangas       2134 ECB             :         if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
                               2135                 :             pg_fatal("could not parse write-ahead log location \"%s\"",
  366 tgl                      2136 EUB             :                      xlogend);
 3941 heikki.linnakangas       2137                 :         xlogendptr = ((uint64) hi) << 32 | lo;
 4183 magnus                   2138                 :         InterlockedIncrement(&has_xlogendptr);
                               2139                 : 
                               2140                 :         /* First wait for the thread to exit */
 2536 andrew                   2141                 :         if (WaitForSingleObjectEx((HANDLE) bgchild_handle, INFINITE, FALSE) !=
                               2142                 :             WAIT_OBJECT_0)
                               2143                 :         {
                               2144                 :             _dosmaperr(GetLastError());
  366 tgl                      2145                 :             pg_fatal("could not wait for child thread: %m");
                               2146                 :         }
                               2147                 :         if (GetExitCodeThread((HANDLE) bgchild_handle, &status) == 0)
                               2148                 :         {
                               2149                 :             _dosmaperr(GetLastError());
                               2150                 :             pg_fatal("could not get child thread exit status: %m");
                               2151                 :         }
                               2152                 :         if (status != 0)
                               2153                 :             pg_fatal("child thread exited with error %u",
                               2154                 :                      (unsigned int) status);
                               2155                 :         /* Exited normally, we're happy */
 4183 magnus                   2156 ECB             : #endif
                               2157                 :     }
                               2158                 : 
                               2159                 :     /* Free the configuration file contents */
 3746 magnus                   2160 GIC         117 :     destroyPQExpBuffer(recoveryconfcontents);
 3746 magnus                   2161 ECB             : 
 4459 magnus                   2162 EUB             :     /*
                               2163                 :      * End of copy data. Final result is already checked inside the loop.
 4459 magnus                   2164 ECB             :      */
 4097 magnus                   2165 CBC         117 :     PQclear(res);
 4459 magnus                   2166 GIC         117 :     PQfinish(conn);
 1562 peter                    2167 CBC         117 :     conn = NULL;
                               2168                 : 
                               2169                 :     /*
 2153 bruce                    2170 EUB             :      * Make data persistent on disk once backup is completed. For tar format
 1313 michael                  2171                 :      * sync the parent directory and all its contents as each tar file was not
                               2172                 :      * synced after being completed.  In plain format, all the data of the
                               2173                 :      * base directory is synced, taking into account all the tablespaces.
                               2174                 :      * Errors are not considered fatal.
  509 rhaas                    2175 ECB             :      *
  509 rhaas                    2176 EUB             :      * If, however, there's a backup target, we're not writing anything
                               2177                 :      * locally, so in that case we skip this step.
                               2178                 :      */
  509 rhaas                    2179 GIC         117 :     if (do_sync && backup_target == NULL)
                               2180                 :     {
 1715 michael                  2181 LBC           0 :         if (verbose)
 1469 peter                    2182 UBC           0 :             pg_log_info("syncing data to disk ...");
 2383 peter_e                  2183 LBC           0 :         if (format == 't')
                               2184                 :         {
 2383 peter_e                  2185 UIC           0 :             if (strcmp(basedir, "-") != 0)
 1313 michael                  2186               0 :                 (void) fsync_dir_recurse(basedir);
 2383 peter_e                  2187 ECB             :         }
                               2188                 :         else
                               2189                 :         {
 1469 peter                    2190 UIC           0 :             (void) fsync_pgdata(basedir, serverVersion);
                               2191                 :         }
                               2192                 :     }
                               2193                 : 
                               2194                 :     /*
                               2195                 :      * After synchronizing data to disk, perform a durable rename of
                               2196                 :      * backup_manifest.tmp to backup_manifest, if we wrote such a file. This
                               2197                 :      * way, a failure or system crash before we reach this point will leave us
                               2198                 :      * without a backup_manifest file, decreasing the chances that a directory
                               2199                 :      * we leave behind will be mistaken for a valid backup.
                               2200                 :      */
  509 rhaas                    2201 GIC         117 :     if (!writing_to_stdout && manifest && backup_target == NULL)
                               2202                 :     {
                               2203                 :         char        tmp_filename[MAXPGPATH];
                               2204                 :         char        filename[MAXPGPATH];
                               2205                 : 
 1101                          2206             106 :         if (verbose)
 1101 rhaas                    2207 UIC           0 :             pg_log_info("renaming backup_manifest.tmp to backup_manifest");
                               2208                 : 
 1101 rhaas                    2209 GIC         106 :         snprintf(tmp_filename, MAXPGPATH, "%s/backup_manifest.tmp", basedir);
                               2210             106 :         snprintf(filename, MAXPGPATH, "%s/backup_manifest", basedir);
                               2211                 : 
  441 andres                   2212             106 :         if (do_sync)
                               2213                 :         {
                               2214                 :             /* durable_rename emits its own log message in case of failure */
  441 andres                   2215 UIC           0 :             if (durable_rename(tmp_filename, filename) != 0)
                               2216               0 :                 exit(1);
                               2217                 :         }
                               2218                 :         else
                               2219                 :         {
  441 andres                   2220 GIC         106 :             if (rename(tmp_filename, filename) != 0)
  366 tgl                      2221 UIC           0 :                 pg_fatal("could not rename file \"%s\" to \"%s\": %m",
                               2222                 :                          tmp_filename, filename);
                               2223                 :         }
                               2224                 :     }
                               2225                 : 
 4459 magnus                   2226 GIC         117 :     if (verbose)
 1469 peter                    2227 UIC           0 :         pg_log_info("base backup completed");
 4459 magnus                   2228 CBC         117 : }
 4459 magnus                   2229 ECB             : 
                               2230                 : 
                               2231                 : int
 4459 magnus                   2232 GIC         176 : main(int argc, char **argv)
 4459 magnus                   2233 ECB             : {
                               2234                 :     static struct option long_options[] = {
                               2235                 :         {"help", no_argument, NULL, '?'},
                               2236                 :         {"version", no_argument, NULL, 'V'},
                               2237                 :         {"pgdata", required_argument, NULL, 'D'},
                               2238                 :         {"format", required_argument, NULL, 'F'},
                               2239                 :         {"checkpoint", required_argument, NULL, 'c'},
                               2240                 :         {"create-slot", no_argument, NULL, 'C'},
 3328 alvherre                 2241                 :         {"max-rate", required_argument, NULL, 'r'},
 3746 magnus                   2242                 :         {"write-recovery-conf", no_argument, NULL, 'R'},
                               2243                 :         {"slot", required_argument, NULL, 'S'},
  509 rhaas                    2244                 :         {"target", required_argument, NULL, 't'},
 3333 peter_e                  2245                 :         {"tablespace-mapping", required_argument, NULL, 'T'},
                               2246                 :         {"wal-method", required_argument, NULL, 'X'},
 4332                          2247                 :         {"gzip", no_argument, NULL, 'z'},
 4459 magnus                   2248                 :         {"compress", required_argument, NULL, 'Z'},
                               2249                 :         {"label", required_argument, NULL, 'l'},
                               2250                 :         {"no-clean", no_argument, NULL, 'n'},
                               2251                 :         {"no-sync", no_argument, NULL, 'N'},
 3695 heikki.linnakangas       2252                 :         {"dbname", required_argument, NULL, 'd'},
                               2253                 :         {"host", required_argument, NULL, 'h'},
 4459 magnus                   2254                 :         {"port", required_argument, NULL, 'p'},
                               2255                 :         {"username", required_argument, NULL, 'U'},
                               2256                 :         {"no-password", no_argument, NULL, 'w'},
                               2257                 :         {"password", no_argument, NULL, 'W'},
                               2258                 :         {"status-interval", required_argument, NULL, 's'},
                               2259                 :         {"verbose", no_argument, NULL, 'v'},
                               2260                 :         {"progress", no_argument, NULL, 'P'},
 2250 rhaas                    2261                 :         {"waldir", required_argument, NULL, 1},
 2274 magnus                   2262 EUB             :         {"no-slot", no_argument, NULL, 2},
 1784 peter_e                  2263                 :         {"no-verify-checksums", no_argument, NULL, 3},
                               2264                 :         {"no-estimate-size", no_argument, NULL, 4},
 1101 rhaas                    2265                 :         {"no-manifest", no_argument, NULL, 5},
                               2266                 :         {"manifest-force-encode", no_argument, NULL, 6},
 1101 rhaas                    2267 ECB             :         {"manifest-checksums", required_argument, NULL, 7},
 4459 magnus                   2268                 :         {NULL, 0, NULL, 0}
                               2269                 :     };
                               2270                 :     int         c;
                               2271                 : 
                               2272                 :     int         option_index;
  382 rhaas                    2273 CBC         176 :     char       *compression_algorithm = "none";
                               2274             176 :     char       *compression_detail = NULL;
  332 tgl                      2275             176 :     CompressionLocation compressloc = COMPRESS_LOCATION_UNSPECIFIED;
  332 tgl                      2276 ECB             :     pg_compress_specification client_compress;
 4459 magnus                   2277                 : 
 1469 peter                    2278 CBC         176 :     pg_logging_init(argv[0]);
 4459 magnus                   2279             176 :     progname = get_progname(argv[0]);
                               2280             176 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
 4459 magnus                   2281 ECB             : 
 4459 magnus                   2282 GIC         176 :     if (argc > 1)
 4459 magnus                   2283 EUB             :     {
 4459 magnus                   2284 GIC         175 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
 4459 magnus                   2285 ECB             :         {
 4459 magnus                   2286 CBC           1 :             usage();
                               2287               1 :             exit(0);
 4459 magnus                   2288 ECB             :         }
 4459 magnus                   2289 GBC         174 :         else if (strcmp(argv[1], "-V") == 0
                               2290             174 :                  || strcmp(argv[1], "--version") == 0)
 4459 magnus                   2291 EUB             :         {
 4459 magnus                   2292 CBC           1 :             puts("pg_basebackup (PostgreSQL) " PG_VERSION);
                               2293               1 :             exit(0);
 4459 magnus                   2294 ECB             :         }
                               2295                 :     }
                               2296                 : 
 2400 peter_e                  2297 CBC         174 :     atexit(cleanup_directories_atexit);
 2400 peter_e                  2298 ECB             : 
  118 peter                    2299 GNC         920 :     while ((c = getopt_long(argc, argv, "c:Cd:D:F:h:l:nNp:Pr:Rs:S:t:T:U:vwWX:zZ:",
 4459 magnus                   2300 CBC         920 :                             long_options, &option_index)) != -1)
 4459 magnus                   2301 EUB             :     {
 4459 magnus                   2302 GBC         753 :         switch (c)
 4459 magnus                   2303 EUB             :         {
  118 peter                    2304 GNC         150 :             case 'c':
                               2305             150 :                 if (pg_strcasecmp(optarg, "fast") == 0)
                               2306             150 :                     fastcheckpoint = true;
  118 peter                    2307 UNC           0 :                 else if (pg_strcasecmp(optarg, "spread") == 0)
                               2308               0 :                     fastcheckpoint = false;
                               2309                 :                 else
                               2310               0 :                     pg_fatal("invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"",
                               2311                 :                              optarg);
  118 peter                    2312 GNC         150 :                 break;
 2021 peter_e                  2313 CBC           6 :             case 'C':
                               2314               6 :                 create_slot = true;
                               2315               6 :                 break;
  118 peter                    2316 GNC           1 :             case 'd':
                               2317               1 :                 connection_string = pg_strdup(optarg);
                               2318               1 :                 break;
 4459 magnus                   2319 CBC         154 :             case 'D':
 3841 tgl                      2320             154 :                 basedir = pg_strdup(optarg);
 4459 magnus                   2321             154 :                 break;
 4459 magnus                   2322 GBC          29 :             case 'F':
                               2323              29 :                 if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
 4459 magnus                   2324 GIC          14 :                     format = 'p';
                               2325              15 :                 else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
 4459 magnus                   2326 GBC          15 :                     format = 't';
 4459 magnus                   2327 EUB             :                 else
  366 tgl                      2328 UBC           0 :                     pg_fatal("invalid output format \"%s\", must be \"plain\" or \"tar\"",
  366 tgl                      2329 ECB             :                              optarg);
 4459 magnus                   2330 GIC          29 :                 break;
  118 peter                    2331 GNC          54 :             case 'h':
                               2332              54 :                 dbhost = pg_strdup(optarg);
                               2333              54 :                 break;
  118 peter                    2334 UNC           0 :             case 'l':
                               2335               0 :                 label = pg_strdup(optarg);
                               2336               0 :                 break;
  118 peter                    2337 GNC           1 :             case 'n':
                               2338               1 :                 noclean = true;
                               2339               1 :                 break;
                               2340             150 :             case 'N':
                               2341             150 :                 do_sync = false;
                               2342             150 :                 break;
                               2343              54 :             case 'p':
                               2344              54 :                 dbport = pg_strdup(optarg);
                               2345              54 :                 break;
  118 peter                    2346 UNC           0 :             case 'P':
                               2347               0 :                 showprogress = true;
                               2348               0 :                 break;
 3328 alvherre                 2349 GIC           1 :             case 'r':
                               2350               1 :                 maxrate = parse_max_rate(optarg);
                               2351               1 :                 break;
 3746 magnus                   2352               2 :             case 'R':
 3746 magnus                   2353 CBC           2 :                 writerecoveryconf = true;
                               2354               2 :                 break;
  118 peter                    2355 UNC           0 :             case 's':
                               2356               0 :                 if (!option_parse_int(optarg, "-s/--status-interval", 0,
                               2357                 :                                       INT_MAX / 1000,
                               2358                 :                                       &standby_message_timeout))
                               2359               0 :                     exit(1);
                               2360               0 :                 standby_message_timeout *= 1000;
                               2361               0 :                 break;
 2819 peter_e                  2362 CBC           9 :             case 'S':
 2274 magnus                   2363 ECB             : 
                               2364                 :                 /*
                               2365                 :                  * When specifying replication slot name, use a permanent
                               2366                 :                  * slot.
                               2367                 :                  */
 2819 peter_e                  2368 CBC           9 :                 replication_slot = pg_strdup(optarg);
 2274 magnus                   2369               9 :                 temp_replication_slot = false;
                               2370               9 :                 break;
  509 rhaas                    2371 GBC          20 :             case 't':
                               2372              20 :                 backup_target = pg_strdup(optarg);
                               2373              20 :                 break;
 3333 peter_e                  2374              19 :             case 'T':
                               2375              19 :                 tablespace_list_append(optarg);
                               2376              13 :                 break;
  118 peter                    2377 GNC           7 :             case 'U':
                               2378               7 :                 dbuser = pg_strdup(optarg);
                               2379               7 :                 break;
  118 peter                    2380 UNC           0 :             case 'v':
                               2381               0 :                 verbose++;
                               2382               0 :                 break;
                               2383               0 :             case 'w':
                               2384               0 :                 dbgetpassword = -1;
                               2385               0 :                 break;
                               2386               0 :             case 'W':
                               2387               0 :                 dbgetpassword = 1;
                               2388               0 :                 break;
 3955 magnus                   2389 GBC          43 :             case 'X':
 2286 magnus                   2390 CBC          43 :                 if (strcmp(optarg, "n") == 0 ||
                               2391              43 :                     strcmp(optarg, "none") == 0)
 3955 magnus                   2392 ECB             :                 {
 2281 magnus                   2393 GIC          10 :                     includewal = NO_WAL;
 3955 magnus                   2394 ECB             :                 }
 2286 magnus                   2395 GIC          33 :                 else if (strcmp(optarg, "f") == 0 ||
 2153 bruce                    2396 CBC          33 :                          strcmp(optarg, "fetch") == 0)
 2286 magnus                   2397 ECB             :                 {
 2281 magnus                   2398 GIC          24 :                     includewal = FETCH_WAL;
 2286 magnus                   2399 ECB             :                 }
 4183 magnus                   2400 GIC           9 :                 else if (strcmp(optarg, "s") == 0 ||
 4183 magnus                   2401 CBC           9 :                          strcmp(optarg, "stream") == 0)
 2286 magnus                   2402 ECB             :                 {
 2281 magnus                   2403 GIC           9 :                     includewal = STREAM_WAL;
 2286 magnus                   2404 ECB             :                 }
                               2405                 :                 else
  366 tgl                      2406 UIC           0 :                     pg_fatal("invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"",
  366 tgl                      2407 EUB             :                              optarg);
 4452 magnus                   2408 GIC          43 :                 break;
 4332 peter_e                  2409 CBC           1 :             case 'z':
  382 rhaas                    2410               1 :                 compression_algorithm = "gzip";
                               2411               1 :                 compression_detail = NULL;
  440                          2412               1 :                 compressloc = COMPRESS_LOCATION_UNSPECIFIED;
 4332 peter_e                  2413               1 :                 break;
 4459 magnus                   2414              37 :             case 'Z':
  130 michael                  2415 GNC          37 :                 backup_parse_compress_options(optarg, &compression_algorithm,
                               2416                 :                                               &compression_detail, &compressloc);
 4459 magnus                   2417 GBC          37 :                 break;
  118 peter                    2418 GNC           1 :             case 1:
                               2419               1 :                 xlog_dir = pg_strdup(optarg);
 4459 magnus                   2420 CBC           1 :                 break;
  118 peter                    2421 GNC           3 :             case 2:
                               2422               3 :                 no_slot = true;
 4459 magnus                   2423 GIC           3 :                 break;
 1784 peter_e                  2424               1 :             case 3:
 1832 magnus                   2425               1 :                 verify_checksums = false;
                               2426               1 :                 break;
 1116 fujii                    2427 LBC           0 :             case 4:
 1116 fujii                    2428 UIC           0 :                 estimatesize = false;
 1116 fujii                    2429 LBC           0 :                 break;
 1101 rhaas                    2430 CBC           1 :             case 5:
                               2431               1 :                 manifest = false;
 1101 rhaas                    2432 GIC           1 :                 break;
 1101 rhaas                    2433 CBC           1 :             case 6:
                               2434               1 :                 manifest_force_encode = true;
 1101 rhaas                    2435 GIC           1 :                 break;
                               2436               7 :             case 7:
                               2437               7 :                 manifest_checksums = pg_strdup(optarg);
                               2438               7 :                 break;
 4459 magnus                   2439 CBC           1 :             default:
                               2440                 :                 /* getopt_long already emitted a complaint */
  366 tgl                      2441               1 :                 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 4459 magnus                   2442               1 :                 exit(1);
 4459 magnus                   2443 ECB             :         }
                               2444                 :     }
                               2445                 : 
                               2446                 :     /*
                               2447                 :      * Any non-option arguments?
                               2448                 :      */
 4459 magnus                   2449 CBC         167 :     if (optind < argc)
                               2450                 :     {
 1469 peter                    2451 UIC           0 :         pg_log_error("too many command-line arguments (first is \"%s\")",
                               2452                 :                      argv[optind]);
  366 tgl                      2453               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 4459 magnus                   2454               0 :         exit(1);
                               2455                 :     }
                               2456                 : 
 4459 magnus                   2457 ECB             :     /*
                               2458                 :      * Setting the backup target to 'client' is equivalent to leaving out the
  509 rhaas                    2459                 :      * option. This logic allows us to assume elsewhere that the backup is
                               2460                 :      * being stored locally if and only if backup_target == NULL.
                               2461                 :      */
  509 rhaas                    2462 CBC         167 :     if (backup_target != NULL && strcmp(backup_target, "client") == 0)
                               2463                 :     {
  509 rhaas                    2464 UIC           0 :         pg_free(backup_target);
                               2465               0 :         backup_target = NULL;
                               2466                 :     }
                               2467                 : 
                               2468                 :     /*
                               2469                 :      * Can't use --format with --target. Without --target, default format is
                               2470                 :      * tar.
  509 rhaas                    2471 ECB             :      */
  509 rhaas                    2472 GIC         167 :     if (backup_target != NULL && format != '\0')
                               2473                 :     {
                               2474               1 :         pg_log_error("cannot specify both format and backup target");
  366 tgl                      2475               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
  509 rhaas                    2476 CBC           1 :         exit(1);
  509 rhaas                    2477 ECB             :     }
  509 rhaas                    2478 GIC         166 :     if (format == '\0')
                               2479             144 :         format = 'p';
  509 rhaas                    2480 ECB             : 
                               2481                 :     /*
                               2482                 :      * Either directory or backup target should be specified, but not both
 4459 magnus                   2483                 :      */
  509 rhaas                    2484 GIC         166 :     if (basedir == NULL && backup_target == NULL)
                               2485                 :     {
                               2486               1 :         pg_log_error("must specify output directory or backup target");
  366 tgl                      2487               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
  509 rhaas                    2488 CBC           1 :         exit(1);
  509 rhaas                    2489 ECB             :     }
  509 rhaas                    2490 CBC         165 :     if (basedir != NULL && backup_target != NULL)
                               2491                 :     {
  509 rhaas                    2492 GIC           2 :         pg_log_error("cannot specify both output directory and backup target");
  366 tgl                      2493               2 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 4459 magnus                   2494               2 :         exit(1);
                               2495                 :     }
                               2496                 : 
 4459 magnus                   2497 ECB             :     /*
                               2498                 :      * If the user has not specified where to perform backup compression,
  332 tgl                      2499 EUB             :      * default to the client, unless the user specified --target, in which
                               2500                 :      * case the server is the only choice.
 4459 magnus                   2501                 :      */
  382 rhaas                    2502 GIC         163 :     if (compressloc == COMPRESS_LOCATION_UNSPECIFIED)
                               2503                 :     {
  509                          2504             140 :         if (backup_target == NULL)
  440                          2505             127 :             compressloc = COMPRESS_LOCATION_CLIENT;
                               2506                 :         else
  440 rhaas                    2507 CBC          13 :             compressloc = COMPRESS_LOCATION_SERVER;
  440 rhaas                    2508 ECB             :     }
                               2509                 : 
  382 rhaas                    2510 EUB             :     /*
  332 tgl                      2511                 :      * If any compression that we're doing is happening on the client side, we
                               2512                 :      * must try to parse the compression algorithm and detail, but if it's all
                               2513                 :      * on the server side, then we're just going to pass through whatever was
                               2514                 :      * requested and let the server decide what to do.
                               2515                 :      */
  382 rhaas                    2516 GIC         163 :     if (compressloc == COMPRESS_LOCATION_CLIENT)
                               2517                 :     {
  332 tgl                      2518 ECB             :         pg_compress_algorithm alg;
                               2519                 :         char       *error_detail;
  382 rhaas                    2520                 : 
  362 michael                  2521 CBC         132 :         if (!parse_compress_algorithm(compression_algorithm, &alg))
  197 peter                    2522               2 :             pg_fatal("unrecognized compression algorithm: \"%s\"",
                               2523                 :                      compression_algorithm);
  382 rhaas                    2524 ECB             : 
  362 michael                  2525 GIC         130 :         parse_compress_specification(alg, compression_detail, &client_compress);
  362 michael                  2526 GBC         130 :         error_detail = validate_compress_specification(&client_compress);
  382 rhaas                    2527             130 :         if (error_detail != NULL)
  366 tgl                      2528              10 :             pg_fatal("invalid compression specification: %s",
                               2529                 :                      error_detail);
                               2530                 :     }
  382 rhaas                    2531 ECB             :     else
                               2532                 :     {
  382 rhaas                    2533 CBC          31 :         Assert(compressloc == COMPRESS_LOCATION_SERVER);
  362 michael                  2534              31 :         client_compress.algorithm = PG_COMPRESSION_NONE;
  382 rhaas                    2535              31 :         client_compress.options = 0;
                               2536                 :     }
                               2537                 : 
                               2538                 :     /*
                               2539                 :      * Can't perform client-side compression if the backup is not being sent
                               2540                 :      * to the client.
  440 rhaas                    2541 ECB             :      */
  440 rhaas                    2542 GIC         151 :     if (backup_target != NULL && compressloc == COMPRESS_LOCATION_CLIENT)
  440 rhaas                    2543 ECB             :     {
  440 rhaas                    2544 UIC           0 :         pg_log_error("client-side compression is not possible when a backup target is specified");
  366 tgl                      2545 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
  440 rhaas                    2546               0 :         exit(1);
  440 rhaas                    2547 ECB             :     }
                               2548                 : 
                               2549                 :     /*
                               2550                 :      * Client-side compression doesn't make sense unless tar format is in use.
                               2551                 :      */
  382 rhaas                    2552 CBC         151 :     if (format == 'p' && compressloc == COMPRESS_LOCATION_CLIENT &&
  362 michael                  2553 GIC         106 :         client_compress.algorithm != PG_COMPRESSION_NONE)
  440 rhaas                    2554 ECB             :     {
  440 rhaas                    2555 UIC           0 :         pg_log_error("only tar mode backups can be compressed");
  366 tgl                      2556 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 4459 magnus                   2557 UIC           0 :         exit(1);
 4459 magnus                   2558 ECB             :     }
                               2559                 : 
                               2560                 :     /*
                               2561                 :      * Sanity checks for WAL method.
  509 rhaas                    2562                 :      */
  509 rhaas                    2563 GIC         151 :     if (backup_target != NULL && includewal == STREAM_WAL)
  509 rhaas                    2564 EUB             :     {
  509 rhaas                    2565 GIC           2 :         pg_log_error("WAL cannot be streamed when a backup target is specified");
  366 tgl                      2566 GBC           2 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
  509 rhaas                    2567               2 :         exit(1);
                               2568                 :     }
 2281 magnus                   2569 GIC         149 :     if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
                               2570                 :     {
 1469 peter                    2571 UIC           0 :         pg_log_error("cannot stream write-ahead logs in tar mode to stdout");
  366 tgl                      2572               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 2300 fujii                    2573               0 :         exit(1);
 2300 fujii                    2574 ECB             :     }
                               2575                 : 
 2274 magnus                   2576 CBC         149 :     if (replication_slot && includewal != STREAM_WAL)
                               2577                 :     {
 1469 peter                    2578 GBC           1 :         pg_log_error("replication slots can only be used with WAL streaming");
  366 tgl                      2579               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 2819 peter_e                  2580               1 :         exit(1);
                               2581                 :     }
 2819 peter_e                  2582 ECB             : 
                               2583                 :     /*
  509 rhaas                    2584 EUB             :      * Sanity checks for replication slot options.
                               2585                 :      */
 2274 magnus                   2586 GBC         148 :     if (no_slot)
                               2587                 :     {
 2274 magnus                   2588 GIC           3 :         if (replication_slot)
                               2589                 :         {
 1469 peter                    2590 CBC           2 :             pg_log_error("--no-slot cannot be used with slot name");
  366 tgl                      2591               2 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 2274 magnus                   2592 GIC           2 :             exit(1);
 2274 magnus                   2593 EUB             :         }
 2274 magnus                   2594 GBC           1 :         temp_replication_slot = false;
 2274 magnus                   2595 EUB             :     }
                               2596                 : 
 2021 peter_e                  2597 GIC         146 :     if (create_slot)
                               2598                 :     {
                               2599               4 :         if (!replication_slot)
                               2600                 :         {
 1469 peter                    2601               2 :             pg_log_error("%s needs a slot to be specified using --slot",
 1469 peter                    2602 ECB             :                          "--create-slot");
  366 tgl                      2603 GIC           2 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 2021 peter_e                  2604 GBC           2 :             exit(1);
                               2605                 :         }
 2021 peter_e                  2606 EUB             : 
 2021 peter_e                  2607 GBC           2 :         if (no_slot)
                               2608                 :         {
 1028 peter                    2609 UIC           0 :             pg_log_error("%s and %s are incompatible options",
                               2610                 :                          "--create-slot", "--no-slot");
  366 tgl                      2611               0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 2021 peter_e                  2612               0 :             exit(1);
 2021 peter_e                  2613 ECB             :         }
                               2614                 :     }
 2021 peter_e                  2615 EUB             : 
                               2616                 :     /*
  509 rhaas                    2617                 :      * Sanity checks on WAL directory.
                               2618                 :      */
 2048 peter_e                  2619 GIC         144 :     if (xlog_dir)
                               2620                 :     {
  509 rhaas                    2621 CBC           1 :         if (backup_target != NULL)
                               2622                 :         {
  509 rhaas                    2623 UBC           0 :             pg_log_error("WAL directory location cannot be specified along with a backup target");
  366 tgl                      2624 UIC           0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
  509 rhaas                    2625 UBC           0 :             exit(1);
  509 rhaas                    2626 EUB             :         }
 3420 fujii                    2627 GIC           1 :         if (format != 'p')
                               2628                 :         {
 1469 peter                    2629 UIC           0 :             pg_log_error("WAL directory location can only be specified in plain mode");
  366 tgl                      2630 LBC           0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 3420 fujii                    2631               0 :             exit(1);
                               2632                 :         }
                               2633                 : 
 3420 fujii                    2634 ECB             :         /* clean up xlog directory name, check it's absolute */
 3420 fujii                    2635 GIC           1 :         canonicalize_path(xlog_dir);
 3420 fujii                    2636 CBC           1 :         if (!is_absolute_path(xlog_dir))
                               2637                 :         {
 1469 peter                    2638 UIC           0 :             pg_log_error("WAL directory location must be an absolute path");
  366 tgl                      2639               0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 3420 fujii                    2640               0 :             exit(1);
                               2641                 :         }
                               2642                 :     }
                               2643                 : 
                               2644                 :     /*
                               2645                 :      * Sanity checks for progress reporting options.
                               2646                 :      */
 1116 fujii                    2647 GIC         144 :     if (showprogress && !estimatesize)
 1116 fujii                    2648 ECB             :     {
 1028 peter                    2649 UIC           0 :         pg_log_error("%s and %s are incompatible options",
                               2650                 :                      "--progress", "--no-estimate-size");
  366 tgl                      2651               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 1116 fujii                    2652               0 :         exit(1);
                               2653                 :     }
                               2654                 : 
                               2655                 :     /*
                               2656                 :      * Sanity checks for backup manifest options.
                               2657                 :      */
 1101 rhaas                    2658 GIC         144 :     if (!manifest && manifest_checksums != NULL)
 1101 rhaas                    2659 ECB             :     {
 1028 peter                    2660 UIC           0 :         pg_log_error("%s and %s are incompatible options",
                               2661                 :                      "--no-manifest", "--manifest-checksums");
  366 tgl                      2662 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 1101 rhaas                    2663 UBC           0 :         exit(1);
                               2664                 :     }
                               2665                 : 
 1101 rhaas                    2666 GIC         144 :     if (!manifest && manifest_force_encode)
                               2667                 :     {
 1028 peter                    2668 UIC           0 :         pg_log_error("%s and %s are incompatible options",
                               2669                 :                      "--no-manifest", "--manifest-force-encode");
  366 tgl                      2670 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 1101 rhaas                    2671               0 :         exit(1);
                               2672                 :     }
                               2673                 : 
 2362 rhaas                    2674 ECB             :     /* connection in replication mode to server */
 2362 rhaas                    2675 GBC         144 :     conn = GetConnection();
 2362 rhaas                    2676 GIC         144 :     if (!conn)
                               2677                 :     {
 2362 rhaas                    2678 ECB             :         /* Error message already written in GetConnection() */
 2362 rhaas                    2679 GIC           2 :         exit(1);
                               2680                 :     }
 1562 peter                    2681             142 :     atexit(disconnect_atexit);
 2362 rhaas                    2682 ECB             : 
                               2683                 : #ifndef WIN32
                               2684                 : 
                               2685                 :     /*
                               2686                 :      * Trap SIGCHLD to be able to handle the WAL stream process exiting. There
                               2687                 :      * is no SIGCHLD on Windows, there we rely on the background thread
  332 tgl                      2688                 :      * setting the signal variable on unexpected but graceful exit. If the WAL
                               2689                 :      * stream thread crashes on Windows it will bring down the entire process
                               2690                 :      * as it's a thread, so there is nothing to catch should that happen. A
                               2691                 :      * crash on UNIX will be caught by the signal handler.
  410 dgustafsson              2692                 :      */
  410 dgustafsson              2693 GBC         142 :     pqsignal(SIGCHLD, sigchld_handler);
  410 dgustafsson              2694 ECB             : #endif
                               2695                 : 
                               2696                 :     /*
 1828 sfrost                   2697                 :      * Set umask so that directories/files are created with the same
                               2698                 :      * permissions as directories/files in the source data directory.
                               2699                 :      *
                               2700                 :      * pg_mode_mask is set to owner-only by default and then updated in
                               2701                 :      * GetConnection() where we get the mode from the server-side with
                               2702                 :      * RetrieveDataDirCreatePerm() and then call SetDataDirectoryCreatePerm().
                               2703                 :      */
 1828 sfrost                   2704 GIC         142 :     umask(pg_mode_mask);
                               2705                 : 
                               2706                 :     /* Backup manifests are supported in 13 and newer versions */
 1088 michael                  2707             142 :     if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_MANIFESTS)
 1088 michael                  2708 UIC           0 :         manifest = false;
                               2709                 : 
                               2710                 :     /*
                               2711                 :      * If an output directory was specified, verify that it exists, or create
                               2712                 :      * it. Note that for a tar backup, an output directory of "-" means we are
                               2713                 :      * writing to stdout, so do nothing in that case.
                               2714                 :      */
  509 rhaas                    2715 GIC         142 :     if (basedir != NULL && (format == 'p' || strcmp(basedir, "-") != 0))
 1828 sfrost                   2716             127 :         verify_dir_is_empty_or_create(basedir, &made_new_pgdata, &found_existing_pgdata);
                               2717                 : 
                               2718                 :     /* determine remote server's xlog segment size */
 2028 andres                   2719             142 :     if (!RetrieveWalSegSize(conn))
 1562 peter                    2720 UIC           0 :         exit(1);
                               2721                 : 
                               2722                 :     /* Create pg_wal symlink, if required */
 2048 peter_e                  2723 GIC         142 :     if (xlog_dir)
                               2724                 :     {
                               2725                 :         char       *linkloc;
                               2726                 : 
 2400                          2727               1 :         verify_dir_is_empty_or_create(xlog_dir, &made_new_xlogdir, &found_existing_xlogdir);
                               2728                 : 
                               2729                 :         /*
                               2730                 :          * Form name of the place where the symlink must go. pg_xlog has been
                               2731                 :          * renamed to pg_wal in post-10 clusters.
                               2732                 :          */
 2362 rhaas                    2733               1 :         linkloc = psprintf("%s/%s", basedir,
 2118 tgl                      2734               1 :                            PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
                               2735                 :                            "pg_xlog" : "pg_wal");
                               2736                 : 
 3420 fujii                    2737               1 :         if (symlink(xlog_dir, linkloc) != 0)
  366 tgl                      2738 UIC           0 :             pg_fatal("could not create symbolic link \"%s\": %m", linkloc);
 3420 fujii                    2739 GIC           1 :         free(linkloc);
                               2740                 :     }
                               2741                 : 
  382 rhaas                    2742             142 :     BaseBackup(compression_algorithm, compression_detail, compressloc,
                               2743                 :                &client_compress);
                               2744                 : 
 2400 peter_e                  2745             117 :     success = true;
 4459 magnus                   2746             117 :     return 0;
                               2747                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a