sparkey_returncode sparkey_hash_open()

in src/hashreader.c [32:96]


sparkey_returncode sparkey_hash_open(sparkey_hashreader **reader_ref, const char *hash_filename, const char *log_filename) {
  RETHROW(correct_endian_platform());

  sparkey_returncode returncode;

  sparkey_hashreader *reader = malloc(sizeof(sparkey_hashreader));
  if (reader == NULL) {
    return SPARKEY_INTERNAL_ERROR;
  }

  reader->open_status = 0;

  TRY(sparkey_load_hashheader(&reader->header, hash_filename), free_reader);
  TRY(sparkey_logreader_open_noalloc(&reader->log, log_filename), free_reader);
  if (reader->header.file_identifier != reader->log.header.file_identifier) {
    returncode = SPARKEY_FILE_IDENTIFIER_MISMATCH;
    goto close_reader;
  }
  if (reader->header.data_end > reader->log.header.data_end) {
    returncode = SPARKEY_HASH_HEADER_CORRUPT;
    goto close_reader;
  }
  if (reader->header.max_key_len > reader->log.header.max_key_len) {
    returncode = SPARKEY_HASH_HEADER_CORRUPT;
    goto close_reader;
  }
  if (reader->header.max_value_len > reader->log.header.max_value_len) {
    returncode = SPARKEY_HASH_HEADER_CORRUPT;
    goto close_reader;
  }

  reader->fd = open(hash_filename, O_RDONLY);
  if (reader->fd < 0) {
    int e = errno;
    returncode = sparkey_open_returncode(e);
    goto close_reader;
  }

  reader->data_len = reader->header.header_size + reader->header.hash_capacity * (reader->header.hash_size + reader->header.address_size);

  struct stat s;
  stat(hash_filename, &s);
  if (reader->data_len > (uint64_t) s.st_size) {
    returncode = SPARKEY_HASH_TOO_SMALL;
    goto close_reader;
  }

  reader->data = mmap(NULL, reader->data_len, PROT_READ, MAP_SHARED, reader->fd, 0);
  if (reader->data == MAP_FAILED) {
    returncode = SPARKEY_MMAP_FAILED;
    goto close_reader;
  }

  *reader_ref = reader;
  reader->open_status = MAGIC_VALUE_HASHREADER;
  return SPARKEY_SUCCESS;

close_reader:
  sparkey_hash_close(&reader);
  return returncode;

free_reader:
  free(reader);
  return returncode;
}