PostgreSQL Source Code  git master
parse_manifest.c File Reference
#include "postgres_fe.h"
#include "parse_manifest.h"
#include "common/jsonapi.h"
Include dependency graph for parse_manifest.c:

Go to the source code of this file.

Data Structures

struct  JsonManifestParseState
 

Enumerations

enum  JsonManifestSemanticState {
  JM_EXPECT_TOPLEVEL_START , JM_EXPECT_TOPLEVEL_END , JM_EXPECT_TOPLEVEL_FIELD , JM_EXPECT_VERSION_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_file (JsonManifestParseState *parse)
 
static void json_manifest_finalize_wal_range (JsonManifestParseState *parse)
 
static void verify_manifest_checksum (JsonManifestParseState *parse, char *buffer, size_t size)
 
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)
 
void json_parse_manifest (JsonManifestParseContext *context, 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 43 of file parse_manifest.c.

44 {
45  JMFF_PATH,
47  JMFF_SIZE,
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_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_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 56 of file parse_manifest.c.

57 {
JsonManifestWALRangeField
@ JMWRF_START_LSN
@ JMWRF_TIMELINE
@ JMWRF_END_LSN

Function Documentation

◆ hexdecode_char()

static int hexdecode_char ( char  c)
static

Definition at line 714 of file parse_manifest.c.

715 {
716  if (c >= '0' && c <= '9')
717  return c - '0';
718  if (c >= 'a' && c <= 'f')
719  return c - 'a' + 10;
720  if (c >= 'A' && c <= 'F')
721  return c - 'A' + 10;
722 
723  return -1;
724 }
char * c

Referenced by hexdecode_string().

◆ hexdecode_string()

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

Definition at line 732 of file parse_manifest.c.

733 {
734  int i;
735 
736  for (i = 0; i < nbytes; ++i)
737  {
738  int n1 = hexdecode_char(input[i * 2]);
739  int n2 = hexdecode_char(input[i * 2 + 1]);
740 
741  if (n1 < 0 || n2 < 0)
742  return false;
743  result[i] = n1 * 16 + n2;
744  }
745 
746  return true;
747 }
FILE * input
int i
Definition: isn.c:73
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 270 of file parse_manifest.c.

271 {
273 
274  switch (parse->state)
275  {
279  break;
280  default:
282  "unexpected array end");
283  break;
284  }
285 
286  return JSON_SUCCESS;
287 }
@ JSON_SUCCESS
Definition: jsonapi.h:38
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:715
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().

◆ json_manifest_array_start()

static JsonParseErrorType json_manifest_array_start ( void *  state)
static

Definition at line 243 of file parse_manifest.c.

244 {
246 
247  switch (parse->state)
248  {
250  parse->state = JM_EXPECT_FILES_NEXT;
251  break;
254  break;
255  default:
257  "unexpected array start");
258  break;
259  }
260 
261  return JSON_SUCCESS;
262 }

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().

◆ json_manifest_finalize_file()

static void json_manifest_finalize_file ( JsonManifestParseState parse)
static

Definition at line 474 of file parse_manifest.c.

475 {
476  JsonManifestParseContext *context = parse->context;
477  size_t size;
478  char *ep;
479  int checksum_string_length;
480  pg_checksum_type checksum_type;
481  int checksum_length;
482  uint8 *checksum_payload;
483 
484  /* Pathname and size are required. */
485  if (parse->pathname == NULL && parse->encoded_pathname == NULL)
486  json_manifest_parse_failure(parse->context, "missing path name");
487  if (parse->pathname != NULL && parse->encoded_pathname != NULL)
489  "both path name and encoded path name");
490  if (parse->size == NULL)
491  json_manifest_parse_failure(parse->context, "missing size");
492  if (parse->algorithm == NULL && parse->checksum != NULL)
494  "checksum without algorithm");
495 
496  /* Decode encoded pathname, if that's what we have. */
497  if (parse->encoded_pathname != NULL)
498  {
499  int encoded_length = strlen(parse->encoded_pathname);
500  int raw_length = encoded_length / 2;
501 
502  parse->pathname = palloc(raw_length + 1);
503  if (encoded_length % 2 != 0 ||
504  !hexdecode_string((uint8 *) parse->pathname,
505  parse->encoded_pathname,
506  raw_length))
508  "could not decode file name");
509  parse->pathname[raw_length] = '\0';
510  pfree(parse->encoded_pathname);
511  parse->encoded_pathname = NULL;
512  }
513 
514  /* Parse size. */
515  size = strtoul(parse->size, &ep, 10);
516  if (*ep)
518  "file size is not an integer");
519 
520  /* Parse the checksum algorithm, if it's present. */
521  if (parse->algorithm == NULL)
522  checksum_type = CHECKSUM_TYPE_NONE;
523  else if (!pg_checksum_parse_type(parse->algorithm, &checksum_type))
524  context->error_cb(context, "unrecognized checksum algorithm: \"%s\"",
525  parse->algorithm);
526 
527  /* Parse the checksum payload, if it's present. */
528  checksum_string_length = parse->checksum == NULL ? 0
529  : strlen(parse->checksum);
530  if (checksum_string_length == 0)
531  {
532  checksum_length = 0;
533  checksum_payload = NULL;
534  }
535  else
536  {
537  checksum_length = checksum_string_length / 2;
538  checksum_payload = palloc(checksum_length);
539  if (checksum_string_length % 2 != 0 ||
540  !hexdecode_string(checksum_payload, parse->checksum,
541  checksum_length))
542  context->error_cb(context,
543  "invalid checksum for file \"%s\": \"%s\"",
544  parse->pathname, parse->checksum);
545  }
546 
547  /* Invoke the callback with the details we've gathered. */
548  context->per_file_cb(context, parse->pathname, size,
549  checksum_type, checksum_length, checksum_payload);
550 
551  /* Free memory we no longer need. */
552  if (parse->size != NULL)
553  {
554  pfree(parse->size);
555  parse->size = NULL;
556  }
557  if (parse->algorithm != NULL)
558  {
559  pfree(parse->algorithm);
560  parse->algorithm = NULL;
561  }
562  if (parse->checksum != NULL)
563  {
564  pfree(parse->checksum);
565  parse->checksum = NULL;
566  }
567 }
unsigned char uint8
Definition: c.h:493
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
pg_checksum_type
@ CHECKSUM_TYPE_NONE
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
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(), and pg_checksum_parse_type().

Referenced by json_manifest_object_end().

◆ json_manifest_finalize_wal_range()

static void json_manifest_finalize_wal_range ( JsonManifestParseState parse)
static

Definition at line 576 of file parse_manifest.c.

577 {
578  JsonManifestParseContext *context = parse->context;
579  TimeLineID tli;
580  XLogRecPtr start_lsn,
581  end_lsn;
582  char *ep;
583 
584  /* Make sure all fields are present. */
585  if (parse->timeline == NULL)
586  json_manifest_parse_failure(parse->context, "missing timeline");
587  if (parse->start_lsn == NULL)
588  json_manifest_parse_failure(parse->context, "missing start LSN");
589  if (parse->end_lsn == NULL)
590  json_manifest_parse_failure(parse->context, "missing end LSN");
591 
592  /* Parse timeline. */
593  tli = strtoul(parse->timeline, &ep, 10);
594  if (*ep)
596  "timeline is not an integer");
597  if (!parse_xlogrecptr(&start_lsn, parse->start_lsn))
599  "could not parse start LSN");
600  if (!parse_xlogrecptr(&end_lsn, parse->end_lsn))
602  "could not parse end LSN");
603 
604  /* Invoke the callback with the details we've gathered. */
605  context->per_wal_range_cb(context, tli, start_lsn, end_lsn);
606 
607  /* Free memory we no longer need. */
608  if (parse->timeline != NULL)
609  {
610  pfree(parse->timeline);
611  parse->timeline = NULL;
612  }
613  if (parse->start_lsn != NULL)
614  {
615  pfree(parse->start_lsn);
616  parse->start_lsn = NULL;
617  }
618  if (parse->end_lsn != NULL)
619  {
620  pfree(parse->end_lsn);
621  parse->end_lsn = NULL;
622  }
623 }
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 209 of file parse_manifest.c.

210 {
212 
213  switch (parse->state)
214  {
216  parse->state = JM_EXPECT_EOF;
217  break;
220  parse->state = JM_EXPECT_FILES_NEXT;
221  break;
225  break;
226  default:
228  "unexpected object end");
229  break;
230  }
231 
232  return JSON_SUCCESS;
233 }
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().

◆ json_manifest_object_field_start()

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

Definition at line 293 of file parse_manifest.c.

294 {
296 
297  switch (parse->state)
298  {
300 
301  /*
302  * Inside toplevel object. The version indicator should always be
303  * the first field.
304  */
305  if (!parse->saw_version_field)
306  {
307  if (strcmp(fname, "PostgreSQL-Backup-Manifest-Version") != 0)
309  "expected version indicator");
311  parse->saw_version_field = true;
312  break;
313  }
314 
315  /* Is this the list of files? */
316  if (strcmp(fname, "Files") == 0)
317  {
318  parse->state = JM_EXPECT_FILES_START;
319  break;
320  }
321 
322  /* Is this the list of WAL ranges? */
323  if (strcmp(fname, "WAL-Ranges") == 0)
324  {
326  break;
327  }
328 
329  /* Is this the manifest checksum? */
330  if (strcmp(fname, "Manifest-Checksum") == 0)
331  {
333  break;
334  }
335 
336  /* It's not a field we recognize. */
338  "unrecognized top-level field");
339  break;
340 
342  /* Inside object for one file; which key have we got? */
343  if (strcmp(fname, "Path") == 0)
344  parse->file_field = JMFF_PATH;
345  else if (strcmp(fname, "Encoded-Path") == 0)
346  parse->file_field = JMFF_ENCODED_PATH;
347  else if (strcmp(fname, "Size") == 0)
348  parse->file_field = JMFF_SIZE;
349  else if (strcmp(fname, "Last-Modified") == 0)
350  parse->file_field = JMFF_LAST_MODIFIED;
351  else if (strcmp(fname, "Checksum-Algorithm") == 0)
352  parse->file_field = JMFF_CHECKSUM_ALGORITHM;
353  else if (strcmp(fname, "Checksum") == 0)
354  parse->file_field = JMFF_CHECKSUM;
355  else
357  "unexpected file field");
359  break;
360 
362  /* Inside object for one file; which key have we got? */
363  if (strcmp(fname, "Timeline") == 0)
364  parse->wal_range_field = JMWRF_TIMELINE;
365  else if (strcmp(fname, "Start-LSN") == 0)
366  parse->wal_range_field = JMWRF_START_LSN;
367  else if (strcmp(fname, "End-LSN") == 0)
368  parse->wal_range_field = JMWRF_END_LSN;
369  else
371  "unexpected WAL range field");
373  break;
374 
375  default:
377  "unexpected object field");
378  break;
379  }
380 
381  return JSON_SUCCESS;
382 }

References JM_EXPECT_FILES_START, JM_EXPECT_MANIFEST_CHECKSUM_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, and parse().

Referenced by json_parse_manifest().

◆ json_manifest_object_start()

static JsonParseErrorType json_manifest_object_start ( void *  state)
static

Definition at line 168 of file parse_manifest.c.

169 {
171 
172  switch (parse->state)
173  {
176  break;
179  parse->pathname = NULL;
180  parse->encoded_pathname = NULL;
181  parse->size = NULL;
182  parse->algorithm = NULL;
183  parse->checksum = NULL;
184  break;
187  parse->timeline = NULL;
188  parse->start_lsn = NULL;
189  parse->end_lsn = NULL;
190  break;
191  default:
193  "unexpected object start");
194  break;
195  }
196 
197  return JSON_SUCCESS;
198 }

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().

◆ json_manifest_parse_failure()

static void json_manifest_parse_failure ( JsonManifestParseContext context,
char *  msg 
)
static

◆ json_manifest_scalar()

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

Definition at line 400 of file parse_manifest.c.

401 {
403 
404  switch (parse->state)
405  {
407  if (strcmp(token, "1") != 0)
409  "unexpected manifest version");
411  break;
412 
414  switch (parse->file_field)
415  {
416  case JMFF_PATH:
417  parse->pathname = token;
418  break;
419  case JMFF_ENCODED_PATH:
420  parse->encoded_pathname = token;
421  break;
422  case JMFF_SIZE:
423  parse->size = token;
424  break;
425  case JMFF_LAST_MODIFIED:
426  pfree(token); /* unused */
427  break;
429  parse->algorithm = token;
430  break;
431  case JMFF_CHECKSUM:
432  parse->checksum = token;
433  break;
434  }
436  break;
437 
439  switch (parse->wal_range_field)
440  {
441  case JMWRF_TIMELINE:
442  parse->timeline = token;
443  break;
444  case JMWRF_START_LSN:
445  parse->start_lsn = token;
446  break;
447  case JMWRF_END_LSN:
448  parse->end_lsn = token;
449  break;
450  }
452  break;
453 
455  parse->state = JM_EXPECT_TOPLEVEL_END;
456  parse->manifest_checksum = token;
457  break;
458 
459  default:
460  json_manifest_parse_failure(parse->context, "unexpected scalar");
461  break;
462  }
463 
464  return JSON_SUCCESS;
465 }
#define token
Definition: indent_globs.h:126

References JM_EXPECT_MANIFEST_CHECKSUM_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_parse_failure(), JSON_SUCCESS, parse(), pfree(), and token.

Referenced by json_parse_manifest().

◆ json_parse_manifest()

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

Definition at line 119 of file parse_manifest.c.

121 {
122  JsonLexContext *lex;
123  JsonParseErrorType json_error;
124  JsonSemAction sem;
126 
127  /* Set up our private parsing context. */
128  parse.context = context;
130  parse.saw_version_field = false;
131 
132  /* Create a JSON lexing context. */
133  lex = makeJsonLexContextCstringLen(NULL, buffer, size, PG_UTF8, true);
134 
135  /* Set up semantic actions. */
136  sem.semstate = &parse;
142  sem.object_field_end = NULL;
143  sem.array_element_start = NULL;
144  sem.array_element_end = NULL;
146 
147  /* Run the actual JSON parser. */
148  json_error = pg_parse_json(lex, &sem);
149  if (json_error != JSON_SUCCESS)
150  json_manifest_parse_failure(context, "parsing failed");
151  if (parse.state != JM_EXPECT_EOF)
152  json_manifest_parse_failure(context, "manifest ended unexpectedly");
153 
154  /* Verify the manifest checksum. */
155  verify_manifest_checksum(&parse, buffer, size);
156 
157  freeJsonLexContext(lex);
158 }
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:205
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:153
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:183
JsonParseErrorType
Definition: jsonapi.h:37
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, char *buffer, size_t size)
@ PG_UTF8
Definition: pg_wchar.h:235
json_struct_action array_end
Definition: jsonapi.h:123
json_struct_action object_start
Definition: jsonapi.h:120
json_ofield_action object_field_start
Definition: jsonapi.h:124
json_aelem_action array_element_start
Definition: jsonapi.h:126
json_scalar_action scalar
Definition: jsonapi.h:128
void * semstate
Definition: jsonapi.h:119
json_aelem_action array_element_end
Definition: jsonapi.h:127
json_struct_action array_start
Definition: jsonapi.h:122
json_struct_action object_end
Definition: jsonapi.h:121
json_ofield_action object_field_end
Definition: jsonapi.h:125

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, freeJsonLexContext(), JM_EXPECT_EOF, 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_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, JsonSemAction::semstate, and verify_manifest_checksum().

Referenced by parse_manifest_file().

◆ parse_xlogrecptr()

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

Definition at line 753 of file parse_manifest.c.

754 {
755  uint32 hi;
756  uint32 lo;
757 
758  if (sscanf(input, "%X/%X", &hi, &lo) != 2)
759  return false;
760  *result = ((uint64) hi) << 32 | lo;
761  return true;
762 }
unsigned int uint32
Definition: c.h:495

References input.

Referenced by json_manifest_finalize_wal_range().

◆ verify_manifest_checksum()

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

Definition at line 633 of file parse_manifest.c.

635 {
636  JsonManifestParseContext *context = parse->context;
637  size_t i;
638  size_t number_of_newlines = 0;
639  size_t ultimate_newline = 0;
640  size_t penultimate_newline = 0;
641  pg_cryptohash_ctx *manifest_ctx;
642  uint8 manifest_checksum_actual[PG_SHA256_DIGEST_LENGTH];
643  uint8 manifest_checksum_expected[PG_SHA256_DIGEST_LENGTH];
644 
645  /* Find the last two newlines in the file. */
646  for (i = 0; i < size; ++i)
647  {
648  if (buffer[i] == '\n')
649  {
650  ++number_of_newlines;
651  penultimate_newline = ultimate_newline;
652  ultimate_newline = i;
653  }
654  }
655 
656  /*
657  * Make sure that the last newline is right at the end, and that there are
658  * at least two lines total. We need this to be true in order for the
659  * following code, which computes the manifest checksum, to work properly.
660  */
661  if (number_of_newlines < 2)
663  "expected at least 2 lines");
664  if (ultimate_newline != size - 1)
666  "last line not newline-terminated");
667 
668  /* Checksum the rest. */
669  manifest_ctx = pg_cryptohash_create(PG_SHA256);
670  if (manifest_ctx == NULL)
671  context->error_cb(context, "out of memory");
672  if (pg_cryptohash_init(manifest_ctx) < 0)
673  context->error_cb(context, "could not initialize checksum of manifest");
674  if (pg_cryptohash_update(manifest_ctx, (uint8 *) buffer, penultimate_newline + 1) < 0)
675  context->error_cb(context, "could not update checksum of manifest");
676  if (pg_cryptohash_final(manifest_ctx, manifest_checksum_actual,
677  sizeof(manifest_checksum_actual)) < 0)
678  context->error_cb(context, "could not finalize checksum of manifest");
679 
680  /* Now verify it. */
681  if (parse->manifest_checksum == NULL)
682  context->error_cb(parse->context, "manifest has no checksum");
683  if (strlen(parse->manifest_checksum) != PG_SHA256_DIGEST_LENGTH * 2 ||
684  !hexdecode_string(manifest_checksum_expected, parse->manifest_checksum,
686  context->error_cb(context, "invalid manifest checksum: \"%s\"",
687  parse->manifest_checksum);
688  if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
690  context->error_cb(context, "manifest checksum mismatch");
691  pg_cryptohash_free(manifest_ctx);
692 }
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
@ PG_SHA256
Definition: cryptohash.h:24
#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, and PG_SHA256_DIGEST_LENGTH.

Referenced by json_parse_manifest().