From 8044540c426b0dbe4919a74ea9434663ab5a13b2 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 23 Mar 2024 14:26:04 +0100 Subject: [PATCH] feat: unprivileged read-only open of SQLite DB If the state SQLite database is configured to use a write-ahead-log, it creates WAL files in the state directory. When the state SQLite database is closed by the `nix-daemon` after builds, those files are removed. When an unprivileged user would like to open _in read only_ that database, they cannot do so because they would need to create those WAL files and they do not have the permission to do so. For this, SQLite offers a "persistent WAL" feature [1] to leave the WAL files around, even after closing the database. This CL enable the persistent WAL mode. Fixes: https://github.com/NixOS/nix/issues/10300 [1]: https://www.sqlite.org/wal.html Change-Id: Id8ae534d7d2290457af28782e5215222ae051fe5 Signed-off-by: Raito Bezarius --- src/libstore/local-store.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 29081244f..db3934d5e 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -548,6 +548,15 @@ void LocalStore::openDB(State & state, bool create) sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK) SQLiteError::throw_(db, "setting journal mode"); + if (mode == "wal" ) { + /* persist the WAL files when the DB connection is closed. + * This allows for read-only connections without any write permissions + * on the state directory to succeed on a closed database. */ + int enable = 1; + if (sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, &enable) != SQLITE_OK) + SQLiteError::throw_(db, "setting persistent WAL mode"); + } + /* Increase the auto-checkpoint interval to 40000 pages. This seems enough to ensure that instantiating the NixOS system derivation is done in a single fsync(). */