45#define INCREMENTAL_PREFIX "INCREMENTAL."
46#define INCREMENTAL_PREFIX_LENGTH (sizeof(INCREMENTAL_PREFIX) - 1)
172 memset(&opt, 0,
sizeof(opt));
205 pg_fatal(
"unrecognized checksum algorithm: \"%s\"",
239 pg_fatal(
"no output directory specified");
247 "The target directory will not be modified.");
252#if (defined(HAVE_COPYFILE) && defined(COPYFILE_CLONE_FORCE)) || \
253 (defined(__linux__) && defined(FICLONE))
261 pg_fatal(
"file cloning not supported on this platform");
266#if defined(HAVE_COPY_FILE_RANGE)
269 pg_log_debug(
"would use copy_file_range to copy blocks");
271 pg_log_debug(
"will use copy_file_range to copy blocks");
274 pg_fatal(
"copy_file_range not supported on this platform");
279 pgdata = argv[argc - 1];
283 pg_log_debug(
"read server version %u from file \"%s/%s\"",
310 manifests[
i]->system_identifier != system_identifier)
341 for (ts = tablespaces; ts !=
NULL; ts = ts->
next)
355 pg_fatal(
"cannot generate a manifest because no manifest is available for the final input backup");
378 for (ts = tablespaces; ts !=
NULL; ts = ts->
next)
395 pg_log_debug(
"would create symbolic link from \"%s\" to \"%s\"",
399 pg_log_debug(
"creating symbolic link from \"%s\" to \"%s\"",
402 pg_fatal(
"could not create symbolic link from \"%s\" to \"%s\": %m",
414 pg_fatal(
"could not create directory \"%s\": %m",
444 pg_log_warning(
"--link mode was used; any modifications to the output "
445 "directory might destructively modify input directories");
474 pg_fatal(
"directory name too long");
480 if (
tsmap->new_dir[0] !=
'\0')
481 pg_fatal(
"multiple \"=\" signs in tablespace mapping");
489 pg_fatal(
"invalid tablespace mapping format \"%s\", must be \"OLDDIR=NEWDIR\"",
arg);
500 pg_fatal(
"old directory is not an absolute path in tablespace mapping: %s",
504 pg_fatal(
"old directory is not an absolute path in tablespace mapping: %s",
573 pg_fatal(
"backup at \"%s\" is a full backup, but only the first backup should be a full backup",
576 pg_fatal(
"backup at \"%s\" is an incremental backup, but the first backup should be a full backup",
579 pg_fatal(
"backup at \"%s\" starts on timeline %u, but expected %u",
582 pg_fatal(
"backup at \"%s\" starts at LSN %X/%08X, but expected %X/%08X",
617 uint64 system_identifier = 0;
618 uint32 data_checksum_version = 0;
638 pg_fatal(
"%s: unexpected control file version",
655 else if (data_checksum_version != 0 &&
677 pg_log_warning_hint(
"Disable, and optionally reenable, checksums on the output directory to avoid failures.");
680 return system_identifier;
694 if (
stat(dir, &st) != 0)
695 pg_fatal(
"could not stat file \"%s\": %m", dir);
718 pg_log_info(
"removing contents of output directory \"%s\"",
721 pg_log_error(
"failed to remove contents of output directory");
749 pg_fatal(
"could not create directory \"%s\": %m", dirname);
754 pg_log_debug(
"using existing directory \"%s\"", dirname);
761 pg_fatal(
"directory \"%s\" exists but is not empty", dirname);
764 pg_fatal(
"could not access directory \"%s\": %m", dirname);
778 printf(
_(
"%s reconstructs full backups from incrementals.\n\n"),
progname);
782 printf(
_(
" -d, --debug generate lots of debugging output\n"));
783 printf(
_(
" -k, --link link files instead of copying\n"));
784 printf(
_(
" -n, --dry-run do not actually do anything\n"));
785 printf(
_(
" -N, --no-sync do not wait for changes to be written safely to disk\n"));
786 printf(
_(
" -o, --output=DIRECTORY output directory\n"));
787 printf(
_(
" -T, --tablespace-mapping=OLDDIR=NEWDIR\n"
788 " relocate tablespace in OLDDIR to NEWDIR\n"));
789 printf(
_(
" --clone clone (reflink) files instead of copying\n"));
790 printf(
_(
" --copy copy files (default)\n"));
791 printf(
_(
" --copy-file-range copy using copy_file_range() system call\n"));
792 printf(
_(
" --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE\n"
793 " use algorithm for manifest checksums\n"));
794 printf(
_(
" --no-manifest suppress generation of backup manifest\n"));
795 printf(
_(
" --sync-method=METHOD set method for syncing files to disk\n"));
796 printf(
_(
" -V, --version output version information, then exit\n"));
797 printf(
_(
" -?, --help show this help, then exit\n"));
961 int checksum_length = 0;
1026 (
strcmp(
de->d_name,
"backup_label") == 0 ||
1027 strcmp(
de->d_name,
"backup_manifest") == 0))
1093 pg_log_warning(
"manifest file \"%s\" contains no entry for file \"%s\"",
1109 if (checksum_length != 0)
1155 sb.st_size,
sb.st_mtime,
1156 checksum_type, checksum_length,
1161 if (checksum_payload !=
NULL)
1162 pfree(checksum_payload);
1245 pg_log_debug(
"skipping \"%s\" because the filename is not a legal tablespace OID",
1256 pg_log_debug(
"skipping \"%s\" because it is neither a symbolic link nor a directory",
1276 pg_fatal(
"could not read symbolic link \"%s\": %m",
1304 pg_fatal(
"tablespace at \"%s\" has no tablespace mapping",
1322 pg_fatal(
"tablespaces with OIDs %u and %u both point at directory \"%s\"",
1369 pg_fatal(
"could not read file \"%s\": read %zd of %lld",
1375 buf->data[
buf->len] =
'\0';
void parse_backup_label(char *filename, StringInfo buf, TimeLineID *start_tli, XLogRecPtr *start_lsn, TimeLineID *previous_tli, XLogRecPtr *previous_lsn)
void write_backup_label(char *output_directory, StringInfo buf, pg_checksum_type checksum_type, manifest_writer *mwriter)
#define PG_TEXTDOMAIN(domain)
#define OidIsValid(objectId)
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
int pg_checksum_final(pg_checksum_context *context, uint8 *output)
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
#define PG_CHECKSUM_MAX_LENGTH
void set_pglocale_pgservice(const char *argv0, const char *app)
ControlFileData * get_controlfile_by_exact_path(const char *ControlFilePath, bool *crc_ok_p)
@ COPY_METHOD_COPY_FILE_RANGE
void copy_file(const char *fromfile, const char *tofile)
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
void * pg_malloc(size_t size)
void * pg_malloc0(size_t size)
uint32 get_pg_version(const char *datadir, char **version_str)
void SetDataDirectoryCreatePerm(int dataDirMode)
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
@ DATA_DIR_SYNC_METHOD_FSYNC
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
static pg_noreturn void manifest_data ** load_backup_manifests(int n_backups, char **backup_directories)
void pg_logging_increase_verbosity(void)
void pg_logging_init(const char *argv0)
#define pg_log_error(...)
#define pg_log_error_hint(...)
#define pg_log_warning_hint(...)
#define pg_log_debug(...)
void pfree(void *pointer)
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
bool parse_sync_method(const char *optarg, DataDirSyncMethod *sync_method)
static cb_tablespace * scan_for_existing_tablespaces(char *pathname, cb_options *opt)
static void remember_to_cleanup_directory(char *target_path, bool rmtopdir)
static void process_directory_recursively(Oid tsoid, char *input_directory, char *output_directory, char *relative_path, int n_prior_backups, char **prior_backup_dirs, manifest_data **manifests, manifest_writer *mwriter, cb_options *opt)
static void create_output_directory(char *dirname, cb_options *opt)
static void check_input_dir_permissions(char *dir)
static uint64 check_control_files(int n_backups, char **backup_dirs)
static cb_cleanup_dir * cleanup_dir_list
#define INCREMENTAL_PREFIX_LENGTH
static void cleanup_directories_atexit(void)
static StringInfo check_backup_label_files(int n_backups, char **backup_dirs)
static void add_tablespace_mapping(cb_options *opt, char *arg)
#define INCREMENTAL_PREFIX
static void slurp_file(int fd, char *filename, StringInfo buf, int maxlen)
static bool parse_oid(char *s, Oid *result)
static void reset_directory_cleanup_list(void)
#define PG_CONTROL_VERSION
PGDLLIMPORT char * optarg
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define pg_log_warning(...)
int pg_mkdir_p(char *path, int omode)
#define is_absolute_path(filename)
void canonicalize_path(char *path)
int pg_check_dir(const char *dir)
const char * get_progname(const char *argv0)
size_t strlcpy(char *dst, const char *src, size_t siz)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
void reconstruct_from_incremental_file(char *input_filename, char *output_filename, char *relative_path, char *bare_file_name, int n_prior_backups, char **prior_backup_dirs, manifest_data **manifests, char *manifest_path, pg_checksum_type checksum_type, int *checksum_length, uint8 **checksum_payload, CopyMethod copy_method, bool debug, bool dry_run)
#define PG_TBLSPC_DIR_SLASH
bool rmtree(const char *path, bool rmtopdir)
void destroyStringInfo(StringInfo str)
StringInfo makeStringInfo(void)
void resetStringInfo(StringInfo str)
void enlargeStringInfo(StringInfo str, int needed)
uint32 pg_control_version
uint32 data_checksum_version
struct cb_cleanup_dir * next
cb_tablespace_mapping * tsmappings
DataDirSyncMethod sync_method
pg_checksum_type manifest_checksums
struct cb_tablespace_mapping * next
struct cb_tablespace * next
pg_checksum_type checksum_type
#define GET_PG_MAJORVERSION_NUM(v)
#define symlink(oldpath, newpath)
#define readlink(path, buf, size)
manifest_writer * create_manifest_writer(char *directory, uint64 system_identifier)
void add_file_to_manifest(manifest_writer *mwriter, const char *manifest_path, uint64 size, time_t mtime, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload)
void finalize_manifest(manifest_writer *mwriter, manifest_wal_range *first_wal_range)
#define XLOG_CONTROL_FILE
#define LSN_FORMAT_ARGS(lsn)
#define InvalidXLogRecPtr