PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/pg_basebackup/pg_basebackup.c

https://github.com/larkly/postgres-docker
C | 2258 lines | 1593 code | 237 blank | 428 comment | 377 complexity | 38986f46f6c4d599b4425d639b6543ce MD5 | raw file
Possible License(s): AGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*-------------------------------------------------------------------------
  2. *
  3. * pg_basebackup.c - receive a base backup using streaming replication protocol
  4. *
  5. * Author: Magnus Hagander <magnus@hagander.net>
  6. *
  7. * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
  8. *
  9. * IDENTIFICATION
  10. * src/bin/pg_basebackup/pg_basebackup.c
  11. *-------------------------------------------------------------------------
  12. */
  13. #include "postgres_fe.h"
  14. #include <unistd.h>
  15. #include <dirent.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <sys/wait.h>
  19. #include <signal.h>
  20. #include <time.h>
  21. #ifdef HAVE_LIBZ
  22. #include <zlib.h>
  23. #endif
  24. #include "getopt_long.h"
  25. #include "libpq-fe.h"
  26. #include "pqexpbuffer.h"
  27. #include "pgtar.h"
  28. #include "pgtime.h"
  29. #include "receivelog.h"
  30. #include "replication/basebackup.h"
  31. #include "streamutil.h"
  32. #define atooid(x) ((Oid) strtoul((x), NULL, 10))
  33. typedef struct TablespaceListCell
  34. {
  35. struct TablespaceListCell *next;
  36. char old_dir[MAXPGPATH];
  37. char new_dir[MAXPGPATH];
  38. } TablespaceListCell;
  39. typedef struct TablespaceList
  40. {
  41. TablespaceListCell *head;
  42. TablespaceListCell *tail;
  43. } TablespaceList;
  44. /* Global options */
  45. static char *basedir = NULL;
  46. static TablespaceList tablespace_dirs = {NULL, NULL};
  47. static char *xlog_dir = "";
  48. static char format = 'p'; /* p(lain)/t(ar) */
  49. static char *label = "pg_basebackup base backup";
  50. static bool showprogress = false;
  51. static int verbose = 0;
  52. static int compresslevel = 0;
  53. static bool includewal = false;
  54. static bool streamwal = false;
  55. static bool fastcheckpoint = false;
  56. static bool writerecoveryconf = false;
  57. static int standby_message_timeout = 10 * 1000; /* 10 sec = default */
  58. static pg_time_t last_progress_report = 0;
  59. static int32 maxrate = 0; /* no limit by default */
  60. /* Progress counters */
  61. static uint64 totalsize;
  62. static uint64 totaldone;
  63. static int tablespacecount;
  64. /* Pipe to communicate with background wal receiver process */
  65. #ifndef WIN32
  66. static int bgpipe[2] = {-1, -1};
  67. #endif
  68. /* Handle to child process */
  69. static pid_t bgchild = -1;
  70. /* End position for xlog streaming, empty string if unknown yet */
  71. static XLogRecPtr xlogendptr;
  72. #ifndef WIN32
  73. static int has_xlogendptr = 0;
  74. #else
  75. static volatile LONG has_xlogendptr = 0;
  76. #endif
  77. /* Contents of recovery.conf to be generated */
  78. static PQExpBuffer recoveryconfcontents = NULL;
  79. /* Function headers */
  80. static void usage(void);
  81. static void disconnect_and_exit(int code);
  82. static void verify_dir_is_empty_or_create(char *dirname);
  83. static void progress_report(int tablespacenum, const char *filename, bool force);
  84. static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum);
  85. static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum);
  86. static void GenerateRecoveryConf(PGconn *conn);
  87. static void WriteRecoveryConf(void);
  88. static void BaseBackup(void);
  89. static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline,
  90. bool segment_finished);
  91. static const char *get_tablespace_mapping(const char *dir);
  92. static void update_tablespace_symlink(Oid oid, const char *old_dir);
  93. static void tablespace_list_append(const char *arg);
  94. static void
  95. disconnect_and_exit(int code)
  96. {
  97. if (conn != NULL)
  98. PQfinish(conn);
  99. #ifndef WIN32
  100. /*
  101. * On windows, our background thread dies along with the process. But on
  102. * Unix, if we have started a subprocess, we want to kill it off so it
  103. * doesn't remain running trying to stream data.
  104. */
  105. if (bgchild > 0)
  106. kill(bgchild, SIGTERM);
  107. #endif
  108. exit(code);
  109. }
  110. /*
  111. * Split argument into old_dir and new_dir and append to tablespace mapping
  112. * list.
  113. */
  114. static void
  115. tablespace_list_append(const char *arg)
  116. {
  117. TablespaceListCell *cell = (TablespaceListCell *) pg_malloc0(sizeof(TablespaceListCell));
  118. char *dst;
  119. char *dst_ptr;
  120. const char *arg_ptr;
  121. dst_ptr = dst = cell->old_dir;
  122. for (arg_ptr = arg; *arg_ptr; arg_ptr++)
  123. {
  124. if (dst_ptr - dst >= MAXPGPATH)
  125. {
  126. fprintf(stderr, _("%s: directory name too long\n"), progname);
  127. exit(1);
  128. }
  129. if (*arg_ptr == '\\' && *(arg_ptr + 1) == '=')
  130. ; /* skip backslash escaping = */
  131. else if (*arg_ptr == '=' && (arg_ptr == arg || *(arg_ptr - 1) != '\\'))
  132. {
  133. if (*cell->new_dir)
  134. {
  135. fprintf(stderr, _("%s: multiple \"=\" signs in tablespace mapping\n"), progname);
  136. exit(1);
  137. }
  138. else
  139. dst = dst_ptr = cell->new_dir;
  140. }
  141. else
  142. *dst_ptr++ = *arg_ptr;
  143. }
  144. if (!*cell->old_dir || !*cell->new_dir)
  145. {
  146. fprintf(stderr,
  147. _("%s: invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"\n"),
  148. progname, arg);
  149. exit(1);
  150. }
  151. /*
  152. * This check isn't absolutely necessary. But all tablespaces are created
  153. * with absolute directories, so specifying a non-absolute path here would
  154. * just never match, possibly confusing users. It's also good to be
  155. * consistent with the new_dir check.
  156. */
  157. if (!is_absolute_path(cell->old_dir))
  158. {
  159. fprintf(stderr, _("%s: old directory is not an absolute path in tablespace mapping: %s\n"),
  160. progname, cell->old_dir);
  161. exit(1);
  162. }
  163. if (!is_absolute_path(cell->new_dir))
  164. {
  165. fprintf(stderr, _("%s: new directory is not an absolute path in tablespace mapping: %s\n"),
  166. progname, cell->new_dir);
  167. exit(1);
  168. }
  169. if (tablespace_dirs.tail)
  170. tablespace_dirs.tail->next = cell;
  171. else
  172. tablespace_dirs.head = cell;
  173. tablespace_dirs.tail = cell;
  174. }
  175. #ifdef HAVE_LIBZ
  176. static const char *
  177. get_gz_error(gzFile gzf)
  178. {
  179. int errnum;
  180. const char *errmsg;
  181. errmsg = gzerror(gzf, &errnum);
  182. if (errnum == Z_ERRNO)
  183. return strerror(errno);
  184. else
  185. return errmsg;
  186. }
  187. #endif
  188. static void
  189. usage(void)
  190. {
  191. printf(_("%s takes a base backup of a running PostgreSQL server.\n\n"),
  192. progname);
  193. printf(_("Usage:\n"));
  194. printf(_(" %s [OPTION]...\n"), progname);
  195. printf(_("\nOptions controlling the output:\n"));
  196. printf(_(" -D, --pgdata=DIRECTORY receive base backup into directory\n"));
  197. printf(_(" -F, --format=p|t output format (plain (default), tar)\n"));
  198. printf(_(" -r, --max-rate=RATE maximum transfer rate to transfer data directory\n"));
  199. printf(_(" -R, --write-recovery-conf\n"
  200. " write recovery.conf after backup\n"));
  201. printf(_(" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
  202. " relocate tablespace in OLDDIR to NEWDIR\n"));
  203. printf(_(" -x, --xlog include required WAL files in backup (fetch mode)\n"));
  204. printf(_(" -X, --xlog-method=fetch|stream\n"
  205. " include required WAL files with specified method\n"));
  206. printf(_(" --xlogdir=XLOGDIR location for the transaction log directory\n"));
  207. printf(_(" -z, --gzip compress tar output\n"));
  208. printf(_(" -Z, --compress=0-9 compress tar output with given compression level\n"));
  209. printf(_("\nGeneral options:\n"));
  210. printf(_(" -c, --checkpoint=fast|spread\n"
  211. " set fast or spread checkpointing\n"));
  212. printf(_(" -l, --label=LABEL set backup label\n"));
  213. printf(_(" -P, --progress show progress information\n"));
  214. printf(_(" -v, --verbose output verbose messages\n"));
  215. printf(_(" -V, --version output version information, then exit\n"));
  216. printf(_(" -?, --help show this help, then exit\n"));
  217. printf(_("\nConnection options:\n"));
  218. printf(_(" -d, --dbname=CONNSTR connection string\n"));
  219. printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
  220. printf(_(" -p, --port=PORT database server port number\n"));
  221. printf(_(" -s, --status-interval=INTERVAL\n"
  222. " time between status packets sent to server (in seconds)\n"));
  223. printf(_(" -U, --username=NAME connect as specified database user\n"));
  224. printf(_(" -w, --no-password never prompt for password\n"));
  225. printf(_(" -W, --password force password prompt (should happen automatically)\n"));
  226. printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
  227. }
  228. /*
  229. * Called in the background process every time data is received.
  230. * On Unix, we check to see if there is any data on our pipe
  231. * (which would mean we have a stop position), and if it is, check if
  232. * it is time to stop.
  233. * On Windows, we are in a single process, so we can just check if it's
  234. * time to stop.
  235. */
  236. static bool
  237. reached_end_position(XLogRecPtr segendpos, uint32 timeline,
  238. bool segment_finished)
  239. {
  240. if (!has_xlogendptr)
  241. {
  242. #ifndef WIN32
  243. fd_set fds;
  244. struct timeval tv;
  245. int r;
  246. /*
  247. * Don't have the end pointer yet - check our pipe to see if it has
  248. * been sent yet.
  249. */
  250. FD_ZERO(&fds);
  251. FD_SET(bgpipe[0], &fds);
  252. MemSet(&tv, 0, sizeof(tv));
  253. r = select(bgpipe[0] + 1, &fds, NULL, NULL, &tv);
  254. if (r == 1)
  255. {
  256. char xlogend[64];
  257. uint32 hi,
  258. lo;
  259. MemSet(xlogend, 0, sizeof(xlogend));
  260. r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
  261. if (r < 0)
  262. {
  263. fprintf(stderr, _("%s: could not read from ready pipe: %s\n"),
  264. progname, strerror(errno));
  265. exit(1);
  266. }
  267. if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
  268. {
  269. fprintf(stderr,
  270. _("%s: could not parse transaction log location \"%s\"\n"),
  271. progname, xlogend);
  272. exit(1);
  273. }
  274. xlogendptr = ((uint64) hi) << 32 | lo;
  275. has_xlogendptr = 1;
  276. /*
  277. * Fall through to check if we've reached the point further
  278. * already.
  279. */
  280. }
  281. else
  282. {
  283. /*
  284. * No data received on the pipe means we don't know the end
  285. * position yet - so just say it's not time to stop yet.
  286. */
  287. return false;
  288. }
  289. #else
  290. /*
  291. * On win32, has_xlogendptr is set by the main thread, so if it's not
  292. * set here, we just go back and wait until it shows up.
  293. */
  294. return false;
  295. #endif
  296. }
  297. /*
  298. * At this point we have an end pointer, so compare it to the current
  299. * position to figure out if it's time to stop.
  300. */
  301. if (segendpos >= xlogendptr)
  302. return true;
  303. /*
  304. * Have end pointer, but haven't reached it yet - so tell the caller to
  305. * keep streaming.
  306. */
  307. return false;
  308. }
  309. typedef struct
  310. {
  311. PGconn *bgconn;
  312. XLogRecPtr startptr;
  313. char xlogdir[MAXPGPATH];
  314. char *sysidentifier;
  315. int timeline;
  316. } logstreamer_param;
  317. static int
  318. LogStreamerMain(logstreamer_param *param)
  319. {
  320. if (!ReceiveXlogStream(param->bgconn, param->startptr, param->timeline,
  321. param->sysidentifier, param->xlogdir,
  322. reached_end_position, standby_message_timeout,
  323. NULL))
  324. /*
  325. * Any errors will already have been reported in the function process,
  326. * but we need to tell the parent that we didn't shutdown in a nice
  327. * way.
  328. */
  329. return 1;
  330. PQfinish(param->bgconn);
  331. return 0;
  332. }
  333. /*
  334. * Initiate background process for receiving xlog during the backup.
  335. * The background stream will use its own database connection so we can
  336. * stream the logfile in parallel with the backups.
  337. */
  338. static void
  339. StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier)
  340. {
  341. logstreamer_param *param;
  342. uint32 hi,
  343. lo;
  344. param = pg_malloc0(sizeof(logstreamer_param));
  345. param->timeline = timeline;
  346. param->sysidentifier = sysidentifier;
  347. /* Convert the starting position */
  348. if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
  349. {
  350. fprintf(stderr,
  351. _("%s: could not parse transaction log location \"%s\"\n"),
  352. progname, startpos);
  353. disconnect_and_exit(1);
  354. }
  355. param->startptr = ((uint64) hi) << 32 | lo;
  356. /* Round off to even segment position */
  357. param->startptr -= param->startptr % XLOG_SEG_SIZE;
  358. #ifndef WIN32
  359. /* Create our background pipe */
  360. if (pipe(bgpipe) < 0)
  361. {
  362. fprintf(stderr,
  363. _("%s: could not create pipe for background process: %s\n"),
  364. progname, strerror(errno));
  365. disconnect_and_exit(1);
  366. }
  367. #endif
  368. /* Get a second connection */
  369. param->bgconn = GetConnection();
  370. if (!param->bgconn)
  371. /* Error message already written in GetConnection() */
  372. exit(1);
  373. /*
  374. * Always in plain format, so we can write to basedir/pg_xlog. But the
  375. * directory entry in the tar file may arrive later, so make sure it's
  376. * created before we start.
  377. */
  378. snprintf(param->xlogdir, sizeof(param->xlogdir), "%s/pg_xlog", basedir);
  379. verify_dir_is_empty_or_create(param->xlogdir);
  380. /*
  381. * Start a child process and tell it to start streaming. On Unix, this is
  382. * a fork(). On Windows, we create a thread.
  383. */
  384. #ifndef WIN32
  385. bgchild = fork();
  386. if (bgchild == 0)
  387. {
  388. /* in child process */
  389. exit(LogStreamerMain(param));
  390. }
  391. else if (bgchild < 0)
  392. {
  393. fprintf(stderr, _("%s: could not create background process: %s\n"),
  394. progname, strerror(errno));
  395. disconnect_and_exit(1);
  396. }
  397. /*
  398. * Else we are in the parent process and all is well.
  399. */
  400. #else /* WIN32 */
  401. bgchild = _beginthreadex(NULL, 0, (void *) LogStreamerMain, param, 0, NULL);
  402. if (bgchild == 0)
  403. {
  404. fprintf(stderr, _("%s: could not create background thread: %s\n"),
  405. progname, strerror(errno));
  406. disconnect_and_exit(1);
  407. }
  408. #endif
  409. }
  410. /*
  411. * Verify that the given directory exists and is empty. If it does not
  412. * exist, it is created. If it exists but is not empty, an error will
  413. * be give and the process ended.
  414. */
  415. static void
  416. verify_dir_is_empty_or_create(char *dirname)
  417. {
  418. switch (pg_check_dir(dirname))
  419. {
  420. case 0:
  421. /*
  422. * Does not exist, so create
  423. */
  424. if (pg_mkdir_p(dirname, S_IRWXU) == -1)
  425. {
  426. fprintf(stderr,
  427. _("%s: could not create directory \"%s\": %s\n"),
  428. progname, dirname, strerror(errno));
  429. disconnect_and_exit(1);
  430. }
  431. return;
  432. case 1:
  433. /*
  434. * Exists, empty
  435. */
  436. return;
  437. case 2:
  438. case 3:
  439. case 4:
  440. /*
  441. * Exists, not empty
  442. */
  443. fprintf(stderr,
  444. _("%s: directory \"%s\" exists but is not empty\n"),
  445. progname, dirname);
  446. disconnect_and_exit(1);
  447. case -1:
  448. /*
  449. * Access problem
  450. */
  451. fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
  452. progname, dirname, strerror(errno));
  453. disconnect_and_exit(1);
  454. }
  455. }
  456. /*
  457. * Print a progress report based on the global variables. If verbose output
  458. * is enabled, also print the current file name.
  459. *
  460. * Progress report is written at maximum once per second, unless the
  461. * force parameter is set to true.
  462. */
  463. static void
  464. progress_report(int tablespacenum, const char *filename, bool force)
  465. {
  466. int percent;
  467. char totaldone_str[32];
  468. char totalsize_str[32];
  469. pg_time_t now;
  470. if (!showprogress)
  471. return;
  472. now = time(NULL);
  473. if (now == last_progress_report && !force)
  474. return; /* Max once per second */
  475. last_progress_report = now;
  476. percent = totalsize ? (int) ((totaldone / 1024) * 100 / totalsize) : 0;
  477. /*
  478. * Avoid overflowing past 100% or the full size. This may make the total
  479. * size number change as we approach the end of the backup (the estimate
  480. * will always be wrong if WAL is included), but that's better than having
  481. * the done column be bigger than the total.
  482. */
  483. if (percent > 100)
  484. percent = 100;
  485. if (totaldone / 1024 > totalsize)
  486. totalsize = totaldone / 1024;
  487. /*
  488. * Separate step to keep platform-dependent format code out of
  489. * translatable strings. And we only test for INT64_FORMAT availability
  490. * in snprintf, not fprintf.
  491. */
  492. snprintf(totaldone_str, sizeof(totaldone_str), INT64_FORMAT,
  493. totaldone / 1024);
  494. snprintf(totalsize_str, sizeof(totalsize_str), INT64_FORMAT, totalsize);
  495. #define VERBOSE_FILENAME_LENGTH 35
  496. if (verbose)
  497. {
  498. if (!filename)
  499. /*
  500. * No filename given, so clear the status line (used for last
  501. * call)
  502. */
  503. fprintf(stderr,
  504. ngettext("%*s/%s kB (100%%), %d/%d tablespace %*s",
  505. "%*s/%s kB (100%%), %d/%d tablespaces %*s",
  506. tablespacecount),
  507. (int) strlen(totalsize_str),
  508. totaldone_str, totalsize_str,
  509. tablespacenum, tablespacecount,
  510. VERBOSE_FILENAME_LENGTH + 5, "");
  511. else
  512. {
  513. bool truncate = (strlen(filename) > VERBOSE_FILENAME_LENGTH);
  514. fprintf(stderr,
  515. ngettext("%*s/%s kB (%d%%), %d/%d tablespace (%s%-*.*s)",
  516. "%*s/%s kB (%d%%), %d/%d tablespaces (%s%-*.*s)",
  517. tablespacecount),
  518. (int) strlen(totalsize_str),
  519. totaldone_str, totalsize_str, percent,
  520. tablespacenum, tablespacecount,
  521. /* Prefix with "..." if we do leading truncation */
  522. truncate ? "..." : "",
  523. truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
  524. truncate ? VERBOSE_FILENAME_LENGTH - 3 : VERBOSE_FILENAME_LENGTH,
  525. /* Truncate filename at beginning if it's too long */
  526. truncate ? filename + strlen(filename) - VERBOSE_FILENAME_LENGTH + 3 : filename);
  527. }
  528. }
  529. else
  530. fprintf(stderr,
  531. ngettext("%*s/%s kB (%d%%), %d/%d tablespace",
  532. "%*s/%s kB (%d%%), %d/%d tablespaces",
  533. tablespacecount),
  534. (int) strlen(totalsize_str),
  535. totaldone_str, totalsize_str, percent,
  536. tablespacenum, tablespacecount);
  537. fprintf(stderr, "\r");
  538. }
  539. static int32
  540. parse_max_rate(char *src)
  541. {
  542. double result;
  543. char *after_num;
  544. char *suffix = NULL;
  545. errno = 0;
  546. result = strtod(src, &after_num);
  547. if (src == after_num)
  548. {
  549. fprintf(stderr,
  550. _("%s: transfer rate \"%s\" is not a valid value\n"),
  551. progname, src);
  552. exit(1);
  553. }
  554. if (errno != 0)
  555. {
  556. fprintf(stderr,
  557. _("%s: invalid transfer rate \"%s\": %s\n"),
  558. progname, src, strerror(errno));
  559. exit(1);
  560. }
  561. if (result <= 0)
  562. {
  563. /*
  564. * Reject obviously wrong values here.
  565. */
  566. fprintf(stderr, _("%s: transfer rate must be greater than zero\n"),
  567. progname);
  568. exit(1);
  569. }
  570. /*
  571. * Evaluate suffix, after skipping over possible whitespace. Lack of
  572. * suffix means kilobytes.
  573. */
  574. while (*after_num != '\0' && isspace((unsigned char) *after_num))
  575. after_num++;
  576. if (*after_num != '\0')
  577. {
  578. suffix = after_num;
  579. if (*after_num == 'k')
  580. {
  581. /* kilobyte is the expected unit. */
  582. after_num++;
  583. }
  584. else if (*after_num == 'M')
  585. {
  586. after_num++;
  587. result *= 1024.0;
  588. }
  589. }
  590. /* The rest can only consist of white space. */
  591. while (*after_num != '\0' && isspace((unsigned char) *after_num))
  592. after_num++;
  593. if (*after_num != '\0')
  594. {
  595. fprintf(stderr,
  596. _("%s: invalid --max-rate unit: \"%s\"\n"),
  597. progname, suffix);
  598. exit(1);
  599. }
  600. /* Valid integer? */
  601. if ((uint64) result != (uint64) ((uint32) result))
  602. {
  603. fprintf(stderr,
  604. _("%s: transfer rate \"%s\" exceeds integer range\n"),
  605. progname, src);
  606. exit(1);
  607. }
  608. /*
  609. * The range is checked on the server side too, but avoid the server
  610. * connection if a nonsensical value was passed.
  611. */
  612. if (result < MAX_RATE_LOWER || result > MAX_RATE_UPPER)
  613. {
  614. fprintf(stderr,
  615. _("%s: transfer rate \"%s\" is out of range\n"),
  616. progname, src);
  617. exit(1);
  618. }
  619. return (int32) result;
  620. }
  621. /*
  622. * Write a piece of tar data
  623. */
  624. static void
  625. writeTarData(
  626. #ifdef HAVE_LIBZ
  627. gzFile ztarfile,
  628. #endif
  629. FILE *tarfile, char *buf, int r, char *current_file)
  630. {
  631. #ifdef HAVE_LIBZ
  632. if (ztarfile != NULL)
  633. {
  634. if (gzwrite(ztarfile, buf, r) != r)
  635. {
  636. fprintf(stderr,
  637. _("%s: could not write to compressed file \"%s\": %s\n"),
  638. progname, current_file, get_gz_error(ztarfile));
  639. disconnect_and_exit(1);
  640. }
  641. }
  642. else
  643. #endif
  644. {
  645. if (fwrite(buf, r, 1, tarfile) != 1)
  646. {
  647. fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
  648. progname, current_file, strerror(errno));
  649. disconnect_and_exit(1);
  650. }
  651. }
  652. }
  653. #ifdef HAVE_LIBZ
  654. #define WRITE_TAR_DATA(buf, sz) writeTarData(ztarfile, tarfile, buf, sz, filename)
  655. #else
  656. #define WRITE_TAR_DATA(buf, sz) writeTarData(tarfile, buf, sz, filename)
  657. #endif
  658. /*
  659. * Receive a tar format file from the connection to the server, and write
  660. * the data from this file directly into a tar file. If compression is
  661. * enabled, the data will be compressed while written to the file.
  662. *
  663. * The file will be named base.tar[.gz] if it's for the main data directory
  664. * or <tablespaceoid>.tar[.gz] if it's for another tablespace.
  665. *
  666. * No attempt to inspect or validate the contents of the file is done.
  667. */
  668. static void
  669. ReceiveTarFile(PGconn *conn, PGresult *res, int rownum)
  670. {
  671. char filename[MAXPGPATH];
  672. char *copybuf = NULL;
  673. FILE *tarfile = NULL;
  674. char tarhdr[512];
  675. bool basetablespace = PQgetisnull(res, rownum, 0);
  676. bool in_tarhdr = true;
  677. bool skip_file = false;
  678. size_t tarhdrsz = 0;
  679. size_t filesz = 0;
  680. #ifdef HAVE_LIBZ
  681. gzFile ztarfile = NULL;
  682. #endif
  683. if (basetablespace)
  684. {
  685. /*
  686. * Base tablespaces
  687. */
  688. if (strcmp(basedir, "-") == 0)
  689. {
  690. #ifdef HAVE_LIBZ
  691. if (compresslevel != 0)
  692. {
  693. ztarfile = gzdopen(dup(fileno(stdout)), "wb");
  694. if (gzsetparams(ztarfile, compresslevel,
  695. Z_DEFAULT_STRATEGY) != Z_OK)
  696. {
  697. fprintf(stderr,
  698. _("%s: could not set compression level %d: %s\n"),
  699. progname, compresslevel, get_gz_error(ztarfile));
  700. disconnect_and_exit(1);
  701. }
  702. }
  703. else
  704. #endif
  705. tarfile = stdout;
  706. strcpy(filename, "-");
  707. }
  708. else
  709. {
  710. #ifdef HAVE_LIBZ
  711. if (compresslevel != 0)
  712. {
  713. snprintf(filename, sizeof(filename), "%s/base.tar.gz", basedir);
  714. ztarfile = gzopen(filename, "wb");
  715. if (gzsetparams(ztarfile, compresslevel,
  716. Z_DEFAULT_STRATEGY) != Z_OK)
  717. {
  718. fprintf(stderr,
  719. _("%s: could not set compression level %d: %s\n"),
  720. progname, compresslevel, get_gz_error(ztarfile));
  721. disconnect_and_exit(1);
  722. }
  723. }
  724. else
  725. #endif
  726. {
  727. snprintf(filename, sizeof(filename), "%s/base.tar", basedir);
  728. tarfile = fopen(filename, "wb");
  729. }
  730. }
  731. }
  732. else
  733. {
  734. /*
  735. * Specific tablespace
  736. */
  737. #ifdef HAVE_LIBZ
  738. if (compresslevel != 0)
  739. {
  740. snprintf(filename, sizeof(filename), "%s/%s.tar.gz", basedir,
  741. PQgetvalue(res, rownum, 0));
  742. ztarfile = gzopen(filename, "wb");
  743. if (gzsetparams(ztarfile, compresslevel,
  744. Z_DEFAULT_STRATEGY) != Z_OK)
  745. {
  746. fprintf(stderr,
  747. _("%s: could not set compression level %d: %s\n"),
  748. progname, compresslevel, get_gz_error(ztarfile));
  749. disconnect_and_exit(1);
  750. }
  751. }
  752. else
  753. #endif
  754. {
  755. snprintf(filename, sizeof(filename), "%s/%s.tar", basedir,
  756. PQgetvalue(res, rownum, 0));
  757. tarfile = fopen(filename, "wb");
  758. }
  759. }
  760. #ifdef HAVE_LIBZ
  761. if (compresslevel != 0)
  762. {
  763. if (!ztarfile)
  764. {
  765. /* Compression is in use */
  766. fprintf(stderr,
  767. _("%s: could not create compressed file \"%s\": %s\n"),
  768. progname, filename, get_gz_error(ztarfile));
  769. disconnect_and_exit(1);
  770. }
  771. }
  772. else
  773. #endif
  774. {
  775. /* Either no zlib support, or zlib support but compresslevel = 0 */
  776. if (!tarfile)
  777. {
  778. fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
  779. progname, filename, strerror(errno));
  780. disconnect_and_exit(1);
  781. }
  782. }
  783. /*
  784. * Get the COPY data stream
  785. */
  786. res = PQgetResult(conn);
  787. if (PQresultStatus(res) != PGRES_COPY_OUT)
  788. {
  789. fprintf(stderr, _("%s: could not get COPY data stream: %s"),
  790. progname, PQerrorMessage(conn));
  791. disconnect_and_exit(1);
  792. }
  793. while (1)
  794. {
  795. int r;
  796. if (copybuf != NULL)
  797. {
  798. PQfreemem(copybuf);
  799. copybuf = NULL;
  800. }
  801. r = PQgetCopyData(conn, &copybuf, 0);
  802. if (r == -1)
  803. {
  804. /*
  805. * End of chunk. If requested, and this is the base tablespace,
  806. * write recovery.conf into the tarfile. When done, close the file
  807. * (but not stdout).
  808. *
  809. * Also, write two completely empty blocks at the end of the tar
  810. * file, as required by some tar programs.
  811. */
  812. char zerobuf[1024];
  813. MemSet(zerobuf, 0, sizeof(zerobuf));
  814. if (basetablespace && writerecoveryconf)
  815. {
  816. char header[512];
  817. int padding;
  818. tarCreateHeader(header, "recovery.conf", NULL,
  819. recoveryconfcontents->len,
  820. 0600, 04000, 02000,
  821. time(NULL));
  822. padding = ((recoveryconfcontents->len + 511) & ~511) - recoveryconfcontents->len;
  823. WRITE_TAR_DATA(header, sizeof(header));
  824. WRITE_TAR_DATA(recoveryconfcontents->data, recoveryconfcontents->len);
  825. if (padding)
  826. WRITE_TAR_DATA(zerobuf, padding);
  827. }
  828. /* 2 * 512 bytes empty data at end of file */
  829. WRITE_TAR_DATA(zerobuf, sizeof(zerobuf));
  830. #ifdef HAVE_LIBZ
  831. if (ztarfile != NULL)
  832. {
  833. if (gzclose(ztarfile) != 0)
  834. {
  835. fprintf(stderr,
  836. _("%s: could not close compressed file \"%s\": %s\n"),
  837. progname, filename, get_gz_error(ztarfile));
  838. disconnect_and_exit(1);
  839. }
  840. }
  841. else
  842. #endif
  843. {
  844. if (strcmp(basedir, "-") != 0)
  845. {
  846. if (fclose(tarfile) != 0)
  847. {
  848. fprintf(stderr,
  849. _("%s: could not close file \"%s\": %s\n"),
  850. progname, filename, strerror(errno));
  851. disconnect_and_exit(1);
  852. }
  853. }
  854. }
  855. break;
  856. }
  857. else if (r == -2)
  858. {
  859. fprintf(stderr, _("%s: could not read COPY data: %s"),
  860. progname, PQerrorMessage(conn));
  861. disconnect_and_exit(1);
  862. }
  863. if (!writerecoveryconf || !basetablespace)
  864. {
  865. /*
  866. * When not writing recovery.conf, or when not working on the base
  867. * tablespace, we never have to look for an existing recovery.conf
  868. * file in the stream.
  869. */
  870. WRITE_TAR_DATA(copybuf, r);
  871. }
  872. else
  873. {
  874. /*
  875. * Look for a recovery.conf in the existing tar stream. If it's
  876. * there, we must skip it so we can later overwrite it with our
  877. * own version of the file.
  878. *
  879. * To do this, we have to process the individual files inside the
  880. * TAR stream. The stream consists of a header and zero or more
  881. * chunks, all 512 bytes long. The stream from the server is
  882. * broken up into smaller pieces, so we have to track the size of
  883. * the files to find the next header structure.
  884. */
  885. int rr = r;
  886. int pos = 0;
  887. while (rr > 0)
  888. {
  889. if (in_tarhdr)
  890. {
  891. /*
  892. * We're currently reading a header structure inside the
  893. * TAR stream, i.e. the file metadata.
  894. */
  895. if (tarhdrsz < 512)
  896. {
  897. /*
  898. * Copy the header structure into tarhdr in case the
  899. * header is not aligned to 512 bytes or it's not
  900. * returned in whole by the last PQgetCopyData call.
  901. */
  902. int hdrleft;
  903. int bytes2copy;
  904. hdrleft = 512 - tarhdrsz;
  905. bytes2copy = (rr > hdrleft ? hdrleft : rr);
  906. memcpy(&tarhdr[tarhdrsz], copybuf + pos, bytes2copy);
  907. rr -= bytes2copy;
  908. pos += bytes2copy;
  909. tarhdrsz += bytes2copy;
  910. }
  911. else
  912. {
  913. /*
  914. * We have the complete header structure in tarhdr,
  915. * look at the file metadata: - the subsequent file
  916. * contents have to be skipped if the filename is
  917. * recovery.conf - find out the size of the file
  918. * padded to the next multiple of 512
  919. */
  920. int padding;
  921. skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
  922. sscanf(&tarhdr[124], "%11o", (unsigned int *) &filesz);
  923. padding = ((filesz + 511) & ~511) - filesz;
  924. filesz += padding;
  925. /* Next part is the file, not the header */
  926. in_tarhdr = false;
  927. /*
  928. * If we're not skipping the file, write the tar
  929. * header unmodified.
  930. */
  931. if (!skip_file)
  932. WRITE_TAR_DATA(tarhdr, 512);
  933. }
  934. }
  935. else
  936. {
  937. /*
  938. * We're processing a file's contents.
  939. */
  940. if (filesz > 0)
  941. {
  942. /*
  943. * We still have data to read (and possibly write).
  944. */
  945. int bytes2write;
  946. bytes2write = (filesz > rr ? rr : filesz);
  947. if (!skip_file)
  948. WRITE_TAR_DATA(copybuf + pos, bytes2write);
  949. rr -= bytes2write;
  950. pos += bytes2write;
  951. filesz -= bytes2write;
  952. }
  953. else
  954. {
  955. /*
  956. * No more data in the current file, the next piece of
  957. * data (if any) will be a new file header structure.
  958. */
  959. in_tarhdr = true;
  960. skip_file = false;
  961. tarhdrsz = 0;
  962. filesz = 0;
  963. }
  964. }
  965. }
  966. }
  967. totaldone += r;
  968. progress_report(rownum, filename, false);
  969. } /* while (1) */
  970. progress_report(rownum, filename, true);
  971. if (copybuf != NULL)
  972. PQfreemem(copybuf);
  973. }
  974. /*
  975. * Retrieve tablespace path, either relocated or original depending on whether
  976. * -T was passed or not.
  977. */
  978. static const char *
  979. get_tablespace_mapping(const char *dir)
  980. {
  981. TablespaceListCell *cell;
  982. for (cell = tablespace_dirs.head; cell; cell = cell->next)
  983. if (strcmp(dir, cell->old_dir) == 0)
  984. return cell->new_dir;
  985. return dir;
  986. }
  987. /*
  988. * Update symlinks to reflect relocated tablespace.
  989. */
  990. static void
  991. update_tablespace_symlink(Oid oid, const char *old_dir)
  992. {
  993. const char *new_dir = get_tablespace_mapping(old_dir);
  994. if (strcmp(old_dir, new_dir) != 0)
  995. {
  996. char *linkloc = psprintf("%s/pg_tblspc/%d", basedir, oid);
  997. if (unlink(linkloc) != 0 && errno != ENOENT)
  998. {
  999. fprintf(stderr, _("%s: could not remove symbolic link \"%s\": %s"),
  1000. progname, linkloc, strerror(errno));
  1001. disconnect_and_exit(1);
  1002. }
  1003. if (symlink(new_dir, linkloc) != 0)
  1004. {
  1005. fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s"),
  1006. progname, linkloc, strerror(errno));
  1007. disconnect_and_exit(1);
  1008. }
  1009. }
  1010. }
  1011. /*
  1012. * Receive a tar format stream from the connection to the server, and unpack
  1013. * the contents of it into a directory. Only files, directories and
  1014. * symlinks are supported, no other kinds of special files.
  1015. *
  1016. * If the data is for the main data directory, it will be restored in the
  1017. * specified directory. If it's for another tablespace, it will be restored
  1018. * in the original or mapped directory.
  1019. */
  1020. static void
  1021. ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum)
  1022. {
  1023. char current_path[MAXPGPATH];
  1024. char filename[MAXPGPATH];
  1025. int current_len_left;
  1026. int current_padding = 0;
  1027. bool basetablespace = PQgetisnull(res, rownum, 0);
  1028. char *copybuf = NULL;
  1029. FILE *file = NULL;
  1030. if (basetablespace)
  1031. strlcpy(current_path, basedir, sizeof(current_path));
  1032. else
  1033. strlcpy(current_path, get_tablespace_mapping(PQgetvalue(res, rownum, 1)), sizeof(current_path));
  1034. /*
  1035. * Get the COPY data
  1036. */
  1037. res = PQgetResult(conn);
  1038. if (PQresultStatus(res) != PGRES_COPY_OUT)
  1039. {
  1040. fprintf(stderr, _("%s: could not get COPY data stream: %s"),
  1041. progname, PQerrorMessage(conn));
  1042. disconnect_and_exit(1);
  1043. }
  1044. while (1)
  1045. {
  1046. int r;
  1047. if (copybuf != NULL)
  1048. {
  1049. PQfreemem(copybuf);
  1050. copybuf = NULL;
  1051. }
  1052. r = PQgetCopyData(conn, &copybuf, 0);
  1053. if (r == -1)
  1054. {
  1055. /*
  1056. * End of chunk
  1057. */
  1058. if (file)
  1059. fclose(file);
  1060. break;
  1061. }
  1062. else if (r == -2)
  1063. {
  1064. fprintf(stderr, _("%s: could not read COPY data: %s"),
  1065. progname, PQerrorMessage(conn));
  1066. disconnect_and_exit(1);
  1067. }
  1068. if (file == NULL)
  1069. {
  1070. int filemode;
  1071. /*
  1072. * No current file, so this must be the header for a new file
  1073. */
  1074. if (r != 512)
  1075. {
  1076. fprintf(stderr, _("%s: invalid tar block header size: %d\n"),
  1077. progname, r);
  1078. disconnect_and_exit(1);
  1079. }
  1080. totaldone += 512;
  1081. if (sscanf(copybuf + 124, "%11o", &current_len_left) != 1)
  1082. {
  1083. fprintf(stderr, _("%s: could not parse file size\n"),
  1084. progname);
  1085. disconnect_and_exit(1);
  1086. }
  1087. /* Set permissions on the file */
  1088. if (sscanf(&copybuf[100], "%07o ", &filemode) != 1)
  1089. {
  1090. fprintf(stderr, _("%s: could not parse file mode\n"),
  1091. progname);
  1092. disconnect_and_exit(1);
  1093. }
  1094. /*
  1095. * All files are padded up to 512 bytes
  1096. */
  1097. current_padding =
  1098. ((current_len_left + 511) & ~511) - current_len_left;
  1099. /*
  1100. * First part of header is zero terminated filename
  1101. */
  1102. snprintf(filename, sizeof(filename), "%s/%s", current_path,
  1103. copybuf);
  1104. if (filename[strlen(filename) - 1] == '/')
  1105. {
  1106. /*
  1107. * Ends in a slash means directory or symlink to directory
  1108. */
  1109. if (copybuf[156] == '5')
  1110. {
  1111. /*
  1112. * Directory
  1113. */
  1114. filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
  1115. if (mkdir(filename, S_IRWXU) != 0)
  1116. {
  1117. /*
  1118. * When streaming WAL, pg_xlog will have been created
  1119. * by the wal receiver process. Also, when transaction
  1120. * log directory location was specified, pg_xlog has
  1121. * already been created as a symbolic link before
  1122. * starting the actual backup. So just ignore failure
  1123. * on them.
  1124. */
  1125. if ((!streamwal && (strcmp(xlog_dir, "") == 0))
  1126. || strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0)
  1127. {
  1128. fprintf(stderr,
  1129. _("%s: could not create directory \"%s\": %s\n"),
  1130. progname, filename, strerror(errno));
  1131. disconnect_and_exit(1);
  1132. }
  1133. }
  1134. #ifndef WIN32
  1135. if (chmod(filename, (mode_t) filemode))
  1136. fprintf(stderr,
  1137. _("%s: could not set permissions on directory \"%s\": %s\n"),
  1138. progname, filename, strerror(errno));
  1139. #endif
  1140. }
  1141. else if (copybuf[156] == '2')
  1142. {
  1143. /*
  1144. * Symbolic link
  1145. */
  1146. filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
  1147. if (symlink(&copybuf[157], filename) != 0)
  1148. {
  1149. fprintf(stderr,
  1150. _("%s: could not create symbolic link from \"%s\" to \"%s\": %s\n"),
  1151. progname, filename, &copybuf[157], strerror(errno));
  1152. disconnect_and_exit(1);
  1153. }
  1154. }
  1155. else
  1156. {
  1157. fprintf(stderr,
  1158. _("%s: unrecognized link indicator \"%c\"\n"),
  1159. progname, copybuf[156]);
  1160. disconnect_and_exit(1);
  1161. }
  1162. continue; /* directory or link handled */
  1163. }
  1164. /*
  1165. * regular file
  1166. */
  1167. file = fopen(filename, "wb");
  1168. if (!file)
  1169. {
  1170. fprintf(stderr, _("%s: could not create file \"%s\": %s\n"),
  1171. progname, filename, strerror(errno));
  1172. disconnect_and_exit(1);
  1173. }
  1174. #ifndef WIN32
  1175. if (chmod(filename, (mode_t) filemode))
  1176. fprintf(stderr, _("%s: could not set permissions on file \"%s\": %s\n"),
  1177. progname, filename, strerror(errno));
  1178. #endif
  1179. if (current_len_left == 0)
  1180. {
  1181. /*
  1182. * Done with this file, next one will be a new tar header
  1183. */
  1184. fclose(file);
  1185. file = NULL;
  1186. continue;
  1187. }
  1188. } /* new file */
  1189. else
  1190. {
  1191. /*
  1192. * Continuing blocks in existing file
  1193. */
  1194. if (current_len_left == 0 && r == current_padding)
  1195. {
  1196. /*
  1197. * Received the padding block for this file, ignore it and
  1198. * close the file, then move on to the next tar header.
  1199. */
  1200. fclose(file);
  1201. file = NULL;
  1202. totaldone += r;
  1203. continue;
  1204. }
  1205. if (fwrite(copybuf, r, 1, file) != 1)
  1206. {
  1207. fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
  1208. progname, filename, strerror(errno));
  1209. disconnect_and_exit(1);
  1210. }
  1211. totaldone += r;
  1212. progress_report(rownum, filename, false);
  1213. current_len_left -= r;
  1214. if (current_len_left == 0 && current_padding == 0)
  1215. {
  1216. /*
  1217. * Received the last block, and there is no padding to be
  1218. * expected. Close the file and move on to the next tar
  1219. * header.
  1220. */
  1221. fclose(file);
  1222. file = NULL;
  1223. continue;
  1224. }
  1225. } /* continuing data in existing file */
  1226. } /* loop over all data blocks */
  1227. progress_report(rownum, filename, true);
  1228. if (file != NULL)
  1229. {
  1230. fprintf(stderr,
  1231. _("%s: COPY stream ended before last file was finished\n"),
  1232. progname);
  1233. disconnect_and_exit(1);
  1234. }
  1235. if (copybuf != NULL)
  1236. PQfreemem(copybuf);
  1237. if (basetablespace && writerecoveryconf)
  1238. WriteRecoveryConf();
  1239. }
  1240. /*
  1241. * Escape a parameter value so that it can be used as part of a libpq
  1242. * connection string, e.g. in:
  1243. *
  1244. * application_name=<value>
  1245. *
  1246. * The returned string is malloc'd. Return NULL on out-of-memory.
  1247. */
  1248. static char *
  1249. escapeConnectionParameter(const char *src)
  1250. {
  1251. bool need_quotes = false;
  1252. bool need_escaping = false;
  1253. const char *p;
  1254. char *dstbuf;
  1255. char *dst;
  1256. /*
  1257. * First check if quoting is needed. Any quote (') or backslash (\)
  1258. * characters need to be escaped. Parameters are separated by whitespace,
  1259. * so any string containing whitespace characters need to be quoted. An
  1260. * empty string is represented by ''.
  1261. */
  1262. if (strchr(src, '\'') != NULL || strchr(src, '\\') != NULL)
  1263. need_escaping = true;
  1264. for (p = src; *p; p++)
  1265. {
  1266. if (isspace((unsigned char) *p))
  1267. {
  1268. need_quotes = true;
  1269. break;
  1270. }
  1271. }
  1272. if (*src == '\0')
  1273. return pg_strdup("''");
  1274. if (!need_quotes && !need_escaping)
  1275. return pg_strdup(src); /* no quoting or escaping needed */
  1276. /*
  1277. * Allocate a buffer large enough for the worst case that all the source
  1278. * characters need to be escaped, plus quotes.
  1279. */
  1280. dstbuf = pg_malloc(strlen(src) * 2 + 2 + 1);
  1281. dst = dstbuf;
  1282. if (need_quotes)
  1283. *(dst++) = '\'';
  1284. for (; *src; src++)
  1285. {
  1286. if (*src == '\'' || *src == '\\')
  1287. *(dst++) = '\\';
  1288. *(dst++) = *src;
  1289. }
  1290. if (need_quotes)
  1291. *(dst++) = '\'';
  1292. *dst = '\0';
  1293. return dstbuf;
  1294. }
  1295. /*
  1296. * Escape a string so that it can be used as a value in a key-value pair
  1297. * a configuration file.
  1298. */
  1299. static char *
  1300. escape_quotes(const char *src)
  1301. {
  1302. char *result = escape_single_quotes_ascii(src);
  1303. if (!result)
  1304. {
  1305. fprintf(stderr, _("%s: out of memory\n"), progname);
  1306. exit(1);
  1307. }
  1308. return result;
  1309. }
  1310. /*
  1311. * Create a recovery.conf file in memory using a PQExpBuffer
  1312. */
  1313. static void
  1314. GenerateRecoveryConf(PGconn *conn)
  1315. {
  1316. PQconninfoOption *connOptions;
  1317. PQconninfoOption *option;
  1318. PQExpBufferData conninfo_buf;
  1319. char *escaped;
  1320. recoveryconfcontents = createPQExpBuffer();
  1321. if (!recoveryconfcontents)
  1322. {
  1323. fprintf(stderr, _("%s: out of memory\n"), progname);
  1324. disconnect_and_exit(1);
  1325. }
  1326. connOptions = PQconninfo(conn);
  1327. if (connOptions == NULL)
  1328. {
  1329. fprintf(stderr, _("%s: out of memory\n"), progname);
  1330. disconnect_and_exit(1);
  1331. }
  1332. appendPQExpBufferStr(recoveryconfcontents, "standby_mode = 'on'\n");
  1333. initPQExpBuffer(&conninfo_buf);
  1334. for (option = connOptions; option && option->keyword; option++)
  1335. {
  1336. /*
  1337. * Do not emit this setting if: - the setting is "replication",
  1338. * "dbname" or "fallback_application_name", since these would be
  1339. * overridden by the libpqwalreceiver module anyway. - not set or
  1340. * empty.
  1341. */
  1342. if (strcmp(option->keyword, "replication") == 0 ||
  1343. strcmp(option->keyword, "dbname") == 0 ||
  1344. strcmp(option->keyword, "fallback_application_name") == 0 ||
  1345. (option->val == NULL) ||
  1346. (option->val != NULL && option->val[0] == '\0'))
  1347. continue;
  1348. /* Separate key-value pairs with spaces */
  1349. if (conninfo_buf.len != 0)
  1350. appendPQExpBufferStr(&conninfo_buf, " ");
  1351. /*
  1352. * Write "keyword=value" pieces, the value string is escaped and/or
  1353. * quoted if necessary.
  1354. */
  1355. escaped = escapeConnectionParameter(option->val);
  1356. appendPQExpBuffer(&conninfo_buf, "%s=%s", option->keyword, escaped);
  1357. free(escaped);
  1358. }
  1359. /*
  1360. * Escape the connection string, so that it can be put in the config file.
  1361. * Note that this is different from the escaping of individual connection
  1362. * options above!
  1363. */
  1364. escaped = escape_quotes(conninfo_buf.data);
  1365. appendPQExpBuffer(recoveryconfcontents, "primary_conninfo = '%s'\n", escaped);
  1366. free(escaped);
  1367. if (PQExpBufferBroken(recoveryconfcontents) ||
  1368. PQExpBufferDataBroken(conninfo_buf))
  1369. {
  1370. fprintf(stderr, _("%s: out of memory\n"), progname);
  1371. disconnect_and_exit(1);
  1372. }
  1373. termPQExpBuffer(&conninfo_buf);
  1374. PQconninfoFree(connOptions);
  1375. }
  1376. /*
  1377. * Write a recovery.conf file into the directory specified in basedir,
  1378. * with the contents already collected in memory.
  1379. */
  1380. static void
  1381. WriteRecoveryConf(void)
  1382. {
  1383. char filename[MAXPGPATH];
  1384. FILE *cf;
  1385. sprintf(filename, "%s/recovery.conf", basedir);
  1386. cf = fopen(filename, "w");
  1387. if (cf == NULL)
  1388. {
  1389. fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno));
  1390. disconnect_and_exit(1);
  1391. }
  1392. if (fwrite(recoveryconfcontents->data, recoveryconfcontents->len, 1, cf) != 1)
  1393. {
  1394. fprintf(stderr,
  1395. _("%s: could not write to file \"%s\": %s\n"),
  1396. progname, filename, strerror(errno));
  1397. disconnect_and_exit(1);
  1398. }
  1399. fclose(cf);
  1400. }
  1401. static void
  1402. BaseBackup(void)
  1403. {
  1404. PGresult *res;
  1405. char *sysidentifier;
  1406. uint32 latesttli;
  1407. uint32 starttli;
  1408. char *basebkp;
  1409. char escaped_label[MAXPGPATH];
  1410. char *maxrate_clause = NULL;
  1411. int i;
  1412. char xlogstart[64];
  1413. char xlogend[64];
  1414. int minServerMajor,
  1415. maxServerMajor;
  1416. int serverMajor;
  1417. /*
  1418. * Connect in replication mode to the server
  1419. */
  1420. conn = GetConnection();
  1421. if (!conn)
  1422. /* Error message already written in GetConnection() */
  1423. exit(1);
  1424. /*
  1425. * Check server version. BASE_BACKUP command was introduced in 9.1, so we
  1426. * can't work with servers older than 9.1.
  1427. */
  1428. minServerMajor = 901;
  1429. maxServerMajor = PG_VERSION_NUM / 100;
  1430. serverMajor = PQserverVersion(conn) / 100;
  1431. if (serverMajor < minServerMajor || serverMajor > maxServerMajor)
  1432. {
  1433. const char *serverver = PQparameterStatus(conn, "server_version");
  1434. fprintf(stderr, _("%s: incompatible server version %s\n"),
  1435. progname, serverver ? serverver : "'unknown'");
  1436. disconnect_and_exit(1);
  1437. }
  1438. /*
  1439. * If WAL streaming was requested, also check that the server is new
  1440. * enough for that.
  1441. */
  1442. if (streamwal && !CheckServerVersionForStreaming(conn))
  1443. {
  1444. /* Error message already written in CheckServerVersionForStreaming() */
  1445. disconnect_and_exit(1);
  1446. }
  1447. /*
  1448. * Build contents of recovery.conf if requested
  1449. */
  1450. if (writerecoveryconf)
  1451. GenerateRecoveryConf(conn);
  1452. /*
  1453. * Run IDENTIFY_SYSTEM so we can get the timeline
  1454. */
  1455. res = PQexec(conn, "IDENTIFY_SYSTEM");
  1456. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  1457. {
  1458. fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
  1459. progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn));
  1460. disconnect_and_exit(1);
  1461. }
  1462. if (PQntuples(res) != 1 || PQnfields(res) < 3)
  1463. {
  1464. fprintf(stderr,
  1465. _("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
  1466. progname, PQntuples(res), PQnfields(res), 1, 3);
  1467. disconnect_and_exit(1);
  1468. }
  1469. sysidentifier = pg_strdup(PQgetvalue(res, 0, 0));
  1470. latesttli = atoi(PQgetvalue(res, 0, 1));
  1471. PQclear(res);
  1472. /*
  1473. * Start the actual backup
  1474. */
  1475. PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i);
  1476. if (maxrate > 0)
  1477. maxrate_clause = psprintf("MAX_RATE %u", maxrate);
  1478. basebkp =
  1479. psprintf("BASE_BACKUP LABEL '%s' %s %s %s %s %s",
  1480. escaped_label,
  1481. showprogress ? "PROGRESS" : "",
  1482. includewal && !streamwal ? "WAL" : "",
  1483. fastcheckpoint ? "FAST" : "",
  1484. includewal ? "NOWAIT" : "",
  1485. maxrate_clause ? maxrate_clause : "");
  1486. if (PQsendQuery(conn, basebkp) == 0)
  1487. {
  1488. fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
  1489. progname, "BASE_BACKUP", PQerrorMessage(conn));
  1490. disconnect_and_exit(1);
  1491. }
  1492. /*
  1493. * Get the starting xlog position
  1494. */
  1495. res = PQgetResult(conn);
  1496. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  1497. {
  1498. fprintf(stderr, _("%s: could not initiate base backup: %s"),
  1499. progname, PQerrorMessage(conn));
  1500. disconnect_and_exit(1);
  1501. }
  1502. if (PQntuples(res) != 1)
  1503. {
  1504. fprintf(stderr,
  1505. _("%s: server returned unexpected response to BASE_BACKUP command; got %d rows and %d fields, expected %d rows and %d fields\n"),
  1506. progname, PQntuples(res), PQnfields(res), 1, 2);
  1507. disconnect_and_exit(1);
  1508. }
  1509. strlcpy(xlogstart, PQgetvalue(res, 0, 0), sizeof(xlogstart));
  1510. /*
  1511. * 9.3 and later sends the TLI of the starting point. With older servers,
  1512. * assume it's the same as the latest timeline reported by
  1513. * IDENTIFY_SYSTEM.
  1514. */
  1515. if (PQnfields(res) >= 2)
  1516. starttli = atoi(PQgetvalue(res, 0, 1));
  1517. else
  1518. starttli = latesttli;
  1519. PQclear(res);
  1520. MemSet(xlogend, 0, sizeof(xlogend));
  1521. if (verbose && includewal)
  1522. fprintf(stderr, _("transaction log start point: %s on timeline %u\n"),
  1523. xlogstart, starttli);
  1524. /*
  1525. * Get the header
  1526. */
  1527. res = PQgetResult(conn);
  1528. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  1529. {
  1530. fprintf(stderr, _("%s: could not get backup header: %s"),
  1531. progname, PQerrorMessage(conn));
  1532. disconnect_and_exit(1);
  1533. }
  1534. if (PQntuples(res) < 1)
  1535. {
  1536. fprintf(stderr, _("%s: no data returned from server\n"), progname);
  1537. disconnect_and_exit(1);
  1538. }
  1539. /*
  1540. * Sum up the total size, for progress reporting
  1541. */
  1542. totalsize = totaldone = 0;
  1543. tablespacecount = PQntuples(res);
  1544. for (i = 0; i < PQntuples(res); i++)
  1545. {
  1546. totalsize += atol(PQgetvalue(res, i, 2));
  1547. /*
  1548. * Verify tablespace directories are empty. Don't bother with the
  1549. * first once since it can be relocated, and it will be checked before
  1550. * we do anything anyway.
  1551. */
  1552. if (format == 'p' && !PQgetisnull(res, i, 1))
  1553. {
  1554. char *path = (char *) get_tablespace_mapping(PQgetvalue(res, i, 1));
  1555. verify_dir_is_empty_or_create(path);
  1556. }
  1557. }
  1558. /*
  1559. * When writing to stdout, require a single tablespace
  1560. */
  1561. if (format == 't' && strcmp(basedir, "-") == 0 && PQntuples(res) > 1)
  1562. {
  1563. fprintf(stderr,
  1564. _("%s: can only write single tablespace to stdout, database has %d\n"),
  1565. progname, PQntuples(res));
  1566. disconnect_and_exit(1);
  1567. }
  1568. /*
  1569. * If we're streaming WAL, start the streaming session before we start
  1570. * receiving the actual data chunks.
  1571. */
  1572. if (streamwal)
  1573. {
  1574. if (verbose)
  1575. fprintf(stderr, _("%s: starting background WAL receiver\n"),
  1576. progname);
  1577. StartLogStreamer(xlogstart, starttli, sysidentifier);
  1578. }
  1579. /*
  1580. * Start receiving chunks
  1581. */
  1582. for (i = 0; i < PQntuples(res); i++)
  1583. {
  1584. if (format == 't')
  1585. ReceiveTarFile(conn, res, i);
  1586. else
  1587. ReceiveAndUnpackTarFile(conn, res, i);
  1588. } /* Loop over all tablespaces */
  1589. if (showprogress)
  1590. {
  1591. progress_report(PQntuples(res), NULL, true);
  1592. fprintf(stderr, "\n"); /* Need to move to next line */
  1593. }
  1594. if (format == 'p' && tablespace_dirs.head != NULL)
  1595. {
  1596. for (i = 0; i < PQntuples(res); i++)
  1597. {
  1598. Oid tblspc_oid = atooid(PQgetvalue(res, i, 0));
  1599. if (tblspc_oid)
  1600. update_tablespace_symlink(tblspc_oid, PQgetvalue(res, i, 1));
  1601. }
  1602. }
  1603. PQclear(res);
  1604. /*
  1605. * Get the stop position
  1606. */
  1607. res = PQgetResult(conn);
  1608. if (PQresultStatus(res) != PGRES_TUPLES_OK)
  1609. {
  1610. fprintf(stderr,
  1611. _("%s: could not get transaction log end position from server: %s"),
  1612. progname, PQerrorMessage(conn));
  1613. disconnect_and_exit(1);
  1614. }
  1615. if (PQntuples(res) != 1)
  1616. {
  1617. fprintf(stderr,
  1618. _("%s: no transaction log end position returned from server\n"),
  1619. progname);
  1620. disconnect_and_exit(1);
  1621. }
  1622. strlcpy(xlogend, PQgetvalue(res, 0, 0), sizeof(xlogend));
  1623. if (verbose && includewal)
  1624. fprintf(stderr, "transaction log end point: %s\n", xlogend);
  1625. PQclear(res);
  1626. res = PQgetResult(conn);
  1627. if (PQresultStatus(res) != PGRES_COMMAND_OK)
  1628. {
  1629. fprintf(stderr, _("%s: final receive failed: %s"),
  1630. progname, PQerrorMessage(conn));
  1631. disconnect_and_exit(1);
  1632. }
  1633. if (bgchild > 0)
  1634. {
  1635. #ifndef WIN32
  1636. int status;
  1637. int r;
  1638. #else
  1639. DWORD status;
  1640. uint32 hi,
  1641. lo;
  1642. #endif
  1643. if (verbose)
  1644. fprintf(stderr,
  1645. _("%s: waiting for background process to finish streaming ...\n"), progname);
  1646. #ifndef WIN32
  1647. if (write(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend))
  1648. {
  1649. fprintf(stderr,
  1650. _("%s: could not send command to background pipe: %s\n"),
  1651. progname, strerror(errno));
  1652. disconnect_and_exit(1);
  1653. }
  1654. /* Just wait for the background process to exit */
  1655. r = waitpid(bgchild, &status, 0);
  1656. if (r == -1)
  1657. {
  1658. fprintf(stderr, _("%s: could not wait for child process: %s\n"),
  1659. progname, strerror(errno));
  1660. disconnect_and_exit(1);
  1661. }
  1662. if (r != bgchild)
  1663. {
  1664. fprintf(stderr, _("%s: child %d died, expected %d\n"),
  1665. progname, r, (int) bgchild);
  1666. disconnect_and_exit(1);
  1667. }
  1668. if (!WIFEXITED(status))
  1669. {
  1670. fprintf(stderr, _("%s: child process did not exit normally\n"),
  1671. progname);
  1672. disconnect_and_exit(1);
  1673. }
  1674. if (WEXITSTATUS(status) != 0)
  1675. {
  1676. fprintf(stderr, _("%s: child process exited with error %d\n"),
  1677. progname, WEXITSTATUS(status));
  1678. disconnect_and_exit(1);
  1679. }
  1680. /* Exited normally, we're happy! */
  1681. #else /* WIN32 */
  1682. /*
  1683. * On Windows, since we are in the same process, we can just store the
  1684. * value directly in the variable, and then set the flag that says
  1685. * it's there.
  1686. */
  1687. if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
  1688. {
  1689. fprintf(stderr,
  1690. _("%s: could not parse transaction log location \"%s\"\n"),
  1691. progname, xlogend);
  1692. disconnect_and_exit(1);
  1693. }
  1694. xlogendptr = ((uint64) hi) << 32 | lo;
  1695. InterlockedIncrement(&has_xlogendptr);
  1696. /* First wait for the thread to exit */
  1697. if (WaitForSingleObjectEx((HANDLE) bgchild, INFINITE, FALSE) !=
  1698. WAIT_OBJECT_0)
  1699. {
  1700. _dosmaperr(GetLastError());
  1701. fprintf(stderr, _("%s: could not wait for child thread: %s\n"),
  1702. progname, strerror(errno));
  1703. disconnect_and_exit(1);
  1704. }
  1705. if (GetExitCodeThread((HANDLE) bgchild, &status) == 0)
  1706. {
  1707. _dosmaperr(GetLastError());
  1708. fprintf(stderr, _("%s: could not get child thread exit status: %s\n"),
  1709. progname, strerror(errno));
  1710. disconnect_and_exit(1);
  1711. }
  1712. if (status != 0)
  1713. {
  1714. fprintf(stderr, _("%s: child thread exited with error %u\n"),
  1715. progname, (unsigned int) status);
  1716. disconnect_and_exit(1);
  1717. }
  1718. /* Exited normally, we're happy */
  1719. #endif
  1720. }
  1721. /* Free the recovery.conf contents */
  1722. destroyPQExpBuffer(recoveryconfcontents);
  1723. /*
  1724. * End of copy data. Final result is already checked inside the loop.
  1725. */
  1726. PQclear(res);
  1727. PQfinish(conn);
  1728. if (verbose)
  1729. fprintf(stderr, "%s: base backup completed\n", progname);
  1730. }
  1731. int
  1732. main(int argc, char **argv)
  1733. {
  1734. static struct option long_options[] = {
  1735. {"help", no_argument, NULL, '?'},
  1736. {"version", no_argument, NULL, 'V'},
  1737. {"pgdata", required_argument, NULL, 'D'},
  1738. {"format", required_argument, NULL, 'F'},
  1739. {"checkpoint", required_argument, NULL, 'c'},
  1740. {"max-rate", required_argument, NULL, 'r'},
  1741. {"write-recovery-conf", no_argument, NULL, 'R'},
  1742. {"tablespace-mapping", required_argument, NULL, 'T'},
  1743. {"xlog", no_argument, NULL, 'x'},
  1744. {"xlog-method", required_argument, NULL, 'X'},
  1745. {"gzip", no_argument, NULL, 'z'},
  1746. {"compress", required_argument, NULL, 'Z'},
  1747. {"label", required_argument, NULL, 'l'},
  1748. {"dbname", required_argument, NULL, 'd'},
  1749. {"host", required_argument, NULL, 'h'},
  1750. {"port", required_argument, NULL, 'p'},
  1751. {"username", required_argument, NULL, 'U'},
  1752. {"no-password", no_argument, NULL, 'w'},
  1753. {"password", no_argument, NULL, 'W'},
  1754. {"status-interval", required_argument, NULL, 's'},
  1755. {"verbose", no_argument, NULL, 'v'},
  1756. {"progress", no_argument, NULL, 'P'},
  1757. {"xlogdir", required_argument, NULL, 1},
  1758. {NULL, 0, NULL, 0}
  1759. };
  1760. int c;
  1761. int option_index;
  1762. progname = get_progname(argv[0]);
  1763. set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup"));
  1764. if (argc > 1)
  1765. {
  1766. if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
  1767. {
  1768. usage();
  1769. exit(0);
  1770. }
  1771. else if (strcmp(argv[1], "-V") == 0
  1772. || strcmp(argv[1], "--version") == 0)
  1773. {
  1774. puts("pg_basebackup (PostgreSQL) " PG_VERSION);
  1775. exit(0);
  1776. }
  1777. }
  1778. while ((c = getopt_long(argc, argv, "D:F:r:RT:xX:l:zZ:d:c:h:p:U:s:wWvP",
  1779. long_options, &option_index))

Large files files are truncated, but you can click here to view the full file