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) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -13,4 +13,12 @@ object Util { | |||||||
|         source.buffered().transferTo(buffer) |         source.buffered().transferTo(buffer) | ||||||
|         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") | rootProject.name = "planterette" | ||||||
| include(":api") |  | ||||||
| include(":cli") |  | ||||||
| include(":gui") |  | ||||||
| 
 | 
 | ||||||
| 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