PostgreSQL Source Code  git master
pg_basebackup.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include "access/xlog_internal.h"
#include "common/file_utils.h"
#include "common/string.h"
#include "fe_utils/string_utils.h"
#include "getopt_long.h"
#include "libpq-fe.h"
#include "pqexpbuffer.h"
#include "pgtar.h"
#include "pgtime.h"
#include "receivelog.h"
#include "replication/basebackup.h"
#include "streamutil.h"
Include dependency graph for pg_basebackup.c:

Go to the source code of this file.

Data Structures

struct  TablespaceListCell
 
struct  TablespaceList
 
struct  logstreamer_param
 

Macros

#define MINIMUM_VERSION_FOR_PG_WAL   100000
 
#define MINIMUM_VERSION_FOR_TEMP_SLOTS   100000
 
#define VERBOSE_FILENAME_LENGTH   35
 
#define WRITE_TAR_DATA(buf, sz)   writeTarData(tarfile, buf, sz, filename)
 

Typedefs

typedef struct TablespaceListCell TablespaceListCell
 
typedef struct TablespaceList TablespaceList
 

Enumerations

enum  IncludeWal { NO_WAL, FETCH_WAL, STREAM_WAL }
 

Functions

static void usage (void)
 
static void disconnect_and_exit (int code) pg_attribute_noreturn()
 
static void verify_dir_is_empty_or_create (char *dirname, bool *created, bool *found)
 
static void progress_report (int tablespacenum, const char *filename, bool force)
 
static void ReceiveTarFile (PGconn *conn, PGresult *res, int rownum)
 
static void ReceiveAndUnpackTarFile (PGconn *conn, PGresult *res, int rownum)
 
static void GenerateRecoveryConf (PGconn *conn)
 
static void WriteRecoveryConf (void)
 
static void BaseBackup (void)
 
static bool reached_end_position (XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
 
static const char * get_tablespace_mapping (const char *dir)
 
static void tablespace_list_append (const char *arg)
 
static void cleanup_directories_atexit (void)
 
static int LogStreamerMain (logstreamer_param *param)
 
static void StartLogStreamer (char *startpos, uint32 timeline, char *sysidentifier)
 
static int32 parse_max_rate (char *src)
 
static void writeTarData (FILE *tarfile, char *buf, int r, char *current_file)
 
static char * escape_quotes (const char *src)
 
int main (int argc, char **argv)
 

Variables

static char * basedir = NULL
 
static TablespaceList tablespace_dirs = {NULL, NULL}
 
static char * xlog_dir = NULL
 
static char format = 'p'
 
static char * label = "pg_basebackup base backup"
 
static bool noclean = false
 
static bool showprogress = false
 
static int verbose = 0
 
static int compresslevel = 0
 
static IncludeWal includewal = STREAM_WAL
 
static bool fastcheckpoint = false
 
static bool writerecoveryconf = false
 
static bool do_sync = true
 
static int standby_message_timeout = 10 * 1000
 
static pg_time_t last_progress_report = 0
 
static int32 maxrate = 0
 
static char * replication_slot = NULL
 
static bool temp_replication_slot = true
 
static bool create_slot = false
 
static bool no_slot = false
 
static bool success = false
 
static bool made_new_pgdata = false
 
static bool found_existing_pgdata = false
 
static bool made_new_xlogdir = false
 
static bool found_existing_xlogdir = false
 
static bool made_tablespace_dirs = false
 
static bool found_tablespace_dirs = false
 
static uint64 totalsize
 
static uint64 totaldone
 
static int tablespacecount
 
static int bgpipe [2] = {-1, -1}
 
static pid_t bgchild = -1
 
static bool in_log_streamer = false
 
static XLogRecPtr xlogendptr
 
static int has_xlogendptr = 0
 
static PQExpBuffer recoveryconfcontents = NULL
 

Macro Definition Documentation

◆ MINIMUM_VERSION_FOR_PG_WAL

#define MINIMUM_VERSION_FOR_PG_WAL   100000

Definition at line 60 of file pg_basebackup.c.

Referenced by main(), and StartLogStreamer().

◆ MINIMUM_VERSION_FOR_TEMP_SLOTS

#define MINIMUM_VERSION_FOR_TEMP_SLOTS   100000

Definition at line 65 of file pg_basebackup.c.

Referenced by StartLogStreamer().

◆ VERBOSE_FILENAME_LENGTH

#define VERBOSE_FILENAME_LENGTH   35

Referenced by progress_report().

◆ WRITE_TAR_DATA

#define WRITE_TAR_DATA (   buf,
  sz 
)    writeTarData(tarfile, buf, sz, filename)

Definition at line 948 of file pg_basebackup.c.

Referenced by ReceiveTarFile().

Typedef Documentation

◆ TablespaceList

◆ TablespaceListCell

Enumeration Type Documentation

◆ IncludeWal

enum IncludeWal
Enumerator
NO_WAL 
FETCH_WAL 
STREAM_WAL 

Definition at line 70 of file pg_basebackup.c.

71 {
72  NO_WAL,
73  FETCH_WAL,
75 } IncludeWal;
IncludeWal
Definition: pg_basebackup.c:70

Function Documentation

◆ BaseBackup()

static void BaseBackup ( void  )
static

Definition at line 1726 of file pg_basebackup.c.

References _, _dosmaperr(), Assert, basedir, bgchild, bgpipe, CheckServerVersionForStreaming(), conn, destroyPQExpBuffer(), disconnect_and_exit(), do_sync, FALSE, fastcheckpoint, FETCH_WAL, format, found_tablespace_dirs, fsync_fname(), fsync_pgdata(), GenerateRecoveryConf(), get_tablespace_mapping(), has_xlogendptr, i, includewal, label, made_tablespace_dirs, MAXPGPATH, maxrate, MemSet, NO_WAL, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PQclear(), PQerrorMessage(), PQescapeStringConn(), PQfinish(), PQgetisnull(), PQgetResult(), PQgetvalue(), PQnfields(), PQntuples(), PQparameterStatus(), PQresultStatus(), PQsendQuery(), PQserverVersion(), progname, progress_report(), psprintf(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), RunIdentifySystem(), showprogress, StartLogStreamer(), status(), STREAM_WAL, strerror(), strlcpy(), tablespacecount, totaldone, totalsize, verbose, verify_dir_is_empty_or_create(), WEXITSTATUS, WIFEXITED, write, writerecoveryconf, and xlogendptr.

Referenced by main().

1727 {
1728  PGresult *res;
1729  char *sysidentifier;
1730  TimeLineID latesttli;
1731  TimeLineID starttli;
1732  char *basebkp;
1733  char escaped_label[MAXPGPATH];
1734  char *maxrate_clause = NULL;
1735  int i;
1736  char xlogstart[64];
1737  char xlogend[64];
1738  int minServerMajor,
1739  maxServerMajor;
1740  int serverVersion,
1741  serverMajor;
1742 
1743  Assert(conn != NULL);
1744 
1745  /*
1746  * Check server version. BASE_BACKUP command was introduced in 9.1, so we
1747  * can't work with servers older than 9.1.
1748  */
1749  minServerMajor = 901;
1750  maxServerMajor = PG_VERSION_NUM / 100;
1751  serverVersion = PQserverVersion(conn);
1752  serverMajor = serverVersion / 100;
1753  if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
1754  {
1755  const char *serverver = PQparameterStatus(conn, "server_version");
1756 
1757  fprintf(stderr, _("%s: incompatible server version %s\n"),
1758  progname, serverver ? serverver : "'unknown'");
1760  }
1761 
1762  /*
1763  * If WAL streaming was requested, also check that the server is new
1764  * enough for that.
1765  */
1767  {
1768  /*
1769  * Error message already written in CheckServerVersionForStreaming(),
1770  * but add a hint about using -X none.
1771  */
1772  fprintf(stderr, _("HINT: use -X none or -X fetch to disable log streaming\n"));
1774  }
1775 
1776  /*
1777  * Build contents of recovery.conf if requested
1778  */
1779  if (writerecoveryconf)
1781 
1782  /*
1783  * Run IDENTIFY_SYSTEM so we can get the timeline
1784  */
1785  if (!RunIdentifySystem(conn, &sysidentifier, &latesttli, NULL, NULL))
1787 
1788  /*
1789  * Start the actual backup
1790  */
1791  PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
1792 
1793  if (maxrate > 0)
1794  maxrate_clause = psprintf("MAX_RATE %u", maxrate);
1795 
1796  if (verbose)
1797  fprintf(stderr,
1798  _("%s: initiating base backup, waiting for checkpoint to complete\n"),
1799  progname);
1800 
1801  if (showprogress && !verbose)
1802  {
1803  fprintf(stderr, "waiting for checkpoint");
1804  if (isatty(fileno(stderr)))
1805  fprintf(stderr, "\r");
1806  else
1807  fprintf(stderr, "\n");
1808  }
1809 
1810  basebkp =
1811  psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s %s",
1812  escaped_label,
1813  showprogress ? "PROGRESS" : "",
1814  includewal == FETCH_WAL ? "WAL" : "",
1815  fastcheckpoint ? "FAST" : "",
1816  includewal == NO_WAL ? "" : "NOWAIT",
1817  maxrate_clause ? maxrate_clause : "",
1818  format == 't' ? "TABLESPACE_MAP" : "");
1819 
1820  if (PQsendQuery(conn, basebkp) == 0)
1821  {
1822  fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
1823  progname, "BASE_BACKUP", PQerrorMessage(conn));
1825  }
1826 
1827  /*
1828  * Get the starting WAL location
1829  */
1830  res = PQgetResult(conn);
1831  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1832  {
1833  fprintf(stderr, _("%s: could not initiate base backup: %s"),
1836  }
1837  if (PQntuples(res) != 1)
1838  {
1839  fprintf(stderr,
1840  _("%s: server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields\n"),
1841  progname, PQntuples(res), PQnfields(res), 1, 2);
1843  }
1844 
1845  strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
1846 
1847  if (verbose)
1848  fprintf(stderr, _("%s: checkpoint completed\n"), progname);
1849 
1850  /*
1851  * 9.3 and later sends the TLI of the starting point. With older servers,
1852  * assume it's the same as the latest timeline reported by
1853  * IDENTIFY_SYSTEM.
1854  */
1855  if (PQnfields(res) >= 2)
1856  starttli = atoi(PQgetvalue(res, 0, 1));
1857  else
1858  starttli = latesttli;
1859  PQclear(res);
1860  MemSet(xlogend, 0, sizeof(xlogend));
1861 
1862  if (verbose && includewal != NO_WAL)
1863  fprintf(stderr, _("%s: write-ahead log start point: %s on timeline %u\n"),
1864  progname, xlogstart, starttli);
1865 
1866  /*
1867  * Get the header
1868  */
1869  res = PQgetResult(conn);
1870  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1871  {
1872  fprintf(stderr, _("%s: could not get backup header: %s"),
1875  }
1876  if (PQntuples(res) < 1)
1877  {
1878  fprintf(stderr, _("%s: no data returned from server\n"), progname);
1880  }
1881 
1882  /*
1883  * Sum up the total size, for progress reporting
1884  */
1885  totalsize = totaldone = 0;
1886  tablespacecount = PQntuples(res);
1887  for (i = 0; i < PQntuples(res); i++)
1888  {
1889  totalsize += atol(PQgetvalue(res, i, 2));
1890 
1891  /*
1892  * Verify tablespace directories are empty. Don't bother with the
1893  * first once since it can be relocated, and it will be checked before
1894  * we do anything anyway.
1895  */
1896  if (format == 'p' && !PQgetisnull(res, i, 1))
1897  {
1898  char *path = (char *) get_tablespace_mapping(PQgetvalue(res, i, 1));
1899 
1901  }
1902  }
1903 
1904  /*
1905  * When writing to stdout, require a single tablespace
1906  */
1907  if (format == 't' && strcmp(basedir, "-") == 0 && PQntuples(res) > 1)
1908  {
1909  fprintf(stderr,
1910  _("%s: can only write single tablespace to stdout, database has %d\n"),
1911  progname, PQntuples(res));
1913  }
1914 
1915  /*
1916  * If we're streaming WAL, start the streaming session before we start
1917  * receiving the actual data chunks.
1918  */
1919  if (includewal == STREAM_WAL)
1920  {
1921  if (verbose)
1922  fprintf(stderr, _("%s: starting background WAL receiver\n"),
1923  progname);
1924  StartLogStreamer(xlogstart, starttli, sysidentifier);
1925  }
1926 
1927  /*
1928  * Start receiving chunks
1929  */
1930  for (i = 0; i < PQntuples(res); i++)
1931  {
1932  if (format == 't')
1933  ReceiveTarFile(conn, res, i);
1934  else
1935  ReceiveAndUnpackTarFile(conn, res, i);
1936  } /* Loop over all tablespaces */
1937 
1938  if (showprogress)
1939  {
1940  progress_report(PQntuples(res), NULL, true);
1941  if (isatty(fileno(stderr)))
1942  fprintf(stderr, "\n"); /* Need to move to next line */
1943  }
1944 
1945  PQclear(res);
1946 
1947  /*
1948  * Get the stop position
1949  */
1950  res = PQgetResult(conn);
1951  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1952  {
1953  fprintf(stderr,
1954  _("%s: could not get write-ahead log end position from server: %s"),
1957  }
1958  if (PQntuples(res) != 1)
1959  {
1960  fprintf(stderr,
1961  _("%s: no write-ahead log end position returned from server\n"),
1962  progname);
1964  }
1965  strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
1966  if (verbose && includewal != NO_WAL)
1967  fprintf(stderr, _("%s: write-ahead log end point: %s\n"), progname, xlogend);
1968  PQclear(res);
1969 
1970  res = PQgetResult(conn);
1971  if (PQresultStatus(res) != PGRES_COMMAND_OK)
1972  {
1973  fprintf(stderr, _("%s: final receive failed: %s"),
1976  }
1977 
1978  if (bgchild > 0)
1979  {
1980 #ifndef WIN32
1981  int status;
1982  int r;
1983 #else
1984  DWORD status;
1985 
1986  /*
1987  * get a pointer sized version of bgchild to avoid warnings about
1988  * casting to a different size on WIN64.
1989  */
1990  intptr_t bgchild_handle = bgchild;
1991  uint32 hi,
1992  lo;
1993 #endif
1994 
1995  if (verbose)
1996  fprintf(stderr,
1997  _("%s: waiting for background process to finish streaming ...\n"), progname);
1998 
1999 #ifndef WIN32
2000  if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
2001  {
2002  fprintf(stderr,
2003  _("%s: could not send command to background pipe: %s\n"),
2004  progname, strerror(errno));
2006  }
2007 
2008  /* Just wait for the background process to exit */
2009  r = waitpid(bgchild, &status, 0);
2010  if (r == -1)
2011  {
2012  fprintf(stderr, _("%s: could not wait for child process: %s\n"),
2013  progname, strerror(errno));
2015  }
2016  if (r != bgchild)
2017  {
2018  fprintf(stderr, _("%s: child %d died, expected %d\n"),
2019  progname, r, (int) bgchild);
2021  }
2022  if (!WIFEXITED(status))
2023  {
2024  fprintf(stderr, _("%s: child process did not exit normally\n"),
2025  progname);
2027  }
2028  if (WEXITSTATUS(status) != 0)
2029  {
2030  fprintf(stderr, _("%s: child process exited with error %d\n"),
2031  progname, WEXITSTATUS(status));
2033  }
2034  /* Exited normally, we're happy! */
2035 #else /* WIN32 */
2036 
2037  /*
2038  * On Windows, since we are in the same process, we can just store the
2039  * value directly in the variable, and then set the flag that says
2040  * it's there.
2041  */
2042  if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
2043  {
2044  fprintf(stderr,
2045  _("%s: could not parse write-ahead log location \"%s\"\n"),
2046  progname, xlogend);
2048  }
2049  xlogendptr = ((uint64) hi) << 32 | lo;
2050  InterlockedIncrement(&has_xlogendptr);
2051 
2052  /* First wait for the thread to exit */
2053  if (WaitForSingleObjectEx((HANDLE) bgchild_handle, INFINITE, FALSE) !=
2054  WAIT_OBJECT_0)
2055  {
2056  _dosmaperr(GetLastError());
2057  fprintf(stderr, _("%s: could not wait for child thread: %s\n"),
2058  progname, strerror(errno));
2060  }
2061  if (GetExitCodeThread((HANDLE) bgchild_handle, &status) == 0)
2062  {
2063  _dosmaperr(GetLastError());
2064  fprintf(stderr, _("%s: could not get child thread exit status: %s\n"),
2065  progname, strerror(errno));
2067  }
2068  if (status != 0)
2069  {
2070  fprintf(stderr, _("%s: child thread exited with error %u\n"),
2071  progname, (unsigned int) status);
2073  }
2074  /* Exited normally, we're happy */
2075 #endif
2076  }
2077 
2078  /* Free the recovery.conf contents */
2080 
2081  /*
2082  * End of copy data. Final result is already checked inside the loop.
2083  */
2084  PQclear(res);
2085  PQfinish(conn);
2086 
2087  /*
2088  * Make data persistent on disk once backup is completed. For tar format
2089  * once syncing the parent directory is fine, each tar file created per
2090  * tablespace has been already synced. In plain format, all the data of
2091  * the base directory is synced, taking into account all the tablespaces.
2092  * Errors are not considered fatal.
2093  */
2094  if (do_sync)
2095  {
2096  if (format == 't')
2097  {
2098  if (strcmp(basedir, "-") != 0)
2099  (void) fsync_fname(basedir, true, progname);
2100  }
2101  else
2102  {
2103  (void) fsync_pgdata(basedir, progname, serverVersion);
2104  }
2105  }
2106 
2107  if (verbose)
2108  fprintf(stderr, _("%s: base backup completed\n"), progname);
2109 }
int PQnfields(const PGresult *res)
Definition: fe-exec.c:2732
static PQExpBuffer recoveryconfcontents
static IncludeWal includewal
Definition: pg_basebackup.c:87
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6106
static int bgpipe[2]
void fsync_pgdata(const char *pg_data, const char *progname, int serverVersion)
Definition: file_utils.c:58
uint32 TimeLineID
Definition: xlogdefs.h:45
static bool found_tablespace_dirs
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
Definition: fe-connect.c:6071
#define write(a, b, c)
Definition: win32.h:14
#define FALSE
Definition: ecpglib.h:39
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:581
static int tablespacecount
void _dosmaperr(unsigned long)
Definition: win32error.c:171
bool RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli, XLogRecPtr *startpos, char **db_name)
Definition: streamutil.c:316
static bool writerecoveryconf
Definition: pg_basebackup.c:89
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
#define MemSet(start, val, len)
Definition: c.h:863
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6096
const char * progname
Definition: pg_standby.c:37
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
static void GenerateRecoveryConf(PGconn *conn)
static char * basedir
Definition: pg_basebackup.c:78
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
int PQsendQuery(PGconn *conn, const char *query)
Definition: fe-exec.c:1183
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
PGconn * conn
Definition: streamutil.c:46
#define MAXPGPATH
static uint64 totaldone
static int32 maxrate
Definition: pg_basebackup.c:93
static int has_xlogendptr
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition: fe-exec.c:3365
unsigned int uint32
Definition: c.h:306
static uint64 totalsize
static const char * get_tablespace_mapping(const char *dir)
static void progress_report(int tablespacenum, const char *filename, bool force)
static int verbose
Definition: pg_basebackup.c:85
static bool showprogress
Definition: pg_basebackup.c:84
#define WIFEXITED(w)
Definition: win32_port.h:147
static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
static char * label
Definition: pg_basebackup.c:82
static void StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
void PQclear(PGresult *res)
Definition: fe-exec.c:671
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:680
static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
static XLogRecPtr xlogendptr
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static bool fastcheckpoint
Definition: pg_basebackup.c:88
static bool made_tablespace_dirs
static pid_t bgchild
int i
const char * strerror(int errnum)
Definition: strerror.c:19
static bool do_sync
Definition: pg_basebackup.c:90
static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
static char format
Definition: pg_basebackup.c:81
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3143
#define _(x)
Definition: elog.c:84
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753
bool CheckServerVersionForStreaming(PGconn *conn)
Definition: receivelog.c:367
#define WEXITSTATUS(w)
Definition: win32_port.h:149

◆ cleanup_directories_atexit()

static void cleanup_directories_atexit ( void  )
static

Definition at line 153 of file pg_basebackup.c.

References _, basedir, found_existing_pgdata, found_existing_xlogdir, found_tablespace_dirs, in_log_streamer, made_new_pgdata, made_new_xlogdir, made_tablespace_dirs, noclean, progname, rmtree(), success, and xlog_dir.

Referenced by main().

154 {
155  if (success || in_log_streamer)
156  return;
157 
158  if (!noclean)
159  {
160  if (made_new_pgdata)
161  {
162  fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
163  progname, basedir);
164  if (!rmtree(basedir, true))
165  fprintf(stderr, _("%s: failed to remove data directory\n"),
166  progname);
167  }
168  else if (found_existing_pgdata)
169  {
170  fprintf(stderr,
171  _("%s: removing contents of data directory \"%s\"\n"),
172  progname, basedir);
173  if (!rmtree(basedir, false))
174  fprintf(stderr, _("%s: failed to remove contents of data directory\n"),
175  progname);
176  }
177 
178  if (made_new_xlogdir)
179  {
180  fprintf(stderr, _("%s: removing WAL directory \"%s\"\n"),
181  progname, xlog_dir);
182  if (!rmtree(xlog_dir, true))
183  fprintf(stderr, _("%s: failed to remove WAL directory\n"),
184  progname);
185  }
186  else if (found_existing_xlogdir)
187  {
188  fprintf(stderr,
189  _("%s: removing contents of WAL directory \"%s\"\n"),
190  progname, xlog_dir);
191  if (!rmtree(xlog_dir, false))
192  fprintf(stderr, _("%s: failed to remove contents of WAL directory\n"),
193  progname);
194  }
195  }
196  else
197  {
199  fprintf(stderr,
200  _("%s: data directory \"%s\" not removed at user's request\n"),
201  progname, basedir);
202 
204  fprintf(stderr,
205  _("%s: WAL directory \"%s\" not removed at user's request\n"),
206  progname, xlog_dir);
207  }
208 
210  fprintf(stderr,
211  _("%s: changes to tablespace directories will not be undone\n"),
212  progname);
213 }
static bool found_existing_pgdata
static bool found_tablespace_dirs
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
static bool found_existing_xlogdir
static bool success
Definition: pg_basebackup.c:99
static bool made_new_pgdata
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:36
static bool in_log_streamer
static char * xlog_dir
Definition: pg_basebackup.c:80
static bool made_new_xlogdir
static bool made_tablespace_dirs
#define _(x)
Definition: elog.c:84
static bool noclean
Definition: pg_basebackup.c:83

◆ disconnect_and_exit()

static void disconnect_and_exit ( int  code)
static

Definition at line 216 of file pg_basebackup.c.

References bgchild, conn, kill, and PQfinish().

Referenced by BaseBackup(), GenerateRecoveryConf(), main(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), StartLogStreamer(), verify_dir_is_empty_or_create(), WriteRecoveryConf(), and writeTarData().

217 {
218  if (conn != NULL)
219  PQfinish(conn);
220 
221 #ifndef WIN32
222 
223  /*
224  * On windows, our background thread dies along with the process. But on
225  * Unix, if we have started a subprocess, we want to kill it off so it
226  * doesn't remain running trying to stream data.
227  */
228  if (bgchild > 0)
229  kill(bgchild, SIGTERM);
230 #endif
231 
232  exit(code);
233 }
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
#define kill(pid, sig)
Definition: win32_port.h:437
PGconn * conn
Definition: streamutil.c:46
static pid_t bgchild

◆ escape_quotes()

static char* escape_quotes ( const char *  src)
static

Definition at line 1598 of file pg_basebackup.c.

References _, escape_single_quotes_ascii(), and progname.

Referenced by bootstrap_template1(), GenerateRecoveryConf(), setup_auth(), setup_config(), setup_description(), setup_privileges(), and setup_schema().

1599 {
1600  char *result = escape_single_quotes_ascii(src);
1601 
1602  if (!result)
1603  {
1604  fprintf(stderr, _("%s: out of memory\n"), progname);
1605  exit(1);
1606  }
1607  return result;
1608 }
const char * progname
Definition: pg_standby.c:37
char * escape_single_quotes_ascii(const char *src)
Definition: quotes.c:33
#define _(x)
Definition: elog.c:84

◆ GenerateRecoveryConf()

static void GenerateRecoveryConf ( PGconn conn)
static

Definition at line 1614 of file pg_basebackup.c.

References _, appendConnStrVal(), appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), createPQExpBuffer(), PQExpBufferData::data, disconnect_and_exit(), escape_quotes(), free, initPQExpBuffer(), _PQconninfoOption::keyword, PQExpBufferData::len, PQconninfo(), PQconninfoFree(), PQExpBufferBroken, PQExpBufferDataBroken, progname, replication_slot, termPQExpBuffer(), and _PQconninfoOption::val.

Referenced by BaseBackup().

1615 {
1616  PQconninfoOption *connOptions;
1618  PQExpBufferData conninfo_buf;
1619  char *escaped;
1620 
1622  if (!recoveryconfcontents)
1623  {
1624  fprintf(stderr, _("%s: out of memory\n"), progname);
1626  }
1627 
1628  connOptions = PQconninfo(conn);
1629  if (connOptions == NULL)
1630  {
1631  fprintf(stderr, _("%s: out of memory\n"), progname);
1633  }
1634 
1635  appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");
1636 
1637  initPQExpBuffer(&conninfo_buf);
1638  for (option = connOptions; option && option->keyword; option++)
1639  {
1640  /*
1641  * Do not emit this setting if: - the setting is "replication",
1642  * "dbname" or "fallback_application_name", since these would be
1643  * overridden by the libpqwalreceiver module anyway. - not set or
1644  * empty.
1645  */
1646  if (strcmp(option->keyword, "replication") == 0 ||
1647  strcmp(option->keyword, "dbname") == 0 ||
1648  strcmp(option->keyword, "fallback_application_name") == 0 ||
1649  (option->val == NULL) ||
1650  (option->val != NULL && option->val[0] == '\0'))
1651  continue;
1652 
1653  /* Separate key-value pairs with spaces */
1654  if (conninfo_buf.len != 0)
1655  appendPQExpBufferChar(&conninfo_buf, ' ');
1656 
1657  /*
1658  * Write "keyword=value" pieces, the value string is escaped and/or
1659  * quoted if necessary.
1660  */
1661  appendPQExpBuffer(&conninfo_buf, "%s=", option->keyword);
1662  appendConnStrVal(&conninfo_buf, option->val);
1663  }
1664 
1665  /*
1666  * Escape the connection string, so that it can be put in the config file.
1667  * Note that this is different from the escaping of individual connection
1668  * options above!
1669  */
1670  escaped = escape_quotes(conninfo_buf.data);
1671  appendPQExpBuffer(recoveryconfcontents, "primary_conninfo = '%s'\n", escaped);
1672  free(escaped);
1673 
1674  if (replication_slot)
1675  {
1676  escaped = escape_quotes(replication_slot);
1677  appendPQExpBuffer(recoveryconfcontents, "primary_slot_name = '%s'\n", replication_slot);
1678  free(escaped);
1679  }
1680 
1682  PQExpBufferDataBroken(conninfo_buf))
1683  {
1684  fprintf(stderr, _("%s: out of memory\n"), progname);
1686  }
1687 
1688  termPQExpBuffer(&conninfo_buf);
1689 
1690  PQconninfoFree(connOptions);
1691 }
static PQExpBuffer recoveryconfcontents
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:551
static char * escape_quotes(const char *src)
const char * progname
Definition: pg_standby.c:37
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:5956
PQconninfoOption * PQconninfo(PGconn *conn)
Definition: fe-connect.c:5915
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
#define free(a)
Definition: header.h:65
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static char * replication_slot
Definition: pg_basebackup.c:94
#define _(x)
Definition: elog.c:84
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89

◆ get_tablespace_mapping()

static const char * get_tablespace_mapping ( const char *  dir)
static

Definition at line 1311 of file pg_basebackup.c.

References canonicalize_path(), TablespaceList::head, MAXPGPATH, TablespaceListCell::new_dir, TablespaceListCell::next, TablespaceListCell::old_dir, and strlcpy().

Referenced by BaseBackup(), and ReceiveAndUnpackTarFile().

1312 {
1313  TablespaceListCell *cell;
1314  char canon_dir[MAXPGPATH];
1315 
1316  /* Canonicalize path for comparison consistency */
1317  strlcpy(canon_dir, dir, sizeof(canon_dir));
1318  canonicalize_path(canon_dir);
1319 
1320  for (cell = tablespace_dirs.head; cell; cell = cell->next)
1321  if (strcmp(canon_dir, cell->old_dir) == 0)
1322  return cell->new_dir;
1323 
1324  return dir;
1325 }
static TablespaceList tablespace_dirs
Definition: pg_basebackup.c:79
char old_dir[MAXPGPATH]
Definition: pg_basebackup.c:46
void canonicalize_path(char *path)
Definition: path.c:254
char new_dir[MAXPGPATH]
Definition: pg_basebackup.c:47
#define MAXPGPATH
struct TablespaceListCell * next
Definition: pg_basebackup.c:45
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
TablespaceListCell * head
Definition: pg_basebackup.c:52

◆ LogStreamerMain()

static int LogStreamerMain ( logstreamer_param param)
static

Definition at line 480 of file pg_basebackup.c.

References _, logstreamer_param::bgconn, bgpipe, compresslevel, CreateWalDirectoryMethod(), CreateWalTarMethod(), StreamCtl::do_sync, do_sync, WalWriteMethod::finish, format, FreeWalDirectoryMethod(), FreeWalTarMethod(), in_log_streamer, StreamCtl::mark_done, MemSet, StreamCtl::partial_suffix, pg_free(), PGINVALID_SOCKET, PQfinish(), progname, reached_end_position(), ReceiveXlogStream(), StreamCtl::replication_slot, replication_slot, StreamCtl::standby_message_timeout, standby_message_timeout, StreamCtl::startpos, logstreamer_param::startptr, StreamCtl::stop_socket, StreamCtl::stream_stop, strerror(), StreamCtl::synchronous, StreamCtl::sysidentifier, logstreamer_param::sysidentifier, StreamCtl::timeline, logstreamer_param::timeline, StreamCtl::walmethod, and logstreamer_param::xlog.

Referenced by StartLogStreamer().

481 {
482  StreamCtl stream;
483 
484  in_log_streamer = true;
485 
486  MemSet(&stream, 0, sizeof(stream));
487  stream.startpos = param->startptr;
488  stream.timeline = param->timeline;
489  stream.sysidentifier = param->sysidentifier;
491 #ifndef WIN32
492  stream.stop_socket = bgpipe[0];
493 #else
494  stream.stop_socket = PGINVALID_SOCKET;
495 #endif
497  stream.synchronous = false;
498  stream.do_sync = do_sync;
499  stream.mark_done = true;
500  stream.partial_suffix = NULL;
502 
503  if (format == 'p')
504  stream.walmethod = CreateWalDirectoryMethod(param->xlog, 0, do_sync);
505  else
507 
508  if (!ReceiveXlogStream(param->bgconn, &stream))
509 
510  /*
511  * Any errors will already have been reported in the function process,
512  * but we need to tell the parent that we didn't shutdown in a nice
513  * way.
514  */
515  return 1;
516 
517  if (!stream.walmethod->finish())
518  {
519  fprintf(stderr,
520  _("%s: could not finish writing WAL files: %s\n"),
521  progname, strerror(errno));
522  return 1;
523  }
524 
525  PQfinish(param->bgconn);
526 
527  if (format == 'p')
529  else
531  pg_free(stream.walmethod);
532 
533  return 0;
534 }
static int bgpipe[2]
bool do_sync
Definition: receivelog.h:39
char * sysidentifier
Definition: receivelog.h:34
void PQfinish(PGconn *conn)
Definition: fe-connect.c:3629
static int compresslevel
Definition: pg_basebackup.c:86
#define MemSet(start, val, len)
Definition: c.h:863
XLogRecPtr startpos
Definition: receivelog.h:32
char * partial_suffix
Definition: receivelog.h:48
const char * progname
Definition: pg_standby.c:37
static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline, bool segment_finished)
TimeLineID timeline
Definition: receivelog.h:33
WalWriteMethod * CreateWalDirectoryMethod(const char *basedir, int compression, bool sync)
Definition: walmethods.c:346
char * replication_slot
Definition: receivelog.h:49
bool mark_done
Definition: receivelog.h:38
XLogRecPtr startptr
stream_stop_callback stream_stop
Definition: receivelog.h:42
WalWriteMethod * walmethod
Definition: receivelog.h:47
static int standby_message_timeout
Definition: pg_basebackup.c:91
void FreeWalTarMethod(void)
Definition: walmethods.c:978
#define PGINVALID_SOCKET
Definition: port.h:33
static bool in_log_streamer
WalWriteMethod * CreateWalTarMethod(const char *tarbase, int compression, bool sync)
Definition: walmethods.c:947
bool ReceiveXlogStream(PGconn *conn, StreamCtl *stream)
Definition: receivelog.c:447
bool synchronous
Definition: receivelog.h:37
void pg_free(void *ptr)
Definition: fe_memutils.c:105
bool(* finish)(void)
Definition: walmethods.h:75
pgsocket stop_socket
Definition: receivelog.h:44
const char * strerror(int errnum)
Definition: strerror.c:19
int standby_message_timeout
Definition: receivelog.h:36
static bool do_sync
Definition: pg_basebackup.c:90
static char format
Definition: pg_basebackup.c:81
static char * replication_slot
Definition: pg_basebackup.c:94
#define _(x)
Definition: elog.c:84
void FreeWalDirectoryMethod(void)
Definition: walmethods.c:370
char xlog[MAXPGPATH]

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 2113 of file pg_basebackup.c.

References _, BaseBackup(), basedir, canonicalize_path(), cleanup_directories_atexit(), compresslevel, conn, connection_string, create_slot, dbgetpassword, dbhost, dbport, dbuser, disconnect_and_exit(), do_sync, fastcheckpoint, FETCH_WAL, format, found_existing_pgdata, found_existing_xlogdir, free, get_progname(), GetConnection(), getopt_long(), includewal, is_absolute_path, label, made_new_pgdata, made_new_xlogdir, maxrate, MINIMUM_VERSION_FOR_PG_WAL, no_argument, no_slot, NO_WAL, noclean, optarg, optind, parse_max_rate(), pg_strcasecmp(), pg_strdup(), PG_TEXTDOMAIN, PQserverVersion(), progname, psprintf(), replication_slot, required_argument, RetrieveWalSegSize(), set_pglocale_pgservice(), showprogress, standby_message_timeout, STREAM_WAL, strerror(), success, symlink, tablespace_list_append(), temp_replication_slot, usage(), verbose, verify_dir_is_empty_or_create(), writerecoveryconf, xlog_dir, and Z_DEFAULT_COMPRESSION.

2114 {
2115  static struct option long_options[] = {
2116  {"help", no_argument, NULL, '?'},
2117  {"version", no_argument, NULL, 'V'},
2118  {"pgdata", required_argument, NULL, 'D'},
2119  {"format", required_argument, NULL, 'F'},
2120  {"checkpoint", required_argument, NULL, 'c'},
2121  {"create-slot", no_argument, NULL, 'C'},
2122  {"max-rate", required_argument, NULL, 'r'},
2123  {"write-recovery-conf", no_argument, NULL, 'R'},
2124  {"slot", required_argument, NULL, 'S'},
2125  {"tablespace-mapping", required_argument, NULL, 'T'},
2126  {"wal-method", required_argument, NULL, 'X'},
2127  {"gzip", no_argument, NULL, 'z'},
2128  {"compress", required_argument, NULL, 'Z'},
2129  {"label", required_argument, NULL, 'l'},
2130  {"no-clean", no_argument, NULL, 'n'},
2131  {"no-sync", no_argument, NULL, 'N'},
2132  {"dbname", required_argument, NULL, 'd'},
2133  {"host", required_argument, NULL, 'h'},
2134  {"port", required_argument, NULL, 'p'},
2135  {"username", required_argument, NULL, 'U'},
2136  {"no-password", no_argument, NULL, 'w'},
2137  {"password", no_argument, NULL, 'W'},
2138  {"status-interval", required_argument, NULL, 's'},
2139  {"verbose", no_argument, NULL, 'v'},
2140  {"progress", no_argument, NULL, 'P'},
2141  {"waldir", required_argument, NULL, 1},
2142  {"no-slot", no_argument, NULL, 2},
2143  {NULL, 0, NULL, 0}
2144  };
2145  int c;
2146 
2147  int option_index;
2148 
2149  progname = get_progname(argv[0]);
2150  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
2151 
2152  if (argc > 1)
2153  {
2154  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2155  {
2156  usage();
2157  exit(0);
2158  }
2159  else if (strcmp(argv[1], "-V") == 0
2160  || strcmp(argv[1], "--version") == 0)
2161  {
2162  puts("pg_basebackup (PostgreSQL) " PG_VERSION);
2163  exit(0);
2164  }
2165  }
2166 
2168 
2169  while ((c = getopt_long(argc, argv, "CD:F:r:RS:T:X:l:nNzZ:d:c:h:p:U:s:wWvP",
2170  long_options, &option_index)) != -1)
2171  {
2172  switch (c)
2173  {
2174  case 'C':
2175  create_slot = true;
2176  break;
2177  case 'D':
2179  break;
2180  case 'F':
2181  if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0)
2182  format = 'p';
2183  else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0)
2184  format = 't';
2185  else
2186  {
2187  fprintf(stderr,
2188  _("%s: invalid output format \"%s\", must be \"plain\" or \"tar\"\n"),
2189  progname, optarg);
2190  exit(1);
2191  }
2192  break;
2193  case 'r':
2195  break;
2196  case 'R':
2197  writerecoveryconf = true;
2198  break;
2199  case 'S':
2200 
2201  /*
2202  * When specifying replication slot name, use a permanent
2203  * slot.
2204  */
2206  temp_replication_slot = false;
2207  break;
2208  case 2:
2209  no_slot = true;
2210  break;
2211  case 'T':
2213  break;
2214  case 'X':
2215  if (strcmp(optarg, "n") == 0 ||
2216  strcmp(optarg, "none") == 0)
2217  {
2218  includewal = NO_WAL;
2219  }
2220  else if (strcmp(optarg, "f") == 0 ||
2221  strcmp(optarg, "fetch") == 0)
2222  {
2224  }
2225  else if (strcmp(optarg, "s") == 0 ||
2226  strcmp(optarg, "stream") == 0)
2227  {
2229  }
2230  else
2231  {
2232  fprintf(stderr,
2233  _("%s: invalid wal-method option \"%s\", must be \"fetch\", \"stream\", or \"none\"\n"),
2234  progname, optarg);
2235  exit(1);
2236  }
2237  break;
2238  case 1:
2240  break;
2241  case 'l':
2242  label = pg_strdup(optarg);
2243  break;
2244  case 'n':
2245  noclean = true;
2246  break;
2247  case 'N':
2248  do_sync = false;
2249  break;
2250  case 'z':
2251 #ifdef HAVE_LIBZ
2253 #else
2254  compresslevel = 1; /* will be rejected below */
2255 #endif
2256  break;
2257  case 'Z':
2258  compresslevel = atoi(optarg);
2259  if (compresslevel < 0 || compresslevel > 9)
2260  {
2261  fprintf(stderr, _("%s: invalid compression level \"%s\"\n"),
2262  progname, optarg);
2263  exit(1);
2264  }
2265  break;
2266  case 'c':
2267  if (pg_strcasecmp(optarg, "fast") == 0)
2268  fastcheckpoint = true;
2269  else if (pg_strcasecmp(optarg, "spread") == 0)
2270  fastcheckpoint = false;
2271  else
2272  {
2273  fprintf(stderr, _("%s: invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"\n"),
2274  progname, optarg);
2275  exit(1);
2276  }
2277  break;
2278  case 'd':
2280  break;
2281  case 'h':
2282  dbhost = pg_strdup(optarg);
2283  break;
2284  case 'p':
2285  dbport = pg_strdup(optarg);
2286  break;
2287  case 'U':
2288  dbuser = pg_strdup(optarg);
2289  break;
2290  case 'w':
2291  dbgetpassword = -1;
2292  break;
2293  case 'W':
2294  dbgetpassword = 1;
2295  break;
2296  case 's':
2297  standby_message_timeout = atoi(optarg) * 1000;
2298  if (standby_message_timeout < 0)
2299  {
2300  fprintf(stderr, _("%s: invalid status interval \"%s\"\n"),
2301  progname, optarg);
2302  exit(1);
2303  }
2304  break;
2305  case 'v':
2306  verbose++;
2307  break;
2308  case 'P':
2309  showprogress = true;
2310  break;
2311  default:
2312 
2313  /*
2314  * getopt_long already emitted a complaint
2315  */
2316  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2317  progname);
2318  exit(1);
2319  }
2320  }
2321 
2322  /*
2323  * Any non-option arguments?
2324  */
2325  if (optind < argc)
2326  {
2327  fprintf(stderr,
2328  _("%s: too many command-line arguments (first is \"%s\")\n"),
2329  progname, argv[optind]);
2330  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2331  progname);
2332  exit(1);
2333  }
2334 
2335  /*
2336  * Required arguments
2337  */
2338  if (basedir == NULL)
2339  {
2340  fprintf(stderr, _("%s: no target directory specified\n"), progname);
2341  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2342  progname);
2343  exit(1);
2344  }
2345 
2346  /*
2347  * Mutually exclusive arguments
2348  */
2349  if (format == 'p' && compresslevel != 0)
2350  {
2351  fprintf(stderr,
2352  _("%s: only tar mode backups can be compressed\n"),
2353  progname);
2354  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2355  progname);
2356  exit(1);
2357  }
2358 
2359  if (format == 't' && includewal == STREAM_WAL && strcmp(basedir, "-") == 0)
2360  {
2361  fprintf(stderr,
2362  _("%s: cannot stream write-ahead logs in tar mode to stdout\n"),
2363  progname);
2364  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2365  progname);
2366  exit(1);
2367  }
2368 
2370  {
2371  fprintf(stderr,
2372  _("%s: replication slots can only be used with WAL streaming\n"),
2373  progname);
2374  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2375  progname);
2376  exit(1);
2377  }
2378 
2379  if (no_slot)
2380  {
2381  if (replication_slot)
2382  {
2383  fprintf(stderr,
2384  _("%s: --no-slot cannot be used with slot name\n"),
2385  progname);
2386  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2387  progname);
2388  exit(1);
2389  }
2390  temp_replication_slot = false;
2391  }
2392 
2393  if (create_slot)
2394  {
2395  if (!replication_slot)
2396  {
2397  fprintf(stderr,
2398  _("%s: --create-slot needs a slot to be specified using --slot\n"),
2399  progname);
2400  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2401  progname);
2402  exit(1);
2403  }
2404 
2405  if (no_slot)
2406  {
2407  fprintf(stderr,
2408  _("%s: --create-slot and --no-slot are incompatible options\n"),
2409  progname);
2410  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2411  progname);
2412  exit(1);
2413  }
2414  }
2415 
2416  if (xlog_dir)
2417  {
2418  if (format != 'p')
2419  {
2420  fprintf(stderr,
2421  _("%s: WAL directory location can only be specified in plain mode\n"),
2422  progname);
2423  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2424  progname);
2425  exit(1);
2426  }
2427 
2428  /* clean up xlog directory name, check it's absolute */
2430  if (!is_absolute_path(xlog_dir))
2431  {
2432  fprintf(stderr, _("%s: WAL directory location must be "
2433  "an absolute path\n"), progname);
2434  fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2435  progname);
2436  exit(1);
2437  }
2438  }
2439 
2440 #ifndef HAVE_LIBZ
2441  if (compresslevel != 0)
2442  {
2443  fprintf(stderr,
2444  _("%s: this build does not support compression\n"),
2445  progname);
2446  exit(1);
2447  }
2448 #endif
2449 
2450  /*
2451  * Verify that the target directory exists, or create it. For plaintext
2452  * backups, always require the directory. For tar backups, require it
2453  * unless we are writing to stdout.
2454  */
2455  if (format == 'p' || strcmp(basedir, "-") != 0)
2457 
2458  /* connection in replication mode to server */
2459  conn = GetConnection();
2460  if (!conn)
2461  {
2462  /* Error message already written in GetConnection() */
2463  exit(1);
2464  }
2465 
2466  /* determine remote server's xlog segment size */
2467  if (!RetrieveWalSegSize(conn))
2469 
2470  /* Create pg_wal symlink, if required */
2471  if (xlog_dir)
2472  {
2473  char *linkloc;
2474 
2476 
2477  /*
2478  * Form name of the place where the symlink must go. pg_xlog has been
2479  * renamed to pg_wal in post-10 clusters.
2480  */
2481  linkloc = psprintf("%s/%s", basedir,
2483  "pg_xlog" : "pg_wal");
2484 
2485 #ifdef HAVE_SYMLINK
2486  if (symlink(xlog_dir, linkloc) != 0)
2487  {
2488  fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
2489  progname, linkloc, strerror(errno));
2491  }
2492 #else
2493  fprintf(stderr, _("%s: symlinks are not supported on this platform\n"));
2495 #endif
2496  free(linkloc);
2497  }
2498 
2499  BaseBackup();
2500 
2501  success = true;
2502  return 0;
2503 }
static IncludeWal includewal
Definition: pg_basebackup.c:87
#define Z_DEFAULT_COMPRESSION
static bool found_existing_pgdata
static void usage(void)
const char * get_progname(const char *argv0)
Definition: path.c:453
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
static int32 parse_max_rate(char *src)
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void canonicalize_path(char *path)
Definition: path.c:254
static bool writerecoveryconf
Definition: pg_basebackup.c:89
static bool create_slot
Definition: pg_basebackup.c:96
static int compresslevel
Definition: pg_basebackup.c:86
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6096
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
static void BaseBackup(void)
#define required_argument
Definition: getopt_long.h:25
int optind
Definition: getopt.c:51
char * connection_string
Definition: streamutil.c:38
bool RetrieveWalSegSize(PGconn *conn)
Definition: streamutil.c:242
PGconn * conn
Definition: streamutil.c:46
#define MINIMUM_VERSION_FOR_PG_WAL
Definition: pg_basebackup.c:60
static bool found_existing_xlogdir
static bool success
Definition: pg_basebackup.c:99
static int32 maxrate
Definition: pg_basebackup.c:93
char * c
#define symlink(oldpath, newpath)
Definition: win32_port.h:232
static bool made_new_pgdata
#define is_absolute_path(filename)
Definition: port.h:86
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static int verbose
Definition: pg_basebackup.c:85
static int standby_message_timeout
Definition: pg_basebackup.c:91
static bool showprogress
Definition: pg_basebackup.c:84
int dbgetpassword
Definition: streamutil.c:43
#define no_argument
Definition: getopt_long.h:24
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1009
static bool temp_replication_slot
Definition: pg_basebackup.c:95
static char * label
Definition: pg_basebackup.c:82
char * dbport
Definition: streamutil.c:41
static void cleanup_directories_atexit(void)
#define free(a)
Definition: header.h:65
PGconn * GetConnection(UserMapping *user, bool will_prep_stmt)
Definition: connection.c:107
char * dbhost
Definition: streamutil.c:39
static char * xlog_dir
Definition: pg_basebackup.c:80
static bool no_slot
Definition: pg_basebackup.c:97
static bool made_new_xlogdir
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static bool fastcheckpoint
Definition: pg_basebackup.c:88
static void tablespace_list_append(const char *arg)
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:550
char * dbuser
Definition: streamutil.c:40
char * optarg
Definition: getopt.c:53
const char * strerror(int errnum)
Definition: strerror.c:19
static bool do_sync
Definition: pg_basebackup.c:90
static void verify_dir_is_empty_or_create(char *dirname, bool *created, bool *found)
static char format
Definition: pg_basebackup.c:81
static char * replication_slot
Definition: pg_basebackup.c:94
#define _(x)
Definition: elog.c:84
static bool noclean
Definition: pg_basebackup.c:83

◆ parse_max_rate()

static int32 parse_max_rate ( char *  src)
static

Definition at line 821 of file pg_basebackup.c.

References _, MAX_RATE_UPPER, progname, and strerror().

Referenced by main().

822 {
823  double result;
824  char *after_num;
825  char *suffix = NULL;
826 
827  errno = 0;
828  result = strtod(src, &after_num);
829  if (src == after_num)
830  {
831  fprintf(stderr,
832  _("%s: transfer rate \"%s\" is not a valid value\n"),
833  progname, src);
834  exit(1);
835  }
836  if (errno != 0)
837  {
838  fprintf(stderr,
839  _("%s: invalid transfer rate \"%s\": %s\n"),
840  progname, src, strerror(errno));
841  exit(1);
842  }
843 
844  if (result <= 0)
845  {
846  /*
847  * Reject obviously wrong values here.
848  */
849  fprintf(stderr, _("%s: transfer rate must be greater than zero\n"),
850  progname);
851  exit(1);
852  }
853 
854  /*
855  * Evaluate suffix, after skipping over possible whitespace. Lack of
856  * suffix means kilobytes.
857  */
858  while (*after_num != '\0' && isspace((unsigned char) *after_num))
859  after_num++;
860 
861  if (*after_num != '\0')
862  {
863  suffix = after_num;
864  if (*after_num == 'k')
865  {
866  /* kilobyte is the expected unit. */
867  after_num++;
868  }
869  else if (*after_num == 'M')
870  {
871  after_num++;
872  result *= 1024.0;
873  }
874  }
875 
876  /* The rest can only consist of white space. */
877  while (*after_num != '\0' && isspace((unsigned char) *after_num))
878  after_num++;
879 
880  if (*after_num != '\0')
881  {
882  fprintf(stderr,
883  _("%s: invalid --max-rate unit: \"%s\"\n"),
884  progname, suffix);
885  exit(1);
886  }
887 
888  /* Valid integer? */
889  if ((uint64) result != (uint64) ((uint32) result))
890  {
891  fprintf(stderr,
892  _("%s: transfer rate \"%s\" exceeds integer range\n"),
893  progname, src);
894  exit(1);
895  }
896 
897  /*
898  * The range is checked on the server side too, but avoid the server
899  * connection if a nonsensical value was passed.
900  */
901  if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
902  {
903  fprintf(stderr,
904  _("%s: transfer rate \"%s\" is out of range\n"),
905  progname, src);
906  exit(1);
907  }
908 
909  return (int32) result;
910 }
const char * progname
Definition: pg_standby.c:37
signed int int32
Definition: c.h:294
#define MAX_RATE_UPPER
Definition: basebackup.h:21
unsigned int uint32
Definition: c.h:306
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

◆ progress_report()

static void progress_report ( int  tablespacenum,
const char *  filename,
bool  force 
)
static

Definition at line 732 of file pg_basebackup.c.

References INT64_FORMAT, last_progress_report, ngettext, now(), showprogress, snprintf(), tablespacecount, totaldone, totalsize, verbose, and VERBOSE_FILENAME_LENGTH.

Referenced by BaseBackup(), main(), ReceiveAndUnpackTarFile(), ReceiveTarFile(), and write_target_range().

733 {
734  int percent;
735  char totaldone_str[32];
736  char totalsize_str[32];
737  pg_time_t now;
738 
739  if (!showprogress)
740  return;
741 
742  now = time(NULL);
743  if (now == last_progress_report && !force)
744  return; /* Max once per second */
745 
747  percent = totalsize ? (int) ((totaldone / 1024) * 100 / totalsize) : 0;
748 
749  /*
750  * Avoid overflowing past 100% or the full size. This may make the total
751  * size number change as we approach the end of the backup (the estimate
752  * will always be wrong if WAL is included), but that's better than having
753  * the done column be bigger than the total.
754  */
755  if (percent > 100)
756  percent = 100;
757  if (totaldone / 1024 > totalsize)
758  totalsize = totaldone / 1024;
759 
760  /*
761  * Separate step to keep platform-dependent format code out of
762  * translatable strings. And we only test for INT64_FORMAT availability
763  * in snprintf, not fprintf.
764  */
765  snprintf(totaldone_str, sizeof(totaldone_str), INT64_FORMAT,
766  totaldone / 1024);
767  snprintf(totalsize_str, sizeof(totalsize_str), INT64_FORMAT, totalsize);
768 
769 #define VERBOSE_FILENAME_LENGTH 35
770  if (verbose)
771  {
772  if (!filename)
773 
774  /*
775  * No filename given, so clear the status line (used for last
776  * call)
777  */
778  fprintf(stderr,
779  ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
780  "%*s/%s kB (100%%), %d/%d tablespaces %*s",
782  (int) strlen(totalsize_str),
783  totaldone_str, totalsize_str,
784  tablespacenum, tablespacecount,
785  VERBOSE_FILENAME_LENGTH + 5, "");
786  else
787  {
788  bool truncate = (strlen(filename) > VERBOSE_FILENAME_LENGTH);
789 
790  fprintf(stderr,
791  ngettext("%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)",
792  "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)",
794  (int) strlen(totalsize_str),
795  totaldone_str, totalsize_str, percent,
796  tablespacenum, tablespacecount,
797  /* Prefix with "..." if we do leading truncation */
798  truncate ? "..." : "",
801  /* Truncate filename at beginning if it's too long */
802  truncate ? filename + strlen(filename) - VERBOSE_FILENAME_LENGTH + 3 : filename);
803  }
804  }
805  else
806  fprintf(stderr,
807  ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
808  "%*s/%s kB (%d%%), %d/%d tablespaces",
810  (int) strlen(totalsize_str),
811  totaldone_str, totalsize_str, percent,
812  tablespacenum, tablespacecount);
813 
814  if (isatty(fileno(stderr)))
815  fprintf(stderr, "\r");
816  else
817  fprintf(stderr, "\n");
818 }
int64 pg_time_t
Definition: pgtime.h:23
static pg_time_t last_progress_report
Definition: pg_basebackup.c:92
static int tablespacecount
#define VERBOSE_FILENAME_LENGTH
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static uint64 totaldone
static uint64 totalsize
static int verbose
Definition: pg_basebackup.c:85
static bool showprogress
Definition: pg_basebackup.c:84
#define ngettext(s, p, n)
Definition: c.h:977
#define INT64_FORMAT
Definition: c.h:348
static char * filename
Definition: pg_dumpall.c:90
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534

◆ reached_end_position()

static bool reached_end_position ( XLogRecPtr  segendpos,
uint32  timeline,
bool  segment_finished 
)
static

Definition at line 388 of file pg_basebackup.c.

References _, bgpipe, has_xlogendptr, MemSet, progname, read, select, strerror(), and xlogendptr.

Referenced by LogStreamerMain().

390 {
391  if (!has_xlogendptr)
392  {
393 #ifndef WIN32
394  fd_set fds;
395  struct timeval tv;
396  int r;
397 
398  /*
399  * Don't have the end pointer yet - check our pipe to see if it has
400  * been sent yet.
401  */
402  FD_ZERO(&fds);
403  FD_SET(bgpipe[0], &fds);
404 
405  MemSet(&tv, 0, sizeof(tv));
406 
407  r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
408  if (r == 1)
409  {
410  char xlogend[64];
411  uint32 hi,
412  lo;
413 
414  MemSet(xlogend, 0, sizeof(xlogend));
415  r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
416  if (r < 0)
417  {
418  fprintf(stderr, _("%s: could not read from ready pipe: %s\n"),
419  progname, strerror(errno));
420  exit(1);
421  }
422 
423  if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
424  {
425  fprintf(stderr,
426  _("%s: could not parse write-ahead log location \"%s\"\n"),
427  progname, xlogend);
428  exit(1);
429  }
430  xlogendptr = ((uint64) hi) << 32 | lo;
431  has_xlogendptr = 1;
432 
433  /*
434  * Fall through to check if we've reached the point further
435  * already.
436  */
437  }
438  else
439  {
440  /*
441  * No data received on the pipe means we don't know the end
442  * position yet - so just say it's not time to stop yet.
443  */
444  return false;
445  }
446 #else
447 
448  /*
449  * On win32, has_xlogendptr is set by the main thread, so if it's not
450  * set here, we just go back and wait until it shows up.
451  */
452  return false;
453 #endif
454  }
455 
456  /*
457  * At this point we have an end pointer, so compare it to the current
458  * position to figure out if it's time to stop.
459  */
460  if (segendpos >= xlogendptr)
461  return true;
462 
463  /*
464  * Have end pointer, but haven't reached it yet - so tell the caller to
465  * keep streaming.
466  */
467  return false;
468 }
static int bgpipe[2]
#define MemSet(start, val, len)
Definition: c.h:863
const char * progname
Definition: pg_standby.c:37
static int has_xlogendptr
#define select(n, r, w, e, timeout)
Definition: win32_port.h:447
unsigned int uint32
Definition: c.h:306
static XLogRecPtr xlogendptr
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84
#define read(a, b, c)
Definition: win32.h:13

◆ ReceiveAndUnpackTarFile()

static void ReceiveAndUnpackTarFile ( PGconn conn,
PGresult res,
int  rownum 
)
static

Definition at line 1338 of file pg_basebackup.c.

References _, basedir, copybuf, disconnect_and_exit(), filename, get_tablespace_mapping(), MAXPGPATH, mkdir, pg_str_endswith(), pgoff_t, PGRES_COPY_OUT, PQerrorMessage(), PQfreemem(), PQgetCopyData(), PQgetisnull(), PQgetResult(), PQgetvalue(), PQresultStatus(), progname, progress_report(), read_tar_number(), S_IRWXU, snprintf(), strerror(), strlcpy(), symlink, totaldone, writerecoveryconf, and WriteRecoveryConf().

Referenced by BaseBackup().

1339 {
1340  char current_path[MAXPGPATH];
1341  char filename[MAXPGPATH];
1342  const char *mapped_tblspc_path;
1343  pgoff_t current_len_left = 0;
1344  int current_padding = 0;
1345  bool basetablespace;
1346  char *copybuf = NULL;
1347  FILE *file = NULL;
1348 
1349  basetablespace = PQgetisnull(res, rownum, 0);
1350  if (basetablespace)
1351  strlcpy(current_path, basedir, sizeof(current_path));
1352  else
1353  strlcpy(current_path,
1354  get_tablespace_mapping(PQgetvalue(res, rownum, 1)),
1355  sizeof(current_path));
1356 
1357  /*
1358  * Get the COPY data
1359  */
1360  res = PQgetResult(conn);
1361  if (PQresultStatus(res) != PGRES_COPY_OUT)
1362  {
1363  fprintf(stderr, _("%s: could not get COPY data stream: %s"),
1364  progname, PQerrorMessage(conn));
1366  }
1367 
1368  while (1)
1369  {
1370  int r;
1371 
1372  if (copybuf != NULL)
1373  {
1374  PQfreemem(copybuf);
1375  copybuf = NULL;
1376  }
1377 
1378  r = PQgetCopyData(conn, &copybuf, 0);
1379 
1380  if (r == -1)
1381  {
1382  /*
1383  * End of chunk
1384  */
1385  if (file)
1386  fclose(file);
1387 
1388  break;
1389  }
1390  else if (r == -2)
1391  {
1392  fprintf(stderr, _("%s: could not read COPY data: %s"),
1393  progname, PQerrorMessage(conn));
1395  }
1396 
1397  if (file == NULL)
1398  {
1399  int filemode;
1400 
1401  /*
1402  * No current file, so this must be the header for a new file
1403  */
1404  if (r != 512)
1405  {
1406  fprintf(stderr, _("%s: invalid tar block header size: %d\n"),
1407  progname, r);
1409  }
1410  totaldone += 512;
1411 
1412  current_len_left = read_tar_number(&copybuf[124], 12);
1413 
1414  /* Set permissions on the file */
1415  filemode = read_tar_number(&copybuf[100], 8);
1416 
1417  /*
1418  * All files are padded up to 512 bytes
1419  */
1420  current_padding =
1421  ((current_len_left + 511) & ~511) - current_len_left;
1422 
1423  /*
1424  * First part of header is zero terminated filename
1425  */
1426  snprintf(filename, sizeof(filename), "%s/%s", current_path,
1427  copybuf);
1428  if (filename[strlen(filename) - 1] == '/')
1429  {
1430  /*
1431  * Ends in a slash means directory or symlink to directory
1432  */
1433  if (copybuf[156] == '5')
1434  {
1435  /*
1436  * Directory
1437  */
1438  filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
1439  if (mkdir(filename, S_IRWXU) != 0)
1440  {
1441  /*
1442  * When streaming WAL, pg_wal (or pg_xlog for pre-9.6
1443  * clusters) will have been created by the wal
1444  * receiver process. Also, when the WAL directory
1445  * location was specified, pg_wal (or pg_xlog) has
1446  * already been created as a symbolic link before
1447  * starting the actual backup. So just ignore creation
1448  * failures on related directories.
1449  */
1450  if (!((pg_str_endswith(filename, "/pg_wal") ||
1451  pg_str_endswith(filename, "/pg_xlog") ||
1452  pg_str_endswith(filename, "/archive_status")) &&
1453  errno == EEXIST))
1454  {
1455  fprintf(stderr,
1456  _("%s: could not create directory \"%s\": %s\n"),
1457  progname, filename, strerror(errno));
1459  }
1460  }
1461 #ifndef WIN32
1462  if (chmod(filename, (mode_t) filemode))
1463  fprintf(stderr,
1464  _("%s: could not set permissions on directory \"%s\": %s\n"),
1465  progname, filename, strerror(errno));
1466 #endif
1467  }
1468  else if (copybuf[156] == '2')
1469  {
1470  /*
1471  * Symbolic link
1472  *
1473  * It's most likely a link in pg_tblspc directory, to the
1474  * location of a tablespace. Apply any tablespace mapping
1475  * given on the command line (--tablespace-mapping). (We
1476  * blindly apply the mapping without checking that the
1477  * link really is inside pg_tblspc. We don't expect there
1478  * to be other symlinks in a data directory, but if there
1479  * are, you can call it an undocumented feature that you
1480  * can map them too.)
1481  */
1482  filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
1483 
1484  mapped_tblspc_path = get_tablespace_mapping(&copybuf[157]);
1485  if (symlink(mapped_tblspc_path, filename) != 0)
1486  {
1487  fprintf(stderr,
1488  _("%s: could not create symbolic link from \"%s\" to \"%s\": %s\n"),
1489  progname, filename, mapped_tblspc_path,
1490  strerror(errno));
1492  }
1493  }
1494  else
1495  {
1496  fprintf(stderr,
1497  _("%s: unrecognized link indicator \"%c\"\n"),
1498  progname, copybuf[156]);
1500  }
1501  continue; /* directory or link handled */
1502  }
1503 
1504  /*
1505  * regular file
1506  */
1507  file = fopen(filename, "wb");
1508  if (!file)
1509  {
1510  fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
1511  progname, filename, strerror(errno));
1513  }
1514 
1515 #ifndef WIN32
1516  if (chmod(filename, (mode_t) filemode))
1517  fprintf(stderr, _("%s: could not set permissions on file \"%s\": %s\n"),
1518  progname, filename, strerror(errno));
1519 #endif
1520 
1521  if (current_len_left == 0)
1522  {
1523  /*
1524  * Done with this file, next one will be a new tar header
1525  */
1526  fclose(file);
1527  file = NULL;
1528  continue;
1529  }
1530  } /* new file */
1531  else
1532  {
1533  /*
1534  * Continuing blocks in existing file
1535  */
1536  if (current_len_left == 0 && r == current_padding)
1537  {
1538  /*
1539  * Received the padding block for this file, ignore it and
1540  * close the file, then move on to the next tar header.
1541  */
1542  fclose(file);
1543  file = NULL;
1544  totaldone += r;
1545  continue;
1546  }
1547 
1548  if (fwrite(copybuf, r, 1, file) != 1)
1549  {
1550  fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
1551  progname, filename, strerror(errno));
1553  }
1554  totaldone += r;
1555  progress_report(rownum, filename, false);
1556 
1557  current_len_left -= r;
1558  if (current_len_left == 0 && current_padding == 0)
1559  {
1560  /*
1561  * Received the last block, and there is no padding to be
1562  * expected. Close the file and move on to the next tar
1563  * header.
1564  */
1565  fclose(file);
1566  file = NULL;
1567  continue;
1568  }
1569  } /* continuing data in existing file */
1570  } /* loop over all data blocks */
1571  progress_report(rownum, filename, true);
1572 
1573  if (file != NULL)
1574  {
1575  fprintf(stderr,
1576  _("%s: COPY stream ended before last file was finished\n"),
1577  progname);
1579  }
1580 
1581  if (copybuf != NULL)
1582  PQfreemem(copybuf);
1583 
1584  if (basetablespace && writerecoveryconf)
1586 
1587  /*
1588  * No data is synced here, everything is done for all tablespaces at the
1589  * end.
1590  */
1591 }
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6106
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
bool pg_str_endswith(const char *str, const char *end)
Definition: string.c:31
uint64 read_tar_number(const char *s, int len)
Definition: tar.c:56
static bool writerecoveryconf
Definition: pg_basebackup.c:89
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
int PQgetCopyData(PGconn *conn, char **buffer, int async)
Definition: fe-exec.c:2428
#define pgoff_t
Definition: win32_port.h:206
#define MAXPGPATH
static uint64 totaldone
#define symlink(oldpath, newpath)
Definition: win32_port.h:232
static const char * get_tablespace_mapping(const char *dir)
static void progress_report(int tablespacenum, const char *filename, bool force)
static void WriteRecoveryConf(void)
StringInfo copybuf
Definition: tablesync.c:114
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static char * filename
Definition: pg_dumpall.c:90
#define S_IRWXU
Definition: win32_port.h:280
const char * strerror(int errnum)
Definition: strerror.c:19
#define mkdir(a, b)
Definition: win32_port.h:58
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3143
#define _(x)
Definition: elog.c:84
void PQfreemem(void *ptr)
Definition: fe-exec.c:3251
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753

◆ ReceiveTarFile()

static void ReceiveTarFile ( PGconn conn,
PGresult res,
int  rownum 
)
static

Definition at line 962 of file pg_basebackup.c.

References _, basedir, compresslevel, copybuf, PQExpBufferData::data, disconnect_and_exit(), do_sync, filename, fsync_fname(), header(), PQExpBufferData::len, MAXPGPATH, MemSet, pgoff_t, PGRES_COPY_OUT, PQerrorMessage(), PQfreemem(), PQgetCopyData(), PQgetisnull(), PQgetResult(), PQgetvalue(), PQresultStatus(), progname, progress_report(), read_tar_number(), snprintf(), strerror(), tarCreateHeader(), totaldone, WRITE_TAR_DATA, and writerecoveryconf.

Referenced by BaseBackup().

963 {
964  char filename[MAXPGPATH];
965  char *copybuf = NULL;
966  FILE *tarfile = NULL;
967  char tarhdr[512];
968  bool basetablespace = PQgetisnull(res, rownum, 0);
969  bool in_tarhdr = true;
970  bool skip_file = false;
971  size_t tarhdrsz = 0;
972  pgoff_t filesz = 0;
973 
974 #ifdef HAVE_LIBZ
975  gzFile ztarfile = NULL;
976 #endif
977 
978  if (basetablespace)
979  {
980  /*
981  * Base tablespaces
982  */
983  if (strcmp(basedir, "-") == 0)
984  {
985 #ifdef WIN32
986  _setmode(fileno(stdout), _O_BINARY);
987 #endif
988 
989 #ifdef HAVE_LIBZ
990  if (compresslevel != 0)
991  {
992  ztarfile = gzdopen(dup(fileno(stdout)), "wb");
993  if (gzsetparams(ztarfile, compresslevel,
994  Z_DEFAULT_STRATEGY) != Z_OK)
995  {
996  fprintf(stderr,
997  _("%s: could not set compression level %d: %s\n"),
998  progname, compresslevel, get_gz_error(ztarfile));
1000  }
1001  }
1002  else
1003 #endif
1004  tarfile = stdout;
1005  strcpy(filename, "-");
1006  }
1007  else
1008  {
1009 #ifdef HAVE_LIBZ
1010  if (compresslevel != 0)
1011  {
1012  snprintf(filename, sizeof(filename), "%s/base.tar.gz", basedir);
1013  ztarfile = gzopen(filename, "wb");
1014  if (gzsetparams(ztarfile, compresslevel,
1015  Z_DEFAULT_STRATEGY) != Z_OK)
1016  {
1017  fprintf(stderr,
1018  _("%s: could not set compression level %d: %s\n"),
1019  progname, compresslevel, get_gz_error(ztarfile));
1021  }
1022  }
1023  else
1024 #endif
1025  {
1026  snprintf(filename, sizeof(filename), "%s/base.tar", basedir);
1027  tarfile = fopen(filename, "wb");
1028  }
1029  }
1030  }
1031  else
1032  {
1033  /*
1034  * Specific tablespace
1035  */
1036 #ifdef HAVE_LIBZ
1037  if (compresslevel != 0)
1038  {
1039  snprintf(filename, sizeof(filename), "%s/%s.tar.gz", basedir,
1040  PQgetvalue(res, rownum, 0));
1041  ztarfile = gzopen(filename, "wb");
1042  if (gzsetparams(ztarfile, compresslevel,
1043  Z_DEFAULT_STRATEGY) != Z_OK)
1044  {
1045  fprintf(stderr,
1046  _("%s: could not set compression level %d: %s\n"),
1047  progname, compresslevel, get_gz_error(ztarfile));
1049  }
1050  }
1051  else
1052 #endif
1053  {
1054  snprintf(filename, sizeof(filename), "%s/%s.tar", basedir,
1055  PQgetvalue(res, rownum, 0));
1056  tarfile = fopen(filename, "wb");
1057  }
1058  }
1059 
1060 #ifdef HAVE_LIBZ
1061  if (compresslevel != 0)
1062  {
1063  if (!ztarfile)
1064  {
1065  /* Compression is in use */
1066  fprintf(stderr,
1067  _("%s: could not create compressed file \"%s\": %s\n"),
1068  progname, filename, get_gz_error(ztarfile));
1070  }
1071  }
1072  else
1073 #endif
1074  {
1075  /* Either no zlib support, or zlib support but compresslevel = 0 */
1076  if (!tarfile)
1077  {
1078  fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
1079  progname, filename, strerror(errno));
1081  }
1082  }
1083 
1084  /*
1085  * Get the COPY data stream
1086  */
1087  res = PQgetResult(conn);
1088  if (PQresultStatus(res) != PGRES_COPY_OUT)
1089  {
1090  fprintf(stderr, _("%s: could not get COPY data stream: %s"),
1091  progname, PQerrorMessage(conn));
1093  }
1094 
1095  while (1)
1096  {
1097  int r;
1098 
1099  if (copybuf != NULL)
1100  {
1101  PQfreemem(copybuf);
1102  copybuf = NULL;
1103  }
1104 
1105  r = PQgetCopyData(conn, &copybuf, 0);
1106  if (r == -1)
1107  {
1108  /*
1109  * End of chunk. If requested, and this is the base tablespace,
1110  * write recovery.conf into the tarfile. When done, close the file
1111  * (but not stdout).
1112  *
1113  * Also, write two completely empty blocks at the end of the tar
1114  * file, as required by some tar programs.
1115  */
1116  char zerobuf[1024];
1117 
1118  MemSet(zerobuf, 0, sizeof(zerobuf));
1119 
1120  if (basetablespace && writerecoveryconf)
1121  {
1122  char header[512];
1123  int padding;
1124 
1125  tarCreateHeader(header, "recovery.conf", NULL,
1127  0600, 04000, 02000,
1128  time(NULL));
1129 
1130  padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
1131 
1132  WRITE_TAR_DATA(header, sizeof(header));
1134  if (padding)
1135  WRITE_TAR_DATA(zerobuf, padding);
1136  }
1137 
1138  /* 2 * 512 bytes empty data at end of file */
1139  WRITE_TAR_DATA(zerobuf, sizeof(zerobuf));
1140 
1141 #ifdef HAVE_LIBZ
1142  if (ztarfile != NULL)
1143  {
1144  if (gzclose(ztarfile) != 0)
1145  {
1146  fprintf(stderr,
1147  _("%s: could not close compressed file \"%s\": %s\n"),
1148  progname, filename, get_gz_error(ztarfile));
1150  }
1151  }
1152  else
1153 #endif
1154  {
1155  if (strcmp(basedir, "-") != 0)
1156  {
1157  if (fclose(tarfile) != 0)
1158  {
1159  fprintf(stderr,
1160  _("%s: could not close file \"%s\": %s\n"),
1161  progname, filename, strerror(errno));
1163  }
1164  }
1165  }
1166 
1167  break;
1168  }
1169  else if (r == -2)
1170  {
1171  fprintf(stderr, _("%s: could not read COPY data: %s"),
1172  progname, PQerrorMessage(conn));
1174  }
1175 
1176  if (!writerecoveryconf || !basetablespace)
1177  {
1178  /*
1179  * When not writing recovery.conf, or when not working on the base
1180  * tablespace, we never have to look for an existing recovery.conf
1181  * file in the stream.
1182  */
1183  WRITE_TAR_DATA(copybuf, r);
1184  }
1185  else
1186  {
1187  /*
1188  * Look for a recovery.conf in the existing tar stream. If it's
1189  * there, we must skip it so we can later overwrite it with our
1190  * own version of the file.
1191  *
1192  * To do this, we have to process the individual files inside the
1193  * TAR stream. The stream consists of a header and zero or more
1194  * chunks, all 512 bytes long. The stream from the server is
1195  * broken up into smaller pieces, so we have to track the size of
1196  * the files to find the next header structure.
1197  */
1198  int rr = r;
1199  int pos = 0;
1200 
1201  while (rr > 0)
1202  {
1203  if (in_tarhdr)
1204  {
1205  /*
1206  * We're currently reading a header structure inside the
1207  * TAR stream, i.e. the file metadata.
1208  */
1209  if (tarhdrsz < 512)
1210  {
1211  /*
1212  * Copy the header structure into tarhdr in case the
1213  * header is not aligned to 512 bytes or it's not
1214  * returned in whole by the last PQgetCopyData call.
1215  */
1216  int hdrleft;
1217  int bytes2copy;
1218 
1219  hdrleft = 512 - tarhdrsz;
1220  bytes2copy = (rr > hdrleft ? hdrleft : rr);
1221 
1222  memcpy(&tarhdr[tarhdrsz], copybuf + pos, bytes2copy);
1223 
1224  rr -= bytes2copy;
1225  pos += bytes2copy;
1226  tarhdrsz += bytes2copy;
1227  }
1228  else
1229  {
1230  /*
1231  * We have the complete header structure in tarhdr,
1232  * look at the file metadata: - the subsequent file
1233  * contents have to be skipped if the filename is
1234  * recovery.conf - find out the size of the file
1235  * padded to the next multiple of 512
1236  */
1237  int padding;
1238 
1239  skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
1240 
1241  filesz = read_tar_number(&tarhdr[124], 12);
1242 
1243  padding = ((filesz + 511) & ~511) - filesz;
1244  filesz += padding;
1245 
1246  /* Next part is the file, not the header */
1247  in_tarhdr = false;
1248 
1249  /*
1250  * If we're not skipping the file, write the tar
1251  * header unmodified.
1252  */
1253  if (!skip_file)
1254  WRITE_TAR_DATA(tarhdr, 512);
1255  }
1256  }
1257  else
1258  {
1259  /*
1260  * We're processing a file's contents.
1261  */
1262  if (filesz > 0)
1263  {
1264  /*
1265  * We still have data to read (and possibly write).
1266  */
1267  int bytes2write;
1268 
1269  bytes2write = (filesz > rr ? rr : filesz);
1270 
1271  if (!skip_file)
1272  WRITE_TAR_DATA(copybuf + pos, bytes2write);
1273 
1274  rr -= bytes2write;
1275  pos += bytes2write;
1276  filesz -= bytes2write;
1277  }
1278  else
1279  {
1280  /*
1281  * No more data in the current file, the next piece of
1282  * data (if any) will be a new file header structure.
1283  */
1284  in_tarhdr = true;
1285  skip_file = false;
1286  tarhdrsz = 0;
1287  filesz = 0;
1288  }
1289  }
1290  }
1291  }
1292  totaldone += r;
1293  progress_report(rownum, filename, false);
1294  } /* while (1) */
1295  progress_report(rownum, filename, true);
1296 
1297  if (copybuf != NULL)
1298  PQfreemem(copybuf);
1299 
1300  /* sync the resulting tar file, errors are not considered fatal */
1301  if (do_sync && strcmp(basedir, "-") != 0)
1302  (void) fsync_fname(filename, false, progname);
1303 }
static PQExpBuffer recoveryconfcontents
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6106
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
uint64 read_tar_number(const char *s, int len)
Definition: tar.c:56
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:581
static bool writerecoveryconf
Definition: pg_basebackup.c:89
static int compresslevel
Definition: pg_basebackup.c:86
#define MemSet(start, val, len)
Definition: c.h:863
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2647
int PQgetCopyData(PGconn *conn, char **buffer, int async)
Definition: fe-exec.c:2428
#define pgoff_t
Definition: win32_port.h:206
#define MAXPGPATH
static uint64 totaldone
static void progress_report(int tablespacenum, const char *filename, bool force)
enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
Definition: tar.c:112
StringInfo copybuf
Definition: tablesync.c:114
static void header(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:208
#define WRITE_TAR_DATA(buf, sz)
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static char * filename
Definition: pg_dumpall.c:90
const char * strerror(int errnum)
Definition: strerror.c:19
static bool do_sync
Definition: pg_basebackup.c:90
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3143
#define _(x)
Definition: elog.c:84
void PQfreemem(void *ptr)
Definition: fe-exec.c:3251
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:1753

◆ StartLogStreamer()

static void StartLogStreamer ( char *  startpos,
uint32  timeline,
char *  sysidentifier 
)
static

Definition at line 542 of file pg_basebackup.c.

References _, basedir, bgchild, logstreamer_param::bgconn, bgpipe, conn, create_slot, CreateReplicationSlot(), disconnect_and_exit(), format, GetConnection(), LogStreamerMain(), MAXPGPATH, MINIMUM_VERSION_FOR_PG_WAL, MINIMUM_VERSION_FOR_TEMP_SLOTS, pg_malloc0(), pg_mkdir_p(), PQbackendPID(), PQserverVersion(), progname, psprintf(), replication_slot, S_IRWXU, snprintf(), logstreamer_param::startptr, strerror(), logstreamer_param::sysidentifier, temp_replication_slot, logstreamer_param::timeline, verbose, WalSegSz, logstreamer_param::xlog, and XLogSegmentOffset.

Referenced by BaseBackup().

543 {
544  logstreamer_param *param;
545  uint32 hi,
546  lo;
547  char statusdir[MAXPGPATH];
548 
549  param = pg_malloc0(sizeof(logstreamer_param));
550  param->timeline = timeline;
551  param->sysidentifier = sysidentifier;
552 
553  /* Convert the starting position */
554  if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
555  {
556  fprintf(stderr,
557  _("%s: could not parse write-ahead log location \"%s\"\n"),
558  progname, startpos);
560  }
561  param->startptr = ((uint64) hi) << 32 | lo;
562  /* Round off to even segment position */
563  param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
564 
565 #ifndef WIN32
566  /* Create our background pipe */
567  if (pipe(bgpipe) < 0)
568  {
569  fprintf(stderr,
570  _("%s: could not create pipe for background process: %s\n"),
571  progname, strerror(errno));
573  }
574 #endif
575 
576  /* Get a second connection */
577  param->bgconn = GetConnection();
578  if (!param->bgconn)
579  /* Error message already written in GetConnection() */
580  exit(1);
581 
582  /* In post-10 cluster, pg_xlog has been renamed to pg_wal */
583  snprintf(param->xlog, sizeof(param->xlog), "%s/%s",
584  basedir,
586  "pg_xlog" : "pg_wal");
587 
588  /* Temporary replication slots are only supported in 10 and newer */
590  temp_replication_slot = false;
591 
592  /*
593  * Create replication slot if requested
594  */
596  replication_slot = psprintf("pg_basebackup_%d", (int) PQbackendPID(param->bgconn));
598  {
599  if (!CreateReplicationSlot(param->bgconn, replication_slot, NULL,
600  temp_replication_slot, true, true, false))
602 
603  if (verbose)
604  {
606  fprintf(stderr, _("%s: created temporary replication slot \"%s\"\n"),
608  else
609  fprintf(stderr, _("%s: created replication slot \"%s\"\n"),
611  }
612  }
613 
614  if (format == 'p')
615  {
616  /*
617  * Create pg_wal/archive_status or pg_xlog/archive_status (and thus
618  * pg_wal or pg_xlog) depending on the target server so we can write
619  * to basedir/pg_wal or basedir/pg_xlog as the directory entry in the
620  * tar file may arrive later.
621  */
622  snprintf(statusdir, sizeof(statusdir), "%s/%s/archive_status",
623  basedir,
625  "pg_xlog" : "pg_wal");
626 
627  if (pg_mkdir_p(statusdir, S_IRWXU) != 0 && errno != EEXIST)
628  {
629  fprintf(stderr,
630  _("%s: could not create directory \"%s\": %s\n"),
631  progname, statusdir, strerror(errno));
633  }
634  }
635 
636  /*
637  * Start a child process and tell it to start streaming. On Unix, this is
638  * a fork(). On Windows, we create a thread.
639  */
640 #ifndef WIN32
641  bgchild = fork();
642  if (bgchild == 0)
643  {
644  /* in child process */
645  exit(LogStreamerMain(param));
646  }
647  else if (bgchild < 0)
648  {
649  fprintf(stderr, _("%s: could not create background process: %s\n"),
650  progname, strerror(errno));
652  }
653 
654  /*
655  * Else we are in the parent process and all is well.
656  */
657 #else /* WIN32 */
658  bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
659  if (bgchild == 0)
660  {
661  fprintf(stderr, _("%s: could not create background thread: %s\n"),
662  progname, strerror(errno));
664  }
665 #endif
666 }
static int bgpipe[2]
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static bool create_slot
Definition: pg_basebackup.c:96
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6096
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
PGconn * conn
Definition: streamutil.c:46
#define MAXPGPATH
#define MINIMUM_VERSION_FOR_PG_WAL
Definition: pg_basebackup.c:60
unsigned int uint32
Definition: c.h:306
XLogRecPtr startptr
static int verbose
Definition: pg_basebackup.c:85
static bool temp_replication_slot
Definition: pg_basebackup.c:95
int PQbackendPID(const PGconn *conn)
Definition: fe-connect.c:6132
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
PGconn * GetConnection(UserMapping *user, bool will_prep_stmt)
Definition: connection.c:107
static XLogRecPtr startpos
static void CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
Definition: walsender.c:835
static void disconnect_and_exit(int code) pg_attribute_noreturn()
int WalSegSz
Definition: pg_standby.c:39
#define S_IRWXU
Definition: win32_port.h:280
static pid_t bgchild
const char * strerror(int errnum)
Definition: strerror.c:19
static char format
Definition: pg_basebackup.c:81
static char * replication_slot
Definition: pg_basebackup.c:94
static int LogStreamerMain(logstreamer_param *param)
#define _(x)
Definition: elog.c:84
#define MINIMUM_VERSION_FOR_TEMP_SLOTS
Definition: pg_basebackup.c:65
char xlog[MAXPGPATH]

◆ tablespace_list_append()

static void tablespace_list_append ( const char *  arg)
static

Definition at line 241 of file pg_basebackup.c.

References _, canonicalize_path(), errmsg(), TablespaceList::head, is_absolute_path, MAXPGPATH, TablespaceListCell::new_dir, TablespaceListCell::next, TablespaceListCell::old_dir, pg_malloc0(), progname, strerror(), and TablespaceList::tail.

Referenced by main().

242 {
244  char *dst;
245  char *dst_ptr;
246  const char *arg_ptr;
247 
248  dst_ptr = dst = cell->old_dir;
249  for (arg_ptr = arg; *arg_ptr; arg_ptr++)
250  {
251  if (dst_ptr - dst >= MAXPGPATH)
252  {
253  fprintf(stderr, _("%s: directory name too long\n"), progname);
254  exit(1);
255  }
256 
257  if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
258  ; /* skip backslash escaping = */
259  else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
260  {
261  if (*cell->new_dir)
262  {
263  fprintf(stderr, _("%s: multiple \"=\" signs in tablespace mapping\n"), progname);
264  exit(1);
265  }
266  else
267  dst = dst_ptr = cell->new_dir;
268  }
269  else
270  *dst_ptr++ = *arg_ptr;
271  }
272 
273  if (!*cell->old_dir || !*cell->new_dir)
274  {
275  fprintf(stderr,
276  _("%s: invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"\n"),
277  progname, arg);
278  exit(1);
279  }
280 
281  /*
282  * This check isn't absolutely necessary. But all tablespaces are created
283  * with absolute directories, so specifying a non-absolute path here would
284  * just never match, possibly confusing users. It's also good to be
285  * consistent with the new_dir check.
286  */
287  if (!is_absolute_path(cell->old_dir))
288  {
289  fprintf(stderr, _("%s: old directory is not an absolute path in tablespace mapping: %s\n"),
290  progname, cell->old_dir);
291  exit(1);
292  }
293 
294  if (!is_absolute_path(cell->new_dir))
295  {
296  fprintf(stderr, _("%s: new directory is not an absolute path in tablespace mapping: %s\n"),
297  progname, cell->new_dir);
298  exit(1);
299  }
300 
301  /*
302  * Comparisons done with these values should involve similarly
303  * canonicalized path values. This is particularly sensitive on Windows
304  * where path values may not necessarily use Unix slashes.
305  */
306  canonicalize_path(cell->old_dir);
307  canonicalize_path(cell->new_dir);
308 
309  if (tablespace_dirs.tail)
310  tablespace_dirs.tail->next = cell;
311  else
312  tablespace_dirs.head = cell;
313  tablespace_dirs.tail = cell;
314 }
static TablespaceList tablespace_dirs
Definition: pg_basebackup.c:79
char old_dir[MAXPGPATH]
Definition: pg_basebackup.c:46
void canonicalize_path(char *path)
Definition: path.c:254
char new_dir[MAXPGPATH]
Definition: pg_basebackup.c:47
const char * progname
Definition: pg_standby.c:37
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
#define MAXPGPATH
#define is_absolute_path(filename)
Definition: port.h:86
struct TablespaceListCell * next
Definition: pg_basebackup.c:45
TablespaceListCell * tail
Definition: pg_basebackup.c:53
TablespaceListCell * head
Definition: pg_basebackup.c:52
void * arg
#define _(x)
Definition: elog.c:84

◆ usage()

static void usage ( void  )
static

Definition at line 333 of file pg_basebackup.c.

References _, and progname.

Referenced by main().

334 {
335  printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
336  progname);
337  printf(_("Usage:\n"));
338  printf(_(" %s [OPTION]...\n"), progname);
339  printf(_("\nOptions controlling the output:\n"));
340  printf(_(" -D, --pgdata=DIRECTORY receive base backup into directory\n"));
341  printf(_(" -F, --format=p|t output format (plain (default), tar)\n"));
342  printf(_(" -r, --max-rate=RATE maximum transfer rate to transfer data directory\n"
343  " (in kB/s, or use suffix \"k\" or \"M\")\n"));
344  printf(_(" -R, --write-recovery-conf\n"
345  " write recovery.conf for replication\n"));
346  printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
347  " relocate tablespace in OLDDIR to NEWDIR\n"));
348  printf(_(" --waldir=WALDIR location for the write-ahead log directory\n"));
349  printf(_(" -X, --wal-method=none|fetch|stream\n"
350  " include required WAL files with specified method\n"));
351  printf(_(" -z, --gzip compress tar output\n"));
352  printf(_(" -Z, --compress=0-9 compress tar output with given compression level\n"));
353  printf(_("\nGeneral options:\n"));
354  printf(_(" -c, --checkpoint=fast|spread\n"
355  " set fast or spread checkpointing\n"));
356  printf(_(" -C, --create-slot create replication slot\n"));
357  printf(_(" -l, --label=LABEL set backup label\n"));
358  printf(_(" -n, --no-clean do not clean up after errors\n"));
359  printf(_(" -N, --no-sync do not wait for changes to be written safely to disk\n"));
360  printf(_(" -P, --progress show progress information\n"));
361  printf(_(" -S, --slot=SLOTNAME replication slot to use\n"));
362  printf(_(" --no-slot prevent creation of temporary replication slot\n"));
363  printf(_(" -v, --verbose output verbose messages\n"));
364  printf(_(" -V, --version output version information, then exit\n"));
365  printf(_(" -?, --help show this help, then exit\n"));
366  printf(_("\nConnection options:\n"));
367  printf(_(" -d, --dbname=CONNSTR connection string\n"));
368  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
369  printf(_(" -p, --port=PORT database server port number\n"));
370  printf(_(" -s, --status-interval=INTERVAL\n"
371  " time between status packets sent to server (in seconds)\n"));
372  printf(_(" -U, --username=NAME connect as specified database user\n"));
373  printf(_(" -w, --no-password never prompt for password\n"));
374  printf(_(" -W, --password force password prompt (should happen automatically)\n"));
375  printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
376 }
const char * progname
Definition: pg_standby.c:37
#define _(x)
Definition: elog.c:84

◆ verify_dir_is_empty_or_create()

static void verify_dir_is_empty_or_create ( char *  dirname,
bool created,
bool found 
)
static

Definition at line 674 of file pg_basebackup.c.

References _, disconnect_and_exit(), pg_check_dir(), pg_mkdir_p(), progname, S_IRWXU, and strerror().

Referenced by BaseBackup(), and main().

675 {
676  switch (pg_check_dir(dirname))
677  {
678  case 0:
679 
680  /*
681  * Does not exist, so create
682  */
683  if (pg_mkdir_p(dirname, S_IRWXU) == -1)
684  {
685  fprintf(stderr,
686  _("%s: could not create directory \"%s\": %s\n"),
687  progname, dirname, strerror(errno));
689  }
690  if (created)
691  *created = true;
692  return;
693  case 1:
694 
695  /*
696  * Exists, empty
697  */
698  if (found)
699  *found = true;
700  return;
701  case 2:
702  case 3:
703  case 4:
704 
705  /*
706  * Exists, not empty
707  */
708  fprintf(stderr,
709  _("%s: directory \"%s\" exists but is not empty\n"),
710  progname, dirname);
712  case -1:
713 
714  /*
715  * Access problem
716  */
717  fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
718  progname, dirname, strerror(errno));
720  }
721 }
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
const char * progname
Definition: pg_standby.c:37
static void disconnect_and_exit(int code) pg_attribute_noreturn()
#define S_IRWXU
Definition: win32_port.h:280
int pg_check_dir(const char *dir)
Definition: pgcheckdir.c:31
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

◆ WriteRecoveryConf()

static void WriteRecoveryConf ( void  )
static

Definition at line 1699 of file pg_basebackup.c.

References _, basedir, PQExpBufferData::data, disconnect_and_exit(), filename, PQExpBufferData::len, MAXPGPATH, progname, and strerror().

Referenced by ReceiveAndUnpackTarFile().

1700 {
1701  char filename[MAXPGPATH];
1702  FILE *cf;
1703 
1704  sprintf(filename, "%s/recovery.conf", basedir);
1705 
1706  cf = fopen(filename, "w");
1707  if (cf == NULL)
1708  {
1709  fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
1711  }
1712 
1713  if (fwrite(recoveryconfcontents->data, recoveryconfcontents->len, 1, cf) != 1)
1714  {
1715  fprintf(stderr,
1716  _("%s: could not write to file \"%s\": %s\n"),
1717  progname, filename, strerror(errno));
1719  }
1720 
1721  fclose(cf);
1722 }
static PQExpBuffer recoveryconfcontents
const char * progname
Definition: pg_standby.c:37
static char * basedir
Definition: pg_basebackup.c:78
#define MAXPGPATH
static void disconnect_and_exit(int code) pg_attribute_noreturn()
static char * filename
Definition: pg_dumpall.c:90
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

◆ writeTarData()

static void writeTarData ( FILE *  tarfile,
char *  buf,
int  r,
char *  current_file 
)
static

Definition at line 916 of file pg_basebackup.c.

References _, disconnect_and_exit(), progname, and strerror().

921 {
922 #ifdef HAVE_LIBZ
923  if (ztarfile != NULL)
924  {
925  if (gzwrite(ztarfile, buf, r) != r)
926  {
927  fprintf(stderr,
928  _("%s: could not write to compressed file \"%s\": %s\n"),
929  progname, current_file, get_gz_error(ztarfile));
931  }
932  }
933  else
934 #endif
935  {
936  if (fwrite(buf, r, 1, tarfile) != 1)
937  {
938  fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
939  progname, current_file, strerror(errno));
941  }
942  }
943 }
const char * progname
Definition: pg_standby.c:37
static char * buf
Definition: pg_test_fsync.c:67
static void disconnect_and_exit(int code) pg_attribute_noreturn()
const char * strerror(int errnum)
Definition: strerror.c:19
#define _(x)
Definition: elog.c:84

Variable Documentation

◆ basedir

◆ bgchild

pid_t bgchild = -1
static

Definition at line 118 of file pg_basebackup.c.

Referenced by BaseBackup(), disconnect_and_exit(), and StartLogStreamer().

◆ bgpipe

int bgpipe[2] = {-1, -1}
static

◆ compresslevel

int compresslevel = 0
static

Definition at line 86 of file pg_basebackup.c.

Referenced by LogStreamerMain(), main(), and ReceiveTarFile().

◆ create_slot

bool create_slot = false
static

Definition at line 96 of file pg_basebackup.c.

Referenced by CreateSubscription(), main(), and StartLogStreamer().

◆ do_sync

bool do_sync = true
static

Definition at line 90 of file pg_basebackup.c.

Referenced by BaseBackup(), LogStreamerMain(), main(), and ReceiveTarFile().

◆ fastcheckpoint

bool fastcheckpoint = false
static

Definition at line 88 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ format

◆ found_existing_pgdata

bool found_existing_pgdata = false
static

Definition at line 101 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ found_existing_xlogdir

bool found_existing_xlogdir = false
static

Definition at line 103 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ found_tablespace_dirs

bool found_tablespace_dirs = false
static

Definition at line 105 of file pg_basebackup.c.

Referenced by BaseBackup(), and cleanup_directories_atexit().

◆ has_xlogendptr

int has_xlogendptr = 0
static

Definition at line 125 of file pg_basebackup.c.

Referenced by BaseBackup(), and reached_end_position().

◆ in_log_streamer

bool in_log_streamer = false
static

Definition at line 119 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and LogStreamerMain().

◆ includewal

IncludeWal includewal = STREAM_WAL
static

Definition at line 87 of file pg_basebackup.c.

Referenced by BaseBackup(), and main().

◆ label

◆ last_progress_report

pg_time_t last_progress_report = 0
static

Definition at line 92 of file pg_basebackup.c.

Referenced by progress_report().

◆ made_new_pgdata

bool made_new_pgdata = false
static

Definition at line 100 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ made_new_xlogdir

bool made_new_xlogdir = false
static

Definition at line 102 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ made_tablespace_dirs

bool made_tablespace_dirs = false
static

Definition at line 104 of file pg_basebackup.c.

Referenced by BaseBackup(), and cleanup_directories_atexit().

◆ maxrate

int32 maxrate = 0
static

Definition at line 93 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), and parse_basebackup_options().

◆ no_slot

bool no_slot = false
static

Definition at line 97 of file pg_basebackup.c.

Referenced by main().

◆ noclean

bool noclean = false
static

Definition at line 83 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ recoveryconfcontents

PQExpBuffer recoveryconfcontents = NULL
static

Definition at line 131 of file pg_basebackup.c.

◆ replication_slot

char* replication_slot = NULL
static

Definition at line 94 of file pg_basebackup.c.

Referenced by GenerateRecoveryConf(), LogStreamerMain(), main(), and StartLogStreamer().

◆ showprogress

bool showprogress = false
static

Definition at line 84 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), pg_attribute_printf(), and progress_report().

◆ standby_message_timeout

int standby_message_timeout = 10 * 1000
static

Definition at line 91 of file pg_basebackup.c.

Referenced by LogStreamerMain(), and main().

◆ success

◆ tablespace_dirs

TablespaceList tablespace_dirs = {NULL, NULL}
static

Definition at line 79 of file pg_basebackup.c.

◆ tablespacecount

int tablespacecount
static

Definition at line 110 of file pg_basebackup.c.

Referenced by BaseBackup(), and progress_report().

◆ temp_replication_slot

bool temp_replication_slot = true
static

Definition at line 95 of file pg_basebackup.c.

Referenced by main(), and StartLogStreamer().

◆ totaldone

uint64 totaldone
static

◆ totalsize

◆ verbose

int verbose = 0
static

◆ writerecoveryconf

bool writerecoveryconf = false
static

Definition at line 89 of file pg_basebackup.c.

Referenced by BaseBackup(), main(), ReceiveAndUnpackTarFile(), and ReceiveTarFile().

◆ xlog_dir

char* xlog_dir = NULL
static

Definition at line 80 of file pg_basebackup.c.

Referenced by cleanup_directories_atexit(), and main().

◆ xlogendptr

XLogRecPtr xlogendptr
static

Definition at line 122 of file pg_basebackup.c.

Referenced by BaseBackup(), and reached_end_position().