PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
parse_manifest.c File Reference
#include "postgres_fe.h"
#include "common/jsonapi.h"
#include "common/parse_manifest.h"
Include dependency graph for parse_manifest.c:

Go to the source code of this file.

Data Structures

struct  JsonManifestParseState
 
struct  JsonManifestParseIncrementalState
 

Enumerations

enum  JsonManifestSemanticState {
  JM_EXPECT_TOPLEVEL_START , JM_EXPECT_TOPLEVEL_END , JM_EXPECT_TOPLEVEL_FIELD , JM_EXPECT_VERSION_VALUE ,
  JM_EXPECT_SYSTEM_IDENTIFIER_VALUE , JM_EXPECT_FILES_START , JM_EXPECT_FILES_NEXT , JM_EXPECT_THIS_FILE_FIELD ,
  JM_EXPECT_THIS_FILE_VALUE , JM_EXPECT_WAL_RANGES_START , JM_EXPECT_WAL_RANGES_NEXT , JM_EXPECT_THIS_WAL_RANGE_FIELD ,
  JM_EXPECT_THIS_WAL_RANGE_VALUE , JM_EXPECT_MANIFEST_CHECKSUM_VALUE , JM_EXPECT_EOF
}
 
enum  JsonManifestFileField {
  JMFF_PATH , JMFF_ENCODED_PATH , JMFF_SIZE , JMFF_LAST_MODIFIED ,
  JMFF_CHECKSUM_ALGORITHM , JMFF_CHECKSUM
}
 
enum  JsonManifestWALRangeField { JMWRF_TIMELINE , JMWRF_START_LSN , JMWRF_END_LSN }
 

Functions

static JsonParseErrorType json_manifest_object_start (void *state)
 
static JsonParseErrorType json_manifest_object_end (void *state)
 
static JsonParseErrorType json_manifest_array_start (void *state)
 
static JsonParseErrorType json_manifest_array_end (void *state)
 
static JsonParseErrorType json_manifest_object_field_start (void *state, char *fname, bool isnull)
 
static JsonParseErrorType json_manifest_scalar (void *state, char *token, JsonTokenType tokentype)
 
static void json_manifest_finalize_version (JsonManifestParseState *parse)
 
static void json_manifest_finalize_system_identifier (JsonManifestParseState *parse)
 
static void json_manifest_finalize_file (JsonManifestParseState *parse)
 
static void json_manifest_finalize_wal_range (JsonManifestParseState *parse)
 
static void verify_manifest_checksum (JsonManifestParseState *parse, const char *buffer, size_t size, pg_cryptohash_ctx *incr_ctx)
 
static void json_manifest_parse_failure (JsonManifestParseContext *context, char *msg)
 
static int hexdecode_char (char c)
 
static bool hexdecode_string (uint8 *result, char *input, int nbytes)
 
static bool parse_xlogrecptr (XLogRecPtr *result, char *input)
 
JsonManifestParseIncrementalStatejson_parse_manifest_incremental_init (JsonManifestParseContext *context)
 
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)
 
void json_parse_manifest (JsonManifestParseContext *context, const char *buffer, size_t size)
 

Enumeration Type Documentation

◆ JsonManifestFileField

Enumerator
JMFF_PATH 
JMFF_ENCODED_PATH 
JMFF_SIZE 
JMFF_LAST_MODIFIED 
JMFF_CHECKSUM_ALGORITHM 
JMFF_CHECKSUM 

Definition at line 44 of file parse_manifest.c.

45{
JsonManifestFileField
@ JMFF_ENCODED_PATH
@ JMFF_PATH
@ JMFF_LAST_MODIFIED
@ JMFF_CHECKSUM_ALGORITHM
@ JMFF_CHECKSUM
@ JMFF_SIZE

◆ JsonManifestSemanticState

Enumerator
JM_EXPECT_TOPLEVEL_START 
JM_EXPECT_TOPLEVEL_END 
JM_EXPECT_TOPLEVEL_FIELD 
JM_EXPECT_VERSION_VALUE 
JM_EXPECT_SYSTEM_IDENTIFIER_VALUE 
JM_EXPECT_FILES_START 
JM_EXPECT_FILES_NEXT 
JM_EXPECT_THIS_FILE_FIELD 
JM_EXPECT_THIS_FILE_VALUE 
JM_EXPECT_WAL_RANGES_START 
JM_EXPECT_WAL_RANGES_NEXT 
JM_EXPECT_THIS_WAL_RANGE_FIELD 
JM_EXPECT_THIS_WAL_RANGE_VALUE 
JM_EXPECT_MANIFEST_CHECKSUM_VALUE 
JM_EXPECT_EOF 

Definition at line 22 of file parse_manifest.c.

23{
JsonManifestSemanticState
@ JM_EXPECT_TOPLEVEL_END
@ JM_EXPECT_FILES_START
@ JM_EXPECT_SYSTEM_IDENTIFIER_VALUE
@ JM_EXPECT_TOPLEVEL_START
@ JM_EXPECT_EOF
@ JM_EXPECT_WAL_RANGES_START
@ JM_EXPECT_FILES_NEXT
@ 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

Enumerator
JMWRF_TIMELINE 
JMWRF_START_LSN 
JMWRF_END_LSN 

Definition at line 57 of file parse_manifest.c.

58{
JsonManifestWALRangeField
@ JMWRF_START_LSN
@ JMWRF_TIMELINE
@ JMWRF_END_LSN

Function Documentation

◆ hexdecode_char()

static int hexdecode_char ( char  c)
static

Definition at line 900 of file parse_manifest.c.

901{
902 if (c >= '0' && c <= '9')
903 return c - '0';
904 if (c >= 'a' && c <= 'f')
905 return c - 'a' + 10;
906 if (c >= 'A' && c <= 'F')
907 return c - 'A' + 10;
908
909 return -1;
910}
char * c

Referenced by hexdecode_string().

◆ hexdecode_string()

static bool hexdecode_string ( uint8 result,
char *  input,
int  nbytes 
)
static

Definition at line 918 of file parse_manifest.c.

919{
920 int i;
921
922 for (i = 0; i < nbytes; ++i)
923 {
924 int n1 = hexdecode_char(input[i * 2]);
925 int n2 = hexdecode_char(input[i * 2 + 1]);
926
927 if (n1 < 0 || n2 < 0)
928 return false;
929 result[i] = n1 * 16 + n2;
930 }
931
932 return true;
933}
FILE * input
int i
Definition: isn.c:72
static int hexdecode_char(char c)

References hexdecode_char(), i, and input.

Referenced by json_manifest_finalize_file(), and verify_manifest_checksum().

◆ json_manifest_array_end()

static JsonParseErrorType json_manifest_array_end ( void *  state)
static

Definition at line 378 of file parse_manifest.c.

379{
381
382 switch (parse->state)
383 {
387 break;
388 default:
390 "unexpected array end");
391 break;
392 }
393
394 return JSON_SUCCESS;
395}
@ JSON_SUCCESS
Definition: jsonapi.h:36
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
Definition: regguts.h:323

References JM_EXPECT_FILES_NEXT, JM_EXPECT_TOPLEVEL_FIELD, JM_EXPECT_WAL_RANGES_NEXT, json_manifest_parse_failure(), JSON_SUCCESS, and parse().

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_manifest_array_start()

static JsonParseErrorType json_manifest_array_start ( void *  state)
static

Definition at line 351 of file parse_manifest.c.

352{
354
355 switch (parse->state)
356 {
359 break;
362 break;
363 default:
365 "unexpected array start");
366 break;
367 }
368
369 return JSON_SUCCESS;
370}

References JM_EXPECT_FILES_NEXT, JM_EXPECT_FILES_START, JM_EXPECT_WAL_RANGES_NEXT, JM_EXPECT_WAL_RANGES_START, json_manifest_parse_failure(), JSON_SUCCESS, and parse().

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_manifest_finalize_file()

static void json_manifest_finalize_file ( JsonManifestParseState parse)
static

Definition at line 649 of file parse_manifest.c.

650{
651 JsonManifestParseContext *context = parse->context;
652 uint64 size;
653 char *ep;
654 int checksum_string_length;
655 pg_checksum_type checksum_type;
656 int checksum_length;
657 uint8 *checksum_payload;
658
659 /* Pathname and size are required. */
660 if (parse->pathname == NULL && parse->encoded_pathname == NULL)
661 json_manifest_parse_failure(parse->context, "missing path name");
662 if (parse->pathname != NULL && parse->encoded_pathname != NULL)
664 "both path name and encoded path name");
665 if (parse->size == NULL)
666 json_manifest_parse_failure(parse->context, "missing size");
667 if (parse->algorithm == NULL && parse->checksum != NULL)
669 "checksum without algorithm");
670
671 /* Decode encoded pathname, if that's what we have. */
672 if (parse->encoded_pathname != NULL)
673 {
674 int encoded_length = strlen(parse->encoded_pathname);
675 int raw_length = encoded_length / 2;
676
677 parse->pathname = palloc(raw_length + 1);
678 if (encoded_length % 2 != 0 ||
679 !hexdecode_string((uint8 *) parse->pathname,
680 parse->encoded_pathname,
681 raw_length))
683 "could not decode file name");
684 parse->pathname[raw_length] = '\0';
685 pfree(parse->encoded_pathname);
686 parse->encoded_pathname = NULL;
687 }
688
689 /* Parse size. */
690 size = strtou64(parse->size, &ep, 10);
691 if (*ep)
693 "file size is not an integer");
694
695 /* Parse the checksum algorithm, if it's present. */
696 if (parse->algorithm == NULL)
697 checksum_type = CHECKSUM_TYPE_NONE;
698 else if (!pg_checksum_parse_type(parse->algorithm, &checksum_type))
699 context->error_cb(context, "unrecognized checksum algorithm: \"%s\"",
700 parse->algorithm);
701
702 /* Parse the checksum payload, if it's present. */
703 checksum_string_length = parse->checksum == NULL ? 0
704 : strlen(parse->checksum);
705 if (checksum_string_length == 0)
706 {
707 checksum_length = 0;
708 checksum_payload = NULL;
709 }
710 else
711 {
712 checksum_length = checksum_string_length / 2;
713 checksum_payload = palloc(checksum_length);
714 if (checksum_string_length % 2 != 0 ||
715 !hexdecode_string(checksum_payload, parse->checksum,
716 checksum_length))
717 context->error_cb(context,
718 "invalid checksum for file \"%s\": \"%s\"",
719 parse->pathname, parse->checksum);
720 }
721
722 /* Invoke the callback with the details we've gathered. */
723 context->per_file_cb(context, parse->pathname, size,
724 checksum_type, checksum_length, checksum_payload);
725
726 /* Free memory we no longer need. */
727 if (parse->size != NULL)
728 {
729 pfree(parse->size);
730 parse->size = NULL;
731 }
732 if (parse->algorithm != NULL)
733 {
734 pfree(parse->algorithm);
735 parse->algorithm = NULL;
736 }
737 if (parse->checksum != NULL)
738 {
739 pfree(parse->checksum);
740 parse->checksum = NULL;
741 }
742}
uint8_t uint8
Definition: c.h:483
uint64_t uint64
Definition: c.h:486
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
pg_checksum_type
@ CHECKSUM_TYPE_NONE
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
static pg_noinline void Size size
Definition: slab.c:607
json_manifest_error_callback error_cb
json_manifest_per_file_callback per_file_cb

References CHECKSUM_TYPE_NONE, JsonManifestParseContext::error_cb, hexdecode_string(), json_manifest_parse_failure(), palloc(), parse(), JsonManifestParseContext::per_file_cb, pfree(), pg_checksum_parse_type(), and size.

Referenced by json_manifest_object_end().

◆ json_manifest_finalize_system_identifier()

static void json_manifest_finalize_system_identifier ( JsonManifestParseState parse)
static

Definition at line 624 of file parse_manifest.c.

625{
626 JsonManifestParseContext *context = parse->context;
627 uint64 system_identifier;
628 char *ep;
629
630 Assert(parse->manifest_system_identifier != NULL);
631
632 /* Parse system identifier. */
633 system_identifier = strtou64(parse->manifest_system_identifier, &ep, 10);
634 if (*ep)
636 "system identifier in manifest not an integer");
637
638 /* Invoke the callback for system identifier */
639 context->system_identifier_cb(context, system_identifier);
640}
#define Assert(condition)
Definition: c.h:812
json_manifest_system_identifier_callback system_identifier_cb

References Assert, json_manifest_parse_failure(), parse(), and JsonManifestParseContext::system_identifier_cb.

Referenced by json_manifest_scalar().

◆ json_manifest_finalize_version()

static void json_manifest_finalize_version ( JsonManifestParseState parse)
static

Definition at line 596 of file parse_manifest.c.

597{
598 JsonManifestParseContext *context = parse->context;
599 int version;
600 char *ep;
601
602 Assert(parse->saw_version_field);
603
604 /* Parse version. */
605 version = strtoi64(parse->manifest_version, &ep, 10);
606 if (*ep)
608 "manifest version not an integer");
609
610 if (version != 1 && version != 2)
612 "unexpected manifest version");
613
614 /* Invoke the callback for version */
615 context->version_cb(context, version);
616}
json_manifest_version_callback version_cb

References Assert, json_manifest_parse_failure(), parse(), and JsonManifestParseContext::version_cb.

Referenced by json_manifest_scalar().

◆ json_manifest_finalize_wal_range()

static void json_manifest_finalize_wal_range ( JsonManifestParseState parse)
static

Definition at line 751 of file parse_manifest.c.

752{
753 JsonManifestParseContext *context = parse->context;
754 TimeLineID tli;
755 XLogRecPtr start_lsn,
756 end_lsn;
757 char *ep;
758
759 /* Make sure all fields are present. */
760 if (parse->timeline == NULL)
761 json_manifest_parse_failure(parse->context, "missing timeline");
762 if (parse->start_lsn == NULL)
763 json_manifest_parse_failure(parse->context, "missing start LSN");
764 if (parse->end_lsn == NULL)
765 json_manifest_parse_failure(parse->context, "missing end LSN");
766
767 /* Parse timeline. */
768 tli = strtoul(parse->timeline, &ep, 10);
769 if (*ep)
771 "timeline is not an integer");
772 if (!parse_xlogrecptr(&start_lsn, parse->start_lsn))
774 "could not parse start LSN");
775 if (!parse_xlogrecptr(&end_lsn, parse->end_lsn))
777 "could not parse end LSN");
778
779 /* Invoke the callback with the details we've gathered. */
780 context->per_wal_range_cb(context, tli, start_lsn, end_lsn);
781
782 /* Free memory we no longer need. */
783 if (parse->timeline != NULL)
784 {
785 pfree(parse->timeline);
786 parse->timeline = NULL;
787 }
788 if (parse->start_lsn != NULL)
789 {
790 pfree(parse->start_lsn);
791 parse->start_lsn = NULL;
792 }
793 if (parse->end_lsn != NULL)
794 {
795 pfree(parse->end_lsn);
796 parse->end_lsn = NULL;
797 }
798}
static bool parse_xlogrecptr(XLogRecPtr *result, char *input)
json_manifest_per_wal_range_callback per_wal_range_cb
uint64 XLogRecPtr
Definition: xlogdefs.h:21
uint32 TimeLineID
Definition: xlogdefs.h:59

References json_manifest_parse_failure(), parse(), parse_xlogrecptr(), JsonManifestParseContext::per_wal_range_cb, and pfree().

Referenced by json_manifest_object_end().

◆ json_manifest_object_end()

static JsonParseErrorType json_manifest_object_end ( void *  state)
static

Definition at line 317 of file parse_manifest.c.

318{
320
321 switch (parse->state)
322 {
324 parse->state = JM_EXPECT_EOF;
325 break;
329 break;
333 break;
334 default:
336 "unexpected object end");
337 break;
338 }
339
340 return JSON_SUCCESS;
341}
static void json_manifest_finalize_wal_range(JsonManifestParseState *parse)
static void json_manifest_finalize_file(JsonManifestParseState *parse)

References JM_EXPECT_EOF, JM_EXPECT_FILES_NEXT, JM_EXPECT_THIS_FILE_FIELD, JM_EXPECT_THIS_WAL_RANGE_FIELD, JM_EXPECT_TOPLEVEL_END, JM_EXPECT_WAL_RANGES_NEXT, json_manifest_finalize_file(), json_manifest_finalize_wal_range(), json_manifest_parse_failure(), JSON_SUCCESS, and parse().

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_manifest_object_field_start()

static JsonParseErrorType json_manifest_object_field_start ( void *  state,
char *  fname,
bool  isnull 
)
static

Definition at line 401 of file parse_manifest.c.

402{
404
405 switch (parse->state)
406 {
408
409 /*
410 * Inside toplevel object. The version indicator should always be
411 * the first field.
412 */
413 if (!parse->saw_version_field)
414 {
415 if (strcmp(fname, "PostgreSQL-Backup-Manifest-Version") != 0)
417 "expected version indicator");
419 parse->saw_version_field = true;
420 break;
421 }
422
423 /* Is this the system identifier? */
424 if (strcmp(fname, "System-Identifier") == 0)
425 {
427 break;
428 }
429
430 /* Is this the list of files? */
431 if (strcmp(fname, "Files") == 0)
432 {
434 break;
435 }
436
437 /* Is this the list of WAL ranges? */
438 if (strcmp(fname, "WAL-Ranges") == 0)
439 {
441 break;
442 }
443
444 /* Is this the manifest checksum? */
445 if (strcmp(fname, "Manifest-Checksum") == 0)
446 {
448 break;
449 }
450
451 /* It's not a field we recognize. */
453 "unrecognized top-level field");
454 break;
455
457 /* Inside object for one file; which key have we got? */
458 if (strcmp(fname, "Path") == 0)
459 parse->file_field = JMFF_PATH;
460 else if (strcmp(fname, "Encoded-Path") == 0)
461 parse->file_field = JMFF_ENCODED_PATH;
462 else if (strcmp(fname, "Size") == 0)
463 parse->file_field = JMFF_SIZE;
464 else if (strcmp(fname, "Last-Modified") == 0)
465 parse->file_field = JMFF_LAST_MODIFIED;
466 else if (strcmp(fname, "Checksum-Algorithm") == 0)
467 parse->file_field = JMFF_CHECKSUM_ALGORITHM;
468 else if (strcmp(fname, "Checksum") == 0)
469 parse->file_field = JMFF_CHECKSUM;
470 else
472 "unexpected file field");
474 break;
475
477 /* Inside object for one file; which key have we got? */
478 if (strcmp(fname, "Timeline") == 0)
479 parse->wal_range_field = JMWRF_TIMELINE;
480 else if (strcmp(fname, "Start-LSN") == 0)
481 parse->wal_range_field = JMWRF_START_LSN;
482 else if (strcmp(fname, "End-LSN") == 0)
483 parse->wal_range_field = JMWRF_END_LSN;
484 else
486 "unexpected WAL range field");
488 break;
489
490 default:
492 "unexpected object field");
493 break;
494 }
495
496 pfree(fname);
497
498 return JSON_SUCCESS;
499}

References JM_EXPECT_FILES_START, JM_EXPECT_MANIFEST_CHECKSUM_VALUE, JM_EXPECT_SYSTEM_IDENTIFIER_VALUE, JM_EXPECT_THIS_FILE_FIELD, JM_EXPECT_THIS_FILE_VALUE, JM_EXPECT_THIS_WAL_RANGE_FIELD, JM_EXPECT_THIS_WAL_RANGE_VALUE, JM_EXPECT_TOPLEVEL_FIELD, JM_EXPECT_VERSION_VALUE, JM_EXPECT_WAL_RANGES_START, JMFF_CHECKSUM, JMFF_CHECKSUM_ALGORITHM, JMFF_ENCODED_PATH, JMFF_LAST_MODIFIED, JMFF_PATH, JMFF_SIZE, JMWRF_END_LSN, JMWRF_START_LSN, JMWRF_TIMELINE, json_manifest_parse_failure(), JSON_SUCCESS, parse(), and pfree().

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_manifest_object_start()

static JsonParseErrorType json_manifest_object_start ( void *  state)
static

Definition at line 276 of file parse_manifest.c.

277{
279
280 switch (parse->state)
281 {
284 break;
287 parse->pathname = NULL;
288 parse->encoded_pathname = NULL;
289 parse->size = NULL;
290 parse->algorithm = NULL;
291 parse->checksum = NULL;
292 break;
295 parse->timeline = NULL;
296 parse->start_lsn = NULL;
297 parse->end_lsn = NULL;
298 break;
299 default:
301 "unexpected object start");
302 break;
303 }
304
305 return JSON_SUCCESS;
306}

References JM_EXPECT_FILES_NEXT, JM_EXPECT_THIS_FILE_FIELD, JM_EXPECT_THIS_WAL_RANGE_FIELD, JM_EXPECT_TOPLEVEL_FIELD, JM_EXPECT_TOPLEVEL_START, JM_EXPECT_WAL_RANGES_NEXT, json_manifest_parse_failure(), JSON_SUCCESS, and parse().

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_manifest_parse_failure()

◆ json_manifest_scalar()

static JsonParseErrorType json_manifest_scalar ( void *  state,
char *  token,
JsonTokenType  tokentype 
)
static

Definition at line 517 of file parse_manifest.c.

518{
520
521 switch (parse->state)
522 {
524 parse->manifest_version = token;
527 break;
528
530 parse->manifest_system_identifier = token;
533 break;
534
536 switch (parse->file_field)
537 {
538 case JMFF_PATH:
539 parse->pathname = token;
540 break;
542 parse->encoded_pathname = token;
543 break;
544 case JMFF_SIZE:
545 parse->size = token;
546 break;
548 pfree(token); /* unused */
549 break;
551 parse->algorithm = token;
552 break;
553 case JMFF_CHECKSUM:
554 parse->checksum = token;
555 break;
556 }
558 break;
559
561 switch (parse->wal_range_field)
562 {
563 case JMWRF_TIMELINE:
564 parse->timeline = token;
565 break;
566 case JMWRF_START_LSN:
567 parse->start_lsn = token;
568 break;
569 case JMWRF_END_LSN:
570 parse->end_lsn = token;
571 break;
572 }
574 break;
575
578 parse->manifest_checksum = token;
579 break;
580
581 default:
582 json_manifest_parse_failure(parse->context, "unexpected scalar");
583 break;
584 }
585
586 return JSON_SUCCESS;
587}
#define token
Definition: indent_globs.h:126
static void json_manifest_finalize_version(JsonManifestParseState *parse)
static void json_manifest_finalize_system_identifier(JsonManifestParseState *parse)

References JM_EXPECT_MANIFEST_CHECKSUM_VALUE, JM_EXPECT_SYSTEM_IDENTIFIER_VALUE, JM_EXPECT_THIS_FILE_FIELD, JM_EXPECT_THIS_FILE_VALUE, JM_EXPECT_THIS_WAL_RANGE_FIELD, JM_EXPECT_THIS_WAL_RANGE_VALUE, JM_EXPECT_TOPLEVEL_END, JM_EXPECT_TOPLEVEL_FIELD, JM_EXPECT_VERSION_VALUE, JMFF_CHECKSUM, JMFF_CHECKSUM_ALGORITHM, JMFF_ENCODED_PATH, JMFF_LAST_MODIFIED, JMFF_PATH, JMFF_SIZE, JMWRF_END_LSN, JMWRF_START_LSN, JMWRF_TIMELINE, json_manifest_finalize_system_identifier(), json_manifest_finalize_version(), json_manifest_parse_failure(), JSON_SUCCESS, parse(), pfree(), and token.

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_init().

◆ json_parse_manifest()

void json_parse_manifest ( JsonManifestParseContext context,
const char *  buffer,
size_t  size 
)

Definition at line 227 of file parse_manifest.c.

229{
230 JsonLexContext *lex;
231 JsonParseErrorType json_error;
234
235 /* Set up our private parsing context. */
236 parse.context = context;
238 parse.saw_version_field = false;
239
240 /* Create a JSON lexing context. */
241 lex = makeJsonLexContextCstringLen(NULL, buffer, size, PG_UTF8, true);
242
243 /* Set up semantic actions. */
244 sem.semstate = &parse;
250 sem.object_field_end = NULL;
252 sem.array_element_end = NULL;
254
255 /* Run the actual JSON parser. */
256 json_error = pg_parse_json(lex, &sem);
257 if (json_error != JSON_SUCCESS)
258 json_manifest_parse_failure(context, json_errdetail(json_error, lex));
259 if (parse.state != JM_EXPECT_EOF)
260 json_manifest_parse_failure(context, "manifest ended unexpectedly");
261
262 /* Verify the manifest checksum. */
263 verify_manifest_checksum(&parse, buffer, size, NULL);
264
266}
JsonParseErrorType pg_parse_json(JsonLexContext *lex, const JsonSemAction *sem)
Definition: jsonapi.c:744
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:392
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:2397
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:687
JsonParseErrorType
Definition: jsonapi.h:35
static JsonParseErrorType json_manifest_array_start(void *state)
static JsonParseErrorType json_manifest_object_field_start(void *state, char *fname, bool isnull)
static JsonParseErrorType json_manifest_object_end(void *state)
static JsonParseErrorType json_manifest_object_start(void *state)
static JsonParseErrorType json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
static JsonParseErrorType json_manifest_array_end(void *state)
static void verify_manifest_checksum(JsonManifestParseState *parse, const char *buffer, size_t size, pg_cryptohash_ctx *incr_ctx)
@ PG_UTF8
Definition: pg_wchar.h:232
json_struct_action array_end
Definition: jsonapi.h:151
json_struct_action object_start
Definition: jsonapi.h:148
json_ofield_action object_field_start
Definition: jsonapi.h:152
json_aelem_action array_element_start
Definition: jsonapi.h:154
json_scalar_action scalar
Definition: jsonapi.h:156
void * semstate
Definition: jsonapi.h:147
json_aelem_action array_element_end
Definition: jsonapi.h:155
json_struct_action array_start
Definition: jsonapi.h:150
json_struct_action object_end
Definition: jsonapi.h:149
json_ofield_action object_field_end
Definition: jsonapi.h:153
static JsonSemAction sem

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, freeJsonLexContext(), JM_EXPECT_EOF, JM_EXPECT_TOPLEVEL_START, json_errdetail(), json_manifest_array_end(), json_manifest_array_start(), json_manifest_object_end(), json_manifest_object_field_start(), json_manifest_object_start(), json_manifest_parse_failure(), json_manifest_scalar(), JSON_SUCCESS, makeJsonLexContextCstringLen(), JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, parse(), pg_parse_json(), PG_UTF8, JsonSemAction::scalar, sem, JsonSemAction::semstate, size, and verify_manifest_checksum().

Referenced by load_backup_manifest(), and parse_manifest_file().

◆ json_parse_manifest_incremental_chunk()

void json_parse_manifest_incremental_chunk ( JsonManifestParseIncrementalState incstate,
const char *  chunk,
size_t  size,
bool  is_last 
)

Definition at line 185 of file parse_manifest.c.

187{
189 expected;
191 JsonManifestParseContext *context = parse->context;
192
193 res = pg_parse_json_incremental(&(incstate->lex), &(incstate->sem),
194 chunk, size, is_last);
195
196 expected = is_last ? JSON_SUCCESS : JSON_INCOMPLETE;
197
198 if (res != expected)
200 json_errdetail(res, &(incstate->lex)));
201
202 if (is_last && parse->state != JM_EXPECT_EOF)
203 json_manifest_parse_failure(context, "manifest ended unexpectedly");
204
205 if (!is_last)
206 {
208 (const uint8 *) chunk, size) < 0)
209 context->error_cb(context, "could not update checksum of manifest");
210 }
211 else
212 {
214 }
215}
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
uint64 chunk
JsonParseErrorType pg_parse_json_incremental(JsonLexContext *lex, const JsonSemAction *sem, const char *json, size_t len, bool is_last)
Definition: jsonapi.c:868
@ JSON_INCOMPLETE
Definition: jsonapi.h:37
pg_cryptohash_ctx * manifest_ctx

References chunk, JsonManifestParseContext::error_cb, JM_EXPECT_EOF, json_errdetail(), JSON_INCOMPLETE, json_manifest_parse_failure(), JSON_SUCCESS, JsonManifestParseIncrementalState::lex, JsonManifestParseIncrementalState::manifest_ctx, parse(), pg_cryptohash_update(), pg_parse_json_incremental(), res, JsonManifestParseIncrementalState::sem, JsonSemAction::semstate, size, and verify_manifest_checksum().

Referenced by AppendIncrementalManifestData(), FinalizeIncrementalManifest(), load_backup_manifest(), and parse_manifest_file().

◆ json_parse_manifest_incremental_init()

JsonManifestParseIncrementalState * json_parse_manifest_incremental_init ( JsonManifestParseContext context)

Definition at line 129 of file parse_manifest.c.

130{
133 pg_cryptohash_ctx *manifest_ctx;
134
135 incstate = palloc(sizeof(JsonManifestParseIncrementalState));
137
138 parse->context = context;
140 parse->saw_version_field = false;
141
142 makeJsonLexContextIncremental(&(incstate->lex), PG_UTF8, true);
143
144 incstate->sem.semstate = parse;
150 incstate->sem.object_field_end = NULL;
151 incstate->sem.array_element_start = NULL;
152 incstate->sem.array_element_end = NULL;
153 incstate->sem.scalar = json_manifest_scalar;
154
155 manifest_ctx = pg_cryptohash_create(PG_SHA256);
156 if (manifest_ctx == NULL)
157 context->error_cb(context, "out of memory");
158 if (pg_cryptohash_init(manifest_ctx) < 0)
159 context->error_cb(context, "could not initialize checksum of manifest");
160 incstate->manifest_ctx = manifest_ctx;
161
162 return incstate;
163}
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
@ PG_SHA256
Definition: cryptohash.h:24
JsonLexContext * makeJsonLexContextIncremental(JsonLexContext *lex, int encoding, bool need_escapes)
Definition: jsonapi.c:497

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, JsonManifestParseContext::error_cb, JM_EXPECT_TOPLEVEL_START, json_manifest_array_end(), json_manifest_array_start(), json_manifest_object_end(), json_manifest_object_field_start(), json_manifest_object_start(), json_manifest_scalar(), JsonManifestParseIncrementalState::lex, makeJsonLexContextIncremental(), JsonManifestParseIncrementalState::manifest_ctx, JsonSemAction::object_end, JsonSemAction::object_field_end, JsonSemAction::object_field_start, JsonSemAction::object_start, palloc(), parse(), pg_cryptohash_create(), pg_cryptohash_init(), PG_SHA256, PG_UTF8, JsonSemAction::scalar, JsonManifestParseIncrementalState::sem, and JsonSemAction::semstate.

Referenced by CreateIncrementalBackupInfo(), load_backup_manifest(), and parse_manifest_file().

◆ json_parse_manifest_incremental_shutdown()

void json_parse_manifest_incremental_shutdown ( JsonManifestParseIncrementalState incstate)

Definition at line 169 of file parse_manifest.c.

170{
171 pfree(incstate->sem.semstate);
172 freeJsonLexContext(&(incstate->lex));
173 /* incstate->manifest_ctx has already been freed */
174 pfree(incstate);
175}

References freeJsonLexContext(), JsonManifestParseIncrementalState::lex, pfree(), JsonManifestParseIncrementalState::sem, and JsonSemAction::semstate.

Referenced by FinalizeIncrementalManifest(), load_backup_manifest(), and parse_manifest_file().

◆ parse_xlogrecptr()

static bool parse_xlogrecptr ( XLogRecPtr result,
char *  input 
)
static

Definition at line 939 of file parse_manifest.c.

940{
941 uint32 hi;
942 uint32 lo;
943
944 if (sscanf(input, "%X/%X", &hi, &lo) != 2)
945 return false;
946 *result = ((uint64) hi) << 32 | lo;
947 return true;
948}
uint32_t uint32
Definition: c.h:485

References input.

Referenced by json_manifest_finalize_wal_range().

◆ verify_manifest_checksum()

static void verify_manifest_checksum ( JsonManifestParseState parse,
const char *  buffer,
size_t  size,
pg_cryptohash_ctx incr_ctx 
)
static

Definition at line 812 of file parse_manifest.c.

814{
815 JsonManifestParseContext *context = parse->context;
816 size_t i;
817 size_t number_of_newlines = 0;
818 size_t ultimate_newline = 0;
819 size_t penultimate_newline = 0;
820 pg_cryptohash_ctx *manifest_ctx;
821 uint8 manifest_checksum_actual[PG_SHA256_DIGEST_LENGTH];
822 uint8 manifest_checksum_expected[PG_SHA256_DIGEST_LENGTH];
823
824 /* Find the last two newlines in the file. */
825 for (i = 0; i < size; ++i)
826 {
827 if (buffer[i] == '\n')
828 {
829 ++number_of_newlines;
830 penultimate_newline = ultimate_newline;
831 ultimate_newline = i;
832 }
833 }
834
835 /*
836 * Make sure that the last newline is right at the end, and that there are
837 * at least two lines total. We need this to be true in order for the
838 * following code, which computes the manifest checksum, to work properly.
839 */
840 if (number_of_newlines < 2)
842 "expected at least 2 lines");
843 if (ultimate_newline != size - 1)
845 "last line not newline-terminated");
846
847 /* Checksum the rest. */
848 if (incr_ctx == NULL)
849 {
850 manifest_ctx = pg_cryptohash_create(PG_SHA256);
851 if (manifest_ctx == NULL)
852 context->error_cb(context, "out of memory");
853 if (pg_cryptohash_init(manifest_ctx) < 0)
854 context->error_cb(context, "could not initialize checksum of manifest");
855 }
856 else
857 {
858 manifest_ctx = incr_ctx;
859 }
860 if (pg_cryptohash_update(manifest_ctx, (const uint8 *) buffer, penultimate_newline + 1) < 0)
861 context->error_cb(context, "could not update checksum of manifest");
862 if (pg_cryptohash_final(manifest_ctx, manifest_checksum_actual,
863 sizeof(manifest_checksum_actual)) < 0)
864 context->error_cb(context, "could not finalize checksum of manifest");
865
866 /* Now verify it. */
867 if (parse->manifest_checksum == NULL)
868 context->error_cb(parse->context, "manifest has no checksum");
869 if (strlen(parse->manifest_checksum) != PG_SHA256_DIGEST_LENGTH * 2 ||
870 !hexdecode_string(manifest_checksum_expected, parse->manifest_checksum,
872 context->error_cb(context, "invalid manifest checksum: \"%s\"",
873 parse->manifest_checksum);
874 if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
876 context->error_cb(context, "manifest checksum mismatch");
877 pg_cryptohash_free(manifest_ctx);
878}
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:23

References JsonManifestParseContext::error_cb, hexdecode_string(), i, json_manifest_parse_failure(), parse(), pg_cryptohash_create(), pg_cryptohash_final(), pg_cryptohash_free(), pg_cryptohash_init(), pg_cryptohash_update(), PG_SHA256, PG_SHA256_DIGEST_LENGTH, and size.

Referenced by json_parse_manifest(), and json_parse_manifest_incremental_chunk().