From 817b02299d690b48a45652c144e54c8269187389 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Tue, 26 Mar 2024 16:40:42 +0200
Subject: [PATCH] db: create uvol database symlink to a configurable mountpoint

This allows apk to create a db-uvol symlink on any write operation
if uvol is active, and the database does not exist yet. This allows
relocation of the uvol-db to an alternative directory, but still
support generic apk builds to find the uvol database using the
symlink.
---
 meson_options.txt |  1 +
 src/database.c    | 22 ++++++++++++++++++++++
 src/meson.build   |  5 +++++
 3 files changed, 28 insertions(+)

diff --git a/meson_options.txt b/meson_options.txt
index 2b82f350..693f46ec 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -5,4 +5,5 @@ option('help', description: 'Build help into apk binaries, needs lua', type: 'fe
 option('lua', description: 'Build luaapk (lua bindings)', type: 'feature', value: 'auto')
 option('lua_version', description: 'Lua version to build against', type: 'string', value: '5.3')
 option('static_apk', description: 'Also build apk.static', type: 'boolean', value: false)
+option('uvol_db_target', description: 'Default target for uvol database layer', type: 'string')
 option('zstd', description: 'Build with zstd support', type: 'boolean', value: true)
diff --git a/src/database.c b/src/database.c
index 0217617d..36060217 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1652,6 +1652,26 @@ const char *apk_db_layer_name(int layer)
 	}
 }
 
+#ifdef APK_UVOL_DB_TARGET
+static void setup_uvol_target(struct apk_database *db)
+{
+	const struct apk_ctx *ac = db->ctx;
+	const char *uvol_db = apk_db_layer_name(APK_DB_LAYER_UVOL);
+	const char *uvol_target = APK_UVOL_DB_TARGET;
+	const char *uvol_symlink_target = "../../" APK_UVOL_DB_TARGET;
+
+	if (!(ac->open_flags & (APK_OPENF_WRITE|APK_OPENF_CREATE))) return;
+	if (IS_ERR(ac->uvol)) return;
+	if (faccessat(db->root_fd, uvol_db, F_OK, 0) == 0) return;
+	if (faccessat(db->root_fd, uvol_target, F_OK, 0) != 0) return;
+
+	// Create symlink from uvol_db to uvol_target in relative form
+	symlinkat(uvol_symlink_target, db->root_fd, uvol_db);
+}
+#else
+static void setup_uvol_target(struct apk_database *db) { }
+#endif
+
 void apk_db_init(struct apk_database *db)
 {
 	memset(db, 0, sizeof(*db));
@@ -1705,6 +1725,8 @@ int apk_db_open(struct apk_database *db, struct apk_ctx *ac)
 	}
 	if (db->usermode) db->extract_flags |= APK_FSEXTRACTF_NO_CHOWN | APK_FSEXTRACTF_NO_SYS_XATTRS;
 
+	setup_uvol_target(db);
+
 	if (ac->arch && (ac->root_set || (ac->open_flags & APK_OPENF_ALLOW_ARCH))) {
 		db->arch = apk_atomize(&db->atoms, APK_BLOB_STR(ac->arch));
 		db->write_arch = ac->root_set;
diff --git a/src/meson.build b/src/meson.build
index b3c1934f..e2579f7e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -122,6 +122,11 @@ if apk_arch_prefix != ''
 	apk_cargs += ['-DAPK_ARCH_PREFIX="@0@"'.format(apk_arch_prefix)]
 endif
 
+apk_uvol_db_target = get_option('uvol_db_target').strip('/')
+if apk_uvol_db_target != ''
+	apk_cargs += ['-DAPK_UVOL_DB_TARGET="@0@"'.format(apk_uvol_db_target)]
+endif
+
 if get_option('zstd')
 	libapk_src += [ 'io_zstd.c' ]
 	apk_cargs += [ '-DHAVE_ZSTD' ]
-- 
GitLab