<commit_before>#include <meagerdb/meagerdb.h>
#include <meagerdb/app.h>
#include "ciphers.h"
#include "basic_packing.h"
#include "util.h"
#include <string.h>
#include <sys/unistd.h>
#include <stddef.h>
#include <fcntl.h>


#define JOURNAL0  0
#define JOURNAL1  1
#define FIRST_PAGE 2

#define ERROR_AND_CLOSE_IF(cond,err) if ((cond)) { mdb_close (db); return (err); }
#define CLOSE_AND_ERROR(err) {mdb_close (db); return (err); }


/* mdb_create and mdb_open depend on these structs, so update those if the data structures change. */
typedef struct __attribute__ ((__packed__)) {
	uint8_t magic[8];
	uint8_t version[2];
	uint8_t page_size[4];
	uint8_t db_id[32];
	uint8_t ciphersuite[32];
	uint8_t hash[32];
} RAW_HEADER;

_Static_assert (sizeof (RAW_HEADER) == (8+2+4+32+32+32), "Struct packing failed");

typedef struct __attribute__ ((__packed__)) {
	uint8_t salt[64];
	uint8_t kdf[32];
	uint8_t kdf_params[32];
	uint8_t keys[128];
	uint8_t mac[32];
	uint8_t hash[32];
} RAW_PARAMS;

_Static_assert (sizeof (RAW_PARAMS) == (64+32+32+128+32+32), "Struct packing failed");


/* We consume one buffer of this size.
 */

_Static_assert (MDB_DEFAULT_PAGE_SIZE <= MDB_MAX_PAGE_SIZE, "MDB_DEFAULT_PAGE_SIZE must be smaller than MDB_MAX_PAGE_SIZE.");

/* These are needed for mdb_create and mdb_open */
_Static_assert (MDB_TMP_SIZE >= sizeof (RAW_HEADER), "MDB_MAX_PAGE_SIZE is too small.");
_Static_assert (MDB_TMP_SIZE >= (sizeof (RAW_PARAMS)+32), "MDB_MAX_PAGE_SIZE is too small.");

/* Necessary to encrypt the key material. */
_Static_assert ((128 % MDBC_ENCRYPTION_BLOCK_SIZE) == 0, "128 must be a multiple of MDBC_ENCRYPTION_BLOCK_SIZE.");


/* Private Prototypes */
static int cleanup_journal (MDB *db);
static int set_journal (MDB *db, int journal, uint32_t page_start, uint32_t page_count);
static int write_page (MDB *db, uint32_t page);



int mdb_create (MDB *db, char const *path, uint8_t const *password, size_t password_len, uint64_t iteration_count)
{
	int err;
	const uint32_t page_size = MDB_DEFAULT_PAGE_SIZE;
	uint8_t header_hash[32];
	uint8_t derived_keys[128];
	const uint32_t header_len = roundup_uint32 (sizeof (RAW_HEADER), page_size);
	const uint32_t params_len = roundup_uint32 (sizeof (RAW_PARAMS), page_size);

	if (strlen (MDBC_CIPHERSUITE) > 32 || strlen (MDBC_KDF) > 32)
		mdba_fatal_error ();

	if (db->fd)
		return MDBE_ALREADY_OPEN;

	memset (db, 0, sizeof (MDB));

	/* Open database file */
	if ((db->fd = mdba_open (path, O_RDWR | O_CREAT)) == -1)
	{
		db->fd = 0;
		return MDBE_OPEN;
	}

	db->page_size = page_size;
	db->page_offset = header_len + 2 * params_len;
	db->real_page_size = (db->page_size - 32) / MDBC_ENCRYPTION_BLOCK_SIZE;
	db->real_page_size *= MDBC_ENCRYPTION_BLOCK_SIZE;

	/* Generate Encryption Keys */
	mdba_read_urandom (db->keys, 128);

	/* Database Header */
	RAW_HEADER *header = (RAW_HEADER *)(db->tmp);

	memset (header, 0, sizeof (RAW_HEADER));
	memmove (header->magic, "MEAGERDB", 8);                                       /* Magic */
	pack_uint16_little (header->version, 0x0100);                                 /* Version */
	pack_uint32_little (header->page_size, db->page_size);                        /* Page Size */
	mdba_read_urandom (header->db_id, 32);                                        /* Unique ID */
	memmove (header->ciphersuite, MDBC_CIPHERSUITE, strlen (MDBC_CIPHERSUITE));   /* Ciphersuite */
	mdbc_hash (header_hash, header, sizeof (RAW_HEADER)-32);
<commit_msg>mdb_create will no longer overwrite existing files.<commit_after>#include <meagerdb/meagerdb.h>
#include <meagerdb/app.h>
#include "ciphers.h"
#include "basic_packing.h"
#include "util.h"
#include <string.h>
#include <sys/unistd.h>
#include <stddef.h>
#include <fcntl.h>


#define JOURNAL0  0
#define JOURNAL1  1
#define FIRST_PAGE 2

#define ERROR_AND_CLOSE_IF(cond,err) if ((cond)) { mdb_close (db); return (err); }
#define CLOSE_AND_ERROR(err) {mdb_close (db); return (err); }


/* mdb_create and mdb_open depend on these structs, so update those if the data structures change. */
typedef struct __attribute__ ((__packed__)) {
	uint8_t magic[8];
	uint8_t version[2];
	uint8_t page_size[4];
	uint8_t db_id[32];
	uint8_t ciphersuite[32];
	uint8_t hash[32];
} RAW_HEADER;

_Static_assert (sizeof (RAW_HEADER) == (8+2+4+32+32+32), "Struct packing failed");

typedef struct __attribute__ ((__packed__)) {
	uint8_t salt[64];
	uint8_t kdf[32];
	uint8_t kdf_params[32];
	uint8_t keys[128];
	uint8_t mac[32];
	uint8_t hash[32];
} RAW_PARAMS;

_Static_assert (sizeof (RAW_PARAMS) == (64+32+32+128+32+32), "Struct packing failed");


/* We consume one buffer of this size.
 */

_Static_assert (MDB_DEFAULT_PAGE_SIZE <= MDB_MAX_PAGE_SIZE, "MDB_DEFAULT_PAGE_SIZE must be smaller than MDB_MAX_PAGE_SIZE.");

/* These are needed for mdb_create and mdb_open */
_Static_assert (MDB_TMP_SIZE >= sizeof (RAW_HEADER), "MDB_MAX_PAGE_SIZE is too small.");
_Static_assert (MDB_TMP_SIZE >= (sizeof (RAW_PARAMS)+32), "MDB_MAX_PAGE_SIZE is too small.");

/* Necessary to encrypt the key material. */
_Static_assert ((128 % MDBC_ENCRYPTION_BLOCK_SIZE) == 0, "128 must be a multiple of MDBC_ENCRYPTION_BLOCK_SIZE.");


/* Private Prototypes */
static int cleanup_journal (MDB *db);
static int set_journal (MDB *db, int journal, uint32_t page_start, uint32_t page_count);
static int write_page (MDB *db, uint32_t page);



int mdb_create (MDB *db, char const *path, uint8_t const *password, size_t password_len, uint64_t iteration_count)
{
	int err;
	const uint32_t page_size = MDB_DEFAULT_PAGE_SIZE;
	uint8_t header_hash[32];
	uint8_t derived_keys[128];
	const uint32_t header_len = roundup_uint32 (sizeof (RAW_HEADER), page_size);
	const uint32_t params_len = roundup_uint32 (sizeof (RAW_PARAMS), page_size);

	if (strlen (MDBC_CIPHERSUITE) > 32 || strlen (MDBC_KDF) > 32)
		mdba_fatal_error ();

	if (db->fd)
		return MDBE_ALREADY_OPEN;

	memset (db, 0, sizeof (MDB));

	/* Open database file */
	if ((db->fd = mdba_open (path, O_RDWR | O_CREAT | O_EXCL)) == -1)
	{
		db->fd = 0;
		return MDBE_OPEN;
	}

	db->page_size = page_size;
	db->page_offset = header_len + 2 * params_len;
	db->real_page_size = (db->page_size - 32) / MDBC_ENCRYPTION_BLOCK_SIZE;
	db->real_page_size *= MDBC_ENCRYPTION_BLOCK_SIZE;

	/* Generate Encryption Keys */
	mdba_read_urandom (db->keys, 128);

	/* Database Header */
	RAW_HEADER *header = (RAW_HEADER *)(db->tmp);

	memset (header, 0, sizeof (RAW_HEADER));
	memmove (header->magic, "MEAGERDB", 8);                                       /* Magic */
	pack_uint16_little (header->version, 0x0100);                                 /* Version */
	pack_uint32_little (header->page_size, db->page_size);                        /* Page Size */
	mdba_read_urandom (header->db_id, 32);                                        /* Unique ID */
	memmove (header->ciphersuite, MDBC_CIPHERSUITE, strlen (MDBC_CIPHERSUITE));   /* Ciphersuite */
	mdbc_hash (header_hash, header, sizeof (RAW_HEADER)-32);

{'fraction_non_alphanumeric': 0.12912523418359995, 'fraction_numerical': 0.035740020175817844, 'mean_word_length': 4.281582952815829, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '567964', 'n_tokens_mistral': 2854, 'n_tokens_neox': 2624, 'n_words': 633}