summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-01-14 18:25:52 -0500
committerJune McEnroe <june@causal.agency>2020-01-14 18:25:52 -0500
commit699a8c625cdf1f9a57bf4be326dc0c797c2d4d63 (patch)
tree590c05c0bd8dac0addf1c89974ad3dac2af37ab9
parentAdd columnsize = 0 option to FTS index (diff)
downloadlitterbox-699a8c625cdf1f9a57bf4be326dc0c797c2d4d63.tar.gz
litterbox-699a8c625cdf1f9a57bf4be326dc0c797c2d4d63.zip
Add -b flag for live backup
-rw-r--r--database.h10
-rw-r--r--litterbox.111
-rw-r--r--litterbox.c8
3 files changed, 27 insertions, 2 deletions
diff --git a/database.h b/database.h
index 83be73c..d9b2718 100644
--- a/database.h
+++ b/database.h
@@ -335,3 +335,13 @@ static inline void dbMigrate(void) {
 		dbExec(MigrationSQL[version]);
 	}
 }
+
+static inline void dbBackup(const char *path) {
+	if (sqlite3_libversion_number() < 3027000) {
+		errx(EX_CONFIG, "SQLite version 3.27.0 or newer required");
+	}
+	sqlite3_stmt *stmt = dbPrepare(SQL(VACUUM INTO :path;));
+	dbBindText(stmt, ":path", path);
+	dbRun(stmt);
+	sqlite3_finalize(stmt);
+}
diff --git a/litterbox.1 b/litterbox.1
index 3a179ae..6493558 100644
--- a/litterbox.1
+++ b/litterbox.1
@@ -1,4 +1,4 @@
-.Dd January 12, 2020
+.Dd January 14, 2020
 .Dt LITTERBOX 1
 .Os
 .
@@ -26,6 +26,10 @@
 .Op Fl d Ar path
 .Fl i | m
 .
+.Nm
+.Op Fl d Ar path
+.Fl b Ar path
+.
 .Sh DESCRIPTION
 The
 .Nm
@@ -90,6 +94,11 @@ The searchable columns are
 For search query syntax, see
 .Aq Lk https://www.sqlite.org/fts5.html#full_text_query_syntax .
 .
+.It Fl b Ar path
+Perform a live database backup to
+.Ar path .
+This operation requires SQLite version 3.27.0 or newer.
+.
 .It Fl c Ar path , Cm cert = Ar path
 Load the TLS client certificate from
 .Ar path
diff --git a/litterbox.c b/litterbox.c
index a928dd0..dbce7b0 100644
--- a/litterbox.c
+++ b/litterbox.c
@@ -645,6 +645,7 @@ int main(int argc, char *argv[]) {
 	char *path = NULL;
 	bool init = false;
 	bool migrate = false;
+	const char *backup = NULL;
 
 	bool insecure = false;
 	const char *cert = NULL;
@@ -657,7 +658,7 @@ int main(int argc, char *argv[]) {
 	const char *user = NULL;
 	const char *pass = NULL;
 
-	const char *Opts = "!N:Qc:d:h:ij:k:l:mn:p:qu:vw:";
+	const char *Opts = "!N:Qb:c:d:h:ij:k:l:mn:p:qu:vw:";
 	const struct option LongOpts[] = {
 		{ "insecure", no_argument, NULL, '!' },
 		{ "network", required_argument, NULL, 'N' },
@@ -683,6 +684,7 @@ int main(int argc, char *argv[]) {
 			break; case '!': insecure = true;
 			break; case 'N': defaultNetwork = optarg;
 			break; case 'Q': searchQuery = Public;
+			break; case 'b': backup = optarg;
 			break; case 'c': cert = optarg;
 			break; case 'd': path = optarg;
 			break; case 'h': host = optarg;
@@ -715,6 +717,10 @@ int main(int argc, char *argv[]) {
 		dbMigrate();
 		return EX_OK;
 	}
+	if (backup) {
+		dbBackup(backup);
+		return EX_OK;
+	}
 	if (dbVersion() != DatabaseVersion) {
 		errx(EX_CONFIG, "database out of date; migrate with -m");
 	}