aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-08-31 22:51:54 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-08-31 22:52:01 +0200
commitc390550249c20bd5049807d836b0107f6a2537e2 (patch)
tree03de3dfa2eaa18e877295c38bdb52c2db6757372
parentfd846cfed6fd51c09d667f129b2df99155558d26 (diff)
server: Set maximum database size
-rw-r--r--db.c61
1 files 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);
}
}