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 15:15:32 Functions: 78.1 % 32 25 7 24 1 7 24 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           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                 : 
     227 ECB             : 
     228                 : static void
     229 CBC         268 : cleanup_directories_atexit(void)
     230 ECB             : {
     231 GIC         268 :     if (success || in_log_streamer)
     232 CBC         211 :         return;
     233                 : 
     234              57 :     if (!noclean && !checksum_failure)
     235                 :     {
     236              53 :         if (made_new_pgdata)
     237 ECB             :         {
     238 GBC          17 :             pg_log_info("removing data directory \"%s\"", basedir);
     239 GIC          17 :             if (!rmtree(basedir, true))
     240 LBC           0 :                 pg_log_error("failed to remove data directory");
     241                 :         }
     242 GBC          36 :         else if (found_existing_pgdata)
     243 EUB             :         {
     244 UBC           0 :             pg_log_info("removing contents of data directory \"%s\"", basedir);
     245 UIC           0 :             if (!rmtree(basedir, false))
     246               0 :                 pg_log_error("failed to remove contents of data directory");
     247 ECB             :         }
     248                 : 
     249 GBC          53 :         if (made_new_xlogdir)
     250 EUB             :         {
     251 UBC           0 :             pg_log_info("removing WAL directory \"%s\"", xlog_dir);
     252 UIC           0 :             if (!rmtree(xlog_dir, true))
     253 LBC           0 :                 pg_log_error("failed to remove WAL directory");
     254                 :         }
     255 GBC          53 :         else if (found_existing_xlogdir)
     256 EUB             :         {
     257 UBC           0 :             pg_log_info("removing contents of WAL directory \"%s\"", xlog_dir);
     258 UIC           0 :             if (!rmtree(xlog_dir, false))
     259               0 :                 pg_log_error("failed to remove contents of WAL directory");
     260                 :         }
     261                 :     }
     262 ECB             :     else
     263 EUB             :     {
     264 GIC           4 :         if ((made_new_pgdata || found_existing_pgdata) && !checksum_failure)
     265 LBC           0 :             pg_log_info("data directory \"%s\" not removed at user's request", basedir);
     266 EUB             : 
     267 GIC           4 :         if (made_new_xlogdir || found_existing_xlogdir)
     268 UIC           0 :             pg_log_info("WAL directory \"%s\" not removed at user's request", xlog_dir);
     269 ECB             :     }
     270 EUB             : 
     271 GIC          57 :     if ((made_tablespace_dirs || found_tablespace_dirs) && !checksum_failure)
     272 UIC           0 :         pg_log_info("changes to tablespace directories will not be undone");
     273                 : }
     274 ECB             : 
     275                 : static void
     276 CBC         236 : disconnect_atexit(void)
     277 ECB             : {
     278 CBC         236 :     if (conn != NULL)
     279 GIC         119 :         PQfinish(conn);
     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.
     288 ECB             :  */
     289                 : static void
     290 CBC          96 : sigchld_handler(SIGNAL_ARGS)
     291 ECB             : {
     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.
     299 ECB             :  */
     300                 : static void
     301 CBC          98 : kill_bgchild_atexit(void)
     302 ECB             : {
     303 CBC          98 :     if (bgchild > 0 && !bgchild_exited)
     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.
     311 ECB             :  */
     312                 : static void
     313 CBC          19 : tablespace_list_append(const char *arg)
     314                 : {
     315 GIC          19 :     TablespaceListCell *cell = (TablespaceListCell *) pg_malloc0(sizeof(TablespaceListCell));
     316                 :     char       *dst;
     317                 :     char       *dst_ptr;
     318 ECB             :     const char *arg_ptr;
     319                 : 
     320 GIC          19 :     dst_ptr = dst = cell->old_dir;
     321 CBC         634 :     for (arg_ptr = arg; *arg_ptr; arg_ptr++)
     322 EUB             :     {
     323 GIC         616 :         if (dst_ptr - dst >= MAXPGPATH)
     324 LBC           0 :             pg_fatal("directory name too long");
     325                 : 
     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) != '\\'))
     329 ECB             :         {
     330 GIC          19 :             if (*cell->new_dir)
     331 CBC           1 :                 pg_fatal("multiple \"=\" signs in tablespace mapping");
     332                 :             else
     333 GIC          18 :                 dst = dst_ptr = cell->new_dir;
     334 ECB             :         }
     335                 :         else
     336 GIC         595 :             *dst_ptr++ = *arg_ptr;
     337 ECB             :     }
     338                 : 
     339 GIC          18 :     if (!*cell->old_dir || !*cell->new_dir)
     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
     355 ECB             :      * as if they'd specified -T for a nonexistent tablespace.)
     356                 :      */
     357 CBC          15 :     if (!is_nonwindows_absolute_path(cell->old_dir) &&
     358 GIC           1 :         !is_windows_absolute_path(cell->old_dir))
     359               1 :         pg_fatal("old directory is not an absolute path in tablespace mapping: %s",
     360 ECB             :                  cell->old_dir);
     361                 : 
     362 GIC          14 :     if (!is_absolute_path(cell->new_dir))
     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
     369 ECB             :      * where path values may not necessarily use Unix slashes.
     370                 :      */
     371 GIC          13 :     canonicalize_path(cell->old_dir);
     372 CBC          13 :     canonicalize_path(cell->new_dir);
     373 EUB             : 
     374 GIC          13 :     if (tablespace_dirs.tail)
     375 LBC           0 :         tablespace_dirs.tail->next = cell;
     376 ECB             :     else
     377 CBC          13 :         tablespace_dirs.head = cell;
     378 GIC          13 :     tablespace_dirs.tail = cell;
     379              13 : }
     380                 : 
     381 ECB             : 
     382                 : static void
     383 CBC           1 : usage(void)
     384                 : {
     385               1 :     printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
     386 ECB             :            progname);
     387 CBC           1 :     printf(_("Usage:\n"));
     388               1 :     printf(_("  %s [OPTION]...\n"), progname);
     389               1 :     printf(_("\nOptions controlling the output:\n"));
     390               1 :     printf(_("  -D, --pgdata=DIRECTORY receive base backup into directory\n"));
     391 GIC           1 :     printf(_("  -F, --format=p|t       output format (plain (default), tar)\n"));
     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"));
     396               1 :     printf(_("  -t, --target=TARGET[:DETAIL]\n"
     397                 :              "                         backup target (if other than client)\n"));
     398               1 :     printf(_("  -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
     399 ECB             :              "                         relocate tablespace in OLDDIR to NEWDIR\n"));
     400 GIC           1 :     printf(_("      --waldir=WALDIR    location for the write-ahead log directory\n"));
     401 CBC           1 :     printf(_("  -X, --wal-method=none|fetch|stream\n"
     402 ECB             :              "                         include required WAL files with specified method\n"));
     403 GIC           1 :     printf(_("  -z, --gzip             compress tar output\n"));
     404 CBC           1 :     printf(_("  -Z, --compress=[{client|server}-]METHOD[:DETAIL]\n"
     405 ECB             :              "                         compress on client or server as specified\n"));
     406 CBC           1 :     printf(_("  -Z, --compress=none    do not compress tar output\n"));
     407 GIC           1 :     printf(_("\nGeneral options:\n"));
     408 CBC           1 :     printf(_("  -c, --checkpoint=fast|spread\n"
     409 ECB             :              "                         set fast or spread checkpointing\n"));
     410 CBC           1 :     printf(_("  -C, --create-slot      create replication slot\n"));
     411               1 :     printf(_("  -l, --label=LABEL      set backup label\n"));
     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"));
     414               1 :     printf(_("  -P, --progress         show progress information\n"));
     415               1 :     printf(_("  -S, --slot=SLOTNAME    replication slot to use\n"));
     416               1 :     printf(_("  -v, --verbose          output verbose messages\n"));
     417 GIC           1 :     printf(_("  -V, --version          output version information, then exit\n"));
     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"
     421 ECB             :              "                         hex encode all file names in manifest\n"));
     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"));
     424 GIC           1 :     printf(_("      --no-slot          prevent creation of temporary replication slot\n"));
     425 CBC           1 :     printf(_("      --no-verify-checksums\n"
     426 ECB             :              "                         do not verify checksums\n"));
     427 CBC           1 :     printf(_("  -?, --help             show this help, then exit\n"));
     428               1 :     printf(_("\nConnection options:\n"));
     429               1 :     printf(_("  -d, --dbname=CONNSTR   connection string\n"));
     430               1 :     printf(_("  -h, --host=HOSTNAME    database server host or socket directory\n"));
     431 GIC           1 :     printf(_("  -p, --port=PORT        database server port number\n"));
     432 CBC           1 :     printf(_("  -s, --status-interval=INTERVAL\n"
     433 ECB             :              "                         time between status packets sent to server (in seconds)\n"));
     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"));
     437               1 :     printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
     438 GIC           1 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
     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.
     449 ECB             :  */
     450                 : static bool
     451 GIC       10313 : reached_end_position(XLogRecPtr segendpos, uint32 timeline,
     452 ECB             :                      bool segment_finished)
     453                 : {
     454 GIC       10313 :     if (!has_xlogendptr)
     455                 :     {
     456 ECB             : #ifndef WIN32
     457                 :         fd_set      fds;
     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
     463 ECB             :          * been sent yet.
     464                 :          */
     465 GIC      173757 :         FD_ZERO(&fds);
     466 CBC       10221 :         FD_SET(bgpipe[0], &fds);
     467 ECB             : 
     468 GIC       10221 :         r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
     469           10221 :         if (r == 1)
     470                 :         {
     471 GNC          91 :             char        xlogend[64] = {0};
     472 ECB             :             uint32      hi,
     473 EUB             :                         lo;
     474                 : 
     475 GBC          91 :             r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
     476 GIC          91 :             if (r < 0)
     477 LBC           0 :                 pg_fatal("could not read from ready pipe: %m");
     478 ECB             : 
     479 GIC          91 :             if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
     480 UIC           0 :                 pg_fatal("could not parse write-ahead log location \"%s\"",
     481                 :                          xlogend);
     482 GIC          91 :             xlogendptr = ((uint64) hi) << 32 | lo;
     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
     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                 :              */
     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                 :     }
     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                 :      */
     512 GIC         183 :     if (segendpos >= xlogendptr)
     513             182 :         return true;
     514 ECB             : 
     515                 :     /*
     516                 :      * Have end pointer, but haven't reached it yet - so tell the caller to
     517                 :      * keep streaming.
     518                 :      */
     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;
     529 ECB             :     pg_compress_algorithm wal_compress_algorithm;
     530                 :     int         wal_compress_level;
     531                 : } logstreamer_param;
     532                 : 
     533                 : static int
     534 GIC          94 : LogStreamerMain(logstreamer_param *param)
     535 ECB             : {
     536 GNC          94 :     StreamCtl   stream = {0};
     537 ECB             : 
     538 CBC          94 :     in_log_streamer = true;
     539                 : 
     540 GIC          94 :     stream.startpos = param->startptr;
     541              94 :     stream.timeline = param->timeline;
     542              94 :     stream.sysidentifier = param->sysidentifier;
     543 CBC          94 :     stream.stream_stop = reached_end_position;
     544 ECB             : #ifndef WIN32
     545 GIC          94 :     stream.stop_socket = bgpipe[0];
     546 ECB             : #else
     547                 :     stream.stop_socket = PGINVALID_SOCKET;
     548                 : #endif
     549 CBC          94 :     stream.standby_message_timeout = standby_message_timeout;
     550              94 :     stream.synchronous = false;
     551 ECB             :     /* fsync happens at the end of pg_basebackup for all data */
     552 GIC          94 :     stream.do_sync = false;
     553 CBC          94 :     stream.mark_done = true;
     554 GIC          94 :     stream.partial_suffix = NULL;
     555 CBC          94 :     stream.replication_slot = replication_slot;
     556 GIC          94 :     if (format == 'p')
     557              87 :         stream.walmethod = CreateWalDirectoryMethod(param->xlog,
     558 ECB             :                                                     PG_COMPRESSION_NONE, 0,
     559 GIC          87 :                                                     stream.do_sync);
     560 ECB             :     else
     561 GIC           7 :         stream.walmethod = CreateWalTarMethod(param->xlog,
     562                 :                                               param->wal_compress_algorithm,
     563                 :                                               param->wal_compress_level,
     564               7 :                                               stream.do_sync);
     565                 : 
     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
     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;
     579 EUB             : #endif
     580 GIC           3 :         return 1;
     581                 :     }
     582                 : 
     583 GNC          91 :     if (!stream.walmethod->ops->finish(stream.walmethod))
     584                 :     {
     585 UIC           0 :         pg_log_error("could not finish writing WAL files: %m");
     586 ECB             : #ifdef WIN32
     587                 :         bgchild_exited = true;
     588                 : #endif
     589 UIC           0 :         return 1;
     590 ECB             :     }
     591                 : 
     592 GIC          91 :     PQfinish(param->bgconn);
     593                 : 
     594 GNC          91 :     stream.walmethod->ops->free(stream.walmethod);
     595 ECB             : 
     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                 :  */
     604 ECB             : static void
     605 CBC          99 : StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier,
     606 ECB             :                  pg_compress_algorithm wal_compress_algorithm,
     607                 :                  int wal_compress_level)
     608                 : {
     609                 :     logstreamer_param *param;
     610                 :     uint32      hi,
     611                 :                 lo;
     612 EUB             :     char        statusdir[MAXPGPATH];
     613                 : 
     614 CBC          99 :     param = pg_malloc0(sizeof(logstreamer_param));
     615 GIC          99 :     param->timeline = timeline;
     616 CBC          99 :     param->sysidentifier = sysidentifier;
     617 GIC          99 :     param->wal_compress_algorithm = wal_compress_algorithm;
     618              99 :     param->wal_compress_level = wal_compress_level;
     619                 : 
     620 ECB             :     /* Convert the starting position */
     621 GBC          99 :     if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
     622 UIC           0 :         pg_fatal("could not parse write-ahead log location \"%s\"",
     623                 :                  startpos);
     624 GIC          99 :     param->startptr = ((uint64) hi) << 32 | lo;
     625 ECB             :     /* Round off to even segment position */
     626 CBC          99 :     param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
     627                 : 
     628 EUB             : #ifndef WIN32
     629                 :     /* Create our background pipe */
     630 GIC          99 :     if (pipe(bgpipe) < 0)
     631 LBC           0 :         pg_fatal("could not create pipe for background process: %m");
     632                 : #endif
     633 ECB             : 
     634                 :     /* Get a second connection */
     635 GIC          99 :     param->bgconn = GetConnection();
     636              99 :     if (!param->bgconn)
     637 ECB             :         /* Error message already written in GetConnection() */
     638 UBC           0 :         exit(1);
     639                 : 
     640                 :     /* In post-10 cluster, pg_xlog has been renamed to pg_wal */
     641 GIC          99 :     snprintf(param->xlog, sizeof(param->xlog), "%s/%s",
     642                 :              basedir,
     643 CBC          99 :              PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
     644 ECB             :              "pg_xlog" : "pg_wal");
     645                 : 
     646                 :     /* Temporary replication slots are only supported in 10 and newer */
     647 CBC          99 :     if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_TEMP_SLOTS)
     648 UIC           0 :         temp_replication_slot = false;
     649 ECB             : 
     650                 :     /*
     651                 :      * Create replication slot if requested
     652                 :      */
     653 GBC          99 :     if (temp_replication_slot && !replication_slot)
     654              92 :         replication_slot = psprintf("pg_basebackup_%d", (int) PQbackendPID(param->bgconn));
     655 GIC          99 :     if (temp_replication_slot || create_slot)
     656                 :     {
     657 GBC          94 :         if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
     658                 :                                    temp_replication_slot, true, true, false, false))
     659 GIC           1 :             exit(1);
     660                 : 
     661              93 :         if (verbose)
     662 ECB             :         {
     663 UIC           0 :             if (temp_replication_slot)
     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                 :         }
     670 ECB             :     }
     671                 : 
     672 CBC          98 :     if (format == 'p')
     673                 :     {
     674                 :         /*
     675 ECB             :          * Create pg_wal/archive_status or pg_xlog/archive_status (and thus
     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                 :          */
     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");
     684 ECB             : 
     685 CBC          90 :         if (pg_mkdir_p(statusdir, pg_dir_create_mode) != 0 && errno != EEXIST)
     686 UIC           0 :             pg_fatal("could not create directory \"%s\": %m", statusdir);
     687                 :     }
     688 ECB             : 
     689                 :     /*
     690                 :      * Start a child process and tell it to start streaming. On Unix, this is
     691 EUB             :      * a fork(). On Windows, we create a thread.
     692                 :      */
     693                 : #ifndef WIN32
     694 GIC          98 :     bgchild = fork();
     695             192 :     if (bgchild == 0)
     696 ECB             :     {
     697                 :         /* in child process */
     698 GIC          94 :         exit(LogStreamerMain(param));
     699                 :     }
     700              98 :     else if (bgchild < 0)
     701 UIC           0 :         pg_fatal("could not create background process: %m");
     702 ECB             : 
     703                 :     /*
     704                 :      * Else we are in the parent process and all is well.
     705                 :      */
     706 GIC          98 :     atexit(kill_bgchild_atexit);
     707                 : #else                           /* WIN32 */
     708                 :     bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
     709                 :     if (bgchild == 0)
     710 ECB             :         pg_fatal("could not create background thread: %m");
     711                 : #endif
     712 CBC          98 : }
     713                 : 
     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
     720 GBC         142 : verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
     721 ECB             : {
     722 CBC         142 :     switch (pg_check_dir(dirname))
     723 ECB             :     {
     724 CBC         130 :         case 0:
     725                 : 
     726                 :             /*
     727                 :              * Does not exist, so create
     728                 :              */
     729             130 :             if (pg_mkdir_p(dirname, pg_dir_create_mode) == -1)
     730 LBC           0 :                 pg_fatal("could not create directory \"%s\": %m", dirname);
     731 CBC         130 :             if (created)
     732             130 :                 *created = true;
     733 GIC         130 :             return;
     734              11 :         case 1:
     735                 : 
     736                 :             /*
     737                 :              * Exists, empty
     738                 :              */
     739 CBC          11 :             if (found)
     740 GBC          11 :                 *found = true;
     741 GIC          11 :             return;
     742               1 :         case 2:
     743                 :         case 3:
     744                 :         case 4:
     745 EUB             : 
     746                 :             /*
     747                 :              * Exists, not empty
     748                 :              */
     749 GIC           1 :             pg_fatal("directory \"%s\" exists but is not empty", dirname);
     750 UIC           0 :         case -1:
     751                 : 
     752                 :             /*
     753                 :              * Access problem
     754                 :              */
     755 LBC           0 :             pg_fatal("could not access directory \"%s\": %m", dirname);
     756                 :     }
     757                 : }
     758 ECB             : 
     759                 : /*
     760 EUB             :  * Callback to update our notion of the current filename.
     761                 :  *
     762                 :  * No other code should modify progress_filename!
     763                 :  */
     764                 : static void
     765 GIC       98801 : progress_update_filename(const char *filename)
     766 ECB             : {
     767                 :     /* We needn't maintain this variable if not doing verbose reports. */
     768 GIC       98801 :     if (showprogress && verbose)
     769                 :     {
     770 UNC           0 :         free(progress_filename);
     771 UIC           0 :         if (filename)
     772               0 :             progress_filename = pg_strdup(filename);
     773                 :         else
     774               0 :             progress_filename = NULL;
     775                 :     }
     776 GIC       98801 : }
     777                 : 
     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                 :  *
     785                 :  * If finished is set to true, this is the last progress report. The cursor
     786                 :  * is moved to the next line.
     787                 :  */
     788 EUB             : static void
     789 GBC         172 : progress_report(int tablespacenum, bool force, bool finished)
     790 EUB             : {
     791                 :     int         percent;
     792                 :     char        totaldone_str[32];
     793                 :     char        totalsize_str[32];
     794                 :     pg_time_t   now;
     795                 : 
     796 GIC         172 :     if (!showprogress)
     797             172 :         return;
     798                 : 
     799 UIC           0 :     now = time(NULL);
     800               0 :     if (now == last_progress_report && !force && !finished)
     801 UBC           0 :         return;                 /* Max once per second */
     802 EUB             : 
     803 UBC           0 :     last_progress_report = now;
     804               0 :     percent = totalsize_kb ? (int) ((totaldone / 1024) * 100 / totalsize_kb) : 0;
     805                 : 
     806 EUB             :     /*
     807                 :      * Avoid overflowing past 100% or the full size. This may make the total
     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.
     811                 :      */
     812 UIC           0 :     if (percent > 100)
     813 UBC           0 :         percent = 100;
     814 UIC           0 :     if (totaldone / 1024 > totalsize_kb)
     815               0 :         totalsize_kb = totaldone / 1024;
     816                 : 
     817               0 :     snprintf(totaldone_str, sizeof(totaldone_str), UINT64_FORMAT,
     818                 :              totaldone / 1024);
     819 UBC           0 :     snprintf(totalsize_str, sizeof(totalsize_str), UINT64_FORMAT, totalsize_kb);
     820 EUB             : 
     821                 : #define VERBOSE_FILENAME_LENGTH 35
     822 UIC           0 :     if (verbose)
     823 EUB             :     {
     824 UIC           0 :         if (!progress_filename)
     825                 : 
     826                 :             /*
     827                 :              * No filename given, so clear the status line (used for last
     828                 :              * call)
     829 EUB             :              */
     830 UIC           0 :             fprintf(stderr,
     831 UBC           0 :                     ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
     832 EUB             :                              "%*s/%s kB (100%%), %d/%d tablespaces %*s",
     833                 :                              tablespacecount),
     834 UIC           0 :                     (int) strlen(totalsize_str),
     835 EUB             :                     totaldone_str, totalsize_str,
     836                 :                     tablespacenum, tablespacecount,
     837                 :                     VERBOSE_FILENAME_LENGTH + 5, "");
     838                 :         else
     839                 :         {
     840 UIC           0 :             bool        truncate = (strlen(progress_filename) > VERBOSE_FILENAME_LENGTH);
     841                 : 
     842               0 :             fprintf(stderr,
     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),
     846 UIC           0 :                     (int) strlen(totalsize_str),
     847 EUB             :                     totaldone_str, totalsize_str, percent,
     848                 :                     tablespacenum, tablespacecount,
     849                 :             /* Prefix with "..." if we do leading truncation */
     850                 :                     truncate ? "..." : "",
     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 */
     854 UIC           0 :                     truncate ? progress_filename + strlen(progress_filename) - VERBOSE_FILENAME_LENGTH + 3 : progress_filename);
     855                 :         }
     856                 :     }
     857                 :     else
     858               0 :         fprintf(stderr,
     859 UBC           0 :                 ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
     860                 :                          "%*s/%s kB (%d%%), %d/%d tablespaces",
     861                 :                          tablespacecount),
     862 UIC           0 :                 (int) strlen(totalsize_str),
     863 ECB             :                 totaldone_str, totalsize_str, percent,
     864                 :                 tablespacenum, tablespacecount);
     865                 : 
     866                 :     /*
     867                 :      * Stay on the same line if reporting to a terminal and we're not done
     868                 :      * yet.
     869                 :      */
     870 LBC           0 :     fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
     871 ECB             : }
     872 EUB             : 
     873 ECB             : static int32
     874 GBC           1 : parse_max_rate(char *src)
     875                 : {
     876 ECB             :     double      result;
     877                 :     char       *after_num;
     878 GIC           1 :     char       *suffix = NULL;
     879                 : 
     880               1 :     errno = 0;
     881 GBC           1 :     result = strtod(src, &after_num);
     882 GIC           1 :     if (src == after_num)
     883 UIC           0 :         pg_fatal("transfer rate \"%s\" is not a valid value", src);
     884 GIC           1 :     if (errno != 0)
     885 UIC           0 :         pg_fatal("invalid transfer rate \"%s\": %m", src);
     886                 : 
     887 GIC           1 :     if (result <= 0)
     888 ECB             :     {
     889 EUB             :         /*
     890                 :          * Reject obviously wrong values here.
     891 ECB             :          */
     892 UIC           0 :         pg_fatal("transfer rate must be greater than zero");
     893 EUB             :     }
     894                 : 
     895                 :     /*
     896                 :      * Evaluate suffix, after skipping over possible whitespace. Lack of
     897                 :      * suffix means kilobytes.
     898                 :      */
     899 GBC           1 :     while (*after_num != '\0' && isspace((unsigned char) *after_num))
     900 UIC           0 :         after_num++;
     901 EUB             : 
     902 GBC           1 :     if (*after_num != '\0')
     903                 :     {
     904 UIC           0 :         suffix = after_num;
     905               0 :         if (*after_num == 'k')
     906                 :         {
     907 ECB             :             /* kilobyte is the expected unit. */
     908 UBC           0 :             after_num++;
     909                 :         }
     910 LBC           0 :         else if (*after_num == 'M')
     911 EUB             :         {
     912 UIC           0 :             after_num++;
     913               0 :             result *= 1024.0;
     914 ECB             :         }
     915 EUB             :     }
     916                 : 
     917                 :     /* The rest can only consist of white space. */
     918 GIC           1 :     while (*after_num != '\0' && isspace((unsigned char) *after_num))
     919 UIC           0 :         after_num++;
     920                 : 
     921 CBC           1 :     if (*after_num != '\0')
     922 UBC           0 :         pg_fatal("invalid --max-rate unit: \"%s\"", suffix);
     923                 : 
     924 ECB             :     /* Valid integer? */
     925 GIC           1 :     if ((uint64) result != (uint64) ((uint32) result))
     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                 :      */
     932 GIC           1 :     if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
     933 UIC           0 :         pg_fatal("transfer rate \"%s\" is out of range", src);
     934                 : 
     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",
     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.
     957                 :  */
     958                 : static void
     959 GNC          37 : backup_parse_compress_options(char *option, char **algorithm, char **detail,
     960                 :                               CompressionLocation *locationres)
     961 ECB             : {
     962                 :     /*
     963                 :      * Strip off any "client-" or "server-" prefix, calculating the location.
     964                 :      */
     965 GIC          37 :     if (strncmp(option, "server-", 7) == 0)
     966                 :     {
     967 CBC          18 :         *locationres = COMPRESS_LOCATION_SERVER;
     968              18 :         option += 7;
     969 EUB             :     }
     970 GIC          19 :     else if (strncmp(option, "client-", 7) == 0)
     971 ECB             :     {
     972 GIC           5 :         *locationres = COMPRESS_LOCATION_CLIENT;
     973               5 :         option += 7;
     974                 :     }
     975 ECB             :     else
     976 GIC          14 :         *locationres = COMPRESS_LOCATION_UNSPECIFIED;
     977                 : 
     978                 :     /* fallback to the common parsing for the algorithm and detail */
     979 GNC          37 :     parse_compress_options(option, algorithm, detail);
     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
     987             124 : ReceiveCopyData(PGconn *conn, WriteDataCallback callback,
     988                 :                 void *callback_data)
     989 ECB             : {
     990                 :     PGresult   *res;
     991                 : 
     992                 :     /* Get the COPY data stream. */
     993 GIC         124 :     res = PQgetResult(conn);
     994             124 :     if (PQresultStatus(res) != PGRES_COPY_OUT)
     995 LBC           0 :         pg_fatal("could not get COPY data stream: %s",
     996 ECB             :                  PQerrorMessage(conn));
     997 GIC         124 :     PQclear(res);
     998                 : 
     999                 :     /* Loop over chunks until done. */
    1000                 :     while (1)
    1001          246055 :     {
    1002                 :         int         r;
    1003                 :         char       *copybuf;
    1004 ECB             : 
    1005 GIC      246179 :         r = PQgetCopyData(conn, &copybuf, 0);
    1006          246179 :         if (r == -1)
    1007                 :         {
    1008                 :             /* End of chunk. */
    1009             121 :             break;
    1010                 :         }
    1011 CBC      246058 :         else if (r == -2)
    1012 UIC           0 :             pg_fatal("could not read COPY data: %s",
    1013                 :                      PQerrorMessage(conn));
    1014 ECB             : 
    1015 CBC      246058 :         if (bgchild_exited)
    1016 GIC           3 :             pg_fatal("background process terminated unexpectedly");
    1017                 : 
    1018 CBC      246055 :         (*callback) (r, copybuf, callback_data);
    1019 ECB             : 
    1020 GIC      246055 :         PQfreemem(copybuf);
    1021                 :     }
    1022 CBC         121 : }
    1023 ECB             : 
    1024                 : /*
    1025                 :  * Figure out what to do with an archive received from the server based on
    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 *
    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                 : {
    1040 CBC         129 :     bbstreamer *streamer = NULL;
    1041 GIC         129 :     bbstreamer *manifest_inject_streamer = NULL;
    1042 EUB             :     bool        inject_manifest;
    1043                 :     bool        is_tar,
    1044                 :                 is_tar_gz,
    1045                 :                 is_tar_lz4,
    1046                 :                 is_tar_zstd,
    1047                 :                 is_compressed_tar;
    1048                 :     bool        must_parse_archive;
    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
    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                 :      */
    1056 GIC         129 :     inject_manifest = (format == 't' && strcmp(basedir, "-") == 0 && manifest);
    1057 ECB             : 
    1058                 :     /* Is this a tar archive? */
    1059 GBC         258 :     is_tar = (archive_name_len > 4 &&
    1060             129 :               strcmp(archive_name + archive_name_len - 4, ".tar") == 0);
    1061 EUB             : 
    1062                 :     /* Is this a .tar.gz archive? */
    1063 GBC         258 :     is_tar_gz = (archive_name_len > 7 &&
    1064             129 :                  strcmp(archive_name + archive_name_len - 7, ".tar.gz") == 0);
    1065 EUB             : 
    1066                 :     /* Is this a .tar.lz4 archive? */
    1067 GBC         148 :     is_tar_lz4 = (archive_name_len > 8 &&
    1068 GIC          19 :                   strcmp(archive_name + archive_name_len - 8, ".tar.lz4") == 0);
    1069                 : 
    1070 ECB             :     /* Is this a .tar.zst archive? */
    1071 GIC         148 :     is_tar_zstd = (archive_name_len > 8 &&
    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
    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                 :      */
    1085 GIC         129 :     if (inject_manifest && is_compressed_tar)
    1086                 :     {
    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");
    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                 :      */
    1098 CBC         143 :     must_parse_archive = (format == 'p' || inject_manifest ||
    1099 GIC          14 :                           (spclocation == NULL && writerecoveryconf));
    1100 EUB             : 
    1101                 :     /* At present, we only know how to parse tar archives. */
    1102 GIC         129 :     if (must_parse_archive && !is_tar && !is_compressed_tar)
    1103                 :     {
    1104 UIC           0 :         pg_log_error("cannot parse archive \"%s\"", archive_name);
    1105 LBC           0 :         pg_log_error_detail("Only tar archives can be parsed.");
    1106 UIC           0 :         if (format == 'p')
    1107 LBC           0 :             pg_log_error_detail("Plain format requires pg_basebackup to parse the archive.");
    1108 UIC           0 :         if (inject_manifest)
    1109               0 :             pg_log_error_detail("Using - as the output directory requires pg_basebackup to parse the archive.");
    1110 LBC           0 :         if (writerecoveryconf)
    1111               0 :             pg_log_error_detail("The -R option requires pg_basebackup to parse the archive.");
    1112 UIC           0 :         exit(1);
    1113 ECB             :     }
    1114                 : 
    1115 CBC         129 :     if (format == 'p')
    1116 ECB             :     {
    1117                 :         const char *directory;
    1118                 : 
    1119                 :         /*
    1120                 :          * In plain format, we must extract the archive. The data for the main
    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                 :          */
    1126 CBC         113 :         directory = spclocation == NULL ? basedir
    1127 GIC         113 :             : get_tablespace_mapping(spclocation);
    1128 CBC         113 :         streamer = bbstreamer_extractor_new(directory,
    1129 ECB             :                                             get_tablespace_mapping,
    1130                 :                                             progress_update_filename);
    1131                 :     }
    1132                 :     else
    1133                 :     {
    1134                 :         FILE       *archive_file;
    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                 :          */
    1143 GIC          16 :         if (strcmp(basedir, "-") == 0)
    1144 ECB             :         {
    1145 UBC           0 :             snprintf(archive_filename, sizeof(archive_filename), "-");
    1146 LBC           0 :             archive_file = stdout;
    1147                 :         }
    1148                 :         else
    1149                 :         {
    1150 GIC          16 :             snprintf(archive_filename, sizeof(archive_filename),
    1151                 :                      "%s/%s", basedir, archive_name);
    1152              16 :             archive_file = NULL;
    1153                 :         }
    1154 ECB             : 
    1155 GBC          16 :         if (compress->algorithm == PG_COMPRESSION_NONE)
    1156 GIC           8 :             streamer = bbstreamer_plain_writer_new(archive_filename,
    1157                 :                                                    archive_file);
    1158               8 :         else if (compress->algorithm == PG_COMPRESSION_GZIP)
    1159                 :         {
    1160               4 :             strlcat(archive_filename, ".gz", sizeof(archive_filename));
    1161 CBC           4 :             streamer = bbstreamer_gzip_writer_new(archive_filename,
    1162                 :                                                   archive_file, compress);
    1163 ECB             :         }
    1164 CBC           4 :         else if (compress->algorithm == PG_COMPRESSION_LZ4)
    1165                 :         {
    1166 GIC           1 :             strlcat(archive_filename, ".lz4", sizeof(archive_filename));
    1167               1 :             streamer = bbstreamer_plain_writer_new(archive_filename,
    1168                 :                                                    archive_file);
    1169               1 :             streamer = bbstreamer_lz4_compressor_new(streamer, compress);
    1170                 :         }
    1171               3 :         else if (compress->algorithm == PG_COMPRESSION_ZSTD)
    1172                 :         {
    1173               3 :             strlcat(archive_filename, ".zst", sizeof(archive_filename));
    1174               3 :             streamer = bbstreamer_plain_writer_new(archive_filename,
    1175 ECB             :                                                    archive_file);
    1176 CBC           3 :             streamer = bbstreamer_zstd_compressor_new(streamer, compress);
    1177 ECB             :         }
    1178 EUB             :         else
    1179                 :         {
    1180 UIC           0 :             Assert(false);      /* not reachable */
    1181                 :         }
    1182                 : 
    1183                 :         /*
    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                 :          */
    1189 CBC          16 :         if (must_parse_archive)
    1190 LBC           0 :             streamer = bbstreamer_tar_archiver_new(streamer);
    1191 CBC          16 :         progress_update_filename(archive_filename);
    1192                 :     }
    1193                 : 
    1194                 :     /*
    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                 :      */
    1199 GIC         129 :     if (inject_manifest)
    1200 UIC           0 :         manifest_inject_streamer = streamer;
    1201                 : 
    1202                 :     /*
    1203                 :      * If this is the main tablespace and we're supposed to write recovery
    1204 ECB             :      * information, arrange to do that.
    1205                 :      */
    1206 GIC         129 :     if (spclocation == NULL && writerecoveryconf)
    1207                 :     {
    1208               2 :         Assert(must_parse_archive);
    1209 CBC           2 :         streamer = bbstreamer_recovery_injector_new(streamer,
    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
    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.
    1219                 :      */
    1220 CBC         129 :     if (must_parse_archive)
    1221 GIC         113 :         streamer = bbstreamer_tar_parser_new(streamer);
    1222              16 :     else if (expect_unterminated_tarfile)
    1223 UIC           0 :         streamer = bbstreamer_tar_terminator_new(streamer);
    1224                 : 
    1225                 :     /*
    1226                 :      * If the user has requested a server compressed archive along with
    1227 ECB             :      * archive extraction at client then we need to decompress it.
    1228 EUB             :      */
    1229 GIC         129 :     if (format == 'p')
    1230 EUB             :     {
    1231 GIC         113 :         if (is_tar_gz)
    1232 GBC           1 :             streamer = bbstreamer_gzip_decompressor_new(streamer);
    1233             112 :         else if (is_tar_lz4)
    1234               1 :             streamer = bbstreamer_lz4_decompressor_new(streamer);
    1235             111 :         else if (is_tar_zstd)
    1236 GIC           2 :             streamer = bbstreamer_zstd_decompressor_new(streamer);
    1237                 :     }
    1238                 : 
    1239 ECB             :     /* Return the results. */
    1240 GIC         129 :     *manifest_inject_streamer_p = manifest_inject_streamer;
    1241 CBC         129 :     return streamer;
    1242 ECB             : }
    1243                 : 
    1244                 : /*
    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
    1249 GIC         124 : ReceiveArchiveStream(PGconn *conn, pg_compress_specification *compress)
    1250                 : {
    1251                 :     ArchiveStreamState state;
    1252 ECB             : 
    1253                 :     /* Set up initial state. */
    1254 CBC         124 :     memset(&state, 0, sizeof(state));
    1255             124 :     state.tablespacenum = -1;
    1256 GIC         124 :     state.compress = compress;
    1257                 : 
    1258 ECB             :     /* All the real work happens in ReceiveArchiveStreamChunk. */
    1259 GIC         124 :     ReceiveCopyData(conn, ReceiveArchiveStreamChunk, &state);
    1260 ECB             : 
    1261                 :     /* If we wrote the backup manifest to a file, close the file. */
    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.
    1271 ECB             :      */
    1272 CBC         121 :     if (state.manifest_inject_streamer != NULL &&
    1273 UIC           0 :         state.manifest_buffer != NULL)
    1274                 :     {
    1275 LBC           0 :         bbstreamer_inject_file(state.manifest_inject_streamer,
    1276 ECB             :                                "backup_manifest",
    1277 UBC           0 :                                state.manifest_buffer->data,
    1278 UIC           0 :                                state.manifest_buffer->len);
    1279               0 :         destroyPQExpBuffer(state.manifest_buffer);
    1280 LBC           0 :         state.manifest_buffer = NULL;
    1281 ECB             :     }
    1282                 : 
    1283                 :     /* If there's still an archive in progress, end processing. */
    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;
    1289 ECB             :     }
    1290 CBC         121 : }
    1291 ECB             : 
    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
    1297 GIC      246055 : ReceiveArchiveStreamChunk(size_t r, char *copybuf, void *callback_data)
    1298                 : {
    1299          246055 :     ArchiveStreamState *state = callback_data;
    1300 CBC      246055 :     size_t      cursor = 0;
    1301 ECB             : 
    1302                 :     /* Each CopyData message begins with a type byte. */
    1303 GIC      246055 :     switch (GetCopyDataByte(r, copybuf, &cursor))
    1304 ECB             :     {
    1305 GIC         139 :         case 'n':
    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                 :                  */
    1316 CBC         139 :                 if (++state->tablespacenum > 0)
    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)
    1322 LBC           0 :                     pg_fatal("archives must precede manifest");
    1323 ECB             : 
    1324                 :                 /* Parse the rest of the CopyData message. */
    1325 GIC         139 :                 archive_name = GetCopyDataString(r, copybuf, &cursor);
    1326             139 :                 spclocation = GetCopyDataString(r, copybuf, &cursor);
    1327             139 :                 GetCopyDataEnd(r, copybuf, cursor);
    1328                 : 
    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                 :                  */
    1334 GIC         139 :                 if (archive_name[0] == '\0' || archive_name[0] == '.' ||
    1335 CBC         139 :                     strchr(archive_name, '/') != NULL ||
    1336 GIC         139 :                     strchr(archive_name, '\\') != NULL)
    1337 UIC           0 :                     pg_fatal("invalid archive name: \"%s\"",
    1338 EUB             :                              archive_name);
    1339                 : 
    1340                 :                 /*
    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                 :                  */
    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                 :                 {
    1351 GBC          15 :                     bbstreamer_finalize(state->streamer);
    1352              15 :                     bbstreamer_free(state->streamer);
    1353              15 :                     state->streamer = NULL;
    1354                 :                 }
    1355                 : 
    1356                 :                 /*
    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.
    1360                 :                  */
    1361 CBC         139 :                 if (backup_target == NULL)
    1362                 :                 {
    1363                 :                     /*
    1364 EUB             :                      * We know that recovery GUCs are supported, because this
    1365 ECB             :                      * protocol can only be used on v15+.
    1366                 :                      */
    1367 GIC         129 :                     state->streamer =
    1368 CBC         129 :                         CreateBackupStreamer(archive_name,
    1369                 :                                              spclocation,
    1370                 :                                              &state->manifest_inject_streamer,
    1371                 :                                              true, false,
    1372                 :                                              state->compress);
    1373                 :                 }
    1374 GIC         139 :                 break;
    1375                 :             }
    1376 ECB             : 
    1377 CBC      245640 :         case 'd':
    1378                 :             {
    1379                 :                 /* Archive or manifest data. */
    1380 GIC      245640 :                 if (state->manifest_buffer != NULL)
    1381                 :                 {
    1382                 :                     /* Manifest data, buffer in memory. */
    1383 LBC           0 :                     appendPQExpBuffer(state->manifest_buffer, copybuf + 1,
    1384 ECB             :                                       r - 1);
    1385                 :                 }
    1386 GIC      245640 :                 else if (state->manifest_file !=NULL)
    1387 ECB             :                 {
    1388                 :                     /* Manifest data, write to disk. */
    1389 GIC         557 :                     if (fwrite(copybuf + 1, r - 1, 1,
    1390                 :                                state->manifest_file) != 1)
    1391                 :                     {
    1392                 :                         /*
    1393 ECB             :                          * If fwrite() didn't set errno, assume that the
    1394                 :                          * problem is that we're out of disk space.
    1395                 :                          */
    1396 UIC           0 :                         if (errno == 0)
    1397               0 :                             errno = ENOSPC;
    1398               0 :                         pg_fatal("could not write to file \"%s\": %m",
    1399                 :                                  state->manifest_filename);
    1400 ECB             :                     }
    1401                 :                 }
    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);
    1407 ECB             :                 }
    1408 EUB             :                 else
    1409 UIC           0 :                     pg_fatal("unexpected payload data");
    1410 GIC      245640 :                 break;
    1411 ECB             :             }
    1412                 : 
    1413 GIC         157 :         case 'p':
    1414 ECB             :             {
    1415                 :                 /*
    1416                 :                  * Progress report.
    1417 EUB             :                  *
    1418                 :                  * The remainder of the message is expected to be an 8-byte
    1419                 :                  * count of bytes completed.
    1420                 :                  */
    1421 CBC         157 :                 totaldone = GetCopyDataUInt64(r, copybuf, &cursor);
    1422 GIC         157 :                 GetCopyDataEnd(r, copybuf, cursor);
    1423                 : 
    1424 EUB             :                 /*
    1425                 :                  * The server shouldn't send progress report messages too
    1426                 :                  * often, so we force an update each time we receive one.
    1427                 :                  */
    1428 CBC         157 :                 progress_report(state->tablespacenum, true, false);
    1429 GIC         157 :                 break;
    1430                 :             }
    1431                 : 
    1432             119 :         case 'm':
    1433                 :             {
    1434                 :                 /*
    1435                 :                  * Manifest data will be sent next. This message is not
    1436 ECB             :                  * expected to have any further payload data.
    1437                 :                  */
    1438 CBC         119 :                 GetCopyDataEnd(r, copybuf, cursor);
    1439 EUB             : 
    1440                 :                 /*
    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                 :                  */
    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
    1450 ECB             :                      * prepare to write it to a temporary file.
    1451                 :                      */
    1452 CBC         109 :                     if (state->manifest_inject_streamer != NULL)
    1453 LBC           0 :                         state->manifest_buffer = createPQExpBuffer();
    1454                 :                     else
    1455                 :                     {
    1456 GIC         109 :                         snprintf(state->manifest_filename,
    1457 ECB             :                                  sizeof(state->manifest_filename),
    1458 EUB             :                                  "%s/backup_manifest.tmp", basedir);
    1459 CBC         109 :                         state->manifest_file =
    1460             109 :                             fopen(state->manifest_filename, "wb");
    1461             109 :                         if (state->manifest_file == NULL)
    1462 UIC           0 :                             pg_fatal("could not create file \"%s\": %m",
    1463                 :                                      state->manifest_filename);
    1464 ECB             :                     }
    1465                 :                 }
    1466 GIC         119 :                 break;
    1467                 :             }
    1468                 : 
    1469 UIC           0 :         default:
    1470               0 :             ReportCopyDataParseError(r, copybuf);
    1471               0 :             break;
    1472                 :     }
    1473 GIC      246055 : }
    1474 ECB             : 
    1475                 : /*
    1476                 :  * Get a single byte from a CopyData message.
    1477                 :  *
    1478                 :  * Bail out if none remain.
    1479 EUB             :  */
    1480 ECB             : static char
    1481 CBC      246055 : GetCopyDataByte(size_t r, char *copybuf, size_t *cursor)
    1482 ECB             : {
    1483 GIC      246055 :     if (*cursor >= r)
    1484 UIC           0 :         ReportCopyDataParseError(r, copybuf);
    1485                 : 
    1486 GIC      246055 :     return copybuf[(*cursor)++];
    1487                 : }
    1488                 : 
    1489 ECB             : /*
    1490                 :  * Get a NUL-terminated string from a CopyData message.
    1491                 :  *
    1492 EUB             :  * Bail out if the terminating NUL cannot be found.
    1493 ECB             :  */
    1494                 : static char *
    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)
    1503 UIC           0 :             ReportCopyDataParseError(r, copybuf);
    1504 GBC        1832 :         if (copybuf[endpos] == '\0')
    1505 GIC         278 :             break;
    1506 GBC        1554 :         ++endpos;
    1507 EUB             :     }
    1508                 : 
    1509 GBC         278 :     *cursor = endpos + 1;
    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
    1519 GBC         157 : GetCopyDataUInt64(size_t r, char *copybuf, size_t *cursor)
    1520                 : {
    1521                 :     uint64      result;
    1522                 : 
    1523 GIC         157 :     if (*cursor + sizeof(uint64) > r)
    1524 UIC           0 :         ReportCopyDataParseError(r, copybuf);
    1525 GIC         157 :     memcpy(&result, &copybuf[*cursor], sizeof(uint64));
    1526             157 :     *cursor += sizeof(uint64);
    1527             157 :     return pg_ntoh64(result);
    1528 EUB             : }
    1529                 : 
    1530                 : /*
    1531                 :  * Bail out if we didn't parse the whole message.
    1532                 :  */
    1533                 : static void
    1534 GIC         415 : GetCopyDataEnd(size_t r, char *copybuf, size_t cursor)
    1535                 : {
    1536             415 :     if (r != cursor)
    1537 UIC           0 :         ReportCopyDataParseError(r, copybuf);
    1538 GBC         415 : }
    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
    1549 UIC           0 : ReportCopyDataParseError(size_t r, char *copybuf)
    1550                 : {
    1551               0 :     if (r == 0)
    1552               0 :         pg_fatal("empty COPY message");
    1553 EUB             :     else
    1554 UBC           0 :         pg_fatal("malformed COPY message of type %d, length %zu",
    1555 EUB             :                  copybuf[0], r);
    1556                 : }
    1557                 : 
    1558                 : /*
    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
    1564 UIC           0 : ReceiveTarFile(PGconn *conn, char *archive_name, char *spclocation,
    1565                 :                bool tablespacenum, pg_compress_specification *compress)
    1566                 : {
    1567 EUB             :     WriteTarState state;
    1568                 :     bbstreamer *manifest_inject_streamer;
    1569                 :     bool        is_recovery_guc_supported;
    1570                 :     bool        expect_unterminated_tarfile;
    1571                 : 
    1572                 :     /* Pass all COPY data through to the backup streamer. */
    1573 UIC           0 :     memset(&state, 0, sizeof(state));
    1574               0 :     is_recovery_guc_supported =
    1575               0 :         PQserverVersion(conn) >= MINIMUM_VERSION_FOR_RECOVERY_GUC;
    1576 UBC           0 :     expect_unterminated_tarfile =
    1577 UIC           0 :         PQserverVersion(conn) < MINIMUM_VERSION_FOR_TERMINATED_TARFILE;
    1578               0 :     state.streamer = CreateBackupStreamer(archive_name, spclocation,
    1579                 :                                           &manifest_inject_streamer,
    1580                 :                                           is_recovery_guc_supported,
    1581                 :                                           expect_unterminated_tarfile,
    1582 EUB             :                                           compress);
    1583 UIC           0 :     state.tablespacenum = tablespacenum;
    1584 UBC           0 :     ReceiveCopyData(conn, ReceiveTarCopyChunk, &state);
    1585 UIC           0 :     progress_update_filename(NULL);
    1586 EUB             : 
    1587                 :     /*
    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                 :      */
    1593 UIC           0 :     if (manifest_inject_streamer != NULL)
    1594                 :     {
    1595                 :         PQExpBufferData buf;
    1596                 : 
    1597                 :         /* Slurp the entire backup manifest into a buffer. */
    1598 LBC           0 :         initPQExpBuffer(&buf);
    1599 UIC           0 :         ReceiveBackupManifestInMemory(conn, &buf);
    1600               0 :         if (PQExpBufferDataBroken(buf))
    1601               0 :             pg_fatal("out of memory");
    1602                 : 
    1603                 :         /* Inject it into the output tarfile. */
    1604 LBC           0 :         bbstreamer_inject_file(manifest_inject_streamer, "backup_manifest",
    1605               0 :                                buf.data, buf.len);
    1606                 : 
    1607 ECB             :         /* Free memory. */
    1608 LBC           0 :         termPQExpBuffer(&buf);
    1609 ECB             :     }
    1610                 : 
    1611                 :     /* Cleanup. */
    1612 UIC           0 :     bbstreamer_finalize(state.streamer);
    1613               0 :     bbstreamer_free(state.streamer);
    1614                 : 
    1615               0 :     progress_report(tablespacenum, true, false);
    1616                 : 
    1617                 :     /*
    1618 EUB             :      * Do not sync the resulting tar file yet, all files are synced once at
    1619                 :      * the end.
    1620                 :      */
    1621 UIC           0 : }
    1622 EUB             : 
    1623                 : /*
    1624                 :  * Receive one chunk of tar-format data from the server.
    1625                 :  */
    1626                 : static void
    1627 UIC           0 : ReceiveTarCopyChunk(size_t r, char *copybuf, void *callback_data)
    1628 EUB             : {
    1629 UIC           0 :     WriteTarState *state = callback_data;
    1630 EUB             : 
    1631 UBC           0 :     bbstreamer_content(state->streamer, NULL, copybuf, r, BBSTREAMER_UNKNOWN);
    1632                 : 
    1633 UIC           0 :     totaldone += r;
    1634               0 :     progress_report(state->tablespacenum, false, false);
    1635               0 : }
    1636                 : 
    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 *
    1643 GIC          40 : get_tablespace_mapping(const char *dir)
    1644                 : {
    1645 EUB             :     TablespaceListCell *cell;
    1646                 :     char        canon_dir[MAXPGPATH];
    1647                 : 
    1648                 :     /* Canonicalize path for comparison consistency */
    1649 GBC          40 :     strlcpy(canon_dir, dir, sizeof(canon_dir));
    1650 GIC          40 :     canonicalize_path(canon_dir);
    1651                 : 
    1652              40 :     for (cell = tablespace_dirs.head; cell; cell = cell->next)
    1653              39 :         if (strcmp(canon_dir, cell->old_dir) == 0)
    1654              39 :             return cell->new_dir;
    1655 EUB             : 
    1656 GIC           1 :     return dir;
    1657 EUB             : }
    1658                 : 
    1659                 : /*
    1660                 :  * Receive the backup manifest file and write it out to a file.
    1661                 :  */
    1662                 : static void
    1663 UIC           0 : ReceiveBackupManifest(PGconn *conn)
    1664 EUB             : {
    1665                 :     WriteManifestState state;
    1666                 : 
    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)
    1671 UIC           0 :         pg_fatal("could not create file \"%s\": %m", state.filename);
    1672                 : 
    1673 LBC           0 :     ReceiveCopyData(conn, ReceiveBackupManifestChunk, &state);
    1674                 : 
    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)
    1683 ECB             : {
    1684 UIC           0 :     WriteManifestState *state = callback_data;
    1685                 : 
    1686               0 :     errno = 0;
    1687               0 :     if (fwrite(copybuf, r, 1, state->file) != 1)
    1688                 :     {
    1689 ECB             :         /* if write didn't set errno, assume problem is no disk space */
    1690 UIC           0 :         if (errno == 0)
    1691               0 :             errno = ENOSPC;
    1692 LBC           0 :         pg_fatal("could not write to file \"%s\": %m", state->filename);
    1693 ECB             :     }
    1694 UIC           0 : }
    1695                 : 
    1696                 : /*
    1697                 :  * Receive the backup manifest file and write it out to a file.
    1698                 :  */
    1699 ECB             : static void
    1700 LBC           0 : ReceiveBackupManifestInMemory(PGconn *conn, PQExpBuffer buf)
    1701 ECB             : {
    1702 LBC           0 :     ReceiveCopyData(conn, ReceiveBackupManifestInMemoryChunk, buf);
    1703               0 : }
    1704                 : 
    1705 EUB             : /*
    1706                 :  * Receive one chunk of the backup manifest file and write it out to a file.
    1707                 :  */
    1708                 : static void
    1709 UIC           0 : ReceiveBackupManifestInMemoryChunk(size_t r, char *copybuf,
    1710 ECB             :                                    void *callback_data)
    1711                 : {
    1712 UIC           0 :     PQExpBuffer buf = callback_data;
    1713                 : 
    1714               0 :     appendPQExpBuffer(buf, copybuf, r);
    1715               0 : }
    1716                 : 
    1717 ECB             : static void
    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;
    1723 EUB             :     TimeLineID  latesttli;
    1724                 :     TimeLineID  starttli;
    1725                 :     char       *basebkp;
    1726                 :     int         i;
    1727                 :     char        xlogstart[64];
    1728 GNC         142 :     char        xlogend[64] = {0};
    1729                 :     int         minServerMajor,
    1730 ECB             :                 maxServerMajor;
    1731                 :     int         serverVersion,
    1732                 :                 serverMajor;
    1733                 :     int         writing_to_stdout;
    1734 GIC         142 :     bool        use_new_option_syntax = false;
    1735                 :     PQExpBufferData buf;
    1736 ECB             : 
    1737 GBC         142 :     Assert(conn != NULL);
    1738 GIC         142 :     initPQExpBuffer(&buf);
    1739                 : 
    1740                 :     /*
    1741                 :      * Check server version. BASE_BACKUP command was introduced in 9.1, so we
    1742 ECB             :      * can't work with servers older than 9.1.
    1743                 :      */
    1744 CBC         142 :     minServerMajor = 901;
    1745             142 :     maxServerMajor = PG_VERSION_NUM / 100;
    1746             142 :     serverVersion = PQserverVersion(conn);
    1747             142 :     serverMajor = serverVersion / 100;
    1748 GIC         142 :     if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
    1749 ECB             :     {
    1750 LBC           0 :         const char *serverver = PQparameterStatus(conn, "server_version");
    1751                 : 
    1752 UIC           0 :         pg_fatal("incompatible server version %s",
    1753 EUB             :                  serverver ? serverver : "'unknown'");
    1754                 :     }
    1755 CBC         142 :     if (serverMajor >= 1500)
    1756 GIC         142 :         use_new_option_syntax = true;
    1757 ECB             : 
    1758                 :     /*
    1759                 :      * If WAL streaming was requested, also check that the server is new
    1760 EUB             :      * enough for that.
    1761                 :      */
    1762 CBC         142 :     if (includewal == STREAM_WAL && !CheckServerVersionForStreaming(conn))
    1763 ECB             :     {
    1764                 :         /*
    1765                 :          * Error message already written in CheckServerVersionForStreaming(),
    1766                 :          * but add a hint about using -X none.
    1767                 :          */
    1768 UIC           0 :         pg_log_error_hint("Use -X none or -X fetch to disable log streaming.");
    1769 LBC           0 :         exit(1);
    1770 ECB             :     }
    1771                 : 
    1772                 :     /*
    1773 EUB             :      * Build contents of configuration file if requested
    1774                 :      */
    1775 GIC         142 :     if (writerecoveryconf)
    1776               2 :         recoveryconfcontents = GenerateRecoveryConfig(conn, replication_slot);
    1777 ECB             : 
    1778                 :     /*
    1779                 :      * Run IDENTIFY_SYSTEM so we can get the timeline
    1780                 :      */
    1781 CBC         142 :     if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
    1782 LBC           0 :         exit(1);
    1783                 : 
    1784                 :     /*
    1785                 :      * Start the actual backup
    1786 ECB             :      */
    1787 GIC         142 :     AppendStringCommandOption(&buf, use_new_option_syntax, "LABEL", label);
    1788             142 :     if (estimatesize)
    1789             142 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "PROGRESS");
    1790 CBC         142 :     if (includewal == FETCH_WAL)
    1791 GBC          24 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "WAL");
    1792 GIC         142 :     if (fastcheckpoint)
    1793 ECB             :     {
    1794 GBC         132 :         if (use_new_option_syntax)
    1795 GIC         132 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1796 ECB             :                                       "CHECKPOINT", "fast");
    1797                 :         else
    1798 LBC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax, "FAST");
    1799                 :     }
    1800 CBC         142 :     if (includewal != NO_WAL)
    1801                 :     {
    1802 GIC         135 :         if (use_new_option_syntax)
    1803             135 :             AppendIntegerCommandOption(&buf, use_new_option_syntax, "WAIT", 0);
    1804                 :         else
    1805 UIC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax, "NOWAIT");
    1806                 :     }
    1807 CBC         142 :     if (maxrate > 0)
    1808               1 :         AppendIntegerCommandOption(&buf, use_new_option_syntax, "MAX_RATE",
    1809                 :                                    maxrate);
    1810             142 :     if (format == 't')
    1811 GIC          14 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "TABLESPACE_MAP");
    1812             142 :     if (!verify_checksums)
    1813                 :     {
    1814 CBC           1 :         if (use_new_option_syntax)
    1815               1 :             AppendIntegerCommandOption(&buf, use_new_option_syntax,
    1816                 :                                        "VERIFY_CHECKSUMS", 0);
    1817                 :         else
    1818 LBC           0 :             AppendPlainCommandOption(&buf, use_new_option_syntax,
    1819                 :                                      "NOVERIFY_CHECKSUMS");
    1820 ECB             :     }
    1821 EUB             : 
    1822 CBC         142 :     if (manifest)
    1823                 :     {
    1824             141 :         AppendStringCommandOption(&buf, use_new_option_syntax, "MANIFEST",
    1825             141 :                                   manifest_force_encode ? "force-encode" : "yes");
    1826 GIC         141 :         if (manifest_checksums != NULL)
    1827               7 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1828                 :                                       "MANIFEST_CHECKSUMS", manifest_checksums);
    1829                 :     }
    1830 ECB             : 
    1831 GBC         142 :     if (backup_target != NULL)
    1832                 :     {
    1833 ECB             :         char       *colon;
    1834                 : 
    1835 GBC          15 :         if (serverMajor < 1500)
    1836 UBC           0 :             pg_fatal("backup targets are not supported by this server version");
    1837 EUB             : 
    1838 GIC          15 :         if (writerecoveryconf)
    1839 UBC           0 :             pg_fatal("recovery configuration cannot be written when a backup target is used");
    1840                 : 
    1841 GIC          15 :         AppendPlainCommandOption(&buf, use_new_option_syntax, "TABLESPACE_MAP");
    1842 ECB             : 
    1843 CBC          15 :         if ((colon = strchr(backup_target, ':')) == NULL)
    1844                 :         {
    1845 GBC           6 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1846                 :                                       "TARGET", backup_target);
    1847 ECB             :         }
    1848 EUB             :         else
    1849                 :         {
    1850                 :             char       *target;
    1851                 : 
    1852 GIC           9 :             target = pnstrdup(backup_target, colon - backup_target);
    1853               9 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1854 ECB             :                                       "TARGET", target);
    1855 CBC           9 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1856 ECB             :                                       "TARGET_DETAIL", colon + 1);
    1857                 :         }
    1858                 :     }
    1859 GBC         127 :     else if (serverMajor >= 1500)
    1860 GIC         127 :         AppendStringCommandOption(&buf, use_new_option_syntax,
    1861                 :                                   "TARGET", "client");
    1862 ECB             : 
    1863 GIC         142 :     if (compressloc == COMPRESS_LOCATION_SERVER)
    1864 ECB             :     {
    1865 GBC          29 :         if (!use_new_option_syntax)
    1866 UIC           0 :             pg_fatal("server does not support server-side compression");
    1867 GIC          29 :         AppendStringCommandOption(&buf, use_new_option_syntax,
    1868                 :                                   "COMPRESSION", compression_algorithm);
    1869              29 :         if (compression_detail != NULL)
    1870              14 :             AppendStringCommandOption(&buf, use_new_option_syntax,
    1871                 :                                       "COMPRESSION_DETAIL",
    1872 ECB             :                                       compression_detail);
    1873                 :     }
    1874                 : 
    1875 GBC         142 :     if (verbose)
    1876 LBC           0 :         pg_log_info("initiating base backup, waiting for checkpoint to complete");
    1877                 : 
    1878 CBC         142 :     if (showprogress && !verbose)
    1879 EUB             :     {
    1880 UIC           0 :         fprintf(stderr, _("waiting for checkpoint"));
    1881               0 :         if (isatty(fileno(stderr)))
    1882               0 :             fprintf(stderr, "\r");
    1883                 :         else
    1884               0 :             fprintf(stderr, "\n");
    1885 ECB             :     }
    1886                 : 
    1887 GBC         142 :     if (use_new_option_syntax && buf.len > 0)
    1888 GIC         142 :         basebkp = psprintf("BASE_BACKUP (%s)", buf.data);
    1889 ECB             :     else
    1890 UBC           0 :         basebkp = psprintf("BASE_BACKUP %s", buf.data);
    1891                 : 
    1892 GIC         142 :     if (PQsendQuery(conn, basebkp) == 0)
    1893 UIC           0 :         pg_fatal("could not send replication command \"%s\": %s",
    1894                 :                  "BASE_BACKUP", PQerrorMessage(conn));
    1895 ECB             : 
    1896                 :     /*
    1897                 :      * Get the starting WAL location
    1898                 :      */
    1899 CBC         142 :     res = PQgetResult(conn);
    1900 GIC         142 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
    1901              16 :         pg_fatal("could not initiate base backup: %s",
    1902                 :                  PQerrorMessage(conn));
    1903             126 :     if (PQntuples(res) != 1)
    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                 : 
    1907 GIC         126 :     strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
    1908                 : 
    1909             126 :     if (verbose)
    1910 UIC           0 :         pg_log_info("checkpoint completed");
    1911 ECB             : 
    1912                 :     /*
    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
    1915                 :      * IDENTIFY_SYSTEM.
    1916                 :      */
    1917 GIC         126 :     if (PQnfields(res) >= 2)
    1918             126 :         starttli = atoi(PQgetvalue(res, 0, 1));
    1919                 :     else
    1920 UIC           0 :         starttli = latesttli;
    1921 GIC         126 :     PQclear(res);
    1922 ECB             : 
    1923 CBC         126 :     if (verbose && includewal != NO_WAL)
    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                 :      */
    1930 GIC         126 :     res = PQgetResult(conn);
    1931 CBC         126 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
    1932 UIC           0 :         pg_fatal("could not get backup header: %s",
    1933                 :                  PQerrorMessage(conn));
    1934 GIC         126 :     if (PQntuples(res) < 1)
    1935 UIC           0 :         pg_fatal("no data returned from server");
    1936 ECB             : 
    1937 EUB             :     /*
    1938                 :      * Sum up the total size, for progress reporting
    1939 ECB             :      */
    1940 GIC         126 :     totalsize_kb = totaldone = 0;
    1941 CBC         126 :     tablespacecount = PQntuples(res);
    1942             266 :     for (i = 0; i < PQntuples(res); i++)
    1943                 :     {
    1944 GIC         141 :         totalsize_kb += atol(PQgetvalue(res, i, 2));
    1945                 : 
    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.
    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.
    1955                 :          */
    1956 GIC         141 :         if (backup_target == NULL && format == 'p' && !PQgetisnull(res, i, 1))
    1957                 :         {
    1958 CBC          14 :             char       *path = unconstify(char *, get_tablespace_mapping(PQgetvalue(res, i, 1)));
    1959                 : 
    1960 GIC          14 :             verify_dir_is_empty_or_create(path, &made_tablespace_dirs, &found_tablespace_dirs);
    1961                 :         }
    1962                 :     }
    1963 EUB             : 
    1964                 :     /*
    1965                 :      * When writing to stdout, require a single tablespace
    1966                 :      */
    1967 GIC         139 :     writing_to_stdout = format == 't' && basedir != NULL &&
    1968              14 :         strcmp(basedir, "-") == 0;
    1969             125 :     if (writing_to_stdout && PQntuples(res) > 1)
    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.
    1976 EUB             :      */
    1977 GIC         125 :     if (includewal == STREAM_WAL)
    1978 EUB             :     {
    1979                 :         pg_compress_algorithm wal_compress_algorithm;
    1980                 :         int         wal_compress_level;
    1981                 : 
    1982 GIC          99 :         if (verbose)
    1983 UBC           0 :             pg_log_info("starting background WAL receiver");
    1984                 : 
    1985 GBC          99 :         if (client_compress->algorithm == PG_COMPRESSION_GZIP)
    1986                 :         {
    1987 GIC           3 :             wal_compress_algorithm = PG_COMPRESSION_GZIP;
    1988 GBC           3 :             wal_compress_level = client_compress->level;
    1989                 :         }
    1990                 :         else
    1991                 :         {
    1992 GIC          96 :             wal_compress_algorithm = PG_COMPRESSION_NONE;
    1993              96 :             wal_compress_level = 0;
    1994                 :         }
    1995                 : 
    1996              99 :         StartLogStreamer(xlogstart, starttli, sysidentifier,
    1997                 :                          wal_compress_algorithm,
    1998                 :                          wal_compress_level);
    1999                 :     }
    2000                 : 
    2001             124 :     if (serverMajor >= 1500)
    2002                 :     {
    2003 EUB             :         /* Receive a single tar stream with everything. */
    2004 GBC         124 :         ReceiveArchiveStream(conn, client_compress);
    2005                 :     }
    2006                 :     else
    2007 ECB             :     {
    2008                 :         /* Receive a tar file for each tablespace in turn */
    2009 UBC           0 :         for (i = 0; i < PQntuples(res); i++)
    2010 EUB             :         {
    2011                 :             char        archive_name[MAXPGPATH];
    2012                 :             char       *spclocation;
    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                 :              */
    2022 UIC           0 :             if (PQgetisnull(res, i, 0))
    2023 ECB             :             {
    2024 UBC           0 :                 strlcpy(archive_name, "base.tar", sizeof(archive_name));
    2025 LBC           0 :                 spclocation = NULL;
    2026 ECB             :             }
    2027 EUB             :             else
    2028 ECB             :             {
    2029 UIC           0 :                 snprintf(archive_name, sizeof(archive_name),
    2030 ECB             :                          "%s.tar", PQgetvalue(res, i, 0));
    2031 LBC           0 :                 spclocation = PQgetvalue(res, i, 1);
    2032                 :             }
    2033 ECB             : 
    2034 UIC           0 :             ReceiveTarFile(conn, archive_name, spclocation, i,
    2035 ECB             :                            client_compress);
    2036                 :         }
    2037                 : 
    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
    2043 EUB             :          * tarfile.  Such a configuration doesn't allow for writing multiple
    2044                 :          * files.
    2045                 :          *
    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                 :          */
    2049 LBC           0 :         if (!writing_to_stdout && manifest)
    2050 UIC           0 :             ReceiveBackupManifest(conn);
    2051                 :     }
    2052                 : 
    2053 GIC         121 :     if (showprogress)
    2054                 :     {
    2055 UIC           0 :         progress_update_filename(NULL);
    2056               0 :         progress_report(PQntuples(res), true, true);
    2057                 :     }
    2058                 : 
    2059 GIC         121 :     PQclear(res);
    2060                 : 
    2061                 :     /*
    2062                 :      * Get the stop position
    2063                 :      */
    2064             121 :     res = PQgetResult(conn);
    2065             121 :     if (PQresultStatus(res) != PGRES_TUPLES_OK)
    2066 CBC           1 :         pg_fatal("backup failed: %s",
    2067 EUB             :                  PQerrorMessage(conn));
    2068 GIC         120 :     if (PQntuples(res) != 1)
    2069 UIC           0 :         pg_fatal("no write-ahead log end position returned from server");
    2070 CBC         120 :     strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
    2071 GBC         120 :     if (verbose && includewal != NO_WAL)
    2072 UIC           0 :         pg_log_info("write-ahead log end point: %s", xlogend);
    2073 GIC         120 :     PQclear(res);
    2074 ECB             : 
    2075 CBC         120 :     res = PQgetResult(conn);
    2076 GBC         120 :     if (PQresultStatus(res) != PGRES_COMMAND_OK)
    2077 ECB             :     {
    2078 GBC           3 :         const char *sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
    2079 ECB             : 
    2080 GBC           3 :         if (sqlstate &&
    2081 GIC           3 :             strcmp(sqlstate, ERRCODE_DATA_CORRUPTED) == 0)
    2082                 :         {
    2083               3 :             pg_log_error("checksum error occurred");
    2084               3 :             checksum_failure = true;
    2085                 :         }
    2086                 :         else
    2087                 :         {
    2088 UIC           0 :             pg_log_error("final receive failed: %s",
    2089                 :                          PQerrorMessage(conn));
    2090                 :         }
    2091 GIC           3 :         exit(1);
    2092                 :     }
    2093                 : 
    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)
    2112 UIC           0 :             pg_log_info("waiting for background process to finish streaming ...");
    2113                 : 
    2114                 : #ifndef WIN32
    2115 CBC          91 :         if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
    2116 UIC           0 :             pg_fatal("could not send command to background pipe: %m");
    2117                 : 
    2118                 :         /* Just wait for the background process to exit */
    2119 GIC          91 :         r = waitpid(bgchild, &status, 0);
    2120 CBC          91 :         if (r == (pid_t) -1)
    2121 LBC           0 :             pg_fatal("could not wait for child process: %m");
    2122 CBC          91 :         if (r != bgchild)
    2123 UIC           0 :             pg_fatal("child %d died, expected %d", (int) r, (int) bgchild);
    2124 GIC          91 :         if (status != 0)
    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                 :          */
    2134 ECB             :         if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
    2135                 :             pg_fatal("could not parse write-ahead log location \"%s\"",
    2136 EUB             :                      xlogend);
    2137                 :         xlogendptr = ((uint64) hi) << 32 | lo;
    2138                 :         InterlockedIncrement(&has_xlogendptr);
    2139                 : 
    2140                 :         /* First wait for the thread to exit */
    2141                 :         if (WaitForSingleObjectEx((HANDLE) bgchild_handle, INFINITE, FALSE) !=
    2142                 :             WAIT_OBJECT_0)
    2143                 :         {
    2144                 :             _dosmaperr(GetLastError());
    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 */
    2156 ECB             : #endif
    2157                 :     }
    2158                 : 
    2159                 :     /* Free the configuration file contents */
    2160 GIC         117 :     destroyPQExpBuffer(recoveryconfcontents);
    2161 ECB             : 
    2162 EUB             :     /*
    2163                 :      * End of copy data. Final result is already checked inside the loop.
    2164 ECB             :      */
    2165 CBC         117 :     PQclear(res);
    2166 GIC         117 :     PQfinish(conn);
    2167 CBC         117 :     conn = NULL;
    2168                 : 
    2169                 :     /*
    2170 EUB             :      * Make data persistent on disk once backup is completed. For tar format
    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.
    2175 ECB             :      *
    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                 :      */
    2179 GIC         117 :     if (do_sync && backup_target == NULL)
    2180                 :     {
    2181 LBC           0 :         if (verbose)
    2182 UBC           0 :             pg_log_info("syncing data to disk ...");
    2183 LBC           0 :         if (format == 't')
    2184                 :         {
    2185 UIC           0 :             if (strcmp(basedir, "-") != 0)
    2186               0 :                 (void) fsync_dir_recurse(basedir);
    2187 ECB             :         }
    2188                 :         else
    2189                 :         {
    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                 :      */
    2201 GIC         117 :     if (!writing_to_stdout && manifest && backup_target == NULL)
    2202                 :     {
    2203                 :         char        tmp_filename[MAXPGPATH];
    2204                 :         char        filename[MAXPGPATH];
    2205                 : 
    2206             106 :         if (verbose)
    2207 UIC           0 :             pg_log_info("renaming backup_manifest.tmp to backup_manifest");
    2208                 : 
    2209 GIC         106 :         snprintf(tmp_filename, MAXPGPATH, "%s/backup_manifest.tmp", basedir);
    2210             106 :         snprintf(filename, MAXPGPATH, "%s/backup_manifest", basedir);
    2211                 : 
    2212             106 :         if (do_sync)
    2213                 :         {
    2214                 :             /* durable_rename emits its own log message in case of failure */
    2215 UIC           0 :             if (durable_rename(tmp_filename, filename) != 0)
    2216               0 :                 exit(1);
    2217                 :         }
    2218                 :         else
    2219                 :         {
    2220 GIC         106 :             if (rename(tmp_filename, filename) != 0)
    2221 UIC           0 :                 pg_fatal("could not rename file \"%s\" to \"%s\": %m",
    2222                 :                          tmp_filename, filename);
    2223                 :         }
    2224                 :     }
    2225                 : 
    2226 GIC         117 :     if (verbose)
    2227 UIC           0 :         pg_log_info("base backup completed");
    2228 CBC         117 : }
    2229 ECB             : 
    2230                 : 
    2231                 : int
    2232 GIC         176 : main(int argc, char **argv)
    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'},
    2241                 :         {"max-rate", required_argument, NULL, 'r'},
    2242                 :         {"write-recovery-conf", no_argument, NULL, 'R'},
    2243                 :         {"slot", required_argument, NULL, 'S'},
    2244                 :         {"target", required_argument, NULL, 't'},
    2245                 :         {"tablespace-mapping", required_argument, NULL, 'T'},
    2246                 :         {"wal-method", required_argument, NULL, 'X'},
    2247                 :         {"gzip", no_argument, NULL, 'z'},
    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'},
    2252                 :         {"dbname", required_argument, NULL, 'd'},
    2253                 :         {"host", required_argument, NULL, 'h'},
    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'},
    2261                 :         {"waldir", required_argument, NULL, 1},
    2262 EUB             :         {"no-slot", no_argument, NULL, 2},
    2263                 :         {"no-verify-checksums", no_argument, NULL, 3},
    2264                 :         {"no-estimate-size", no_argument, NULL, 4},
    2265                 :         {"no-manifest", no_argument, NULL, 5},
    2266                 :         {"manifest-force-encode", no_argument, NULL, 6},
    2267 ECB             :         {"manifest-checksums", required_argument, NULL, 7},
    2268                 :         {NULL, 0, NULL, 0}
    2269                 :     };
    2270                 :     int         c;
    2271                 : 
    2272                 :     int         option_index;
    2273 CBC         176 :     char       *compression_algorithm = "none";
    2274             176 :     char       *compression_detail = NULL;
    2275             176 :     CompressionLocation compressloc = COMPRESS_LOCATION_UNSPECIFIED;
    2276 ECB             :     pg_compress_specification client_compress;
    2277                 : 
    2278 CBC         176 :     pg_logging_init(argv[0]);
    2279             176 :     progname = get_progname(argv[0]);
    2280             176 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
    2281 ECB             : 
    2282 GIC         176 :     if (argc > 1)
    2283 EUB             :     {
    2284 GIC         175 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
    2285 ECB             :         {
    2286 CBC           1 :             usage();
    2287               1 :             exit(0);
    2288 ECB             :         }
    2289 GBC         174 :         else if (strcmp(argv[1], "-V") == 0
    2290             174 :                  || strcmp(argv[1], "--version") == 0)
    2291 EUB             :         {
    2292 CBC           1 :             puts("pg_basebackup (PostgreSQL) " PG_VERSION);
    2293               1 :             exit(0);
    2294 ECB             :         }
    2295                 :     }
    2296                 : 
    2297 CBC         174 :     atexit(cleanup_directories_atexit);
    2298 ECB             : 
    2299 GNC         920 :     while ((c = getopt_long(argc, argv, "c:Cd:D:F:h:l:nNp:Pr:Rs:S:t:T:U:vwWX:zZ:",
    2300 CBC         920 :                             long_options, &option_index)) != -1)
    2301 EUB             :     {
    2302 GBC         753 :         switch (c)
    2303 EUB             :         {
    2304 GNC         150 :             case 'c':
    2305             150 :                 if (pg_strcasecmp(optarg, "fast") == 0)
    2306             150 :                     fastcheckpoint = true;
    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);
    2312 GNC         150 :                 break;
    2313 CBC           6 :             case 'C':
    2314               6 :                 create_slot = true;
    2315               6 :                 break;
    2316 GNC           1 :             case 'd':
    2317               1 :                 connection_string = pg_strdup(optarg);
    2318               1 :                 break;
    2319 CBC         154 :             case 'D':
    2320             154 :                 basedir = pg_strdup(optarg);
    2321             154 :                 break;
    2322 GBC          29 :             case 'F':
    2323              29 :                 if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
    2324 GIC          14 :                     format = 'p';
    2325              15 :                 else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
    2326 GBC          15 :                     format = 't';
    2327 EUB             :                 else
    2328 UBC           0 :                     pg_fatal("invalid output format \"%s\", must be \"plain\" or \"tar\"",
    2329 ECB             :                              optarg);
    2330 GIC          29 :                 break;
    2331 GNC          54 :             case 'h':
    2332              54 :                 dbhost = pg_strdup(optarg);
    2333              54 :                 break;
    2334 UNC           0 :             case 'l':
    2335               0 :                 label = pg_strdup(optarg);
    2336               0 :                 break;
    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;
    2346 UNC           0 :             case 'P':
    2347               0 :                 showprogress = true;
    2348               0 :                 break;
    2349 GIC           1 :             case 'r':
    2350               1 :                 maxrate = parse_max_rate(optarg);
    2351               1 :                 break;
    2352               2 :             case 'R':
    2353 CBC           2 :                 writerecoveryconf = true;
    2354               2 :                 break;
    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;
    2362 CBC           9 :             case 'S':
    2363 ECB             : 
    2364                 :                 /*
    2365                 :                  * When specifying replication slot name, use a permanent
    2366                 :                  * slot.
    2367                 :                  */
    2368 CBC           9 :                 replication_slot = pg_strdup(optarg);
    2369               9 :                 temp_replication_slot = false;
    2370               9 :                 break;
    2371 GBC          20 :             case 't':
    2372              20 :                 backup_target = pg_strdup(optarg);
    2373              20 :                 break;
    2374              19 :             case 'T':
    2375              19 :                 tablespace_list_append(optarg);
    2376              13 :                 break;
    2377 GNC           7 :             case 'U':
    2378               7 :                 dbuser = pg_strdup(optarg);
    2379               7 :                 break;
    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;
    2389 GBC          43 :             case 'X':
    2390 CBC          43 :                 if (strcmp(optarg, "n") == 0 ||
    2391              43 :                     strcmp(optarg, "none") == 0)
    2392 ECB             :                 {
    2393 GIC          10 :                     includewal = NO_WAL;
    2394 ECB             :                 }
    2395 GIC          33 :                 else if (strcmp(optarg, "f") == 0 ||
    2396 CBC          33 :                          strcmp(optarg, "fetch") == 0)
    2397 ECB             :                 {
    2398 GIC          24 :                     includewal = FETCH_WAL;
    2399 ECB             :                 }
    2400 GIC           9 :                 else if (strcmp(optarg, "s") == 0 ||
    2401 CBC           9 :                          strcmp(optarg, "stream") == 0)
    2402 ECB             :                 {
    2403 GIC           9 :                     includewal = STREAM_WAL;
    2404 ECB             :                 }
    2405                 :                 else
    2406 UIC           0 :                     pg_fatal("invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"",
    2407 EUB             :                              optarg);
    2408 GIC          43 :                 break;
    2409 CBC           1 :             case 'z':
    2410               1 :                 compression_algorithm = "gzip";
    2411               1 :                 compression_detail = NULL;
    2412               1 :                 compressloc = COMPRESS_LOCATION_UNSPECIFIED;
    2413               1 :                 break;
    2414              37 :             case 'Z':
    2415 GNC          37 :                 backup_parse_compress_options(optarg, &compression_algorithm,
    2416                 :                                               &compression_detail, &compressloc);
    2417 GBC          37 :                 break;
    2418 GNC           1 :             case 1:
    2419               1 :                 xlog_dir = pg_strdup(optarg);
    2420 CBC           1 :                 break;
    2421 GNC           3 :             case 2:
    2422               3 :                 no_slot = true;
    2423 GIC           3 :                 break;
    2424               1 :             case 3:
    2425               1 :                 verify_checksums = false;
    2426               1 :                 break;
    2427 LBC           0 :             case 4:
    2428 UIC           0 :                 estimatesize = false;
    2429 LBC           0 :                 break;
    2430 CBC           1 :             case 5:
    2431               1 :                 manifest = false;
    2432 GIC           1 :                 break;
    2433 CBC           1 :             case 6:
    2434               1 :                 manifest_force_encode = true;
    2435 GIC           1 :                 break;
    2436               7 :             case 7:
    2437               7 :                 manifest_checksums = pg_strdup(optarg);
    2438               7 :                 break;
    2439 CBC           1 :             default:
    2440                 :                 /* getopt_long already emitted a complaint */
    2441               1 :                 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2442               1 :                 exit(1);
    2443 ECB             :         }
    2444                 :     }
    2445                 : 
    2446                 :     /*
    2447                 :      * Any non-option arguments?
    2448                 :      */
    2449 CBC         167 :     if (optind < argc)
    2450                 :     {
    2451 UIC           0 :         pg_log_error("too many command-line arguments (first is \"%s\")",
    2452                 :                      argv[optind]);
    2453               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2454               0 :         exit(1);
    2455                 :     }
    2456                 : 
    2457 ECB             :     /*
    2458                 :      * Setting the backup target to 'client' is equivalent to leaving out the
    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                 :      */
    2462 CBC         167 :     if (backup_target != NULL && strcmp(backup_target, "client") == 0)
    2463                 :     {
    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.
    2471 ECB             :      */
    2472 GIC         167 :     if (backup_target != NULL && format != '\0')
    2473                 :     {
    2474               1 :         pg_log_error("cannot specify both format and backup target");
    2475               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2476 CBC           1 :         exit(1);
    2477 ECB             :     }
    2478 GIC         166 :     if (format == '\0')
    2479             144 :         format = 'p';
    2480 ECB             : 
    2481                 :     /*
    2482                 :      * Either directory or backup target should be specified, but not both
    2483                 :      */
    2484 GIC         166 :     if (basedir == NULL && backup_target == NULL)
    2485                 :     {
    2486               1 :         pg_log_error("must specify output directory or backup target");
    2487               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2488 CBC           1 :         exit(1);
    2489 ECB             :     }
    2490 CBC         165 :     if (basedir != NULL && backup_target != NULL)
    2491                 :     {
    2492 GIC           2 :         pg_log_error("cannot specify both output directory and backup target");
    2493               2 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2494               2 :         exit(1);
    2495                 :     }
    2496                 : 
    2497 ECB             :     /*
    2498                 :      * If the user has not specified where to perform backup compression,
    2499 EUB             :      * default to the client, unless the user specified --target, in which
    2500                 :      * case the server is the only choice.
    2501                 :      */
    2502 GIC         163 :     if (compressloc == COMPRESS_LOCATION_UNSPECIFIED)
    2503                 :     {
    2504             140 :         if (backup_target == NULL)
    2505             127 :             compressloc = COMPRESS_LOCATION_CLIENT;
    2506                 :         else
    2507 CBC          13 :             compressloc = COMPRESS_LOCATION_SERVER;
    2508 ECB             :     }
    2509                 : 
    2510 EUB             :     /*
    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                 :      */
    2516 GIC         163 :     if (compressloc == COMPRESS_LOCATION_CLIENT)
    2517                 :     {
    2518 ECB             :         pg_compress_algorithm alg;
    2519                 :         char       *error_detail;
    2520                 : 
    2521 CBC         132 :         if (!parse_compress_algorithm(compression_algorithm, &alg))
    2522               2 :             pg_fatal("unrecognized compression algorithm: \"%s\"",
    2523                 :                      compression_algorithm);
    2524 ECB             : 
    2525 GIC         130 :         parse_compress_specification(alg, compression_detail, &client_compress);
    2526 GBC         130 :         error_detail = validate_compress_specification(&client_compress);
    2527             130 :         if (error_detail != NULL)
    2528              10 :             pg_fatal("invalid compression specification: %s",
    2529                 :                      error_detail);
    2530                 :     }
    2531 ECB             :     else
    2532                 :     {
    2533 CBC          31 :         Assert(compressloc == COMPRESS_LOCATION_SERVER);
    2534              31 :         client_compress.algorithm = PG_COMPRESSION_NONE;
    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.
    2541 ECB             :      */
    2542 GIC         151 :     if (backup_target != NULL && compressloc == COMPRESS_LOCATION_CLIENT)
    2543 ECB             :     {
    2544 UIC           0 :         pg_log_error("client-side compression is not possible when a backup target is specified");
    2545 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2546               0 :         exit(1);
    2547 ECB             :     }
    2548                 : 
    2549                 :     /*
    2550                 :      * Client-side compression doesn't make sense unless tar format is in use.
    2551                 :      */
    2552 CBC         151 :     if (format == 'p' && compressloc == COMPRESS_LOCATION_CLIENT &&
    2553 GIC         106 :         client_compress.algorithm != PG_COMPRESSION_NONE)
    2554 ECB             :     {
    2555 UIC           0 :         pg_log_error("only tar mode backups can be compressed");
    2556 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2557 UIC           0 :         exit(1);
    2558 ECB             :     }
    2559                 : 
    2560                 :     /*
    2561                 :      * Sanity checks for WAL method.
    2562                 :      */
    2563 GIC         151 :     if (backup_target != NULL && includewal == STREAM_WAL)
    2564 EUB             :     {
    2565 GIC           2 :         pg_log_error("WAL cannot be streamed when a backup target is specified");
    2566 GBC           2 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2567               2 :         exit(1);
    2568                 :     }
    2569 GIC         149 :     if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
    2570                 :     {
    2571 UIC           0 :         pg_log_error("cannot stream write-ahead logs in tar mode to stdout");
    2572               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2573               0 :         exit(1);
    2574 ECB             :     }
    2575                 : 
    2576 CBC         149 :     if (replication_slot && includewal != STREAM_WAL)
    2577                 :     {
    2578 GBC           1 :         pg_log_error("replication slots can only be used with WAL streaming");
    2579               1 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2580               1 :         exit(1);
    2581                 :     }
    2582 ECB             : 
    2583                 :     /*
    2584 EUB             :      * Sanity checks for replication slot options.
    2585                 :      */
    2586 GBC         148 :     if (no_slot)
    2587                 :     {
    2588 GIC           3 :         if (replication_slot)
    2589                 :         {
    2590 CBC           2 :             pg_log_error("--no-slot cannot be used with slot name");
    2591               2 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2592 GIC           2 :             exit(1);
    2593 EUB             :         }
    2594 GBC           1 :         temp_replication_slot = false;
    2595 EUB             :     }
    2596                 : 
    2597 GIC         146 :     if (create_slot)
    2598                 :     {
    2599               4 :         if (!replication_slot)
    2600                 :         {
    2601               2 :             pg_log_error("%s needs a slot to be specified using --slot",
    2602 ECB             :                          "--create-slot");
    2603 GIC           2 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2604 GBC           2 :             exit(1);
    2605                 :         }
    2606 EUB             : 
    2607 GBC           2 :         if (no_slot)
    2608                 :         {
    2609 UIC           0 :             pg_log_error("%s and %s are incompatible options",
    2610                 :                          "--create-slot", "--no-slot");
    2611               0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2612               0 :             exit(1);
    2613 ECB             :         }
    2614                 :     }
    2615 EUB             : 
    2616                 :     /*
    2617                 :      * Sanity checks on WAL directory.
    2618                 :      */
    2619 GIC         144 :     if (xlog_dir)
    2620                 :     {
    2621 CBC           1 :         if (backup_target != NULL)
    2622                 :         {
    2623 UBC           0 :             pg_log_error("WAL directory location cannot be specified along with a backup target");
    2624 UIC           0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2625 UBC           0 :             exit(1);
    2626 EUB             :         }
    2627 GIC           1 :         if (format != 'p')
    2628                 :         {
    2629 UIC           0 :             pg_log_error("WAL directory location can only be specified in plain mode");
    2630 LBC           0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2631               0 :             exit(1);
    2632                 :         }
    2633                 : 
    2634 ECB             :         /* clean up xlog directory name, check it's absolute */
    2635 GIC           1 :         canonicalize_path(xlog_dir);
    2636 CBC           1 :         if (!is_absolute_path(xlog_dir))
    2637                 :         {
    2638 UIC           0 :             pg_log_error("WAL directory location must be an absolute path");
    2639               0 :             pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2640               0 :             exit(1);
    2641                 :         }
    2642                 :     }
    2643                 : 
    2644                 :     /*
    2645                 :      * Sanity checks for progress reporting options.
    2646                 :      */
    2647 GIC         144 :     if (showprogress && !estimatesize)
    2648 ECB             :     {
    2649 UIC           0 :         pg_log_error("%s and %s are incompatible options",
    2650                 :                      "--progress", "--no-estimate-size");
    2651               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2652               0 :         exit(1);
    2653                 :     }
    2654                 : 
    2655                 :     /*
    2656                 :      * Sanity checks for backup manifest options.
    2657                 :      */
    2658 GIC         144 :     if (!manifest && manifest_checksums != NULL)
    2659 ECB             :     {
    2660 UIC           0 :         pg_log_error("%s and %s are incompatible options",
    2661                 :                      "--no-manifest", "--manifest-checksums");
    2662 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2663 UBC           0 :         exit(1);
    2664                 :     }
    2665                 : 
    2666 GIC         144 :     if (!manifest && manifest_force_encode)
    2667                 :     {
    2668 UIC           0 :         pg_log_error("%s and %s are incompatible options",
    2669                 :                      "--no-manifest", "--manifest-force-encode");
    2670 LBC           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
    2671               0 :         exit(1);
    2672                 :     }
    2673                 : 
    2674 ECB             :     /* connection in replication mode to server */
    2675 GBC         144 :     conn = GetConnection();
    2676 GIC         144 :     if (!conn)
    2677                 :     {
    2678 ECB             :         /* Error message already written in GetConnection() */
    2679 GIC           2 :         exit(1);
    2680                 :     }
    2681             142 :     atexit(disconnect_atexit);
    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
    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.
    2692                 :      */
    2693 GBC         142 :     pqsignal(SIGCHLD, sigchld_handler);
    2694 ECB             : #endif
    2695                 : 
    2696                 :     /*
    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                 :      */
    2704 GIC         142 :     umask(pg_mode_mask);
    2705                 : 
    2706                 :     /* Backup manifests are supported in 13 and newer versions */
    2707             142 :     if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_MANIFESTS)
    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                 :      */
    2715 GIC         142 :     if (basedir != NULL && (format == 'p' || strcmp(basedir, "-") != 0))
    2716             127 :         verify_dir_is_empty_or_create(basedir, &made_new_pgdata, &found_existing_pgdata);
    2717                 : 
    2718                 :     /* determine remote server's xlog segment size */
    2719             142 :     if (!RetrieveWalSegSize(conn))
    2720 UIC           0 :         exit(1);
    2721                 : 
    2722                 :     /* Create pg_wal symlink, if required */
    2723 GIC         142 :     if (xlog_dir)
    2724                 :     {
    2725                 :         char       *linkloc;
    2726                 : 
    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                 :          */
    2733               1 :         linkloc = psprintf("%s/%s", basedir,
    2734               1 :                            PQserverVersion(conn) < MINIMUM_VERSION_FOR_PG_WAL ?
    2735                 :                            "pg_xlog" : "pg_wal");
    2736                 : 
    2737               1 :         if (symlink(xlog_dir, linkloc) != 0)
    2738 UIC           0 :             pg_fatal("could not create symbolic link \"%s\": %m", linkloc);
    2739 GIC           1 :         free(linkloc);
    2740                 :     }
    2741                 : 
    2742             142 :     BaseBackup(compression_algorithm, compression_detail, compressloc,
    2743                 :                &client_compress);
    2744                 : 
    2745             117 :     success = true;
    2746             117 :     return 0;
    2747                 : }
        

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