summaryrefslogtreecommitdiff
path: root/src/main/kotlin/files.kt
diff options
context:
space:
mode:
authornea <romangraef@gmail.com>2021-08-12 23:37:47 +0200
committernea <romangraef@gmail.com>2021-08-12 23:37:47 +0200
commit2ee4b7c2bef9f80ed12e58bc3cdbb965299920e1 (patch)
treed4ac288bb7c9e15acfd9cfa1868a69b0b15fc30e /src/main/kotlin/files.kt
parent14f72a3d6005dec3f9fc1e9832161b5de0d1b354 (diff)
downloadwebos-2ee4b7c2bef9f80ed12e58bc3cdbb965299920e1.tar.gz
webos-2ee4b7c2bef9f80ed12e58bc3cdbb965299920e1.tar.bz2
webos-2ee4b7c2bef9f80ed12e58bc3cdbb965299920e1.zip
file system rework
Diffstat (limited to 'src/main/kotlin/files.kt')
-rw-r--r--src/main/kotlin/files.kt86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/main/kotlin/files.kt b/src/main/kotlin/files.kt
new file mode 100644
index 0000000..990ae7e
--- /dev/null
+++ b/src/main/kotlin/files.kt
@@ -0,0 +1,86 @@
+class IOHandler {
+ val mounts = mutableListOf<Mount>()
+ fun mount(absolutePath: Path.Absolute, fileSystem: FileSystem) {
+ if (mounts.any { it.mountPoint == absolutePath })
+ return // TODO sensible error message handling
+ mounts += Mount(absolutePath, fileSystem)
+ }
+
+ fun unmount(mountPoint: Path.Absolute) {
+ mounts.removeAll { it.mountPoint == mountPoint }
+ }
+
+ fun <T> findMountFor(
+ workingDirectory: Path.Absolute,
+ path: Path,
+ operation: FileSystem.(relativePath: Path) -> T
+ ): T {
+ val absolutPath = path.toAbsolutePath(workingDirectory)
+ val mount = mounts.filter {
+ it.mountPoint.parts.zip(absolutPath.parts).all { (a, b) -> a == b }
+ }.maxByOrNull { it.mountPoint.parts.size } ?: throw IllegalStateException("No mount present")
+ return mount.fileSystem.operation(
+ Path.Absolute(
+ absolutPath.parts.subList(
+ mount.mountPoint.parts.size,
+ absolutPath.parts.size
+ )
+ ) // TODO: unangenehm
+ )
+ }
+
+ fun findINode(absolutePath: Path.Absolute): INode {
+ val mount = mounts.filter {
+ it.mountPoint.parts.zip(absolutePath.parts).all { (a, b) -> a == b }
+ }.maxByOrNull { it.mountPoint.parts.size } ?: throw IllegalStateException("No mount present")
+ val iNode = mount.fileSystem.getINode(absolutePath.relativize(mount.mountPoint))
+ return when (iNode) {
+ is INodeResult.File -> iNode.op
+ is INodeResult.ResolveAgain -> findINode(absolutePath.resolve(iNode.relativeToOriginal))
+ }
+ }
+
+ fun read(workingDirectory: Path.Absolute, path: Path): ReadResult =
+ findMountFor(workingDirectory, path) { read(it) }
+
+ fun write(workingDirectory: Path.Absolute, path: Path, data: ByteArray): Unit =
+ findMountFor(workingDirectory, path) { write(it, data) }
+
+ fun stat(workingDirectory: Path.Absolute, path: Path): Unit =
+ findMountFor(workingDirectory, path) { stat(it) }
+}
+
+interface INode {
+ val fs: FileSystem
+}
+
+sealed interface INodeResult {
+ class File(val op: INode) : INodeResult
+ class ResolveAgain(val relativeToOriginal: Path): INodeResult
+}
+
+interface FileSystem {
+ fun getINode(relativePath: Path.Relative): INodeResult
+ fun read(relativePath: Path): ReadResult
+ fun write(path: Path, data: ByteArray): Unit // Write result
+ fun stat(path: Path): Unit // TODO Stat result
+}
+
+sealed class ReadResult {
+ class Success(val text: String) : ReadResult()
+ object NotFound : ReadResult()
+ object NoAccess : ReadResult()
+}
+
+data class Mount(
+ val mountPoint: Path.Absolute,
+ val fileSystem: FileSystem
+)
+
+data class Stat(
+ val exists: Boolean,
+ var owner: User,
+ val created: Long,
+ val edited: Long,
+ val size: Long
+)