summaryrefslogtreecommitdiffstats
path: root/src/bin/pg_rewind
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:19:15 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:19:15 +0000
commit6eb9c5a5657d1fe77b55cc261450f3538d35a94d (patch)
tree657d8194422a5daccecfd42d654b8a245ef7b4c8 /src/bin/pg_rewind
parentInitial commit. (diff)
downloadpostgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.tar.xz
postgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.zip
Adding upstream version 13.4.upstream/13.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/bin/pg_rewind')
-rw-r--r--src/bin/pg_rewind/.gitignore6
-rw-r--r--src/bin/pg_rewind/Makefile61
-rw-r--r--src/bin/pg_rewind/copy_fetch.c262
-rw-r--r--src/bin/pg_rewind/datapagemap.c127
-rw-r--r--src/bin/pg_rewind/datapagemap.h29
-rw-r--r--src/bin/pg_rewind/fetch.c60
-rw-r--r--src/bin/pg_rewind/fetch.h44
-rw-r--r--src/bin/pg_rewind/file_ops.c325
-rw-r--r--src/bin/pg_rewind/file_ops.h25
-rw-r--r--src/bin/pg_rewind/filemap.c827
-rw-r--r--src/bin/pg_rewind/filemap.h104
-rw-r--r--src/bin/pg_rewind/libpq_fetch.c538
-rw-r--r--src/bin/pg_rewind/nls.mk8
-rw-r--r--src/bin/pg_rewind/parsexlog.c437
-rw-r--r--src/bin/pg_rewind/pg_rewind.c965
-rw-r--r--src/bin/pg_rewind/pg_rewind.h63
-rw-r--r--src/bin/pg_rewind/po/cs.po1019
-rw-r--r--src/bin/pg_rewind/po/de.po935
-rw-r--r--src/bin/pg_rewind/po/es.po942
-rw-r--r--src/bin/pg_rewind/po/fr.po1153
-rw-r--r--src/bin/pg_rewind/po/ja.po1070
-rw-r--r--src/bin/pg_rewind/po/ko.po855
-rw-r--r--src/bin/pg_rewind/po/ru.po1089
-rw-r--r--src/bin/pg_rewind/po/sv.po973
-rw-r--r--src/bin/pg_rewind/po/tr.po966
-rw-r--r--src/bin/pg_rewind/po/uk.po913
-rw-r--r--src/bin/pg_rewind/po/zh_CN.po821
-rw-r--r--src/bin/pg_rewind/t/001_basic.pl176
-rw-r--r--src/bin/pg_rewind/t/002_databases.pl74
-rw-r--r--src/bin/pg_rewind/t/003_extrafiles.pl94
-rw-r--r--src/bin/pg_rewind/t/004_pg_xlog_symlink.pl85
-rw-r--r--src/bin/pg_rewind/t/005_same_timeline.pl20
-rw-r--r--src/bin/pg_rewind/t/006_options.pl40
-rw-r--r--src/bin/pg_rewind/t/008_min_recovery_point.pl171
-rw-r--r--src/bin/pg_rewind/t/RewindTest.pm394
-rw-r--r--src/bin/pg_rewind/timeline.c130
36 files changed, 15801 insertions, 0 deletions
diff --git a/src/bin/pg_rewind/.gitignore b/src/bin/pg_rewind/.gitignore
new file mode 100644
index 0000000..79ddca3
--- /dev/null
+++ b/src/bin/pg_rewind/.gitignore
@@ -0,0 +1,6 @@
+# Files generated during build
+/xlogreader.c
+/pg_rewind
+
+# Generated by test suite
+/tmp_check/
diff --git a/src/bin/pg_rewind/Makefile b/src/bin/pg_rewind/Makefile
new file mode 100644
index 0000000..f398c3d
--- /dev/null
+++ b/src/bin/pg_rewind/Makefile
@@ -0,0 +1,61 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/bin/pg_rewind
+#
+# Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+#
+# src/bin/pg_rewind/Makefile
+#
+#-------------------------------------------------------------------------
+
+PGFILEDESC = "pg_rewind - synchronize a data directory with another one forked from"
+PGAPPICON = win32
+
+subdir = src/bin/pg_rewind
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -I$(libpq_srcdir) -DFRONTEND $(CPPFLAGS)
+LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
+
+OBJS = \
+ $(WIN32RES) \
+ copy_fetch.o \
+ datapagemap.o \
+ fetch.o \
+ file_ops.o \
+ filemap.o \
+ libpq_fetch.o \
+ parsexlog.o \
+ pg_rewind.o \
+ timeline.o \
+ xlogreader.o
+
+EXTRA_CLEAN = xlogreader.c
+
+all: pg_rewind
+
+pg_rewind: $(OBJS) | submake-libpq submake-libpgport
+ $(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
+xlogreader.c: % : $(top_srcdir)/src/backend/access/transam/%
+ rm -f $@ && $(LN_S) $< .
+
+install: all installdirs
+ $(INSTALL_PROGRAM) pg_rewind$(X) '$(DESTDIR)$(bindir)/pg_rewind$(X)'
+
+installdirs:
+ $(MKDIR_P) '$(DESTDIR)$(bindir)'
+
+uninstall:
+ rm -f '$(DESTDIR)$(bindir)/pg_rewind$(X)'
+
+clean distclean maintainer-clean:
+ rm -f pg_rewind$(X) $(OBJS) xlogreader.c
+ rm -rf tmp_check
+
+check:
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
diff --git a/src/bin/pg_rewind/copy_fetch.c b/src/bin/pg_rewind/copy_fetch.c
new file mode 100644
index 0000000..223c326
--- /dev/null
+++ b/src/bin/pg_rewind/copy_fetch.c
@@ -0,0 +1,262 @@
+/*-------------------------------------------------------------------------
+ *
+ * copy_fetch.c
+ * Functions for using a data directory as the source.
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "datapagemap.h"
+#include "fetch.h"
+#include "file_ops.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+
+static void recurse_dir(const char *datadir, const char *path,
+ process_file_callback_t callback);
+
+static void execute_pagemap(datapagemap_t *pagemap, const char *path);
+
+/*
+ * Traverse through all files in a data directory, calling 'callback'
+ * for each file.
+ */
+void
+traverse_datadir(const char *datadir, process_file_callback_t callback)
+{
+ recurse_dir(datadir, NULL, callback);
+}
+
+/*
+ * recursive part of traverse_datadir
+ *
+ * parentpath is the current subdirectory's path relative to datadir,
+ * or NULL at the top level.
+ */
+static void
+recurse_dir(const char *datadir, const char *parentpath,
+ process_file_callback_t callback)
+{
+ DIR *xldir;
+ struct dirent *xlde;
+ char fullparentpath[MAXPGPATH];
+
+ if (parentpath)
+ snprintf(fullparentpath, MAXPGPATH, "%s/%s", datadir, parentpath);
+ else
+ snprintf(fullparentpath, MAXPGPATH, "%s", datadir);
+
+ xldir = opendir(fullparentpath);
+ if (xldir == NULL)
+ pg_fatal("could not open directory \"%s\": %m",
+ fullparentpath);
+
+ while (errno = 0, (xlde = readdir(xldir)) != NULL)
+ {
+ struct stat fst;
+ char fullpath[MAXPGPATH * 2];
+ char path[MAXPGPATH * 2];
+
+ if (strcmp(xlde->d_name, ".") == 0 ||
+ strcmp(xlde->d_name, "..") == 0)
+ continue;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", fullparentpath, xlde->d_name);
+
+ if (lstat(fullpath, &fst) < 0)
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * File doesn't exist anymore. This is ok, if the new master
+ * is running and the file was just removed. If it was a data
+ * file, there should be a WAL record of the removal. If it
+ * was something else, it couldn't have been anyway.
+ *
+ * TODO: But complain if we're processing the target dir!
+ */
+ }
+ else
+ pg_fatal("could not stat file \"%s\": %m",
+ fullpath);
+ }
+
+ if (parentpath)
+ snprintf(path, sizeof(path), "%s/%s", parentpath, xlde->d_name);
+ else
+ snprintf(path, sizeof(path), "%s", xlde->d_name);
+
+ if (S_ISREG(fst.st_mode))
+ callback(path, FILE_TYPE_REGULAR, fst.st_size, NULL);
+ else if (S_ISDIR(fst.st_mode))
+ {
+ callback(path, FILE_TYPE_DIRECTORY, 0, NULL);
+ /* recurse to handle subdirectories */
+ recurse_dir(datadir, path, callback);
+ }
+#ifndef WIN32
+ else if (S_ISLNK(fst.st_mode))
+#else
+ else if (pgwin32_is_junction(fullpath))
+#endif
+ {
+#if defined(HAVE_READLINK) || defined(WIN32)
+ char link_target[MAXPGPATH];
+ int len;
+
+ len = readlink(fullpath, link_target, sizeof(link_target));
+ if (len < 0)
+ pg_fatal("could not read symbolic link \"%s\": %m",
+ fullpath);
+ if (len >= sizeof(link_target))
+ pg_fatal("symbolic link \"%s\" target is too long",
+ fullpath);
+ link_target[len] = '\0';
+
+ callback(path, FILE_TYPE_SYMLINK, 0, link_target);
+
+ /*
+ * If it's a symlink within pg_tblspc, we need to recurse into it,
+ * to process all the tablespaces. We also follow a symlink if
+ * it's for pg_wal. Symlinks elsewhere are ignored.
+ */
+ if ((parentpath && strcmp(parentpath, "pg_tblspc") == 0) ||
+ strcmp(path, "pg_wal") == 0)
+ recurse_dir(datadir, path, callback);
+#else
+ pg_fatal("\"%s\" is a symbolic link, but symbolic links are not supported on this platform",
+ fullpath);
+#endif /* HAVE_READLINK */
+ }
+ }
+
+ if (errno)
+ pg_fatal("could not read directory \"%s\": %m",
+ fullparentpath);
+
+ if (closedir(xldir))
+ pg_fatal("could not close directory \"%s\": %m",
+ fullparentpath);
+}
+
+/*
+ * Copy a file from source to target, between 'begin' and 'end' offsets.
+ *
+ * If 'trunc' is true, any existing file with the same name is truncated.
+ */
+static void
+rewind_copy_file_range(const char *path, off_t begin, off_t end, bool trunc)
+{
+ PGAlignedBlock buf;
+ char srcpath[MAXPGPATH];
+ int srcfd;
+
+ snprintf(srcpath, sizeof(srcpath), "%s/%s", datadir_source, path);
+
+ srcfd = open(srcpath, O_RDONLY | PG_BINARY, 0);
+ if (srcfd < 0)
+ pg_fatal("could not open source file \"%s\": %m",
+ srcpath);
+
+ if (lseek(srcfd, begin, SEEK_SET) == -1)
+ pg_fatal("could not seek in source file: %m");
+
+ open_target_file(path, trunc);
+
+ while (end - begin > 0)
+ {
+ int readlen;
+ int len;
+
+ if (end - begin > sizeof(buf))
+ len = sizeof(buf);
+ else
+ len = end - begin;
+
+ readlen = read(srcfd, buf.data, len);
+
+ if (readlen < 0)
+ pg_fatal("could not read file \"%s\": %m",
+ srcpath);
+ else if (readlen == 0)
+ pg_fatal("unexpected EOF while reading file \"%s\"", srcpath);
+
+ write_target_range(buf.data, begin, readlen);
+ begin += readlen;
+ }
+
+ if (close(srcfd) != 0)
+ pg_fatal("could not close file \"%s\": %m", srcpath);
+}
+
+/*
+ * Copy all relation data files from datadir_source to datadir_target, which
+ * are marked in the given data page map.
+ */
+void
+copy_executeFileMap(filemap_t *map)
+{
+ file_entry_t *entry;
+ int i;
+
+ for (i = 0; i < map->narray; i++)
+ {
+ entry = map->array[i];
+ execute_pagemap(&entry->pagemap, entry->path);
+
+ switch (entry->action)
+ {
+ case FILE_ACTION_NONE:
+ /* ok, do nothing.. */
+ break;
+
+ case FILE_ACTION_COPY:
+ rewind_copy_file_range(entry->path, 0, entry->newsize, true);
+ break;
+
+ case FILE_ACTION_TRUNCATE:
+ truncate_target_file(entry->path, entry->newsize);
+ break;
+
+ case FILE_ACTION_COPY_TAIL:
+ rewind_copy_file_range(entry->path, entry->oldsize,
+ entry->newsize, false);
+ break;
+
+ case FILE_ACTION_CREATE:
+ create_target(entry);
+ break;
+
+ case FILE_ACTION_REMOVE:
+ remove_target(entry);
+ break;
+ }
+ }
+
+ close_target_file();
+}
+
+static void
+execute_pagemap(datapagemap_t *pagemap, const char *path)
+{
+ datapagemap_iterator_t *iter;
+ BlockNumber blkno;
+ off_t offset;
+
+ iter = datapagemap_iterate(pagemap);
+ while (datapagemap_next(iter, &blkno))
+ {
+ offset = blkno * BLCKSZ;
+ rewind_copy_file_range(path, offset, offset + BLCKSZ, false);
+ /* Ok, this block has now been copied from new data dir to old */
+ }
+ pg_free(iter);
+}
diff --git a/src/bin/pg_rewind/datapagemap.c b/src/bin/pg_rewind/datapagemap.c
new file mode 100644
index 0000000..16fa89d
--- /dev/null
+++ b/src/bin/pg_rewind/datapagemap.c
@@ -0,0 +1,127 @@
+/*-------------------------------------------------------------------------
+ *
+ * datapagemap.c
+ * A data structure for keeping track of data pages that have changed.
+ *
+ * This is a fairly simple bitmap.
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include "common/logging.h"
+#include "datapagemap.h"
+
+struct datapagemap_iterator
+{
+ datapagemap_t *map;
+ BlockNumber nextblkno;
+};
+
+/*****
+ * Public functions
+ */
+
+/*
+ * Add a block to the bitmap.
+ */
+void
+datapagemap_add(datapagemap_t *map, BlockNumber blkno)
+{
+ int offset;
+ int bitno;
+
+ offset = blkno / 8;
+ bitno = blkno % 8;
+
+ /* enlarge or create bitmap if needed */
+ if (map->bitmapsize <= offset)
+ {
+ int oldsize = map->bitmapsize;
+ int newsize;
+
+ /*
+ * The minimum to hold the new bit is offset + 1. But add some
+ * headroom, so that we don't need to repeatedly enlarge the bitmap in
+ * the common case that blocks are modified in order, from beginning
+ * of a relation to the end.
+ */
+ newsize = offset + 1;
+ newsize += 10;
+
+ map->bitmap = pg_realloc(map->bitmap, newsize);
+
+ /* zero out the newly allocated region */
+ memset(&map->bitmap[oldsize], 0, newsize - oldsize);
+
+ map->bitmapsize = newsize;
+ }
+
+ /* Set the bit */
+ map->bitmap[offset] |= (1 << bitno);
+}
+
+/*
+ * Start iterating through all entries in the page map.
+ *
+ * After datapagemap_iterate, call datapagemap_next to return the entries,
+ * until it returns false. After you're done, use pg_free() to destroy the
+ * iterator.
+ */
+datapagemap_iterator_t *
+datapagemap_iterate(datapagemap_t *map)
+{
+ datapagemap_iterator_t *iter;
+
+ iter = pg_malloc(sizeof(datapagemap_iterator_t));
+ iter->map = map;
+ iter->nextblkno = 0;
+
+ return iter;
+}
+
+bool
+datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
+{
+ datapagemap_t *map = iter->map;
+
+ for (;;)
+ {
+ BlockNumber blk = iter->nextblkno;
+ int nextoff = blk / 8;
+ int bitno = blk % 8;
+
+ if (nextoff >= map->bitmapsize)
+ break;
+
+ iter->nextblkno++;
+
+ if (map->bitmap[nextoff] & (1 << bitno))
+ {
+ *blkno = blk;
+ return true;
+ }
+ }
+
+ /* no more set bits in this bitmap. */
+ return false;
+}
+
+/*
+ * A debugging aid. Prints out the contents of the page map.
+ */
+void
+datapagemap_print(datapagemap_t *map)
+{
+ datapagemap_iterator_t *iter;
+ BlockNumber blocknum;
+
+ iter = datapagemap_iterate(map);
+ while (datapagemap_next(iter, &blocknum))
+ pg_log_debug("block %u", blocknum);
+
+ pg_free(iter);
+}
diff --git a/src/bin/pg_rewind/datapagemap.h b/src/bin/pg_rewind/datapagemap.h
new file mode 100644
index 0000000..b5fac09
--- /dev/null
+++ b/src/bin/pg_rewind/datapagemap.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * datapagemap.h
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATAPAGEMAP_H
+#define DATAPAGEMAP_H
+
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+struct datapagemap
+{
+ char *bitmap;
+ int bitmapsize;
+};
+
+typedef struct datapagemap datapagemap_t;
+typedef struct datapagemap_iterator datapagemap_iterator_t;
+
+extern void datapagemap_add(datapagemap_t *map, BlockNumber blkno);
+extern datapagemap_iterator_t *datapagemap_iterate(datapagemap_t *map);
+extern bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno);
+extern void datapagemap_print(datapagemap_t *map);
+
+#endif /* DATAPAGEMAP_H */
diff --git a/src/bin/pg_rewind/fetch.c b/src/bin/pg_rewind/fetch.c
new file mode 100644
index 0000000..f18fe53
--- /dev/null
+++ b/src/bin/pg_rewind/fetch.c
@@ -0,0 +1,60 @@
+/*-------------------------------------------------------------------------
+ *
+ * fetch.c
+ * Functions for fetching files from a local or remote data dir
+ *
+ * This file forms an abstraction of getting files from the "source".
+ * There are two implementations of this interface: one for copying files
+ * from a data directory via normal filesystem operations (copy_fetch.c),
+ * and another for fetching files from a remote server via a libpq
+ * connection (libpq_fetch.c)
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "fetch.h"
+#include "file_ops.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+
+void
+fetchSourceFileList(void)
+{
+ if (datadir_source)
+ traverse_datadir(datadir_source, &process_source_file);
+ else
+ libpqProcessFileList();
+}
+
+/*
+ * Fetch all relation data files that are marked in the given data page map.
+ */
+void
+executeFileMap(void)
+{
+ if (datadir_source)
+ copy_executeFileMap(filemap);
+ else
+ libpq_executeFileMap(filemap);
+}
+
+/*
+ * Fetch a single file into a malloc'd buffer. The file size is returned
+ * in *filesize. The returned buffer is always zero-terminated, which is
+ * handy for text files.
+ */
+char *
+fetchFile(const char *filename, size_t *filesize)
+{
+ if (datadir_source)
+ return slurpFile(datadir_source, filename, filesize);
+ else
+ return libpqGetFile(filename, filesize);
+}
diff --git a/src/bin/pg_rewind/fetch.h b/src/bin/pg_rewind/fetch.h
new file mode 100644
index 0000000..7cf8b6e
--- /dev/null
+++ b/src/bin/pg_rewind/fetch.h
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------
+ *
+ * fetch.h
+ * Fetching data from a local or remote data directory.
+ *
+ * This file includes the prototypes for functions used to copy files from
+ * one data directory to another. The source to copy from can be a local
+ * directory (copy method), or a remote PostgreSQL server (libpq fetch
+ * method).
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FETCH_H
+#define FETCH_H
+
+#include "access/xlogdefs.h"
+
+#include "filemap.h"
+
+/*
+ * Common interface. Calls the copy or libpq method depending on global
+ * config options.
+ */
+extern void fetchSourceFileList(void);
+extern char *fetchFile(const char *filename, size_t *filesize);
+extern void executeFileMap(void);
+
+/* in libpq_fetch.c */
+extern void libpqProcessFileList(void);
+extern char *libpqGetFile(const char *filename, size_t *filesize);
+extern void libpq_executeFileMap(filemap_t *map);
+
+extern void libpqConnect(const char *connstr);
+extern XLogRecPtr libpqGetCurrentXlogInsertLocation(void);
+
+/* in copy_fetch.c */
+extern void copy_executeFileMap(filemap_t *map);
+
+typedef void (*process_file_callback_t) (const char *path, file_type_t type, size_t size, const char *link_target);
+extern void traverse_datadir(const char *datadir, process_file_callback_t callback);
+
+#endif /* FETCH_H */
diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c
new file mode 100644
index 0000000..b3bf091
--- /dev/null
+++ b/src/bin/pg_rewind/file_ops.c
@@ -0,0 +1,325 @@
+/*-------------------------------------------------------------------------
+ *
+ * file_ops.c
+ * Helper functions for operating on files.
+ *
+ * Most of the functions in this file are helper functions for writing to
+ * the target data directory. The functions check the --dry-run flag, and
+ * do nothing if it's enabled. You should avoid accessing the target files
+ * directly but if you do, make sure you honor the --dry-run mode!
+ *
+ * Portions Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "common/file_perm.h"
+#include "file_ops.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+
+/*
+ * Currently open target file.
+ */
+static int dstfd = -1;
+static char dstpath[MAXPGPATH] = "";
+
+static void create_target_dir(const char *path);
+static void remove_target_dir(const char *path);
+static void create_target_symlink(const char *path, const char *link);
+static void remove_target_symlink(const char *path);
+
+/*
+ * Open a target file for writing. If 'trunc' is true and the file already
+ * exists, it will be truncated.
+ */
+void
+open_target_file(const char *path, bool trunc)
+{
+ int mode;
+
+ if (dry_run)
+ return;
+
+ if (dstfd != -1 && !trunc &&
+ strcmp(path, &dstpath[strlen(datadir_target) + 1]) == 0)
+ return; /* already open */
+
+ close_target_file();
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+
+ mode = O_WRONLY | O_CREAT | PG_BINARY;
+ if (trunc)
+ mode |= O_TRUNC;
+ dstfd = open(dstpath, mode, pg_file_create_mode);
+ if (dstfd < 0)
+ pg_fatal("could not open target file \"%s\": %m",
+ dstpath);
+}
+
+/*
+ * Close target file, if it's open.
+ */
+void
+close_target_file(void)
+{
+ if (dstfd == -1)
+ return;
+
+ if (close(dstfd) != 0)
+ pg_fatal("could not close target file \"%s\": %m",
+ dstpath);
+
+ dstfd = -1;
+}
+
+void
+write_target_range(char *buf, off_t begin, size_t size)
+{
+ int writeleft;
+ char *p;
+
+ /* update progress report */
+ fetch_done += size;
+ progress_report(false);
+
+ if (dry_run)
+ return;
+
+ if (lseek(dstfd, begin, SEEK_SET) == -1)
+ pg_fatal("could not seek in target file \"%s\": %m",
+ dstpath);
+
+ writeleft = size;
+ p = buf;
+ while (writeleft > 0)
+ {
+ int writelen;
+
+ errno = 0;
+ writelen = write(dstfd, p, writeleft);
+ if (writelen < 0)
+ {
+ /* if write didn't set errno, assume problem is no disk space */
+ if (errno == 0)
+ errno = ENOSPC;
+ pg_fatal("could not write file \"%s\": %m",
+ dstpath);
+ }
+
+ p += writelen;
+ writeleft -= writelen;
+ }
+
+ /* keep the file open, in case we need to copy more blocks in it */
+}
+
+
+void
+remove_target(file_entry_t *entry)
+{
+ Assert(entry->action == FILE_ACTION_REMOVE);
+
+ switch (entry->type)
+ {
+ case FILE_TYPE_DIRECTORY:
+ remove_target_dir(entry->path);
+ break;
+
+ case FILE_TYPE_REGULAR:
+ remove_target_file(entry->path, false);
+ break;
+
+ case FILE_TYPE_SYMLINK:
+ remove_target_symlink(entry->path);
+ break;
+ }
+}
+
+void
+create_target(file_entry_t *entry)
+{
+ Assert(entry->action == FILE_ACTION_CREATE);
+
+ switch (entry->type)
+ {
+ case FILE_TYPE_DIRECTORY:
+ create_target_dir(entry->path);
+ break;
+
+ case FILE_TYPE_SYMLINK:
+ create_target_symlink(entry->path, entry->link_target);
+ break;
+
+ case FILE_TYPE_REGULAR:
+ /* can't happen. Regular files are created with open_target_file. */
+ pg_fatal("invalid action (CREATE) for regular file");
+ break;
+ }
+}
+
+/*
+ * Remove a file from target data directory. If missing_ok is true, it
+ * is fine for the target file to not exist.
+ */
+void
+remove_target_file(const char *path, bool missing_ok)
+{
+ char dstpath[MAXPGPATH];
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+ if (unlink(dstpath) != 0)
+ {
+ if (errno == ENOENT && missing_ok)
+ return;
+
+ pg_fatal("could not remove file \"%s\": %m",
+ dstpath);
+ }
+}
+
+void
+truncate_target_file(const char *path, off_t newsize)
+{
+ char dstpath[MAXPGPATH];
+ int fd;
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+
+ fd = open(dstpath, O_WRONLY, pg_file_create_mode);
+ if (fd < 0)
+ pg_fatal("could not open file \"%s\" for truncation: %m",
+ dstpath);
+
+ if (ftruncate(fd, newsize) != 0)
+ pg_fatal("could not truncate file \"%s\" to %u: %m",
+ dstpath, (unsigned int) newsize);
+
+ close(fd);
+}
+
+static void
+create_target_dir(const char *path)
+{
+ char dstpath[MAXPGPATH];
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+ if (mkdir(dstpath, pg_dir_create_mode) != 0)
+ pg_fatal("could not create directory \"%s\": %m",
+ dstpath);
+}
+
+static void
+remove_target_dir(const char *path)
+{
+ char dstpath[MAXPGPATH];
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+ if (rmdir(dstpath) != 0)
+ pg_fatal("could not remove directory \"%s\": %m",
+ dstpath);
+}
+
+static void
+create_target_symlink(const char *path, const char *link)
+{
+ char dstpath[MAXPGPATH];
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+ if (symlink(link, dstpath) != 0)
+ pg_fatal("could not create symbolic link at \"%s\": %m",
+ dstpath);
+}
+
+static void
+remove_target_symlink(const char *path)
+{
+ char dstpath[MAXPGPATH];
+
+ if (dry_run)
+ return;
+
+ snprintf(dstpath, sizeof(dstpath), "%s/%s", datadir_target, path);
+ if (unlink(dstpath) != 0)
+ pg_fatal("could not remove symbolic link \"%s\": %m",
+ dstpath);
+}
+
+
+/*
+ * Read a file into memory. The file to be read is <datadir>/<path>.
+ * The file contents are returned in a malloc'd buffer, and *filesize
+ * is set to the length of the file.
+ *
+ * The returned buffer is always zero-terminated; the size of the returned
+ * buffer is actually *filesize + 1. That's handy when reading a text file.
+ * This function can be used to read binary files as well, you can just
+ * ignore the zero-terminator in that case.
+ *
+ * This function is used to implement the fetchFile function in the "fetch"
+ * interface (see fetch.c), but is also called directly.
+ */
+char *
+slurpFile(const char *datadir, const char *path, size_t *filesize)
+{
+ int fd;
+ char *buffer;
+ struct stat statbuf;
+ char fullpath[MAXPGPATH];
+ int len;
+ int r;
+
+ snprintf(fullpath, sizeof(fullpath), "%s/%s", datadir, path);
+
+ if ((fd = open(fullpath, O_RDONLY | PG_BINARY, 0)) == -1)
+ pg_fatal("could not open file \"%s\" for reading: %m",
+ fullpath);
+
+ if (fstat(fd, &statbuf) < 0)
+ pg_fatal("could not open file \"%s\" for reading: %m",
+ fullpath);
+
+ len = statbuf.st_size;
+
+ buffer = pg_malloc(len + 1);
+
+ r = read(fd, buffer, len);
+ if (r != len)
+ {
+ if (r < 0)
+ pg_fatal("could not read file \"%s\": %m",
+ fullpath);
+ else
+ pg_fatal("could not read file \"%s\": read %d of %zu",
+ fullpath, r, (Size) len);
+ }
+ close(fd);
+
+ /* Zero-terminate the buffer. */
+ buffer[len] = '\0';
+
+ if (filesize)
+ *filesize = len;
+ return buffer;
+}
diff --git a/src/bin/pg_rewind/file_ops.h b/src/bin/pg_rewind/file_ops.h
new file mode 100644
index 0000000..025f241
--- /dev/null
+++ b/src/bin/pg_rewind/file_ops.h
@@ -0,0 +1,25 @@
+/*-------------------------------------------------------------------------
+ *
+ * file_ops.h
+ * Helper functions for operating on files
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILE_OPS_H
+#define FILE_OPS_H
+
+#include "filemap.h"
+
+extern void open_target_file(const char *path, bool trunc);
+extern void write_target_range(char *buf, off_t begin, size_t size);
+extern void close_target_file(void);
+extern void remove_target_file(const char *path, bool missing_ok);
+extern void truncate_target_file(const char *path, off_t newsize);
+extern void create_target(file_entry_t *t);
+extern void remove_target(file_entry_t *t);
+
+extern char *slurpFile(const char *datadir, const char *path, size_t *filesize);
+
+#endif /* FILE_OPS_H */
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
new file mode 100644
index 0000000..fbb97b5
--- /dev/null
+++ b/src/bin/pg_rewind/filemap.c
@@ -0,0 +1,827 @@
+/*-------------------------------------------------------------------------
+ *
+ * filemap.c
+ * A data structure for keeping track of files that have changed.
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "catalog/pg_tablespace_d.h"
+#include "common/string.h"
+#include "datapagemap.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+#include "storage/fd.h"
+
+filemap_t *filemap = NULL;
+
+static bool isRelDataFile(const char *path);
+static char *datasegpath(RelFileNode rnode, ForkNumber forknum,
+ BlockNumber segno);
+static int path_cmp(const void *a, const void *b);
+static int final_filemap_cmp(const void *a, const void *b);
+static void filemap_list_to_array(filemap_t *map);
+static bool check_file_excluded(const char *path, bool is_source);
+
+/*
+ * Definition of one element part of an exclusion list, used to exclude
+ * contents when rewinding. "name" is the name of the file or path to
+ * check for exclusion. If "match_prefix" is true, any items matching
+ * the name as prefix are excluded.
+ */
+struct exclude_list_item
+{
+ const char *name;
+ bool match_prefix;
+};
+
+/*
+ * The contents of these directories are removed or recreated during server
+ * start so they are not included in data processed by pg_rewind.
+ *
+ * Note: those lists should be kept in sync with what basebackup.c provides.
+ * Some of the values, contrary to what basebackup.c uses, are hardcoded as
+ * they are defined in backend-only headers. So this list is maintained
+ * with a best effort in mind.
+ */
+static const char *excludeDirContents[] =
+{
+ /*
+ * Skip temporary statistics files. PG_STAT_TMP_DIR must be skipped even
+ * when stats_temp_directory is set because PGSS_TEXT_FILE is always
+ * created there.
+ */
+ "pg_stat_tmp", /* defined as PG_STAT_TMP_DIR */
+
+ /*
+ * It is generally not useful to backup the contents of this directory
+ * even if the intention is to restore to another master. See backup.sgml
+ * for a more detailed description.
+ */
+ "pg_replslot",
+
+ /* Contents removed on startup, see dsm_cleanup_for_mmap(). */
+ "pg_dynshmem", /* defined as PG_DYNSHMEM_DIR */
+
+ /* Contents removed on startup, see AsyncShmemInit(). */
+ "pg_notify",
+
+ /*
+ * Old contents are loaded for possible debugging but are not required for
+ * normal operation, see SerialInit().
+ */
+ "pg_serial",
+
+ /* Contents removed on startup, see DeleteAllExportedSnapshotFiles(). */
+ "pg_snapshots",
+
+ /* Contents zeroed on startup, see StartupSUBTRANS(). */
+ "pg_subtrans",
+
+ /* end of list */
+ NULL
+};
+
+/*
+ * List of files excluded from filemap processing. Files are excluded
+ * if their prefix match.
+ */
+static const struct exclude_list_item excludeFiles[] =
+{
+ /* Skip auto conf temporary file. */
+ {"postgresql.auto.conf.tmp", false}, /* defined as PG_AUTOCONF_FILENAME */
+
+ /* Skip current log file temporary file */
+ {"current_logfiles.tmp", false}, /* defined as
+ * LOG_METAINFO_DATAFILE_TMP */
+
+ /* Skip relation cache because it is rebuilt on startup */
+ {"pg_internal.init", true}, /* defined as RELCACHE_INIT_FILENAME */
+
+ /*
+ * If there's a backup_label or tablespace_map file, it belongs to a
+ * backup started by the user with pg_start_backup(). It is *not* correct
+ * for this backup. Our backup_label is written later on separately.
+ */
+ {"backup_label", false}, /* defined as BACKUP_LABEL_FILE */
+ {"tablespace_map", false}, /* defined as TABLESPACE_MAP */
+
+ /*
+ * If there's a backup_manifest, it belongs to a backup that was used to
+ * start this server. It is *not* correct for this backup. Our
+ * backup_manifest is injected into the backup separately if users want
+ * it.
+ */
+ {"backup_manifest", false},
+
+ {"postmaster.pid", false},
+ {"postmaster.opts", false},
+
+ /* end of list */
+ {NULL, false}
+};
+
+/*
+ * Create a new file map (stored in the global pointer "filemap").
+ */
+void
+filemap_create(void)
+{
+ filemap_t *map;
+
+ map = pg_malloc(sizeof(filemap_t));
+ map->first = map->last = NULL;
+ map->nlist = 0;
+ map->array = NULL;
+ map->narray = 0;
+
+ Assert(filemap == NULL);
+ filemap = map;
+}
+
+/*
+ * Callback for processing source file list.
+ *
+ * This is called once for every file in the source server. We decide what
+ * action needs to be taken for the file, depending on whether the file
+ * exists in the target and whether the size matches.
+ */
+void
+process_source_file(const char *path, file_type_t type, size_t newsize,
+ const char *link_target)
+{
+ bool exists;
+ char localpath[MAXPGPATH];
+ struct stat statbuf;
+ filemap_t *map = filemap;
+ file_action_t action = FILE_ACTION_NONE;
+ size_t oldsize = 0;
+ file_entry_t *entry;
+
+ Assert(map->array == NULL);
+
+ /*
+ * Skip any files matching the exclusion filters. This has the effect to
+ * remove all those files on the target.
+ */
+ if (check_file_excluded(path, true))
+ return;
+
+ /*
+ * Pretend that pg_wal is a directory, even if it's really a symlink. We
+ * don't want to mess with the symlink itself, nor complain if it's a
+ * symlink in source but not in target or vice versa.
+ */
+ if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
+ type = FILE_TYPE_DIRECTORY;
+
+ /*
+ * Skip temporary files, .../pgsql_tmp/... and .../pgsql_tmp.* in source.
+ * This has the effect that all temporary files in the destination will be
+ * removed.
+ */
+ if (strstr(path, "/" PG_TEMP_FILE_PREFIX) != NULL)
+ return;
+ if (strstr(path, "/" PG_TEMP_FILES_DIR "/") != NULL)
+ return;
+
+ /*
+ * sanity check: a filename that looks like a data file better be a
+ * regular file
+ */
+ if (type != FILE_TYPE_REGULAR && isRelDataFile(path))
+ pg_fatal("data file \"%s\" in source is not a regular file", path);
+
+ snprintf(localpath, sizeof(localpath), "%s/%s", datadir_target, path);
+
+ /* Does the corresponding file exist in the target data dir? */
+ if (lstat(localpath, &statbuf) < 0)
+ {
+ if (errno != ENOENT)
+ pg_fatal("could not stat file \"%s\": %m",
+ localpath);
+
+ exists = false;
+ }
+ else
+ exists = true;
+
+ switch (type)
+ {
+ case FILE_TYPE_DIRECTORY:
+ if (exists && !S_ISDIR(statbuf.st_mode) && strcmp(path, "pg_wal") != 0)
+ {
+ /* it's a directory in source, but not in target. Strange.. */
+ pg_fatal("\"%s\" is not a directory", localpath);
+ }
+
+ if (!exists)
+ action = FILE_ACTION_CREATE;
+ else
+ action = FILE_ACTION_NONE;
+ oldsize = 0;
+ break;
+
+ case FILE_TYPE_SYMLINK:
+ if (exists &&
+#ifndef WIN32
+ !S_ISLNK(statbuf.st_mode)
+#else
+ !pgwin32_is_junction(localpath)
+#endif
+ )
+ {
+ /*
+ * It's a symbolic link in source, but not in target.
+ * Strange..
+ */
+ pg_fatal("\"%s\" is not a symbolic link", localpath);
+ }
+
+ if (!exists)
+ action = FILE_ACTION_CREATE;
+ else
+ action = FILE_ACTION_NONE;
+ oldsize = 0;
+ break;
+
+ case FILE_TYPE_REGULAR:
+ if (exists && !S_ISREG(statbuf.st_mode))
+ pg_fatal("\"%s\" is not a regular file", localpath);
+
+ if (!exists || !isRelDataFile(path))
+ {
+ /*
+ * File exists in source, but not in target. Or it's a
+ * non-data file that we have no special processing for. Copy
+ * it in toto.
+ *
+ * An exception: PG_VERSIONs should be identical, but avoid
+ * overwriting it for paranoia.
+ */
+ if (pg_str_endswith(path, "PG_VERSION"))
+ {
+ action = FILE_ACTION_NONE;
+ oldsize = statbuf.st_size;
+ }
+ else
+ {
+ action = FILE_ACTION_COPY;
+ oldsize = 0;
+ }
+ }
+ else
+ {
+ /*
+ * It's a data file that exists in both.
+ *
+ * If it's larger in target, we can truncate it. There will
+ * also be a WAL record of the truncation in the source
+ * system, so WAL replay would eventually truncate the target
+ * too, but we might as well do it now.
+ *
+ * If it's smaller in the target, it means that it has been
+ * truncated in the target, or enlarged in the source, or
+ * both. If it was truncated in the target, we need to copy
+ * the missing tail from the source system. If it was enlarged
+ * in the source system, there will be WAL records in the
+ * source system for the new blocks, so we wouldn't need to
+ * copy them here. But we don't know which scenario we're
+ * dealing with, and there's no harm in copying the missing
+ * blocks now, so do it now.
+ *
+ * If it's the same size, do nothing here. Any blocks modified
+ * in the target will be copied based on parsing the target
+ * system's WAL, and any blocks modified in the source will be
+ * updated after rewinding, when the source system's WAL is
+ * replayed.
+ */
+ oldsize = statbuf.st_size;
+ if (oldsize < newsize)
+ action = FILE_ACTION_COPY_TAIL;
+ else if (oldsize > newsize)
+ action = FILE_ACTION_TRUNCATE;
+ else
+ action = FILE_ACTION_NONE;
+ }
+ break;
+ }
+
+ /* Create a new entry for this file */
+ entry = pg_malloc(sizeof(file_entry_t));
+ entry->path = pg_strdup(path);
+ entry->type = type;
+ entry->action = action;
+ entry->oldsize = oldsize;
+ entry->newsize = newsize;
+ entry->link_target = link_target ? pg_strdup(link_target) : NULL;
+ entry->next = NULL;
+ entry->pagemap.bitmap = NULL;
+ entry->pagemap.bitmapsize = 0;
+ entry->isrelfile = isRelDataFile(path);
+
+ if (map->last)
+ {
+ map->last->next = entry;
+ map->last = entry;
+ }
+ else
+ map->first = map->last = entry;
+ map->nlist++;
+}
+
+/*
+ * Callback for processing target file list.
+ *
+ * All source files must be already processed before calling this. This only
+ * marks target data directory's files that didn't exist in the source for
+ * deletion.
+ */
+void
+process_target_file(const char *path, file_type_t type, size_t oldsize,
+ const char *link_target)
+{
+ bool exists;
+ file_entry_t key;
+ file_entry_t *key_ptr;
+ filemap_t *map = filemap;
+ file_entry_t *entry;
+
+ /*
+ * Do not apply any exclusion filters here. This has advantage to remove
+ * from the target data folder all paths which have been filtered out from
+ * the source data folder when processing the source files.
+ */
+
+ if (map->array == NULL)
+ {
+ /* on first call, initialize lookup array */
+ if (map->nlist == 0)
+ {
+ /* should not happen */
+ pg_fatal("source file list is empty");
+ }
+
+ filemap_list_to_array(map);
+
+ Assert(map->array != NULL);
+
+ qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
+ }
+
+ /*
+ * Like in process_source_file, pretend that xlog is always a directory.
+ */
+ if (strcmp(path, "pg_wal") == 0 && type == FILE_TYPE_SYMLINK)
+ type = FILE_TYPE_DIRECTORY;
+
+ key.path = (char *) path;
+ key_ptr = &key;
+ exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
+ path_cmp) != NULL);
+
+ /* Remove any file or folder that doesn't exist in the source system. */
+ if (!exists)
+ {
+ entry = pg_malloc(sizeof(file_entry_t));
+ entry->path = pg_strdup(path);
+ entry->type = type;
+ entry->action = FILE_ACTION_REMOVE;
+ entry->oldsize = oldsize;
+ entry->newsize = 0;
+ entry->link_target = link_target ? pg_strdup(link_target) : NULL;
+ entry->next = NULL;
+ entry->pagemap.bitmap = NULL;
+ entry->pagemap.bitmapsize = 0;
+ entry->isrelfile = isRelDataFile(path);
+
+ if (map->last == NULL)
+ map->first = entry;
+ else
+ map->last->next = entry;
+ map->last = entry;
+ map->nlist++;
+ }
+ else
+ {
+ /*
+ * We already handled all files that exist in the source system in
+ * process_source_file().
+ */
+ }
+}
+
+/*
+ * This callback gets called while we read the WAL in the target, for every
+ * block that have changed in the target system. It makes note of all the
+ * changed blocks in the pagemap of the file.
+ */
+void
+process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
+{
+ char *path;
+ file_entry_t key;
+ file_entry_t *key_ptr;
+ file_entry_t *entry;
+ BlockNumber blkno_inseg;
+ int segno;
+ filemap_t *map = filemap;
+ file_entry_t **e;
+
+ Assert(map->array);
+
+ segno = blkno / RELSEG_SIZE;
+ blkno_inseg = blkno % RELSEG_SIZE;
+
+ path = datasegpath(rnode, forknum, segno);
+
+ key.path = (char *) path;
+ key_ptr = &key;
+
+ e = bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
+ path_cmp);
+ if (e)
+ entry = *e;
+ else
+ entry = NULL;
+ pfree(path);
+
+ if (entry)
+ {
+ Assert(entry->isrelfile);
+
+ switch (entry->action)
+ {
+ case FILE_ACTION_NONE:
+ case FILE_ACTION_TRUNCATE:
+ /* skip if we're truncating away the modified block anyway */
+ if ((blkno_inseg + 1) * BLCKSZ <= entry->newsize)
+ datapagemap_add(&entry->pagemap, blkno_inseg);
+ break;
+
+ case FILE_ACTION_COPY_TAIL:
+
+ /*
+ * skip the modified block if it is part of the "tail" that
+ * we're copying anyway.
+ */
+ if ((blkno_inseg + 1) * BLCKSZ <= entry->oldsize)
+ datapagemap_add(&entry->pagemap, blkno_inseg);
+ break;
+
+ case FILE_ACTION_COPY:
+ case FILE_ACTION_REMOVE:
+ break;
+
+ case FILE_ACTION_CREATE:
+ pg_fatal("unexpected page modification for directory or symbolic link \"%s\"", entry->path);
+ }
+ }
+ else
+ {
+ /*
+ * If we don't have any record of this file in the file map, it means
+ * that it's a relation that doesn't exist in the source system, and
+ * it was subsequently removed in the target system, too. We can
+ * safely ignore it.
+ */
+ }
+}
+
+/*
+ * Is this the path of file that pg_rewind can skip copying?
+ */
+static bool
+check_file_excluded(const char *path, bool is_source)
+{
+ char localpath[MAXPGPATH];
+ int excludeIdx;
+ const char *filename;
+
+ /* check individual files... */
+ for (excludeIdx = 0; excludeFiles[excludeIdx].name != NULL; excludeIdx++)
+ {
+ int cmplen = strlen(excludeFiles[excludeIdx].name);
+
+ filename = last_dir_separator(path);
+ if (filename == NULL)
+ filename = path;
+ else
+ filename++;
+
+ if (!excludeFiles[excludeIdx].match_prefix)
+ cmplen++;
+ if (strncmp(filename, excludeFiles[excludeIdx].name, cmplen) == 0)
+ {
+ if (is_source)
+ pg_log_debug("entry \"%s\" excluded from source file list",
+ path);
+ else
+ pg_log_debug("entry \"%s\" excluded from target file list",
+ path);
+ return true;
+ }
+ }
+
+ /*
+ * ... And check some directories. Note that this includes any contents
+ * within the directories themselves.
+ */
+ for (excludeIdx = 0; excludeDirContents[excludeIdx] != NULL; excludeIdx++)
+ {
+ snprintf(localpath, sizeof(localpath), "%s/",
+ excludeDirContents[excludeIdx]);
+ if (strstr(path, localpath) == path)
+ {
+ if (is_source)
+ pg_log_debug("entry \"%s\" excluded from source file list",
+ path);
+ else
+ pg_log_debug("entry \"%s\" excluded from target file list",
+ path);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Convert the linked list of entries in map->first/last to the array,
+ * map->array.
+ */
+static void
+filemap_list_to_array(filemap_t *map)
+{
+ int narray;
+ file_entry_t *entry,
+ *next;
+
+ map->array = (file_entry_t **)
+ pg_realloc(map->array,
+ (map->nlist + map->narray) * sizeof(file_entry_t *));
+
+ narray = map->narray;
+ for (entry = map->first; entry != NULL; entry = next)
+ {
+ map->array[narray++] = entry;
+ next = entry->next;
+ entry->next = NULL;
+ }
+ Assert(narray == map->nlist + map->narray);
+ map->narray = narray;
+ map->nlist = 0;
+ map->first = map->last = NULL;
+}
+
+void
+filemap_finalize(void)
+{
+ filemap_t *map = filemap;
+
+ filemap_list_to_array(map);
+ qsort(map->array, map->narray, sizeof(file_entry_t *),
+ final_filemap_cmp);
+}
+
+static const char *
+action_to_str(file_action_t action)
+{
+ switch (action)
+ {
+ case FILE_ACTION_NONE:
+ return "NONE";
+ case FILE_ACTION_COPY:
+ return "COPY";
+ case FILE_ACTION_TRUNCATE:
+ return "TRUNCATE";
+ case FILE_ACTION_COPY_TAIL:
+ return "COPY_TAIL";
+ case FILE_ACTION_CREATE:
+ return "CREATE";
+ case FILE_ACTION_REMOVE:
+ return "REMOVE";
+
+ default:
+ return "unknown";
+ }
+}
+
+/*
+ * Calculate the totals needed for progress reports.
+ */
+void
+calculate_totals(void)
+{
+ file_entry_t *entry;
+ int i;
+ filemap_t *map = filemap;
+
+ map->total_size = 0;
+ map->fetch_size = 0;
+
+ for (i = 0; i < map->narray; i++)
+ {
+ entry = map->array[i];
+
+ if (entry->type != FILE_TYPE_REGULAR)
+ continue;
+
+ map->total_size += entry->newsize;
+
+ if (entry->action == FILE_ACTION_COPY)
+ {
+ map->fetch_size += entry->newsize;
+ continue;
+ }
+
+ if (entry->action == FILE_ACTION_COPY_TAIL)
+ map->fetch_size += (entry->newsize - entry->oldsize);
+
+ if (entry->pagemap.bitmapsize > 0)
+ {
+ datapagemap_iterator_t *iter;
+ BlockNumber blk;
+
+ iter = datapagemap_iterate(&entry->pagemap);
+ while (datapagemap_next(iter, &blk))
+ map->fetch_size += BLCKSZ;
+
+ pg_free(iter);
+ }
+ }
+}
+
+void
+print_filemap(void)
+{
+ filemap_t *map = filemap;
+ file_entry_t *entry;
+ int i;
+
+ for (i = 0; i < map->narray; i++)
+ {
+ entry = map->array[i];
+ if (entry->action != FILE_ACTION_NONE ||
+ entry->pagemap.bitmapsize > 0)
+ {
+ pg_log_debug("%s (%s)", entry->path,
+ action_to_str(entry->action));
+
+ if (entry->pagemap.bitmapsize > 0)
+ datapagemap_print(&entry->pagemap);
+ }
+ }
+ fflush(stdout);
+}
+
+/*
+ * Does it look like a relation data file?
+ *
+ * For our purposes, only files belonging to the main fork are considered
+ * relation files. Other forks are always copied in toto, because we cannot
+ * reliably track changes to them, because WAL only contains block references
+ * for the main fork.
+ */
+static bool
+isRelDataFile(const char *path)
+{
+ RelFileNode rnode;
+ unsigned int segNo;
+ int nmatch;
+ bool matched;
+
+ /*----
+ * Relation data files can be in one of the following directories:
+ *
+ * global/
+ * shared relations
+ *
+ * base/<db oid>/
+ * regular relations, default tablespace
+ *
+ * pg_tblspc/<tblspc oid>/<tblspc version>/
+ * within a non-default tablespace (the name of the directory
+ * depends on version)
+ *
+ * And the relation data files themselves have a filename like:
+ *
+ * <oid>.<segment number>
+ *
+ *----
+ */
+ rnode.spcNode = InvalidOid;
+ rnode.dbNode = InvalidOid;
+ rnode.relNode = InvalidOid;
+ segNo = 0;
+ matched = false;
+
+ nmatch = sscanf(path, "global/%u.%u", &rnode.relNode, &segNo);
+ if (nmatch == 1 || nmatch == 2)
+ {
+ rnode.spcNode = GLOBALTABLESPACE_OID;
+ rnode.dbNode = 0;
+ matched = true;
+ }
+ else
+ {
+ nmatch = sscanf(path, "base/%u/%u.%u",
+ &rnode.dbNode, &rnode.relNode, &segNo);
+ if (nmatch == 2 || nmatch == 3)
+ {
+ rnode.spcNode = DEFAULTTABLESPACE_OID;
+ matched = true;
+ }
+ else
+ {
+ nmatch = sscanf(path, "pg_tblspc/%u/" TABLESPACE_VERSION_DIRECTORY "/%u/%u.%u",
+ &rnode.spcNode, &rnode.dbNode, &rnode.relNode,
+ &segNo);
+ if (nmatch == 3 || nmatch == 4)
+ matched = true;
+ }
+ }
+
+ /*
+ * The sscanf tests above can match files that have extra characters at
+ * the end. To eliminate such cases, cross-check that GetRelationPath
+ * creates the exact same filename, when passed the RelFileNode
+ * information we extracted from the filename.
+ */
+ if (matched)
+ {
+ char *check_path = datasegpath(rnode, MAIN_FORKNUM, segNo);
+
+ if (strcmp(check_path, path) != 0)
+ matched = false;
+
+ pfree(check_path);
+ }
+
+ return matched;
+}
+
+/*
+ * A helper function to create the path of a relation file and segment.
+ *
+ * The returned path is palloc'd
+ */
+static char *
+datasegpath(RelFileNode rnode, ForkNumber forknum, BlockNumber segno)
+{
+ char *path;
+ char *segpath;
+
+ path = relpathperm(rnode, forknum);
+ if (segno > 0)
+ {
+ segpath = psprintf("%s.%u", path, segno);
+ pfree(path);
+ return segpath;
+ }
+ else
+ return path;
+}
+
+static int
+path_cmp(const void *a, const void *b)
+{
+ file_entry_t *fa = *((file_entry_t **) a);
+ file_entry_t *fb = *((file_entry_t **) b);
+
+ return strcmp(fa->path, fb->path);
+}
+
+/*
+ * In the final stage, the filemap is sorted so that removals come last.
+ * From disk space usage point of view, it would be better to do removals
+ * first, but for now, safety first. If a whole directory is deleted, all
+ * files and subdirectories inside it need to removed first. On creation,
+ * parent directory needs to be created before files and directories inside
+ * it. To achieve that, the file_action_t enum is ordered so that we can
+ * just sort on that first. Furthermore, sort REMOVE entries in reverse
+ * path order, so that "foo/bar" subdirectory is removed before "foo".
+ */
+static int
+final_filemap_cmp(const void *a, const void *b)
+{
+ file_entry_t *fa = *((file_entry_t **) a);
+ file_entry_t *fb = *((file_entry_t **) b);
+
+ if (fa->action > fb->action)
+ return 1;
+ if (fa->action < fb->action)
+ return -1;
+
+ if (fa->action == FILE_ACTION_REMOVE)
+ return strcmp(fb->path, fa->path);
+ else
+ return strcmp(fa->path, fb->path);
+}
diff --git a/src/bin/pg_rewind/filemap.h b/src/bin/pg_rewind/filemap.h
new file mode 100644
index 0000000..0cb7425
--- /dev/null
+++ b/src/bin/pg_rewind/filemap.h
@@ -0,0 +1,104 @@
+/*-------------------------------------------------------------------------
+ *
+ * filemap.h
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *-------------------------------------------------------------------------
+ */
+#ifndef FILEMAP_H
+#define FILEMAP_H
+
+#include "datapagemap.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+/*
+ * For every file found in the local or remote system, we have a file entry
+ * which says what we are going to do with the file. For relation files,
+ * there is also a page map, marking pages in the file that were changed
+ * locally.
+ *
+ * The enum values are sorted in the order we want actions to be processed.
+ */
+typedef enum
+{
+ FILE_ACTION_CREATE, /* create local directory or symbolic link */
+ FILE_ACTION_COPY, /* copy whole file, overwriting if exists */
+ FILE_ACTION_COPY_TAIL, /* copy tail from 'oldsize' to 'newsize' */
+ FILE_ACTION_NONE, /* no action (we might still copy modified
+ * blocks based on the parsed WAL) */
+ FILE_ACTION_TRUNCATE, /* truncate local file to 'newsize' bytes */
+ FILE_ACTION_REMOVE /* remove local file / directory / symlink */
+} file_action_t;
+
+typedef enum
+{
+ FILE_TYPE_REGULAR,
+ FILE_TYPE_DIRECTORY,
+ FILE_TYPE_SYMLINK
+} file_type_t;
+
+typedef struct file_entry_t
+{
+ char *path;
+ file_type_t type;
+
+ file_action_t action;
+
+ /* for a regular file */
+ size_t oldsize;
+ size_t newsize;
+ bool isrelfile; /* is it a relation data file? */
+
+ datapagemap_t pagemap;
+
+ /* for a symlink */
+ char *link_target;
+
+ struct file_entry_t *next;
+} file_entry_t;
+
+typedef struct filemap_t
+{
+ /*
+ * New entries are accumulated to a linked list, in process_source_file
+ * and process_target_file.
+ */
+ file_entry_t *first;
+ file_entry_t *last;
+ int nlist; /* number of entries currently in list */
+
+ /*
+ * After processing all the remote files, the entries in the linked list
+ * are moved to this array. After processing local files, too, all the
+ * local entries are added to the array by filemap_finalize, and sorted in
+ * the final order. After filemap_finalize, all the entries are in the
+ * array, and the linked list is empty.
+ */
+ file_entry_t **array;
+ int narray; /* current length of array */
+
+ /*
+ * Summary information. total_size is the total size of the source
+ * cluster, and fetch_size is the number of bytes that needs to be copied.
+ */
+ uint64 total_size;
+ uint64 fetch_size;
+} filemap_t;
+
+extern filemap_t *filemap;
+
+extern void filemap_create(void);
+extern void calculate_totals(void);
+extern void print_filemap(void);
+
+/* Functions for populating the filemap */
+extern void process_source_file(const char *path, file_type_t type,
+ size_t newsize, const char *link_target);
+extern void process_target_file(const char *path, file_type_t type,
+ size_t newsize, const char *link_target);
+extern void process_block_change(ForkNumber forknum, RelFileNode rnode,
+ BlockNumber blkno);
+extern void filemap_finalize(void);
+
+#endif /* FILEMAP_H */
diff --git a/src/bin/pg_rewind/libpq_fetch.c b/src/bin/pg_rewind/libpq_fetch.c
new file mode 100644
index 0000000..f4706e9
--- /dev/null
+++ b/src/bin/pg_rewind/libpq_fetch.c
@@ -0,0 +1,538 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq_fetch.c
+ * Functions for fetching files from a remote server.
+ *
+ * Copyright (c) 2013-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "catalog/pg_type_d.h"
+#include "common/connect.h"
+#include "datapagemap.h"
+#include "fetch.h"
+#include "file_ops.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+#include "port/pg_bswap.h"
+
+PGconn *conn = NULL;
+
+/*
+ * Files are fetched max CHUNKSIZE bytes at a time.
+ *
+ * (This only applies to files that are copied in whole, or for truncated
+ * files where we copy the tail. Relation files, where we know the individual
+ * blocks that need to be fetched, are fetched in BLCKSZ chunks.)
+ */
+#define CHUNKSIZE 1000000
+
+static void receiveFileChunks(const char *sql);
+static void execute_pagemap(datapagemap_t *pagemap, const char *path);
+static char *run_simple_query(const char *sql);
+static void run_simple_command(const char *sql);
+
+void
+libpqConnect(const char *connstr)
+{
+ char *str;
+ PGresult *res;
+
+ conn = PQconnectdb(connstr);
+ if (PQstatus(conn) == CONNECTION_BAD)
+ pg_fatal("%s", PQerrorMessage(conn));
+
+ if (showprogress)
+ pg_log_info("connected to server");
+
+ /* disable all types of timeouts */
+ run_simple_command("SET statement_timeout = 0");
+ run_simple_command("SET lock_timeout = 0");
+ run_simple_command("SET idle_in_transaction_session_timeout = 0");
+
+ res = PQexec(conn, ALWAYS_SECURE_SEARCH_PATH_SQL);
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("could not clear search_path: %s",
+ PQresultErrorMessage(res));
+ PQclear(res);
+
+ /*
+ * Check that the server is not in hot standby mode. There is no
+ * fundamental reason that couldn't be made to work, but it doesn't
+ * currently because we use a temporary table. Better to check for it
+ * explicitly than error out, for a better error message.
+ */
+ str = run_simple_query("SELECT pg_is_in_recovery()");
+ if (strcmp(str, "f") != 0)
+ pg_fatal("source server must not be in recovery mode");
+ pg_free(str);
+
+ /*
+ * Also check that full_page_writes is enabled. We can get torn pages if
+ * a page is modified while we read it with pg_read_binary_file(), and we
+ * rely on full page images to fix them.
+ */
+ str = run_simple_query("SHOW full_page_writes");
+ if (strcmp(str, "on") != 0)
+ pg_fatal("full_page_writes must be enabled in the source server");
+ pg_free(str);
+
+ /*
+ * Although we don't do any "real" updates, we do work with a temporary
+ * table. We don't care about synchronous commit for that. It doesn't
+ * otherwise matter much, but if the server is using synchronous
+ * replication, and replication isn't working for some reason, we don't
+ * want to get stuck, waiting for it to start working again.
+ */
+ run_simple_command("SET synchronous_commit = off");
+}
+
+/*
+ * Runs a query that returns a single value.
+ * The result should be pg_free'd after use.
+ */
+static char *
+run_simple_query(const char *sql)
+{
+ PGresult *res;
+ char *result;
+
+ res = PQexec(conn, sql);
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("error running query (%s) on source server: %s",
+ sql, PQresultErrorMessage(res));
+
+ /* sanity check the result set */
+ if (PQnfields(res) != 1 || PQntuples(res) != 1 || PQgetisnull(res, 0, 0))
+ pg_fatal("unexpected result set from query");
+
+ result = pg_strdup(PQgetvalue(res, 0, 0));
+
+ PQclear(res);
+
+ return result;
+}
+
+/*
+ * Runs a command.
+ * In the event of a failure, exit immediately.
+ */
+static void
+run_simple_command(const char *sql)
+{
+ PGresult *res;
+
+ res = PQexec(conn, sql);
+
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("error running query (%s) in source server: %s",
+ sql, PQresultErrorMessage(res));
+
+ PQclear(res);
+}
+
+/*
+ * Calls pg_current_wal_insert_lsn() function
+ */
+XLogRecPtr
+libpqGetCurrentXlogInsertLocation(void)
+{
+ XLogRecPtr result;
+ uint32 hi;
+ uint32 lo;
+ char *val;
+
+ val = run_simple_query("SELECT pg_current_wal_insert_lsn()");
+
+ if (sscanf(val, "%X/%X", &hi, &lo) != 2)
+ pg_fatal("unrecognized result \"%s\" for current WAL insert location", val);
+
+ result = ((uint64) hi) << 32 | lo;
+
+ pg_free(val);
+
+ return result;
+}
+
+/*
+ * Get a list of all files in the data directory.
+ */
+void
+libpqProcessFileList(void)
+{
+ PGresult *res;
+ const char *sql;
+ int i;
+
+ /*
+ * Create a recursive directory listing of the whole data directory.
+ *
+ * The WITH RECURSIVE part does most of the work. The second part gets the
+ * targets of the symlinks in pg_tblspc directory.
+ *
+ * XXX: There is no backend function to get a symbolic link's target in
+ * general, so if the admin has put any custom symbolic links in the data
+ * directory, they won't be copied correctly.
+ */
+ sql =
+ "WITH RECURSIVE files (path, filename, size, isdir) AS (\n"
+ " SELECT '' AS path, filename, size, isdir FROM\n"
+ " (SELECT pg_ls_dir('.', true, false) AS filename) AS fn,\n"
+ " pg_stat_file(fn.filename, true) AS this\n"
+ " UNION ALL\n"
+ " SELECT parent.path || parent.filename || '/' AS path,\n"
+ " fn, this.size, this.isdir\n"
+ " FROM files AS parent,\n"
+ " pg_ls_dir(parent.path || parent.filename, true, false) AS fn,\n"
+ " pg_stat_file(parent.path || parent.filename || '/' || fn, true) AS this\n"
+ " WHERE parent.isdir = 't'\n"
+ ")\n"
+ "SELECT path || filename, size, isdir,\n"
+ " pg_tablespace_location(pg_tablespace.oid) AS link_target\n"
+ "FROM files\n"
+ "LEFT OUTER JOIN pg_tablespace ON files.path = 'pg_tblspc/'\n"
+ " AND oid::text = files.filename\n";
+ res = PQexec(conn, sql);
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("could not fetch file list: %s",
+ PQresultErrorMessage(res));
+
+ /* sanity check the result set */
+ if (PQnfields(res) != 4)
+ pg_fatal("unexpected result set while fetching file list");
+
+ /* Read result to local variables */
+ for (i = 0; i < PQntuples(res); i++)
+ {
+ char *path;
+ int64 filesize;
+ bool isdir;
+ char *link_target;
+ file_type_t type;
+
+ if (PQgetisnull(res, i, 1))
+ {
+ /*
+ * The file was removed from the server while the query was
+ * running. Ignore it.
+ */
+ continue;
+ }
+
+ path = PQgetvalue(res, i, 0);
+ filesize = atol(PQgetvalue(res, i, 1));
+ isdir = (strcmp(PQgetvalue(res, i, 2), "t") == 0);
+ link_target = PQgetvalue(res, i, 3);
+
+ if (link_target[0])
+ type = FILE_TYPE_SYMLINK;
+ else if (isdir)
+ type = FILE_TYPE_DIRECTORY;
+ else
+ type = FILE_TYPE_REGULAR;
+
+ process_source_file(path, type, filesize, link_target);
+ }
+ PQclear(res);
+}
+
+/*----
+ * Runs a query, which returns pieces of files from the remote source data
+ * directory, and overwrites the corresponding parts of target files with
+ * the received parts. The result set is expected to be of format:
+ *
+ * path text -- path in the data directory, e.g "base/1/123"
+ * begin int8 -- offset within the file
+ * chunk bytea -- file content
+ *----
+ */
+static void
+receiveFileChunks(const char *sql)
+{
+ PGresult *res;
+
+ if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1)
+ pg_fatal("could not send query: %s", PQerrorMessage(conn));
+
+ pg_log_debug("getting file chunks");
+
+ if (PQsetSingleRowMode(conn) != 1)
+ pg_fatal("could not set libpq connection to single row mode");
+
+ while ((res = PQgetResult(conn)) != NULL)
+ {
+ char *filename;
+ int filenamelen;
+ int64 chunkoff;
+ int chunksize;
+ char *chunk;
+
+ switch (PQresultStatus(res))
+ {
+ case PGRES_SINGLE_TUPLE:
+ break;
+
+ case PGRES_TUPLES_OK:
+ PQclear(res);
+ continue; /* final zero-row result */
+
+ default:
+ pg_fatal("unexpected result while fetching remote files: %s",
+ PQresultErrorMessage(res));
+ }
+
+ /* sanity check the result set */
+ if (PQnfields(res) != 3 || PQntuples(res) != 1)
+ pg_fatal("unexpected result set size while fetching remote files");
+
+ if (PQftype(res, 0) != TEXTOID ||
+ PQftype(res, 1) != INT8OID ||
+ PQftype(res, 2) != BYTEAOID)
+ {
+ pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u",
+ PQftype(res, 0), PQftype(res, 1), PQftype(res, 2));
+ }
+
+ if (PQfformat(res, 0) != 1 &&
+ PQfformat(res, 1) != 1 &&
+ PQfformat(res, 2) != 1)
+ {
+ pg_fatal("unexpected result format while fetching remote files");
+ }
+
+ if (PQgetisnull(res, 0, 0) ||
+ PQgetisnull(res, 0, 1))
+ {
+ pg_fatal("unexpected null values in result while fetching remote files");
+ }
+
+ if (PQgetlength(res, 0, 1) != sizeof(int64))
+ pg_fatal("unexpected result length while fetching remote files");
+
+ /* Read result set to local variables */
+ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int64));
+ chunkoff = pg_ntoh64(chunkoff);
+ chunksize = PQgetlength(res, 0, 2);
+
+ filenamelen = PQgetlength(res, 0, 0);
+ filename = pg_malloc(filenamelen + 1);
+ memcpy(filename, PQgetvalue(res, 0, 0), filenamelen);
+ filename[filenamelen] = '\0';
+
+ chunk = PQgetvalue(res, 0, 2);
+
+ /*
+ * If a file has been deleted on the source, remove it on the target
+ * as well. Note that multiple unlink() calls may happen on the same
+ * file if multiple data chunks are associated with it, hence ignore
+ * unconditionally anything missing. If this file is not a relation
+ * data file, then it has been already truncated when creating the
+ * file chunk list at the previous execution of the filemap.
+ */
+ if (PQgetisnull(res, 0, 2))
+ {
+ pg_log_debug("received null value for chunk for file \"%s\", file has been deleted",
+ filename);
+ remove_target_file(filename, true);
+ pg_free(filename);
+ PQclear(res);
+ continue;
+ }
+
+ pg_log_debug("received chunk for file \"%s\", offset %lld, size %d",
+ filename, (long long int) chunkoff, chunksize);
+
+ open_target_file(filename, false);
+
+ write_target_range(chunk, chunkoff, chunksize);
+
+ pg_free(filename);
+
+ PQclear(res);
+ }
+}
+
+/*
+ * Receive a single file as a malloc'd buffer.
+ */
+char *
+libpqGetFile(const char *filename, size_t *filesize)
+{
+ PGresult *res;
+ char *result;
+ int len;
+ const char *paramValues[1];
+
+ paramValues[0] = filename;
+ res = PQexecParams(conn, "SELECT pg_read_binary_file($1)",
+ 1, NULL, paramValues, NULL, NULL, 1);
+
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ pg_fatal("could not fetch remote file \"%s\": %s",
+ filename, PQresultErrorMessage(res));
+
+ /* sanity check the result set */
+ if (PQntuples(res) != 1 || PQgetisnull(res, 0, 0))
+ pg_fatal("unexpected result set while fetching remote file \"%s\"",
+ filename);
+
+ /* Read result to local variables */
+ len = PQgetlength(res, 0, 0);
+ result = pg_malloc(len + 1);
+ memcpy(result, PQgetvalue(res, 0, 0), len);
+ result[len] = '\0';
+
+ PQclear(res);
+
+ pg_log_debug("fetched file \"%s\", length %d", filename, len);
+
+ if (filesize)
+ *filesize = len;
+ return result;
+}
+
+/*
+ * Write a file range to a temporary table in the server.
+ *
+ * The range is sent to the server as a COPY formatted line, to be inserted
+ * into the 'fetchchunks' temporary table. It is used in receiveFileChunks()
+ * function to actually fetch the data.
+ */
+static void
+fetch_file_range(const char *path, uint64 begin, uint64 end)
+{
+ char linebuf[MAXPGPATH + 23];
+
+ /* Split the range into CHUNKSIZE chunks */
+ while (end - begin > 0)
+ {
+ unsigned int len;
+
+ /* Fine as long as CHUNKSIZE is not bigger than UINT32_MAX */
+ if (end - begin > CHUNKSIZE)
+ len = CHUNKSIZE;
+ else
+ len = (unsigned int) (end - begin);
+
+ snprintf(linebuf, sizeof(linebuf), "%s\t" UINT64_FORMAT "\t%u\n", path, begin, len);
+
+ if (PQputCopyData(conn, linebuf, strlen(linebuf)) != 1)
+ pg_fatal("could not send COPY data: %s",
+ PQerrorMessage(conn));
+
+ begin += len;
+ }
+}
+
+/*
+ * Fetch all changed blocks from remote source data directory.
+ */
+void
+libpq_executeFileMap(filemap_t *map)
+{
+ file_entry_t *entry;
+ const char *sql;
+ PGresult *res;
+ int i;
+
+ /*
+ * First create a temporary table, and load it with the blocks that we
+ * need to fetch.
+ */
+ sql = "CREATE TEMPORARY TABLE fetchchunks(path text, begin int8, len int4);";
+ run_simple_command(sql);
+
+ sql = "COPY fetchchunks FROM STDIN";
+ res = PQexec(conn, sql);
+
+ if (PQresultStatus(res) != PGRES_COPY_IN)
+ pg_fatal("could not send file list: %s",
+ PQresultErrorMessage(res));
+ PQclear(res);
+
+ for (i = 0; i < map->narray; i++)
+ {
+ entry = map->array[i];
+
+ /* If this is a relation file, copy the modified blocks */
+ execute_pagemap(&entry->pagemap, entry->path);
+
+ switch (entry->action)
+ {
+ case FILE_ACTION_NONE:
+ /* nothing else to do */
+ break;
+
+ case FILE_ACTION_COPY:
+ /* Truncate the old file out of the way, if any */
+ open_target_file(entry->path, true);
+ fetch_file_range(entry->path, 0, entry->newsize);
+ break;
+
+ case FILE_ACTION_TRUNCATE:
+ truncate_target_file(entry->path, entry->newsize);
+ break;
+
+ case FILE_ACTION_COPY_TAIL:
+ fetch_file_range(entry->path, entry->oldsize, entry->newsize);
+ break;
+
+ case FILE_ACTION_REMOVE:
+ remove_target(entry);
+ break;
+
+ case FILE_ACTION_CREATE:
+ create_target(entry);
+ break;
+ }
+ }
+
+ if (PQputCopyEnd(conn, NULL) != 1)
+ pg_fatal("could not send end-of-COPY: %s",
+ PQerrorMessage(conn));
+
+ while ((res = PQgetResult(conn)) != NULL)
+ {
+ if (PQresultStatus(res) != PGRES_COMMAND_OK)
+ pg_fatal("unexpected result while sending file list: %s",
+ PQresultErrorMessage(res));
+ PQclear(res);
+ }
+
+ /*
+ * We've now copied the list of file ranges that we need to fetch to the
+ * temporary table. Now, actually fetch all of those ranges.
+ */
+ sql =
+ "SELECT path, begin,\n"
+ " pg_read_binary_file(path, begin, len, true) AS chunk\n"
+ "FROM fetchchunks\n";
+
+ receiveFileChunks(sql);
+}
+
+static void
+execute_pagemap(datapagemap_t *pagemap, const char *path)
+{
+ datapagemap_iterator_t *iter;
+ BlockNumber blkno;
+ off_t offset;
+
+ iter = datapagemap_iterate(pagemap);
+ while (datapagemap_next(iter, &blkno))
+ {
+ offset = blkno * BLCKSZ;
+
+ fetch_file_range(path, offset, offset + BLCKSZ);
+ }
+ pg_free(iter);
+}
diff --git a/src/bin/pg_rewind/nls.mk b/src/bin/pg_rewind/nls.mk
new file mode 100644
index 0000000..2cefb92
--- /dev/null
+++ b/src/bin/pg_rewind/nls.mk
@@ -0,0 +1,8 @@
+# src/bin/pg_rewind/nls.mk
+CATALOG_NAME = pg_rewind
+AVAIL_LANGUAGES = cs de es fr ja ko ru sv tr uk zh_CN
+GETTEXT_FILES = $(FRONTEND_COMMON_GETTEXT_FILES) copy_fetch.c datapagemap.c fetch.c file_ops.c filemap.c libpq_fetch.c parsexlog.c pg_rewind.c timeline.c xlogreader.c ../../common/fe_memutils.c ../../common/restricted_token.c ../../fe_utils/archive.c ../../fe_utils/recovery_gen.c
+GETTEXT_TRIGGERS = $(FRONTEND_COMMON_GETTEXT_TRIGGERS) pg_fatal report_invalid_record:2
+GETTEXT_FLAGS = $(FRONTEND_COMMON_GETTEXT_FLAGS) \
+ pg_fatal:1:c-format \
+ report_invalid_record:2:c-format
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
new file mode 100644
index 0000000..1a67725
--- /dev/null
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -0,0 +1,437 @@
+/*-------------------------------------------------------------------------
+ *
+ * parsexlog.c
+ * Functions for reading Write-Ahead-Log
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <unistd.h>
+
+#include "access/rmgr.h"
+#include "access/xlog_internal.h"
+#include "access/xlogreader.h"
+#include "catalog/pg_control.h"
+#include "catalog/storage_xlog.h"
+#include "commands/dbcommands_xlog.h"
+#include "fe_utils/archive.h"
+#include "filemap.h"
+#include "pg_rewind.h"
+
+/*
+ * RmgrNames is an array of resource manager names, to make error messages
+ * a bit nicer.
+ */
+#define PG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask) \
+ name,
+
+static const char *RmgrNames[RM_MAX_ID + 1] = {
+#include "access/rmgrlist.h"
+};
+
+static void extractPageInfo(XLogReaderState *record);
+
+static int xlogreadfd = -1;
+static XLogSegNo xlogreadsegno = -1;
+static char xlogfpath[MAXPGPATH];
+
+typedef struct XLogPageReadPrivate
+{
+ const char *restoreCommand;
+ int tliIndex;
+} XLogPageReadPrivate;
+
+static int SimpleXLogPageRead(XLogReaderState *xlogreader,
+ XLogRecPtr targetPagePtr,
+ int reqLen, XLogRecPtr targetRecPtr, char *readBuf);
+
+/*
+ * Read WAL from the datadir/pg_wal, starting from 'startpoint' on timeline
+ * index 'tliIndex' in target timeline history, until 'endpoint'. Make note of
+ * the data blocks touched by the WAL records, and return them in a page map.
+ *
+ * 'endpoint' is the end of the last record to read. The record starting at
+ * 'endpoint' is the first one that is not read.
+ */
+void
+extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
+ XLogRecPtr endpoint, const char *restoreCommand)
+{
+ XLogRecord *record;
+ XLogReaderState *xlogreader;
+ char *errormsg;
+ XLogPageReadPrivate private;
+
+ private.tliIndex = tliIndex;
+ private.restoreCommand = restoreCommand;
+ xlogreader = XLogReaderAllocate(WalSegSz, datadir,
+ XL_ROUTINE(.page_read = &SimpleXLogPageRead),
+ &private);
+ if (xlogreader == NULL)
+ pg_fatal("out of memory");
+
+ XLogBeginRead(xlogreader, startpoint);
+ do
+ {
+ record = XLogReadRecord(xlogreader, &errormsg);
+
+ if (record == NULL)
+ {
+ XLogRecPtr errptr = xlogreader->EndRecPtr;
+
+ if (errormsg)
+ pg_fatal("could not read WAL record at %X/%X: %s",
+ (uint32) (errptr >> 32), (uint32) (errptr),
+ errormsg);
+ else
+ pg_fatal("could not read WAL record at %X/%X",
+ (uint32) (errptr >> 32), (uint32) (errptr));
+ }
+
+ extractPageInfo(xlogreader);
+
+ } while (xlogreader->EndRecPtr < endpoint);
+
+ /*
+ * If 'endpoint' didn't point exactly at a record boundary, the caller
+ * messed up.
+ */
+ Assert(xlogreader->EndRecPtr == endpoint);
+
+ XLogReaderFree(xlogreader);
+ if (xlogreadfd != -1)
+ {
+ close(xlogreadfd);
+ xlogreadfd = -1;
+ }
+}
+
+/*
+ * Reads one WAL record. Returns the end position of the record, without
+ * doing anything with the record itself.
+ */
+XLogRecPtr
+readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex,
+ const char *restoreCommand)
+{
+ XLogRecord *record;
+ XLogReaderState *xlogreader;
+ char *errormsg;
+ XLogPageReadPrivate private;
+ XLogRecPtr endptr;
+
+ private.tliIndex = tliIndex;
+ private.restoreCommand = restoreCommand;
+ xlogreader = XLogReaderAllocate(WalSegSz, datadir,
+ XL_ROUTINE(.page_read = &SimpleXLogPageRead),
+ &private);
+ if (xlogreader == NULL)
+ pg_fatal("out of memory");
+
+ XLogBeginRead(xlogreader, ptr);
+ record = XLogReadRecord(xlogreader, &errormsg);
+ if (record == NULL)
+ {
+ if (errormsg)
+ pg_fatal("could not read WAL record at %X/%X: %s",
+ (uint32) (ptr >> 32), (uint32) (ptr), errormsg);
+ else
+ pg_fatal("could not read WAL record at %X/%X",
+ (uint32) (ptr >> 32), (uint32) (ptr));
+ }
+ endptr = xlogreader->EndRecPtr;
+
+ XLogReaderFree(xlogreader);
+ if (xlogreadfd != -1)
+ {
+ close(xlogreadfd);
+ xlogreadfd = -1;
+ }
+
+ return endptr;
+}
+
+/*
+ * Find the previous checkpoint preceding given WAL location.
+ */
+void
+findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
+ XLogRecPtr *lastchkptrec, TimeLineID *lastchkpttli,
+ XLogRecPtr *lastchkptredo, const char *restoreCommand)
+{
+ /* Walk backwards, starting from the given record */
+ XLogRecord *record;
+ XLogRecPtr searchptr;
+ XLogReaderState *xlogreader;
+ char *errormsg;
+ XLogPageReadPrivate private;
+
+ /*
+ * The given fork pointer points to the end of the last common record,
+ * which is not necessarily the beginning of the next record, if the
+ * previous record happens to end at a page boundary. Skip over the page
+ * header in that case to find the next record.
+ */
+ if (forkptr % XLOG_BLCKSZ == 0)
+ {
+ if (XLogSegmentOffset(forkptr, WalSegSz) == 0)
+ forkptr += SizeOfXLogLongPHD;
+ else
+ forkptr += SizeOfXLogShortPHD;
+ }
+
+ private.tliIndex = tliIndex;
+ private.restoreCommand = restoreCommand;
+ xlogreader = XLogReaderAllocate(WalSegSz, datadir,
+ XL_ROUTINE(.page_read = &SimpleXLogPageRead),
+ &private);
+ if (xlogreader == NULL)
+ pg_fatal("out of memory");
+
+ searchptr = forkptr;
+ for (;;)
+ {
+ uint8 info;
+
+ XLogBeginRead(xlogreader, searchptr);
+ record = XLogReadRecord(xlogreader, &errormsg);
+
+ if (record == NULL)
+ {
+ if (errormsg)
+ pg_fatal("could not find previous WAL record at %X/%X: %s",
+ (uint32) (searchptr >> 32), (uint32) (searchptr),
+ errormsg);
+ else
+ pg_fatal("could not find previous WAL record at %X/%X",
+ (uint32) (searchptr >> 32), (uint32) (searchptr));
+ }
+
+ /*
+ * Check if it is a checkpoint record. This checkpoint record needs to
+ * be the latest checkpoint before WAL forked and not the checkpoint
+ * where the master has been stopped to be rewinded.
+ */
+ info = XLogRecGetInfo(xlogreader) & ~XLR_INFO_MASK;
+ if (searchptr < forkptr &&
+ XLogRecGetRmid(xlogreader) == RM_XLOG_ID &&
+ (info == XLOG_CHECKPOINT_SHUTDOWN ||
+ info == XLOG_CHECKPOINT_ONLINE))
+ {
+ CheckPoint checkPoint;
+
+ memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
+ *lastchkptrec = searchptr;
+ *lastchkpttli = checkPoint.ThisTimeLineID;
+ *lastchkptredo = checkPoint.redo;
+ break;
+ }
+
+ /* Walk backwards to previous record. */
+ searchptr = record->xl_prev;
+ }
+
+ XLogReaderFree(xlogreader);
+ if (xlogreadfd != -1)
+ {
+ close(xlogreadfd);
+ xlogreadfd = -1;
+ }
+}
+
+/* XLogReader callback function, to read a WAL page */
+static int
+SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
+ int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
+{
+ XLogPageReadPrivate *private = (XLogPageReadPrivate *) xlogreader->private_data;
+ uint32 targetPageOff;
+ XLogRecPtr targetSegEnd;
+ XLogSegNo targetSegNo;
+ int r;
+
+ XLByteToSeg(targetPagePtr, targetSegNo, WalSegSz);
+ XLogSegNoOffsetToRecPtr(targetSegNo + 1, 0, WalSegSz, targetSegEnd);
+ targetPageOff = XLogSegmentOffset(targetPagePtr, WalSegSz);
+
+ /*
+ * See if we need to switch to a new segment because the requested record
+ * is not in the currently open one.
+ */
+ if (xlogreadfd >= 0 &&
+ !XLByteInSeg(targetPagePtr, xlogreadsegno, WalSegSz))
+ {
+ close(xlogreadfd);
+ xlogreadfd = -1;
+ }
+
+ XLByteToSeg(targetPagePtr, xlogreadsegno, WalSegSz);
+
+ if (xlogreadfd < 0)
+ {
+ char xlogfname[MAXFNAMELEN];
+
+ /*
+ * Since incomplete segments are copied into next timelines, switch to
+ * the timeline holding the required segment. Assuming this scan can
+ * be done both forward and backward, consider also switching timeline
+ * accordingly.
+ */
+ while (private->tliIndex < targetNentries - 1 &&
+ targetHistory[private->tliIndex].end < targetSegEnd)
+ private->tliIndex++;
+ while (private->tliIndex > 0 &&
+ targetHistory[private->tliIndex].begin >= targetSegEnd)
+ private->tliIndex--;
+
+ XLogFileName(xlogfname, targetHistory[private->tliIndex].tli,
+ xlogreadsegno, WalSegSz);
+
+ snprintf(xlogfpath, MAXPGPATH, "%s/" XLOGDIR "/%s",
+ xlogreader->segcxt.ws_dir, xlogfname);
+
+ xlogreadfd = open(xlogfpath, O_RDONLY | PG_BINARY, 0);
+
+ if (xlogreadfd < 0)
+ {
+ /*
+ * If we have no restore_command to execute, then exit.
+ */
+ if (private->restoreCommand == NULL)
+ {
+ pg_log_error("could not open file \"%s\": %m", xlogfpath);
+ return -1;
+ }
+
+ /*
+ * Since we have restore_command, then try to retrieve missing WAL
+ * file from the archive.
+ */
+ xlogreadfd = RestoreArchivedFile(xlogreader->segcxt.ws_dir,
+ xlogfname,
+ WalSegSz,
+ private->restoreCommand);
+
+ if (xlogreadfd < 0)
+ return -1;
+ else
+ pg_log_debug("using file \"%s\" restored from archive",
+ xlogfpath);
+ }
+ }
+
+ /*
+ * At this point, we have the right segment open.
+ */
+ Assert(xlogreadfd != -1);
+
+ /* Read the requested page */
+ if (lseek(xlogreadfd, (off_t) targetPageOff, SEEK_SET) < 0)
+ {
+ pg_log_error("could not seek in file \"%s\": %m", xlogfpath);
+ return -1;
+ }
+
+
+ r = read(xlogreadfd, readBuf, XLOG_BLCKSZ);
+ if (r != XLOG_BLCKSZ)
+ {
+ if (r < 0)
+ pg_log_error("could not read file \"%s\": %m", xlogfpath);
+ else
+ pg_log_error("could not read file \"%s\": read %d of %zu",
+ xlogfpath, r, (Size) XLOG_BLCKSZ);
+
+ return -1;
+ }
+
+ Assert(targetSegNo == xlogreadsegno);
+
+ xlogreader->seg.ws_tli = targetHistory[private->tliIndex].tli;
+ return XLOG_BLCKSZ;
+}
+
+/*
+ * Extract information on which blocks the current record modifies.
+ */
+static void
+extractPageInfo(XLogReaderState *record)
+{
+ int block_id;
+ RmgrId rmid = XLogRecGetRmid(record);
+ uint8 info = XLogRecGetInfo(record);
+ uint8 rminfo = info & ~XLR_INFO_MASK;
+
+ /* Is this a special record type that I recognize? */
+
+ if (rmid == RM_DBASE_ID && rminfo == XLOG_DBASE_CREATE)
+ {
+ /*
+ * New databases can be safely ignored. It won't be present in the
+ * source system, so it will be deleted. There's one corner-case,
+ * though: if a new, different, database is also created in the source
+ * system, we'll see that the files already exist and not copy them.
+ * That's OK, though; WAL replay of creating the new database, from
+ * the source systems's WAL, will re-copy the new database,
+ * overwriting the database created in the target system.
+ */
+ }
+ else if (rmid == RM_DBASE_ID && rminfo == XLOG_DBASE_DROP)
+ {
+ /*
+ * An existing database was dropped. We'll see that the files don't
+ * exist in the target data dir, and copy them in toto from the source
+ * system. No need to do anything special here.
+ */
+ }
+ else if (rmid == RM_SMGR_ID && rminfo == XLOG_SMGR_CREATE)
+ {
+ /*
+ * We can safely ignore these. The file will be removed from the
+ * target, if it doesn't exist in source system. If a file with same
+ * name is created in source system, too, there will be WAL records
+ * for all the blocks in it.
+ */
+ }
+ else if (rmid == RM_SMGR_ID && rminfo == XLOG_SMGR_TRUNCATE)
+ {
+ /*
+ * We can safely ignore these. When we compare the sizes later on,
+ * we'll notice that they differ, and copy the missing tail from
+ * source system.
+ */
+ }
+ else if (info & XLR_SPECIAL_REL_UPDATE)
+ {
+ /*
+ * This record type modifies a relation file in some special way, but
+ * we don't recognize the type. That's bad - we don't know how to
+ * track that change.
+ */
+ pg_fatal("WAL record modifies a relation, but record type is not recognized: "
+ "lsn: %X/%X, rmgr: %s, info: %02X",
+ (uint32) (record->ReadRecPtr >> 32), (uint32) (record->ReadRecPtr),
+ RmgrNames[rmid], info);
+ }
+
+ for (block_id = 0; block_id <= record->max_block_id; block_id++)
+ {
+ RelFileNode rnode;
+ ForkNumber forknum;
+ BlockNumber blkno;
+
+ if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
+ continue;
+
+ /* We only care about the main fork; others are copied in toto */
+ if (forknum != MAIN_FORKNUM)
+ continue;
+
+ process_block_change(forknum, rnode, blkno);
+ }
+}
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
new file mode 100644
index 0000000..789f2ff
--- /dev/null
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -0,0 +1,965 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rewind.c
+ * Synchronizes a PostgreSQL data directory to a new timeline
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "access/timeline.h"
+#include "access/xlog_internal.h"
+#include "catalog/catversion.h"
+#include "catalog/pg_control.h"
+#include "common/controldata_utils.h"
+#include "common/file_perm.h"
+#include "common/file_utils.h"
+#include "common/restricted_token.h"
+#include "common/string.h"
+#include "fe_utils/recovery_gen.h"
+#include "fetch.h"
+#include "file_ops.h"
+#include "filemap.h"
+#include "getopt_long.h"
+#include "pg_rewind.h"
+#include "storage/bufpage.h"
+
+static void usage(const char *progname);
+
+static void createBackupLabel(XLogRecPtr startpoint, TimeLineID starttli,
+ XLogRecPtr checkpointloc);
+
+static void digestControlFile(ControlFileData *ControlFile, char *source,
+ size_t size);
+static void syncTargetDirectory(void);
+static void getRestoreCommand(const char *argv0);
+static void sanityChecks(void);
+static void findCommonAncestorTimeline(XLogRecPtr *recptr, int *tliIndex);
+static void ensureCleanShutdown(const char *argv0);
+static void disconnect_atexit(void);
+
+static ControlFileData ControlFile_target;
+static ControlFileData ControlFile_source;
+
+const char *progname;
+int WalSegSz;
+
+/* Configuration options */
+char *datadir_target = NULL;
+char *datadir_source = NULL;
+char *connstr_source = NULL;
+char *restore_command = NULL;
+
+static bool debug = false;
+bool showprogress = false;
+bool dry_run = false;
+bool do_sync = true;
+bool restore_wal = false;
+
+/* Target history */
+TimeLineHistoryEntry *targetHistory;
+int targetNentries;
+
+/* Progress counters */
+uint64 fetch_size;
+uint64 fetch_done;
+
+
+static void
+usage(const char *progname)
+{
+ printf(_("%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n\n"), progname);
+ printf(_("Usage:\n %s [OPTION]...\n\n"), progname);
+ printf(_("Options:\n"));
+ printf(_(" -c, --restore-target-wal use restore_command in target configuration to\n"
+ " retrieve WAL files from archives\n"));
+ printf(_(" -D, --target-pgdata=DIRECTORY existing data directory to modify\n"));
+ printf(_(" --source-pgdata=DIRECTORY source data directory to synchronize with\n"));
+ printf(_(" --source-server=CONNSTR source server to synchronize with\n"));
+ printf(_(" -n, --dry-run stop before modifying anything\n"));
+ printf(_(" -N, --no-sync do not wait for changes to be written\n"
+ " safely to disk\n"));
+ printf(_(" -P, --progress write progress messages\n"));
+ printf(_(" -R, --write-recovery-conf write configuration for replication\n"
+ " (requires --source-server)\n"));
+ printf(_(" --debug write a lot of debug messages\n"));
+ printf(_(" --no-ensure-shutdown do not automatically fix unclean shutdown\n"));
+ printf(_(" -V, --version output version information, then exit\n"));
+ printf(_(" -?, --help show this help, then exit\n"));
+ printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
+ printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ static struct option long_options[] = {
+ {"help", no_argument, NULL, '?'},
+ {"target-pgdata", required_argument, NULL, 'D'},
+ {"write-recovery-conf", no_argument, NULL, 'R'},
+ {"source-pgdata", required_argument, NULL, 1},
+ {"source-server", required_argument, NULL, 2},
+ {"no-ensure-shutdown", no_argument, NULL, 4},
+ {"version", no_argument, NULL, 'V'},
+ {"restore-target-wal", no_argument, NULL, 'c'},
+ {"dry-run", no_argument, NULL, 'n'},
+ {"no-sync", no_argument, NULL, 'N'},
+ {"progress", no_argument, NULL, 'P'},
+ {"debug", no_argument, NULL, 3},
+ {NULL, 0, NULL, 0}
+ };
+ int option_index;
+ int c;
+ XLogRecPtr divergerec;
+ int lastcommontliIndex;
+ XLogRecPtr chkptrec;
+ TimeLineID chkpttli;
+ XLogRecPtr chkptredo;
+ XLogRecPtr target_wal_endrec;
+ size_t size;
+ char *buffer;
+ bool no_ensure_shutdown = false;
+ bool rewind_needed;
+ XLogRecPtr endrec;
+ TimeLineID endtli;
+ ControlFileData ControlFile_new;
+ bool writerecoveryconf = false;
+
+ pg_logging_init(argv[0]);
+ set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_rewind"));
+ progname = get_progname(argv[0]);
+
+ /* Process command-line arguments */
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+ {
+ usage(progname);
+ exit(0);
+ }
+ if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+ {
+ puts("pg_rewind (PostgreSQL) " PG_VERSION);
+ exit(0);
+ }
+ }
+
+ while ((c = getopt_long(argc, argv, "cD:nNPR", long_options, &option_index)) != -1)
+ {
+ switch (c)
+ {
+ case '?':
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+
+ case 'c':
+ restore_wal = true;
+ break;
+
+ case 'P':
+ showprogress = true;
+ break;
+
+ case 'n':
+ dry_run = true;
+ break;
+
+ case 'N':
+ do_sync = false;
+ break;
+
+ case 'R':
+ writerecoveryconf = true;
+ break;
+
+ case 3:
+ debug = true;
+ pg_logging_set_level(PG_LOG_DEBUG);
+ break;
+
+ case 'D': /* -D or --target-pgdata */
+ datadir_target = pg_strdup(optarg);
+ break;
+
+ case 1: /* --source-pgdata */
+ datadir_source = pg_strdup(optarg);
+ break;
+
+ case 2: /* --source-server */
+ connstr_source = pg_strdup(optarg);
+ break;
+
+ case 4:
+ no_ensure_shutdown = true;
+ break;
+ }
+ }
+
+ if (datadir_source == NULL && connstr_source == NULL)
+ {
+ pg_log_error("no source specified (--source-pgdata or --source-server)");
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (datadir_source != NULL && connstr_source != NULL)
+ {
+ pg_log_error("only one of --source-pgdata or --source-server can be specified");
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (datadir_target == NULL)
+ {
+ pg_log_error("no target data directory specified (--target-pgdata)");
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (writerecoveryconf && connstr_source == NULL)
+ {
+ pg_log_error("no source server information (--source-server) specified for --write-recovery-conf");
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ if (optind < argc)
+ {
+ pg_log_error("too many command-line arguments (first is \"%s\")",
+ argv[optind]);
+ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+ exit(1);
+ }
+
+ /*
+ * Don't allow pg_rewind to be run as root, to avoid overwriting the
+ * ownership of files in the data directory. We need only check for root
+ * -- any other user won't have sufficient permissions to modify files in
+ * the data directory.
+ */
+#ifndef WIN32
+ if (geteuid() == 0)
+ {
+ pg_log_error("cannot be executed by \"root\"");
+ fprintf(stderr, _("You must run %s as the PostgreSQL superuser.\n"),
+ progname);
+ exit(1);
+ }
+#endif
+
+ get_restricted_token();
+
+ /* Set mask based on PGDATA permissions */
+ if (!GetDataDirectoryCreatePerm(datadir_target))
+ {
+ pg_log_error("could not read permissions of directory \"%s\": %m",
+ datadir_target);
+ exit(1);
+ }
+
+ umask(pg_mode_mask);
+
+ getRestoreCommand(argv[0]);
+
+ atexit(disconnect_atexit);
+
+ /* Connect to remote server */
+ if (connstr_source)
+ libpqConnect(connstr_source);
+
+ /*
+ * Ok, we have all the options and we're ready to start. Read in all the
+ * information we need from both clusters.
+ */
+ buffer = slurpFile(datadir_target, "global/pg_control", &size);
+ digestControlFile(&ControlFile_target, buffer, size);
+ pg_free(buffer);
+
+ /*
+ * If the target instance was not cleanly shut down, start and stop the
+ * target cluster once in single-user mode to enforce recovery to finish,
+ * ensuring that the cluster can be used by pg_rewind. Note that if
+ * no_ensure_shutdown is specified, pg_rewind ignores this step, and users
+ * need to make sure by themselves that the target cluster is in a clean
+ * state.
+ */
+ if (!no_ensure_shutdown &&
+ ControlFile_target.state != DB_SHUTDOWNED &&
+ ControlFile_target.state != DB_SHUTDOWNED_IN_RECOVERY)
+ {
+ ensureCleanShutdown(argv[0]);
+
+ buffer = slurpFile(datadir_target, "global/pg_control", &size);
+ digestControlFile(&ControlFile_target, buffer, size);
+ pg_free(buffer);
+ }
+
+ buffer = fetchFile("global/pg_control", &size);
+ digestControlFile(&ControlFile_source, buffer, size);
+ pg_free(buffer);
+
+ sanityChecks();
+
+ /*
+ * If both clusters are already on the same timeline, there's nothing to
+ * do.
+ */
+ if (ControlFile_target.checkPointCopy.ThisTimeLineID == ControlFile_source.checkPointCopy.ThisTimeLineID)
+ {
+ pg_log_info("source and target cluster are on the same timeline");
+ rewind_needed = false;
+ target_wal_endrec = 0;
+ }
+ else
+ {
+ XLogRecPtr chkptendrec;
+
+ findCommonAncestorTimeline(&divergerec, &lastcommontliIndex);
+ pg_log_info("servers diverged at WAL location %X/%X on timeline %u",
+ (uint32) (divergerec >> 32), (uint32) divergerec,
+ targetHistory[lastcommontliIndex].tli);
+
+ /*
+ * Determine the end-of-WAL on the target.
+ *
+ * The WAL ends at the last shutdown checkpoint, or at
+ * minRecoveryPoint if it was a standby. (If we supported rewinding a
+ * server that was not shut down cleanly, we would need to replay
+ * until we reach the first invalid record, like crash recovery does.)
+ */
+
+ /* read the checkpoint record on the target to see where it ends. */
+ chkptendrec = readOneRecord(datadir_target,
+ ControlFile_target.checkPoint,
+ targetNentries - 1,
+ restore_command);
+
+ if (ControlFile_target.minRecoveryPoint > chkptendrec)
+ {
+ target_wal_endrec = ControlFile_target.minRecoveryPoint;
+ }
+ else
+ {
+ target_wal_endrec = chkptendrec;
+ }
+
+ /*
+ * Check for the possibility that the target is in fact a direct
+ * ancestor of the source. In that case, there is no divergent history
+ * in the target that needs rewinding.
+ */
+ if (target_wal_endrec > divergerec)
+ {
+ rewind_needed = true;
+ }
+ else
+ {
+ /* the last common checkpoint record must be part of target WAL */
+ Assert(target_wal_endrec == divergerec);
+
+ rewind_needed = false;
+ }
+ }
+
+ if (!rewind_needed)
+ {
+ pg_log_info("no rewind required");
+ if (writerecoveryconf && !dry_run)
+ WriteRecoveryConfig(conn, datadir_target,
+ GenerateRecoveryConfig(conn, NULL));
+ exit(0);
+ }
+
+ findLastCheckpoint(datadir_target, divergerec, lastcommontliIndex,
+ &chkptrec, &chkpttli, &chkptredo, restore_command);
+ pg_log_info("rewinding from last common checkpoint at %X/%X on timeline %u",
+ (uint32) (chkptrec >> 32), (uint32) chkptrec,
+ chkpttli);
+
+ /*
+ * Build the filemap, by comparing the source and target data directories.
+ */
+ filemap_create();
+ if (showprogress)
+ pg_log_info("reading source file list");
+ fetchSourceFileList();
+ if (showprogress)
+ pg_log_info("reading target file list");
+ traverse_datadir(datadir_target, &process_target_file);
+
+ /*
+ * Read the target WAL from last checkpoint before the point of fork, to
+ * extract all the pages that were modified on the target cluster after
+ * the fork.
+ */
+ if (showprogress)
+ pg_log_info("reading WAL in target");
+ extractPageMap(datadir_target, chkptrec, lastcommontliIndex,
+ target_wal_endrec, restore_command);
+ filemap_finalize();
+
+ if (showprogress)
+ calculate_totals();
+
+ /* this is too verbose even for verbose mode */
+ if (debug)
+ print_filemap();
+
+ /*
+ * Ok, we're ready to start copying things over.
+ */
+ if (showprogress)
+ {
+ pg_log_info("need to copy %lu MB (total source directory size is %lu MB)",
+ (unsigned long) (filemap->fetch_size / (1024 * 1024)),
+ (unsigned long) (filemap->total_size / (1024 * 1024)));
+
+ fetch_size = filemap->fetch_size;
+ fetch_done = 0;
+ }
+
+ /*
+ * This is the point of no return. Once we start copying things, we have
+ * modified the target directory and there is no turning back!
+ */
+
+ executeFileMap();
+
+ progress_report(true);
+
+ if (showprogress)
+ pg_log_info("creating backup label and updating control file");
+ createBackupLabel(chkptredo, chkpttli, chkptrec);
+
+ /*
+ * Update control file of target. Make it ready to perform archive
+ * recovery when restarting.
+ *
+ * minRecoveryPoint is set to the current WAL insert location in the
+ * source server. Like in an online backup, it's important that we recover
+ * all the WAL that was generated while we copied the files over.
+ */
+ memcpy(&ControlFile_new, &ControlFile_source, sizeof(ControlFileData));
+
+ if (connstr_source)
+ {
+ endrec = libpqGetCurrentXlogInsertLocation();
+ endtli = ControlFile_source.checkPointCopy.ThisTimeLineID;
+ }
+ else
+ {
+ endrec = ControlFile_source.checkPoint;
+ endtli = ControlFile_source.checkPointCopy.ThisTimeLineID;
+ }
+ ControlFile_new.minRecoveryPoint = endrec;
+ ControlFile_new.minRecoveryPointTLI = endtli;
+ ControlFile_new.state = DB_IN_ARCHIVE_RECOVERY;
+ if (!dry_run)
+ update_controlfile(datadir_target, &ControlFile_new, do_sync);
+
+ if (showprogress)
+ pg_log_info("syncing target data directory");
+ syncTargetDirectory();
+
+ if (writerecoveryconf && !dry_run)
+ WriteRecoveryConfig(conn, datadir_target,
+ GenerateRecoveryConfig(conn, NULL));
+
+ pg_log_info("Done!");
+
+ return 0;
+}
+
+static void
+sanityChecks(void)
+{
+ /* TODO Check that there's no backup_label in either cluster */
+
+ /* Check system_identifier match */
+ if (ControlFile_target.system_identifier != ControlFile_source.system_identifier)
+ pg_fatal("source and target clusters are from different systems");
+
+ /* check version */
+ if (ControlFile_target.pg_control_version != PG_CONTROL_VERSION ||
+ ControlFile_source.pg_control_version != PG_CONTROL_VERSION ||
+ ControlFile_target.catalog_version_no != CATALOG_VERSION_NO ||
+ ControlFile_source.catalog_version_no != CATALOG_VERSION_NO)
+ {
+ pg_fatal("clusters are not compatible with this version of pg_rewind");
+ }
+
+ /*
+ * Target cluster need to use checksums or hint bit wal-logging, this to
+ * prevent from data corruption that could occur because of hint bits.
+ */
+ if (ControlFile_target.data_checksum_version != PG_DATA_CHECKSUM_VERSION &&
+ !ControlFile_target.wal_log_hints)
+ {
+ pg_fatal("target server needs to use either data checksums or \"wal_log_hints = on\"");
+ }
+
+ /*
+ * Target cluster better not be running. This doesn't guard against
+ * someone starting the cluster concurrently. Also, this is probably more
+ * strict than necessary; it's OK if the target node was not shut down
+ * cleanly, as long as it isn't running at the moment.
+ */
+ if (ControlFile_target.state != DB_SHUTDOWNED &&
+ ControlFile_target.state != DB_SHUTDOWNED_IN_RECOVERY)
+ pg_fatal("target server must be shut down cleanly");
+
+ /*
+ * When the source is a data directory, also require that the source
+ * server is shut down. There isn't any very strong reason for this
+ * limitation, but better safe than sorry.
+ */
+ if (datadir_source &&
+ ControlFile_source.state != DB_SHUTDOWNED &&
+ ControlFile_source.state != DB_SHUTDOWNED_IN_RECOVERY)
+ pg_fatal("source data directory must be shut down cleanly");
+}
+
+/*
+ * Print a progress report based on the fetch_size and fetch_done variables.
+ *
+ * Progress report is written at maximum once per second, except that the
+ * last progress report is always printed.
+ *
+ * If finished is set to true, this is the last progress report. The cursor
+ * is moved to the next line.
+ */
+void
+progress_report(bool finished)
+{
+ static pg_time_t last_progress_report = 0;
+ int percent;
+ char fetch_done_str[32];
+ char fetch_size_str[32];
+ pg_time_t now;
+
+ if (!showprogress)
+ return;
+
+ now = time(NULL);
+ if (now == last_progress_report && !finished)
+ return; /* Max once per second */
+
+ last_progress_report = now;
+ percent = fetch_size ? (int) ((fetch_done) * 100 / fetch_size) : 0;
+
+ /*
+ * Avoid overflowing past 100% or the full size. This may make the total
+ * size number change as we approach the end of the backup (the estimate
+ * will always be wrong if WAL is included), but that's better than having
+ * the done column be bigger than the total.
+ */
+ if (percent > 100)
+ percent = 100;
+ if (fetch_done > fetch_size)
+ fetch_size = fetch_done;
+
+ /*
+ * Separate step to keep platform-dependent format code out of
+ * translatable strings. And we only test for INT64_FORMAT availability
+ * in snprintf, not fprintf.
+ */
+ snprintf(fetch_done_str, sizeof(fetch_done_str), INT64_FORMAT,
+ fetch_done / 1024);
+ snprintf(fetch_size_str, sizeof(fetch_size_str), INT64_FORMAT,
+ fetch_size / 1024);
+
+ fprintf(stderr, _("%*s/%s kB (%d%%) copied"),
+ (int) strlen(fetch_size_str), fetch_done_str, fetch_size_str,
+ percent);
+
+ /*
+ * Stay on the same line if reporting to a terminal and we're not done
+ * yet.
+ */
+ fputc((!finished && isatty(fileno(stderr))) ? '\r' : '\n', stderr);
+}
+
+/*
+ * Find minimum from two WAL locations assuming InvalidXLogRecPtr means
+ * infinity as src/include/access/timeline.h states. This routine should
+ * be used only when comparing WAL locations related to history files.
+ */
+static XLogRecPtr
+MinXLogRecPtr(XLogRecPtr a, XLogRecPtr b)
+{
+ if (XLogRecPtrIsInvalid(a))
+ return b;
+ else if (XLogRecPtrIsInvalid(b))
+ return a;
+ else
+ return Min(a, b);
+}
+
+/*
+ * Retrieve timeline history for given control file which should behold
+ * either source or target.
+ */
+static TimeLineHistoryEntry *
+getTimelineHistory(ControlFileData *controlFile, int *nentries)
+{
+ TimeLineHistoryEntry *history;
+ TimeLineID tli;
+
+ tli = controlFile->checkPointCopy.ThisTimeLineID;
+
+ /*
+ * Timeline 1 does not have a history file, so there is no need to check
+ * and fake an entry with infinite start and end positions.
+ */
+ if (tli == 1)
+ {
+ history = (TimeLineHistoryEntry *) pg_malloc(sizeof(TimeLineHistoryEntry));
+ history->tli = tli;
+ history->begin = history->end = InvalidXLogRecPtr;
+ *nentries = 1;
+ }
+ else
+ {
+ char path[MAXPGPATH];
+ char *histfile;
+
+ TLHistoryFilePath(path, tli);
+
+ /* Get history file from appropriate source */
+ if (controlFile == &ControlFile_source)
+ histfile = fetchFile(path, NULL);
+ else if (controlFile == &ControlFile_target)
+ histfile = slurpFile(datadir_target, path, NULL);
+ else
+ pg_fatal("invalid control file");
+
+ history = rewind_parseTimeLineHistory(histfile, tli, nentries);
+ pg_free(histfile);
+ }
+
+ if (debug)
+ {
+ int i;
+
+ if (controlFile == &ControlFile_source)
+ pg_log_debug("Source timeline history:");
+ else if (controlFile == &ControlFile_target)
+ pg_log_debug("Target timeline history:");
+ else
+ Assert(false);
+
+ /*
+ * Print the target timeline history.
+ */
+ for (i = 0; i < targetNentries; i++)
+ {
+ TimeLineHistoryEntry *entry;
+
+ entry = &history[i];
+ pg_log_debug("%d: %X/%X - %X/%X", entry->tli,
+ (uint32) (entry->begin >> 32), (uint32) (entry->begin),
+ (uint32) (entry->end >> 32), (uint32) (entry->end));
+ }
+ }
+
+ return history;
+}
+
+/*
+ * Determine the TLI of the last common timeline in the timeline history of the
+ * two clusters. targetHistory is filled with target timeline history and
+ * targetNentries is number of items in targetHistory. *tliIndex is set to the
+ * index of last common timeline in targetHistory array, and *recptr is set to
+ * the position where the timeline history diverged (ie. the first WAL record
+ * that's not the same in both clusters).
+ *
+ * Control files of both clusters must be read into ControlFile_target/source
+ * before calling this routine.
+ */
+static void
+findCommonAncestorTimeline(XLogRecPtr *recptr, int *tliIndex)
+{
+ TimeLineHistoryEntry *sourceHistory;
+ int sourceNentries;
+ int i,
+ n;
+
+ /* Retrieve timelines for both source and target */
+ sourceHistory = getTimelineHistory(&ControlFile_source, &sourceNentries);
+ targetHistory = getTimelineHistory(&ControlFile_target, &targetNentries);
+
+ /*
+ * Trace the history forward, until we hit the timeline diverge. It may
+ * still be possible that the source and target nodes used the same
+ * timeline number in their history but with different start position
+ * depending on the history files that each node has fetched in previous
+ * recovery processes. Hence check the start position of the new timeline
+ * as well and move down by one extra timeline entry if they do not match.
+ */
+ n = Min(sourceNentries, targetNentries);
+ for (i = 0; i < n; i++)
+ {
+ if (sourceHistory[i].tli != targetHistory[i].tli ||
+ sourceHistory[i].begin != targetHistory[i].begin)
+ break;
+ }
+
+ if (i > 0)
+ {
+ i--;
+ *recptr = MinXLogRecPtr(sourceHistory[i].end, targetHistory[i].end);
+ *tliIndex = i;
+
+ pg_free(sourceHistory);
+ return;
+ }
+ else
+ {
+ pg_fatal("could not find common ancestor of the source and target cluster's timelines");
+ }
+}
+
+
+/*
+ * Create a backup_label file that forces recovery to begin at the last common
+ * checkpoint.
+ */
+static void
+createBackupLabel(XLogRecPtr startpoint, TimeLineID starttli, XLogRecPtr checkpointloc)
+{
+ XLogSegNo startsegno;
+ time_t stamp_time;
+ char strfbuf[128];
+ char xlogfilename[MAXFNAMELEN];
+ struct tm *tmp;
+ char buf[1000];
+ int len;
+
+ XLByteToSeg(startpoint, startsegno, WalSegSz);
+ XLogFileName(xlogfilename, starttli, startsegno, WalSegSz);
+
+ /*
+ * Construct backup label file
+ */
+ stamp_time = time(NULL);
+ tmp = localtime(&stamp_time);
+ strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", tmp);
+
+ len = snprintf(buf, sizeof(buf),
+ "START WAL LOCATION: %X/%X (file %s)\n"
+ "CHECKPOINT LOCATION: %X/%X\n"
+ "BACKUP METHOD: pg_rewind\n"
+ "BACKUP FROM: standby\n"
+ "START TIME: %s\n",
+ /* omit LABEL: line */
+ (uint32) (startpoint >> 32), (uint32) startpoint, xlogfilename,
+ (uint32) (checkpointloc >> 32), (uint32) checkpointloc,
+ strfbuf);
+ if (len >= sizeof(buf))
+ pg_fatal("backup label buffer too small"); /* shouldn't happen */
+
+ /* TODO: move old file out of the way, if any. */
+ open_target_file("backup_label", true); /* BACKUP_LABEL_FILE */
+ write_target_range(buf, 0, len);
+ close_target_file();
+}
+
+/*
+ * Check CRC of control file
+ */
+static void
+checkControlFile(ControlFileData *ControlFile)
+{
+ pg_crc32c crc;
+
+ /* Calculate CRC */
+ INIT_CRC32C(crc);
+ COMP_CRC32C(crc, (char *) ControlFile, offsetof(ControlFileData, crc));
+ FIN_CRC32C(crc);
+
+ /* And simply compare it */
+ if (!EQ_CRC32C(crc, ControlFile->crc))
+ pg_fatal("unexpected control file CRC");
+}
+
+/*
+ * Verify control file contents in the buffer src, and copy it to *ControlFile.
+ */
+static void
+digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
+{
+ if (size != PG_CONTROL_FILE_SIZE)
+ pg_fatal("unexpected control file size %d, expected %d",
+ (int) size, PG_CONTROL_FILE_SIZE);
+
+ memcpy(ControlFile, src, sizeof(ControlFileData));
+
+ /* set and validate WalSegSz */
+ WalSegSz = ControlFile->xlog_seg_size;
+
+ if (!IsValidWalSegSize(WalSegSz))
+ pg_fatal(ngettext("WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte",
+ "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes",
+ WalSegSz),
+ WalSegSz);
+
+ /* Additional checks on control file */
+ checkControlFile(ControlFile);
+}
+
+/*
+ * Sync target data directory to ensure that modifications are safely on disk.
+ *
+ * We do this once, for the whole data directory, for performance reasons. At
+ * the end of pg_rewind's run, the kernel is likely to already have flushed
+ * most dirty buffers to disk. Additionally fsync_pgdata uses a two-pass
+ * approach (only initiating writeback in the first pass), which often reduces
+ * the overall amount of IO noticeably.
+ */
+static void
+syncTargetDirectory(void)
+{
+ if (!do_sync || dry_run)
+ return;
+
+ fsync_pgdata(datadir_target, PG_VERSION_NUM);
+}
+
+/*
+ * Get value of GUC parameter restore_command from the target cluster.
+ *
+ * This uses a logic based on "postgres -C" to get the value from the
+ * cluster.
+ */
+static void
+getRestoreCommand(const char *argv0)
+{
+ int rc;
+ char postgres_exec_path[MAXPGPATH],
+ postgres_cmd[MAXPGPATH],
+ cmd_output[MAXPGPATH];
+
+ if (!restore_wal)
+ return;
+
+ /* find postgres executable */
+ rc = find_other_exec(argv0, "postgres",
+ PG_BACKEND_VERSIONSTR,
+ postgres_exec_path);
+
+ if (rc < 0)
+ {
+ char full_path[MAXPGPATH];
+
+ if (find_my_exec(argv0, full_path) < 0)
+ strlcpy(full_path, progname, sizeof(full_path));
+
+ if (rc == -1)
+ pg_log_error("The program \"%s\" is needed by %s but was not found in the\n"
+ "same directory as \"%s\".\n"
+ "Check your installation.",
+ "postgres", progname, full_path);
+ else
+ pg_log_error("The program \"%s\" was found by \"%s\"\n"
+ "but was not the same version as %s.\n"
+ "Check your installation.",
+ "postgres", full_path, progname);
+ exit(1);
+ }
+
+ /*
+ * Build a command able to retrieve the value of GUC parameter
+ * restore_command, if set.
+ */
+ snprintf(postgres_cmd, sizeof(postgres_cmd),
+ "\"%s\" -D \"%s\" -C restore_command",
+ postgres_exec_path, datadir_target);
+
+ if (!pipe_read_line(postgres_cmd, cmd_output, sizeof(cmd_output)))
+ exit(1);
+
+ (void) pg_strip_crlf(cmd_output);
+
+ if (strcmp(cmd_output, "") == 0)
+ pg_fatal("restore_command is not set in the target cluster");
+
+ restore_command = pg_strdup(cmd_output);
+
+ pg_log_debug("using for rewind restore_command = \'%s\'",
+ restore_command);
+}
+
+
+/*
+ * Ensure clean shutdown of target instance by launching single-user mode
+ * postgres to do crash recovery.
+ */
+static void
+ensureCleanShutdown(const char *argv0)
+{
+ int ret;
+#define MAXCMDLEN (2 * MAXPGPATH)
+ char exec_path[MAXPGPATH];
+ char cmd[MAXCMDLEN];
+
+ /* locate postgres binary */
+ if ((ret = find_other_exec(argv0, "postgres",
+ PG_BACKEND_VERSIONSTR,
+ exec_path)) < 0)
+ {
+ char full_path[MAXPGPATH];
+
+ if (find_my_exec(argv0, full_path) < 0)
+ strlcpy(full_path, progname, sizeof(full_path));
+
+ if (ret == -1)
+ pg_fatal("The program \"%s\" is needed by %s but was not found in the\n"
+ "same directory as \"%s\".\n"
+ "Check your installation.",
+ "postgres", progname, full_path);
+ else
+ pg_fatal("The program \"%s\" was found by \"%s\"\n"
+ "but was not the same version as %s.\n"
+ "Check your installation.",
+ "postgres", full_path, progname);
+ }
+
+ pg_log_info("executing \"%s\" for target server to complete crash recovery",
+ exec_path);
+
+ /*
+ * Skip processing if requested, but only after ensuring presence of
+ * postgres.
+ */
+ if (dry_run)
+ return;
+
+ /*
+ * Finally run postgres in single-user mode. There is no need to use
+ * fsync here. This makes the recovery faster, and the target data folder
+ * is synced at the end anyway.
+ */
+ snprintf(cmd, MAXCMDLEN, "\"%s\" --single -F -D \"%s\" template1 < \"%s\"",
+ exec_path, datadir_target, DEVNULL);
+
+ if (system(cmd) != 0)
+ {
+ pg_log_error("postgres single-user mode in target cluster failed");
+ pg_fatal("Command was: %s", cmd);
+ }
+}
+
+static void
+disconnect_atexit(void)
+{
+ if (conn != NULL)
+ PQfinish(conn);
+}
diff --git a/src/bin/pg_rewind/pg_rewind.h b/src/bin/pg_rewind/pg_rewind.h
new file mode 100644
index 0000000..8a9319e
--- /dev/null
+++ b/src/bin/pg_rewind/pg_rewind.h
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_rewind.h
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_REWIND_H
+#define PG_REWIND_H
+
+#include "access/timeline.h"
+#include "common/logging.h"
+#include "datapagemap.h"
+#include "libpq-fe.h"
+#include "storage/block.h"
+#include "storage/relfilenode.h"
+
+/* Configuration options */
+extern char *datadir_target;
+extern char *datadir_source;
+extern char *connstr_source;
+extern bool showprogress;
+extern bool dry_run;
+extern int WalSegSz;
+
+/* Target history */
+extern TimeLineHistoryEntry *targetHistory;
+extern int targetNentries;
+
+/* general state */
+extern PGconn *conn;
+
+/* Progress counters */
+extern uint64 fetch_size;
+extern uint64 fetch_done;
+
+/* logging support */
+#define pg_fatal(...) do { pg_log_fatal(__VA_ARGS__); exit(1); } while(0)
+
+/* in parsexlog.c */
+extern void extractPageMap(const char *datadir, XLogRecPtr startpoint,
+ int tliIndex, XLogRecPtr endpoint,
+ const char *restoreCommand);
+extern void findLastCheckpoint(const char *datadir, XLogRecPtr searchptr,
+ int tliIndex,
+ XLogRecPtr *lastchkptrec, TimeLineID *lastchkpttli,
+ XLogRecPtr *lastchkptredo,
+ const char *restoreCommand);
+extern XLogRecPtr readOneRecord(const char *datadir, XLogRecPtr ptr,
+ int tliIndex, const char *restoreCommand);
+
+/* in pg_rewind.c */
+extern void progress_report(bool finished);
+
+/* in timeline.c */
+extern TimeLineHistoryEntry *rewind_parseTimeLineHistory(char *buffer,
+ TimeLineID targetTLI,
+ int *nentries);
+
+#endif /* PG_REWIND_H */
diff --git a/src/bin/pg_rewind/po/cs.po b/src/bin/pg_rewind/po/cs.po
new file mode 100644
index 0000000..1f4a8eb
--- /dev/null
+++ b/src/bin/pg_rewind/po/cs.po
@@ -0,0 +1,1019 @@
+# LANGUAGE message translation file for pg_rewind
+# Copyright (C) 2018 PostgreSQL Global Development Group
+# This file is distributed under the same license as the pg_rewind (PostgreSQL) package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 11\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-10-31 16:16+0000\n"
+"PO-Revision-Date: 2020-10-31 21:24+0100\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+"X-Generator: Poedit 2.4.1\n"
+"X-Poedit-Bookmarks: -1,-1,-1,-1,-1,-1,-1,-1,-1,17\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "fatal: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "error: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "warning: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "nedostatek paměti\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "nelze duplikovat null pointer (interní chyba)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "nelze načíst knihovnu \"%s\": kód chyby %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "na této platformě nelze vytvářet vyhrazené tokeny: kód chyby %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "nelze otevřít token procesu: chybový kód %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "nelze alokovat SIDs: chybový kód %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "nelze vytvořit vyhrazený token: chybový kód %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "nelze nastartovat proces pro příkaz \"%s\": chybový kód %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "nelze znovu spustit s vyhrazeným tokenem: chybový kód %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "nelze získat návratový kód z podprovesu: chybový kód %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "nelze použít restore_command se zástupnou hodnotou %%r"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "neočekávaná velikost souboru \"%s\": %lu namísto %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "nelze otevřít soubor \"%s\" obnovený z archivu: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "nelze přistoupit k souboru \"%s\": %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "restore_command selhal: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "nelze obnovit soubor\"%s\" z archivu"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:73 parsexlog.c:125
+#: parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "nedostatek paměti"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:298
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "nelze otevřít soubor \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "nelze zapsat do souboru \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "nelze vytvořit soubor \"%s\": %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "nelze otevřít adresář \"%s\": %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "nelze přečíst symbolický odkaz \"%s\": %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "cíl symbolického odkazu \"%s\" je příliš dlouhý"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\" je symbolický odkaz, ale symbolické odkazy nejsou na této platformě podporovány"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "nelze číst z adresáře \"%s\": %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "nelze uzavřít adresář \"%s\": %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "nelze otevřít zdrojový soubor \"%s\": %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "nelze změnit pozici (seek) ve zdrojovém souboru: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:336
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "nelze číst soubor \"%s\": %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "neočekávaný znak EOF při čtení souboru \"%s\""
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "nelze uzavřít soubor \"%s\": %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "nelze otevřít cílový soubor \"%s\": %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "nelze uzavřít cílový soubor \"%s\": %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "nelze změnit pozici (seek) v cílovém souboru \"%s\": %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "nelze zapsat soubor \"%s\": %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "neplatná akce (CREATE) pro obyčejný soubor"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "nelze odstranit soubor \"%s\": %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "nelze otevřít soubor \"%s\" pro zkrácení (truncate): %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "nelze zkrátit (truncate) soubor \"%s\" na %u: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "nelze vytvořit adresář \"%s\": %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "nelze odstranit adresář \"%s\": %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "nelze vytvořit symbolický odkaz na \"%s\": %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "nelze odstranit symbolický odkaz \"%s\": %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "nelze otevřít soubor \"%s\" pro čtení: %m"
+
+#: file_ops.c:314 parsexlog.c:338
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "nelze číst soubor \"%s\": načteno %d z %zu"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "datový soubor \"%s\" ve zdroji není obyčejný soubor"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" není adresář"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" není symbolický odkaz"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" není obyčejný soubor"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "seznam zdrojových souborů je prázdný"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "neočekávaná modifikace stránky pro adresář nebo symbolický odkaz \"%s\""
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "nelze se připojit k serveru: %s"
+
+#: libpq_fetch.c:54
+#, c-format
+msgid "connected to server"
+msgstr "připojen k serveru"
+
+#: libpq_fetch.c:63
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "nelze vyčistit search_path: %s"
+
+#: libpq_fetch.c:75
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "zdrojový server musí být v recovery módu"
+
+#: libpq_fetch.c:85
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "full_page_writes musí být zapnuty na zdrojovém serveru"
+
+#: libpq_fetch.c:111
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "chyba při spuštění dotazu (%s) na zdrojovém serveru: %s"
+
+#: libpq_fetch.c:116
+#, c-format
+msgid "unexpected result set from query"
+msgstr "neočekávaný výsledek dotazu"
+
+#: libpq_fetch.c:137
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "chyba při spuštění dotazu (%s) na zdrojovém serveru: %s"
+
+#: libpq_fetch.c:157
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "nerozpoznaný výsledek \"%s\" pro aktuální WAL insert pozici"
+
+#: libpq_fetch.c:207
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "nelze načíst seznam souborů: %s"
+
+#: libpq_fetch.c:212
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "neočekávaný výsledek při načítání seznamu souborů"
+
+#: libpq_fetch.c:265
+#, c-format
+msgid "could not send query: %s"
+msgstr "nelze zaslat dotaz: %s"
+
+#: libpq_fetch.c:270
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "nelze nastavit libpq spojení na single row mód"
+
+#: libpq_fetch.c:290
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "neočekávaný výsledek při načítání vzdálených souborů: %s"
+
+#: libpq_fetch.c:296
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "neočekávaná velikost výsledku při načítání vzdálených souborů"
+
+#: libpq_fetch.c:302
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "neočekávané datové typy ve vysledku při načítání vzdálených souborů: %u %u %u"
+
+#: libpq_fetch.c:310
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "neočekávaný formát výsledku při načítání vzdálených souborů"
+
+#: libpq_fetch.c:316
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "neočekávané null hodnoty ve výsledku při načítání vzdálených souborů"
+
+#: libpq_fetch.c:320
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "neočekávaná délka výsledku při načítání vzdálených souborů"
+
+#: libpq_fetch.c:381
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "nelze načíst vzdálený soubor \"%s\": %s"
+
+#: libpq_fetch.c:386
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "neočekávaný výsledek při načítání vzdáleného souboru \"%s\""
+
+#: libpq_fetch.c:430
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "nelze poslat COPY data: %s"
+
+#: libpq_fetch.c:459
+#, c-format
+msgid "could not send file list: %s"
+msgstr "nelze poslat seznam souborů: %s"
+
+#: libpq_fetch.c:501
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "nelze poslat end-of-COPY: %s"
+
+#: libpq_fetch.c:507
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "neočekávaný výsledek při posílání seznamu souborů: %s"
+
+#: parsexlog.c:85 parsexlog.c:132
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "nelze načíst WAL záznam na %X/%X: %s"
+
+#: parsexlog.c:89 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "nelze načíst WAL záznam na %X/%X"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "nelze nalézt předchozí WAL záznam na %X/%X: %s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "nelze načíst předchozí WAL záznam na %X/%X"
+
+#: parsexlog.c:327
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "nelze nastavit pozici (seek) v souboru \"%s\": %m"
+
+#: parsexlog.c:407
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL záznam modifikuje relaci, ale typ záznamu není rozpoznán: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s resynchronizuje PostgreSQL cluster s jinou kopií daného clusteru.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Použití:\n"
+" %s [OPTION]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Přepínače:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal použij restore_command v cílové konfiguraci pro\n"
+" získání WAL souborů z archivu\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=ADRESÁŘ existující datový adresář pro modifikaci\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=ADRESÁŘ zdrojový datový adresář proti kterému se synchronizovat\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR zdrojový server se kterým se synchronizovat\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run zastavit před modifikací čehokoliv\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync nečekat na bezpečné zapsání změn na disk\n"
+"\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress průběžně vypisovat zprávy o postupu\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf zapíše konfiguraci pro replikaci\n"
+" (vyžaduje zadání --source-server)\n"
+"\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug vypisovat mnoho zpráv s debug informacemi\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown neopravuj automaticky nečisté vypnutí databáze\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version vypíše informaci o verzi, poté skončí\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help vypíše tuto nápovědu, poté skončí\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Chyby oznamujte na <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "%s domácí stránka: <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Zkuste \"%s --help\" pro více informací.\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "nespecifikován žádný zdroj (--source-pgdata nebo --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "pouze jedna z voleb --source-pgdata nebo --source-server může být zadána"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "cílový datový adresář nespecifikován (--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr ""
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "příliš mnoho argumentů v příkazové řádce (první je \"%s\")"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "nelze spouštět jako \"root\""
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Musíte spustit %s jako PostgreSQL superuživatel.\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "nelze zjistit přístupová práva adresáře \"%s\": %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "zdrojový a cílový cluster jsou na stejné timeline"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "servery se rozešly na WAL pozici %X/%X na timeline %u"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "rewind není potřeba"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "provádím rewind z posledního společného checkpointu na %X/%X na timeline %u"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "načítám seznam zdrojových souborů"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "načítám seznam cílových souborů"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "čtu WAL na cílovém clusteru"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "je třeba zkopírovat %lu MB (celková velikost zdrojového adresáře je %lu MB)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "vytvářím backup label a aktualizuji control file"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "provádím sync cílového datového adresáře"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "Hotovo!"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "zdrojový a cílový cluster jsou z různých systémů"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "clustery nejsou kompatibilní s touto verzí pg_rewind"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "cílový server musí používat buď data checksums nebo \"wal_log_hints = on\""
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "cílový server musí být zastaven čistě"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "zdrojový datový adresář musí být zastaven čistě"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) zkopírováno"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "neplatný control file"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "nelze najít společného předka pro timeline ze zdrojového a cílového clusteru"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "backup label buffer je příliš malý"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "neočekávaná CRC hodnota control file"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "neočekávaná velikost control file %d, očekáváno %d"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "Velikost WAL segmentu musí být mocnina dvou mezi 1 MB a 1 GB, ale control file udává %d byte"
+msgstr[1] "Velikost WAL segmentu musí být mocnina dvou mezi 1 MB a 1 GB, ale control file udává %d bytů"
+msgstr[2] "Velikost WAL segmentu musí být mocnina dvou mezi 1 MB a 1 GB, ale control file udává %d bytů"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"Program \"%s\" je vyžadován aplikací %s, ale nebyl nalezen ve stejném\n"
+"adresáři jako \"%s\".\n"
+"Zkontrolujte vaši instalaci."
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"Program \"%s\" byl nalezen pomocí \"%s\",\n"
+"ale nebyl ve stejné verzi jako %s.\n"
+"Zkontrolujte vaši instalaci."
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "restore_command není nastaven pro cílový cluster"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "spouštím \"%s\" na cílovém serveru pro dokončení crash recovery"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "postgres single-user mód v cílovém clusteru selhal"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "Příkaz byl: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "syntaktická chyba v souboru s historií: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Očekávána číselná hodnota timeline ID."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Očekávána pozice pro switchpoint write-ahead logu."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "chybná data v souboru s historií: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Timeline IDs musí být rostoucí posloupnost."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "chybná data v souboru s historií"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "Timeline IDs musí být nižší než timeline ID potomka."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "neplatný offset záznamu na %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "contrecord je vyžadován %X/%X"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "neplatná délka záznamu na %X/%X: potřeba %u, získáno %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "délka záznamu %u na %X/%X je příliš vysoká"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "na %X/%X není nastaven contrecord flag"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "chybná contrecord délka %u na %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "chybný ID resource managera %u na %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "záznam s neplatnou hodnotou prev-link %X/%X na %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "neplatný data checksum resource managera v záznamu na %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "neplatné magické číslo %04X v log segmentu %s, offset %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "neplatné info bity %04X v log segmentu %s, offset %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "WAL soubor je z jiného databázového systému: systémový identifikátor z WAL souboru je %llu, systémový identifikátor z pg_control je %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL soubor je z jiného databázového systému: neplatná velikost segmentu v hlavičce stránky"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL soubor je z jiného databázového systému: neplatná hodnota XLOG_BLCKSZ v hlavičce stránky"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "neočekávaná pageaddr hodnota %X/%X v log segmentu %s, offset %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "timeline ID %u mimo pořadí (po %u) v log segmentu %s, offset %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "block_id %u mimo pořadí na %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA flag nastaven, ale žádná data nejsou přiložena na %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA flag nenastaven, ale délka dat je %u na %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE flag nastaven, ale hole offset %u length %u block image length %u na %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE flag nenastaven, ale hole offset %u length %u na %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED flag nastaven, ale block image length %u na %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE ani BKPIMAGE_IS_COMPRESSED flag nenastaven, ale block image length je %u na %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL flag nastaven, ale žádná předchozí rel hodnota na %X/%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "neplatné block_id %u na %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "záznam s neplatnou délkou na %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "neplatný komprimovaný image na %X/%X, block %d"
+
+#~ msgid "could not open directory \"%s\": %s\n"
+#~ msgstr "nelze otevřít adresář \"%s\": %s\n"
+
+#~ msgid "could not read file \"%s\": %s\n"
+#~ msgstr "nelze číst soubor \"%s\": %s\n"
+
+#~ msgid " block %u\n"
+#~ msgstr " blok %u\n"
+
+#~ msgid "entry \"%s\" excluded from %s file list\n"
+#~ msgstr "položka \"%s\" vyloučena ze %s seznamu souborů\n"
+
+#~ msgid "%s (%s)\n"
+#~ msgstr "%s (%s)\n"
+
+#~ msgid "could not set up connection context: %s"
+#~ msgstr "nelze nastavit kontext spojení: %s"
+
+#~ msgid "getting file chunks\n"
+#~ msgstr "načítám části souborů\n"
+
+#~ msgid "received null value for chunk for file \"%s\", file has been deleted\n"
+#~ msgstr "přijata null hodnota pro chunk souboru \"%s\", soubor byl smazán\n"
+
+#~ msgid "received chunk for file \"%s\", offset %s, size %d\n"
+#~ msgstr "přijat chunk souboru \"%s\", offset %s, délka %d\n"
+
+#~ msgid "fetched file \"%s\", length %d\n"
+#~ msgstr "načten soubor \"%s\", délka %d\n"
+
+#~ msgid "could not create temporary table: %s"
+#~ msgstr "nelze vytvořit temporary tabulku: %s"
+
+#~ msgid "Failure, exiting\n"
+#~ msgstr "Chyba, končím\n"
+
+#~ msgid "could not open file \"%s\": %s\n"
+#~ msgstr "nelze otevřít soubor \"%s\": %s\n"
+
+#~ msgid "could not read from file \"%s\": %s\n"
+#~ msgstr "nelze číst ze souboru \"%s\": %s\n"
+
+#~ msgid "%s: could not read permissions of directory \"%s\": %s\n"
+#~ msgstr "%s: nelze načíst práva adresáře \"%s\": %s\n"
+
+#~ msgid "Source timeline history:\n"
+#~ msgstr "Zdrojová timeline history:\n"
+
+#~ msgid "Target timeline history:\n"
+#~ msgstr "Cílová timeline history:\n"
+
+#~ msgid "%d: %X/%X - %X/%X\n"
+#~ msgstr "%d: %X/%X - %X/%X\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "Program \"initdb\" je vyžadován %s ale nebyl\n"
+#~ "nalezen ve stejném adresáři jako \"%s\".\n"
+#~ "Zkontrolujte svou instalaci.\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "Program \"initdb\" byl nalezen \"%s\"\n"
+#~ "ale nemá stejnou verzi jako \"%s\".\n"
+#~ "Zkontrolujte svou instalaci.\n"
+
+#~ msgid "sync of target directory failed\n"
+#~ msgstr "sync na cílovém adresáři selhal\n"
+
+#~ msgid ""
+#~ "\n"
+#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Chyby hlaste na adresu <pgsql-bugs@postgresql.org>.\n"
diff --git a/src/bin/pg_rewind/po/de.po b/src/bin/pg_rewind/po/de.po
new file mode 100644
index 0000000..aebbf29
--- /dev/null
+++ b/src/bin/pg_rewind/po/de.po
@@ -0,0 +1,935 @@
+# German message translation file for pg_rewind
+# Copyright (C) 2015-2020 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# Peter Eisentraut <peter@eisentraut.org>, 2015-2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 13\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-11-08 07:16+0000\n"
+"PO-Revision-Date: 2020-11-08 09:04+0100\n"
+"Last-Translator: Peter Eisentraut <peter@eisentraut.org>\n"
+"Language-Team: German <pgsql-translators@postgresql.org>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "Fatal: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "Fehler: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "Warnung: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "Speicher aufgebraucht\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "kann NULL-Zeiger nicht kopieren (interner Fehler)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "konnte Bibliothek »%s« nicht laden: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "auf dieser Plattform können keine beschränkten Token erzeugt werden: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "konnte Prozess-Token nicht öffnen: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "konnte SIDs nicht erzeugen: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "konnte beschränktes Token nicht erzeugen: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "konnte Prozess für Befehl »%s« nicht starten: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "konnte Prozess nicht mit beschränktem Token neu starten: Fehlercode %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "konnte Statuscode des Subprozesses nicht ermitteln: Fehlercode %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "kann restore_command mit Platzhalter %%r nicht verwenden"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "unerwartete Dateigröße für »%s«: %lu statt %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "konnte aus dem Archiv wiederhergestellte Datei »%s« nicht öffnen: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "konnte »stat« für Datei »%s« nicht ausführen: %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "restore_command fehlgeschlagen: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "konnte Datei »%s« nicht aus Archiv wiederherstellen"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:73 parsexlog.c:125
+#: parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "Speicher aufgebraucht"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:298
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht öffnen: %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "konnte nicht in Datei »%s« schreiben: %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht erstellen: %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "konnte Verzeichnis »%s« nicht öffnen: %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "konnte symbolische Verknüpfung »%s« nicht lesen: %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "Ziel für symbolische Verknüpfung »%s« ist zu lang"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "»%s« ist eine symbolische Verknüpfung, aber symbolische Verknüpfungen werden auf dieser Plattform nicht unterstützt"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "konnte Verzeichnis »%s« nicht lesen: %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "konnte Verzeichnis »%s« nicht schließen: %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "konnte Quelldatei »%s« nicht öffnen: %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "konnte Positionszeiger in Quelldatei nicht setzen: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:336
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht lesen: %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "unerwartetes EOF beim Lesen der Datei »%s«"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht schließen: %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "konnte Zieldatei »%s« nicht öffnen: %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "konnte Zieldatei »%s« nicht schließen: %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "konnte Positionszeiger in Zieldatei »%s« nicht setzen: %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht schreiben: %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "ungültige Aktion (CREATE) für normale Datei"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "konnte Datei »%s« nicht löschen: %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "konnte Datei »%s« nicht zum Kürzen öffnen: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "konnte Datei »%s« nicht auf %u kürzen: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "konnte Verzeichnis »%s« nicht erzeugen: %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "konnte Verzeichnis »%s« nicht löschen: %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "konnte symbolische Verknüpfung »%s« nicht erstellen: %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "konnte symbolische Verknüpfung »%s« nicht löschen: %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "konnte Datei »%s« nicht zum Lesen öffnen: %m"
+
+#: file_ops.c:314 parsexlog.c:338
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "konnte Datei »%s« nicht lesen: %d von %zu gelesen"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "Datendatei »%s« in der Quelle ist keine normale Datei"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "»%s« ist kein Verzeichnis"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "»%s« ist keine symbolische Verknüpfung"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "»%s« ist keine normale Datei"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "Quelldateiliste ist leer"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "unerwartete Seitenänderung für Verzeichnis oder symbolische Verknüpfung »%s«"
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "%s"
+msgstr "%s"
+
+#: libpq_fetch.c:53
+#, c-format
+msgid "connected to server"
+msgstr "mit Server verbunden"
+
+#: libpq_fetch.c:62
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "konnte search_path nicht auf leer setzen: %s"
+
+#: libpq_fetch.c:74
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "Quell-Server darf nicht im Wiederherstellungsmodus sein"
+
+#: libpq_fetch.c:84
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "full_page_writes muss im Quell-Server eingeschaltet sein"
+
+#: libpq_fetch.c:110
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "Fehler beim Ausführen einer Anfrage (%s) auf dem Quellserver: %s"
+
+#: libpq_fetch.c:115
+#, c-format
+msgid "unexpected result set from query"
+msgstr "Anfrage ergab unerwartete Ergebnismenge"
+
+#: libpq_fetch.c:136
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "Fehler beim Ausführen einer Anfrage (%s) im Quellserver: %s"
+
+#: libpq_fetch.c:156
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "unbekanntes Ergebnis »%s« für aktuelle WAL-Einfügeposition"
+
+#: libpq_fetch.c:206
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "konnte Dateiliste nicht holen: %s"
+
+#: libpq_fetch.c:211
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "unerwartete Ergebnismenge beim Holen der Dateiliste"
+
+#: libpq_fetch.c:264
+#, c-format
+msgid "could not send query: %s"
+msgstr "konnte Anfrage nicht senden: %s"
+
+#: libpq_fetch.c:269
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "konnte libpq-Verbindung nicht in den Einzelzeilenmodus setzen"
+
+#: libpq_fetch.c:289
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "unerwartetes Ergebnis beim Holen von fernen Dateien: %s"
+
+#: libpq_fetch.c:295
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "unerwartete Ergebnismengengröße beim Holen von fernen Dateien"
+
+#: libpq_fetch.c:301
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "unerwartete Datentypen in Ergebnismenge beim Holen von fernen Dateien: %u %u %u"
+
+#: libpq_fetch.c:309
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "unerwartetes Ergebnisformat beim Holen von fernen Dateien"
+
+#: libpq_fetch.c:315
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "unerwartete NULL-Werte im Ergebnis beim Holen von fernen Dateien"
+
+#: libpq_fetch.c:319
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "unerwartete Ergebnislänge beim Holen von fernen Dateien"
+
+#: libpq_fetch.c:380
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "konnte ferne Datei »%s« nicht holen: %s"
+
+#: libpq_fetch.c:385
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "unerwartete Ergebnismenge beim Holen der fernen Datei »%s«"
+
+#: libpq_fetch.c:429
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "konnte COPY-Daten nicht senden: %s"
+
+#: libpq_fetch.c:458
+#, c-format
+msgid "could not send file list: %s"
+msgstr "konnte Dateiliste nicht senden: %s"
+
+#: libpq_fetch.c:500
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "konnte COPY-Ende nicht senden: %s"
+
+#: libpq_fetch.c:506
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "unerwartetes Ergebnis beim Senden der Dateiliste: %s"
+
+#: parsexlog.c:85 parsexlog.c:132
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "konnte WAL-Eintrag bei %X/%X nicht lesen: %s"
+
+#: parsexlog.c:89 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "konnte WAL-Eintrag bei %X/%X nicht lesen"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "konnte vorangegangenen WAL-Eintrag bei %X/%X nicht finden: %s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "konnte vorangegangenen WAL-Eintrag bei %X/%X nicht finden"
+
+#: parsexlog.c:327
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "konnte Positionszeiger in Datei »%s« nicht setzen: %m"
+
+#: parsexlog.c:407
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL-Eintrag modifiziert eine Relation, aber Typ des Eintrags wurde nicht erkannt: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s resynchronisiert einen PostgreSQL-Cluster mit einer Kopie des Clusters.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Aufruf:\n"
+" %s [OPTION]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Optionen:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal restore_command in der Zielkonfiguration zum\n"
+" Laden von WAL-Dateien aus Archiv verwenden\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=VERZ bestehendes zu modifizierendes Datenverzeichnis\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr ""
+" --source-pgdata=VERZ Quelldatenverzeichnis, mit dem synchronisiert\n"
+" werden soll\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=VERB Quellserver, mit dem synchronisiert werden soll\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run anhalten, bevor etwas geändert wird\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync nicht warten, bis Änderungen sicher auf Festplatte\n"
+" geschrieben sind\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress Fortschrittsmeldungen ausgeben\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf Konfiguration für Replikation schreiben\n"
+" (benötigt --source-server)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug viele Debug-Meldungen ausgeben\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown unsauberen Shutdown nicht automatisch reparieren\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version Versionsinformationen anzeigen, dann beenden\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help diese Hilfe anzeigen, dann beenden\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Berichten Sie Fehler an <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "%s Homepage: <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Versuchen Sie »%s --help« für weitere Informationen.\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "keine Quelle angegeben (--source-pgdata oder --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "--source-pgdata und --source-server können nicht zusammen angegeben werden"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "kein Zielverzeichnis angegeben (--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "kein Quellserver (--source-server) angegeben für --write-recovery-conf"
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "zu viele Kommandozeilenargumente (das erste ist »%s«)"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "kann nicht von »root« ausgeführt werden"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Sie müssen %s als PostgreSQL-Superuser ausführen.\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "konnte Zugriffsrechte von Verzeichnis »%s« nicht lesen: %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "Quell- und Ziel-Cluster sind auf der gleichen Zeitleiste"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "Server divergierten bei WAL-Position %X/%X auf Zeitleiste %u"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "kein Rückspulen nötig"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "Rückspulen ab letztem gemeinsamen Checkpoint bei %X/%X auf Zeitleiste %u"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "lese Quelldateiliste"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "lese Zieldateiliste"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "lese WAL im Ziel-Cluster"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "%lu MB müssen kopiert werden (Gesamtgröße des Quellverzeichnisses ist %lu MB)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "erzeuge Backup-Label und aktualisiere Kontrolldatei"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "synchronisiere Zieldatenverzeichnis"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "Fertig!"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "Quell- und Ziel-Cluster sind von verschiedenen Systemen"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "die Cluster sind nicht mit dieser Version von pg_rewind kompatibel"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "Zielserver muss entweder Datenprüfsummen oder »wal_log_hints = on« verwenden"
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "Zielserver muss sauber heruntergefahren worden sein"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "Quelldatenverzeichnis muss sauber heruntergefahren worden sein"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) kopiert"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "ungültige Kontrolldatei"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "konnte keinen gemeinsamen Anfangspunkt in den Zeitleisten von Quell- und Ziel-Cluster finden"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "Puffer für Backup-Label ist zu klein"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "unerwartete CRC in Kontrolldatei"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "unerwartete Kontrolldateigröße %d, erwartet wurde %d"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "WAL-Segmentgröße muss eine Zweierpotenz zwischen 1 MB und 1 GB sein, aber die Kontrolldatei gibt %d Byte an"
+msgstr[1] "WAL-Segmentgröße muss eine Zweierpotenz zwischen 1 MB und 1 GB sein, aber die Kontrolldatei gibt %d Bytes an"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"Das Programm »%s« wird von %s benötigt, aber wurde nicht im\n"
+"selben Verzeichnis wie »%s« gefunden.\n"
+"Prüfen Sie Ihre Installation."
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"Das Programm »%s« wurde von %s gefunden,\n"
+"aber es hatte nicht die gleiche Version wie %s.\n"
+"Prüfen Sie Ihre Installation."
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "restore_command ist im Ziel-Cluster nicht gesetzt"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "führe »%s« für Zielserver aus, um Wiederherstellung abzuschließen"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "postgres im Einzelbenutzermodus im Ziel-Cluster fehlgeschlagen"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "Die Anweisung war: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "Syntaxfehler in History-Datei: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Eine numerische Zeitleisten-ID wurde erwartet."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Eine Write-Ahead-Log-Switchpoint-Position wurde erwartet."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "ungültige Daten in History-Datei: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Zeitleisten-IDs müssen in aufsteigender Folge sein."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "ungültige Daten in History-Datei"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "Zeitleisten-IDs müssen kleiner als die Zeitleisten-ID des Kindes sein."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "ungültiger Datensatz-Offset bei %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "Contrecord angefordert von %X/%X"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "ungültige Datensatzlänge bei %X/%X: %u erwartet, %u erhalten"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "Datensatzlänge %u bei %X/%X ist zu lang"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "keine Contrecord-Flag bei %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "ungültige Contrecord-Länge %u bei %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "ungültige Resource-Manager-ID %u bei %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "Datensatz mit falschem Prev-Link %X/%X bei %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "ungültige Resource-Manager-Datenprüfsumme in Datensatz bei %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "ungültige magische Zahl %04X in Logsegment %s, Offset %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "ungültige Info-Bits %04X in Logsegment %s, Offset %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "WAL-Datei ist von einem anderen Datenbanksystem: Datenbanksystemidentifikator in WAL-Datei ist %llu, Datenbanksystemidentifikator in pg_control ist %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche Segmentgröße im Seitenkopf"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL-Datei ist von einem anderen Datenbanksystem: falsche XLOG_BLCKSZ im Seitenkopf"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "unerwartete Pageaddr %X/%X in Logsegment %s, Offset %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "Zeitleisten-ID %u außer der Reihe (nach %u) in Logsegment %s, Offset %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "block_id %u außer der Reihe bei %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA gesetzt, aber keine Daten enthalten bei %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA nicht gesetzt, aber Datenlänge ist %u bei %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE gesetzt, aber Loch Offset %u Länge %u Block-Abbild-Länge %u bei %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE nicht gesetzt, aber Loch Offset %u Länge %u bei %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED gesetzt, aber Block-Abbild-Länge %u bei %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "weder BKPIMAGE_HAS_HOLE noch BKPIMAGE_IS_COMPRESSED gesetzt, aber Block-Abbild-Länge ist %u bei %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL gesetzt, aber keine vorangehende Relation bei %X/%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "ungültige block_id %u bei %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "Datensatz mit ungültiger Länge bei %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "ungültiges komprimiertes Abbild bei %X/%X, Block %d"
diff --git a/src/bin/pg_rewind/po/es.po b/src/bin/pg_rewind/po/es.po
new file mode 100644
index 0000000..f8612c0
--- /dev/null
+++ b/src/bin/pg_rewind/po/es.po
@@ -0,0 +1,942 @@
+# Spanish message translation file for pg_rewind
+#
+# Copyright (c) 2015-2019, PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+#
+# Álvaro Herrera <alvherre@alvh.no-ip.org>, 2015.
+# Carlos Chapi <carloswaldo@babelruins.org>, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 12\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2021-05-13 14:01+0000\n"
+"PO-Revision-Date: 2020-10-16 15:59-0300\n"
+"Last-Translator: Carlos Chapi <carloswaldo@babelruins.org>\n"
+"Language-Team: PgSQL-es-Ayuda <pgsql-es-ayuda@lists.postgresql.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: BlackCAT 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "fatal: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "error: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "precaución: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "memoria agotada\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "no se puede duplicar un puntero nulo (error interno)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "no se pudo cargar la biblioteca «%s»: código de error %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "no se pueden crear tokens restrigidos en esta plataforma: código de error %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "no se pudo abrir el token de proceso: código de error %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "no se pudo emplazar los SIDs: código de error %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "no se pudo crear el token restringido: código de error %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "no se pudo iniciar el proceso para la orden «%s»: código de error %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "no se pudo re-ejecutar con el token restringido: código de error %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "no se pudo obtener el código de salida del subproceso»: código de error %lu"
+
+#: ../../fe_utils/archive.c:53
+#, fuzzy, c-format
+#| msgid "could not use restore_command with %%r alias"
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "no se puede usar restore_command con el alias %%r"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "el archivo «%s» tiene tamaño inesperado: %lu en lugar de %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "no se pudo abrir el archivo «%s» restaurado del archivo: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "no se pudo hacer stat al archivo «%s»: %m"
+
+#: ../../fe_utils/archive.c:112
+#, fuzzy, c-format
+#| msgid "restore_command failed due to the signal: %s"
+msgid "restore_command failed: %s"
+msgstr "restore_command falló debido a la señal: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "no se pudo recuperar el archivo «%s» del archivo"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:76 parsexlog.c:134
+#: parsexlog.c:194
+#, c-format
+msgid "out of memory"
+msgstr "memoria agotada"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:307
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "no se pudo abrir el archivo «%s»: %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "no se pudo escribir a archivo «%s»: %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "no se pudo crear archivo «%s»: %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "no se pudo abrir el directorio «%s»: %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "no se pudo leer el enlace simbólico «%s»: %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "la ruta «%s» del enlace simbólico es demasiado larga"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "«%s» es un link simbólico, pero los links simbólicos no están soportados en esta plataforma"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "no se pudo leer el directorio «%s»: %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "no se pudo abrir el directorio «%s»: %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "no se pudo abrir el archivo de origen «%s»: %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "no se pudo posicionar en archivo de origen: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:345
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "no se pudo leer el archivo «%s»: %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "EOF inesperado mientras se leía el archivo «%s»"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "no se pudo cerrar el archivo «%s»: %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "no se pudo abrir el archivo de destino «%s»: %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "no se pudo cerrar el archivo de destino «%s»: %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "no se pudo posicionar en archivo de destino «%s»: %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "no se pudo escribir el archivo «%s»: %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "acción no válida (CREATE) para archivo regular"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "no se pudo eliminar el archivo «%s»: %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "no se pudo abrir el archivo «%s» para truncarlo: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "no se pudo truncar el archivo «%s» a %u: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "no se pudo crear el directorio «%s»: %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "no se pudo eliminar el directorio «%s»: %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "no se pudo crear el link simbólico en «%s»: %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "no se pudo eliminar el enlace simbólico «%s»: %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "no se pudo abrir archivo «%s» para lectura: %m"
+
+#: file_ops.c:314 parsexlog.c:347
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "no se pudo leer el archivo «%s»: leídos %d de %zu"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "el archivo de datos «%s» en el origen no es un archivo regular"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "«%s» no es un directorio"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "«%s» no es un link simbólico"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "«%s» no es un archivo regular"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "el listado de archivos de origen está vacío"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "modificación de página inesperada para el directorio o link simbólico «%s»"
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "%s"
+msgstr "%s"
+
+#: libpq_fetch.c:53
+#, c-format
+msgid "connected to server"
+msgstr "conectado al servidor"
+
+#: libpq_fetch.c:62
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "no se pudo limpiar search_path: %s"
+
+#: libpq_fetch.c:74
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "el servidor de origen no debe estar en modo de recuperación"
+
+#: libpq_fetch.c:84
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "full_page_writes debe estar activado en el servidor de origen"
+
+#: libpq_fetch.c:110
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "error ejecutando consulta (%s) en el servidor de origen: %s"
+
+#: libpq_fetch.c:115
+#, c-format
+msgid "unexpected result set from query"
+msgstr "conjunto de resultados inesperados de la consulta"
+
+#: libpq_fetch.c:136
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "error ejecutando consulta (%s) en el servidor de origen: %s"
+
+#: libpq_fetch.c:156
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "resultado «%s» no reconocido para la ubicación de inserción WAL actual"
+
+#: libpq_fetch.c:206
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "no se pudo obtener el listado de archivos: %s"
+
+#: libpq_fetch.c:211
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "conjunto de resultados inesperado mientras se obtenía el listado de archivos"
+
+#: libpq_fetch.c:264
+#, c-format
+msgid "could not send query: %s"
+msgstr "no se pudo enviar la consulta: %s"
+
+#: libpq_fetch.c:269
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "no se pudo establecer la coneción libpq a modo «single row»"
+
+#: libpq_fetch.c:289
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "resultados inesperados mientras se obtenían archivos remotos: %s"
+
+#: libpq_fetch.c:295
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "tamaño del conjunto de resultados inesperado mientras se obtenían archivos remotos"
+
+#: libpq_fetch.c:301
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "tipos de dato inesperados en el conjunto de resultados mientras se obtenían archivos remotos: %u %u %u"
+
+#: libpq_fetch.c:309
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "formato de resultados inesperado mientras se obtenían archivos remotos"
+
+#: libpq_fetch.c:315
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "valores nulos inesperados en el resultado mientras se obtenían archivos remotos"
+
+#: libpq_fetch.c:319
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "largo del resultado inesperado mientras se obtenían los archivos remotos"
+
+#: libpq_fetch.c:380
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "no se pudo obtener el archivo remoto «%s»: %s"
+
+#: libpq_fetch.c:385
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "conjunto de resultados inesperado mientras se obtenía el archivo remoto «%s»"
+
+#: libpq_fetch.c:429
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "no se pudo enviar datos COPY: %s"
+
+#: libpq_fetch.c:458
+#, c-format
+msgid "could not send file list: %s"
+msgstr "no se pudo enviar el listado de archivos: %s"
+
+#: libpq_fetch.c:500
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "no se pudo enviar fin-de-COPY: %s"
+
+#: libpq_fetch.c:506
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "resultados inesperados mientras se enviaba el listado de archivos: %s"
+
+#: parsexlog.c:88 parsexlog.c:141
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "no se pudo leer el registro WAL en %X/%X: %s"
+
+#: parsexlog.c:92 parsexlog.c:144
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "no se pudo leer el registro WAL en %X/%X"
+
+#: parsexlog.c:207
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "no se pudo encontrar el registro WAL anterior en %X/%X: %s"
+
+#: parsexlog.c:211
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "no se pudo encontrar el registro WAL anterior en %X/%X"
+
+#: parsexlog.c:336
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "no se pudo posicionar (seek) el archivo «%s»: %m"
+
+#: parsexlog.c:416
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "el registro WAL modifica una relación, pero el tipo de registro no es reconocido lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s resincroniza un cluster PostgreSQL con otra copia del cluster.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Empleo:\n"
+" %s [OPCION]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Opciones:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal utilizar restore_command de la configuración\n"
+" de destino para obtener archivos WAL\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=DIRECTORIO directorio de datos existente a modificar\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=DIRECTORIO directorio de datos de origen a sincronizar\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONN servidor de origen a sincronizar\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run detener antes de modificar nada\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr " -N, --no-sync no esperar que los cambios se sincronicen a disco\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress escribir mensajes de progreso\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf escribe configuración para replicación\n"
+" (requiere --source-server)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug escribir muchos mensajes de depuración\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr ""
+" --no-ensure-shutdown no corregir automáticamente un apagado\n"
+" no-limpio\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version mostrar información de versión y salir\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help mostrar esta ayuda y salir\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Reporte errores a <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "Sitio web de %s: <%s>\n"
+
+#: pg_rewind.c:160 pg_rewind.c:209 pg_rewind.c:216 pg_rewind.c:223
+#: pg_rewind.c:230 pg_rewind.c:238
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Pruebe «%s --help» para mayor información.\n"
+
+#: pg_rewind.c:208
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "no se especificó origen (--source-pgdata o --source-server)"
+
+#: pg_rewind.c:215
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "sólo uno de --source-pgdata o --source-server puede ser especificado"
+
+#: pg_rewind.c:222
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "no se especificó directorio de datos de destino (--target-pgdata)"
+
+#: pg_rewind.c:229
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "no se especificó información de servidor de origen (--source-server) para --write-recovery-conf"
+
+#: pg_rewind.c:236
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "demasiados argumentos en la línea de órdenes (el primero es «%s»)"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "no puede ser ejecutado por «root»"
+
+#: pg_rewind.c:252
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Debe ejecutar %s con el superusuario de PostgreSQL.\n"
+
+#: pg_rewind.c:263
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "no se pudo obtener los permisos del directorio «%s»: %m"
+
+#: pg_rewind.c:317
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "el cluster de origen y destino están en el mismo timeline"
+
+#: pg_rewind.c:326
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "servidores divergieron en la posición de WAL %X/%X en el timeline %u"
+
+#: pg_rewind.c:374
+#, c-format
+msgid "no rewind required"
+msgstr "no se requiere rebobinar"
+
+#: pg_rewind.c:383
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "rebobinando desde el último checkpoint común en %X/%X en el timeline %u"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading source file list"
+msgstr "leyendo la lista de archivos de origen"
+
+#: pg_rewind.c:395
+#, c-format
+msgid "reading target file list"
+msgstr "leyendo la lista de archivos de destino"
+
+#: pg_rewind.c:404
+#, c-format
+msgid "reading WAL in target"
+msgstr "leyendo WAL en destino"
+
+#: pg_rewind.c:421
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "se necesitan copiar %lu MB (tamaño total de directorio de origen es %lu MB)"
+
+#: pg_rewind.c:439
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "creando etiqueta de respaldo y actualizando archivo de control"
+
+#: pg_rewind.c:469
+#, c-format
+msgid "syncing target data directory"
+msgstr "sincronizando directorio de datos de destino"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "Done!"
+msgstr "¡Listo!"
+
+#: pg_rewind.c:488
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "clusters de origen y destino son de sistemas diferentes"
+
+#: pg_rewind.c:496
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "los clusters no son compatibles con esta versión de pg_rewind"
+
+#: pg_rewind.c:506
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "el servidor de destino necesita tener sumas de verificación de datos o «wal_log_hints» activados"
+
+#: pg_rewind.c:517
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "el directorio de destino debe estar apagado limpiamente"
+
+#: pg_rewind.c:527
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "el directorio de origen debe estar apagado limpiamente"
+
+#: pg_rewind.c:579
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) copiados"
+
+#: pg_rewind.c:642
+#, c-format
+msgid "invalid control file"
+msgstr "archivo de control no válido"
+
+#: pg_rewind.c:726
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "no se pudo encontrar un ancestro común en el timeline de los clusters de origen y destino"
+
+#: pg_rewind.c:767
+#, c-format
+msgid "backup label buffer too small"
+msgstr "el búfer del backup label es demasiado pequeño"
+
+#: pg_rewind.c:790
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "CRC de archivo de control inesperado"
+
+#: pg_rewind.c:800
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "tamaño del archivo de control %d inesperado, se esperaba %d"
+
+#: pg_rewind.c:809
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d byte"
+msgstr[1] "El tamaño del segmento de WAL debe ser una potencia de dos entre 1 MB y 1 GB, pero el archivo de control especifica %d bytes"
+
+#: pg_rewind.c:866 pg_rewind.c:924
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"%s necesita el programa «%s», pero no pudo encontrarlo en el mismo\n"
+"directorio que «%s».\n"
+"Verifique su instalación."
+
+#: pg_rewind.c:871 pg_rewind.c:929
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"El programa «%s» fue encontrado por «%s»,\n"
+"pero no es de la misma versión que %s.\n"
+"Verifique su instalación."
+
+#: pg_rewind.c:892
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "restore_command no está definido en el clúster de destino"
+
+#: pg_rewind.c:935
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "ejecutando «%s» en el servidor de destino para completar la recuperación de caídas"
+
+#: pg_rewind.c:955
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "el modo «single-user» en el servidor de destino falló"
+
+#: pg_rewind.c:956
+#, c-format
+msgid "Command was: %s"
+msgstr "La orden era: % s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "error de sintaxis en archivo de historia: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Se esperaba un ID numérico de timeline."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Se esperaba una ubicación de punto de cambio del «write-ahead log»."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "datos no válidos en archivo de historia: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "IDs de timeline deben ser una secuencia creciente."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "datos no válidos en archivo de historia"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "IDs de timeline deben ser menores que el ID de timeline del hijo."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "posición de registro no válida en %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "contrecord solicitado por %X/%X"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "largo de registro no válido en %X/%X: se esperaba %u, se obtuvo %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "largo de registro %u en %X/%X demasiado largo"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "no hay bandera de contrecord en %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "largo de contrecord %u no válido en %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "ID de gestor de recursos %u no válido en %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "registro con prev-link %X/%X incorrecto en %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "suma de verificación de los datos del gestor de recursos incorrecta en el registro en %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "número mágico %04X no válido en archivo %s, posición %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "info bits %04X no válidos en archivo %s, posición %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "archivo WAL es de un sistema de bases de datos distinto: identificador de sistema en archivo WAL es %llu, identificador en pg_control es %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "archivo WAL es de un sistema de bases de datos distinto: tamaño de segmento incorrecto en cabecera de paǵina"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "archivo WAL es de un sistema de bases de datos distinto: XLOG_BLCKSZ incorrecto en cabecera de paǵina"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "pageaddr %X/%X inesperado en archivo %s, posición %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "ID de timeline %u fuera de secuencia (después de %u) en archivo %s, posición %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "block_id %u fuera de orden en %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA está definido, pero no hay datos en %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA no está definido, pero el largo de los datos es %u en %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE está definido, pero posición del agujero es %u largo %u largo de imagen %u en %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE no está definido, pero posición del agujero es %u largo %u en %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED definido, pero largo de imagen de bloque es %u en %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_IS_COMPRESSED está definido, pero largo de imagen de bloque es %u en %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL está definido, pero no hay «rel» anterior en %X/%X "
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "block_id %u no válido en %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "registro con largo no válido en %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "imagen comprimida no válida en %X/%X, bloque %d"
+
+#~ msgid "could not connect to server: %s"
+#~ msgstr "no se pudo conectar al servidor: %s"
diff --git a/src/bin/pg_rewind/po/fr.po b/src/bin/pg_rewind/po/fr.po
new file mode 100644
index 0000000..8172621
--- /dev/null
+++ b/src/bin/pg_rewind/po/fr.po
@@ -0,0 +1,1153 @@
+# LANGUAGE message translation file for pg_rewind
+# Copyright (C) 2016 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2016.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 12\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-11-08 08:46+0000\n"
+"PO-Revision-Date: 2020-09-17 08:30+0200\n"
+"Last-Translator: Guillaume Lelarge <guillaume@lelarge.info>\n"
+"Language-Team: \n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.4.1\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "fatal : "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "erreur : "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "attention : "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "mémoire épuisée\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "ne peut pas dupliquer un pointeur nul (erreur interne)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "n'a pas pu charger la bibliothèque « %s » : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "ne peut pas créer les jetons restreints sur cette plateforme : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "n'a pas pu ouvrir le jeton du processus : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "n'a pas pu allouer les SID : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "n'a pas pu créer le jeton restreint : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "ne peut pas utiliser restore_command avec le joker %%r"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "taille de fichier inattendu pour « %s » : %lu au lieu de %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » à partir de l'archive : %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "n'a pas pu tester le fichier « %s » : %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "échec de la restore_command : %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "n'a pas pu restaurer le fichier « %s » à partir de l'archive"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:73 parsexlog.c:125
+#: parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "mémoire épuisée"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:298
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » : %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "n'a pas pu écrire dans le fichier « %s » : %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "n'a pas pu créer le fichier « %s » : %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "n'a pas pu ouvrir le répertoire « %s » : %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "n'a pas pu lire le lien symbolique « %s » : %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "la cible du lien symbolique « %s » est trop long"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "« %s » est un lien symbolique mais les liens symboliques ne sont pas supportés sur cette plateforme"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "n'a pas pu lire le répertoire « %s » : %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "n'a pas pu fermer le répertoire « %s » : %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "n'a pas pu ouvrir le fichier source « %s » : %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "n'a pas pu chercher dans le fichier source : %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:336
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "n'a pas pu lire le fichier « %s » : %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "EOF inattendu lors de la lecture du fichier « %s »"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "n'a pas pu fermer le fichier « %s » : %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "n'a pas pu ouvrir le fichier cible « %s » : %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "n'a pas pu fermer le fichier cible « %s » : %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "n'a pas pu chercher dans le fichier cible « %s » : %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "impossible d'écrire le fichier « %s » : %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "action (CREATE) invalide pour le fichier régulier"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "n'a pas pu supprimer le fichier « %s » : %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » pour le troncage : %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "n'a pas pu tronquer le fichier « %s » en %u : %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "n'a pas pu créer le répertoire « %s » : %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "n'a pas pu supprimer le répertoire « %s » : %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "n'a pas pu créer le lien symbolique à « %s » : %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "n'a pas pu supprimer le lien symbolique « %s » : %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %m"
+
+#: file_ops.c:314 parsexlog.c:338
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "n'a pas pu lire le fichier « %s » : a lu %d sur %zu"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "le fichier de données « %s » en source n'est pas un fichier standard"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "« %s » n'est pas un répertoire"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "« %s » n'est pas un lien symbolique"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "« %s » n'est pas un fichier standard"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "la liste de fichiers sources est vide"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "modification inattendue de page pour le répertoire ou le lien symbolique « %s »"
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "%s"
+msgstr "%s"
+
+#: libpq_fetch.c:53
+#, c-format
+msgid "connected to server"
+msgstr "connecté au serveur"
+
+#: libpq_fetch.c:62
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "n'a pas pu effacer search_path : %s"
+
+#: libpq_fetch.c:74
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "le serveur source ne doit pas être en mode restauration"
+
+#: libpq_fetch.c:84
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "full_page_writes doit être activé sur le serveur source"
+
+#: libpq_fetch.c:110
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "erreur lors de l'exécution de la requête (%s) sur le serveur source : %s"
+
+#: libpq_fetch.c:115
+#, c-format
+msgid "unexpected result set from query"
+msgstr "ensemble de résultats inattendu provenant de la requête"
+
+#: libpq_fetch.c:136
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "erreur lors de l'exécution de la requête (%s) dans le serveur source : %s"
+
+#: libpq_fetch.c:156
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "résultat non reconnu « %s » pour l'emplacement d'insertion actuel dans les WAL"
+
+#: libpq_fetch.c:206
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "n'a pas pu récupérer la liste des fichiers : %s"
+
+#: libpq_fetch.c:211
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "ensemble de résultats inattendu lors de la récupération de la liste des fichiers"
+
+#: libpq_fetch.c:264
+#, c-format
+msgid "could not send query: %s"
+msgstr "n'a pas pu envoyer la requête : %s"
+
+#: libpq_fetch.c:269
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "n'a pas pu configurer la connexion libpq en mode ligne seule"
+
+#: libpq_fetch.c:289
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "résultat inattendu lors de la récupération des fichiers cibles : %s"
+
+#: libpq_fetch.c:295
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "taille inattendue de l'ensemble de résultats lors de la récupération des fichiers distants"
+
+#: libpq_fetch.c:301
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "types de données inattendus dans l'ensemble de résultats lors de la récupération des fichiers distants : %u %u %u"
+
+#: libpq_fetch.c:309
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "format de résultat inattendu lors de la récupération des fichiers distants"
+
+#: libpq_fetch.c:315
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "valeurs NULL inattendues dans le résultat lors de la récupération des fichiers distants"
+
+#: libpq_fetch.c:319
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "longueur de résultats inattendu lors de la récupération des fichiers distants"
+
+#: libpq_fetch.c:380
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "n'a pas pu récupérer le fichier distant « %s » : %s"
+
+#: libpq_fetch.c:385
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "ensemble de résultats inattendu lors de la récupération du fichier distant « %s »"
+
+#: libpq_fetch.c:429
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "n'a pas pu envoyer les données COPY : %s"
+
+#: libpq_fetch.c:458
+#, c-format
+msgid "could not send file list: %s"
+msgstr "n'a pas pu envoyer la liste de fichiers : %s"
+
+#: libpq_fetch.c:500
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "n'a pas pu envoyer end-of-COPY : %s"
+
+#: libpq_fetch.c:506
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "résultat inattendu lors de l'envoi de la liste de fichiers : %s"
+
+#: parsexlog.c:85 parsexlog.c:132
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "n'a pas pu lire l'enregistrement WAL précédent à %X/%X : %s"
+
+#: parsexlog.c:89 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "n'a pas pu lire l'enregistrement WAL précédent à %X/%X"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "n'a pas pu trouver l'enregistrement WAL précédent à %X/%X : %s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "n'a pas pu trouver l'enregistrement WAL précédent à %X/%X"
+
+#: parsexlog.c:327
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "n'a pas pu parcourir le fichier « %s » : %m"
+
+#: parsexlog.c:407
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "l'enregistrement WAL modifie une relation mais le type d'enregistrement n'est pas reconnu: lsn : %X/%X, rmgr : %s, info : %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s resynchronise une instance PostgreSQL avec une autre copie de l'instance.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Usage :\n"
+" %s [OPTION]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Options :\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal utilise restore_command pour la configuration cible\n"
+" de récupération des fichiers WAL des archives\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=RÉPERTOIRE répertoire de données existant à modifier\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=RÉPERTOIRE répertoire des données source pour la synchronisation\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR serveur source pour la synchronisation\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run arrête avant de modifier quoi que ce soit\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr " -N, --nosync n'attend pas que les modifications soient proprement écrites sur disque\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress écrit les messages de progression\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf écrit la configuration pour la réplication\n"
+" (requiert --source-server)\n"
+"\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug écrit beaucoup de messages de débogage\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown ne corrige pas automatiquement l'arrêt non propre\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version affiche la version, puis quitte\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help affiche cette aide, puis quitte\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Rapporter les bogues à <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "page d'accueil %s : <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Essayez « %s --help » pour plus d'informations.\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "aucune source indiquée (--source-pgdata ou --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "une seule des options --source-pgdata et --source-server peut être indiquée"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "aucun répertoire de données cible indiqué (--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "aucune information sur le serveur source (--source-server) indiquée pour --write-recovery-conf"
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "trop d'arguments en ligne de commande (le premier étant « %s »)"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "ne peut pas être exécuté par « root »"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Vous devez exécuter %s en tant que super-utilisateur PostgreSQL.\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "n'a pas pu lire les droits du répertoire « %s » : %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "les instances source et cible sont sur la même ligne de temps"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "les serveurs ont divergé à la position %X/%X des WAL sur la timeline %u"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "pas de retour en arrière requis"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "retour en arrière depuis le dernier checkpoint commun à %X/%X sur la ligne de temps %u"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "lecture de la liste des fichiers sources"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "lecture de la liste des fichiers cibles"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "lecture du WAL dans la cible"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "a besoin de copier %lu Mo (la taille totale du répertoire source est %lu Mo)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "création du fichier backup_label et mise à jour du fichier contrôle"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "synchronisation du répertoire des données cible"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "Terminé !"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "les instances source et cible proviennent de systèmes différents"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "les instances ne sont pas compatibles avec cette version de pg_rewind"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "le serveur cible doit soit utiliser les sommes de contrôle sur les données soit avoir wal_log_hints configuré à on"
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "le serveur cible doit être arrêté proprement"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "le répertoire de données source doit être arrêté proprement"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s Ko (%d%%) copiés"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "fichier de contrôle invalide"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "n'a pas pu trouver l'ancêtre commun des lignes de temps des instances source et cible"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "tampon du label de sauvegarde trop petit"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "CRC inattendu pour le fichier de contrôle"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "taille %d inattendue du fichier de contrôle, %d attendu"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octet"
+msgstr[1] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octets"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"Le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé\n"
+"dans le même répertoire que « %s ».\n"
+"Vérifiez votre installation."
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"Le programme « %s » a été trouvé par « %s »\n"
+"mais n'est pas de la même version que %s.\n"
+"Vérifiez votre installation."
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "restore_command n'est pas configuré sur l'instance cible"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "exécution de « %s » pour terminer la restauration après crash du serveur cible"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "le mot simple-utilisateur de postgres a échoué pour l'instance cible"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "La commande était : %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "erreur de syntaxe dans le fichier historique : %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Attendait un identifiant timeline numérique."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Attendait un emplacement de bascule de journal de transactions."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "données invalides dans le fichier historique : %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Les identifiants timeline doivent être en ordre croissant."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "données invalides dans le fichier historique"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr ""
+"Les identifiants timeline doivent être plus petits que les enfants des\n"
+"identifiants timeline."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "décalage invalide de l'enregistrement %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "« contrecord » est requis par %X/%X"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "longueur invalide de l'enregistrement à %X/%X : voulait %u, a eu %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "longueur trop importante de l'enregistrement %u à %X/%X"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "il n'existe pas de drapeau contrecord à %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "longueur %u invalide du contrecord à %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "identifiant du gestionnaire de ressources invalide %u à %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "enregistrement avec prev-link %X/%X incorrect à %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr ""
+"somme de contrôle des données du gestionnaire de ressources incorrecte à\n"
+"l'enregistrement %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "numéro magique invalide %04X dans le segment %s, décalage %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "bits d'information %04X invalides dans le segment %s, décalage %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "le fichier WAL provient d'un système différent : l'identifiant système de la base dans le fichier WAL est %llu, alors que l'identifiant système de la base dans pg_control est %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "Le fichier WAL provient d'un système différent : taille invalide du segment dans l'en-tête de page"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "Le fichier WAL provient d'un système différent : XLOG_BLCKSZ invalide dans l'en-tête de page"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "pageaddr %X/%X inattendue dans le journal de transactions %s, segment %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "identifiant timeline %u hors de la séquence (après %u) dans le segment %s, décalage %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "block_id %u désordonné à %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA configuré, mais aucune donnée inclus à %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA non configuré, mais la longueur des données est %u à %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE activé, mais décalage trou %u longueur %u longueur image bloc %u à %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE désactivé, mais décalage trou %u longueur %u à %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "ni BKPIMAGE_HAS_HOLE ni BKPIMAGE_IS_COMPRESSED configuré, mais la longueur de l'image du bloc est %u à %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL configuré, mais pas de relation précédente à %X/%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "block_id %u invalide à %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "enregistrement de longueur invalide à %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "image compressée invalide à %X/%X, bloc %d"
+
+#~ msgid "%s: WARNING: cannot create restricted tokens on this platform\n"
+#~ msgstr "%s : ATTENTION : ne peut pas créer les jetons restreints sur cette plateforme\n"
+
+#~ msgid "%s: could not open process token: error code %lu\n"
+#~ msgstr "%s : n'a pas pu ouvrir le jeton du processus : code d'erreur %lu\n"
+
+#~ msgid "%s: could not allocate SIDs: error code %lu\n"
+#~ msgstr "%s : n'a pas pu allouer les SID : code d'erreur %lu\n"
+
+#~ msgid "%s: could not create restricted token: error code %lu\n"
+#~ msgstr "%s : n'a pas pu créer le jeton restreint : code d'erreur %lu\n"
+
+#~ msgid "%s: could not start process for command \"%s\": error code %lu\n"
+#~ msgstr "%s : n'a pas pu démarrer le processus pour la commande « %s » : code d'erreur %lu\n"
+
+#~ msgid "%s: could not re-execute with restricted token: error code %lu\n"
+#~ msgstr "%s : n'a pas pu ré-exécuter le jeton restreint : code d'erreur %lu\n"
+
+#~ msgid "%s: could not get exit code from subprocess: error code %lu\n"
+#~ msgstr "%s : n'a pas pu récupérer le code de statut du sous-processus : code d'erreur %lu\n"
+
+#~ msgid "could not open directory \"%s\": %s\n"
+#~ msgstr "n'a pas pu ouvrir le répertoire « %s » : %s\n"
+
+#~ msgid "could not stat file \"%s\": %s\n"
+#~ msgstr "n'a pas pu tester le fichier « %s » : %s\n"
+
+#~ msgid "could not read symbolic link \"%s\": %s\n"
+#~ msgstr "n'a pas pu lire le lien symbolique « %s » : %s\n"
+
+#~ msgid "symbolic link \"%s\" target is too long\n"
+#~ msgstr "la cible du lien symbolique « %s » est trop long\n"
+
+#~ msgid "could not read directory \"%s\": %s\n"
+#~ msgstr "n'a pas pu lire le répertoire « %s » : %s\n"
+
+#~ msgid "could not close directory \"%s\": %s\n"
+#~ msgstr "n'a pas pu fermer le répertoire « %s » : %s\n"
+
+#~ msgid "could not read file \"%s\": %s\n"
+#~ msgstr "n'a pas pu lire le fichier « %s » : %s\n"
+
+#~ msgid "could not close file \"%s\": %s\n"
+#~ msgstr "n'a pas pu fermer le fichier « %s » : %s\n"
+
+#~ msgid " block %u\n"
+#~ msgstr " bloc %u\n"
+
+#~ msgid "could not write file \"%s\": %s\n"
+#~ msgstr "n'a pas pu écrire le fichier « %s » : %s\n"
+
+#~ msgid "could not remove file \"%s\": %s\n"
+#~ msgstr "n'a pas pu supprimer le fichier « %s » : %s\n"
+
+#~ msgid "could not truncate file \"%s\" to %u: %s\n"
+#~ msgstr "n'a pas pu tronquer le fichier « %s » à %u : %s\n"
+
+#~ msgid "could not create directory \"%s\": %s\n"
+#~ msgstr "n'a pas pu créer le répertoire « %s » : %s\n"
+
+#~ msgid "could not remove directory \"%s\": %s\n"
+#~ msgstr "n'a pas pu supprimer le répertoire « %s » : %s\n"
+
+#~ msgid "could not remove symbolic link \"%s\": %s\n"
+#~ msgstr "n'a pas pu supprimer le lien symbolique « %s » : %s\n"
+
+#~ msgid "could not open file \"%s\" for reading: %s\n"
+#~ msgstr "n'a pas pu ouvrir le fichier « %s » pour une lecture : %s\n"
+
+#~ msgid "entry \"%s\" excluded from source file list\n"
+#~ msgstr "enregistrement « %s » exclus de la liste des fichiers sources\n"
+
+#~ msgid "entry \"%s\" excluded from target file list\n"
+#~ msgstr "enregistrement « %s » exclus de la liste des fichiers cibles\n"
+
+#~ msgid "%s (%s)\n"
+#~ msgstr "%s (%s)\n"
+
+#~ msgid "could not set up connection context: %s"
+#~ msgstr "n'a pas pu initialiser le contexte de connexion : « %s »"
+
+#~ msgid "getting file chunks\n"
+#~ msgstr "récupération des parties de fichier\n"
+
+#~ msgid "received null value for chunk for file \"%s\", file has been deleted\n"
+#~ msgstr "a reçu une valeur NULL pour une partie du fichier « %s », le fichier a été supprimé\n"
+
+#~ msgid "received chunk for file \"%s\", offset %s, size %d\n"
+#~ msgstr "a reçu une partie du fichier « %s », décalage %s, taille %d\n"
+
+#~ msgid "fetched file \"%s\", length %d\n"
+#~ msgstr "fichier récupéré « %s », longueur %d\n"
+
+#~ msgid "could not create temporary table: %s"
+#~ msgstr "n'a pas pu créer la table temporaire : %s"
+
+#~ msgid "Failure, exiting\n"
+#~ msgstr "Échec, sortie\n"
+
+#~ msgid "could not open file \"%s\": %s\n"
+#~ msgstr "n'a pas pu ouvrir le fichier « %s » : %s\n"
+
+#~ msgid "could not seek in file \"%s\": %s\n"
+#~ msgstr "n'a pas pu chercher dans le fichier « %s » : %s\n"
+
+#~ msgid "could not read from file \"%s\": %s\n"
+#~ msgstr "n'a pas pu lire le fichier « %s » : %s\n"
+
+#~ msgid "%s: too many command-line arguments (first is \"%s\")\n"
+#~ msgstr "%s : trop d'arguments en ligne de commande (le premier étant « %s »)\n"
+
+#~ msgid "%s: could not read permissions of directory \"%s\": %s\n"
+#~ msgstr "%s : n'a pas pu lire les droits sur le répertoire « %s » : %s\n"
+
+#~ msgid "Source timeline history:\n"
+#~ msgstr "Historique de la ligne de temps source :\n"
+
+#~ msgid "Target timeline history:\n"
+#~ msgstr "Historique de la ligne de temps cible :\n"
+
+#~ msgid "%d: %X/%X - %X/%X\n"
+#~ msgstr "%d : %X/%X - %X/%X\n"
+
+#~ msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte\n"
+#~ msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes\n"
+#~ msgstr[0] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octet\n"
+#~ msgstr[1] "La taille du segment WAL doit être une puissance de deux comprise entre 1 Mo et 1 Go, mais le fichier de contrôle indique %d octets\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "Le programme « initdb » est nécessaire pour %s, mais n'a pas été trouvé\n"
+#~ "dans le même répertoire que « %s ».\n"
+#~ "Vérifiez votre installation.\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "Le programme « initdb » a été trouvé par « %s », mais n'est pas de la même version\n"
+#~ "que %s.\n"
+#~ "Vérifiez votre installation.\n"
+
+#~ msgid "sync of target directory failed\n"
+#~ msgstr "échec de la synchronisation du répertoire cible\n"
+
+#~ msgid "syntax error in history file: %s\n"
+#~ msgstr "erreur de syntaxe dans le fichier historique : %s\n"
+
+#~ msgid "Expected a numeric timeline ID.\n"
+#~ msgstr "Attendait un identifiant numérique de ligne de temps.\n"
+
+#~ msgid "Expected a write-ahead log switchpoint location.\n"
+#~ msgstr "Attendait un emplacement de bascule de journal de transactions.\n"
+
+#~ msgid "invalid data in history file: %s\n"
+#~ msgstr "données invalides dans le fichier historique : %s\n"
+
+#~ msgid "Timeline IDs must be in increasing sequence.\n"
+#~ msgstr "Les identifiants de ligne de temps doivent être dans une séquence croissante.\n"
+
+#~ msgid "Timeline IDs must be less than child timeline's ID.\n"
+#~ msgstr "Les identifiants de ligne de temps doivent être inférieurs à l'identifiant de la ligne de temps enfant.\n"
+
+#~ msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
+#~ msgstr "le fichier WAL provient d'un système différent : XLOG_SEG_SIZE invalide dans l'en-tête de page"
+
+#~ msgid ""
+#~ "\n"
+#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Rapporter les bogues à <pgsql-bugs@lists.postgresql.org>.\n"
+
+#~ msgid ""
+#~ "The program \"%s\" was found by \"%s\" but was\n"
+#~ "not the same version as %s.\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Le programme « %s » a été trouvé par « %s » mais n'était pas de la même version\n"
+#~ "que %s.\n"
+#~ "Vérifiez votre installation."
+
+#~ msgid ""
+#~ "The program \"%s\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Le programme « %s » est nécessaire pour %s, mais n'a pas été trouvé\n"
+#~ "dans le même répertoire que « %s ».\n"
+#~ "Vérifiez votre installation."
+
+#~ msgid ""
+#~ "The program \"postgres\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Le programme « postgres » a été trouvé par « %s » mais n'est pas de la même\n"
+#~ "version que « %s ».\n"
+#~ "Vérifiez votre installation."
+
+#~ msgid ""
+#~ "The program \"postgres\" is needed by %s but was not found in the\n"
+#~ "same directory as \"%s\".\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Le programme « postgres » est nécessaire à %s mais n'a pas été trouvé dans\n"
+#~ "le même répertoire que « %s ».\n"
+#~ "Vérifiez votre installation."
+
+#~ msgid "could not connect to server: %s"
+#~ msgstr "n'a pas pu se connecter au serveur : %s"
diff --git a/src/bin/pg_rewind/po/ja.po b/src/bin/pg_rewind/po/ja.po
new file mode 100644
index 0000000..bfaea37
--- /dev/null
+++ b/src/bin/pg_rewind/po/ja.po
@@ -0,0 +1,1070 @@
+# Japanese message translation file for pg_rewind
+# Copyright (C) 2019 PostgreSQL Global Development Group
+# This file is distributed under the same license as the pg_archivecleanup (PostgreSQL) package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL 13)\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-08-21 15:55+0900\n"
+"PO-Revision-Date: 2020-08-21 23:25+0900\n"
+"Last-Translator: Kyotaro Horiguchi <horikyota.ntt@gmail.com>\n"
+"Language-Team: Japan PostgreSQL Users Group <jpug-doc@ml.postgresql.jp>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.13\n"
+"Plural-Forms: nplurals=2; plural=n!=1;\n"
+
+#: ../../../src/common/logging.c:241
+#, c-format
+msgid "fatal: "
+msgstr "致命的エラー: "
+
+#: ../../../src/common/logging.c:248
+#, c-format
+msgid "error: "
+msgstr "エラー: "
+
+#: ../../../src/common/logging.c:255
+#, c-format
+msgid "warning: "
+msgstr "警告: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "メモリ不足です\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "null ポインタを複製できません(内部エラー)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "ライブラリ\"%s\"をロードできませんでした: エラーコード %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "このプラットフォームでは制限付きトークンを生成できません: エラーコード %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "プロセストークンをオープンできませんでした: エラーコード %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "SIDを割り当てられませんでした: エラーコード %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "制限付きトークンを作成できませんでした: エラーコード %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "\"%s\"コマンドのプロセスを起動できませんでした: エラーコード %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "制限付きトークンで再実行できませんでした: %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "サブプロセスの終了コードを取得できませんでした。: エラーコード %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "could not use restore_command with %%r alias"
+msgstr "%%rエイリアスを含むrestore_commandは使用できません"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "予期しない\"%1$s\"のサイズ: %3$lu ではなく %2$lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "アーカイブからリストアされたファイル\"%s\"のオープンに失敗しました: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208 filemap.c:369
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "ファイル\"%s\"のstatに失敗しました: %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed due to the signal: %s"
+msgstr "restore_commandがシグナルにより失敗しました: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "ファイル\"%s\"をアーカイブからリストアできませんでした"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:74 parsexlog.c:126
+#: parsexlog.c:186
+#, c-format
+msgid "out of memory"
+msgstr "メモリ不足です"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:299
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "ファイル\"%s\"をオープンできませんでした: %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "ファイル\"%s\"を書き出せませんでした: %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "ファイル\"%s\"を作成できませんでした: %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"をオープンできませんでした: %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "シンボリックリンク\"%s\"を読めませんでした: %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "シンボリックリンク\"%s\"の参照先が長すぎます"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\"はシンボリックリンクですが、このプラットフォームではシンボリックリンクをサポートしていません"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"を読み取れませんでした: %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"をクローズできませんでした: %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "ソースファイル\"%s\"をオープンすることができませんでした: %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "ソースファイルをシークすることができませんでした: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:337
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "ファイル\"%s\"の読み取りに失敗しました: %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "ファイル\"%s\"を読み込み中に想定外のEOF"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "ファイル\"%s\"をクローズできませんでした: %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "ターゲットファイル\"%s\"をオープンできませんでした: %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "ターゲットファイル\"%s\"をクローズできませんでした: %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "ターゲットファイル\"%s\"をシークできませんでした: %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "ファイル\"%s\"を書き出せませんでした: %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "通常のファイルに対する不正なアクション(CREATE)です"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "ファイル\"%s\"を削除できませんでした: %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "ファイル\"%s\"を切り詰めのためにオープンできませんでした: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "ファイル\"%s\"を%uバイトに切り詰められませんでした: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"を作成できませんでした: %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"を削除できませんでした: %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "\"%s\"にシンボリックリンクを作成できませんでした: %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "シンボリックリンク\"%s\"を削除できませんでした: %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "ファイル\"%s\"を読み取り用にオープンできませんでした: %m"
+
+#: file_ops.c:314 parsexlog.c:339
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "ファイル\"%1$s\"を読み込めませんでした: %3$zuバイトのうち%2$dバイトを読み込みました"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "ソースのデータファイル\"%s\"は通常のファイルではありません"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\"はディレクトリではありません"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\"はシンボリックリンクではありません"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" は通常のファイルではありません"
+
+#: filemap.c:381
+#, c-format
+msgid "source file list is empty"
+msgstr "ソースファイルリストが空です"
+
+#: filemap.c:496
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "ディレクトリまたはシンボリックリンク\"%s\"に対する想定外のページの書き換えです"
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "サーバに接続できませんでした: %s"
+
+#: libpq_fetch.c:54
+#, c-format
+msgid "connected to server"
+msgstr "サーバへ接続しました"
+
+#: libpq_fetch.c:63
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "search_pathを消去できませんでした: %s"
+
+#: libpq_fetch.c:75
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "ソースサーバはリカバリモードであってはなりません"
+
+#: libpq_fetch.c:85
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "ソースサーバではfull_pate_writesは有効でなければなりません"
+
+#: libpq_fetch.c:111
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "ソースサーバで実行中のクエリ(%s)でエラー: %s"
+
+#: libpq_fetch.c:116
+#, c-format
+msgid "unexpected result set from query"
+msgstr "クエリから想定外の結果セット"
+
+#: libpq_fetch.c:137
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "ソースサーバの実行中のクエリ(%s)でエラー: %s"
+
+#: libpq_fetch.c:157
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "現在のWAL挿入位置として認識不可の結果\"%s\""
+
+#: libpq_fetch.c:207
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "ファイルリストをフェッチできませんでした: %s"
+
+#: libpq_fetch.c:212
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "ファイルリストのフェッチ中に想定外の結果セット"
+
+#: libpq_fetch.c:265
+#, c-format
+msgid "could not send query: %s"
+msgstr "クエリを送信できませんでした: %s"
+
+#: libpq_fetch.c:270
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "libpq接続を単一行モードに設定できませんでした"
+
+#: libpq_fetch.c:290
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "リモートファイルをフェッチ中に想定外の結果: %s"
+
+#: libpq_fetch.c:296
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "リモートファイルのフェッチ中に想定外の結果セットサイズ"
+
+#: libpq_fetch.c:302
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "リモートファイルのフェッチ中の結果セットに想定外のデータ型: %u %u %u"
+
+#: libpq_fetch.c:310
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "リモートファイルのフェッチ中に想定外の結果形式"
+
+#: libpq_fetch.c:316
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "リモートファイルのフェッチ中の結果に想定外のNULL値"
+
+#: libpq_fetch.c:320
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "リモートファイルのフェッチ中に想定外の結果の長さ"
+
+#: libpq_fetch.c:381
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "リモートファイル\"%s\"をフェッチできませんでした: %s"
+
+#: libpq_fetch.c:386
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "リモートファイル\"%s\"のフェッチ中に想定外の結果セット"
+
+#: libpq_fetch.c:430
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "COPY 対象データを送信できませんでした: %s"
+
+#: libpq_fetch.c:459
+#, c-format
+msgid "could not send file list: %s"
+msgstr "ファイルリストを送信できませんでした: %s"
+
+#: libpq_fetch.c:501
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "コピー終端を送信できませんでした: %s"
+
+#: libpq_fetch.c:507
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "ファイルリストを送信中に想定外の結果: %s"
+
+#: parsexlog.c:86 parsexlog.c:133
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "%X/%XのWALレコードを読み取れませんでした: %s"
+
+#: parsexlog.c:90 parsexlog.c:136
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "%X/%XのWALレコードを読み取れませんでした"
+
+#: parsexlog.c:199
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "%X/%Xの前のWALレコードが見つかりませんでした: %s"
+
+#: parsexlog.c:203
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "%X/%Xの前のWALレコードが見つかりませんでした"
+
+#: parsexlog.c:328
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "ファイル\"%s\"をシークできませんでした: %m"
+
+#: parsexlog.c:420
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WALレコードはリレーションを修正しますが、レコードの型を認識できません: lsn: %X/%X、rmgr: %s、info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s はPostgreSQLクラスタをそのクラスタのコピーで再同期します。\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"使用方法:\n"
+" %s [オプション]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "オプション:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal ターゲットの設定の中のrestore_commandを使用して\n"
+" アーカイブからWALファイルを取得する\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=DIRECTORY 修正を行う既存データディレクトリ\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=DIRECTORY 同期元とするデータディレクトリ\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR 同期元とするサーバ\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run 修正を始める前に停止する\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr " -N, --no-sync 変更のディスクへの安全な書き出しを待機しない\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress 進捗メッセージを出力\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf レプリケーションのための設定を書き込む\n"
+" (--source-server が必要となります)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug 多量のデバッグメッセージを出力\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown 非クリーンシャットダウン後の修正を自動で行わない\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version バージョン情報を表示して終了\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help このヘルプを表示して終了\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"バグは<%s>に報告してください。\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "%s ホームページ: <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "詳細は\"%s --help\"を実行してください。\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "ソースが指定されていません(--source-pgdata または --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "--source-pgdataか--source-server はいずれか一方のみ指定可能です"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "ターゲットデータディレクトリが指定されていません(--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "--write-recovery-confにソースサーバ情報(--source-server)が指定されていません"
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr " コマンドライン引数が多すぎます(先頭は\"%s\")"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "\"root\"では実行できません"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "PostgreSQLのスーパユーザで%sを実行しなければなりません\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "ディレクトリ\"%s\"の権限を読み取れませんでした: %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "ソースとターゲットのクラスタが同一タイムライン上にあります"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "タイムライン%3$uのWAL位置%1$X/%2$Xで両サーバが分岐しています"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "巻き戻しは必要ありません"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "タイムライン%3$uの%1$X/%2$Xにある最新の共通チェックポイントから巻き戻しています"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "ソースファイルリストを読み込んでいます"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "ターゲットファイルリストを読み込んでいます"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "ターゲットでWALを読み込んでいます"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "%lu MBコピーする必要があります(ソースディレクトリの合計サイズは%lu MBです)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "backup labelを作成して制御ファイルを更新しています"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "ターゲットデータディレクトリを同期しています"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "完了!"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "ソースクラスタとターゲットクラスタは異なるシステムのものです"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "クラスタは、このバージョンのpg_rewindとの互換性がありません"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "ターゲットサーバはデータチェックサムを利用している、または\"wal_log_hints = on\"である必要があります"
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "ターゲットサーバはきれいにシャットダウンされていなければなりません"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "ソースデータディレクトリはきれいにシャットダウンされていなければなりません"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) コピーしました"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "不正な制御ファイル"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "ソースクラスタとターゲットクラスタのタイムラインの共通の祖先を見つけられません"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "バックアップラベルのバッファが小さすぎます"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "想定外の制御ファイルCRCです"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "想定外の制御ファイルのサイズ%d、想定は%d"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "WALセグメントのサイズ指定は1MBと1GBの間の2の累乗でなければなりません、しかしコントロールファイルでは%dバイトとなっています"
+msgstr[1] "WALセグメントのサイズ指定は1MBと1GBの間の2の累乗でなければなりません、しかしコントロールファイルでは%dバイトとなっています"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"%2$sには\"%1$s\"プログラムが必要ですが、\"%3$s\"と同じディレクトリ\n"
+"にありませんでした。\n"
+"インストール状況を確認してください。"
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"\"%2$s\"がプログラム\"%1$s\"を見つけましたが、これは%3$sと同じ\n"
+"バージョンではありませんでした。\n"
+"インストール状況を確認してください。"
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "ターゲットクラスタでrestore_commandが設定されていません"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "ターゲットサーバに対して\"%s\"を実行してクラッシュリカバリを完了させます"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "ターゲットクラスタでのpostgresコマンドのシングルユーザモード実行に失敗しました"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "コマンド: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "履歴ファイル内の構文エラー: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "数字のタイムラインIDを想定しました。"
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "先行書き込みログの切り替え点の場所があるはずでした。"
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "履歴ファイル内の不正なデータ: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "タイムラインIDは昇順でなければなりません"
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "履歴ファイル内の無効なデータ"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "タイムラインIDは子のタイムラインIDより小さくなければなりません。"
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "%X/%Xのレコードオフセットが無効です"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "%X/%Xではcontrecordが必要です"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "%X/%Xのレコード長が無効です:長さは%uである必要がありますが、長さは%uでした"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "%2$X/%3$Xのレコード長%1$uが大きすぎます"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "%X/%Xで contrecord フラグがありません"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "%2$X/%3$Xのcontrecordの長さ %1$u が無効です"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "%2$X/%3$XのリソースマネージャID %1$uが無効です"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "直前のリンク%1$X/%2$Xが不正なレコードが%3$X/%4$Xにあります"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "%X/%Xのレコード内のリソースマネージャデータのチェックサムが不正です"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "ログセグメント%2$s、オフセット%3$uのマジックナンバー%1$04Xは無効です"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "ログセグメント %2$s、オフセット %3$u の情報ビット %1$04X は無効です"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "WALファイルは異なるデータベースシステム由来のものです: WALファイルのデータベースシステム識別子は %lluで、pg_control におけるデータベースシステム識別子は %lluです"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのセグメントサイズが正しくありません"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのXLOG_BLCKSZが正しくありません"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "ログセグメント%3$s、オフセット%4$uのページアドレス%1$X/%2$Xは想定外です"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "ログセグメント%3$s、オフセット%4$uの時系列ID %1$u(%2$uの後)は順序に従っていません"
+
+#: xlogreader.c:1252
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "block_id %uが%X/%Xで無効です"
+
+#: xlogreader.c:1275
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATAが設定されていますが、%X/%Xにデータがありません"
+
+#: xlogreader.c:1282
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATAが設定されていませんが、%2$X/%3$Xのデータ長は%1$u"
+
+#: xlogreader.c:1318
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLEが設定されていますが、%4$X/%5$Xでホールオフセット%1$u、長さ%2$u、ブロックイメージ長%3$u"
+
+#: xlogreader.c:1334
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLEが設定されていませんが、%3$X/%4$Xにホールオフセット%1$u、長さ%2$u"
+
+#: xlogreader.c:1349
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSEDが設定されていますが、%2$X/%3$Xにおいてブロックイメージ長が%1$u"
+
+#: xlogreader.c:1364
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLEもBKPIMAGE_IS_COMPRESSEDも設定されていませんが、%2$X/%3$Xにおいてブロックイメージ長が%1$u"
+
+#: xlogreader.c:1380
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_RELが設定されていますが、%X/%Xにおいて以前のリレーションがありません"
+
+#: xlogreader.c:1392
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "%2$X/%3$Xにおけるblock_id %1$uが無効です"
+
+#: xlogreader.c:1481
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "%X/%Xのレコードのサイズが無効です"
+
+#: xlogreader.c:1570
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "%X/%X、ブロック %d での圧縮イメージが無効です"
+
+#~ msgid "could not create temporary table: %s"
+#~ msgstr "一時テーブルを作成できませんでした: %s"
+
+#~ msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
+#~ msgstr "WAL ファイルは異なるデータベースシステム由来のものです: ページヘッダーのXLOG_SEG_SIZEが正しくありません"
+
+#~ msgid "Timeline IDs must be less than child timeline's ID.\n"
+#~ msgstr "時系列IDは副時系列IDより小さくなければなりません。\n"
+
+#~ msgid "Timeline IDs must be in increasing sequence.\n"
+#~ msgstr "時系列IDは昇順の並びでなければなりません\n"
+
+#~ msgid "invalid data in history file: %s\n"
+#~ msgstr "履歴ファイル内の無効なデータ: %s\n"
+
+#~ msgid "Expected a transaction log switchpoint location.\n"
+#~ msgstr "トランザクションログの切替えポイントを想定しています。\n"
+
+#~ msgid "Expected a numeric timeline ID.\n"
+#~ msgstr "数字の時系列IDを想定しました。\n"
+
+#~ msgid "syntax error in history file: %s\n"
+#~ msgstr "履歴ファイル内の構文エラー: %s\n"
+
+#~ msgid "sync of target directory failed\n"
+#~ msgstr "ターゲットディレクトリの同期が失敗しました\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "\"%s\"がプログラム \"initdb\" を見つけましたが、これは%sと同じ\n"
+#~ "バージョンではありませんでした。\n"
+#~ "インストレーションを検査してください。\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "%sには \"initdb\" プログラムが必要ですが、\"%s\"と同じディレクトリ\n"
+#~ "にありませんでした。\n"
+#~ "インストール状況を確認してください。\n"
+
+#~ msgid "%d: %X/%X - %X/%X\n"
+#~ msgstr "%d: %X/%X - %X/%X\n"
+
+#~ msgid "Target timeline history:\n"
+#~ msgstr "ターゲットタイムラインの履歴:\n"
+
+#~ msgid "Source timeline history:\n"
+#~ msgstr "ソースタイムラインの履歴\n"
+
+#~ msgid "could not read from file \"%s\": %s\n"
+#~ msgstr "ファイル\"%s\"を読み込めませんでした: %s\n"
+
+#~ msgid "could not seek in file \"%s\": %s\n"
+#~ msgstr "ファイル\"%s\"をシークできませんでした: %s\n"
+
+#~ msgid "could not open file \"%s\": %s\n"
+#~ msgstr "ファイル \"%s\" をオープンできませんでした: %s\n"
+
+#~ msgid "Failure, exiting\n"
+#~ msgstr "失敗しました、終了します\n"
+
+#~ msgid "fetched file \"%s\", length %d\n"
+#~ msgstr "フェッチしたファイル \"%s\",長さ %d\n"
+
+#~ msgid "received chunk for file \"%s\", offset %d, size %d\n"
+#~ msgstr "ファイル \"%s\",オフセット %d, サイズ %dのチャンクを受け取りました\n"
+
+#~ msgid "received null value for chunk for file \"%s\", file has been deleted\n"
+#~ msgstr "ファイル\"%s\"のNULL値のチャンクを受け取りました。ファイルは削除されました。\n"
+
+#~ msgid "getting file chunks\n"
+#~ msgstr "ファイルチャンクの取得\n"
+
+#~ msgid "%s (%s)\n"
+#~ msgstr "%s (%s)\n"
+
+#~ msgid "could not open file \"%s\" for reading: %s\n"
+#~ msgstr "読み取り用のファイル\"%s\"をオープンできませんでした:%s\n"
+
+#~ msgid "could not remove symbolic link \"%s\": %s\n"
+#~ msgstr "シンボリックリンク \"%s\" を削除できませんでした: %s\n"
+
+#~ msgid "could not remove directory \"%s\": %s\n"
+#~ msgstr "ディレクトリ\"%s\"を削除できませんでした: %s\n"
+
+#~ msgid "could not create directory \"%s\": %s\n"
+#~ msgstr "ディレクトリ\"%s\"を作成できませんでした: %s\n"
+
+#~ msgid "could not truncate file \"%s\" to %u: %s\n"
+#~ msgstr "ファイル \"%s\" を%uに切り詰められませんでした: %s\n"
+
+#~ msgid "could not remove file \"%s\": %s\n"
+#~ msgstr "ファイル\"%s\"を削除できませんでした: %s\n"
+
+#~ msgid "could not write file \"%s\": %s\n"
+#~ msgstr "ファイル\"%s\"に書き込めませんでした: %s\n"
+
+#~ msgid " block %u\n"
+#~ msgstr "ブロック数 %u\n"
+
+#~ msgid "could not close file \"%s\": %s\n"
+#~ msgstr "ファイル \"%s\" をクローズできませんでした: %s\n"
+
+#~ msgid "could not read file \"%s\": %s\n"
+#~ msgstr "ファイル \"%s\" を読み込めませんでした: %s\n"
+
+#~ msgid "could not read directory \"%s\": %s\n"
+#~ msgstr "ディレクトリ\"%s\"を読み取れませんでした: %s\n"
+
+#~ msgid "symbolic link \"%s\" target is too long\n"
+#~ msgstr "シンボリックリンク\"%s\"の参照先は長すぎます\n"
+
+#~ msgid "could not read symbolic link \"%s\": %s\n"
+#~ msgstr "シンボリックリンク \"%s\" を読み込めませんでした: %s\n"
+
+#~ msgid "could not stat file \"%s\": %s\n"
+#~ msgstr "ファイル\"%s\"のstatができませんでした: %s\n"
+
+#~ msgid "could not open directory \"%s\": %s\n"
+#~ msgstr "ディレクトリ\"%s\"をオープンできませんでした: %s\n"
+
+#~ msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
+#~ msgstr "WAL ファイルは異なるデータベースシステム由来ものです: WAL ファイルにおけるデータベースシステムの識別子は %s で、pg_control におけるデータベースシステムの識別子は %s です。"
+
+#~ msgid ""
+#~ "\n"
+#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "不具合は<pgsql-bugs@lists.postgresql.org>まで報告してください。\n"
+
+#~ msgid "cannot create restricted tokens on this platform"
+#~ msgstr "このプラットフォームでは制限付きトークンを作成できません"
diff --git a/src/bin/pg_rewind/po/ko.po b/src/bin/pg_rewind/po/ko.po
new file mode 100644
index 0000000..f0c98d4
--- /dev/null
+++ b/src/bin/pg_rewind/po/ko.po
@@ -0,0 +1,855 @@
+# LANGUAGE message translation file for pg_rewind
+# Copyright (C) 2015 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# Ioseph Kim <ioseph@uri.sarang.net>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 13\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-02-09 20:16+0000\n"
+"PO-Revision-Date: 2020-10-27 14:47+0900\n"
+"Last-Translator: Ioseph Kim <ioseph@uri.sarang.net>\n"
+"Language-Team: Korean <pgsql-kr@postgresql.kr>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: ../../../src/common/logging.c:188
+#, c-format
+msgid "fatal: "
+msgstr "심각: "
+
+#: ../../../src/common/logging.c:195
+#, c-format
+msgid "error: "
+msgstr "오류: "
+
+#: ../../../src/common/logging.c:202
+#, c-format
+msgid "warning: "
+msgstr "경고: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98
+#, c-format
+msgid "out of memory\n"
+msgstr "메모리 부족\n"
+
+#: ../../common/fe_memutils.c:92
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "null 포인터를 복제할 수 없음(내부 오류)\n"
+
+#: ../../common/restricted_token.c:69
+#, c-format
+msgid "cannot create restricted tokens on this platform"
+msgstr "restricted token을 이 운영체제에서는 만들 수 없음"
+
+#: ../../common/restricted_token.c:78
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "프로세스 토큰을 열 수 없음: 오류 코드 %lu"
+
+#: ../../common/restricted_token.c:91
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "SID를 할당할 수 없음: 오류 코드 %lu"
+
+#: ../../common/restricted_token.c:110
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "restricted token을 만들 수 없음: 오류 코드 %lu"
+
+#: ../../common/restricted_token.c:131
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "\"%s\" 명령을 위한 프로세스를 시작할 수 없음: 오류 코드 %lu"
+
+#: ../../common/restricted_token.c:169
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "restricted token을 재실행 할 수 없음: 오류 코드 %lu"
+
+#: ../../common/restricted_token.c:185
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "하위 프로세스의 종료 코드를 구할 수 없음: 오류 코드 %lu"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 열 수 없음: %m"
+
+#: copy_fetch.c:88 filemap.c:187 filemap.c:348
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "\"%s\" 파일의 상태값을 알 수 없음: %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "\"%s\" 심볼릭 링크 파일을 읽을 수 없음: %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "\"%s\" 심볼릭 링크의 대상이 너무 긺"
+
+#: copy_fetch.c:135
+#, c-format
+msgid ""
+"\"%s\" is a symbolic link, but symbolic links are not supported on this "
+"platform"
+msgstr ""
+"\"%s\" 파일은 심볼릭 링크 파일이지만 이 운영체제는 심볼릭 링크 파일을 지원하"
+"지 않음"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 읽을 수 없음: %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 닫을 수 없음: %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "\"%s\" 원본 파일을 열 수 없음: %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "원본 파일에서 seek 작업을 할 수 없음: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:314
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "\"%s\" 파일을 읽을 수 없음: %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "\"%s\" 파일을 읽는 중 예상치 못한 EOF"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "\"%s\" 파일을 닫을 수 없음: %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "\"%s\" 대상 파일을 열 수 없음: %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "\"%s\" 대상 파일을 닫을 수 없음: %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "\"%s\" 대상 파일에서 seek 작업을 할 수 없음: %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "\"%s\" 파일 쓰기 실패: %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "일반 파일에 대한 잘못 된 작업 (CREATE)"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "\"%s\" 파일을 삭제할 수 없음: %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "트랙잭션을 위한 \"%s\" 파일을 열 수 없음: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "\"%s\" 파일을 %u 크기로 정리할 수 없음: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 만들 수 없음: %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리를 삭제할 수 없음: %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "\"%s\"에 대한 심볼릭 링크를 만들 수 없음: %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "\"%s\" 심벌릭 링크를 삭제할 수 없음: %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "\"%s\" 파일 일기 모드로 열기 실패: %m"
+
+#: file_ops.c:314 parsexlog.c:316
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "\"%s\" 파일을 읽을 수 없음: %d 읽음, 전체 %zu"
+
+#: filemap.c:179
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "\"%s\" 자료 파일은 일반 파일이 아님"
+
+#: filemap.c:201
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" 디렉터리가 아님"
+
+#: filemap.c:224
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" 심볼릭 링크가 아님"
+
+#: filemap.c:236
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" 일반 파일이 아님"
+
+#: filemap.c:360
+#, c-format
+msgid "source file list is empty"
+msgstr "원본 파일 목록이 비었음"
+
+#: filemap.c:475
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "디텍터리나 심볼릭 링크 \"%s\" 의 페이지 변경 정보가 잘못 됨"
+
+#: libpq_fetch.c:52
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "서버 접속 실패: %s"
+
+#: libpq_fetch.c:56
+#, c-format
+msgid "connected to server"
+msgstr "서버 접속 완료"
+
+#: libpq_fetch.c:65
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "search_path를 지울 수 없음: %s"
+
+#: libpq_fetch.c:77
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "원본 서버는 복구 모드가 아니여야 함"
+
+#: libpq_fetch.c:87
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "원본 서버는 full_page_writes 옵션으로 운영되어야 함"
+
+#: libpq_fetch.c:113 libpq_fetch.c:139
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "원본에서에서 쿼리(%s) 실행 오류: %s"
+
+#: libpq_fetch.c:118
+#, c-format
+msgid "unexpected result set from query"
+msgstr "쿼리 결과가 바르지 않음"
+
+#: libpq_fetch.c:159
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "현재 WAL 삽입 위치를 위한 결과가 잘못됨 : \"%s\""
+
+#: libpq_fetch.c:209
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "파일 목록을 가져올 수 없음: %s"
+
+#: libpq_fetch.c:214
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "파일 목록을 가져온 결과가 잘못 됨"
+
+#: libpq_fetch.c:262
+#, c-format
+msgid "could not send query: %s"
+msgstr "쿼리를 보낼 수 없음: %s"
+
+#: libpq_fetch.c:267
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "libpq 연결을 단일 로우 모드로 지정할 수 없음"
+
+#: libpq_fetch.c:288
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "원격 파일을 가져오는 도중 결과가 잘못됨: %s"
+
+#: libpq_fetch.c:294
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "원격 파일을 가져오는 도중 결과 집합의 크기가 잘못 됨"
+
+#: libpq_fetch.c:300
+#, c-format
+msgid ""
+"unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "원격 파일을 가져오는 도중 결과 집합의 자료형이 잘못 됨: %u %u %u"
+
+#: libpq_fetch.c:308
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "원격 파일을 가져오는 중 예상치 못한 결과 형식 발견"
+
+#: libpq_fetch.c:314
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "원격 파일을 가져오는 도중 결과안에 null 값이 잘못됨"
+
+#: libpq_fetch.c:318
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "원격 파일을 가져오는 도중 결과 길이가 잘못됨"
+
+#: libpq_fetch.c:384
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "\"%s\" 원격 파일을 가져올 수 없음: %s"
+
+#: libpq_fetch.c:389
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "\"%s\" 원격파일을 가져오는 도중 결과 집합이 잘못 됨"
+
+#: libpq_fetch.c:433
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "COPY 자료를 보낼 수 없음: %s"
+
+#: libpq_fetch.c:462
+#, c-format
+msgid "could not send file list: %s"
+msgstr "파일 목록을 보낼 수 없음: %s"
+
+#: libpq_fetch.c:504
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "COPY끝을 보낼 수 없음: %s"
+
+#: libpq_fetch.c:510
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "파일 목록을 보내는 도중 결과가 잘못 됨: %s"
+
+#: parsexlog.c:74 parsexlog.c:127 parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "메모리 부족"
+
+#: parsexlog.c:87 parsexlog.c:133
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "%X/%X 위치에서 WAL 레코드를 읽을 수 없음: %s"
+
+#: parsexlog.c:91 parsexlog.c:136
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "%X/%X 위치에서 WAL 레코드를 읽을 수 없음"
+
+#: parsexlog.c:197
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "%X/%X 위치에서 이전 WAL 레코드를 찾을 수 없음: %s"
+
+#: parsexlog.c:201
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "%X/%X 위치에서 이전 WAL 레코드를 찾을 수 없음"
+
+#: parsexlog.c:292
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "\"%s\" 파일을 열 수 없음: %m"
+
+#: parsexlog.c:305
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "\"%s\" 파일에서 seek 작업을 할 수 없음: %m"
+
+#: parsexlog.c:385
+#, c-format
+msgid ""
+"WAL record modifies a relation, but record type is not recognized: lsn: %X/"
+"%X, rmgr: %s, info: %02X"
+msgstr ""
+"WAL 레코드가 릴레이션을 변경하려고 하지만, 레코드 형태가 올바르지 않음\n"
+"lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:72
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s 프로그램은 PostgreSQL 한 클러스터에서 다른 클러스터로 재동기화 하는 도구입"
+"니다.\n"
+"\n"
+
+#: pg_rewind.c:73
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"사용법:\n"
+" %s [옵션]...\n"
+"\n"
+
+#: pg_rewind.c:74
+#, c-format
+msgid "Options:\n"
+msgstr "옵션들:\n"
+
+#: pg_rewind.c:75
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=디렉터리 변경하려는 데이터 디렉터리\n"
+
+#: pg_rewind.c:76
+#, c-format
+msgid ""
+" --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=디렉터리 동기화 원본이 되는 데이터 디렉터리\n"
+
+#: pg_rewind.c:77
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=연결문자열 원본 서버 접속 정보\n"
+
+#: pg_rewind.c:78
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run 변경 작업 전에 멈춤(검사, 확인용)\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync 작업 완료 뒤 디스크 동기화 작업을 하지 않"
+"음\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress 진행 과정 메시지를 보여줌\n"
+
+#: pg_rewind.c:82
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug 디버그 메시지를 보여줌\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid ""
+" -V, --version output version information, then exit\n"
+msgstr " -V, --version 버전 정보를 보여주고 마침\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help 이 도움말을 보여주고 마침\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+msgstr ""
+"\n"
+"오류보고: <pgsql-bugs@lists.postgresql.org>.\n"
+
+#: pg_rewind.c:142 pg_rewind.c:178 pg_rewind.c:185 pg_rewind.c:192
+#: pg_rewind.c:200
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "자제한 사항은 \"%s --help\" 명령으로 살펴보십시오.\n"
+
+#: pg_rewind.c:177
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr ""
+"원본을 지정하지 않았음 (--source-pgdata 또는 --source-server 옵션을 지정 해"
+"야 함)"
+
+#: pg_rewind.c:184
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "--source-pgdata 또는 --source-server 옵션 중 하나만 지정해야 함"
+
+#: pg_rewind.c:191
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "대상 데이터 디렉토리가 지정되지 않았음 (--target-pgdata 옵션 사용)"
+
+#: pg_rewind.c:198
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "너무 많은 명령행 인수를 지정했습니다. (처음 \"%s\")"
+
+#: pg_rewind.c:213
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "\"root\" 계정으로는 실행 할 수 없음"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "PostgreSQL superuser로 %s 프로그램을 실행하십시오.\n"
+
+#: pg_rewind.c:225
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "\"%s\" 디렉터리 읽기 권한 없음: %m"
+
+#: pg_rewind.c:256
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "원본과 대상 클러스터의 타임라인이 같음"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "서버 분기 WAL 위치: %X/%X, 타임라인 %u"
+
+#: pg_rewind.c:299
+#, c-format
+msgid "no rewind required"
+msgstr "되감을 필요 없음"
+
+#: pg_rewind.c:306
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "재동기화 시작함, 마지막 체크포인트 위치 %X/%X, 타임라인 %u"
+
+#: pg_rewind.c:315
+#, c-format
+msgid "reading source file list"
+msgstr "원본 파일 목록 읽는 중"
+
+#: pg_rewind.c:318
+#, c-format
+msgid "reading target file list"
+msgstr "대상 파일 목록 읽는 중"
+
+#: pg_rewind.c:329
+#, c-format
+msgid "reading WAL in target"
+msgstr "대상 서버에서 WAL 읽는 중"
+
+#: pg_rewind.c:346
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "복사를 위해서 %lu MB 필요함 (원본 디렉토리 전체 크기는 %lu MB)"
+
+#: pg_rewind.c:365
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "백업 라벨을 만들고, 컨트롤 파일을 갱신 중"
+
+#: pg_rewind.c:395
+#, c-format
+msgid "syncing target data directory"
+msgstr "대상 데이터 디렉터리 동기화 중"
+
+#: pg_rewind.c:398
+#, c-format
+msgid "Done!"
+msgstr "완료!"
+
+#: pg_rewind.c:410
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "원본과 대상 클러스터가 서로 다른 시스템임"
+
+#: pg_rewind.c:418
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "해당 클러스터는 이 pg_rewind 버전으로 작업할 수 없음"
+
+#: pg_rewind.c:428
+#, c-format
+msgid ""
+"target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr ""
+"대상 서버의 데이터 클러스터가 데이터 체크섬 기능을 켰거나, \"wal_log_hints "
+"= on\" 설정이 되어야 함"
+
+#: pg_rewind.c:439
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "대상 서버는 정상 종료되어야 함"
+
+#: pg_rewind.c:449
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "원본 데이터 디렉토리는 정상적으로 종료되어야 함"
+
+#: pg_rewind.c:498
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) 복사됨"
+
+#: pg_rewind.c:559
+#, c-format
+msgid "invalid control file"
+msgstr "잘못된 컨트롤 파일"
+
+#: pg_rewind.c:643
+#, c-format
+msgid ""
+"could not find common ancestor of the source and target cluster's timelines"
+msgstr "원본과 대상 서버의 공통된 상위 타임라인을 찾을 수 없음"
+
+#: pg_rewind.c:684
+#, c-format
+msgid "backup label buffer too small"
+msgstr "백업 라벨 버퍼가 너무 작음"
+
+#: pg_rewind.c:707
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "컨트롤 파일 CRC 오류"
+
+#: pg_rewind.c:717
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "컨트롤 파일의 크기가 %d 로 비정상, 정상값 %d"
+
+#: pg_rewind.c:726
+#, c-format
+msgid ""
+"WAL segment size must be a power of two between 1 MB and 1 GB, but the "
+"control file specifies %d byte"
+msgid_plural ""
+"WAL segment size must be a power of two between 1 MB and 1 GB, but the "
+"control file specifies %d bytes"
+msgstr[0] ""
+"WAL 조각 파일은 1MB부터 1GB 사이 2^n 크기여야 하지만, 컨트롤 파일에는 %d 바이"
+"트로 지정되었음"
+
+#: timeline.c:76 timeline.c:82
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "히스토리 파일에서 문법오류: %s"
+
+#: timeline.c:77
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "숫자 타임라인 ID가 필요합니다."
+
+#: timeline.c:83
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "트랜잭션 로그 전환 위치 값이 있어야 함"
+
+#: timeline.c:88
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "작업내역 파일에 잘못된 자료가 있음: %s"
+
+#: timeline.c:89
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "타임라인 ID 값은 그 값이 증가하는 순번값이어야합니다."
+
+#: timeline.c:109
+#, c-format
+msgid "invalid data in history file"
+msgstr "내역 파일에 잘못된 자료가 있음"
+
+#: timeline.c:110
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "타임라인 ID는 하위 타임라인 ID보다 작아야 합니다."
+
+#: xlogreader.c:299
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "잘못된 레코드 위치: %X/%X"
+
+#: xlogreader.c:307
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "%X/%X에서 contrecord를 필요로 함"
+
+#: xlogreader.c:348 xlogreader.c:645
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "잘못된 레코드 길이: %X/%X, 기대값 %u, 실재값 %u"
+
+#: xlogreader.c:372
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "너무 긴 길이(%u)의 레코드가 %X/%X에 있음"
+
+#: xlogreader.c:404
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "%X/%X 위치에 contrecord 플래그가 없음"
+
+#: xlogreader.c:417
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "잘못된 contrecord 길이 %u, 위치 %X/%X"
+
+#: xlogreader.c:653
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "잘못된 자원 관리 ID %u, 위치: %X/%X"
+
+#: xlogreader.c:667 xlogreader.c:684
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "레코드의 잘못된 프리링크 %X/%X, 해당 레코드 %X/%X"
+
+#: xlogreader.c:721
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "잘못된 자원관리자 데이터 체크섬, 위치: %X/%X 레코드"
+
+#: xlogreader.c:758
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "%04X 매직 번호가 잘못됨, 로그 파일 %s, 위치 %u"
+
+#: xlogreader.c:772 xlogreader.c:823
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "잘못된 정보 비트 %04X, 로그 파일 %s, 위치 %u"
+
+#: xlogreader.c:798
+#, c-format
+msgid ""
+"WAL file is from different database system: WAL file database system "
+"identifier is %s, pg_control database system identifier is %s"
+msgstr ""
+"WAL 파일이 다른 시스템의 것입니다. WAL 파일의 시스템 식별자는 %s, pg_control "
+"의 식별자는 %s"
+
+#: xlogreader.c:805
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect segment size in page "
+"header"
+msgstr ""
+"WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더에 지정된 값이 잘"
+"못된 조각 크기임"
+
+#: xlogreader.c:811
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect XLOG_BLCKSZ in page "
+"header"
+msgstr ""
+"WAL 파일이 다른 데이터베이스 시스템의 것입니다: 페이지 헤더의 XLOG_BLCKSZ 값"
+"이 바르지 않음"
+
+#: xlogreader.c:842
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "잘못된 페이지 주소 %X/%X, 로그 파일 %s, 위치 %u"
+
+#: xlogreader.c:867
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "타임라인 범위 벗어남 %u (이전 번호 %u), 로그 파일 %s, 위치 %u"
+
+#: xlogreader.c:1112
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "%u block_id는 범위를 벗어남, 위치 %X/%X"
+
+#: xlogreader.c:1135
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA 지정했지만, %X/%X 에 자료가 없음"
+
+#: xlogreader.c:1142
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA 지정 않았지만, %u 길이의 자료가 있음, 위치 %X/%X"
+
+#: xlogreader.c:1178
+#, c-format
+msgid ""
+"BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at "
+"%X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE 설정이 되어 있지만, 옵셋: %u, 길이: %u, 블록 이미지 길이: "
+"%u, 대상: %X/%X"
+
+#: xlogreader.c:1194
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE 설정이 안되어 있지만, 옵셋: %u, 길이: %u, 대상: %X/%X"
+
+#: xlogreader.c:1209
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_IS_COMPRESSED 설정이 되어 있지만, 블록 이미지 길이: %u, 대상: %X/%X"
+
+#: xlogreader.c:1224
+#, c-format
+msgid ""
+"neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image "
+"length is %u at %X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE, BKPIMAGE_IS_COMPRESSED 지정 안되어 있으나, 블록 이미지 길"
+"이는 %u, 대상: %X/%X"
+
+#: xlogreader.c:1240
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL 설정이 되어 있지만, %X/%X 에 이전 릴레이션 없음"
+
+#: xlogreader.c:1252
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "잘못된 block_id %u, 위치 %X/%X"
+
+#: xlogreader.c:1341
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "잘못된 레코드 길이, 위치 %X/%X"
+
+#: xlogreader.c:1430
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "잘못된 압축 이미지, 위치 %X/%X, 블록 %d"
diff --git a/src/bin/pg_rewind/po/ru.po b/src/bin/pg_rewind/po/ru.po
new file mode 100644
index 0000000..88f1f4c
--- /dev/null
+++ b/src/bin/pg_rewind/po/ru.po
@@ -0,0 +1,1089 @@
+# Russian message translation file for pg_rewind
+# Copyright (C) 2015-2016 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# Alexander Lakhin <exclusion@gmail.com>, 2015-2017, 2018, 2019, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL current)\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-12-11 07:48+0300\n"
+"PO-Revision-Date: 2020-11-09 08:33+0300\n"
+"Last-Translator: Alexander Lakhin <exclusion@gmail.com>\n"
+"Language-Team: Russian <pgsql-ru-general@postgresql.org>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "важно: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "ошибка: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "предупреждение: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "нехватка памяти\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "попытка дублирования нулевого указателя (внутренняя ошибка)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "не удалось загрузить библиотеку \"%s\" (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "в этой ОС нельзя создавать ограниченные маркеры (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "не удалось открыть маркер процесса (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "не удалось подготовить структуры SID (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "не удалось создать ограниченный маркер (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "не удалось запустить процесс для команды \"%s\" (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "не удалось перезапуститься с ограниченным маркером (код ошибки: %lu)"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "не удалось получить код выхода от подпроцесса (код ошибки: %lu)"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "нельзя использовать restore_command со знаком подстановки %%r"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "неподходящий размер файла \"%s\": %lu вместо %lu байт"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "не удалось открыть файл \"%s\", восстановленный из архива: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "не удалось получить информацию о файле \"%s\": %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "ошибка при выполнении restore_command: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "восстановить файл \"%s\" из архива не удалось"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:76 parsexlog.c:134
+#: parsexlog.c:194
+#, c-format
+msgid "out of memory"
+msgstr "нехватка памяти"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:307
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "не удалось открыть файл \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "не удалось записать в файл \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "не удалось создать файл \"%s\": %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "не удалось открыть каталог \"%s\": %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "не удалось прочитать символическую ссылку \"%s\": %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "целевой путь символической ссылки \"%s\" слишком длинный"
+
+#: copy_fetch.c:135
+#, c-format
+msgid ""
+"\"%s\" is a symbolic link, but symbolic links are not supported on this "
+"platform"
+msgstr ""
+"\"%s\" — символическая ссылка, но в этой ОС символические ссылки не "
+"поддерживаются"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "не удалось прочитать каталог \"%s\": %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "не удалось закрыть каталог \"%s\": %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "не удалось открыть исходный файл \"%s\": %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "не удалось переместиться в исходном файле: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:345
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "не удалось прочитать файл \"%s\": %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "неожиданный конец файла при чтении \"%s\""
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "не удалось закрыть файл \"%s\": %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "не удалось открыть целевой файл \"%s\": %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "не удалось закрыть целевой файл \"%s\": %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "не удалось переместиться в целевом файле \"%s\": %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "не удалось записать файл \"%s\": %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "неверное действие (CREATE) для обычного файла"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "не удалось стереть файл \"%s\": %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "не удалось открыть файл \"%s\" для усечения: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "не удалось обрезать файл \"%s\" до нужного размера (%u): %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "не удалось создать каталог \"%s\": %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "ошибка при удалении каталога \"%s\": %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "не удалось создать символическую ссылку \"%s\": %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "ошибка при удалении символической ссылки \"%s\": %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "не удалось открыть файл \"%s\" для чтения: %m"
+
+#: file_ops.c:314 parsexlog.c:347
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "не удалось прочитать файл \"%s\" (прочитано байт: %d из %zu)"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "файл данных \"%s\" в источнике не является обычным файлом"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" не является каталогом"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" не является символической ссылкой"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" не является обычным файлом"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "список файлов в источнике пуст"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr ""
+"неожиданная модификация страницы для каталога или символической ссылки \"%s\""
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "%s"
+msgstr "%s"
+
+#: libpq_fetch.c:53
+#, c-format
+msgid "connected to server"
+msgstr "подключение к серверу установлено"
+
+#: libpq_fetch.c:62
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "не удалось очистить search_path: %s"
+
+#: libpq_fetch.c:74
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "исходный сервер должен выйти из режима восстановления"
+
+#: libpq_fetch.c:84
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "на исходном сервере должен быть включён режим full_page_writes"
+
+#: libpq_fetch.c:110
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "ошибка выполнения запроса (%s) на исходном сервере: %s"
+
+#: libpq_fetch.c:115
+#, c-format
+msgid "unexpected result set from query"
+msgstr "неожиданный результат запроса"
+
+#: libpq_fetch.c:136
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "ошибка выполнения запроса (%s) на исходном сервере: %s"
+
+#: libpq_fetch.c:156
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr ""
+"нераспознанный результат \"%s\" вместо текущей позиции добавления в WAL"
+
+#: libpq_fetch.c:206
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "не удалось получить список файлов: %s"
+
+#: libpq_fetch.c:211
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "неожиданный результат при получении списка файлов"
+
+#: libpq_fetch.c:264
+#, c-format
+msgid "could not send query: %s"
+msgstr "не удалось отправить запрос: %s"
+
+#: libpq_fetch.c:269
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "не удалось перевести подключение libpq в однострочный режим"
+
+#: libpq_fetch.c:289
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "неожиданный результат при получении файлов с сервера: %s"
+
+#: libpq_fetch.c:295
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "неожиданный размер набора результатов при получении файлов с сервера"
+
+#: libpq_fetch.c:301
+#, c-format
+msgid ""
+"unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr ""
+"неожиданные типы данных в наборе результатов при получении файлов с сервера: "
+"%u %u %u"
+
+#: libpq_fetch.c:309
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "неожиданный формат результата при получении файлов с сервера"
+
+#: libpq_fetch.c:315
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "неожиданные значения NULL в результате при получении файлов с сервера"
+
+#: libpq_fetch.c:319
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "неожиданная длина результата при получении файлов с сервера"
+
+#: libpq_fetch.c:380
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "не удалось получить с сервера файл \"%s\": %s"
+
+#: libpq_fetch.c:385
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "неожиданный набор результатов при получении файла \"%s\" с сервера"
+
+#: libpq_fetch.c:429
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "не удалось отправить данные COPY: %s"
+
+#: libpq_fetch.c:458
+#, c-format
+msgid "could not send file list: %s"
+msgstr "не удалось отправить список файлов: %s"
+
+#: libpq_fetch.c:500
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "не удалось отправить сообщение о завершении копирования: %s"
+
+#: libpq_fetch.c:506
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "неожиданный результат при передаче списка: %s"
+
+#: parsexlog.c:88 parsexlog.c:141
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "не удалось прочитать запись WAL в позиции %X/%X: %s"
+
+#: parsexlog.c:92 parsexlog.c:144
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "не удалось прочитать запись WAL в позиции %X/%X"
+
+#: parsexlog.c:207
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "не удалось найти предыдущую запись WAL в позиции %X/%X: %s"
+
+#: parsexlog.c:211
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "не удалось найти предыдущую запись WAL в позиции %X/%X"
+
+#: parsexlog.c:336
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "не удалось переместиться в файле \"%s\": %m"
+
+#: parsexlog.c:416
+#, c-format
+msgid ""
+"WAL record modifies a relation, but record type is not recognized: lsn: %X/"
+"%X, rmgr: %s, info: %02X"
+msgstr ""
+"Запись WAL модифицирует отношение, но тип записи не распознан: lsn: %X/%X, "
+"rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s синхронизирует кластер PostgreSQL с другой копией кластера.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Использование:\n"
+" %s [ПАРАМЕТР]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Параметры:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration "
+"to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal использовать для получения файлов WAL из\n"
+" архива команду restore_command из целевой\n"
+" конфигурации\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr ""
+" -D, --target-pgdata=КАТАЛОГ существующий каталог, куда будут записаны "
+"данные\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid ""
+" --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr ""
+" --source-pgdata=КАТАЛОГ исходный каталог, с которым будет проведена "
+"синхронизация\n"
+
+# well-spelled: ПОДКЛ
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr ""
+" --source-server=СТР_ПОДКЛ сервер, с которым будет проведена "
+"синхронизация\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr ""
+" -n, --dry-run остановиться до внесения каких-либо "
+"изменений\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync не ждать завершения сохранения данных на "
+"диске\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress выводить сообщения о ходе процесса\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf записать конфигурацию для репликации\n"
+" (требуется указание --source-server)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr ""
+" --debug выдавать множество отладочных сообщений\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid ""
+" --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr ""
+" --no-ensure-shutdown не исправлять автоматически состояние,\n"
+" возникающее при нештатном отключении\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid ""
+" -V, --version output version information, then exit\n"
+msgstr " -V, --version показать версию и выйти\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help показать эту справку и выйти\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Об ошибках сообщайте по адресу <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "Домашняя страница %s: <%s>\n"
+
+#: pg_rewind.c:160 pg_rewind.c:209 pg_rewind.c:216 pg_rewind.c:223
+#: pg_rewind.c:230 pg_rewind.c:238
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Для дополнительной информации попробуйте \"%s --help\".\n"
+
+#: pg_rewind.c:208
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "источник не указан (требуется --source-pgdata или --source-server)"
+
+#: pg_rewind.c:215
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "указать можно только --source-pgdata либо --source-server"
+
+#: pg_rewind.c:222
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "целевой каталог данных не указан (--target-pgdata)"
+
+#: pg_rewind.c:229
+#, c-format
+msgid ""
+"no source server information (--source-server) specified for --write-"
+"recovery-conf"
+msgstr ""
+"отсутствует информация об исходном сервере (--source-server) для --write-"
+"recovery-conf"
+
+#: pg_rewind.c:236
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "слишком много аргументов командной строки (первый: \"%s\")"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "программу не должен запускать root"
+
+#: pg_rewind.c:252
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Запускать %s нужно от имени суперпользователя PostgreSQL.\n"
+
+#: pg_rewind.c:263
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "не удалось считать права на каталог \"%s\": %m"
+
+#: pg_rewind.c:317
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "исходный и целевой кластер уже на одной линии времени"
+
+#: pg_rewind.c:326
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "серверы разошлись в позиции WAL %X/%X на линии времени %u"
+
+#: pg_rewind.c:374
+#, c-format
+msgid "no rewind required"
+msgstr "перемотка не требуется"
+
+#: pg_rewind.c:383
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr ""
+"перемотка от последней общей контрольной точки в позиции %X/%X на линии "
+"времени %u"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading source file list"
+msgstr "чтение списка исходных файлов"
+
+#: pg_rewind.c:395
+#, c-format
+msgid "reading target file list"
+msgstr "чтение списка целевых файлов"
+
+#: pg_rewind.c:404
+#, c-format
+msgid "reading WAL in target"
+msgstr "чтение WAL в целевом кластере"
+
+#: pg_rewind.c:421
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "требуется скопировать %lu МБ (общий размер исходного каталога: %lu МБ)"
+
+#: pg_rewind.c:439
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "создание метки копии и модификация управляющего файла"
+
+#: pg_rewind.c:469
+#, c-format
+msgid "syncing target data directory"
+msgstr "синхронизация целевого каталога данных"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "Done!"
+msgstr "Готово!"
+
+#: pg_rewind.c:488
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "исходный и целевой кластеры относятся к разным системам"
+
+#: pg_rewind.c:496
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "кластеры несовместимы с этой версией pg_rewind"
+
+#: pg_rewind.c:506
+#, c-format
+msgid ""
+"target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr ""
+"на целевом сервере должны быть контрольные суммы данных или \"wal_log_hints "
+"= on\""
+
+#: pg_rewind.c:517
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "целевой сервер должен быть выключен штатно"
+
+#: pg_rewind.c:527
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "работа с исходным каталогом данных должна быть завершена штатно"
+
+#: pg_rewind.c:579
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s КБ (%d%%) скопировано"
+
+#: pg_rewind.c:642
+#, c-format
+msgid "invalid control file"
+msgstr "неверный управляющий файл"
+
+#: pg_rewind.c:726
+#, c-format
+msgid ""
+"could not find common ancestor of the source and target cluster's timelines"
+msgstr ""
+"не удалось найти общего предка линий времени исходного и целевого кластеров"
+
+#: pg_rewind.c:767
+#, c-format
+msgid "backup label buffer too small"
+msgstr "буфер для метки копии слишком мал"
+
+#: pg_rewind.c:790
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "неверная контрольная сумма управляющего файла"
+
+#: pg_rewind.c:800
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "неверный размер управляющего файла (%d), ожидалось: %d"
+
+#: pg_rewind.c:809
+#, c-format
+msgid ""
+"WAL segment size must be a power of two between 1 MB and 1 GB, but the "
+"control file specifies %d byte"
+msgid_plural ""
+"WAL segment size must be a power of two between 1 MB and 1 GB, but the "
+"control file specifies %d bytes"
+msgstr[0] ""
+"размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 "
+"ГБ, но в управляющем файле указано значение: %d"
+msgstr[1] ""
+"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 "
+"ГБ, но в управляющем файле указано значение: %d"
+msgstr[2] ""
+"Размер сегмента WAL должен задаваться степенью 2 в интервале от 1 МБ до 1 "
+"ГБ, но в управляющем файле указано значение: %d"
+
+#: pg_rewind.c:866 pg_rewind.c:924
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"Программа \"%s\" нужна для %s, но она не найдена\n"
+"в каталоге \"%s\".\n"
+"Проверьте правильность установки СУБД."
+
+#: pg_rewind.c:871 pg_rewind.c:929
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"Программа \"%s\" найдена программой \"%s\",\n"
+"но её версия отличается от версии %s.\n"
+"Проверьте правильность установки СУБД."
+
+#: pg_rewind.c:892
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "команда restore_command в целевом кластере не определена"
+
+#: pg_rewind.c:935
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr ""
+"выполнение \"%s\" для восстановления согласованности на целевом сервере"
+
+#: pg_rewind.c:955
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr ""
+"не удалось запустить postgres в целевом кластере в однопользовательском "
+"режиме"
+
+#: pg_rewind.c:956
+#, c-format
+msgid "Command was: %s"
+msgstr "Выполнялась команда: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "синтаксическая ошибка в файле истории: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Ожидается числовой идентификатор линии времени."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Ожидается положение точки переключения журнала предзаписи."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "неверные данные в файле истории: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Идентификаторы линий времени должны возрастать."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "неверные данные в файле истории"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr ""
+"Идентификаторы линий времени должны быть меньше идентификатора линии-потомка."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "неверное смещение записи: %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "по смещению %X/%X запрошено продолжение записи"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "неверная длина записи по смещению %X/%X: ожидалось %u, получено %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "длина записи %u по смещению %X/%X слишком велика"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "нет флага contrecord в позиции %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "неверная длина contrecord (%u) в позиции %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "неверный ID менеджера ресурсов %u по смещению %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "запись с неверной ссылкой назад %X/%X по смещению %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr ""
+"некорректная контрольная сумма данных менеджера ресурсов в записи по "
+"смещению %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "неверное магическое число %04X в сегменте журнала %s, смещение %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "неверные информационные биты %04X в сегменте журнала %s, смещение %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid ""
+"WAL file is from different database system: WAL file database system "
+"identifier is %llu, pg_control database system identifier is %llu"
+msgstr ""
+"файл WAL принадлежит другой СУБД: в нём указан идентификатор системы БД "
+"%llu, а идентификатор системы pg_control: %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect segment size in page "
+"header"
+msgstr ""
+"файл WAL принадлежит другой СУБД: некорректный размер сегмента в заголовке "
+"страницы"
+
+#: xlogreader.c:851
+#, c-format
+msgid ""
+"WAL file is from different database system: incorrect XLOG_BLCKSZ in page "
+"header"
+msgstr ""
+"файл WAL принадлежит другой СУБД: некорректный XLOG_BLCKSZ в заголовке "
+"страницы"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "неожиданный pageaddr %X/%X в сегменте журнала %s, смещение %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr ""
+"нарушение последовательности ID линии времени %u (после %u) в сегменте "
+"журнала %s, смещение %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "идентификатор блока %u идёт не по порядку в позиции %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA установлен, но данных в позиции %X/%X нет"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr ""
+"BKPBLOCK_HAS_DATA не установлен, но длина данных равна %u в позиции %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid ""
+"BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at "
+"%X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE установлен, но для пропуска заданы смещение %u и длина %u "
+"при длине образа блока %u в позиции %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_HAS_HOLE не установлен, но для пропуска заданы смещение %u и длина "
+"%u в позиции %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr ""
+"BKPIMAGE_IS_COMPRESSED установлен, но длина образа блока равна %u в позиции "
+"%X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid ""
+"neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image "
+"length is %u at %X/%X"
+msgstr ""
+"ни BKPIMAGE_HAS_HOLE, ни BKPIMAGE_IS_COMPRESSED не установлены, но длина "
+"образа блока равна %u в позиции %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr ""
+"BKPBLOCK_SAME_REL установлен, но предыдущее значение не задано в позиции %X/"
+"%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "неверный идентификатор блока %u в позиции %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "запись с неверной длиной в позиции %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "неверный сжатый образ в позиции %X/%X, блок %d"
+
+#~ msgid "could not connect to server: %s"
+#~ msgstr "не удалось подключиться к серверу: %s"
+
+#~ msgid ""
+#~ "\n"
+#~ "Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Об ошибках сообщайте по адресу <pgsql-bugs@lists.postgresql.org>.\n"
+
+#~ msgid " block %u\n"
+#~ msgstr " блок %u\n"
+
+#~ msgid "entry \"%s\" excluded from source file list\n"
+#~ msgstr "\"%s\" исключён из списка исходных файлов\n"
+
+#~ msgid "entry \"%s\" excluded from target file list\n"
+#~ msgstr "\"%s\" исключён из списка целевых файлов\n"
+
+#~ msgid "%s (%s)\n"
+#~ msgstr "%s (%s)\n"
+
+#, fuzzy
+#~ msgid "could not set up connection context: %s"
+#~ msgstr "не удалось настроить контекст подключения: %s"
+
+#~ msgid "getting file chunks\n"
+#~ msgstr "получение сегментов файлов\n"
+
+#~ msgid ""
+#~ "received null value for chunk for file \"%s\", file has been deleted\n"
+#~ msgstr ""
+#~ "для файла \"%s\" вместо сегмента получено NULL-значение, файл удалён\n"
+
+#~ msgid "received chunk for file \"%s\", offset %s, size %d\n"
+#~ msgstr "получен сегмент файла \"%s\": смещение %s, размер %d\n"
+
+#~ msgid "fetched file \"%s\", length %d\n"
+#~ msgstr "получен файл \"%s\", длина %d\n"
+
+#, fuzzy
+#~ msgid "could not create temporary table: %s"
+#~ msgstr "не удалось создать временную таблицу: %s"
+
+#~ msgid "Failure, exiting\n"
+#~ msgstr "Ошибка, выполняется выход\n"
+
+#~ msgid "could not read from file \"%s\": %s\n"
+#~ msgstr "не удалось прочитать файл \"%s\": %s\n"
+
+#~ msgid "Source timeline history:\n"
+#~ msgstr "История линии времени источника:\n"
+
+#~ msgid "Target timeline history:\n"
+#~ msgstr "История линии времени получателя:\n"
+
+#~ msgid "%d: %X/%X - %X/%X\n"
+#~ msgstr "%d: %X/%X - %X/%X\n"
+
+#~ msgid "sync of target directory failed\n"
+#~ msgstr "сбой синхронизации целевого каталога\n"
+
+#~ msgid ""
+#~ "WAL file is from different database system: incorrect XLOG_SEG_SIZE in "
+#~ "page header"
+#~ msgstr ""
+#~ "файл WAL принадлежит другой СУБД: некорректный XLOG_SEG_SIZE в заголовке "
+#~ "страницы"
diff --git a/src/bin/pg_rewind/po/sv.po b/src/bin/pg_rewind/po/sv.po
new file mode 100644
index 0000000..0df9e35
--- /dev/null
+++ b/src/bin/pg_rewind/po/sv.po
@@ -0,0 +1,973 @@
+# Swedish message translation file for pg_rewind
+# Copyright (C) 2017 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# Dennis Björklund <db@zigo.dhs.org>, 2017, 2018, 2019, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PostgreSQL 13\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-09-16 05:17+0000\n"
+"PO-Revision-Date: 2020-09-16 07:53+0200\n"
+"Last-Translator: Dennis Björklund <db@zigo.dhs.org>\n"
+"Language-Team: Swedish <pgsql-translators@postgresql.org>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "fatalt: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "fel: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "varning: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "slut på minne\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "kan inte duplicera null-pekare (internt fel)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "kunde inte ladda länkbibliotek \"%s\": felkod %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "kan inte skapa token för begränsad åtkomst på denna plattorm: felkod %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "kunde inte öppna process-token: felkod %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "kunde inte allokera SID: felkod %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "kunde inte skapa token för begränsad åtkomst: felkod %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "kunde inte starta process för kommando \"%s\": felkod %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "kunde inte köra igen med token för begränsad åtkomst: felkod %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "kunde inte hämta statuskod för underprocess: felkod %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "kan inte använda restore_command med %%r-platshållare"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "oväntad filstorlek på \"%s\": %lu istället för %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "kunde inte öppna fil \"%s\" återställd från arkiv: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "kunde inte göra stat() på fil \"%s\": %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "restore_command misslyckades: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "kunde inte återställa fil \"%s\" från arkiv"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:73 parsexlog.c:125
+#: parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "slut på minne"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:298
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "kunde inte öppna fil \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "kunde inte skriva till fil \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "kan inte skapa fil \"%s\": %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "kunde inte öppna katalog \"%s\": %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "kan inte läsa symbolisk länk \"%s\": %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "mål för symbolisk länk \"%s\" är för lång"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\" är en symbolisk länk men symboliska länkar stöds inte på denna plattform"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "kunde inte läsa katalog \"%s\": %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "kunde inte stänga katalog \"%s\": %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "kunde inte öppna källfil \"%s\": %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "kunde inte söka i källfil: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:336
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "kunde inte läsa fil \"%s\": %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "oväntad EOF under läsning av fil \"%s\""
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "kunde inte stänga fil \"%s\": %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "kunde inte öppna målfil \"%s\": %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "kunde inte stänga målfil \"%s\": %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "kunde inte söka i målfil \"%s\": %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "kunde inte skriva fil \"%s\": %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "ogiltig aktion (CREATE) för vanlig fil"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "kunde inte ta bort fil \"%s\": %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "kunde inte öppna fil \"%s\" för trunkering: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "kunde inte trunkera fil \"%s\" till %u: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "kunde inte skapa katalog \"%s\": %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "kunde inte ta bort katalog \"%s\": %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "kunde inte skapa en symnbolisk länk vid \"%s\": %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "kan inte ta bort symbolisk länk \"%s\": %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "kunde inte öppna filen \"%s\" för läsning: %m"
+
+#: file_ops.c:314 parsexlog.c:338
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "kunde inte läsa fil \"%s\": läste %d av %zu"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "datafil \"%s\" i källan är inte en vanlig fil"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" är inte en katalog"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" är inte en symbolisk länk"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" är inte en vanlig fil"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "källfillistan är tom"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "oväntad sidmodifiering för katalog eller symbolisk länk \"%s\""
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "kunde inte ansluta till server: %s"
+
+#: libpq_fetch.c:54
+#, c-format
+msgid "connected to server"
+msgstr "ansluten till server"
+
+#: libpq_fetch.c:63
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "kunde inte nollställa search_path: %s"
+
+#: libpq_fetch.c:75
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "källserver får inte vara i återställningsläge"
+
+#: libpq_fetch.c:85
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "full_page_writes måste vara påslagen i källservern"
+
+#: libpq_fetch.c:111
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "fel vid körande av fråga (%s) på källserver: %s"
+
+#: libpq_fetch.c:116
+#, c-format
+msgid "unexpected result set from query"
+msgstr "oväntad resultatmängd från fråga"
+
+#: libpq_fetch.c:137
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "fel vid körande av fråga (%s) i källserver: %s"
+
+#: libpq_fetch.c:157
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "oväntat resultat \"%s\" för nuvarande WAL-insättningsposition"
+
+#: libpq_fetch.c:207
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "kunde inte hämta fillista: %s"
+
+#: libpq_fetch.c:212
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "oväntad resultatmängd vid hämtning av fillista"
+
+#: libpq_fetch.c:265
+#, c-format
+msgid "could not send query: %s"
+msgstr "kunde inte skicka fråga: %s"
+
+#: libpq_fetch.c:270
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "kunde inte sätta libpq-anslutning till enradsläge"
+
+#: libpq_fetch.c:290
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "oväntat resultat vid hämtning av extern fil: %s"
+
+#: libpq_fetch.c:296
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "oväntad resultatmängdstorlek vid hämtning av externa filer"
+
+#: libpq_fetch.c:302
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "oväntade datayper i resultatmängd vid hämtning av externa filer: %u %u %u"
+
+#: libpq_fetch.c:310
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "oväntat resultatformat vid hämtning av externa filer"
+
+#: libpq_fetch.c:316
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "oväntade null-värden i resultat vid hämtning av externa filer"
+
+#: libpq_fetch.c:320
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "oväntad resultatlängd vid hämtning av externa filer"
+
+#: libpq_fetch.c:381
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "kunde inte hämta extern fil \"%s\": %s"
+
+#: libpq_fetch.c:386
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "oväntat resultatmängd vid hämtning av extern fil \"%s\""
+
+#: libpq_fetch.c:430
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "kunde inte skicka COPY-data: %s"
+
+#: libpq_fetch.c:459
+#, c-format
+msgid "could not send file list: %s"
+msgstr "kunde inte skicka fillista: %s"
+
+#: libpq_fetch.c:501
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "kunde inte skicka slut-på-COPY: %s"
+
+#: libpq_fetch.c:507
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "oväntat resultat vid skickande av fillista: %s"
+
+#: parsexlog.c:85 parsexlog.c:132
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "kunde inte läsa WAL-post vid %X/%X: %s"
+
+#: parsexlog.c:89 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "kunde inte läsa WAL-post vid %X/%X"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "kunde inte hitta föregående WAL-post vid %X/%X: %s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "kunde inte hitta förgående WAL-post vid %X/%X"
+
+#: parsexlog.c:327
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "kunde inte söka (seek) i fil \"%s\": %m"
+
+#: parsexlog.c:407
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL-post modifierar en relation, men posttypen känns inte igen: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s resynkroniserar ett PostgreSQL-kluster med en annan kopia av klustret.\n"
+"\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"Användning:\n"
+" %s [FLAGGA]...\n"
+"\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Flaggor:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid ""
+" -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr ""
+" -c, --restore-target-wal använd restore_command i målkonfigurationen\n"
+" för att hämta WAL-filer från arkiv\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=KATALOG existerande datakatalog att modifiera\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=KATALOG källdatakatalog att synkronisera med\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=ANSLSTR källserver att synkronisera med\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run stoppa innan något modifieras\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync vänta inte på att ändingar säkert\n"
+" skrivits till disk\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress skriv ut förloppmeddelanden\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid ""
+" -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr ""
+" -R, --write-recovery-conf\n"
+" skriv konfiguration för replikering\n"
+" (kräver --source-server)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug skriv ut en massa debugmeddelanden\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown ingen automatisk hantering av trasig nedstängning\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version skriv ut versioninformation och avsluta sedan\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help visa denna hjälp och avsluta sedan\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <%s>.\n"
+msgstr ""
+"\n"
+"Rapportera fel till <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "hemsida för %s: <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Försök med \"%s --help\" för mer information.\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "ingen källa angavs (--source-pgdata eller --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "bara en av --source-pgdata och --source-server får anges"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "ingen måldatakatalog angiven (--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "ingen källserverinformation (--source-server) angiven för --write-recovery-conf"
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "för många kommandoradsargument (första är \"%s\")"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "kan inte köras av \"root\""
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Du måste köra %s som PostgreSQL:s superanvändare.\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "kunde inte läsa rättigheter på katalog \"%s\": %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "källa och målkluster är på samma tidslinje"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "servrarna divergerade vid WAL-position %X/%X på tidslinje %u"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "ingen rewind krävs"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "rewind från senaste gemensamma checkpoint vid %X/%X på tidslinje %u"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "läser källfillista"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "läser målfillista"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "läser WAL i målet"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "behöver kopiera %lu MB (total källkatalogstorlek är %lu MB)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "skapar backupetikett och uppdaterar kontrollfil"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "synkar måldatakatalog"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "Klar!"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "källa och målkluster är från olika system"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "klustren är inte kompatibla med denna version av pg_rewind"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "målservern behöver använda antingen datachecksums eller \"wal_log_hints = on\""
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "målserver måste stängas ner utan fel"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "måldatakatalog måste stängas ner utan fel"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) kopierad"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "ogiltig kontrollfil"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "kunde inte finna en gemensam anfader av källa och målklusterets tidslinjer"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "backupetikett-buffer för liten"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "oväntad kontrollfil-CRC"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "oväntad kontrollfilstorlek %d, förväntade %d"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte"
+msgstr[1] "WAL-segmentstorlek måste vara en tvåpotens mellan 1MB och 1GB men kontrollfilen anger %d byte"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid ""
+"The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr ""
+"Programmet \"%s\" behövs av %s men hittades inte i samma\n"
+"katalog som \"%s\".\n"
+"Kontrollera din installation."
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid ""
+"The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr ""
+"Programmet \"%s\" hittades av \"%s\"\n"
+"men är inte av samma version som %s.\n"
+"Kontrollera din installation."
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "restore_command är inte satt i målklustret"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "kör \"%s\" för målservern för att slutföra krashåterställning"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "postgres enanvändarläge misslyckades i målklustret"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "Kommandot var: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "syntaxfel i history-fil: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Förväntade ett numeriskt tidslinje-ID."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Förväntade en write-ahead-logg:s switchpoint-position."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "felaktig data i history-fil: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Tidslinje-ID måste komma i en stigande sekvens."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "ogiltig data i historikfil"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "Tidslinje-ID:er måste vara mindre än barnens tidslinje-ID:er."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "ogiltig postoffset vid %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "contrecord är begärd vid %X/%X"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "ogiltig postlängd vid %X/%X: förväntade %u, fick %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "postlängd %u vid %X/%X är för lång"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "det finns ingen contrecord-flagga vid %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "ogiltig contrecord-längd %u vid %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "ogiltigt resurshanterar-ID %u vid %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "post med inkorrekt prev-link %X/%X vid %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "felaktig resurshanterardatakontrollsumma i post vid %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "felaktigt magiskt nummer %04X i loggsegment %s, offset %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "ogiltiga infobitar %04X i loggsegment %s, offset %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "WAL-fil är från ett annat databassystem: WAL-filens databassystemidentifierare är %llu, pg_control databassystemidentifierare är %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL-fil är från ett annat databassystem: inkorrekt segmentstorlek i sidhuvud"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL-fil är från ett annat databassystem: inkorrekt XLOG_BLCKSZ i sidhuvud"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "oväntad sidadress %X/%X i loggsegment %s, offset %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "ej-i-sekvens för tidslinje-ID %u (efter %u) i loggsegment %s, offset %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "ej-i-sekvens block_id %u vid %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA satt, men ingen data inkluderad vid %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA ej satt, men datalängd är %u vid %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE satt, men håloffset %u längd %u block-image-längd %u vid %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE ej satt, men håloffset %u längd %u vid %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED satt, men block-image-längd %u vid %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "varken BKPIMAGE_HAS_HOLE eller BKPIMAGE_IS_COMPRESSED satt, men block-image-längd är %u vid %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL satt men ingen tidigare rel vid %X/%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "ogiltig block_id %u vid %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "post med ogiltig längd vid %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "ogiltig komprimerad image vid %X/%X, block %d"
+
+#~ msgid "could not load advapi32.dll: error code %lu"
+#~ msgstr "kunde inte ladda advapi32.dll: felkod %lu"
+
+#~ msgid ""
+#~ "The program \"%s\" was found by \"%s\" but was\n"
+#~ "not the same version as %s.\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Programmet \"%s\" hittades av \"%s\"\n"
+#~ "men är inte av samma version som %s.\n"
+#~ "Kontrollera din installation."
+
+#~ msgid ""
+#~ "The program \"%s\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Programmet \"%s\" behövs av %s men hittades inte i samma\n"
+#~ "katalog som \"%s\".\n"
+#~ "Kontrollera din installation."
+
+#~ msgid ""
+#~ "The program \"postgres\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Programmet \"postgres\" hittades av \"%s\",\n"
+#~ "men det är inte byggt i samma version som %s.\n"
+#~ "Kontrollera din installation."
+
+#~ msgid ""
+#~ "The program \"postgres\" is needed by %s but was not found in the\n"
+#~ "same directory as \"%s\".\n"
+#~ "Check your installation."
+#~ msgstr ""
+#~ "Programmet \"postgres\" behövs av %s men kunde inte hittas\n"
+#~ "i samma katalog som \"%s\".\n"
+#~ "Kontrollera din installation."
diff --git a/src/bin/pg_rewind/po/tr.po b/src/bin/pg_rewind/po/tr.po
new file mode 100644
index 0000000..d314931
--- /dev/null
+++ b/src/bin/pg_rewind/po/tr.po
@@ -0,0 +1,966 @@
+# LANGUAGE message translation file for pg_rewind
+# Copyright (C) 2018 PostgreSQL Global Development Group
+# This file is distributed under the same license as the pg_rewind (PostgreSQL) package.
+# Abdullah GÜLNER <agulner@gmail.com>, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 10\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2019-04-26 13:48+0000\n"
+"PO-Revision-Date: 2019-06-12 16:57+0300\n"
+"Last-Translator: Abdullah Gülner\n"
+"Language-Team: \n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.7.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../../../src/fe_utils/logging.c:182
+#, c-format
+msgid "fatal: "
+msgstr "ölümcül (fatal): "
+
+#: ../../../src/fe_utils/logging.c:189
+#, c-format
+msgid "error: "
+msgstr "hata: "
+
+#: ../../../src/fe_utils/logging.c:196
+#, c-format
+msgid "warning: "
+msgstr "uyarı: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98
+#, c-format
+msgid "out of memory\n"
+msgstr "bellek yetersiz\n"
+
+#: ../../common/fe_memutils.c:92
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "null pointer duplicate edilemiyor (iç hata)\n"
+
+#: ../../common/restricted_token.c:69
+#, c-format
+msgid "cannot create restricted tokens on this platform"
+msgstr "bu platformda restricted token oluşturulamıyor"
+
+#: ../../common/restricted_token.c:78
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "process token açma başarısız: hata kodu %lu"
+
+#: ../../common/restricted_token.c:91
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "SIDler ayrılamıyor (allocate): hata kodu %lu"
+
+#: ../../common/restricted_token.c:110
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "restricted token oluşturulamıyor: hata kodu %lu"
+
+#: ../../common/restricted_token.c:131
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "\"%s\" komutu için işlem (process) başlatılamadı: hata kodu %lu"
+
+#: ../../common/restricted_token.c:169
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "restricted token ile tekrar çalıştırılamadı (re-execute): hata kodu %lu"
+
+#: ../../common/restricted_token.c:185
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "alt-işlemden çıkış kodu alınamadı: hata kodu %lu"
+
+#: copy_fetch.c:60
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "\"%s\" dizini açılamıyor: %m"
+
+#: copy_fetch.c:89 filemap.c:189 filemap.c:350
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "\"%s\" dosyası durumlanamadı: %m"
+
+#: copy_fetch.c:118
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "symbolic link \"%s\" okuma hatası: %m"
+
+#: copy_fetch.c:121
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "symbolic link \"%s\" hedefi çok uzun"
+
+#: copy_fetch.c:136
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\" bir sembolik link, fakat bu platformda sembolik linkler desteklenmiyor"
+
+#: copy_fetch.c:143
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "\"%s\" dizini okunamıyor: %m"
+
+#: copy_fetch.c:147
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "\"%s\" dizini kapatılamadı: %m"
+
+#: copy_fetch.c:167
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "\"%s\" kaynak dosyası açılamadı: %m"
+
+#: copy_fetch.c:171
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "kaynak dosyada arama yapılamadı: %m"
+
+#: copy_fetch.c:188 file_ops.c:312 parsexlog.c:316
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "\"%s\" dosyası okuma hatası: %m"
+
+#: copy_fetch.c:191
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "\"%s\" dosyası okunurken beklenmedik dosya sonu (EOF)"
+
+#: copy_fetch.c:198
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "\"%s\" dosyası kapatılamıyor: %m"
+
+#: file_ops.c:63
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "\"%s\" hedef dosyası açılamadı: %m"
+
+#: file_ops.c:77
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "\"%s\" hedef dosyası kapatılamadı: %m"
+
+#: file_ops.c:97
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "\"%s\" hedef dosyasında arama yapılamadı: %m"
+
+#: file_ops.c:113
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "\"%s\" dosyasına yazma hatası: %m"
+
+#: file_ops.c:163
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "normal (regular) dosya için geçersiz işlem (CREATE)"
+
+#: file_ops.c:186
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "\"%s\" dosyası silinemedi: %m"
+
+#: file_ops.c:204
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "\"%s\" dosyası küçültme (truncation) için açılamadı: %m"
+
+#: file_ops.c:208
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "%s dosyası %u'ya küçültülemedi: %m"
+
+#: file_ops.c:224
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "\"%s\" dizini oluşturulamadı: %m"
+
+#: file_ops.c:238
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "\"%s\" dizini silme hatası: %m"
+
+#: file_ops.c:252
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "\"%s\" de sembolik link oluşturulamadı: %m"
+
+#: file_ops.c:266
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "symbolic link \"%s\" kaldırma hatası: %m"
+
+#: file_ops.c:297 file_ops.c:301
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "\"%s\" dosyası, okunmak için açılamadı: %m"
+
+#: file_ops.c:315 parsexlog.c:318
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "\"%1$s\" dosyası okuma hatası: %3$zu nun %2$d si okundu"
+
+#: filemap.c:181
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "kaynaktaki \"%s\" veri dosyası normal (regular) bir dosya değil"
+
+#: filemap.c:203
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" bir dizin değil"
+
+#: filemap.c:226
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" bir sembolik link değil"
+
+#: filemap.c:238
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" normal (regular) bir dosya değil"
+
+#: filemap.c:362
+#, c-format
+msgid "source file list is empty"
+msgstr "kaynak dosya listesi boş"
+
+#: filemap.c:477
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "\"%s\" dizini veya sembolik linki için beklenmedik sayfa değişikliği (page modification)"
+
+#: libpq_fetch.c:53
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "sunucuya bağlanamadı: %s"
+
+#: libpq_fetch.c:57
+#, c-format
+msgid "connected to server"
+msgstr "sunucuya bağlandı"
+
+#: libpq_fetch.c:61
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "search_path temizlenemedi: %s"
+
+#: libpq_fetch.c:73
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "kaynak sunucu kurtarma (recovery) modunda olmamalı"
+
+#: libpq_fetch.c:83
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "kaynak sunucuda full_page_writes etkinleştirilmiş olmalı"
+
+#: libpq_fetch.c:95
+#, c-format
+msgid "could not set up connection context: %s"
+msgstr "bağlantı bağlamı (context) kurulamadı: %s"
+
+#: libpq_fetch.c:113
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "kaynak sunucuda (%s) sorgusu hata üretti: %s"
+
+#: libpq_fetch.c:118
+#, c-format
+msgid "unexpected result set from query"
+msgstr "sorgudan beklenmedik sonuç kümesi"
+
+#: libpq_fetch.c:141
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "geçerli WAL ekleme (insert) yeri için bilinmeyen sonuç \"%s\""
+
+#: libpq_fetch.c:191
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "dosya listesi getirilemedi: %s"
+
+#: libpq_fetch.c:196
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "dosya listesi getirilirken beklenmedik sonuç kümesi"
+
+#: libpq_fetch.c:244
+#, c-format
+msgid "could not send query: %s"
+msgstr "sorgu gönderilemedi: %s"
+
+#: libpq_fetch.c:249
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "libpq bağlantısı tek satır moduna ayarlanamadı"
+
+#: libpq_fetch.c:270
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "uzak dosyalar getirilirken beklenmedik sonuç: %s"
+
+#: libpq_fetch.c:276
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "uzak dosyalar getirilirken beklenmedik sonuç kümesi"
+
+#: libpq_fetch.c:282
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "uzak dosyalar getirilirken sonuç kümesinde beklenmedik veri tipleri: %u %u %u"
+
+#: libpq_fetch.c:290
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "uzak dosyalar getirilirken beklenmedik sonuç formatı"
+
+#: libpq_fetch.c:296
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "uzak dosyalar getirilirken sonuçta beklenmeyen boş (null) değerler"
+
+#: libpq_fetch.c:300
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "uzak dosyalar getirilirken beklenmedik sonuç uzunluğu"
+
+#: libpq_fetch.c:366
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "\"%s\" uzak dosyası getirilemedi: %s"
+
+#: libpq_fetch.c:371
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "\"%s\" uzak dosyası getirilirken beklenmedik sonuç kümesi"
+
+#: libpq_fetch.c:415
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "COPY veri gönderilemedi: %s"
+
+#: libpq_fetch.c:441
+#, c-format
+msgid "could not create temporary table: %s"
+msgstr "geçici dosya oluşturulamadı: %s"
+
+#: libpq_fetch.c:449
+#, c-format
+msgid "could not send file list: %s"
+msgstr "dosya listesi gönderilemedi: %s"
+
+#: libpq_fetch.c:491
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "kopya sonu (end-of-COPY) gönderilemedi: %s"
+
+#: libpq_fetch.c:497
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "dosya listesi gönderilirken beklenmeye sonuç: %s"
+
+#: logging.c:72
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "%*s/%s kB (%d%%) kopyalandı"
+
+#: parsexlog.c:75 parsexlog.c:129 parsexlog.c:187
+#, c-format
+msgid "out of memory"
+msgstr "yetersiz bellek"
+
+#: parsexlog.c:88 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "%X/%X deki WAL kaydı okunamadı: %s"
+
+#: parsexlog.c:92 parsexlog.c:138
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "%X/%X deki WAL kaydı okunamadı"
+
+#: parsexlog.c:199
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "önceki WAL kaydı %X/%X de bulunamadı: %s"
+
+#: parsexlog.c:203
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "önceki WAL kaydı %X/%X de bulunamadı"
+
+#: parsexlog.c:294
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "\"%s\" dosyası açılamıyor: %m"
+
+#: parsexlog.c:307
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "\"%s\" dosyası ilerleme hatası: %m"
+
+#: parsexlog.c:387
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL kaydı bir nesneyi değiştiriyor, fakat kayıt türü tanınmıyor: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:69
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s bir PostgreSQL kümesini kümenin diğer bir kopyasıyla yeniden senkronize eder.\n"
+"\n"
+
+#: pg_rewind.c:70
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"kullanım:\n"
+" %s [OPTION]...\n"
+"\n"
+
+#: pg_rewind.c:71
+#, c-format
+msgid "Options:\n"
+msgstr "Seçenekler:\n"
+
+#: pg_rewind.c:72
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=DİZİN değiştirilecek mevcut veri dizini\n"
+
+#: pg_rewind.c:73
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=DİZİN senkronize edilecek kaynak veri dizini\n"
+
+#: pg_rewind.c:74
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR senkronize edilecek kaynak sunucu\n"
+
+#: pg_rewind.c:75
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run herhangi bir şeyi değiştirmeden dur\n"
+
+#: pg_rewind.c:76
+#, fuzzy, c-format
+#| msgid " -N, --no-sync do not wait for changes to be written safely to disk\n"
+msgid " -N, --no-sync do not wait for changes to be written\n"
+msgstr " -N, --no-sync değişikliklerin diske yazılmasını bekleme\n"
+
+#: pg_rewind.c:77
+#, fuzzy, c-format
+#| msgid " --no-sync do not wait for changes to be written safely to disk\n"
+msgid " safely to disk\n"
+msgstr ""
+" --no-sync değişikliklerin diske yazılması için bekleme\n"
+"\n"
+
+#: pg_rewind.c:78
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress ilerleme mesajları yaz\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug bir çok hata ayıklama mesajı yaz\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version sürüm bilgisini göster, sonra çık\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help bu yardımı göster, sonra çık\n"
+
+#: pg_rewind.c:82
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+msgstr ""
+"\n"
+"Hataları <pgsql-bugs@lists.postgresql.org> adresine bildirebilirsiniz.\n"
+
+#: pg_rewind.c:139 pg_rewind.c:175 pg_rewind.c:182 pg_rewind.c:189
+#: pg_rewind.c:197
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Daha fazla bilgi için \"%s --help\" yazın\n"
+
+#: pg_rewind.c:174
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "kaynak belirtilmemiş (--source-pgdata veya --source-server)"
+
+#: pg_rewind.c:181
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "--source-pgdata veya --source-server'dan sadece biri belirtilebilir"
+
+#: pg_rewind.c:188
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "hedef veri dizini belirtilmemiş (--target-pgdata)"
+
+#: pg_rewind.c:195
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "çok fazla komut satırı girdisi var (ilki \"%s\")"
+
+#: pg_rewind.c:210
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "\"root\" tarafından çalıştırılamaz"
+
+#: pg_rewind.c:211
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "%s komutunu PostgreSQL superuser olarak çalıştırmalısınız.\n"
+
+#: pg_rewind.c:222
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "\"%s\" dizininin erişim haklarını okunamıyor: %m"
+
+#: pg_rewind.c:253
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "kaynak ve hedef kümesi aynı zaman çizelgesinde"
+
+#: pg_rewind.c:259
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "sunucular %3$u zaman çizelgesinde %1$X/%2$X WAL konumunda birbirlerinden farklılaşıyor"
+
+#: pg_rewind.c:296
+#, c-format
+msgid "no rewind required"
+msgstr "geri sarma (rewind) gerekmiyor"
+
+#: pg_rewind.c:303
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "%3$u zaman çizelgesinde %1$X/%2$X deki son ortak kontrol noktasından geri sarıyor (rewind)"
+
+#: pg_rewind.c:312
+#, c-format
+msgid "reading source file list"
+msgstr "kaynak dosya listesi okunuyor"
+
+#: pg_rewind.c:315
+#, c-format
+msgid "reading target file list"
+msgstr "hedef dosya listesi okunuyor"
+
+#: pg_rewind.c:326
+#, c-format
+msgid "reading WAL in target"
+msgstr "hedefteki WAL okunuyor"
+
+#: pg_rewind.c:343
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "%lu MB kopyalanmalı (toplam kaynak dizin boyutu %lu MB)"
+
+#: pg_rewind.c:362
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "yedek etiketi oluşturuluyor ve kontrol dosyası güncelleniyor"
+
+#: pg_rewind.c:391
+#, c-format
+msgid "syncing target data directory"
+msgstr "hedef veri dizini senkronize ediliyor"
+
+#: pg_rewind.c:394
+#, c-format
+msgid "Done!"
+msgstr "Tamamlandı!"
+
+#: pg_rewind.c:406
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "kaynak ve hedef kümeleri farklı sistemlerden"
+
+#: pg_rewind.c:414
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "kümeler pg_rewind'in bu sürümüyle uyumlu değil"
+
+#: pg_rewind.c:424
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "hedef sunucu ya veri sağlama toplamları (checksum) ya da \"wal_log_hints = on\" kullanmalı"
+
+#: pg_rewind.c:435
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "hedef sunucu düzgün bir şekilde kapatılmalı"
+
+#: pg_rewind.c:445
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "kaynak veri dizini düzgün bir şekilde kapatılmalı"
+
+#: pg_rewind.c:500
+#, c-format
+msgid "invalid control file\n"
+msgstr "geçersiz kontrol dosyası\n"
+
+#: pg_rewind.c:584
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "kaynak ve hedef kümelerin zaman çizelgelerinin ortak atası bulunamadı"
+
+#: pg_rewind.c:625
+#, c-format
+msgid "backup label buffer too small"
+msgstr "yedek etiketi tamponu (buffer) çok küçük"
+
+#: pg_rewind.c:648
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "beklenmedik kontrol dosyası CRC'si"
+
+#: pg_rewind.c:658
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "beklenmedik kontrol dosyası boyutu %d, beklenen %d"
+
+#: pg_rewind.c:667
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "WAL segment boyutu 1 MB ve 1GB arasında 2 nin üssü bir değer olmalıdır, fakat kontrol dosyası %d bayt belirtmektedir"
+msgstr[1] "WAL segment boyutu 1 MB ve 1GB arasında 2 nin üssü bir değer olmalıdır, fakat kontrol dosyası %d bayt belirtmektedir"
+
+#: timeline.c:77 timeline.c:83
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "%s geçmiş dosyasında sözdizimi hatası"
+
+#: timeline.c:78
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Sayısal timeline ID bekleniyordu."
+
+#: timeline.c:84
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Bir write-ahead log geçiş noktası (switchpoint) lokasyonu bekleniyordu "
+
+#: timeline.c:89
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "geçmiş dosyasında geçersiz veri: %s"
+
+#: timeline.c:90
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Timeline ID daima artan sırayla olmalıdır."
+
+#: timeline.c:110
+#, c-format
+msgid "invalid data in history file"
+msgstr "geçmiş dosyasında geçersiz veri"
+
+#: timeline.c:111
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "timeline ID, child timeline ID'sinden daha düşük olmalıdır."
+
+#: xlogreader.c:299
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "%X/%X adresinde geçersiz kayıt offseti"
+
+#: xlogreader.c:307
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "contrecord %X/%X tarafından talep edilmiştir"
+
+#: xlogreader.c:348 xlogreader.c:645
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "%X/%X adresinde geçersiz kayıt uzunluğu: istenen %u, alınan %u"
+
+#: xlogreader.c:372
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "%2$X/%3$X adresinde çok büyük kayıt uzunluğu: %1$u "
+
+#: xlogreader.c:404
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "%X/%X de contrecord bayrağı (flag) bulunmuyor"
+
+#: xlogreader.c:417
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "%X/%X adresinde geçersiz %u contrecord uzunluğu"
+
+#: xlogreader.c:653
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "%2$X/%3$X adresinde geçersiz resource manager ID %1$u"
+
+#: xlogreader.c:667 xlogreader.c:684
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "geçersiz incorrect prev-link olan kayıt: %X/%X at %X/%X"
+
+#: xlogreader.c:721
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "resoource manager data checksum %X/%X kaydında geçersiz"
+
+#: xlogreader.c:758
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "%04X geçersiz tanııtım kodu; %s kayıt segmentinde, offset %u"
+
+#: xlogreader.c:772 xlogreader.c:823
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "%04X geçersiz info bits; %s kayıt segmentinde, offset %u"
+
+#: xlogreader.c:798
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
+msgstr "WAL dosyası farklı veritabanı sisteminden: WAL dosya veritabanı sistem tanımlayıcı %s, pg_control veritabanı sistem tanımlayıcı %s"
+
+#: xlogreader.c:805
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL dosyası farklı veritabanı sisteminden: page header'da yanlış segment boyutu değeri"
+
+#: xlogreader.c:811
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL dosyası farklı veritabanı sisteminden: page header'da yanlış XLOG_BLCKSZ değeri"
+
+#: xlogreader.c:842
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "beklenmeyen pageaddr %X/%X: log segmenti %s, offset %u"
+
+#: xlogreader.c:867
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "sıra dışı timeline ID %u (%u'dan sonra), bulunduğu log segmenti %s, offset %u"
+
+#: xlogreader.c:1112
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "%X/%X deki %u block_id değeri bozuk"
+
+#: xlogreader.c:1135
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA ayarlandı, fakat %X/%X de veri yok"
+
+#: xlogreader.c:1142
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA ayarlanmadı, fakat veri uzunluğu %u (%X/%x de)"
+
+#: xlogreader.c:1178
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE ayarlandı, fakat hole offset %u uzunluk %u blok image uzunluğu %u (%X/%X de)"
+
+#: xlogreader.c:1194
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE ayarlanmadı, fakat hole offset %u uzunluk %u (%X/%X de)"
+
+#: xlogreader.c:1209
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED ayarlandı, fakat block image uzunluğu %u (%X/%X de)"
+
+#: xlogreader.c:1224
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE ve BKPIMAGE_IS_COMPRESSED ayarlanmadı, fakat block image uzunluğu %u (%X/%X de)"
+
+#: xlogreader.c:1240
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL ayarlandı fakat %X/%X de önceki rel yok"
+
+#: xlogreader.c:1252
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "%X/%X adresinde %u block_id geçersiz"
+
+#: xlogreader.c:1341
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "%X/%X adresinde geçersiz uzunlukta kayıt"
+
+#: xlogreader.c:1430
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "%X/%X adresinde (blok %d), geçersiz compressed image"
+
+#~ msgid "WAL file is from different database system: incorrect XLOG_SEG_SIZE in page header"
+#~ msgstr "WAL dosyası farklı veritabanı sisteminden: page header'da yanlış XLOG_SEG_SIZE değeri"
+
+#~ msgid "Timeline IDs must be less than child timeline's ID.\n"
+#~ msgstr "Zamançizelgesi ID'leri alt zaman çizelgesinin ID'lerinden küçük olmalı.\n"
+
+#~ msgid "Timeline IDs must be in increasing sequence.\n"
+#~ msgstr "Zaman çizelgesi ID'leri artan sırada olmalı.\n"
+
+#~ msgid "invalid data in history file: %s\n"
+#~ msgstr "geçmiş dosyasında geçersiz veri: %s\n"
+
+#~ msgid "Expected a write-ahead log switchpoint location.\n"
+#~ msgstr "İşlem kaydı (WAL) geçiş noktası konumu bekleniyor.\n"
+
+#~ msgid "Expected a numeric timeline ID.\n"
+#~ msgstr "Sayısal bir zaman çizelgesi ID'si bekleniyor.\n"
+
+#~ msgid "syntax error in history file: %s\n"
+#~ msgstr "geçmiş dosyasında sözdizimi hatası: %s\n"
+
+#~ msgid "sync of target directory failed\n"
+#~ msgstr "hedef dizinin senkronizasyonu başarısız oldu\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" was found by \"%s\"\n"
+#~ "but was not the same version as %s.\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "\"initdb\" programı \"%s\" tarafından bulundu\n"
+#~ "fakat %s ile aynı sürümde değil.\n"
+#~ "Kurulumunuzu kontrol ediniz\n"
+
+#~ msgid ""
+#~ "The program \"initdb\" is needed by %s but was\n"
+#~ "not found in the same directory as \"%s\".\n"
+#~ "Check your installation.\n"
+#~ msgstr ""
+#~ "\"initdb\" programına %s tarafından ihtiyaç duyuluyor fakat\n"
+#~ "\"%s\" ile aynı dizinde bulunmuyor.\n"
+#~ "Kurulumunuzu kontrol ediniz.\n"
+
+#~ msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte\n"
+#~ msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes\n"
+#~ msgstr[0] "WAL segment boyutu 1 MB ve 1GB arasında 2 nin üssü bir değer olmalıdır, fakat kontrol dosyası %d bayt belirtmektedir\n"
+#~ msgstr[1] "WAL segment boyutu 1 MB ve 1GB arasında 2 nin üssü bir değer olmalıdır, fakat kontrol dosyası %d bayt belirtmektedir\n"
+
+#~ msgid "%d: %X/%X - %X/%X\n"
+#~ msgstr "%d: %X/%X - %X/%X\n"
+
+#~ msgid "Target timeline history:\n"
+#~ msgstr "Hedef zaman çizelgesi geçmişi:\n"
+
+#~ msgid "Source timeline history:\n"
+#~ msgstr "Kaynak zaman çizelgesi geçmişi:\n"
+
+#~ msgid "%s: could not read permissions of directory \"%s\": %s\n"
+#~ msgstr "%s: \"%s\" dizininin erişim hakları okunamadı : %s\n"
+
+#~ msgid "could not read from file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyasından okuma hatası: %s\n"
+
+#~ msgid "could not seek in file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyasında arama yapılamadı: %s\n"
+
+#~ msgid "could not open file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyası açılamadı: %s\n"
+
+#~ msgid "Failure, exiting\n"
+#~ msgstr "Başarısız, çıkılıyor\n"
+
+#~ msgid "fetched file \"%s\", length %d\n"
+#~ msgstr "\"%s\" dosyası getirildi, uzunluk %d\n"
+
+#~ msgid "received chunk for file \"%s\", offset %s, size %d\n"
+#~ msgstr "\"%s\" dosyası için parça (chunk) alındı, ofset %s, boyut %d\n"
+
+#~ msgid "received null value for chunk for file \"%s\", file has been deleted\n"
+#~ msgstr "\"%s\" dosyası parçası (chunk) için boş (null) değer alındı, dosya silindi\n"
+
+#~ msgid "getting file chunks\n"
+#~ msgstr "dosya parçaları alınıyor\n"
+
+#~ msgid "%s (%s)\n"
+#~ msgstr "%s (%s)\n"
+
+#~ msgid "entry \"%s\" excluded from target file list\n"
+#~ msgstr "\"%s\" kaydı hedef dosya listesinden hariç tutuldu\n"
+
+#~ msgid "entry \"%s\" excluded from source file list\n"
+#~ msgstr "\"%s\" kaydı kaynak dosya listesinden hariç tutuldu\n"
+
+#~ msgid "could not open file \"%s\" for reading: %s\n"
+#~ msgstr "\"%s\" dosyası okuma için açılamadı: %s\n"
+
+#~ msgid "could not remove symbolic link \"%s\": %s\n"
+#~ msgstr "\"%s\" sembolik linki kaldırılamadı: %s\n"
+
+#~ msgid "could not remove directory \"%s\": %s\n"
+#~ msgstr "\"%s\" dizini silinemedi: %s\n"
+
+#~ msgid "could not create directory \"%s\": %s\n"
+#~ msgstr "\"%s\" dizini oluşturulamadı: %s\n"
+
+#~ msgid "could not truncate file \"%s\" to %u: %s\n"
+#~ msgstr "\"%s\" dosyası %u'ya küçültülemedi (truncate): %s\n"
+
+#~ msgid "could not remove file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyası silinemedi: %s\n"
+
+#~ msgid "could not write file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyasına yazılamadı: %s\n"
+
+#~ msgid " block %u\n"
+#~ msgstr " blok %u\n"
+
+#~ msgid "could not close file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyası kapatılamadı: %s\n"
+
+#~ msgid "could not read file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyası okunamadı: %s\n"
+
+#~ msgid "could not read directory \"%s\": %s\n"
+#~ msgstr "\"%s\" dizini okunamıyor: %s\n"
+
+#~ msgid "symbolic link \"%s\" target is too long\n"
+#~ msgstr "\"%s\" sembolik link hedefi çok uzun\n"
+
+#~ msgid "could not read symbolic link \"%s\": %s\n"
+#~ msgstr "\"%s\" sembolik linki okunamadı: %s\n"
+
+#~ msgid "could not stat file \"%s\": %s\n"
+#~ msgstr "\"%s\" dosyasının durumu görüntülenemedi (stat): %s\n"
+
+#~ msgid "could not open directory \"%s\": %s\n"
+#~ msgstr "\"%s\" dizini açılamıyor: %s\n"
+
+#~ msgid "%s: could not open process token: error code %lu\n"
+#~ msgstr "%s: process token açma başarısız: hata kodu %lu\n"
diff --git a/src/bin/pg_rewind/po/uk.po b/src/bin/pg_rewind/po/uk.po
new file mode 100644
index 0000000..841576c
--- /dev/null
+++ b/src/bin/pg_rewind/po/uk.po
@@ -0,0 +1,913 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: postgresql\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2020-09-21 21:17+0000\n"
+"PO-Revision-Date: 2020-09-22 13:43\n"
+"Last-Translator: \n"
+"Language-Team: Ukrainian\n"
+"Language: uk_UA\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
+"X-Crowdin-Project: postgresql\n"
+"X-Crowdin-Project-ID: 324573\n"
+"X-Crowdin-Language: uk\n"
+"X-Crowdin-File: /DEV_13/pg_rewind.pot\n"
+"X-Crowdin-File-ID: 504\n"
+
+#: ../../../src/common/logging.c:236
+#, c-format
+msgid "fatal: "
+msgstr "збій: "
+
+#: ../../../src/common/logging.c:243
+#, c-format
+msgid "error: "
+msgstr "помилка: "
+
+#: ../../../src/common/logging.c:250
+#, c-format
+msgid "warning: "
+msgstr "попередження: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98 ../../common/fe_memutils.c:162
+#, c-format
+msgid "out of memory\n"
+msgstr "недостатньо пам'яті\n"
+
+#: ../../common/fe_memutils.c:92 ../../common/fe_memutils.c:154
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "неможливо дублювати нульовий покажчик (внутрішня помилка)\n"
+
+#: ../../common/restricted_token.c:64
+#, c-format
+msgid "could not load library \"%s\": error code %lu"
+msgstr "не вдалося завантажити бібліотеку \"%s\": код помилки %lu"
+
+#: ../../common/restricted_token.c:73
+#, c-format
+msgid "cannot create restricted tokens on this platform: error code %lu"
+msgstr "не вдалося створити обмежені токени на цій платформі: код помилки %lu"
+
+#: ../../common/restricted_token.c:82
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "не вдалося відкрити токен процесу: код помилки %lu"
+
+#: ../../common/restricted_token.c:97
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "не вдалося виділити SID: код помилки %lu"
+
+#: ../../common/restricted_token.c:119
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "не вдалося створити обмежений токен: код помилки %lu"
+
+#: ../../common/restricted_token.c:140
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "не вдалося запустити процес для команди \"%s\": код помилки %lu"
+
+#: ../../common/restricted_token.c:178
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "не вдалося перезапустити з обмеженим токеном: код помилки %lu"
+
+#: ../../common/restricted_token.c:194
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "не вдалося отримати код завершення підпроцесу: код помилки %lu"
+
+#: ../../fe_utils/archive.c:53
+#, c-format
+msgid "cannot use restore_command with %%r placeholder"
+msgstr "не вдалося використати restore_command із заповнювачем %%r"
+
+#: ../../fe_utils/archive.c:74
+#, c-format
+msgid "unexpected file size for \"%s\": %lu instead of %lu"
+msgstr "неочікуваний розмір файлу для \"%s\": %lu замість %lu"
+
+#: ../../fe_utils/archive.c:85
+#, c-format
+msgid "could not open file \"%s\" restored from archive: %m"
+msgstr "не вдалося відкрити файл \"%s\" відновлений з архіву: %m"
+
+#: ../../fe_utils/archive.c:97 copy_fetch.c:88 filemap.c:208
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "не вдалося отримати інформацію від файлу \"%s\": %m"
+
+#: ../../fe_utils/archive.c:112
+#, c-format
+msgid "restore_command failed: %s"
+msgstr "помилка restore_command: %s"
+
+#: ../../fe_utils/archive.c:121
+#, c-format
+msgid "could not restore file \"%s\" from archive"
+msgstr "не вдалося відновити файл \"%s\" з архіву"
+
+#: ../../fe_utils/recovery_gen.c:35 ../../fe_utils/recovery_gen.c:49
+#: ../../fe_utils/recovery_gen.c:77 ../../fe_utils/recovery_gen.c:100
+#: ../../fe_utils/recovery_gen.c:171 parsexlog.c:73 parsexlog.c:125
+#: parsexlog.c:185
+#, c-format
+msgid "out of memory"
+msgstr "недостатньо пам'яті"
+
+#: ../../fe_utils/recovery_gen.c:134 parsexlog.c:298
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "не можливо відкрити файл \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:140
+#, c-format
+msgid "could not write to file \"%s\": %m"
+msgstr "неможливо записати до файлу \"%s\": %m"
+
+#: ../../fe_utils/recovery_gen.c:152
+#, c-format
+msgid "could not create file \"%s\": %m"
+msgstr "неможливо створити файл \"%s\": %m"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "не вдалося відкрити каталог \"%s\": %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "не можливо прочитати символічне послання \"%s\": %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "таргет символічного посилання \"%s\" задовгий"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\"є символічним посиланням, але символічні посилання не підтримуються на даній платформі"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "не вдалося прочитати каталог \"%s\": %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "не вдалося закрити каталог \"%s\": %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "не вдалося відкрити вихідний файл \"%s\": %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "не вдалося знайти у вихідному файлі: %m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:336
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "не вдалося прочитати файл \"%s\": %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "неочікуваний кінець при читанні файлу \"%s\""
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "неможливо закрити файл \"%s\": %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "не вдалося відкрити цільовий файл \"%s\": %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "не вдалося закрити цільовий файл \"%s\": %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "не вдалося знайти в цільовому файлі \"%s\": %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "не вдалося записати файл \"%s\": %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "неприпустима дія (CREATE) для звичайного файлу"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "не можливо видалити файл \"%s\": %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "не вдалося відкрити файл \"%s\" для скорочення: %m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "не вдалося скоротити файл \"%s\" до потрібного розміру %u: %m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "не вдалося створити каталог \"%s\": %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "не вдалося видалити каталог \"%s\": %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "неможливо створити символічне послання на \"%s\": %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "не вдалося видалити символьне посилання \"%s\": %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "не вдалося відкрити файл \"%s\" для читання: %m"
+
+#: file_ops.c:314 parsexlog.c:338
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "не вдалося прочитати файл \"%s\": прочитано %d з %zu"
+
+#: filemap.c:200
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "файл даних \"%s\" в джерелі не є регулярним файлом"
+
+#: filemap.c:222
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\" не є каталогом"
+
+#: filemap.c:245
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\" не є символічним посиланням"
+
+#: filemap.c:257
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\" не є регулярним файлом"
+
+#: filemap.c:369
+#, c-format
+msgid "source file list is empty"
+msgstr "список файлів в джерелі порожній"
+
+#: filemap.c:484
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "неочікувана модифікація сторінки для каталогу або символічного посилання \"%s\""
+
+#: libpq_fetch.c:50
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "не вдалося підключитися до сервера: %s"
+
+#: libpq_fetch.c:54
+#, c-format
+msgid "connected to server"
+msgstr "під'єднано до серверу"
+
+#: libpq_fetch.c:63
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "не вдалося очистити search_path: %s"
+
+#: libpq_fetch.c:75
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "початковий сервер не повинен бути у стані відновлення"
+
+#: libpq_fetch.c:85
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "на початковому сервері повинно бути увімкнено full_page_writes"
+
+#: libpq_fetch.c:111
+#, c-format
+msgid "error running query (%s) on source server: %s"
+msgstr "помилка при виконанні запиту (%s) на вихідному сервері: %s"
+
+#: libpq_fetch.c:116
+#, c-format
+msgid "unexpected result set from query"
+msgstr "неочікуваний результат запиту"
+
+#: libpq_fetch.c:137
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "помилка при виконанні запиту (%s) на початковому сервері: %s"
+
+#: libpq_fetch.c:157
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "нерозпізнаний результат \"%s\" замість поточної добавленої позиції WAL"
+
+#: libpq_fetch.c:207
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "не вдалося отримати список файлів: %s"
+
+#: libpq_fetch.c:212
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "неочікуваний результат при отриманні списку файлів"
+
+#: libpq_fetch.c:265
+#, c-format
+msgid "could not send query: %s"
+msgstr "не вдалося надіслати запит: %s"
+
+#: libpq_fetch.c:270
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "не вдалося встановити libpq з'єднання для однорядкового режиму"
+
+#: libpq_fetch.c:290
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "неочікуваний результат при отриманні віддалених файлів: %s"
+
+#: libpq_fetch.c:296
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "неочікуваний розмір набору результатів при отриманні віддалених файлів"
+
+#: libpq_fetch.c:302
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "неочікувані типи даних в результаті при отриманні віддалених файлів: %u %u %u"
+
+#: libpq_fetch.c:310
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "неочікуваний формат результату при отриманні віддалених файлів"
+
+#: libpq_fetch.c:316
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "неочікувані нульові значення в результаті при отриманні віддалених файлів"
+
+#: libpq_fetch.c:320
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "неочікувана довжина результату при отриманні віддалених файлів"
+
+#: libpq_fetch.c:381
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "не вдалося отримати віддалений файл \"%s\": %s"
+
+#: libpq_fetch.c:386
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "неочікуваний набір результатів при отриманні віддаленого файлу \"%s\""
+
+#: libpq_fetch.c:430
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "не вдалося надіслати дані COPY: %s"
+
+#: libpq_fetch.c:459
+#, c-format
+msgid "could not send file list: %s"
+msgstr "не вдалося надіслати список файлів: %s"
+
+#: libpq_fetch.c:501
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "не вдалося надіслати сповіщення про закінчення копіювання: %s"
+
+#: libpq_fetch.c:507
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "неочікуваний результат при надсиланні списку файлів: %s"
+
+#: parsexlog.c:85 parsexlog.c:132
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "не вдалося прочитати запис WAL на %X/%X: %s"
+
+#: parsexlog.c:89 parsexlog.c:135
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "не вдалося прочитати запис WAL на %X/%X"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "не вдалося знайти попередній запис WAL на %X/%X: %s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "не вдалося знайти попередній запис WAL на %X/%X"
+
+#: parsexlog.c:327
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "не вдалося знайти в файлі \"%s\": %m"
+
+#: parsexlog.c:407
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL модифікує відношення, але тип запису не розпізнано: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:78
+#, c-format
+msgid "%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n\n"
+msgstr "%s синхронізує кластер PostgreSQL з іншою копією кластеру.\n\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid "Usage:\n"
+" %s [OPTION]...\n\n"
+msgstr "Використання:\n"
+" %s [OPTION]...\n\n"
+
+#: pg_rewind.c:80
+#, c-format
+msgid "Options:\n"
+msgstr "Параметри:\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid " -c, --restore-target-wal use restore_command in target configuration to\n"
+" retrieve WAL files from archives\n"
+msgstr " -c, --restore-target-wal використовує restore_command в цільовій конфігурації, щоб\n"
+" отримати файли WAL з архівів\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=DIRECTORY існуючий каталог для змін\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=DIRECTORY початковий каталог даних для синхронізації\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR початковий сервер для синхронізації\n"
+
+#: pg_rewind.c:86
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run зупинитися до внесення будь-яких змін\n"
+
+#: pg_rewind.c:87
+#, c-format
+msgid " -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr " -N, --no-sync не чекати поки зміни будуть записані на диск\n"
+
+#: pg_rewind.c:89
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress повідомляти про хід процесу\n"
+
+#: pg_rewind.c:90
+#, c-format
+msgid " -R, --write-recovery-conf write configuration for replication\n"
+" (requires --source-server)\n"
+msgstr " -R, --write-recovery-conf записує конфігурацію для реплікації \n"
+" (потребує --source-server)\n"
+
+#: pg_rewind.c:92
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug виводити багато налагоджувальних повідомлень\n"
+
+#: pg_rewind.c:93
+#, c-format
+msgid " --no-ensure-shutdown do not automatically fix unclean shutdown\n"
+msgstr " --no-ensure-shutdown не виправляти автоматично неочищене завершення роботи\n"
+
+#: pg_rewind.c:94
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version вивести інформацію про версію і вийти\n"
+
+#: pg_rewind.c:95
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help показати довідку, потім вийти\n"
+
+#: pg_rewind.c:96
+#, c-format
+msgid "\n"
+"Report bugs to <%s>.\n"
+msgstr "\n"
+"Повідомляти про помилки на <%s>.\n"
+
+#: pg_rewind.c:97
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "Домашня сторінка %s: <%s>\n"
+
+#: pg_rewind.c:159 pg_rewind.c:208 pg_rewind.c:215 pg_rewind.c:222
+#: pg_rewind.c:229 pg_rewind.c:237
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "Спробуйте \"%s --help\" для отримання додаткової інформації.\n"
+
+#: pg_rewind.c:207
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "джерело не вказано (--source-pgdata чи --source-server)"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "може бути вказано лише --source-pgdata чи --source-server"
+
+#: pg_rewind.c:221
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "не вказано жодного каталогу цільових даних (--target-pgdata)"
+
+#: pg_rewind.c:228
+#, c-format
+msgid "no source server information (--source-server) specified for --write-recovery-conf"
+msgstr "немає інформації про вихідний сервер (--source-server) вказаної для --write-recovery-conf"
+
+#: pg_rewind.c:235
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "забагато аргументів у командному рядку (перший \"%s\")"
+
+#: pg_rewind.c:250
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "\"root\" не може це виконувати"
+
+#: pg_rewind.c:251
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "Запускати %s треба від суперкористувача PostgreSQL.\n"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "не вдалося прочитати дозволи на каталог \"%s\": %m"
+
+#: pg_rewind.c:316
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "початковий і цільовий кластери знаходяться на одній лінії часу"
+
+#: pg_rewind.c:322
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "сервери розійшлись в позиції WAL %X/%X на лінії часу %u"
+
+#: pg_rewind.c:360
+#, c-format
+msgid "no rewind required"
+msgstr "перемотування не потрібне"
+
+#: pg_rewind.c:369
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "перемотування від останньої спільної контрольної точки на %X/%X на лінії часу %u"
+
+#: pg_rewind.c:378
+#, c-format
+msgid "reading source file list"
+msgstr "читання списку файлів із джерела"
+
+#: pg_rewind.c:381
+#, c-format
+msgid "reading target file list"
+msgstr "читання списку цільових файлів"
+
+#: pg_rewind.c:392
+#, c-format
+msgid "reading WAL in target"
+msgstr "читання WAL у цілі"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "треба скопіювати %lu МБ (загальний розмір каталогу джерела становить %lu МБ)"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "створення мітки резервного копіювання і оновлення контрольного файлу"
+
+#: pg_rewind.c:457
+#, c-format
+msgid "syncing target data directory"
+msgstr "синхронізація цільового каталогу даних"
+
+#: pg_rewind.c:464
+#, c-format
+msgid "Done!"
+msgstr "Готово!"
+
+#: pg_rewind.c:476
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "початковий і цільовий кластер належать до різних систем"
+
+#: pg_rewind.c:484
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "кластери не сумісні з даною версією pg_rewind"
+
+#: pg_rewind.c:494
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "цільовий сервер потребує використання контрольної суми даних або \"wal_log_hints = on\""
+
+#: pg_rewind.c:505
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "цільовий сервер повинен бути вимкненим штатно"
+
+#: pg_rewind.c:515
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "робота з початковим каталогом даних повинна бути завершена штатно"
+
+#: pg_rewind.c:567
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "скопійовано %*s/%s кБ (%d%%)"
+
+#: pg_rewind.c:630
+#, c-format
+msgid "invalid control file"
+msgstr "неприпустимий контрольний файл"
+
+#: pg_rewind.c:714
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "не вдалося знайти спільного предка ліній часу початкового та цільового кластерів"
+
+#: pg_rewind.c:755
+#, c-format
+msgid "backup label buffer too small"
+msgstr "буфер для мітки резервного копіювання замалий"
+
+#: pg_rewind.c:778
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "неочікуваний контрольний файл CRC"
+
+#: pg_rewind.c:788
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "неочікуваний розмір контрольного файлу %d, очікувалося %d"
+
+#: pg_rewind.c:797
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d"
+msgstr[1] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d"
+msgstr[2] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d"
+msgstr[3] "Розмір сегменту WAL повинен задаватись ступенем 2 в інтервалі від 1 МБ до 1 ГБ, але в керуючому файлі вказано значення %d"
+
+#: pg_rewind.c:854 pg_rewind.c:912
+#, c-format
+msgid "The program \"%s\" is needed by %s but was not found in the\n"
+"same directory as \"%s\".\n"
+"Check your installation."
+msgstr "Програма \"%s\" потрібна для %s, але не знайдена в тому ж каталозі, що й \"%s\".\n"
+"Перевірте вашу установку."
+
+#: pg_rewind.c:859 pg_rewind.c:917
+#, c-format
+msgid "The program \"%s\" was found by \"%s\"\n"
+"but was not the same version as %s.\n"
+"Check your installation."
+msgstr "Програма \"%s\" була знайдена \"%s\", але не була тієї ж версії, що %s.\n"
+"Перевірте вашу установку."
+
+#: pg_rewind.c:880
+#, c-format
+msgid "restore_command is not set in the target cluster"
+msgstr "команда restore_command не встановлена в цільовому кластері"
+
+#: pg_rewind.c:923
+#, c-format
+msgid "executing \"%s\" for target server to complete crash recovery"
+msgstr "виконання \"%s\" для цільового серверу, щоб завершити відновлення після аварійного завершення роботи"
+
+#: pg_rewind.c:943
+#, c-format
+msgid "postgres single-user mode in target cluster failed"
+msgstr "не вдалося ввімкнути однокористувацький режим postgres в цільовому кластері"
+
+#: pg_rewind.c:944
+#, c-format
+msgid "Command was: %s"
+msgstr "Команда була: %s"
+
+#: timeline.c:75 timeline.c:81
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "синтаксична помилка у файлі історії: %s"
+
+#: timeline.c:76
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "Очікується числовий ідентифікатор лінії часу."
+
+#: timeline.c:82
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "Очікується положення точки випереджувального журналювання."
+
+#: timeline.c:87
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "неприпустимі дані у файлу історії: %s"
+
+#: timeline.c:88
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "Ідентифікатори ліній часу повинні збільшуватись."
+
+#: timeline.c:108
+#, c-format
+msgid "invalid data in history file"
+msgstr "неприпустимі дані у файлі історії"
+
+#: timeline.c:109
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "Ідентифікатори ліній часу повинні бути меншими від ідентифікатора дочірньої лінії."
+
+#: xlogreader.c:349
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "невірний зсув запису: %X/%X"
+
+#: xlogreader.c:357
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "по зсуву %X/%X запитано продовження запису"
+
+#: xlogreader.c:398 xlogreader.c:695
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "невірна довжина запису по зсуву %X/%X: очікувалось %u, отримано %u"
+
+#: xlogreader.c:422
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "довжина запису %u на %X/%X є задовгою"
+
+#: xlogreader.c:454
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "немає флага contrecord в позиції %X/%X"
+
+#: xlogreader.c:467
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "невірна довижна contrecord (%u) в позиції %X/%X"
+
+#: xlogreader.c:703
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "невірний ID менеджера ресурсів %u в %X/%X"
+
+#: xlogreader.c:717 xlogreader.c:734
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "запис з неправильним попереднім посиланням %X/%X на %X/%X"
+
+#: xlogreader.c:771
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "некоректна контрольна сума даних менеджера ресурсів у запису по зсуву %X/%X"
+
+#: xlogreader.c:808
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "невірне магічне число %04X в сегменті журналу %s, зсув %u"
+
+#: xlogreader.c:822 xlogreader.c:863
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "невірні інформаційні біти %04X в сегменті журналу %s, зсув %u"
+
+#: xlogreader.c:837
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu"
+msgstr "WAL файл належить іншій системі баз даних: ідентифікатор системи баз даних де міститься WAL файл - %llu, а ідентифікатор системи баз даних pg_control - %llu"
+
+#: xlogreader.c:845
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "Файл WAL належить іншій системі баз даних: некоректний розмір сегменту в заголовку сторінки"
+
+#: xlogreader.c:851
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "Файл WAL належить іншій системі баз даних: некоректний XLOG_BLCKSZ в заголовку сторінки"
+
+#: xlogreader.c:882
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "неочікуваний pageaddr %X/%X в сегменті журналу %s, зсув %u"
+
+#: xlogreader.c:907
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "порушення послідовності ID лінії часу %u (після %u) в сегменті журналу %s, зсув %u"
+
+#: xlogreader.c:1247
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "ідентифікатор блока %u out-of-order в позиції %X/%X"
+
+#: xlogreader.c:1270
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA встановлений, але немає даних в позиції %X/%X"
+
+#: xlogreader.c:1277
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA встановлений, але довжина даних дорівнює %u в позиції %X/%X"
+
+#: xlogreader.c:1313
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE встановлений, але для пропуску задані: зсув %u, довжина %u, при довжині образу блока %u в позиції %X/%X"
+
+#: xlogreader.c:1329
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE не встановлений, але для пропуску задані: зсув %u, довжина %u в позиції %X/%X"
+
+#: xlogreader.c:1344
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED встановлений, але довжина образу блока дорівнює %u в позиції %X/%X"
+
+#: xlogreader.c:1359
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "ні BKPIMAGE_HAS_HOLE, ні BKPIMAGE_IS_COMPRESSED не встановлені, але довжина образу блока дорвінює %u в позиції %X/%X"
+
+#: xlogreader.c:1375
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL встановлений, але попереднє значення не задано в позиції %X/%X"
+
+#: xlogreader.c:1387
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "невірний ідентифікатор блоку %u в позиції %X/%X"
+
+#: xlogreader.c:1476
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "запис з невірною довжиною на %X/%X"
+
+#: xlogreader.c:1565
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "невірно стиснутий образ в позиції %X/%X, блок %d"
+
diff --git a/src/bin/pg_rewind/po/zh_CN.po b/src/bin/pg_rewind/po/zh_CN.po
new file mode 100644
index 0000000..4918fd4
--- /dev/null
+++ b/src/bin/pg_rewind/po/zh_CN.po
@@ -0,0 +1,821 @@
+# LANGUAGE message translation file for pg_rewind
+# Copyright (C) 2019 PostgreSQL Global Development Group
+# This file is distributed under the same license as the PostgreSQL package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pg_rewind (PostgreSQL) 12\n"
+"Report-Msgid-Bugs-To: pgsql-bugs@lists.postgresql.org\n"
+"POT-Creation-Date: 2019-05-22 17:56+0800\n"
+"PO-Revision-Date: 2019-05-31 18:00+0800\n"
+"Last-Translator: Jie Zhang <zhangjie2@cn.fujitsu.com>\n"
+"Language-Team: Chinese (Simplified) <zhangjie2@cn.fujitsu.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 1.5.7\n"
+
+#: ../../../src/common/logging.c:188
+#, c-format
+msgid "fatal: "
+msgstr "致命的: "
+
+#: ../../../src/common/logging.c:195
+#, c-format
+msgid "error: "
+msgstr "错误: "
+
+#: ../../../src/common/logging.c:202
+#, c-format
+msgid "warning: "
+msgstr "警告: "
+
+#: ../../common/fe_memutils.c:35 ../../common/fe_memutils.c:75
+#: ../../common/fe_memutils.c:98
+#, c-format
+msgid "out of memory\n"
+msgstr "内存溢出\n"
+
+#: ../../common/fe_memutils.c:92
+#, c-format
+msgid "cannot duplicate null pointer (internal error)\n"
+msgstr "无法复制空指针 (内部错误)\n"
+
+#: ../../common/restricted_token.c:69
+#, c-format
+msgid "cannot create restricted tokens on this platform"
+msgstr "无法为该平台创建受限制的令牌"
+
+#: ../../common/restricted_token.c:78
+#, c-format
+msgid "could not open process token: error code %lu"
+msgstr "无法打开进程令牌 (token): 错误码 %lu"
+
+#: ../../common/restricted_token.c:91
+#, c-format
+msgid "could not allocate SIDs: error code %lu"
+msgstr "无法分配SID: 错误码 %lu"
+
+#: ../../common/restricted_token.c:110
+#, c-format
+msgid "could not create restricted token: error code %lu"
+msgstr "无法创建受限令牌: 错误码为 %lu"
+
+#: ../../common/restricted_token.c:131
+#, c-format
+msgid "could not start process for command \"%s\": error code %lu"
+msgstr "无法为命令 \"%s\"创建进程: 错误码 %lu"
+
+#: ../../common/restricted_token.c:169
+#, c-format
+msgid "could not re-execute with restricted token: error code %lu"
+msgstr "无法使用受限令牌再次执行: 错误码 %lu"
+
+#: ../../common/restricted_token.c:185
+#, c-format
+msgid "could not get exit code from subprocess: error code %lu"
+msgstr "无法从子进程得到退出码: 错误码 %lu"
+
+#: copy_fetch.c:59
+#, c-format
+msgid "could not open directory \"%s\": %m"
+msgstr "无法打开目录 \"%s\": %m"
+
+#: copy_fetch.c:88 filemap.c:187 filemap.c:348
+#, c-format
+msgid "could not stat file \"%s\": %m"
+msgstr "无法取文件 \"%s\" 的状态: %m"
+
+#: copy_fetch.c:117
+#, c-format
+msgid "could not read symbolic link \"%s\": %m"
+msgstr "无法读取符号链接 \"%s\": %m"
+
+#: copy_fetch.c:120
+#, c-format
+msgid "symbolic link \"%s\" target is too long"
+msgstr "符号链接 \"%s\" 目标超长"
+
+#: copy_fetch.c:135
+#, c-format
+msgid "\"%s\" is a symbolic link, but symbolic links are not supported on this platform"
+msgstr "\"%s\"是一个符号链接,但是这个平台上不支持平台链接"
+
+#: copy_fetch.c:142
+#, c-format
+msgid "could not read directory \"%s\": %m"
+msgstr "无法读取目录 \"%s\": %m"
+
+#: copy_fetch.c:146
+#, c-format
+msgid "could not close directory \"%s\": %m"
+msgstr "无法关闭目录 \"%s\": %m"
+
+#: copy_fetch.c:166
+#, c-format
+msgid "could not open source file \"%s\": %m"
+msgstr "无法打开源文件\"%s\": %m"
+
+#: copy_fetch.c:170
+#, c-format
+msgid "could not seek in source file: %m"
+msgstr "无法在源文件中定位(seek):%m"
+
+#: copy_fetch.c:187 file_ops.c:311 parsexlog.c:315
+#, c-format
+msgid "could not read file \"%s\": %m"
+msgstr "无法读取文件 \"%s\": %m"
+
+#: copy_fetch.c:190
+#, c-format
+msgid "unexpected EOF while reading file \"%s\""
+msgstr "读取文件\"%s\"时遇到意料之外的EOF"
+
+#: copy_fetch.c:197
+#, c-format
+msgid "could not close file \"%s\": %m"
+msgstr "无法关闭文件 \"%s\": %m"
+
+#: file_ops.c:62
+#, c-format
+msgid "could not open target file \"%s\": %m"
+msgstr "无法打开目标文件\"%s\": %m"
+
+#: file_ops.c:76
+#, c-format
+msgid "could not close target file \"%s\": %m"
+msgstr "无法关闭目标文件\"%s\": %m"
+
+#: file_ops.c:96
+#, c-format
+msgid "could not seek in target file \"%s\": %m"
+msgstr "无法在目标文件\"%s\"中定位(seek): %m"
+
+#: file_ops.c:112
+#, c-format
+msgid "could not write file \"%s\": %m"
+msgstr "无法写入文件 \"%s\": %m"
+
+#: file_ops.c:162
+#, c-format
+msgid "invalid action (CREATE) for regular file"
+msgstr "对常规文件无效的动作(CREATE)"
+
+#: file_ops.c:185
+#, c-format
+msgid "could not remove file \"%s\": %m"
+msgstr "无法删除文件 \"%s\": %m"
+
+#: file_ops.c:203
+#, c-format
+msgid "could not open file \"%s\" for truncation: %m"
+msgstr "无法打开文件\"%s\"用于截断:%m"
+
+#: file_ops.c:207
+#, c-format
+msgid "could not truncate file \"%s\" to %u: %m"
+msgstr "无法将文件\"%s\"截断为%u:%m"
+
+#: file_ops.c:223
+#, c-format
+msgid "could not create directory \"%s\": %m"
+msgstr "无法创建目录 \"%s\": %m"
+
+#: file_ops.c:237
+#, c-format
+msgid "could not remove directory \"%s\": %m"
+msgstr "无法删除目录 \"%s\": %m"
+
+#: file_ops.c:251
+#, c-format
+msgid "could not create symbolic link at \"%s\": %m"
+msgstr "无法在\"%s\"创建符号链接: %m"
+
+#: file_ops.c:265
+#, c-format
+msgid "could not remove symbolic link \"%s\": %m"
+msgstr "无法删除符号链接 \"%s\": %m"
+
+#: file_ops.c:296 file_ops.c:300
+#, c-format
+msgid "could not open file \"%s\" for reading: %m"
+msgstr "为了读取, 无法打开文件 \"%s\": %m"
+
+#: file_ops.c:314 parsexlog.c:317
+#, c-format
+msgid "could not read file \"%s\": read %d of %zu"
+msgstr "无法读取文件\"%1$s\":读取了%3$zu中的%2$d"
+
+#: filemap.c:179
+#, c-format
+msgid "data file \"%s\" in source is not a regular file"
+msgstr "源头的数据文件\"%s\"不是一个常规文件"
+
+#: filemap.c:201
+#, c-format
+msgid "\"%s\" is not a directory"
+msgstr "\"%s\"不是一个目录"
+
+#: filemap.c:224
+#, c-format
+msgid "\"%s\" is not a symbolic link"
+msgstr "\"%s\"不是一个符号链接"
+
+#: filemap.c:236
+#, c-format
+msgid "\"%s\" is not a regular file"
+msgstr "\"%s\"不是一个常规文件"
+
+#: filemap.c:360
+#, c-format
+msgid "source file list is empty"
+msgstr "源文件列表为空"
+
+#: filemap.c:475
+#, c-format
+msgid "unexpected page modification for directory or symbolic link \"%s\""
+msgstr "对目录或符号链接\"%s\"的意料之外的页修改"
+
+#: libpq_fetch.c:51
+#, c-format
+msgid "could not connect to server: %s"
+msgstr "无法连接到服务器:%s"
+
+#: libpq_fetch.c:55
+#, c-format
+msgid "connected to server"
+msgstr "已连接服务器"
+
+#: libpq_fetch.c:59
+#, c-format
+msgid "could not clear search_path: %s"
+msgstr "无法清除search_path: %s"
+
+#: libpq_fetch.c:71
+#, c-format
+msgid "source server must not be in recovery mode"
+msgstr "源服务器不能处于恢复模式"
+
+#: libpq_fetch.c:81
+#, c-format
+msgid "full_page_writes must be enabled in the source server"
+msgstr "源服务器中的full_page_writes必须被启用"
+
+#: libpq_fetch.c:93
+#, c-format
+msgid "could not set up connection context: %s"
+msgstr "无法设置连接上下文: %s"
+
+#: libpq_fetch.c:111
+#, c-format
+msgid "error running query (%s) in source server: %s"
+msgstr "源服务器中有错误运行的查询(%s):%s"
+
+#: libpq_fetch.c:116
+#, c-format
+msgid "unexpected result set from query"
+msgstr "从查询得到意料之外的结果集"
+
+#: libpq_fetch.c:139
+#, c-format
+msgid "unrecognized result \"%s\" for current WAL insert location"
+msgstr "当前WAL插入位置的未识别结果\"%s\""
+
+#: libpq_fetch.c:189
+#, c-format
+msgid "could not fetch file list: %s"
+msgstr "无法取得文件列表:%s"
+
+#: libpq_fetch.c:194
+#, c-format
+msgid "unexpected result set while fetching file list"
+msgstr "在取得文件列表时得到意料之外的结果集"
+
+#: libpq_fetch.c:242
+#, c-format
+msgid "could not send query: %s"
+msgstr "无法发送查询:%s"
+
+#: libpq_fetch.c:247
+#, c-format
+msgid "could not set libpq connection to single row mode"
+msgstr "无法设置libpq连接为单行模式"
+
+#: libpq_fetch.c:268
+#, c-format
+msgid "unexpected result while fetching remote files: %s"
+msgstr "在取得远程文件时得到意料之外的结果:%s"
+
+#: libpq_fetch.c:274
+#, c-format
+msgid "unexpected result set size while fetching remote files"
+msgstr "在取得远程文件时得到意料之外的结果集大小"
+
+#: libpq_fetch.c:280
+#, c-format
+msgid "unexpected data types in result set while fetching remote files: %u %u %u"
+msgstr "在取得远程文件时结果集中有意料之外的数据类型:%u %u %u"
+
+#: libpq_fetch.c:288
+#, c-format
+msgid "unexpected result format while fetching remote files"
+msgstr "在取得远程文件时得到意料之外的结果格式"
+
+#: libpq_fetch.c:294
+#, c-format
+msgid "unexpected null values in result while fetching remote files"
+msgstr "在取得远程文件时结果中有意料之外的空值"
+
+#: libpq_fetch.c:298
+#, c-format
+msgid "unexpected result length while fetching remote files"
+msgstr "在取得远程文件时得到意料之外的结果长度"
+
+#: libpq_fetch.c:364
+#, c-format
+msgid "could not fetch remote file \"%s\": %s"
+msgstr "无法取得远程文件\"%s\": %s"
+
+#: libpq_fetch.c:369
+#, c-format
+msgid "unexpected result set while fetching remote file \"%s\""
+msgstr "在取得远程文件\"%s\"时得到意料之外的结果集"
+
+#: libpq_fetch.c:413
+#, c-format
+msgid "could not send COPY data: %s"
+msgstr "无法发送COPY数据:%s"
+
+#: libpq_fetch.c:439
+#, c-format
+msgid "could not create temporary table: %s"
+msgstr "无法创建临时表:%s"
+
+#: libpq_fetch.c:447
+#, c-format
+msgid "could not send file list: %s"
+msgstr "无法发送文件列表:%s"
+
+#: libpq_fetch.c:489
+#, c-format
+msgid "could not send end-of-COPY: %s"
+msgstr "无法发送COPY结束标记:%s"
+
+#: libpq_fetch.c:495
+#, c-format
+msgid "unexpected result while sending file list: %s"
+msgstr "在发送文件列表时得到意料之外的结果:%s"
+
+#: parsexlog.c:74 parsexlog.c:128 parsexlog.c:186
+#, c-format
+msgid "out of memory"
+msgstr "内存用尽"
+
+#: parsexlog.c:87 parsexlog.c:134
+#, c-format
+msgid "could not read WAL record at %X/%X: %s"
+msgstr "无法读取%X/%X处的WAL记录:%s"
+
+#: parsexlog.c:91 parsexlog.c:137
+#, c-format
+msgid "could not read WAL record at %X/%X"
+msgstr "无法读取%X/%X处的WAL记录"
+
+#: parsexlog.c:198
+#, c-format
+msgid "could not find previous WAL record at %X/%X: %s"
+msgstr "无法在%X/%X找到前一个WAL记录:%s"
+
+#: parsexlog.c:202
+#, c-format
+msgid "could not find previous WAL record at %X/%X"
+msgstr "无法在%X/%X找到前一个WAL记录"
+
+#: parsexlog.c:293
+#, c-format
+msgid "could not open file \"%s\": %m"
+msgstr "无法打开文件 \"%s\": %m"
+
+#: parsexlog.c:306
+#, c-format
+msgid "could not seek in file \"%s\": %m"
+msgstr "无法在文件\"%s\"进行查找: %m"
+
+#: parsexlog.c:386
+#, c-format
+msgid "WAL record modifies a relation, but record type is not recognized: lsn: %X/%X, rmgr: %s, info: %02X"
+msgstr "WAL记录修改了一个关系,但是记录类型无法识别: lsn: %X/%X, rmgr: %s, info: %02X"
+
+#: pg_rewind.c:72
+#, c-format
+msgid ""
+"%s resynchronizes a PostgreSQL cluster with another copy of the cluster.\n"
+"\n"
+msgstr ""
+"%s用一个PostgreSQL集簇的另一个拷贝重新同步了该集簇。\n"
+"\n"
+
+#: pg_rewind.c:73
+#, c-format
+msgid ""
+"Usage:\n"
+" %s [OPTION]...\n"
+"\n"
+msgstr ""
+"用法:\n"
+" %s [选项]...\n"
+"\n"
+
+#: pg_rewind.c:74
+#, c-format
+msgid "Options:\n"
+msgstr "选项:\n"
+
+#: pg_rewind.c:75
+#, c-format
+msgid " -D, --target-pgdata=DIRECTORY existing data directory to modify\n"
+msgstr " -D, --target-pgdata=DIRECTORY 已有的要修改的数据目录\n"
+
+#: pg_rewind.c:76
+#, c-format
+msgid " --source-pgdata=DIRECTORY source data directory to synchronize with\n"
+msgstr " --source-pgdata=DIRECTORY 要与之同步的源数据目录\n"
+
+#: pg_rewind.c:77
+#, c-format
+msgid " --source-server=CONNSTR source server to synchronize with\n"
+msgstr " --source-server=CONNSTR 要与之同步的源服务器\n"
+
+#: pg_rewind.c:78
+#, c-format
+msgid " -n, --dry-run stop before modifying anything\n"
+msgstr " -n, --dry-run 在修改任何东西之前停止\n"
+
+#: pg_rewind.c:79
+#, c-format
+msgid ""
+" -N, --no-sync do not wait for changes to be written\n"
+" safely to disk\n"
+msgstr ""
+" -N, --no-sync 不用等待变化安全\n"
+" 写入磁盘\n"
+
+#: pg_rewind.c:81
+#, c-format
+msgid " -P, --progress write progress messages\n"
+msgstr " -P, --progress 写出进度消息\n"
+
+#: pg_rewind.c:82
+#, c-format
+msgid " --debug write a lot of debug messages\n"
+msgstr " --debug 写出很多调试消息\n"
+
+#: pg_rewind.c:83
+#, c-format
+msgid " -V, --version output version information, then exit\n"
+msgstr " -V, --version 输出版本信息,然后退出\n"
+
+#: pg_rewind.c:84
+#, c-format
+msgid " -?, --help show this help, then exit\n"
+msgstr " -?, --help 显示本帮助,然后退出\n"
+
+#: pg_rewind.c:85
+#, c-format
+msgid ""
+"\n"
+"Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"
+msgstr ""
+"\n"
+"报告错误至 <pgsql-bugs@lists.postgresql.org>.\n"
+
+#: pg_rewind.c:142 pg_rewind.c:178 pg_rewind.c:185 pg_rewind.c:192
+#: pg_rewind.c:200
+#, c-format
+msgid "Try \"%s --help\" for more information.\n"
+msgstr "请用 \"%s --help\" 获取更多的信息.\n"
+
+#: pg_rewind.c:177
+#, c-format
+msgid "no source specified (--source-pgdata or --source-server)"
+msgstr "没有指定源 (--source-pgdata 或者 --source-server)"
+
+#: pg_rewind.c:184
+#, c-format
+msgid "only one of --source-pgdata or --source-server can be specified"
+msgstr "只能指定--source-pgdata和--source-server这两个选项之一"
+
+#: pg_rewind.c:191
+#, c-format
+msgid "no target data directory specified (--target-pgdata)"
+msgstr "没有指定目标数据目录 (--target-pgdata)"
+
+#: pg_rewind.c:198
+#, c-format
+msgid "too many command-line arguments (first is \"%s\")"
+msgstr "命令行参数太多 (第一个是 \"%s\")"
+
+#: pg_rewind.c:213
+#, c-format
+msgid "cannot be executed by \"root\""
+msgstr "不能由\"root\"执行"
+
+#: pg_rewind.c:214
+#, c-format
+msgid "You must run %s as the PostgreSQL superuser.\n"
+msgstr "您现在作为PostgreSQL超级用户运行%s.\n"
+
+#: pg_rewind.c:225
+#, c-format
+msgid "could not read permissions of directory \"%s\": %m"
+msgstr "没有读取目录 \"%s\" 的权限: %m"
+
+#: pg_rewind.c:256
+#, c-format
+msgid "source and target cluster are on the same timeline"
+msgstr "源集簇和目标集簇处于同一时间线"
+
+#: pg_rewind.c:262
+#, c-format
+msgid "servers diverged at WAL location %X/%X on timeline %u"
+msgstr "服务器在时间线%3$u上的WAL位置%1$X/%2$X处发生了分歧"
+
+#: pg_rewind.c:299
+#, c-format
+msgid "no rewind required"
+msgstr "不需要倒带(rewind)"
+
+#: pg_rewind.c:306
+#, c-format
+msgid "rewinding from last common checkpoint at %X/%X on timeline %u"
+msgstr "从时间线%3$u上%1$X/%2$X处的最后一个普通检查点倒带"
+
+#: pg_rewind.c:315
+#, c-format
+msgid "reading source file list"
+msgstr "读取源文件列表"
+
+#: pg_rewind.c:318
+#, c-format
+msgid "reading target file list"
+msgstr "读取目标文件列表"
+
+#: pg_rewind.c:329
+#, c-format
+msgid "reading WAL in target"
+msgstr "读取目标中的WAL"
+
+#: pg_rewind.c:346
+#, c-format
+msgid "need to copy %lu MB (total source directory size is %lu MB)"
+msgstr "需要复制 %lu MB(整个源目录的大小是 %lu MB)"
+
+#: pg_rewind.c:365
+#, c-format
+msgid "creating backup label and updating control file"
+msgstr "正在创建备份标签并且更新控制文件"
+
+#: pg_rewind.c:394
+#, c-format
+msgid "syncing target data directory"
+msgstr "正在同步目标数据目录"
+
+#: pg_rewind.c:397
+#, c-format
+msgid "Done!"
+msgstr "完成!"
+
+#: pg_rewind.c:409
+#, c-format
+msgid "source and target clusters are from different systems"
+msgstr "源集簇和目标集簇来自不同的系统"
+
+#: pg_rewind.c:417
+#, c-format
+msgid "clusters are not compatible with this version of pg_rewind"
+msgstr "集簇与这个pg_rewind的版本不兼容"
+
+#: pg_rewind.c:427
+#, c-format
+msgid "target server needs to use either data checksums or \"wal_log_hints = on\""
+msgstr "目标服务器需要使用数据校验和或者让\"wal_log_hints = on\""
+
+#: pg_rewind.c:438
+#, c-format
+msgid "target server must be shut down cleanly"
+msgstr "目标服务器必须被干净地关闭"
+
+#: pg_rewind.c:448
+#, c-format
+msgid "source data directory must be shut down cleanly"
+msgstr "源数据目录必须被干净地关闭"
+
+#: pg_rewind.c:497
+#, c-format
+msgid "%*s/%s kB (%d%%) copied"
+msgstr "已复制%*s/%s kB (%d%%)"
+
+#: pg_rewind.c:558
+#, c-format
+msgid "invalid control file\n"
+msgstr "无效的控制文件\n"
+
+#: pg_rewind.c:642
+#, c-format
+msgid "could not find common ancestor of the source and target cluster's timelines"
+msgstr "无法找到源集簇和目标集簇的时间线的共同祖先"
+
+#: pg_rewind.c:683
+#, c-format
+msgid "backup label buffer too small"
+msgstr "备份标签缓冲太小"
+
+#: pg_rewind.c:706
+#, c-format
+msgid "unexpected control file CRC"
+msgstr "意料之外的控制文件CRC"
+
+#: pg_rewind.c:716
+#, c-format
+msgid "unexpected control file size %d, expected %d"
+msgstr "意料之外的控制文件大小%d,应该是%d"
+
+#: pg_rewind.c:725
+#, c-format
+msgid "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d byte"
+msgid_plural "WAL segment size must be a power of two between 1 MB and 1 GB, but the control file specifies %d bytes"
+msgstr[0] "WAL段大小必须是1 MB到1 GB之间的2的幂,但控制文件指定了%d字节"
+msgstr[1] "WAL段大小必须是1 MB到1 GB之间的2的幂,但控制文件指定了%d字节"
+
+#: timeline.c:76 timeline.c:82
+#, c-format
+msgid "syntax error in history file: %s"
+msgstr "历史文件中的语法错误: %s"
+
+#: timeline.c:77
+#, c-format
+msgid "Expected a numeric timeline ID."
+msgstr "期望一个数字 timeline ID."
+
+#: timeline.c:83
+#, c-format
+msgid "Expected a write-ahead log switchpoint location."
+msgstr "期望一个预写日志切换点位置."
+
+#: timeline.c:88
+#, c-format
+msgid "invalid data in history file: %s"
+msgstr "历史文件中的无效数据: %s"
+
+#: timeline.c:89
+#, c-format
+msgid "Timeline IDs must be in increasing sequence."
+msgstr "TimeLine ID 必须为递增序列."
+
+#: timeline.c:109
+#, c-format
+msgid "invalid data in history file"
+msgstr "历史文件中有无效数据"
+
+#: timeline.c:110
+#, c-format
+msgid "Timeline IDs must be less than child timeline's ID."
+msgstr "Timeline ID 必须小于子 timeline 的 ID."
+
+#: xlogreader.c:299
+#, c-format
+msgid "invalid record offset at %X/%X"
+msgstr "%X/%X处有无效的记录偏移量"
+
+#: xlogreader.c:307
+#, c-format
+msgid "contrecord is requested by %X/%X"
+msgstr "%X/%X请求继续记录(contrecord)"
+
+#: xlogreader.c:348 xlogreader.c:645
+#, c-format
+msgid "invalid record length at %X/%X: wanted %u, got %u"
+msgstr "%X/%X处有无效记录长度: 应该是%u, 但实际是%u"
+
+#: xlogreader.c:372
+#, c-format
+msgid "record length %u at %X/%X too long"
+msgstr "%2$X/%3$X处有的记录长度%1$u过长"
+
+#: xlogreader.c:404
+#, c-format
+msgid "there is no contrecord flag at %X/%X"
+msgstr "%X/%X处没有继续记录标志"
+
+#: xlogreader.c:417
+#, c-format
+msgid "invalid contrecord length %u at %X/%X"
+msgstr "%2$X/%3$X处有无效的继续记录长度%1$u"
+
+#: xlogreader.c:653
+#, c-format
+msgid "invalid resource manager ID %u at %X/%X"
+msgstr "%2$X/%3$X处有无效的资源管理器 ID %1$u"
+
+#: xlogreader.c:667 xlogreader.c:684
+#, c-format
+msgid "record with incorrect prev-link %X/%X at %X/%X"
+msgstr "%3$X/%4$X处的记录有不正确的prev-link %1$X/%2$X"
+
+#: xlogreader.c:721
+#, c-format
+msgid "incorrect resource manager data checksum in record at %X/%X"
+msgstr "%X/%X处的记录中有不正确的资源管理器数据校验和"
+
+#: xlogreader.c:758
+#, c-format
+msgid "invalid magic number %04X in log segment %s, offset %u"
+msgstr "在日志段%2$s的偏移量%3$u处有无效的magic号%1$04X"
+
+#: xlogreader.c:772 xlogreader.c:823
+#, c-format
+msgid "invalid info bits %04X in log segment %s, offset %u"
+msgstr "在日志段%2$s的偏移量%3$u处有无效的info位%1$04X"
+
+#: xlogreader.c:798
+#, c-format
+msgid "WAL file is from different database system: WAL file database system identifier is %s, pg_control database system identifier is %s"
+msgstr "WAL文件来自于不同的数据库系统:WAL文件数据库系统标识符是%s,pg_control数据库系统标识符是%s"
+
+#: xlogreader.c:805
+#, c-format
+msgid "WAL file is from different database system: incorrect segment size in page header"
+msgstr "WAL文件来自于不同的数据库系统:页头部中有不正确的段大小"
+
+#: xlogreader.c:811
+#, c-format
+msgid "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header"
+msgstr "WAL文件来自于不同的数据库系统:页头部中有不正确的XLOG_BLCKSZ"
+
+#: xlogreader.c:842
+#, c-format
+msgid "unexpected pageaddr %X/%X in log segment %s, offset %u"
+msgstr "在日志段%3$s的偏移量%4$u处有意料之外的pageaddr %1$X/%2$X"
+
+#: xlogreader.c:867
+#, c-format
+msgid "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u"
+msgstr "在日志段%3$s的偏移量%4$u处有失序的时间线 ID %1$u(在%2$u之后)"
+
+#: xlogreader.c:1112
+#, c-format
+msgid "out-of-order block_id %u at %X/%X"
+msgstr "在%2$X/%3$X处有无序的block_id %1$u"
+
+#: xlogreader.c:1135
+#, c-format
+msgid "BKPBLOCK_HAS_DATA set, but no data included at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA已被设置,但是在%X/%X处没有包括数据"
+
+#: xlogreader.c:1142
+#, c-format
+msgid "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X"
+msgstr "BKPBLOCK_HAS_DATA没有被设置,但是在%2$X/%3$X处的数据长度为%1$u"
+
+#: xlogreader.c:1178
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE已被设置,但是%4$X/%5$X处记录了洞偏移量为%1$u、长度为%2$u、块映像长度为%3$u"
+
+#: xlogreader.c:1194
+#, c-format
+msgid "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE没有被设置,但是%3$X/%4$X处记录了洞偏移量为%1$u、长度为%2$u"
+
+#: xlogreader.c:1209
+#, c-format
+msgid "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X"
+msgstr "BKPIMAGE_IS_COMPRESSED已被设置,但是%2$X/%3$X处记录的块映像长度为%1$u"
+
+#: xlogreader.c:1224
+#, c-format
+msgid "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X"
+msgstr "BKPIMAGE_HAS_HOLE和BKPIMAGE_IS_COMPRESSED都没有被设置,但是%2$X/%3$X处记录的块映像长度为%1$u"
+
+#: xlogreader.c:1240
+#, c-format
+msgid "BKPBLOCK_SAME_REL set but no previous rel at %X/%X"
+msgstr "BKPBLOCK_SAME_REL已被设置,但是在%X/%X没有前一个关系"
+
+#: xlogreader.c:1252
+#, c-format
+msgid "invalid block_id %u at %X/%X"
+msgstr "%2$X/%3$X处有无效block_id %1$u"
+
+#: xlogreader.c:1341
+#, c-format
+msgid "record with invalid length at %X/%X"
+msgstr "%X/%X处的记录的长度无效"
+
+#: xlogreader.c:1430
+#, c-format
+msgid "invalid compressed image at %X/%X, block %d"
+msgstr "%X/%X处是块%d的无效压缩映像"
diff --git a/src/bin/pg_rewind/t/001_basic.pl b/src/bin/pg_rewind/t/001_basic.pl
new file mode 100644
index 0000000..d97e437
--- /dev/null
+++ b/src/bin/pg_rewind/t/001_basic.pl
@@ -0,0 +1,176 @@
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 20;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+sub run_test
+{
+ my $test_mode = shift;
+
+ RewindTest::setup_cluster($test_mode);
+ RewindTest::start_master();
+
+ # Create a test table and insert a row in master.
+ master_psql("CREATE TABLE tbl1 (d text)");
+ master_psql("INSERT INTO tbl1 VALUES ('in master')");
+
+ # This test table will be used to test truncation, i.e. the table
+ # is extended in the old master after promotion
+ master_psql("CREATE TABLE trunc_tbl (d text)");
+ master_psql("INSERT INTO trunc_tbl VALUES ('in master')");
+
+ # This test table will be used to test the "copy-tail" case, i.e. the
+ # table is truncated in the old master after promotion
+ master_psql("CREATE TABLE tail_tbl (id integer, d text)");
+ master_psql("INSERT INTO tail_tbl VALUES (0, 'in master')");
+
+ master_psql("CHECKPOINT");
+
+ RewindTest::create_standby($test_mode);
+
+ # Insert additional data on master that will be replicated to standby
+ master_psql("INSERT INTO tbl1 values ('in master, before promotion')");
+ master_psql(
+ "INSERT INTO trunc_tbl values ('in master, before promotion')");
+ master_psql(
+ "INSERT INTO tail_tbl SELECT g, 'in master, before promotion: ' || g FROM generate_series(1, 10000) g"
+ );
+
+ master_psql('CHECKPOINT');
+
+ RewindTest::promote_standby();
+
+ # Insert a row in the old master. This causes the master and standby
+ # to have "diverged", it's no longer possible to just apply the
+ # standy's logs over master directory - you need to rewind.
+ master_psql("INSERT INTO tbl1 VALUES ('in master, after promotion')");
+
+ # Also insert a new row in the standby, which won't be present in the
+ # old master.
+ standby_psql("INSERT INTO tbl1 VALUES ('in standby, after promotion')");
+
+ # Insert enough rows to trunc_tbl to extend the file. pg_rewind should
+ # truncate it back to the old size.
+ master_psql(
+ "INSERT INTO trunc_tbl SELECT 'in master, after promotion: ' || g FROM generate_series(1, 10000) g"
+ );
+
+ # Truncate tail_tbl. pg_rewind should copy back the truncated part
+ # (We cannot use an actual TRUNCATE command here, as that creates a
+ # whole new relfilenode)
+ master_psql("DELETE FROM tail_tbl WHERE id > 10");
+ master_psql("VACUUM tail_tbl");
+
+ # Before running pg_rewind, do a couple of extra tests with several
+ # option combinations. As the code paths taken by those tests
+ # do not change for the "local" and "remote" modes, just run them
+ # in "local" mode for simplicity's sake.
+ if ($test_mode eq 'local')
+ {
+ my $master_pgdata = $node_master->data_dir;
+ my $standby_pgdata = $node_standby->data_dir;
+
+ # First check that pg_rewind fails if the target cluster is
+ # not stopped as it fails to start up for the forced recovery
+ # step.
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $master_pgdata,
+ '--no-sync'
+ ],
+ 'pg_rewind with running target');
+
+ # Again with --no-ensure-shutdown, which should equally fail.
+ # This time pg_rewind complains without attempting to perform
+ # recovery once.
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $master_pgdata,
+ '--no-sync', '--no-ensure-shutdown'
+ ],
+ 'pg_rewind --no-ensure-shutdown with running target');
+
+ # Stop the target, and attempt to run with a local source
+ # still running. This fails as pg_rewind requires to have
+ # a source cleanly stopped.
+ $node_master->stop;
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $master_pgdata,
+ '--no-sync', '--no-ensure-shutdown'
+ ],
+ 'pg_rewind with unexpected running source');
+
+ # Stop the target cluster cleanly, and run again pg_rewind
+ # with --dry-run mode. If anything gets generated in the data
+ # folder, the follow-up run of pg_rewind will most likely fail,
+ # so keep this test as the last one of this subset.
+ $node_standby->stop;
+ command_ok(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $master_pgdata,
+ '--no-sync', '--dry-run'
+ ],
+ 'pg_rewind --dry-run');
+
+ # Both clusters need to be alive moving forward.
+ $node_standby->start;
+ $node_master->start;
+ }
+
+ RewindTest::run_pg_rewind($test_mode);
+
+ check_query(
+ 'SELECT * FROM tbl1',
+ qq(in master
+in master, before promotion
+in standby, after promotion
+),
+ 'table content');
+
+ check_query(
+ 'SELECT * FROM trunc_tbl',
+ qq(in master
+in master, before promotion
+),
+ 'truncation');
+
+ check_query(
+ 'SELECT count(*) FROM tail_tbl',
+ qq(10001
+),
+ 'tail-copy');
+
+ # Permissions on PGDATA should be default
+ SKIP:
+ {
+ skip "unix-style permissions not supported on Windows", 1
+ if ($windows_os);
+
+ ok(check_mode_recursive($node_master->data_dir(), 0700, 0600),
+ 'check PGDATA permissions');
+ }
+
+ RewindTest::clean_rewind_test();
+ return;
+}
+
+# Run the test in both modes
+run_test('local');
+run_test('remote');
+run_test('archive');
+
+exit(0);
diff --git a/src/bin/pg_rewind/t/002_databases.pl b/src/bin/pg_rewind/t/002_databases.pl
new file mode 100644
index 0000000..1db534c
--- /dev/null
+++ b/src/bin/pg_rewind/t/002_databases.pl
@@ -0,0 +1,74 @@
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 7;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+sub run_test
+{
+ my $test_mode = shift;
+
+ RewindTest::setup_cluster($test_mode, ['-g']);
+ RewindTest::start_master();
+
+ # Create a database in master with a table.
+ master_psql('CREATE DATABASE inmaster');
+ master_psql('CREATE TABLE inmaster_tab (a int)', 'inmaster');
+
+ RewindTest::create_standby($test_mode);
+
+ # Create another database with another table, the creation is
+ # replicated to the standby.
+ master_psql('CREATE DATABASE beforepromotion');
+ master_psql('CREATE TABLE beforepromotion_tab (a int)',
+ 'beforepromotion');
+
+ RewindTest::promote_standby();
+
+ # Create databases in the old master and the new promoted standby.
+ master_psql('CREATE DATABASE master_afterpromotion');
+ master_psql('CREATE TABLE master_promotion_tab (a int)',
+ 'master_afterpromotion');
+ standby_psql('CREATE DATABASE standby_afterpromotion');
+ standby_psql('CREATE TABLE standby_promotion_tab (a int)',
+ 'standby_afterpromotion');
+
+ # The clusters are now diverged.
+
+ RewindTest::run_pg_rewind($test_mode);
+
+ # Check that the correct databases are present after pg_rewind.
+ check_query(
+ 'SELECT datname FROM pg_database ORDER BY 1',
+ qq(beforepromotion
+inmaster
+postgres
+standby_afterpromotion
+template0
+template1
+),
+ 'database names');
+
+ # Permissions on PGDATA should have group permissions
+ SKIP:
+ {
+ skip "unix-style permissions not supported on Windows", 1
+ if ($windows_os);
+
+ ok(check_mode_recursive($node_master->data_dir(), 0750, 0640),
+ 'check PGDATA permissions');
+ }
+
+ RewindTest::clean_rewind_test();
+ return;
+}
+
+# Run the test in both modes.
+run_test('local');
+run_test('remote');
+
+exit(0);
diff --git a/src/bin/pg_rewind/t/003_extrafiles.pl b/src/bin/pg_rewind/t/003_extrafiles.pl
new file mode 100644
index 0000000..f471044
--- /dev/null
+++ b/src/bin/pg_rewind/t/003_extrafiles.pl
@@ -0,0 +1,94 @@
+# Test how pg_rewind reacts to extra files and directories in the data dirs.
+
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 5;
+
+use File::Find;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+
+sub run_test
+{
+ my $test_mode = shift;
+
+ RewindTest::setup_cluster($test_mode);
+ RewindTest::start_master();
+
+ my $test_master_datadir = $node_master->data_dir;
+
+ # Create a subdir and files that will be present in both
+ mkdir "$test_master_datadir/tst_both_dir";
+ append_to_file "$test_master_datadir/tst_both_dir/both_file1", "in both1";
+ append_to_file "$test_master_datadir/tst_both_dir/both_file2", "in both2";
+ mkdir "$test_master_datadir/tst_both_dir/both_subdir/";
+ append_to_file "$test_master_datadir/tst_both_dir/both_subdir/both_file3",
+ "in both3";
+
+ RewindTest::create_standby($test_mode);
+
+ # Create different subdirs and files in master and standby
+ my $test_standby_datadir = $node_standby->data_dir;
+
+ mkdir "$test_standby_datadir/tst_standby_dir";
+ append_to_file "$test_standby_datadir/tst_standby_dir/standby_file1",
+ "in standby1";
+ append_to_file "$test_standby_datadir/tst_standby_dir/standby_file2",
+ "in standby2";
+ mkdir "$test_standby_datadir/tst_standby_dir/standby_subdir/";
+ append_to_file
+ "$test_standby_datadir/tst_standby_dir/standby_subdir/standby_file3",
+ "in standby3";
+
+ mkdir "$test_master_datadir/tst_master_dir";
+ append_to_file "$test_master_datadir/tst_master_dir/master_file1",
+ "in master1";
+ append_to_file "$test_master_datadir/tst_master_dir/master_file2",
+ "in master2";
+ mkdir "$test_master_datadir/tst_master_dir/master_subdir/";
+ append_to_file
+ "$test_master_datadir/tst_master_dir/master_subdir/master_file3",
+ "in master3";
+
+ RewindTest::promote_standby();
+ RewindTest::run_pg_rewind($test_mode);
+
+ # List files in the data directory after rewind.
+ my @paths;
+ find(
+ sub {
+ push @paths, $File::Find::name
+ if $File::Find::name =~ m/.*tst_.*/;
+ },
+ $test_master_datadir);
+ @paths = sort @paths;
+ is_deeply(
+ \@paths,
+ [
+ "$test_master_datadir/tst_both_dir",
+ "$test_master_datadir/tst_both_dir/both_file1",
+ "$test_master_datadir/tst_both_dir/both_file2",
+ "$test_master_datadir/tst_both_dir/both_subdir",
+ "$test_master_datadir/tst_both_dir/both_subdir/both_file3",
+ "$test_master_datadir/tst_standby_dir",
+ "$test_master_datadir/tst_standby_dir/standby_file1",
+ "$test_master_datadir/tst_standby_dir/standby_file2",
+ "$test_master_datadir/tst_standby_dir/standby_subdir",
+ "$test_master_datadir/tst_standby_dir/standby_subdir/standby_file3"
+ ],
+ "file lists match");
+
+ RewindTest::clean_rewind_test();
+ return;
+}
+
+# Run the test in both modes.
+run_test('local');
+run_test('remote');
+
+exit(0);
diff --git a/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl
new file mode 100644
index 0000000..639eeb9
--- /dev/null
+++ b/src/bin/pg_rewind/t/004_pg_xlog_symlink.pl
@@ -0,0 +1,85 @@
+#
+# Test pg_rewind when the target's pg_wal directory is a symlink.
+#
+use strict;
+use warnings;
+use File::Copy;
+use File::Path qw(rmtree);
+use TestLib;
+use Test::More;
+if ($windows_os)
+{
+ plan skip_all => 'symlinks not supported on Windows';
+ exit;
+}
+else
+{
+ plan tests => 5;
+}
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+sub run_test
+{
+ my $test_mode = shift;
+
+ my $master_xlogdir = "${TestLib::tmp_check}/xlog_master";
+
+ rmtree($master_xlogdir);
+ RewindTest::setup_cluster($test_mode);
+
+ my $test_master_datadir = $node_master->data_dir;
+
+ # turn pg_wal into a symlink
+ print("moving $test_master_datadir/pg_wal to $master_xlogdir\n");
+ move("$test_master_datadir/pg_wal", $master_xlogdir) or die;
+ symlink($master_xlogdir, "$test_master_datadir/pg_wal") or die;
+
+ RewindTest::start_master();
+
+ # Create a test table and insert a row in master.
+ master_psql("CREATE TABLE tbl1 (d text)");
+ master_psql("INSERT INTO tbl1 VALUES ('in master')");
+
+ master_psql("CHECKPOINT");
+
+ RewindTest::create_standby($test_mode);
+
+ # Insert additional data on master that will be replicated to standby
+ master_psql("INSERT INTO tbl1 values ('in master, before promotion')");
+
+ master_psql('CHECKPOINT');
+
+ RewindTest::promote_standby();
+
+ # Insert a row in the old master. This causes the master and standby
+ # to have "diverged", it's no longer possible to just apply the
+ # standy's logs over master directory - you need to rewind.
+ master_psql("INSERT INTO tbl1 VALUES ('in master, after promotion')");
+
+ # Also insert a new row in the standby, which won't be present in the
+ # old master.
+ standby_psql("INSERT INTO tbl1 VALUES ('in standby, after promotion')");
+
+ RewindTest::run_pg_rewind($test_mode);
+
+ check_query(
+ 'SELECT * FROM tbl1',
+ qq(in master
+in master, before promotion
+in standby, after promotion
+),
+ 'table content');
+
+ RewindTest::clean_rewind_test();
+ return;
+}
+
+# Run the test in both modes
+run_test('local');
+run_test('remote');
+
+exit(0);
diff --git a/src/bin/pg_rewind/t/005_same_timeline.pl b/src/bin/pg_rewind/t/005_same_timeline.pl
new file mode 100644
index 0000000..5464f42
--- /dev/null
+++ b/src/bin/pg_rewind/t/005_same_timeline.pl
@@ -0,0 +1,20 @@
+#
+# Test that running pg_rewind with the source and target clusters
+# on the same timeline runs successfully.
+#
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 1;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+RewindTest::setup_cluster();
+RewindTest::start_master();
+RewindTest::create_standby();
+RewindTest::run_pg_rewind('local');
+RewindTest::clean_rewind_test();
+exit(0);
diff --git a/src/bin/pg_rewind/t/006_options.pl b/src/bin/pg_rewind/t/006_options.pl
new file mode 100644
index 0000000..1515696
--- /dev/null
+++ b/src/bin/pg_rewind/t/006_options.pl
@@ -0,0 +1,40 @@
+#
+# Test checking options of pg_rewind.
+#
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 12;
+
+program_help_ok('pg_rewind');
+program_version_ok('pg_rewind');
+program_options_handling_ok('pg_rewind');
+
+my $primary_pgdata = TestLib::tempdir;
+my $standby_pgdata = TestLib::tempdir;
+command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--target-pgdata', $primary_pgdata,
+ '--source-pgdata', $standby_pgdata,
+ 'extra_arg1'
+ ],
+ 'too many arguments');
+command_fails([ 'pg_rewind', '--target-pgdata', $primary_pgdata ],
+ 'no source specified');
+command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--target-pgdata', $primary_pgdata,
+ '--source-pgdata', $standby_pgdata,
+ '--source-server', 'incorrect_source'
+ ],
+ 'both remote and local sources specified');
+command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--target-pgdata', $primary_pgdata,
+ '--source-pgdata', $standby_pgdata,
+ '--write-recovery-conf'
+ ],
+ 'no local source with --write-recovery-conf');
diff --git a/src/bin/pg_rewind/t/008_min_recovery_point.pl b/src/bin/pg_rewind/t/008_min_recovery_point.pl
new file mode 100644
index 0000000..e3d94b3
--- /dev/null
+++ b/src/bin/pg_rewind/t/008_min_recovery_point.pl
@@ -0,0 +1,171 @@
+#
+# Test situation where a target data directory contains
+# WAL records beyond both the last checkpoint and the divergence
+# point:
+#
+# Target WAL (TLI 2):
+#
+# backup ... Checkpoint A ... INSERT 'rewind this'
+# (TLI 1 -> 2)
+#
+# ^ last common ^ minRecoveryPoint
+# checkpoint
+#
+# Source WAL (TLI 3):
+#
+# backup ... Checkpoint A ... Checkpoint B ... INSERT 'keep this'
+# (TLI 1 -> 2) (TLI 2 -> 3)
+#
+#
+# The last common checkpoint is Checkpoint A. But there is WAL on TLI 2
+# after the last common checkpoint that needs to be rewound. We used to
+# have a bug where minRecoveryPoint was ignored, and pg_rewind concluded
+# that the target doesn't need rewinding in this scenario, because the
+# last checkpoint on the target TLI was an ancestor of the source TLI.
+#
+#
+# This test does not make use of RewindTest as it requires three
+# nodes.
+
+use strict;
+use warnings;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 3;
+
+use File::Copy;
+
+my $tmp_folder = TestLib::tempdir;
+
+my $node_1 = get_new_node('node_1');
+$node_1->init(allows_streaming => 1);
+$node_1->append_conf('postgresql.conf', qq(
+wal_keep_size='100 MB'
+));
+
+$node_1->start;
+
+# Create a couple of test tables
+$node_1->safe_psql('postgres', 'CREATE TABLE public.foo (t TEXT)');
+$node_1->safe_psql('postgres', 'CREATE TABLE public.bar (t TEXT)');
+$node_1->safe_psql('postgres', "INSERT INTO public.bar VALUES ('in both')");
+
+#
+# Create node_2 and node_3 as standbys following node_1
+#
+my $backup_name = 'my_backup';
+$node_1->backup($backup_name);
+
+my $node_2 = get_new_node('node_2');
+$node_2->init_from_backup($node_1, $backup_name,
+ has_streaming => 1);
+$node_2->start;
+
+my $node_3 = get_new_node('node_3');
+$node_3->init_from_backup($node_1, $backup_name,
+ has_streaming => 1);
+$node_3->start;
+
+# Wait until node 3 has connected and caught up
+my $lsn = $node_1->lsn('insert');
+$node_1->wait_for_catchup('node_3', 'replay', $lsn);
+
+#
+# Swap the roles of node_1 and node_3, so that node_1 follows node_3.
+#
+$node_1->stop('fast');
+$node_3->promote;
+# Force a checkpoint after the promotion. pg_rewind looks at the control
+# file to determine what timeline the server is on, and that isn't updated
+# immediately at promotion, but only at the next checkpoint. When running
+# pg_rewind in remote mode, it's possible that we complete the test steps
+# after promotion so quickly that when pg_rewind runs, the standby has not
+# performed a checkpoint after promotion yet.
+$node_3->safe_psql('postgres', "checkpoint");
+
+# reconfigure node_1 as a standby following node_3
+my $node_3_connstr = $node_3->connstr;
+$node_1->append_conf('postgresql.conf', qq(
+primary_conninfo='$node_3_connstr'
+));
+$node_1->set_standby_mode();
+$node_1->start();
+
+# also reconfigure node_2 to follow node_3
+$node_2->append_conf('postgresql.conf', qq(
+primary_conninfo='$node_3_connstr'
+));
+$node_2->restart();
+
+#
+# Promote node_1, to create a split-brain scenario.
+#
+
+# make sure node_1 is full caught up with node_3 first
+$lsn = $node_3->lsn('insert');
+$node_3->wait_for_catchup('node_1', 'replay', $lsn);
+
+$node_1->promote;
+# Force a checkpoint after promotion, like earlier.
+$node_1->safe_psql('postgres', "checkpoint");
+
+#
+# We now have a split-brain with two primaries. Insert a row on both to
+# demonstratively create a split brain. After the rewind, we should only
+# see the insert on 1, as the insert on node 3 is rewound away.
+#
+$node_1->safe_psql('postgres', "INSERT INTO public.foo (t) VALUES ('keep this')");
+# 'bar' is unmodified in node 1, so it won't be overwritten by replaying the
+# WAL from node 1.
+$node_3->safe_psql('postgres', "INSERT INTO public.bar (t) VALUES ('rewind this')");
+
+# Insert more rows in node 1, to bump up the XID counter. Otherwise, if
+# rewind doesn't correctly rewind the changes made on the other node,
+# we might fail to notice if the inserts are invisible because the XIDs
+# are not marked as committed.
+$node_1->safe_psql('postgres', "INSERT INTO public.foo (t) VALUES ('and this')");
+$node_1->safe_psql('postgres', "INSERT INTO public.foo (t) VALUES ('and this too')");
+
+# Wait for node 2 to catch up
+$node_2->poll_query_until('postgres',
+ q|SELECT COUNT(*) > 1 FROM public.bar|, 't');
+
+# At this point node_2 will shut down without a shutdown checkpoint,
+# but with WAL entries beyond the preceding shutdown checkpoint.
+$node_2->stop('fast');
+$node_3->stop('fast');
+
+my $node_2_pgdata = $node_2->data_dir;
+my $node_1_connstr = $node_1->connstr;
+
+# Keep a temporary postgresql.conf or it would be overwritten during the rewind.
+copy(
+ "$node_2_pgdata/postgresql.conf",
+ "$tmp_folder/node_2-postgresql.conf.tmp");
+
+command_ok(
+ [
+ 'pg_rewind',
+ "--source-server=$node_1_connstr",
+ "--target-pgdata=$node_2_pgdata",
+ "--debug"
+ ],
+ 'run pg_rewind');
+
+# Now move back postgresql.conf with old settings
+move(
+ "$tmp_folder/node_2-postgresql.conf.tmp",
+ "$node_2_pgdata/postgresql.conf");
+
+$node_2->start;
+
+# Check contents of the test tables after rewind. The rows inserted in node 3
+# before rewind should've been overwritten with the data from node 1.
+my $result;
+$result = $node_2->safe_psql('postgres', 'SELECT * FROM public.foo');
+is($result, qq(keep this
+and this
+and this too), 'table foo after rewind');
+
+$result = $node_2->safe_psql('postgres', 'SELECT * FROM public.bar');
+is($result, qq(in both), 'table bar after rewind');
diff --git a/src/bin/pg_rewind/t/RewindTest.pm b/src/bin/pg_rewind/t/RewindTest.pm
new file mode 100644
index 0000000..422a563
--- /dev/null
+++ b/src/bin/pg_rewind/t/RewindTest.pm
@@ -0,0 +1,394 @@
+package RewindTest;
+
+# Test driver for pg_rewind. Each test consists of a cycle where a new cluster
+# is first created with initdb, and a streaming replication standby is set up
+# to follow the master. Then the master is shut down and the standby is
+# promoted, and finally pg_rewind is used to rewind the old master, using the
+# standby as the source.
+#
+# To run a test, the test script (in t/ subdirectory) calls the functions
+# in this module. These functions should be called in this sequence:
+#
+# 1. setup_cluster - creates a PostgreSQL cluster that runs as the master
+#
+# 2. start_master - starts the master server
+#
+# 3. create_standby - runs pg_basebackup to initialize a standby server, and
+# sets it up to follow the master.
+#
+# 4. promote_standby - runs "pg_ctl promote" to promote the standby server.
+# The old master keeps running.
+#
+# 5. run_pg_rewind - stops the old master (if it's still running) and runs
+# pg_rewind to synchronize it with the now-promoted standby server.
+#
+# 6. clean_rewind_test - stops both servers used in the test, if they're
+# still running.
+#
+# The test script can use the helper functions master_psql and standby_psql
+# to run psql against the master and standby servers, respectively.
+
+use strict;
+use warnings;
+
+use Carp;
+use Config;
+use Exporter 'import';
+use File::Copy;
+use File::Path qw(rmtree);
+use IPC::Run qw(run);
+use PostgresNode;
+use RecursiveCopy;
+use TestLib;
+use Test::More;
+
+our @EXPORT = qw(
+ $node_master
+ $node_standby
+
+ master_psql
+ standby_psql
+ check_query
+
+ setup_cluster
+ start_master
+ create_standby
+ promote_standby
+ run_pg_rewind
+ clean_rewind_test
+);
+
+# Our nodes.
+our $node_master;
+our $node_standby;
+
+sub master_psql
+{
+ my $cmd = shift;
+ my $dbname = shift || 'postgres';
+
+ system_or_bail 'psql', '-q', '--no-psqlrc', '-d',
+ $node_master->connstr($dbname), '-c', "$cmd";
+ return;
+}
+
+sub standby_psql
+{
+ my $cmd = shift;
+ my $dbname = shift || 'postgres';
+
+ system_or_bail 'psql', '-q', '--no-psqlrc', '-d',
+ $node_standby->connstr($dbname), '-c', "$cmd";
+ return;
+}
+
+# Run a query against the master, and check that the output matches what's
+# expected
+sub check_query
+{
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my ($query, $expected_stdout, $test_name) = @_;
+ my ($stdout, $stderr);
+
+ # we want just the output, no formatting
+ my $result = run [
+ 'psql', '-q', '-A', '-t', '--no-psqlrc', '-d',
+ $node_master->connstr('postgres'),
+ '-c', $query
+ ],
+ '>', \$stdout, '2>', \$stderr;
+
+ # We don't use ok() for the exit code and stderr, because we want this
+ # check to be just a single test.
+ if (!$result)
+ {
+ fail("$test_name: psql exit code");
+ }
+ elsif ($stderr ne '')
+ {
+ diag $stderr;
+ fail("$test_name: psql no stderr");
+ }
+ else
+ {
+ $stdout =~ s/\r\n/\n/g if $Config{osname} eq 'msys';
+ is($stdout, $expected_stdout, "$test_name: query result matches");
+ }
+ return;
+}
+
+sub setup_cluster
+{
+ my $extra_name = shift; # Used to differentiate clusters
+ my $extra = shift; # Extra params for initdb
+
+ # Initialize master, data checksums are mandatory
+ $node_master =
+ get_new_node('master' . ($extra_name ? "_${extra_name}" : ''));
+
+ # Set up pg_hba.conf and pg_ident.conf for the role running
+ # pg_rewind. This role is used for all the tests, and has
+ # minimal permissions enough to rewind from an online source.
+ $node_master->init(
+ allows_streaming => 1,
+ extra => $extra,
+ auth_extra => [ '--create-role', 'rewind_user' ]);
+
+ # Set wal_keep_size to prevent WAL segment recycling after enforced
+ # checkpoints in the tests.
+ $node_master->append_conf(
+ 'postgresql.conf', qq(
+wal_keep_size = 320MB
+));
+ return;
+}
+
+sub start_master
+{
+ $node_master->start;
+
+ # Create custom role which is used to run pg_rewind, and adjust its
+ # permissions to the minimum necessary.
+ $node_master->safe_psql(
+ 'postgres', "
+ CREATE ROLE rewind_user LOGIN;
+ GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text, boolean, boolean)
+ TO rewind_user;
+ GRANT EXECUTE ON function pg_catalog.pg_stat_file(text, boolean)
+ TO rewind_user;
+ GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text)
+ TO rewind_user;
+ GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text, bigint, bigint, boolean)
+ TO rewind_user;");
+
+ #### Now run the test-specific parts to initialize the master before setting
+ # up standby
+
+ return;
+}
+
+sub create_standby
+{
+ my $extra_name = shift;
+
+ $node_standby =
+ get_new_node('standby' . ($extra_name ? "_${extra_name}" : ''));
+ $node_master->backup('my_backup');
+ $node_standby->init_from_backup($node_master, 'my_backup');
+ my $connstr_master = $node_master->connstr();
+
+ $node_standby->append_conf(
+ "postgresql.conf", qq(
+primary_conninfo='$connstr_master'
+));
+
+ $node_standby->set_standby_mode();
+
+ # Start standby
+ $node_standby->start;
+
+ # The standby may have WAL to apply before it matches the primary. That
+ # is fine, because no test examines the standby before promotion.
+
+ return;
+}
+
+sub promote_standby
+{
+ #### Now run the test-specific parts to run after standby has been started
+ # up standby
+
+ # Wait for the standby to receive and write all WAL.
+ $node_master->wait_for_catchup($node_standby, 'write');
+
+ # Now promote standby and insert some new data on master, this will put
+ # the master out-of-sync with the standby.
+ $node_standby->promote;
+
+ # Force a checkpoint after the promotion. pg_rewind looks at the control
+ # file to determine what timeline the server is on, and that isn't updated
+ # immediately at promotion, but only at the next checkpoint. When running
+ # pg_rewind in remote mode, it's possible that we complete the test steps
+ # after promotion so quickly that when pg_rewind runs, the standby has not
+ # performed a checkpoint after promotion yet.
+ standby_psql("checkpoint");
+
+ return;
+}
+
+sub run_pg_rewind
+{
+ my $test_mode = shift;
+ my $master_pgdata = $node_master->data_dir;
+ my $standby_pgdata = $node_standby->data_dir;
+ my $standby_connstr = $node_standby->connstr('postgres');
+ my $tmp_folder = TestLib::tempdir;
+
+ # Append the rewind-specific role to the connection string.
+ $standby_connstr = "$standby_connstr user=rewind_user";
+
+ if ($test_mode eq 'archive')
+ {
+ # pg_rewind is tested with --restore-target-wal by moving all
+ # WAL files to a secondary location. Note that this leads to
+ # a failure in ensureCleanShutdown(), forcing to the use of
+ # --no-ensure-shutdown in this mode as the initial set of WAL
+ # files needed to ensure a clean restart is gone. This could
+ # be improved by keeping around only a minimum set of WAL
+ # segments but that would just make the test more costly,
+ # without improving the coverage. Hence, instead, stop
+ # gracefully the primary here.
+ $node_master->stop;
+ }
+ else
+ {
+ # Stop the master and be ready to perform the rewind. The cluster
+ # needs recovery to finish once, and pg_rewind makes sure that it
+ # happens automatically.
+ $node_master->stop('immediate');
+ }
+
+ # At this point, the rewind processing is ready to run.
+ # We now have a very simple scenario with a few diverged WAL record.
+ # The real testing begins really now with a bifurcation of the possible
+ # scenarios that pg_rewind supports.
+
+ # Keep a temporary postgresql.conf for master node or it would be
+ # overwritten during the rewind.
+ copy(
+ "$master_pgdata/postgresql.conf",
+ "$tmp_folder/master-postgresql.conf.tmp");
+
+ # Now run pg_rewind
+ if ($test_mode eq "local")
+ {
+
+ # Do rewind using a local pgdata as source
+ # Stop the master and be ready to perform the rewind
+ $node_standby->stop;
+ command_ok(
+ [
+ 'pg_rewind',
+ "--debug",
+ "--source-pgdata=$standby_pgdata",
+ "--target-pgdata=$master_pgdata",
+ "--no-sync"
+ ],
+ 'pg_rewind local');
+ }
+ elsif ($test_mode eq "remote")
+ {
+ # Do rewind using a remote connection as source, generating
+ # recovery configuration automatically.
+ command_ok(
+ [
+ 'pg_rewind', "--debug",
+ "--source-server", $standby_connstr,
+ "--target-pgdata=$master_pgdata", "--no-sync",
+ "--write-recovery-conf"
+ ],
+ 'pg_rewind remote');
+
+ # Check that standby.signal is here as recovery configuration
+ # was requested.
+ ok( -e "$master_pgdata/standby.signal",
+ 'standby.signal created after pg_rewind');
+
+ # Now, when pg_rewind apparently succeeded with minimal permissions,
+ # add REPLICATION privilege. So we could test that new standby
+ # is able to connect to the new master with generated config.
+ $node_standby->safe_psql('postgres',
+ "ALTER ROLE rewind_user WITH REPLICATION;");
+ }
+ elsif ($test_mode eq "archive")
+ {
+
+ # Do rewind using a local pgdata as source and specified
+ # directory with target WAL archive. The old master has
+ # to be stopped at this point.
+
+ # Remove the existing archive directory and move all WAL
+ # segments from the old master to the archives. These
+ # will be used by pg_rewind.
+ rmtree($node_master->archive_dir);
+ RecursiveCopy::copypath($node_master->data_dir . "/pg_wal",
+ $node_master->archive_dir);
+
+ # Fast way to remove entire directory content
+ rmtree($node_master->data_dir . "/pg_wal");
+ mkdir($node_master->data_dir . "/pg_wal");
+
+ # Make sure that directories have the right umask as this is
+ # required by a follow-up check on permissions, and better
+ # safe than sorry.
+ chmod(0700, $node_master->archive_dir);
+ chmod(0700, $node_master->data_dir . "/pg_wal");
+
+ # Add appropriate restore_command to the target cluster
+ $node_master->enable_restoring($node_master, 0);
+
+ # Stop the new master and be ready to perform the rewind.
+ $node_standby->stop;
+
+ # Note the use of --no-ensure-shutdown here. WAL files are
+ # gone in this mode and the primary has been stopped
+ # gracefully already.
+ command_ok(
+ [
+ 'pg_rewind',
+ "--debug",
+ "--source-pgdata=$standby_pgdata",
+ "--target-pgdata=$master_pgdata",
+ "--no-sync",
+ "--no-ensure-shutdown",
+ "--restore-target-wal"
+ ],
+ 'pg_rewind archive');
+ }
+ else
+ {
+
+ # Cannot come here normally
+ croak("Incorrect test mode specified");
+ }
+
+ # Now move back postgresql.conf with old settings
+ move(
+ "$tmp_folder/master-postgresql.conf.tmp",
+ "$master_pgdata/postgresql.conf");
+
+ chmod(
+ $node_master->group_access() ? 0640 : 0600,
+ "$master_pgdata/postgresql.conf")
+ or BAIL_OUT(
+ "unable to set permissions for $master_pgdata/postgresql.conf");
+
+ # Plug-in rewound node to the now-promoted standby node
+ if ($test_mode ne "remote")
+ {
+ my $port_standby = $node_standby->port;
+ $node_master->append_conf(
+ 'postgresql.conf', qq(
+primary_conninfo='port=$port_standby'));
+
+ $node_master->set_standby_mode();
+ }
+
+ # Restart the master to check that rewind went correctly
+ $node_master->start;
+
+ #### Now run the test-specific parts to check the result
+
+ return;
+}
+
+# Clean up after the test. Stop both servers, if they're still running.
+sub clean_rewind_test
+{
+ $node_master->teardown_node if defined $node_master;
+ $node_standby->teardown_node if defined $node_standby;
+ return;
+}
+
+1;
diff --git a/src/bin/pg_rewind/timeline.c b/src/bin/pg_rewind/timeline.c
new file mode 100644
index 0000000..1ea6607
--- /dev/null
+++ b/src/bin/pg_rewind/timeline.c
@@ -0,0 +1,130 @@
+/*-------------------------------------------------------------------------
+ *
+ * timeline.c
+ * timeline-related functions.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include "access/timeline.h"
+#include "access/xlog_internal.h"
+#include "pg_rewind.h"
+
+/*
+ * This is copy-pasted from the backend readTimeLineHistory, modified to
+ * return a malloc'd array and to work without backend functions.
+ */
+/*
+ * Try to read a timeline's history file.
+ *
+ * If successful, return the list of component TLIs (the given TLI followed by
+ * its ancestor TLIs). If we can't find the history file, assume that the
+ * timeline has no parents, and return a list of just the specified timeline
+ * ID.
+ */
+TimeLineHistoryEntry *
+rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
+{
+ char *fline;
+ TimeLineHistoryEntry *entry;
+ TimeLineHistoryEntry *entries = NULL;
+ int nlines = 0;
+ TimeLineID lasttli = 0;
+ XLogRecPtr prevend;
+ char *bufptr;
+ bool lastline = false;
+
+ /*
+ * Parse the file...
+ */
+ prevend = InvalidXLogRecPtr;
+ bufptr = buffer;
+ while (!lastline)
+ {
+ char *ptr;
+ TimeLineID tli;
+ uint32 switchpoint_hi;
+ uint32 switchpoint_lo;
+ int nfields;
+
+ fline = bufptr;
+ while (*bufptr && *bufptr != '\n')
+ bufptr++;
+ if (!(*bufptr))
+ lastline = true;
+ else
+ *bufptr++ = '\0';
+
+ /* skip leading whitespace and check for # comment */
+ for (ptr = fline; *ptr; ptr++)
+ {
+ if (!isspace((unsigned char) *ptr))
+ break;
+ }
+ if (*ptr == '\0' || *ptr == '#')
+ continue;
+
+ nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
+
+ if (nfields < 1)
+ {
+ /* expect a numeric timeline ID as first field of line */
+ pg_log_error("syntax error in history file: %s", fline);
+ pg_log_error("Expected a numeric timeline ID.");
+ exit(1);
+ }
+ if (nfields != 3)
+ {
+ pg_log_error("syntax error in history file: %s", fline);
+ pg_log_error("Expected a write-ahead log switchpoint location.");
+ exit(1);
+ }
+ if (entries && tli <= lasttli)
+ {
+ pg_log_error("invalid data in history file: %s", fline);
+ pg_log_error("Timeline IDs must be in increasing sequence.");
+ exit(1);
+ }
+
+ lasttli = tli;
+
+ nlines++;
+ entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
+
+ entry = &entries[nlines - 1];
+ entry->tli = tli;
+ entry->begin = prevend;
+ entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
+ prevend = entry->end;
+
+ /* we ignore the remainder of each line */
+ }
+
+ if (entries && targetTLI <= lasttli)
+ {
+ pg_log_error("invalid data in history file");
+ pg_log_error("Timeline IDs must be less than child timeline's ID.");
+ exit(1);
+ }
+
+ /*
+ * Create one more entry for the "tip" of the timeline, which has no entry
+ * in the history file.
+ */
+ nlines++;
+ if (entries)
+ entries = pg_realloc(entries, nlines * sizeof(TimeLineHistoryEntry));
+ else
+ entries = pg_malloc(1 * sizeof(TimeLineHistoryEntry));
+
+ entry = &entries[nlines - 1];
+ entry->tli = targetTLI;
+ entry->begin = prevend;
+ entry->end = InvalidXLogRecPtr;
+
+ *nentries = nlines;
+ return entries;
+}