102 char *buffer,
size_t size);
128 parse.context = context;
130 parse.saw_version_field =
false;
170 switch (
parse->state)
177 parse->pathname = NULL;
178 parse->encoded_pathname = NULL;
180 parse->algorithm = NULL;
181 parse->checksum = NULL;
185 parse->timeline = NULL;
186 parse->start_lsn = NULL;
187 parse->end_lsn = NULL;
191 "unexpected object start");
209 switch (
parse->state)
224 "unexpected object end");
241 switch (
parse->state)
251 "unexpected array start");
266 switch (
parse->state)
274 "unexpected array end");
287 switch (
parse->state)
295 if (!
parse->saw_version_field)
297 if (strcmp(fname,
"PostgreSQL-Backup-Manifest-Version") != 0)
299 "expected version indicator");
301 parse->saw_version_field =
true;
306 if (strcmp(fname,
"Files") == 0)
313 if (strcmp(fname,
"WAL-Ranges") == 0)
320 if (strcmp(fname,
"Manifest-Checksum") == 0)
328 "unrecognized top-level field");
333 if (strcmp(fname,
"Path") == 0)
335 else if (strcmp(fname,
"Encoded-Path") == 0)
337 else if (strcmp(fname,
"Size") == 0)
339 else if (strcmp(fname,
"Last-Modified") == 0)
341 else if (strcmp(fname,
"Checksum-Algorithm") == 0)
343 else if (strcmp(fname,
"Checksum") == 0)
347 "unexpected file field");
353 if (strcmp(fname,
"Timeline") == 0)
355 else if (strcmp(fname,
"Start-LSN") == 0)
357 else if (strcmp(fname,
"End-LSN") == 0)
361 "unexpected WAL range field");
367 "unexpected object field");
392 switch (
parse->state)
395 if (strcmp(token,
"1") != 0)
397 "unexpected manifest version");
402 switch (
parse->file_field)
405 parse->pathname = token;
408 parse->encoded_pathname = token;
417 parse->algorithm = token;
420 parse->checksum = token;
427 switch (
parse->wal_range_field)
430 parse->timeline = token;
433 parse->start_lsn = token;
436 parse->end_lsn = token;
444 parse->manifest_checksum = token;
465 int checksum_string_length;
468 uint8 *checksum_payload;
471 if (
parse->pathname == NULL &&
parse->encoded_pathname == NULL)
473 if (
parse->pathname != NULL &&
parse->encoded_pathname != NULL)
475 "both path name and encoded path name");
476 if (
parse->size == NULL)
478 if (
parse->algorithm == NULL &&
parse->checksum != NULL)
480 "checksum without algorithm");
483 if (
parse->encoded_pathname != NULL)
485 int encoded_length = strlen(
parse->encoded_pathname);
486 int raw_length = encoded_length / 2;
489 if (encoded_length % 2 != 0 ||
491 parse->encoded_pathname,
494 "could not decode file name");
495 parse->pathname[raw_length] =
'\0';
497 parse->encoded_pathname = NULL;
501 size = strtoul(
parse->size, &ep, 10);
504 "file size is not an integer");
507 if (
parse->algorithm == NULL)
510 context->
error_cb(context,
"unrecognized checksum algorithm: \"%s\"",
514 checksum_string_length =
parse->checksum == NULL ? 0
515 : strlen(
parse->checksum);
516 if (checksum_string_length == 0)
519 checksum_payload = NULL;
523 checksum_length = checksum_string_length / 2;
524 checksum_payload =
palloc(checksum_length);
525 if (checksum_string_length % 2 != 0 ||
529 "invalid checksum for file \"%s\": \"%s\"",
535 checksum_type, checksum_length, checksum_payload);
538 if (
parse->size != NULL)
543 if (
parse->algorithm != NULL)
546 parse->algorithm = NULL;
548 if (
parse->checksum != NULL)
551 parse->checksum = NULL;
571 if (
parse->timeline == NULL)
573 if (
parse->start_lsn == NULL)
575 if (
parse->end_lsn == NULL)
579 tli = strtoul(
parse->timeline, &ep, 10);
582 "timeline is not an integer");
585 "could not parse start LSN");
588 "could not parse end LSN");
594 if (
parse->timeline != NULL)
597 parse->timeline = NULL;
599 if (
parse->start_lsn != NULL)
602 parse->start_lsn = NULL;
604 if (
parse->end_lsn != NULL)
607 parse->end_lsn = NULL;
624 size_t number_of_newlines = 0;
625 size_t ultimate_newline = 0;
626 size_t penultimate_newline = 0;
632 for (
i = 0;
i < size; ++
i)
634 if (buffer[
i] ==
'\n')
636 ++number_of_newlines;
637 penultimate_newline = ultimate_newline;
638 ultimate_newline =
i;
647 if (number_of_newlines < 2)
649 "expected at least 2 lines");
650 if (ultimate_newline != size - 1)
652 "last line not newline-terminated");
656 if (manifest_ctx == NULL)
657 context->
error_cb(context,
"out of memory");
659 context->
error_cb(context,
"could not initialize checksum of manifest");
661 context->
error_cb(context,
"could not update checksum of manifest");
663 sizeof(manifest_checksum_actual)) < 0)
664 context->
error_cb(context,
"could not finalize checksum of manifest");
667 if (
parse->manifest_checksum == NULL)
668 context->
error_cb(
parse->context,
"manifest has no checksum");
672 context->
error_cb(context,
"invalid manifest checksum: \"%s\"",
673 parse->manifest_checksum);
674 if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
676 context->
error_cb(context,
"manifest checksum mismatch");
691 context->
error_cb(context,
"could not parse backup manifest: %s", msg);
702 if (
c >=
'0' &&
c <=
'9')
704 if (
c >=
'a' &&
c <=
'f')
706 if (
c >=
'A' &&
c <=
'F')
722 for (
i = 0;
i < nbytes; ++
i)
727 if (n1 < 0 || n2 < 0)
729 result[
i] = n1 * 16 + n2;
744 if (sscanf(input,
"%X/%X", &hi, &lo) != 2)
746 *result = ((uint64) hi) << 32 | lo;
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)
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
void pfree(void *pointer)
JsonManifestSemanticState
@ 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
JsonManifestWALRangeField
static bool parse_xlogrecptr(XLogRecPtr *result, char *input)
static void json_manifest_finalize_wal_range(JsonManifestParseState *parse)
static void json_manifest_object_start(void *state)
static void json_manifest_object_field_start(void *state, char *fname, bool isnull)
static void json_manifest_finalize_file(JsonManifestParseState *parse)
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
@ JMFF_CHECKSUM_ALGORITHM
void json_parse_manifest(JsonManifestParseContext *context, char *buffer, size_t size)
static void json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
static void json_manifest_object_end(void *state)
static int hexdecode_char(char c)
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
static void json_manifest_array_start(void *state)
static void verify_manifest_checksum(JsonManifestParseState *parse, char *buffer, size_t size)
static void json_manifest_array_end(void *state)
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
#define PG_SHA256_DIGEST_LENGTH
json_manifest_perwalrange_callback perwalrange_cb
json_manifest_perfile_callback perfile_cb
json_manifest_error_callback error_cb
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