40 #define ESTIMATED_BYTES_PER_MANIFEST_LINE 100
45 #define READ_CHUNK_SIZE 4096
63 #define should_verify_checksum(m) \
64 (((m)->matched) && !((m)->bad) && (((m)->checksum_type) != CHECKSUM_TYPE_NONE))
71 #define SH_PREFIX manifest_files
72 #define SH_ELEMENT_TYPE manifest_file
73 #define SH_KEY_TYPE char *
74 #define SH_KEY pathname
75 #define SH_HASH_KEY(tb, key) hash_string_pointer(key)
76 #define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0)
77 #define SH_SCOPE static inline
78 #define SH_RAW_ALLOCATOR pg_malloc0
101 manifest_files_hash *
ht;
111 manifest_files_hash *
ht;
119 manifest_files_hash **ht_p,
123 char *pathname,
size_t size,
126 uint8 *checksum_payload);
136 char *
relpath,
char *fullpath);
138 char *
relpath,
char *fullpath);
144 char *pg_waldump_path,
149 const
char *pg_restrict
fmt,...)
156 static
void usage(
void);
174 static struct option long_options[] = {
189 char *manifest_path = NULL;
190 bool no_parse_wal =
false;
192 char *wal_directory = NULL;
193 char *pg_waldump_path = NULL;
199 memset(&context, 0,
sizeof(context));
203 if (strcmp(argv[1],
"--help") == 0 || strcmp(argv[1],
"-?") == 0)
208 if (strcmp(argv[1],
"--version") == 0 || strcmp(argv[1],
"-V") == 0)
210 puts(
"pg_verifybackup (PostgreSQL) " PG_VERSION);
236 while ((
c =
getopt_long(argc, argv,
"ei:m:nPqsw:", long_options, NULL)) != -1)
241 context.exit_on_error =
true;
291 pg_log_error(
"too many command-line arguments (first is \"%s\")",
299 pg_fatal(
"cannot specify both %s and %s",
300 "-P/--progress",
"-q/--quiet");
309 "pg_waldump (PostgreSQL) " PG_VERSION
"\n",
319 pg_fatal(
"program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
320 "pg_waldump",
"pg_verifybackup", full_path);
322 pg_fatal(
"program \"%s\" was found by \"%s\" but was not the same version as %s",
323 "pg_waldump", full_path,
"pg_verifybackup");
328 if (manifest_path == NULL)
329 manifest_path =
psprintf(
"%s/backup_manifest",
330 context.backup_directory);
333 if (wal_directory == NULL)
334 wal_directory =
psprintf(
"%s/pg_wal", context.backup_directory);
371 wal_directory, first_wal_range);
377 if (!context.saw_any_error && !quiet)
378 printf(
_(
"backup successfully verified\n"));
380 return context.saw_any_error ? 1 : 0;
396 manifest_files_hash *ht;
403 if ((
fd = open(manifest_path, O_RDONLY |
PG_BINARY, 0)) < 0)
415 ht = manifest_files_create(initial_size, NULL);
432 manifest_path, rc, (
long long int) statbuf.
st_size);
439 private_context.
ht = ht;
479 char *pathname,
size_t size,
481 int checksum_length,
uint8 *checksum_payload)
484 manifest_files_hash *ht = pcxt->
ht;
489 m = manifest_files_insert(ht, pathname, &found);
517 range->start_lsn = start_lsn;
518 range->end_lsn = end_lsn;
561 "could not open directory \"%s\": %m", fullpath);
593 "could not close directory \"%s\": %m", fullpath);
610 if (
stat(fullpath, &sb) != 0)
613 "could not stat file or directory \"%s\": %m",
636 "\"%s\" is not a file or directory",
642 m = manifest_files_lookup(context->
ht,
relpath);
646 "\"%s\" is present on disk but not in the manifest",
658 "\"%s\" has size %lld on disk but size %zu in the manifest",
682 manifest_files_iterator it;
685 manifest_files_start_iterate(context->
ht, &it);
686 while ((m = manifest_files_iterate(context->
ht, &it)) != NULL)
689 "\"%s\" is present in the manifest but not on disk",
701 manifest_files_iterator it;
706 manifest_files_start_iterate(context->
ht, &it);
707 while ((m = manifest_files_iterate(context->
ht, &it)) != NULL)
740 size_t bytes_read = 0;
746 if ((
fd = open(fullpath, O_RDONLY |
PG_BINARY, 0)) < 0)
801 if (bytes_read != m->
size)
804 "file \"%s\" should contain %zu bytes, but read %zu bytes",
814 "could not finalize checksum of file \"%s\"",
822 "file \"%s\" has checksum of length %d, but expected %d",
826 "checksum mismatch for file \"%s\"",
840 while (this_wal_range != NULL)
842 char *pg_waldump_cmd;
844 pg_waldump_cmd =
psprintf(
"\"%s\" --quiet --path=\"%s\" --timeline=%u --start=%X/%X --end=%X/%X\n",
845 pg_waldump_path, wal_directory, this_wal_range->
tli,
849 if (system(pg_waldump_cmd) != 0)
851 "WAL parsing failed for timeline %u",
852 this_wal_range->
tli);
854 this_wal_range = this_wal_range->
next;
910 while (*v !=
'\0' && *r == *v)
913 if (*v ==
'\0' && (*r ==
'\0' || *r ==
'/'))
926 unsigned char *ss = (
unsigned char *) s;
945 int percent_size = 0;
946 char totalsize_str[32];
947 char donesize_str[32];
965 _(
"%*s/%s kB (%d%%) verified"),
966 (
int) strlen(totalsize_str),
967 donesize_str, totalsize_str, percent_size);
973 fputc((!finished && isatty(fileno(stderr))) ?
'\r' :
'\n', stderr);
982 printf(
_(
"%s verifies a backup against the backup manifest.\n\n"),
progname);
985 printf(
_(
" -e, --exit-on-error exit immediately on error\n"));
986 printf(
_(
" -i, --ignore=RELATIVE_PATH ignore indicated path\n"));
987 printf(
_(
" -m, --manifest-path=PATH use specified path for manifest\n"));
988 printf(
_(
" -n, --no-parse-wal do not try to parse WAL files\n"));
989 printf(
_(
" -P, --progress show progress information\n"));
990 printf(
_(
" -q, --quiet do not print any output, except for errors\n"));
991 printf(
_(
" -s, --skip-checksums skip checksum verification\n"));
992 printf(
_(
" -w, --wal-directory=PATH use specified path for WAL files\n"));
993 printf(
_(
" -V, --version output version information, then exit\n"));
994 printf(
_(
" -?, --help show this help, then exit\n"));
995 printf(
_(
"\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
996 printf(
_(
"%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
Datum now(PG_FUNCTION_ARGS)
#define PG_TEXTDOMAIN(domain)
#define pg_attribute_printf(f, a)
int pg_checksum_final(pg_checksum_context *context, uint8 *output)
int pg_checksum_update(pg_checksum_context *context, const uint8 *input, size_t len)
int pg_checksum_init(pg_checksum_context *context, pg_checksum_type type)
#define PG_CHECKSUM_MAX_LENGTH
int find_my_exec(const char *argv0, char *retpath)
void set_pglocale_pgservice(const char *argv0, const char *app)
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
void * pg_malloc(size_t size)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
uint32 hash_bytes(const unsigned char *k, int keylen)
static void const char * fmt
static void const char fflush(stdout)
void pg_logging_init(const char *argv0)
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt, va_list ap)
#define pg_log_error(...)
#define pg_log_error_hint(...)
char * pstrdup(const char *in)
void pfree(void *pointer)
void json_parse_manifest(JsonManifestParseContext *context, char *buffer, size_t size)
static pg_time_t last_progress_report
PGDLLIMPORT char * optarg
static void verify_backup_checksums(verifier_context *context)
static void record_manifest_details_for_file(JsonManifestParseContext *context, char *pathname, size_t size, pg_checksum_type checksum_type, int checksum_length, uint8 *checksum_payload)
struct verifier_context verifier_context
static void parse_manifest_file(char *manifest_path, manifest_files_hash **ht_p, manifest_wal_range **first_wal_range_p)
struct parser_context parser_context
static void parse_required_wal(verifier_context *context, char *pg_waldump_path, char *wal_directory, manifest_wal_range *first_wal_range)
int main(int argc, char **argv)
struct manifest_wal_range manifest_wal_range
static void report_extra_backup_files(verifier_context *context)
#define ESTIMATED_BYTES_PER_MANIFEST_LINE
static bool skip_checksums
static void progress_report(bool finished)
struct manifest_file manifest_file
static void pg_attribute_noreturn()
static bool should_ignore_relpath(verifier_context *context, char *relpath)
#define should_verify_checksum(m)
static void record_manifest_details_for_wal_range(JsonManifestParseContext *context, TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
static bool show_progress
static void verify_backup_file(verifier_context *context, char *relpath, char *fullpath)
static void report_manifest_error(JsonManifestParseContext *context, const char *fmt,...) pg_attribute_printf(2
static void static void report_fatal_error(const char *pg_restrict fmt,...) pg_attribute_printf(1
static void verify_file_checksum(verifier_context *context, manifest_file *m, char *fullpath)
static const char * progname
static void verify_backup_directory(verifier_context *context, char *relpath, char *fullpath)
static uint32 hash_string_pointer(char *s)
static void report_backup_error(verifier_context *context, const char *pg_restrict fmt,...) pg_attribute_printf(2
void canonicalize_path(char *path)
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,...)
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
#define relpath(rlocator, forknum)
void simple_string_list_append(SimpleStringList *list, const char *val)
json_manifest_perwalrange_callback perwalrange_cb
json_manifest_perfile_callback perfile_cb
json_manifest_error_callback error_cb
char val[FLEXIBLE_ARRAY_MEMBER]
struct SimpleStringListCell * next
SimpleStringListCell * head
pg_checksum_type checksum_type
struct manifest_wal_range * next
struct manifest_wal_range * prev
manifest_wal_range * last_wal_range
manifest_wal_range * first_wal_range
SimpleStringList ignore_list
#define LSN_FORMAT_ARGS(lsn)