diff options
author | nea <romangraef@gmail.com> | 2021-08-20 15:33:32 +0200 |
---|---|---|
committer | nea <romangraef@gmail.com> | 2021-08-20 15:33:58 +0200 |
commit | 5042498c8fe12751c1b6560ae1fde07e7cd78259 (patch) | |
tree | 688aa93978ffffd0b15c639768fdad6f17609bdd /src/jsMain/kotlin/io | |
parent | 65a6ffeb6761994d4d69011c87f23fe074f7a1f7 (diff) | |
download | webos-5042498c8fe12751c1b6560ae1fde07e7cd78259.tar.gz webos-5042498c8fe12751c1b6560ae1fde07e7cd78259.tar.bz2 webos-5042498c8fe12751c1b6560ae1fde07e7cd78259.zip |
Diffstat (limited to 'src/jsMain/kotlin/io')
-rw-r--r-- | src/jsMain/kotlin/io/Path.kt | 78 | ||||
-rw-r--r-- | src/jsMain/kotlin/io/files.kt | 203 |
2 files changed, 0 insertions, 281 deletions
diff --git a/src/jsMain/kotlin/io/Path.kt b/src/jsMain/kotlin/io/Path.kt deleted file mode 100644 index 241c559..0000000 --- a/src/jsMain/kotlin/io/Path.kt +++ /dev/null @@ -1,78 +0,0 @@ -package io - -sealed class Path { - abstract val parts: List<String> - fun toAbsolutePath(relativeTo: Absolute): Absolute { - return relativeTo.resolve(this) - } - - abstract fun resolve(path: Path): Path - - abstract val stringPath: String - - companion object { - val root = Absolute(listOf()) - - fun ofShell(string: String, userHome: Absolute): Path = - ofShell(string.split("/"), userHome) - - fun ofShell(vararg parts: String, userHome: Absolute): Path = - ofShell(parts.toList(), userHome) - - fun of(vararg parts: String): Path = - of(parts.toList()) - - fun of(string: String): Path = - of(string.split("/")) - - fun ofShell(parts: List<String>, userHome: Absolute): Path { - if (parts.firstOrNull() == "~") - return userHome.resolve(Relative(parts.subList(1, parts.size).filter { it.isNotEmpty() })) - return of(parts) - } - - fun of(parts: List<String>): Path { - if (parts.isEmpty()) - return root - if (parts[0] == "") // Starts with a / - return Absolute(parts.subList(1, parts.size).filter { it.isNotEmpty() }) - return Relative(parts.filter { it.isNotEmpty() }) - } - } - - data class Relative internal constructor(override val parts: List<String>) : Path() { - override fun resolve(path: Path): Path { - if (path is Absolute) return path - return Relative(this.parts + path.parts) - } - - override val stringPath: String get() = parts.joinToString("/") - } - - data class Absolute internal constructor(override val parts: List<String>) : Path() { - override fun resolve(path: Path): Absolute { - if (path is Absolute) return path - return Absolute(this.parts + path.parts) - } - - override val stringPath: String get() = "/" + parts.joinToString("/") - - fun relativize(path: Path): Relative = when (path) { - is Relative -> path - is Absolute -> { - var idx = 0 - while (idx < path.parts.size && idx < parts.size && path.parts[idx] == parts[idx]) { - idx++ - } - val returns = if (idx < parts.size) { - parts.size - idx - } else { - 0 - } - Relative(List(returns) { ".." } + path.parts.subList(idx, path.parts.size)) - } - } - } - - override fun toString(): String = "Path($stringPath)" -} diff --git a/src/jsMain/kotlin/io/files.kt b/src/jsMain/kotlin/io/files.kt deleted file mode 100644 index 4c53c4e..0000000 --- a/src/jsMain/kotlin/io/files.kt +++ /dev/null @@ -1,203 +0,0 @@ -package io - -import User - -sealed interface CreateFileResult { - object Created : CreateFileResult - sealed interface Failure : CreateFileResult { - object NoPermission : Failure - object NoParent : Failure - object AlreadyExists : Failure - } -} - -sealed interface WriteFileResult { - object Written : WriteFileResult - sealed interface Failure : WriteFileResult { - object NoPermission : Failure - object NotAFile : Failure - data class NotEnoughSpace( - val dataSize: Long, - val spaceLeft: Long - ) : Failure - } -} - -sealed interface ReadFileResult { - data class Read(val data: ByteArray) : ReadFileResult { - override fun equals(other: Any?): Boolean = (other as? Read)?.let { it.data.contentEquals(this.data) } ?: false - - override fun hashCode(): Int { - return data.contentHashCode() - } - } - - sealed interface Failure : ReadFileResult { - object NoPermission : Failure - object NotAFile : Failure - } -} - -sealed interface DeleteFileResult { - sealed interface Failure : DeleteFileResult { - object NoPermission : Failure - object NotAFile : Failure - } - - object Deleted : DeleteFileResult -} - -interface FileService<INode> { - fun getPath(iNode: INode): Path.Absolute - fun getINode(path: Path.Absolute): INode - fun createFile(iNode: INode, user: User): CreateFileResult - fun createSymlink(iNode: INode, user: User, path: Path): CreateFileResult - fun createDirectory(iNode: INode, user: User): CreateFileResult - fun writeToFile(iNode: INode, user: User, data: ByteArray): WriteFileResult - fun readFromFile(iNode: INode, user: User): ReadFileResult - fun deleteFile(iNode: INode, user: User): DeleteFileResult - fun exists(iNode: INode): Boolean - fun isFile(iNode: INode): Boolean - fun isDirectory(iNode: INode): Boolean - fun isSymlink(iNode: INode): Boolean - fun resolve(iNode: INode, fragment: String): INode - fun resolve(iNode: INode, path: Path.Relative): INode - fun changePermissions(iNode: INode, user: User, permissionUpdate: Map<User, Permission>) -} - -data class Permission( - val read: Boolean, - val write: Boolean, - val execute: Boolean -) { - companion object { - val default get() = Permission(read = true, write = true, execute = false) - } -} - -sealed interface PrimitiveStorageBlob { - val permissions: MutableMap<User, Permission> - - class File(var data: ByteArray, override val permissions: MutableMap<User, Permission>) : PrimitiveStorageBlob - class Symlink(val path: Path, override val permissions: MutableMap<User, Permission>) : PrimitiveStorageBlob - class Directory(override val permissions: MutableMap<User, Permission>) : PrimitiveStorageBlob -} - -data class PrimitiveINode internal constructor(internal val internalPath: String) -class PrimitiveFileService : FileService<PrimitiveINode> { - private val storageBlobs = mutableMapOf<String, PrimitiveStorageBlob>( - "/" to PrimitiveStorageBlob.Directory(mutableMapOf()) - ) - - override fun getPath(iNode: PrimitiveINode): Path.Absolute = Path.of(iNode.internalPath) as Path.Absolute - - override fun getINode(path: Path.Absolute): PrimitiveINode { - return resolve(PrimitiveINode("/"), Path.Relative(path.parts)) - } - - override fun resolve(iNode: PrimitiveINode, fragment: String): PrimitiveINode { - if (fragment == "..") { - val up = iNode.internalPath.substringBeforeLast('/') - if (up.isEmpty()) return PrimitiveINode("/") - return PrimitiveINode(up) - } - if (fragment.isEmpty() || fragment == ".") - return iNode - val blob = storageBlobs[iNode.internalPath] - return when (blob) { - is PrimitiveStorageBlob.Symlink -> { - when (blob.path) { - is Path.Absolute -> getINode(blob.path) - is Path.Relative -> resolve(resolve(iNode, ".."), blob.path) - } - } - else -> { - PrimitiveINode(iNode.internalPath + "/" + fragment) - } - } - } - - override fun resolve(iNode: PrimitiveINode, path: Path.Relative): PrimitiveINode = - path.parts.fold(iNode) { node, fragment -> resolve(node, fragment) } - - private fun getStorageBlob(iNode: PrimitiveINode): PrimitiveStorageBlob? = storageBlobs[iNode.internalPath] - - override fun writeToFile(iNode: PrimitiveINode, user: User, data: ByteArray): WriteFileResult { - val file = getStorageBlob(iNode) as? PrimitiveStorageBlob.File ?: return WriteFileResult.Failure.NotAFile - if (!hasPermission(user, file) { read }) - return WriteFileResult.Failure.NoPermission - file.data = data - return WriteFileResult.Written - } - - override fun readFromFile(iNode: PrimitiveINode, user: User): ReadFileResult { - val file = getStorageBlob(iNode) as? PrimitiveStorageBlob.File ?: return ReadFileResult.Failure.NotAFile - if (!hasPermission(user, file) { read }) - return ReadFileResult.Failure.NoPermission - return ReadFileResult.Read(file.data) - } - - override fun exists(iNode: PrimitiveINode): Boolean = - getStorageBlob(iNode) != null - - override fun isFile(iNode: PrimitiveINode): Boolean = - getStorageBlob(iNode) is PrimitiveStorageBlob.File - - override fun isDirectory(iNode: PrimitiveINode): Boolean = - getStorageBlob(iNode) is PrimitiveStorageBlob.Directory - - override fun isSymlink(iNode: PrimitiveINode): Boolean = - getStorageBlob(iNode) is PrimitiveStorageBlob.Symlink - - override fun changePermissions(iNode: PrimitiveINode, user: User, permissionUpdate: Map<User, Permission>) { - val file = getStorageBlob(iNode) ?: return // TODO Results - if (!hasPermission(user, file) { write }) - return // TODO Results - file.permissions.putAll(permissionUpdate) - return // TODO Results - } - - override fun deleteFile(iNode: PrimitiveINode, user: User): DeleteFileResult { - val file = getStorageBlob(iNode) ?: return DeleteFileResult.Failure.NotAFile - if (!hasPermission(user, file) { write }) - return DeleteFileResult.Failure.NoPermission - (storageBlobs.keys.filter { it.startsWith(iNode.internalPath + "/") } + listOf(iNode.internalPath)).forEach { - storageBlobs.remove(it) - } - return DeleteFileResult.Deleted - } - - private fun hasPermission(user: User, blob: PrimitiveStorageBlob, check: Permission.() -> Boolean): Boolean { - return user.isRoot || blob.permissions[user]?.let(check) ?: false - } - - private fun checkCreationPreconditions(iNode: PrimitiveINode, user: User): CreateFileResult? { - if (storageBlobs.containsKey(iNode.internalPath)) return CreateFileResult.Failure.AlreadyExists - val parent = getStorageBlob(resolve(iNode, "..")) - if (parent !is PrimitiveStorageBlob.Directory) return CreateFileResult.Failure.NoParent - if (!hasPermission(user, parent) { write }) return CreateFileResult.Failure.NoPermission - return null - } - - override fun createFile(iNode: PrimitiveINode, user: User): CreateFileResult { - val preconditions = checkCreationPreconditions(iNode, user) - if (preconditions != null) return preconditions - storageBlobs[iNode.internalPath] = PrimitiveStorageBlob.File(byteArrayOf(), mutableMapOf(user to Permission.default)) - return CreateFileResult.Created - } - - override fun createSymlink(iNode: PrimitiveINode, user: User, path: Path): CreateFileResult { - val preconditions = checkCreationPreconditions(iNode, user) - if (preconditions != null) return preconditions - storageBlobs[iNode.internalPath] = PrimitiveStorageBlob.Symlink(path, mutableMapOf(user to Permission.default)) - return CreateFileResult.Created - } - - override fun createDirectory(iNode: PrimitiveINode, user: User): CreateFileResult { - val preconditions = checkCreationPreconditions(iNode, user) - if (preconditions != null) return preconditions - storageBlobs[iNode.internalPath] = PrimitiveStorageBlob.Directory(mutableMapOf(user to Permission.default)) - return CreateFileResult.Created - } - -} |