115 const char *buffer,
size_t size,
140 parse->saw_version_field =
false;
156 if (manifest_ctx == NULL)
159 context->error_cb(
context,
"could not initialize checksum of manifest");
210 context->error_cb(
context,
"could not update checksum of manifest");
239 parse.saw_version_field =
false;
281 switch (
parse->state)
288 parse->pathname = NULL;
289 parse->encoded_pathname = NULL;
291 parse->algorithm = NULL;
292 parse->checksum = NULL;
296 parse->timeline = NULL;
297 parse->start_lsn = NULL;
298 parse->end_lsn = NULL;
302 "unexpected object start");
322 switch (
parse->state)
337 "unexpected object end");
356 switch (
parse->state)
366 "unexpected array start");
383 switch (
parse->state)
391 "unexpected array end");
406 switch (
parse->state)
414 if (!
parse->saw_version_field)
416 if (strcmp(fname,
"PostgreSQL-Backup-Manifest-Version") != 0)
418 "expected version indicator");
420 parse->saw_version_field =
true;
425 if (strcmp(fname,
"System-Identifier") == 0)
432 if (strcmp(fname,
"Files") == 0)
439 if (strcmp(fname,
"WAL-Ranges") == 0)
446 if (strcmp(fname,
"Manifest-Checksum") == 0)
454 "unrecognized top-level field");
459 if (strcmp(fname,
"Path") == 0)
461 else if (strcmp(fname,
"Encoded-Path") == 0)
463 else if (strcmp(fname,
"Size") == 0)
465 else if (strcmp(fname,
"Last-Modified") == 0)
467 else if (strcmp(fname,
"Checksum-Algorithm") == 0)
469 else if (strcmp(fname,
"Checksum") == 0)
473 "unexpected file field");
479 if (strcmp(fname,
"Timeline") == 0)
481 else if (strcmp(fname,
"Start-LSN") == 0)
483 else if (strcmp(fname,
"End-LSN") == 0)
487 "unexpected WAL range field");
493 "unexpected object field");
522 switch (
parse->state)
537 switch (
parse->file_field)
562 switch (
parse->wal_range_field)
609 "manifest version not an integer");
611 if (version != 1 && version != 2)
613 "unexpected manifest version");
628 uint64 system_identifier;
634 system_identifier =
strtou64(
parse->manifest_system_identifier, &ep, 10);
637 "system identifier in manifest not an integer");
655 int checksum_string_length;
658 uint8 *checksum_payload;
661 if (
parse->pathname == NULL &&
parse->encoded_pathname == NULL)
663 if (
parse->pathname != NULL &&
parse->encoded_pathname != NULL)
665 "both path name and encoded path name");
666 if (
parse->size == NULL)
668 if (
parse->algorithm == NULL &&
parse->checksum != NULL)
670 "checksum without algorithm");
673 if (
parse->encoded_pathname != NULL)
675 int encoded_length = strlen(
parse->encoded_pathname);
676 int raw_length = encoded_length / 2;
679 if (encoded_length % 2 != 0 ||
681 parse->encoded_pathname,
684 "could not decode file name");
685 parse->pathname[raw_length] =
'\0';
687 parse->encoded_pathname = NULL;
694 "file size is not an integer");
697 if (
parse->algorithm == NULL)
700 context->error_cb(
context,
"unrecognized checksum algorithm: \"%s\"",
704 checksum_string_length =
parse->checksum == NULL ? 0
705 : strlen(
parse->checksum);
706 if (checksum_string_length == 0)
709 checksum_payload = NULL;
713 checksum_length = checksum_string_length / 2;
714 checksum_payload =
palloc(checksum_length);
715 if (checksum_string_length % 2 != 0 ||
719 "invalid checksum for file \"%s\": \"%s\"",
725 checksum_type, checksum_length, checksum_payload);
728 if (
parse->size != NULL)
733 if (
parse->algorithm != NULL)
736 parse->algorithm = NULL;
738 if (
parse->checksum != NULL)
741 parse->checksum = NULL;
761 if (
parse->timeline == NULL)
763 if (
parse->start_lsn == NULL)
765 if (
parse->end_lsn == NULL)
769 tli = strtoul(
parse->timeline, &ep, 10);
772 "timeline is not an integer");
775 "could not parse start LSN");
778 "could not parse end LSN");
784 if (
parse->timeline != NULL)
787 parse->timeline = NULL;
789 if (
parse->start_lsn != NULL)
792 parse->start_lsn = NULL;
794 if (
parse->end_lsn != NULL)
797 parse->end_lsn = NULL;
818 size_t number_of_newlines = 0;
819 size_t ultimate_newline = 0;
820 size_t penultimate_newline = 0;
828 if (buffer[
i] ==
'\n')
830 ++number_of_newlines;
831 penultimate_newline = ultimate_newline;
832 ultimate_newline =
i;
841 if (number_of_newlines < 2)
843 "expected at least 2 lines");
844 if (ultimate_newline !=
size - 1)
846 "last line not newline-terminated");
849 if (incr_ctx == NULL)
852 if (manifest_ctx == NULL)
855 context->error_cb(
context,
"could not initialize checksum of manifest");
859 manifest_ctx = incr_ctx;
862 context->error_cb(
context,
"could not update checksum of manifest");
864 sizeof(manifest_checksum_actual)) < 0)
865 context->error_cb(
context,
"could not finalize checksum of manifest");
868 if (
parse->manifest_checksum == NULL)
869 context->error_cb(
parse->context,
"manifest has no checksum");
874 parse->manifest_checksum);
875 if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
892 context->error_cb(
context,
"could not parse backup manifest: %s", msg);
903 if (
c >=
'0' &&
c <=
'9')
905 if (
c >=
'a' &&
c <=
'f')
907 if (
c >=
'A' &&
c <=
'F')
923 for (
i = 0;
i < nbytes; ++
i)
928 if (n1 < 0 || n2 < 0)
930 result[
i] = n1 * 16 + n2;
945 if (sscanf(
input,
"%X/%X", &hi, &lo) != 2)
947 *result = ((uint64) hi) << 32 | lo;
#define strtoi64(str, endptr, base)
#define Assert(condition)
#define strtou64(str, endptr, base)
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
static void PGresult * res
JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, const JsonSemAction *sem, const char *json, size_t len, bool is_last)
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
void freeJsonLexContext(JsonLexContext *lex)
JsonLexContext * makeJsonLexContextIncremental(JsonLexContext *lex, int encoding, bool need_escapes)
void pfree(void *pointer)
JsonManifestSemanticState
@ JM_EXPECT_SYSTEM_IDENTIFIER_VALUE
@ JM_EXPECT_TOPLEVEL_START
@ JM_EXPECT_WAL_RANGES_START
@ JM_EXPECT_THIS_FILE_FIELD
@ JM_EXPECT_THIS_FILE_VALUE
@ JM_EXPECT_THIS_WAL_RANGE_VALUE
@ JM_EXPECT_VERSION_VALUE
@ JM_EXPECT_MANIFEST_CHECKSUM_VALUE
@ JM_EXPECT_THIS_WAL_RANGE_FIELD
@ JM_EXPECT_TOPLEVEL_FIELD
@ JM_EXPECT_WAL_RANGES_NEXT
static JsonParseErrorType json_manifest_array_start(void *state)
void json_parse_manifest(JsonManifestParseContext *context, const char *buffer, size_t size)
JsonManifestWALRangeField
static bool parse_xlogrecptr(XLogRecPtr *result, char *input)
static void json_manifest_finalize_wal_range(JsonManifestParseState *parse)
static JsonParseErrorType json_manifest_object_field_start(void *state, char *fname, bool isnull)
JsonManifestParseIncrementalState * json_parse_manifest_incremental_init(JsonManifestParseContext *context)
static void json_manifest_finalize_file(JsonManifestParseState *parse)
static JsonParseErrorType json_manifest_object_end(void *state)
static JsonParseErrorType json_manifest_object_start(void *state)
static void json_manifest_finalize_version(JsonManifestParseState *parse)
static JsonParseErrorType json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
static JsonParseErrorType json_manifest_array_end(void *state)
@ JMFF_CHECKSUM_ALGORITHM
void json_parse_manifest_incremental_shutdown(JsonManifestParseIncrementalState *incstate)
void json_parse_manifest_incremental_chunk(JsonManifestParseIncrementalState *incstate, const char *chunk, size_t size, bool is_last)
static void json_manifest_finalize_system_identifier(JsonManifestParseState *parse)
static void verify_manifest_checksum(JsonManifestParseState *parse, const char *buffer, size_t size, pg_cryptohash_ctx *incr_ctx)
static int hexdecode_char(char c)
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
#define PG_SHA256_DIGEST_LENGTH
static pg_noinline void Size size
pg_cryptohash_ctx * manifest_ctx
char * manifest_system_identifier
JsonManifestWALRangeField wal_range_field
JsonManifestParseContext * context
JsonManifestFileField file_field
pg_checksum_type checksum_algorithm
JsonManifestSemanticState state
json_struct_action array_end
json_struct_action object_start
json_ofield_action object_field_start
json_aelem_action array_element_start
json_scalar_action scalar
json_aelem_action array_element_end
json_struct_action array_start
json_struct_action object_end
json_ofield_action object_field_end