From c390550249c20bd5049807d836b0107f6a2537e2 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Mon, 31 Aug 2020 22:51:54 +0200 Subject: server: Set maximum database size --- db.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/db.c b/db.c index f5f2572..f4c28f3 100644 --- a/db.c +++ b/db.c @@ -15,6 +15,8 @@ #define PASSHASH_OPSLIMIT 3 #define PASSHASH_MEMLIMIT crypto_pwhash_MEMLIMIT_INTERACTIVE +#define MAX_DATABASE_SIZE_BYTES ((i64)2 * 1024 * 1024 * 1024) + sqlite3 *database=NULL; @@ -41,40 +43,69 @@ static struct hashed_password hash_password(const char *pass) { return result; } +// Returns whether successful +bool select_simple_int(const char *query, i64 *out) { + sqlite3_stmt *stmt; + int res = sqlite3_prepare_v2(database, query, -1, &stmt, NULL); + bool retval = false; + if (res == SQLITE_OK) { + if (sqlite3_step(stmt) == SQLITE_ROW) { + *out = sqlite3_column_int64(stmt, 0); + retval = true; + } + SQLITE(finalize, stmt); + } + return retval; +} + void db_init(void){ - SQLITE(config,SQLITE_CONFIG_SERIALIZED); + SQLITE(config, SQLITE_CONFIG_SERIALIZED); SQLITE(initialize); - SQLITE(open_v2,"db.db",&database,SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE,NULL); - SQLITE(busy_timeout,database,500); + SQLITE(open_v2, "db.db", &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + SQLITE(busy_timeout, database, 500); - SQLITE(exec,database,"pragma foreign_keys = 1",NULL,NULL,NULL); + SQLITE(exec, database, "pragma foreign_keys = 1", NULL, NULL, NULL); - sqlite3_stmt *stmt; - int res = sqlite3_prepare_v2(database, "select version from Meta", -1, &stmt, NULL); - if (res == SQLITE_OK && sqlite3_step(stmt) == SQLITE_ROW) { - i64 version = sqlite3_column_int64(stmt, 0); - SQLITE(finalize, stmt); + i64 page_size, page_count; + if (select_simple_int("pragma page_size", &page_size) && + select_simple_int("pragma page_count", &page_count)) { + i64 max_num_pages = MAX_DATABASE_SIZE_BYTES / page_size; + if (page_count >= max_num_pages - 1) { + fprintf(stderr, "WARNING: Database already at maximum size!\n"); + max_num_pages = page_count + 2; + } + + // SQLite doesn't allow preparing a pragma, so let's splice the integer in directly + char *str = NULL; + asprintf(&str, "pragma max_page_count = %" PRIi64, max_num_pages); + SQLITE(exec, database, str, NULL, NULL, NULL); + free(str); + } else { + die("Failed to query database page statistics: %s", sqlite3_errmsg(database)); + } + i64 version; + if (select_simple_int("select version from Meta", &version)) { if (version != DATABASE_VERSION) { die("Database version incompatible: database %" PRIi64 ", application %d", version, DATABASE_VERSION); } } else { - if (res == SQLITE_OK) SQLITE(finalize, stmt); - - char *str=malloc(schema_sql_len+1,char); - memcpy(str,schema_sql,schema_sql_len); - str[schema_sql_len]='\0'; - SQLITE(exec,database,str,NULL,NULL,NULL); + char *str = malloc(schema_sql_len+1, char); + memcpy(str, schema_sql, schema_sql_len); + str[schema_sql_len] = '\0'; + SQLITE(exec, database, str, NULL, NULL, NULL); free(str); + sqlite3_stmt *stmt; SQLITE(prepare_v2, database, "insert into Meta (version) values (?)", -1, &stmt, NULL); SQLITE(bind_int64, stmt, 1, DATABASE_VERSION); if (sqlite3_step(stmt) != SQLITE_DONE) { die("Could not set database version: %s", sqlite3_errmsg(database)); } + SQLITE(finalize, stmt); } } -- cgit v1.2.3-70-g09d2