restructure, begin implementing libplt
This commit is contained in:
parent
ae166bc45c
commit
ca586aaa36
9
.idea/gradle.xml
generated
9
.idea/gradle.xml
generated
@ -20,11 +20,12 @@
|
|||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/api" />
|
|
||||||
<option value="$PROJECT_DIR$/buildSrc" />
|
<option value="$PROJECT_DIR$/buildSrc" />
|
||||||
<option value="$PROJECT_DIR$/cli" />
|
<option value="$PROJECT_DIR$/libplt" />
|
||||||
<option value="$PROJECT_DIR$/daemon" />
|
<option value="$PROJECT_DIR$/plt" />
|
||||||
<option value="$PROJECT_DIR$/gui" />
|
<option value="$PROJECT_DIR$/plt-build" />
|
||||||
|
<option value="$PROJECT_DIR$/plt-fetch" />
|
||||||
|
<option value="$PROJECT_DIR$/plt-pkg" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
package app.hakurei.planterette.api
|
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class HakureiConfig(
|
|
||||||
val id: String,
|
|
||||||
|
|
||||||
val path: String? = null,
|
|
||||||
val args: List<String>,
|
|
||||||
|
|
||||||
val enablements: Byte,
|
|
||||||
|
|
||||||
@SerialName("session_bus") val sessionBus: DbusConfig? = null,
|
|
||||||
@SerialName("system_bus") val systemBus: DbusConfig? = null,
|
|
||||||
@SerialName("direct_wayland") val directWayland: Boolean? = null,
|
|
||||||
|
|
||||||
val username: String? = null,
|
|
||||||
val shell: String? = null,
|
|
||||||
val data: String,
|
|
||||||
val dir: String,
|
|
||||||
@SerialName("extra_perms") val extraPerms: List<ExtraPermConfig>?,
|
|
||||||
|
|
||||||
val identity: Int,
|
|
||||||
val groups: List<String>,
|
|
||||||
|
|
||||||
val container: ContainerConfig
|
|
||||||
) {
|
|
||||||
@Serializable
|
|
||||||
data class DbusConfig(
|
|
||||||
val see: List<String>? = null,
|
|
||||||
val talk: List<String>? = null,
|
|
||||||
val own: List<String>? = null,
|
|
||||||
val call: Map<String, String>? = null,
|
|
||||||
val broadcast: Map<String, String>? = null,
|
|
||||||
val log: Boolean? = null,
|
|
||||||
val filter: Boolean? = null
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ExtraPermConfig(
|
|
||||||
val ensure: Boolean? = null,
|
|
||||||
val path: String,
|
|
||||||
@SerialName("r") val read: Boolean? = null,
|
|
||||||
@SerialName("w") val write: Boolean? = null,
|
|
||||||
@SerialName("x") val execute: Boolean? = null
|
|
||||||
)
|
|
||||||
@Serializable
|
|
||||||
data class ContainerConfig(
|
|
||||||
val hostname: String? = null,
|
|
||||||
@SerialName("wait_delay") val delay: Int = -1,
|
|
||||||
@SerialName("seccomp_flags") val seccompFlags: Int,
|
|
||||||
@SerialName("seccomp_presets") val seccompPresets: Int,
|
|
||||||
@SerialName("seccomp_compat") val seccompCompat: Boolean? = null,
|
|
||||||
|
|
||||||
val devel: Boolean? = null,
|
|
||||||
val userns: Boolean? = null,
|
|
||||||
val net: Boolean? = null,
|
|
||||||
val tty: Boolean? = null,
|
|
||||||
val multiarch: Boolean? = null,
|
|
||||||
|
|
||||||
val env: Map<String, String>,
|
|
||||||
@SerialName("map_real_uid") val mapRealUid: Boolean,
|
|
||||||
|
|
||||||
val device: Boolean? = null,
|
|
||||||
val filesystem: List<FilesystemConfig>,
|
|
||||||
@SerialName("symlink") val link: List<String>,
|
|
||||||
|
|
||||||
val etc: String? = null,
|
|
||||||
@SerialName("auto_etc") val autoEtc: Boolean,
|
|
||||||
val cover: List<String>
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class FilesystemConfig(
|
|
||||||
val dst: String? = null,
|
|
||||||
val src: String,
|
|
||||||
val write: Boolean? = null,
|
|
||||||
@SerialName("dev") val device: Boolean? = null,
|
|
||||||
@SerialName("require") val must: Boolean? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
enum class Enablement(val value: Int) {
|
|
||||||
Wayland(1 shl 0),
|
|
||||||
X11(1 shl 1),
|
|
||||||
DBus(1 shl 2),
|
|
||||||
Pulse(1 shl 3);
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun enablements(vararg enablements: Enablement): Byte {
|
|
||||||
return enablements.sumOf(Enablement::value).toByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
enum class SeccompFilterPreset(val value: Int) {
|
|
||||||
Ext(1 shl 0),
|
|
||||||
DenyNS(1 shl 1),
|
|
||||||
DenyTTY(1 shl 2),
|
|
||||||
DenyDevel(1 shl 3),
|
|
||||||
Linux32(1 shl 4);
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun filterPresets(vararg filterPresets: SeccompFilterPreset): Int {
|
|
||||||
return filterPresets.sumOf(SeccompFilterPreset::value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
enum class HakureiExportFlag(val value: Int) {
|
|
||||||
Multiarch(1 shl 0),
|
|
||||||
CAN(1 shl 1),
|
|
||||||
Bluetooth(1 shl 2);
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun exportFlags(vararg exportFlags: HakureiExportFlag): Int {
|
|
||||||
return exportFlags.sumOf(HakureiExportFlag::value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package app.hakurei.planterette.api
|
|
||||||
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import kotlinx.serialization.serializer
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class HakureiConfigTest {
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
val format = Json {
|
|
||||||
explicitNulls = false
|
|
||||||
prettyPrint = true
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testHakureiConfigSerialization() {
|
|
||||||
val testConfig = HakureiConfig(
|
|
||||||
id = "org.chromium.Chromium",
|
|
||||||
path = "/run/current-system/sw/bin/chromium",
|
|
||||||
args = listOf(
|
|
||||||
"chromium",
|
|
||||||
"--ignore-gpu-blocklist",
|
|
||||||
"--disable-smooth-scrolling",
|
|
||||||
"--enable-features=UseOzonePlatform",
|
|
||||||
"--ozone-platform=wayland"
|
|
||||||
),
|
|
||||||
enablements = HakureiConfig.Enablement.enablements(HakureiConfig.Enablement.Wayland, HakureiConfig.Enablement.DBus,
|
|
||||||
HakureiConfig.Enablement.Pulse),
|
|
||||||
sessionBus = HakureiConfig.DbusConfig(
|
|
||||||
see = null,
|
|
||||||
talk = listOf("org.freedesktop.Notifications", "org.freedesktop.FileManager1", "org.freedesktop.ScreenSaver",
|
|
||||||
"org.freedesktop.secrets", "org.kde.kwalletd5", "org.kde.kwalletd6", "org.gnome.SessionManager"),
|
|
||||||
own = listOf("org.chromium.Chromium.*", "org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.chromium.*"),
|
|
||||||
call = mapOf("org.freedesktop.portal.*" to "*"),
|
|
||||||
broadcast = mapOf("org.freedesktop.portal.*" to "@/org/freedesktop/portal/*"),
|
|
||||||
filter = true
|
|
||||||
),
|
|
||||||
systemBus = HakureiConfig.DbusConfig(
|
|
||||||
talk = listOf("org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"),
|
|
||||||
filter = true
|
|
||||||
),
|
|
||||||
|
|
||||||
username = "chronos",
|
|
||||||
shell = "/run/current-system/sw/bin/zsh",
|
|
||||||
data = "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
||||||
dir = "/data/data/org.chromium.Chromium",
|
|
||||||
extraPerms = listOf(
|
|
||||||
HakureiConfig.ExtraPermConfig(path = "/var/lib/hakurei/u0", ensure = true, execute = true),
|
|
||||||
HakureiConfig.ExtraPermConfig(path = "/var/lib/hakurei/u0/org.chromium.Chromium", read = true, write = true, execute = true)
|
|
||||||
),
|
|
||||||
identity = 9,
|
|
||||||
groups = listOf("video", "dialout", "plugdev"),
|
|
||||||
container = HakureiConfig.ContainerConfig(
|
|
||||||
hostname = "localhost",
|
|
||||||
devel = true,
|
|
||||||
userns = true,
|
|
||||||
net = true,
|
|
||||||
device = true,
|
|
||||||
seccompFlags = HakureiConfig.HakureiExportFlag.Multiarch.value,
|
|
||||||
seccompPresets = HakureiConfig.SeccompFilterPreset.Ext.value,
|
|
||||||
tty = true,
|
|
||||||
multiarch = true,
|
|
||||||
mapRealUid = true,
|
|
||||||
env = mapOf(
|
|
||||||
"GOOGLE_API_KEY" to "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
|
||||||
"GOOGLE_DEFAULT_CLIENT_ID" to "77185425430.apps.googleusercontent.com",
|
|
||||||
"GOOGLE_DEFAULT_CLIENT_SECRET" to "OTJgUOQcT7lO7GsGZq2G4IlT",
|
|
||||||
),
|
|
||||||
filesystem = listOf(
|
|
||||||
HakureiConfig.FilesystemConfig(src = "/nix/store"),
|
|
||||||
HakureiConfig.FilesystemConfig(src = "/run/current-system"),
|
|
||||||
HakureiConfig.FilesystemConfig(src = "/run/opengl-driver"),
|
|
||||||
HakureiConfig.FilesystemConfig(src = "/var/db/nix-channels"),
|
|
||||||
HakureiConfig.FilesystemConfig(
|
|
||||||
src = "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
||||||
dst = "/data/data/org.chromium.Chromium",
|
|
||||||
write = true,
|
|
||||||
must = true
|
|
||||||
),
|
|
||||||
HakureiConfig.FilesystemConfig(src = "/dev/dri", device = true)
|
|
||||||
),
|
|
||||||
link = listOf("/run/user/65534", "/run/user/150"),
|
|
||||||
etc = "/etc",
|
|
||||||
autoEtc = true,
|
|
||||||
cover = listOf("/var/run/nscd"),
|
|
||||||
delay = -1,
|
|
||||||
seccompCompat = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val json = format.encodeToString(serializer(), testConfig)
|
|
||||||
val deserializeJson: HakureiConfig = format.decodeFromString(json)
|
|
||||||
val templateJson: HakureiConfig = format.decodeFromString(Util.readFileToString("/home/lilly/Documents/Projects/Rosa/planterette/api/src/commonTest/resources/template.json"))
|
|
||||||
assertEquals(templateJson, deserializeJson, "")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "org.chromium.Chromium",
|
|
||||||
"path": "/run/current-system/sw/bin/chromium",
|
|
||||||
"args": [
|
|
||||||
"chromium",
|
|
||||||
"--ignore-gpu-blocklist",
|
|
||||||
"--disable-smooth-scrolling",
|
|
||||||
"--enable-features=UseOzonePlatform",
|
|
||||||
"--ozone-platform=wayland"
|
|
||||||
],
|
|
||||||
"enablements": 13,
|
|
||||||
"session_bus": {
|
|
||||||
"see": null,
|
|
||||||
"talk": [
|
|
||||||
"org.freedesktop.Notifications",
|
|
||||||
"org.freedesktop.FileManager1",
|
|
||||||
"org.freedesktop.ScreenSaver",
|
|
||||||
"org.freedesktop.secrets",
|
|
||||||
"org.kde.kwalletd5",
|
|
||||||
"org.kde.kwalletd6",
|
|
||||||
"org.gnome.SessionManager"
|
|
||||||
],
|
|
||||||
"own": [
|
|
||||||
"org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
||||||
"org.mpris.MediaPlayer2.chromium.*"
|
|
||||||
],
|
|
||||||
"call": {
|
|
||||||
"org.freedesktop.portal.*": "*"
|
|
||||||
},
|
|
||||||
"broadcast": {
|
|
||||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
|
||||||
},
|
|
||||||
"filter": true
|
|
||||||
},
|
|
||||||
"system_bus": {
|
|
||||||
"see": null,
|
|
||||||
"talk": [
|
|
||||||
"org.bluez",
|
|
||||||
"org.freedesktop.Avahi",
|
|
||||||
"org.freedesktop.UPower"
|
|
||||||
],
|
|
||||||
"own": null,
|
|
||||||
"call": null,
|
|
||||||
"broadcast": null,
|
|
||||||
"filter": true
|
|
||||||
},
|
|
||||||
"username": "chronos",
|
|
||||||
"shell": "/run/current-system/sw/bin/zsh",
|
|
||||||
"data": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
||||||
"dir": "/data/data/org.chromium.Chromium",
|
|
||||||
"extra_perms": [
|
|
||||||
{
|
|
||||||
"ensure": true,
|
|
||||||
"path": "/var/lib/hakurei/u0",
|
|
||||||
"x": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
||||||
"r": true,
|
|
||||||
"w": true,
|
|
||||||
"x": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"identity": 9,
|
|
||||||
"groups": [
|
|
||||||
"video",
|
|
||||||
"dialout",
|
|
||||||
"plugdev"
|
|
||||||
],
|
|
||||||
"container": {
|
|
||||||
"hostname": "localhost",
|
|
||||||
"wait_delay": -1,
|
|
||||||
"seccomp_flags": 1,
|
|
||||||
"seccomp_presets": 1,
|
|
||||||
"seccomp_compat": true,
|
|
||||||
"devel": true,
|
|
||||||
"userns": true,
|
|
||||||
"net": true,
|
|
||||||
"tty": true,
|
|
||||||
"multiarch": true,
|
|
||||||
"env": {
|
|
||||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
|
||||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
|
||||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
|
||||||
},
|
|
||||||
"map_real_uid": true,
|
|
||||||
"device": true,
|
|
||||||
"filesystem": [
|
|
||||||
{
|
|
||||||
"src": "/nix/store"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/run/current-system"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/run/opengl-driver"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/var/db/nix-channels"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/data/data/org.chromium.Chromium",
|
|
||||||
"src": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
||||||
"write": true,
|
|
||||||
"require": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/dev/dri",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"symlink": [
|
|
||||||
"/run/user/65534",
|
|
||||||
"/run/user/150"
|
|
||||||
],
|
|
||||||
"etc": "/etc",
|
|
||||||
"auto_etc": true,
|
|
||||||
"cover": [
|
|
||||||
"/var/run/nscd"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
package app.hakurei.planterette.api.dsl
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
plugins {
|
|
||||||
kotlin("jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":api"))
|
|
||||||
testImplementation(kotlin("test"))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
kotlin {
|
|
||||||
jvmToolchain(21)
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("buildsrc.convention.kotlin-jvm")
|
|
||||||
kotlin("jvm")
|
|
||||||
application
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":api"))
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
mainClass = "app.hakurei.planterette.PlanteretteKt"
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package app.hakurei.planterette
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
{
|
|
||||||
"id": "org.debian",
|
|
||||||
"path": "/bin/bash",
|
|
||||||
"args": [
|
|
||||||
"bash"
|
|
||||||
],
|
|
||||||
"enablements": 13,
|
|
||||||
"session_bus": {
|
|
||||||
"see": null,
|
|
||||||
"talk": [
|
|
||||||
"org.freedesktop.Notifications",
|
|
||||||
"org.freedesktop.FileManager1",
|
|
||||||
"org.freedesktop.ScreenSaver"
|
|
||||||
],
|
|
||||||
"own": null,
|
|
||||||
"call": null,
|
|
||||||
"broadcast": null,
|
|
||||||
"filter": true
|
|
||||||
},
|
|
||||||
"system_bus": {
|
|
||||||
"see": null,
|
|
||||||
"talk": null,
|
|
||||||
"own": null,
|
|
||||||
"call": null,
|
|
||||||
"broadcast": null,
|
|
||||||
"filter": true
|
|
||||||
},
|
|
||||||
"username": "chronos",
|
|
||||||
"shell": "/bin/bash",
|
|
||||||
"data": "/tmp/chronos",
|
|
||||||
"dir": "/.hakurei/home",
|
|
||||||
"identity": 9,
|
|
||||||
"groups": null,
|
|
||||||
"container": {
|
|
||||||
"hostname": "debian",
|
|
||||||
"seccomp_flags": 0,
|
|
||||||
"seccomp_presets": 0,
|
|
||||||
"devel": true,
|
|
||||||
"userns": true,
|
|
||||||
"net": true,
|
|
||||||
"tty": true,
|
|
||||||
"multiarch": true,
|
|
||||||
"env": null,
|
|
||||||
"map_real_uid": true,
|
|
||||||
"filesystem": [
|
|
||||||
{
|
|
||||||
"dst": "/boot",
|
|
||||||
"src": "/mnt/debian/boot"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/home",
|
|
||||||
"src": "/mnt/debian/home"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/media",
|
|
||||||
"src": "/mnt/debian/media"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/mnt",
|
|
||||||
"src": "/mnt/debian/mnt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/opt",
|
|
||||||
"src": "/mnt/debian/opt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/root",
|
|
||||||
"src": "/mnt/debian/root"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/srv",
|
|
||||||
"src": "/mnt/debian/srv"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/usr",
|
|
||||||
"src": "/mnt/debian/usr"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dst": "/var",
|
|
||||||
"src": "/mnt/debian/var"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/sys/block"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/sys/bus"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/sys/class"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/sys/dev"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/sys/devices"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "/dev/dri",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"symlink": [
|
|
||||||
[
|
|
||||||
"usr/bin",
|
|
||||||
"/bin"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"usr/lib",
|
|
||||||
"/lib"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"usr/lib64",
|
|
||||||
"/lib64"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"usr/sbin",
|
|
||||||
"/sbin"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"etc": "/mnt/debian/etc",
|
|
||||||
"auto_etc": false,
|
|
||||||
"cover": null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
plugins {
|
|
||||||
kotlin("jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":api"))
|
|
||||||
implementation(project(":cli"))
|
|
||||||
testImplementation(kotlin("test"))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
kotlin {
|
|
||||||
jvmToolchain(21)
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ kotlin {
|
|||||||
}
|
}
|
||||||
nativeTarget.binaries {
|
nativeTarget.binaries {
|
||||||
sharedLib {
|
sharedLib {
|
||||||
baseName = "planterette"
|
baseName = "libplt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -22,11 +22,5 @@ kotlin {
|
|||||||
implementation(libs.bundles.kotlinxEcosystem)
|
implementation(libs.bundles.kotlinxEcosystem)
|
||||||
implementation(kotlin("test"))
|
implementation(kotlin("test"))
|
||||||
}
|
}
|
||||||
jvmMain.dependencies {
|
|
||||||
|
|
||||||
}
|
|
||||||
jvmTest.dependencies {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package app.hakurei.planterette.api
|
||||||
|
|
||||||
|
import app.hakurei.planterette.api.AbsolutePath.Companion.isAbsolute
|
||||||
|
import kotlinx.io.files.Path
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Serializer
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbsolutePath holds a pathname checked to be absolute.
|
||||||
|
* @constructor checks pathname and returns a new AbsolutePath if pathname is absolute.
|
||||||
|
*/
|
||||||
|
@Serializable(with = AbsolutePathSerializer::class)
|
||||||
|
data class AbsolutePath(val pathname: String, @Transient val path: Path = Path(pathname)) {
|
||||||
|
init {
|
||||||
|
if(!isAbsolute(pathname)) {
|
||||||
|
throw AbsolutePathException(pathname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operator fun plus(other: String): AbsolutePath {
|
||||||
|
return AbsolutePath(pathname + other)
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
fun isAbsolute(pathname: String): Boolean {
|
||||||
|
return Path(pathname).isAbsolute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object AbsolutePathSerializer : KSerializer<AbsolutePath> {
|
||||||
|
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(this::class.qualifiedName!!, PrimitiveKind.STRING)
|
||||||
|
override fun serialize(encoder: Encoder, value: AbsolutePath) {
|
||||||
|
encoder.encodeString(value.pathname)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): AbsolutePath {
|
||||||
|
val path = decoder.decodeString()
|
||||||
|
return AbsolutePath(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbsolutePathException is returned by @see AbsolutePath() and holds the invalid pathname.
|
||||||
|
*/
|
||||||
|
data class AbsolutePathException(val pathname: String) : IllegalArgumentException("Path $pathname is not absolute")
|
@ -0,0 +1,209 @@
|
|||||||
|
package app.hakurei.planterette.api
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HakureiConfig is used to seal an app implementation.
|
||||||
|
* @param id reverse-DNS style arbitrary identifier string from config; Passed to wayland security-context-v1 as application ID and used as part of defaults in dbus session proxy
|
||||||
|
*
|
||||||
|
* @param path absolute path to executable file
|
||||||
|
* @param args final args passed to container init
|
||||||
|
*
|
||||||
|
* @param enablements system services to make available in the container
|
||||||
|
*
|
||||||
|
* @param sessionBus session D-Bus proxy configuration; null makes session bus proxy assume built-in defaults
|
||||||
|
* @param systemBus system D-Bus proxy configuration; null disables system bus proxy
|
||||||
|
* @param directWayland direct access to the wayland socket; when this gets set no attempt is made to attach security-context-v1 and the bare socket is mounted to the sandbox
|
||||||
|
*
|
||||||
|
* @param username passwd username in container, defaults to passwd name of target uid or chronos
|
||||||
|
* @param shell absolute path to shell
|
||||||
|
* @param data absolute path to home directory in the init mount namespace
|
||||||
|
* @param dir directory to ender and use as home in the container mount namespace, null for Data
|
||||||
|
* @param extraPerms extra ACL ops, dispatches before container init
|
||||||
|
*
|
||||||
|
* @param identity numerical application id, used for init user namespace credentials
|
||||||
|
* @param groups list of supplementary groups inherited by container processes
|
||||||
|
*
|
||||||
|
* @param container abstract container configuration baseline
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class HakureiConfig(
|
||||||
|
val id: String,
|
||||||
|
|
||||||
|
val path: AbsolutePath? = null,
|
||||||
|
val args: List<String>,
|
||||||
|
|
||||||
|
val enablements: Byte,
|
||||||
|
|
||||||
|
@SerialName("session_bus") val sessionBus: DbusConfig? = null,
|
||||||
|
@SerialName("system_bus") val systemBus: DbusConfig? = null,
|
||||||
|
@SerialName("direct_wayland") val directWayland: Boolean? = null,
|
||||||
|
|
||||||
|
val username: String? = null,
|
||||||
|
val shell: AbsolutePath,
|
||||||
|
val data: AbsolutePath,
|
||||||
|
val dir: AbsolutePath,
|
||||||
|
@SerialName("extra_perms") val extraPerms: List<ExtraPermConfig>? = null,
|
||||||
|
|
||||||
|
val identity: Int,
|
||||||
|
val groups: List<String>,
|
||||||
|
|
||||||
|
val container: ContainerConfig
|
||||||
|
) {
|
||||||
|
@Serializable
|
||||||
|
data class DbusConfig(
|
||||||
|
val see: List<String>? = null,
|
||||||
|
val talk: List<String>? = null,
|
||||||
|
val own: List<String>? = null,
|
||||||
|
val call: Map<String, String>? = null,
|
||||||
|
val broadcast: Map<String, String>? = null,
|
||||||
|
|
||||||
|
val log: Boolean? = null,
|
||||||
|
val filter: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExtraPermConfig describes an ACL update op.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class ExtraPermConfig(
|
||||||
|
val ensure: Boolean? = null,
|
||||||
|
val path: AbsolutePath,
|
||||||
|
@SerialName("r") val read: Boolean? = null,
|
||||||
|
@SerialName("w") val write: Boolean? = null,
|
||||||
|
@SerialName("x") val execute: Boolean? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ContainerConfig describes the container configuration baseline to which the app implementation adds upon.
|
||||||
|
* @param hostname container hostname
|
||||||
|
* @param waitDelay duration to wait for after interrupting a container's initial process in nanoseconds; a negative value causes the container to be terminated immediately on cancellation
|
||||||
|
* @param seccompFlags extra seccomp flags
|
||||||
|
* @param seccompPresets extra seccomp presets
|
||||||
|
* @param seccompCompat disable project-specific filter extensions
|
||||||
|
* @param devel allow ptrace and friends
|
||||||
|
* @param userns allow userns creation in container
|
||||||
|
* @param net share host net namespace
|
||||||
|
* @param tty allow dangerous terminal I/O
|
||||||
|
* @param multiarch allow multiarch
|
||||||
|
*
|
||||||
|
* @param env initial process environment variables
|
||||||
|
* @param mapRealUid map target user uid to privileged user uid in the user namespace
|
||||||
|
*
|
||||||
|
* @param device pass through all devices
|
||||||
|
* @param filesystem container host filesystem bind mounts
|
||||||
|
* @param link create symlinks inside container filesystem
|
||||||
|
*
|
||||||
|
* @param autoRoot automatically bind mount top-level directories to container root; the zero value disables this behaviour
|
||||||
|
* @param rootFlags extra flags for AutoRoot
|
||||||
|
*
|
||||||
|
* @param etc read-only /etc directory
|
||||||
|
* @param autoEtc automatically set up /etc symlinks
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class ContainerConfig(
|
||||||
|
val hostname: String?,
|
||||||
|
@SerialName("wait_delay") val waitDelay: Int? = null,
|
||||||
|
@SerialName("seccomp_flags") val seccompFlags: Int,
|
||||||
|
@SerialName("seccomp_presets") val seccompPresets: Int,
|
||||||
|
@SerialName("seccomp_compat") val seccompCompat: Boolean? = null,
|
||||||
|
|
||||||
|
val devel: Boolean? = null,
|
||||||
|
val userns: Boolean? = null,
|
||||||
|
val net: Boolean? = null,
|
||||||
|
val tty: Boolean? = null,
|
||||||
|
val multiarch: Boolean? = null,
|
||||||
|
|
||||||
|
val env: Map<String, String>,
|
||||||
|
@SerialName("map_real_uid") val mapRealUid: Boolean,
|
||||||
|
|
||||||
|
val device: Boolean?,
|
||||||
|
val filesystem: List<FilesystemConfig>,
|
||||||
|
@SerialName("symlink") val link: List<LinkConfig>,
|
||||||
|
|
||||||
|
@SerialName("auto_root") val autoRoot: AbsolutePath,
|
||||||
|
@SerialName("root_flags") val rootFlags: Int,
|
||||||
|
|
||||||
|
val etc: AbsolutePath?,
|
||||||
|
|
||||||
|
@SerialName("auto_etc") val autoEtc: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FilesystemConfig is an abstract representation of a bind mount.
|
||||||
|
* @param dst mount point in container, same as src if empty
|
||||||
|
* @param src host filesystem path to make available to the container
|
||||||
|
* @param write do not mount filesystem read-only
|
||||||
|
* @param device do not disable device files
|
||||||
|
* @param must fail if the bind mount cannot be established for any reason
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class FilesystemConfig(
|
||||||
|
val dst: AbsolutePath? = null,
|
||||||
|
val src: AbsolutePath,
|
||||||
|
val write: Boolean? = null,
|
||||||
|
@SerialName("dev") val device: Boolean? = null,
|
||||||
|
@SerialName("require") val must: Boolean? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param target symlink target in container
|
||||||
|
* @param linkname linkname the symlink points to; prepend '*' to dereference an absolute pathname on host
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class LinkConfig(
|
||||||
|
val target: AbsolutePath,
|
||||||
|
val linkname: String
|
||||||
|
)
|
||||||
|
enum class Enablement(val value: Int) {
|
||||||
|
Wayland(1 shl 0),
|
||||||
|
X11(1 shl 1),
|
||||||
|
DBus(1 shl 2),
|
||||||
|
Pulse(1 shl 3);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun enablements(vararg enablements: Enablement): Byte {
|
||||||
|
return enablements.orOf(Enablement::value).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class SeccompFilterPreset(val value: Int) {
|
||||||
|
Ext(1 shl 0),
|
||||||
|
DenyNS(1 shl 1),
|
||||||
|
DenyTTY(1 shl 2),
|
||||||
|
DenyDevel(1 shl 3),
|
||||||
|
Linux32(1 shl 4);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun filterPresets(vararg filterPresets: SeccompFilterPreset): Int {
|
||||||
|
return filterPresets.orOf(SeccompFilterPreset::value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class HakureiExportFlag(val value: Int) {
|
||||||
|
Multiarch(1 shl 0),
|
||||||
|
CAN(1 shl 1),
|
||||||
|
Bluetooth(1 shl 2);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun exportFlags(vararg exportFlags: HakureiExportFlag): Int {
|
||||||
|
return exportFlags.orOf(HakureiExportFlag::value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class RootFlag(val value: Int) {
|
||||||
|
Optional(1 shl 0),
|
||||||
|
Writable(1 shl 1),
|
||||||
|
Device(1 shl 2);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun rootFlags(vararg rootFlags: RootFlag): Int {
|
||||||
|
return rootFlags.orOf(RootFlag::value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,13 +4,13 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PackageManifest(
|
data class PackageManifest(
|
||||||
val hakureiConfig: HakureiConfig,
|
var hakureiConfig: HakureiConfig,
|
||||||
val id: String,
|
var id: String,
|
||||||
val version: Version,
|
var version: Version,
|
||||||
val name: String,
|
var name: String,
|
||||||
val description: String,
|
var description: String,
|
||||||
val architecture: List<Architecture>,
|
var architecture: MutableList<Architecture>,
|
||||||
val baseImage: BaseImage
|
var baseImage: BaseImage
|
||||||
) {
|
) {
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Version(val version: String, val canonicalVersion: UInt)
|
data class Version(val version: String, val canonicalVersion: UInt)
|
||||||
@ -21,10 +21,12 @@ data class PackageManifest(
|
|||||||
ARM64,
|
ARM64,
|
||||||
}
|
}
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class BaseImage {
|
data class BaseImage(val type: Type) {
|
||||||
DEBIAN,
|
@Serializable
|
||||||
CHIMERA,
|
enum class Type {
|
||||||
|
DEBIAN,
|
||||||
|
CHIMERA,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
val fileList = listOf("planterette.json", "icon.png", "image.tar")
|
val fileList = listOf("planterette.json", "icon.png", "image.tar")
|
@ -0,0 +1,47 @@
|
|||||||
|
package app.hakurei.planterette.api
|
||||||
|
|
||||||
|
object Paths {
|
||||||
|
const val FHSRoot = "/"
|
||||||
|
const val FHSEtc = "/etc/"
|
||||||
|
const val FHSTmp = "/tmp/"
|
||||||
|
|
||||||
|
const val FHSRun = "/run/"
|
||||||
|
const val FHSRunUser = FHSRun + "user/"
|
||||||
|
|
||||||
|
const val FHSUsr = "/usr/"
|
||||||
|
const val FHSUsrBin = FHSUsr + "bin/"
|
||||||
|
|
||||||
|
const val FHSVar = "/var/"
|
||||||
|
const val FHSVarLib = FHSVar + "lib/"
|
||||||
|
const val FHSVarEmpty = FHSVar + "empty/"
|
||||||
|
|
||||||
|
const val FHSDev = "/dev/"
|
||||||
|
const val FHSProc = "/proc/"
|
||||||
|
const val FHSProcSys = FHSProc + "sys/"
|
||||||
|
const val FHSSys = "/sys/"
|
||||||
|
|
||||||
|
const val Nonexistent = FHSProc + "nonexistent"
|
||||||
|
const val sysrootDir = "sysroot"
|
||||||
|
const val hostDir = "host"
|
||||||
|
const val hostPath = FHSRoot + hostDir
|
||||||
|
const val sysrootPath = FHSRoot + sysrootDir
|
||||||
|
|
||||||
|
val AbsFHSRoot = AbsolutePath(FHSRoot)
|
||||||
|
val AbsFHSEtc = AbsolutePath(FHSEtc)
|
||||||
|
val AbsFHSTmp = AbsolutePath(FHSTmp)
|
||||||
|
|
||||||
|
val AbsFHSRun = AbsolutePath(FHSRun)
|
||||||
|
val AbsFHSRunUser = AbsolutePath(FHSRunUser)
|
||||||
|
|
||||||
|
val AbsFHSUsrBin = AbsolutePath(FHSUsrBin)
|
||||||
|
|
||||||
|
val AbsFHSVar = AbsolutePath(FHSVar)
|
||||||
|
val AbsFHSVarLib = AbsolutePath(FHSVarLib)
|
||||||
|
|
||||||
|
val AbsFHSDev = AbsolutePath(FHSDev)
|
||||||
|
val AbsFHSProc = AbsolutePath(FHSProc)
|
||||||
|
val AbsFHSSys = AbsolutePath(FHSSys)
|
||||||
|
|
||||||
|
val AbsNonexistent = AbsolutePath(Nonexistent)
|
||||||
|
}
|
||||||
|
|
@ -14,3 +14,11 @@ object Util {
|
|||||||
return buffer.readString()
|
return buffer.readString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <T> Array<out T>.orOf(selector: (T) -> Int): Int {
|
||||||
|
var sum = 0
|
||||||
|
for (element in this) {
|
||||||
|
sum = sum or selector(element)
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
@ -0,0 +1,230 @@
|
|||||||
|
package app.hakurei.planterette.api
|
||||||
|
|
||||||
|
import app.hakurei.planterette.api.HakureiConfig.Enablement.*
|
||||||
|
import app.hakurei.planterette.api.HakureiConfig.RootFlag
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class HakureiConfigTest {
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
val format = Json {
|
||||||
|
explicitNulls = false
|
||||||
|
prettyPrint = true
|
||||||
|
}
|
||||||
|
val want: String = """
|
||||||
|
{
|
||||||
|
"id": "org.chromium.Chromium",
|
||||||
|
"path": "/run/current-system/sw/bin/chromium",
|
||||||
|
"args": [
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland"
|
||||||
|
],
|
||||||
|
"enablements": 13,
|
||||||
|
"session_bus": {
|
||||||
|
"see": null,
|
||||||
|
"talk": [
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"org.freedesktop.FileManager1",
|
||||||
|
"org.freedesktop.ScreenSaver",
|
||||||
|
"org.freedesktop.secrets",
|
||||||
|
"org.kde.kwalletd5",
|
||||||
|
"org.kde.kwalletd6",
|
||||||
|
"org.gnome.SessionManager"
|
||||||
|
],
|
||||||
|
"own": [
|
||||||
|
"org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.chromium.*"
|
||||||
|
],
|
||||||
|
"call": {
|
||||||
|
"org.freedesktop.portal.*": "*"
|
||||||
|
},
|
||||||
|
"broadcast": {
|
||||||
|
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
||||||
|
},
|
||||||
|
"filter": true
|
||||||
|
},
|
||||||
|
"system_bus": {
|
||||||
|
"see": null,
|
||||||
|
"talk": [
|
||||||
|
"org.bluez",
|
||||||
|
"org.freedesktop.Avahi",
|
||||||
|
"org.freedesktop.UPower"
|
||||||
|
],
|
||||||
|
"own": null,
|
||||||
|
"call": null,
|
||||||
|
"broadcast": null,
|
||||||
|
"filter": true
|
||||||
|
},
|
||||||
|
"username": "chronos",
|
||||||
|
"shell": "/run/current-system/sw/bin/zsh",
|
||||||
|
"data": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
||||||
|
"dir": "/data/data/org.chromium.Chromium",
|
||||||
|
"extra_perms": [
|
||||||
|
{
|
||||||
|
"ensure": true,
|
||||||
|
"path": "/var/lib/hakurei/u0",
|
||||||
|
"x": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
||||||
|
"r": true,
|
||||||
|
"w": true,
|
||||||
|
"x": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"identity": 9,
|
||||||
|
"groups": [
|
||||||
|
"video",
|
||||||
|
"dialout",
|
||||||
|
"plugdev"
|
||||||
|
],
|
||||||
|
"container": {
|
||||||
|
"hostname": "localhost",
|
||||||
|
"wait_delay": -1,
|
||||||
|
"seccomp_flags": 1,
|
||||||
|
"seccomp_presets": 1,
|
||||||
|
"seccomp_compat": true,
|
||||||
|
"devel": true,
|
||||||
|
"userns": true,
|
||||||
|
"net": true,
|
||||||
|
"tty": true,
|
||||||
|
"multiarch": true,
|
||||||
|
"env": {
|
||||||
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||||
|
},
|
||||||
|
"map_real_uid": true,
|
||||||
|
"device": true,
|
||||||
|
"filesystem": [
|
||||||
|
{
|
||||||
|
"dst": "/tmp/",
|
||||||
|
"src": "/proc/nonexistent",
|
||||||
|
"write": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/nix/store"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/run/current-system"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/run/opengl-driver"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/var/db/nix-channels"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"dst": "/data/data/org.chromium.Chromium",
|
||||||
|
"src": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
||||||
|
"write": true,
|
||||||
|
"require": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/dev/dri",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"symlink": [
|
||||||
|
{
|
||||||
|
"target": "/run/user/65534",
|
||||||
|
"linkname": "/run/user/150"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"auto_root": "/var/lib/hakurei/base/org.debian",
|
||||||
|
"root_flags": 2,
|
||||||
|
"etc": "/etc/",
|
||||||
|
"auto_etc": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
@Test
|
||||||
|
fun testHakureiConfigSerialization() {
|
||||||
|
val testConfig = HakureiConfig(
|
||||||
|
id = "org.chromium.Chromium",
|
||||||
|
path = Paths.AbsFHSRun + "current-system/sw/bin/chromium",
|
||||||
|
args = listOf(
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland",
|
||||||
|
),
|
||||||
|
enablements = HakureiConfig.Enablement.enablements(Wayland, DBus, Pulse),
|
||||||
|
sessionBus = HakureiConfig.DbusConfig(
|
||||||
|
see = null,
|
||||||
|
talk = listOf("org.freedesktop.Notifications", "org.freedesktop.FileManager1", "org.freedesktop.ScreenSaver"),
|
||||||
|
own = listOf("org.chromium.Chromium.*", "org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||||
|
"org.mpris.MediaPlayer2.chromium.*"),
|
||||||
|
call = mapOf("org.freedesktop.portal.*" to "*"),
|
||||||
|
broadcast = mapOf("org.freedesktop.portal.*" to "@/org/freedesktop/portal/*"),
|
||||||
|
log = false,
|
||||||
|
filter = true,
|
||||||
|
),
|
||||||
|
systemBus = HakureiConfig.DbusConfig(
|
||||||
|
see = null,
|
||||||
|
talk = listOf("org.bluez", "org.freedesktop.Avahi", "org.freedesktop.UPower"),
|
||||||
|
own = null,
|
||||||
|
call = null,
|
||||||
|
broadcast = null,
|
||||||
|
log = false,
|
||||||
|
filter = true,
|
||||||
|
),
|
||||||
|
directWayland = false,
|
||||||
|
|
||||||
|
username = "chronos",
|
||||||
|
shell = Paths.AbsFHSRun + "current-system/sw/bin/zsh",
|
||||||
|
data = Paths.AbsFHSVarLib + "hakurei/u0/org.chromium.Chromium",
|
||||||
|
dir = AbsolutePath("/data/data/org.chromium.Chromium"),
|
||||||
|
extraPerms = listOf(
|
||||||
|
HakureiConfig.ExtraPermConfig(path = Paths.AbsFHSVarLib + "hakurei/u0", ensure = true, execute = true),
|
||||||
|
HakureiConfig.ExtraPermConfig(path = Paths.AbsFHSVarLib + "hakurei/u0/org.chromium.Chromium", read = true, write = true, execute = true)
|
||||||
|
),
|
||||||
|
identity = 9,
|
||||||
|
groups = listOf("video", "dialout", "plugdev"),
|
||||||
|
container = HakureiConfig.ContainerConfig(
|
||||||
|
hostname = "localhost",
|
||||||
|
devel = true,
|
||||||
|
userns = true,
|
||||||
|
net = true,
|
||||||
|
device = true,
|
||||||
|
waitDelay = -1,
|
||||||
|
seccompFlags = HakureiConfig.HakureiExportFlag.exportFlags(HakureiConfig.HakureiExportFlag.Multiarch),
|
||||||
|
seccompPresets = HakureiConfig.SeccompFilterPreset.filterPresets(HakureiConfig.SeccompFilterPreset.Ext),
|
||||||
|
seccompCompat = true,
|
||||||
|
tty = true,
|
||||||
|
multiarch = true,
|
||||||
|
mapRealUid = true,
|
||||||
|
env = mapOf(
|
||||||
|
"GOOGLE_API_KEY" to "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_ID" to "77185425430.apps.googleusercontent.com",
|
||||||
|
"GOOGLE_DEFAULT_CLIENT_SECRET" to "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||||
|
),
|
||||||
|
filesystem = listOf(
|
||||||
|
HakureiConfig.FilesystemConfig(dst = Paths.AbsFHSTmp, src = Paths.AbsNonexistent, write = true),
|
||||||
|
HakureiConfig.FilesystemConfig(src = AbsolutePath("/nix/store")),
|
||||||
|
HakureiConfig.FilesystemConfig(src = Paths.AbsFHSRun + "current-system"),
|
||||||
|
HakureiConfig.FilesystemConfig(src = Paths.AbsFHSRun + "opengl-driver"),
|
||||||
|
HakureiConfig.FilesystemConfig(src = Paths.AbsFHSVar + "db/nix-channels"),
|
||||||
|
HakureiConfig.FilesystemConfig(src = Paths.AbsFHSVarLib + "hakurei/u0/org.chromium.Chromium", dst = AbsolutePath("/data/data/org.chromium.Chromium"), write = true, must = true),
|
||||||
|
HakureiConfig.FilesystemConfig(src = Paths.AbsFHSDev + "dri", device = true)
|
||||||
|
),
|
||||||
|
link = listOf(HakureiConfig.LinkConfig(Paths.AbsFHSRunUser + "65534", Paths.FHSRunUser + "150")),
|
||||||
|
autoRoot = Paths.AbsFHSVarLib + "hakurei/base/org.debian",
|
||||||
|
rootFlags = RootFlag.rootFlags(RootFlag.Writable),
|
||||||
|
etc = Paths.AbsFHSEtc,
|
||||||
|
autoEtc = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
println("printing for now until a more proper test can be written")
|
||||||
|
println(format.encodeToString(testConfig))
|
||||||
|
}
|
||||||
|
}
|
30
plt-build/build.gradle.kts
Normal file
30
plt-build/build.gradle.kts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
val nativeTarget = if(System.getProperty("os.arch") == "aarch64") {
|
||||||
|
linuxArm64("native")
|
||||||
|
} else {
|
||||||
|
linuxX64("native")
|
||||||
|
}
|
||||||
|
nativeTarget.binaries {
|
||||||
|
executable()
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
nativeMain.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
}
|
||||||
|
nativeTest.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
jvmMain.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
}
|
||||||
|
jvmTest.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package app.hakurei.planterette.api
|
||||||
|
|
||||||
|
interface Task {
|
||||||
|
val execute: String
|
||||||
|
}
|
||||||
|
class AptInstallTask(val packages: List<String>) : Task {
|
||||||
|
private fun getPackageList(): String {
|
||||||
|
var string = ""
|
||||||
|
packages.forEach { p ->
|
||||||
|
string += "$p "
|
||||||
|
}
|
||||||
|
return string
|
||||||
|
}
|
||||||
|
override val execute: String
|
||||||
|
get() = "sudo apt install ${getPackageList()}"
|
||||||
|
}
|
22
plt-fetch/build.gradle.kts
Normal file
22
plt-fetch/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
val nativeTarget = if(System.getProperty("os.arch") == "aarch64") {
|
||||||
|
linuxArm64("native")
|
||||||
|
} else {
|
||||||
|
linuxX64("native")
|
||||||
|
}
|
||||||
|
nativeTarget.binaries {
|
||||||
|
executable()
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
nativeMain.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
}
|
||||||
|
nativeTest.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
plt-pkg/build.gradle.kts
Normal file
22
plt-pkg/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
val nativeTarget = if(System.getProperty("os.arch") == "aarch64") {
|
||||||
|
linuxArm64("native")
|
||||||
|
} else {
|
||||||
|
linuxX64("native")
|
||||||
|
}
|
||||||
|
nativeTarget.binaries {
|
||||||
|
executable()
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
nativeMain.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
}
|
||||||
|
nativeTest.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
plt/build.gradle.kts
Normal file
22
plt/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
val nativeTarget = if(System.getProperty("os.arch") == "aarch64") {
|
||||||
|
linuxArm64("native")
|
||||||
|
} else {
|
||||||
|
linuxX64("native")
|
||||||
|
}
|
||||||
|
nativeTarget.binaries {
|
||||||
|
executable()
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
nativeMain.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
}
|
||||||
|
nativeTest.dependencies {
|
||||||
|
implementation(project(":libplt"))
|
||||||
|
implementation(kotlin("test"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,10 @@ plugins {
|
|||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
include(":daemon")
|
|
||||||
include(":api")
|
|
||||||
include(":cli")
|
|
||||||
include(":gui")
|
|
||||||
|
|
||||||
rootProject.name = "planterette"
|
rootProject.name = "planterette"
|
||||||
|
|
||||||
|
include("plt")
|
||||||
|
include("libplt")
|
||||||
|
include("plt-build")
|
||||||
|
include("plt-fetch")
|
||||||
|
include("plt-pkg")
|
Loading…
x
Reference in New Issue
Block a user