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 void json_manifest_object_start (void *state)
 
static void json_manifest_object_end (void *state)
 
static void json_manifest_array_start (void *state)
 
static void json_manifest_array_end (void *state)
 
static void json_manifest_object_field_start (void *state, char *fname, bool isnull)
 
static void 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.

◆ 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.

◆ JsonManifestWALRangeField

Enumerator
JMWRF_TIMELINE 
JMWRF_START_LSN 
JMWRF_END_LSN 

Definition at line 56 of file parse_manifest.c.

Function Documentation

◆ hexdecode_char()

static int hexdecode_char ( char  c)
static

Definition at line 692 of file parse_manifest.c.

Referenced by hexdecode_string().

693 {
694  if (c >= '0' && c <= '9')
695  return c - '0';
696  if (c >= 'a' && c <= 'f')
697  return c - 'a' + 10;
698  if (c >= 'A' && c <= 'F')
699  return c - 'A' + 10;
700 
701  return -1;
702 }
char * c

◆ hexdecode_string()

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

Definition at line 710 of file parse_manifest.c.

References hexdecode_char(), and i.

Referenced by json_manifest_finalize_file(), and verify_manifest_checksum().

711 {
712  int i;
713 
714  for (i = 0; i < nbytes; ++i)
715  {
716  int n1 = hexdecode_char(input[i * 2]);
717  int n2 = hexdecode_char(input[i * 2 + 1]);
718 
719  if (n1 < 0 || n2 < 0)
720  return false;
721  result[i] = n1 * 16 + n2;
722  }
723 
724  return true;
725 }
static int hexdecode_char(char c)
int i

◆ json_manifest_array_end()

static void json_manifest_array_end ( void *  state)
static

Definition at line 262 of file parse_manifest.c.

References JsonManifestParseState::context, JM_EXPECT_FILES_NEXT, JM_EXPECT_TOPLEVEL_FIELD, JM_EXPECT_WAL_RANGES_NEXT, json_manifest_parse_failure(), parse(), and JsonManifestParseState::state.

Referenced by json_parse_manifest().

263 {
265 
266  switch (parse->state)
267  {
271  break;
272  default:
274  "unexpected array end");
275  break;
276  }
277 }
JsonManifestParseContext * context
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
Definition: regguts.h:298
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_manifest_array_start()

static void json_manifest_array_start ( void *  state)
static

Definition at line 237 of file parse_manifest.c.

References JsonManifestParseState::context, JM_EXPECT_FILES_NEXT, JM_EXPECT_FILES_START, JM_EXPECT_WAL_RANGES_NEXT, JM_EXPECT_WAL_RANGES_START, json_manifest_parse_failure(), parse(), and JsonManifestParseState::state.

Referenced by json_parse_manifest().

238 {
240 
241  switch (parse->state)
242  {
244  parse->state = JM_EXPECT_FILES_NEXT;
245  break;
248  break;
249  default:
251  "unexpected array start");
252  break;
253  }
254 }
JsonManifestParseContext * context
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
Definition: regguts.h:298
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_manifest_finalize_file()

static void json_manifest_finalize_file ( JsonManifestParseState parse)
static

Definition at line 460 of file parse_manifest.c.

References JsonManifestParseState::algorithm, JsonManifestParseState::checksum, CHECKSUM_TYPE_NONE, JsonManifestParseState::context, JsonManifestParseState::encoded_pathname, JsonManifestParseContext::error_cb, hexdecode_string(), json_manifest_parse_failure(), palloc(), JsonManifestParseState::pathname, JsonManifestParseContext::perfile_cb, pfree(), pg_checksum_parse_type(), and JsonManifestParseState::size.

Referenced by json_manifest_object_end().

461 {
462  JsonManifestParseContext *context = parse->context;
463  size_t size;
464  char *ep;
465  int checksum_string_length;
466  pg_checksum_type checksum_type;
467  int checksum_length;
468  uint8 *checksum_payload;
469 
470  /* Pathname and size are required. */
471  if (parse->pathname == NULL && parse->encoded_pathname == NULL)
472  json_manifest_parse_failure(parse->context, "missing path name");
473  if (parse->pathname != NULL && parse->encoded_pathname != NULL)
475  "both path name and encoded path name");
476  if (parse->size == NULL)
477  json_manifest_parse_failure(parse->context, "missing size");
478  if (parse->algorithm == NULL && parse->checksum != NULL)
480  "checksum without algorithm");
481 
482  /* Decode encoded pathname, if that's what we have. */
483  if (parse->encoded_pathname != NULL)
484  {
485  int encoded_length = strlen(parse->encoded_pathname);
486  int raw_length = encoded_length / 2;
487 
488  parse->pathname = palloc(raw_length + 1);
489  if (encoded_length % 2 != 0 ||
490  !hexdecode_string((uint8 *) parse->pathname,
491  parse->encoded_pathname,
492  raw_length))
494  "could not decode file name");
495  parse->pathname[raw_length] = '\0';
496  pfree(parse->encoded_pathname);
497  parse->encoded_pathname = NULL;
498  }
499 
500  /* Parse size. */
501  size = strtoul(parse->size, &ep, 10);
502  if (*ep)
504  "file size is not an integer");
505 
506  /* Parse the checksum algorithm, if it's present. */
507  if (parse->algorithm == NULL)
508  checksum_type = CHECKSUM_TYPE_NONE;
509  else if (!pg_checksum_parse_type(parse->algorithm, &checksum_type))
510  context->error_cb(context, "unrecognized checksum algorithm: \"%s\"",
511  parse->algorithm);
512 
513  /* Parse the checksum payload, if it's present. */
514  checksum_string_length = parse->checksum == NULL ? 0
515  : strlen(parse->checksum);
516  if (checksum_string_length == 0)
517  {
518  checksum_length = 0;
519  checksum_payload = NULL;
520  }
521  else
522  {
523  checksum_length = checksum_string_length / 2;
524  checksum_payload = palloc(checksum_length);
525  if (checksum_string_length % 2 != 0 ||
526  !hexdecode_string(checksum_payload, parse->checksum,
527  checksum_length))
528  context->error_cb(context,
529  "invalid checksum for file \"%s\": \"%s\"",
530  parse->pathname, parse->checksum);
531  }
532 
533  /* Invoke the callback with the details we've gathered. */
534  context->perfile_cb(context, parse->pathname, size,
535  checksum_type, checksum_length, checksum_payload);
536 
537  /* Free memory we no longer need. */
538  if (parse->size != NULL)
539  {
540  pfree(parse->size);
541  parse->size = NULL;
542  }
543  if (parse->algorithm != NULL)
544  {
545  pfree(parse->algorithm);
546  parse->algorithm = NULL;
547  }
548  if (parse->checksum != NULL)
549  {
550  pfree(parse->checksum);
551  parse->checksum = NULL;
552  }
553 }
json_manifest_error_callback error_cb
JsonManifestParseContext * context
unsigned char uint8
Definition: c.h:427
bool pg_checksum_parse_type(char *name, pg_checksum_type *type)
void pfree(void *pointer)
Definition: mcxt.c:1057
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
pg_checksum_type
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
void * palloc(Size size)
Definition: mcxt.c:950
json_manifest_perfile_callback perfile_cb

◆ json_manifest_finalize_wal_range()

static void json_manifest_finalize_wal_range ( JsonManifestParseState parse)
static

Definition at line 562 of file parse_manifest.c.

References JsonManifestParseState::context, JsonManifestParseState::end_lsn, json_manifest_parse_failure(), parse_xlogrecptr(), JsonManifestParseContext::perwalrange_cb, pfree(), JsonManifestParseState::start_lsn, and JsonManifestParseState::timeline.

Referenced by json_manifest_object_end().

563 {
564  JsonManifestParseContext *context = parse->context;
565  TimeLineID tli;
566  XLogRecPtr start_lsn,
567  end_lsn;
568  char *ep;
569 
570  /* Make sure all fields are present. */
571  if (parse->timeline == NULL)
572  json_manifest_parse_failure(parse->context, "missing timeline");
573  if (parse->start_lsn == NULL)
574  json_manifest_parse_failure(parse->context, "missing start LSN");
575  if (parse->end_lsn == NULL)
576  json_manifest_parse_failure(parse->context, "missing end LSN");
577 
578  /* Parse timeline. */
579  tli = strtoul(parse->timeline, &ep, 10);
580  if (*ep)
582  "timeline is not an integer");
583  if (!parse_xlogrecptr(&start_lsn, parse->start_lsn))
585  "could not parse start LSN");
586  if (!parse_xlogrecptr(&end_lsn, parse->end_lsn))
588  "could not parse end LSN");
589 
590  /* Invoke the callback with the details we've gathered. */
591  context->perwalrange_cb(context, tli, start_lsn, end_lsn);
592 
593  /* Free memory we no longer need. */
594  if (parse->timeline != NULL)
595  {
596  pfree(parse->timeline);
597  parse->timeline = NULL;
598  }
599  if (parse->start_lsn != NULL)
600  {
601  pfree(parse->start_lsn);
602  parse->start_lsn = NULL;
603  }
604  if (parse->end_lsn != NULL)
605  {
606  pfree(parse->end_lsn);
607  parse->end_lsn = NULL;
608  }
609 }
uint32 TimeLineID
Definition: xlogdefs.h:52
JsonManifestParseContext * context
void pfree(void *pointer)
Definition: mcxt.c:1057
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
static bool parse_xlogrecptr(XLogRecPtr *result, char *input)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
json_manifest_perwalrange_callback perwalrange_cb

◆ json_manifest_object_end()

static void json_manifest_object_end ( void *  state)
static

Definition at line 205 of file parse_manifest.c.

References JsonManifestParseState::context, 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(), parse(), and JsonManifestParseState::state.

Referenced by json_parse_manifest().

206 {
208 
209  switch (parse->state)
210  {
212  parse->state = JM_EXPECT_EOF;
213  break;
216  parse->state = JM_EXPECT_FILES_NEXT;
217  break;
221  break;
222  default:
224  "unexpected object end");
225  break;
226  }
227 }
JsonManifestParseContext * context
static void json_manifest_finalize_wal_range(JsonManifestParseState *parse)
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
Definition: regguts.h:298
static void json_manifest_finalize_file(JsonManifestParseState *parse)
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_manifest_object_field_start()

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

Definition at line 283 of file parse_manifest.c.

References JsonManifestParseState::context, JsonManifestParseState::file_field, 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(), parse(), JsonManifestParseState::saw_version_field, JsonManifestParseState::state, and JsonManifestParseState::wal_range_field.

Referenced by json_parse_manifest().

284 {
286 
287  switch (parse->state)
288  {
290 
291  /*
292  * Inside toplevel object. The version indicator should always be
293  * the first field.
294  */
295  if (!parse->saw_version_field)
296  {
297  if (strcmp(fname, "PostgreSQL-Backup-Manifest-Version") != 0)
299  "expected version indicator");
301  parse->saw_version_field = true;
302  break;
303  }
304 
305  /* Is this the list of files? */
306  if (strcmp(fname, "Files") == 0)
307  {
308  parse->state = JM_EXPECT_FILES_START;
309  break;
310  }
311 
312  /* Is this the list of WAL ranges? */
313  if (strcmp(fname, "WAL-Ranges") == 0)
314  {
316  break;
317  }
318 
319  /* Is this the manifest checksum? */
320  if (strcmp(fname, "Manifest-Checksum") == 0)
321  {
323  break;
324  }
325 
326  /* It's not a field we recognize. */
328  "unrecognized top-level field");
329  break;
330 
332  /* Inside object for one file; which key have we got? */
333  if (strcmp(fname, "Path") == 0)
334  parse->file_field = JMFF_PATH;
335  else if (strcmp(fname, "Encoded-Path") == 0)
336  parse->file_field = JMFF_ENCODED_PATH;
337  else if (strcmp(fname, "Size") == 0)
338  parse->file_field = JMFF_SIZE;
339  else if (strcmp(fname, "Last-Modified") == 0)
341  else if (strcmp(fname, "Checksum-Algorithm") == 0)
343  else if (strcmp(fname, "Checksum") == 0)
344  parse->file_field = JMFF_CHECKSUM;
345  else
347  "unexpected file field");
349  break;
350 
352  /* Inside object for one file; which key have we got? */
353  if (strcmp(fname, "Timeline") == 0)
355  else if (strcmp(fname, "Start-LSN") == 0)
357  else if (strcmp(fname, "End-LSN") == 0)
359  else
361  "unexpected WAL range field");
363  break;
364 
365  default:
367  "unexpected object field");
368  break;
369  }
370 }
JsonManifestParseContext * context
JsonManifestFileField file_field
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
JsonManifestWALRangeField wal_range_field
Definition: regguts.h:298
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_manifest_object_start()

static void json_manifest_object_start ( void *  state)
static

Definition at line 166 of file parse_manifest.c.

References JsonManifestParseState::algorithm, JsonManifestParseState::checksum, JsonManifestParseState::context, JsonManifestParseState::encoded_pathname, JsonManifestParseState::end_lsn, 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(), parse(), JsonManifestParseState::pathname, JsonManifestParseState::size, JsonManifestParseState::start_lsn, JsonManifestParseState::state, and JsonManifestParseState::timeline.

Referenced by json_parse_manifest().

167 {
169 
170  switch (parse->state)
171  {
174  break;
177  parse->pathname = NULL;
178  parse->encoded_pathname = NULL;
179  parse->size = NULL;
180  parse->algorithm = NULL;
181  parse->checksum = NULL;
182  break;
185  parse->timeline = NULL;
186  parse->start_lsn = NULL;
187  parse->end_lsn = NULL;
188  break;
189  default:
191  "unexpected object start");
192  break;
193  }
194 }
JsonManifestParseContext * context
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
Definition: regguts.h:298
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_manifest_parse_failure()

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

◆ json_manifest_scalar()

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

Definition at line 388 of file parse_manifest.c.

References JsonManifestParseState::algorithm, JsonManifestParseState::checksum, JsonManifestParseState::context, JsonManifestParseState::encoded_pathname, JsonManifestParseState::end_lsn, JsonManifestParseState::file_field, 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(), JsonManifestParseState::manifest_checksum, parse(), JsonManifestParseState::pathname, pfree(), JsonManifestParseState::size, JsonManifestParseState::start_lsn, JsonManifestParseState::state, JsonManifestParseState::timeline, and JsonManifestParseState::wal_range_field.

Referenced by json_parse_manifest().

389 {
391 
392  switch (parse->state)
393  {
395  if (strcmp(token, "1") != 0)
397  "unexpected manifest version");
399  break;
400 
402  switch (parse->file_field)
403  {
404  case JMFF_PATH:
405  parse->pathname = token;
406  break;
407  case JMFF_ENCODED_PATH:
408  parse->encoded_pathname = token;
409  break;
410  case JMFF_SIZE:
411  parse->size = token;
412  break;
413  case JMFF_LAST_MODIFIED:
414  pfree(token); /* unused */
415  break;
417  parse->algorithm = token;
418  break;
419  case JMFF_CHECKSUM:
420  parse->checksum = token;
421  break;
422  }
424  break;
425 
427  switch (parse->wal_range_field)
428  {
429  case JMWRF_TIMELINE:
430  parse->timeline = token;
431  break;
432  case JMWRF_START_LSN:
433  parse->start_lsn = token;
434  break;
435  case JMWRF_END_LSN:
436  parse->end_lsn = token;
437  break;
438  }
440  break;
441 
443  parse->state = JM_EXPECT_TOPLEVEL_END;
444  parse->manifest_checksum = token;
445  break;
446 
447  default:
448  json_manifest_parse_failure(parse->context, "unexpected scalar");
449  break;
450  }
451 }
JsonManifestParseContext * context
JsonManifestFileField file_field
void pfree(void *pointer)
Definition: mcxt.c:1057
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
JsonManifestWALRangeField wal_range_field
Definition: regguts.h:298
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ json_parse_manifest()

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

Definition at line 119 of file parse_manifest.c.

References JsonSemAction::array_element_end, JsonSemAction::array_element_start, JsonSemAction::array_end, JsonSemAction::array_start, JsonManifestParseState::context, 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, JsonManifestParseState::saw_version_field, JsonSemAction::scalar, JsonSemAction::semstate, JsonManifestParseState::state, and verify_manifest_checksum().

Referenced by parse_manifest_file().

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(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, json_errdetail(json_error, lex));
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 }
json_struct_action array_end
Definition: jsonapi.h:110
static void json_manifest_scalar(void *state, char *token, JsonTokenType tokentype)
json_struct_action object_end
Definition: jsonapi.h:108
JsonManifestParseContext * context
json_struct_action object_start
Definition: jsonapi.h:107
char * json_errdetail(JsonParseErrorType error, JsonLexContext *lex)
Definition: jsonapi.c:1056
json_scalar_action scalar
Definition: jsonapi.h:115
static void verify_manifest_checksum(JsonManifestParseState *parse, char *buffer, size_t size)
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, int encoding, bool need_escapes)
Definition: jsonapi.c:155
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
JsonManifestSemanticState state
JsonParseErrorType pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: jsonapi.c:179
json_ofield_action object_field_end
Definition: jsonapi.h:112
static void json_manifest_object_start(void *state)
static void json_manifest_array_start(void *state)
JsonParseErrorType
Definition: jsonapi.h:36
json_aelem_action array_element_start
Definition: jsonapi.h:113
json_struct_action array_start
Definition: jsonapi.h:109
static void json_manifest_object_field_start(void *state, char *fname, bool isnull)
json_ofield_action object_field_start
Definition: jsonapi.h:111
static void json_manifest_object_end(void *state)
void * semstate
Definition: jsonapi.h:106
static void json_manifest_array_end(void *state)
json_aelem_action array_element_end
Definition: jsonapi.h:114
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ parse_xlogrecptr()

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

Definition at line 731 of file parse_manifest.c.

Referenced by json_manifest_finalize_wal_range().

732 {
733  uint32 hi;
734  uint32 lo;
735 
736  if (sscanf(input, "%X/%X", &hi, &lo) != 2)
737  return false;
738  *result = ((uint64) hi) << 32 | lo;
739  return true;
740 }
unsigned int uint32
Definition: c.h:429

◆ verify_manifest_checksum()

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

Definition at line 619 of file parse_manifest.c.

References JsonManifestParseState::context, JsonManifestParseContext::error_cb, hexdecode_string(), i, json_manifest_parse_failure(), JsonManifestParseState::manifest_checksum, PG_SHA256_DIGEST_LENGTH, pg_sha256_final(), pg_sha256_init(), and pg_sha256_update().

Referenced by json_parse_manifest().

621 {
622  JsonManifestParseContext *context = parse->context;
623  size_t i;
624  size_t number_of_newlines = 0;
625  size_t ultimate_newline = 0;
626  size_t penultimate_newline = 0;
627  pg_sha256_ctx manifest_ctx;
628  uint8 manifest_checksum_actual[PG_SHA256_DIGEST_LENGTH];
629  uint8 manifest_checksum_expected[PG_SHA256_DIGEST_LENGTH];
630 
631  /* Find the last two newlines in the file. */
632  for (i = 0; i < size; ++i)
633  {
634  if (buffer[i] == '\n')
635  {
636  ++number_of_newlines;
637  penultimate_newline = ultimate_newline;
638  ultimate_newline = i;
639  }
640  }
641 
642  /*
643  * Make sure that the last newline is right at the end, and that there are
644  * at least two lines total. We need this to be true in order for the
645  * following code, which computes the manifest checksum, to work properly.
646  */
647  if (number_of_newlines < 2)
649  "expected at least 2 lines");
650  if (ultimate_newline != size - 1)
652  "last line not newline-terminated");
653 
654  /* Checksum the rest. */
655  pg_sha256_init(&manifest_ctx);
656  pg_sha256_update(&manifest_ctx, (uint8 *) buffer, penultimate_newline + 1);
657  pg_sha256_final(&manifest_ctx, manifest_checksum_actual);
658 
659  /* Now verify it. */
660  if (parse->manifest_checksum == NULL)
661  context->error_cb(parse->context, "manifest has no checksum");
662  if (strlen(parse->manifest_checksum) != PG_SHA256_DIGEST_LENGTH * 2 ||
663  !hexdecode_string(manifest_checksum_expected, parse->manifest_checksum,
665  context->error_cb(context, "invalid manifest checksum: \"%s\"",
666  parse->manifest_checksum);
667  if (memcmp(manifest_checksum_actual, manifest_checksum_expected,
669  context->error_cb(context, "manifest checksum mismatch");
670 }
json_manifest_error_callback error_cb
JsonManifestParseContext * context
#define PG_SHA256_DIGEST_LENGTH
Definition: sha2.h:62
unsigned char uint8
Definition: c.h:427
void pg_sha256_init(pg_sha256_ctx *context)
Definition: sha2.c:268
static void json_manifest_parse_failure(JsonManifestParseContext *context, char *msg)
void pg_sha256_update(pg_sha256_ctx *context, const uint8 *data, size_t len)
Definition: sha2.c:465
static bool hexdecode_string(uint8 *result, char *input, int nbytes)
void pg_sha256_final(pg_sha256_ctx *context, uint8 *digest)
Definition: sha2.c:566
int i