mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
TEVD disk drive wip
This commit is contained in:
4
.idea/libraries/TerranVirtualDisk.xml
generated
4
.idea/libraries/TerranVirtualDisk.xml
generated
@@ -4,6 +4,8 @@
|
||||
<root url="jar://$PROJECT_DIR$/lib/TerranVirtualDisk.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/TerranVirtualDisk-src.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
Binary file not shown.
Binary file not shown.
@@ -462,10 +462,10 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath:
|
||||
|
||||
private fun getSizeStr(): String {
|
||||
val sb = StringBuilder()
|
||||
val isRoot = (file.absolutePath == rootPath.absolutePath)
|
||||
// val isRoot = (file.absolutePath == rootPath.absolutePath)
|
||||
|
||||
if (file.isFile) sb.append(file.length())
|
||||
else sb.append(file.listFiles().size)
|
||||
else sb.append(file.listFiles()!!.size)
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
@@ -2,28 +2,30 @@ package net.torvald.tsvm.peripheral
|
||||
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil
|
||||
import net.torvald.tsvm.VM
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2022-12-15.
|
||||
*/
|
||||
class TevdDiskDrive(private val vm: VM, private val theRootPath: String) : BlockTransferInterface(false, true) {
|
||||
class TevdDiskDrive(private val vm: VM, private val theTevdPath: String, val diskUUIDstr: String) : BlockTransferInterface(false, true) {
|
||||
|
||||
|
||||
private val DBGPRN = true
|
||||
|
||||
val diskID: UUID = UUID.fromString(diskUUIDstr)
|
||||
|
||||
|
||||
private fun printdbg(msg: Any) {
|
||||
if (DBGPRN) println("[TestDiskDrive] $msg")
|
||||
if (DBGPRN) println("[TevDiskDrive] $msg")
|
||||
}
|
||||
|
||||
private val rootPath = File(theRootPath)
|
||||
private val tevdPath = File(theTevdPath)
|
||||
private val DOM = VDUtil.readDiskArchive(tevdPath, charset = VM.CHARSET)
|
||||
|
||||
private var fileOpen = false
|
||||
private var fileOpenMode = -1 // 1: 'W", 2: 'A'
|
||||
private var file = File(rootPath.toURI())
|
||||
private var file: TevdFileDescriptor = TevdFileDescriptor(DOM, "")
|
||||
//private var readModeLength = -1 // always 4096
|
||||
private var writeMode = false
|
||||
private var appendMode = false
|
||||
@@ -37,12 +39,11 @@ class TevdDiskDrive(private val vm: VM, private val theRootPath: String) : Block
|
||||
init {
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
|
||||
if (!rootPath.exists()) {
|
||||
throw FileNotFoundException("Disk file '${theRootPath}' not found")
|
||||
if (!tevdPath.exists()) {
|
||||
throw FileNotFoundException("Disk file '${theTevdPath}' not found")
|
||||
}
|
||||
}
|
||||
|
||||
private val DOM = VDUtil.readDiskArchive(rootPath, charset = VM.CHARSET)
|
||||
|
||||
companion object {
|
||||
/** How often the changes in DOM (disk object model) should be saved to the physical drive when there are changes. Seconds. */
|
||||
@@ -50,7 +51,7 @@ class TevdDiskDrive(private val vm: VM, private val theRootPath: String) : Block
|
||||
}
|
||||
|
||||
fun commit() {
|
||||
VDUtil.dumpToRealMachine(DOM, rootPath)
|
||||
VDUtil.dumpToRealMachine(DOM, tevdPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -91,9 +92,378 @@ class TevdDiskDrive(private val vm: VM, private val theRootPath: String) : Block
|
||||
private lateinit var writeBuffer: ByteArray
|
||||
private var writeBufferUsage = 0
|
||||
|
||||
/** Computer's attempt to startSend() will result in calling this very function.
|
||||
* In such cases, `inputData` will be the message the computer sends.
|
||||
*
|
||||
* Disk drive must create desired side effects in accordance with the input message.
|
||||
*/
|
||||
override fun writeoutImpl(inputData: ByteArray) {
|
||||
TODO("Not yet implemented")
|
||||
if (writeMode || appendMode) {
|
||||
//println("[DiskDrive] writeout with inputdata length of ${inputData.size}")
|
||||
//println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}")
|
||||
|
||||
if (!fileOpen) throw InternalError("File is not open but the drive is in write mode")
|
||||
|
||||
System.arraycopy(inputData, 0, writeBuffer, writeBufferUsage, minOf(writeModeLength - writeBufferUsage, inputData.size, BLOCK_SIZE))
|
||||
writeBufferUsage += inputData.size
|
||||
|
||||
if (writeBufferUsage >= writeModeLength) {
|
||||
// commit to the disk
|
||||
if (appendMode)
|
||||
file.appendBytes(writeBuffer)
|
||||
else if (writeMode)
|
||||
file.writeBytes(writeBuffer)
|
||||
|
||||
writeMode = false
|
||||
appendMode = false
|
||||
}
|
||||
}
|
||||
else {
|
||||
val inputString = inputData.trimNull().toString(VM.CHARSET)
|
||||
|
||||
if (inputString.startsWith("DEVRST\u0017")) {
|
||||
printdbg("Device Reset")
|
||||
//readModeLength = -1
|
||||
fileOpen = false
|
||||
fileOpenMode = -1
|
||||
file = TevdFileDescriptor(DOM, "")
|
||||
blockSendCount = 0
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
writeMode = false
|
||||
writeModeLength = -1
|
||||
}
|
||||
else if (inputString.startsWith("DEVSTU\u0017"))
|
||||
recipient?.writeout(
|
||||
TestDiskDrive.composePositiveAns(
|
||||
"${statusCode.toChar()}",
|
||||
TestDiskDrive.errorMsgs[statusCode]
|
||||
)
|
||||
)
|
||||
else if (inputString.startsWith("DEVTYP\u0017"))
|
||||
recipient?.writeout(TestDiskDrive.composePositiveAns("STOR"))
|
||||
else if (inputString.startsWith("DEVNAM\u0017"))
|
||||
recipient?.writeout(TestDiskDrive.composePositiveAns("Testtec Virtual Disk Drive"))
|
||||
else if (inputString.startsWith("OPENR\"") || inputString.startsWith("OPENW\"") || inputString.startsWith("OPENA\"")) {
|
||||
if (fileOpen) {
|
||||
|
||||
statusCode = TestDiskDrive.STATE_CODE_FILE_ALREADY_OPENED
|
||||
return
|
||||
}
|
||||
|
||||
printdbg("msg: $inputString, lastIndex: ${inputString.lastIndex}")
|
||||
|
||||
val openMode = inputString[4]
|
||||
printdbg("open mode: $openMode")
|
||||
// split inputstring into path and optional drive-number
|
||||
|
||||
// get position of latest delimeter (comma)
|
||||
var commaIndex = inputString.lastIndex
|
||||
while (commaIndex > 6) {
|
||||
if (inputString[commaIndex] == ',') break; commaIndex -= 1
|
||||
}
|
||||
// sanity check if path is actually enclosed with double-quote
|
||||
if (commaIndex != 6 && inputString[commaIndex - 1] != '"') {
|
||||
statusCode = TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND
|
||||
return
|
||||
}
|
||||
val pathStr = inputString.substring(6, if (commaIndex == 6) inputString.lastIndex else commaIndex - 1)
|
||||
val driveNum =
|
||||
if (commaIndex == 6) null else inputString.substring(commaIndex + 1, inputString.length).toInt()
|
||||
val filePath = filterSuperRoot(sanitisePath(pathStr))
|
||||
|
||||
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
|
||||
|
||||
file = TevdFileDescriptor(DOM, filePath)
|
||||
printdbg("file path: ${file.canonicalPath}, drive num: $driveNum")
|
||||
|
||||
if (openMode == 'R' && !file.exists()) {
|
||||
printdbg("! file not found")
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_SUCH_FILE_EXISTS
|
||||
return
|
||||
}
|
||||
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
fileOpen = true
|
||||
fileOpenMode = when (openMode) {
|
||||
'W' -> 1
|
||||
'A' -> 2
|
||||
else -> -1
|
||||
}
|
||||
blockSendCount = 0
|
||||
}
|
||||
else if (inputString.startsWith("DELETE")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
try {
|
||||
file.delete()
|
||||
}
|
||||
catch (e: SecurityException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
return
|
||||
}
|
||||
catch (e1: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("LISTFILES")) {
|
||||
// TODO temporary behaviour to ignore any arguments
|
||||
resetBuf()
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
try {
|
||||
if (file.isDirectory) {
|
||||
file.listFiles()!!.forEachIndexed { index, lsfile ->
|
||||
if (index != 0) messageComposeBuffer.write(0x1E)
|
||||
messageComposeBuffer.write(if (lsfile.isDirectory) 0x11 else 0x12)
|
||||
messageComposeBuffer.write(lsfile.name.toByteArray(VM.CHARSET))
|
||||
}
|
||||
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
else {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NOT_A_DIRECTORY
|
||||
return
|
||||
}
|
||||
}
|
||||
catch (e: SecurityException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
return
|
||||
}
|
||||
catch (e1: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("GETLEN")) {
|
||||
// TODO temporary behaviour to ignore any arguments
|
||||
resetBuf()
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
|
||||
messageComposeBuffer.write(getSizeStr().toByteArray(VM.CHARSET))
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
else if (inputString.startsWith("LIST")) {
|
||||
// TODO temporary behaviour to ignore any arguments
|
||||
resetBuf()
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
|
||||
messageComposeBuffer.write(getReadableLs().toByteArray(VM.CHARSET))
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
else if (inputString.startsWith("CLOSE")) {
|
||||
fileOpen = false
|
||||
fileOpenMode = -1
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
else if (inputString.startsWith("READ")) {
|
||||
//readModeLength = inputString.substring(4 until inputString.length).toInt()
|
||||
|
||||
resetBuf()
|
||||
if (file.isFile) {
|
||||
try {
|
||||
messageComposeBuffer.write(file.readBytes())
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
catch (e: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
}
|
||||
}
|
||||
else {
|
||||
statusCode = TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("LOADBOOT")) {
|
||||
var commaIndex = 0
|
||||
while (commaIndex < inputString.length) {
|
||||
if (inputString[commaIndex] == ',') break
|
||||
commaIndex += 1
|
||||
}
|
||||
val driveNum = if (commaIndex >= inputString.length) null else commaIndex
|
||||
|
||||
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
|
||||
|
||||
val bootFile = TevdFileDescriptor(DOM, "!BOOTSEC")
|
||||
|
||||
if (!bootFile.exists()) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_SUCH_FILE_EXISTS
|
||||
return
|
||||
}
|
||||
try {
|
||||
val retMsg = bootFile.getHeadBytes(BLOCK_SIZE)
|
||||
recipient?.writeout(retMsg)
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
catch (e: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
return
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("MKDIR")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
if (fileOpenMode < 1) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
return
|
||||
}
|
||||
try {
|
||||
val status = file.mkdir()
|
||||
statusCode = if (status) 0 else 1
|
||||
}
|
||||
catch (e: SecurityException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("MKFILE")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
if (fileOpenMode < 1) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
return
|
||||
}
|
||||
try {
|
||||
val f1 = file.createNewFile()
|
||||
statusCode = if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED
|
||||
return
|
||||
}
|
||||
catch (e: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
}
|
||||
catch (e1: SecurityException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("TOUCH")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
if (fileOpenMode < 1) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
return
|
||||
}
|
||||
try {
|
||||
val f1 = file.setLastModified(vm.worldInterface.currentTimeInMills())
|
||||
statusCode = if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED
|
||||
return
|
||||
}
|
||||
catch (e: IOException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR
|
||||
}
|
||||
catch (e1: SecurityException) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR
|
||||
}
|
||||
}
|
||||
else if (inputString.startsWith("WRITE")) {
|
||||
if (!fileOpen) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_NO_FILE_OPENED
|
||||
return
|
||||
}
|
||||
if (fileOpenMode < 0) {
|
||||
statusCode = TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED
|
||||
return
|
||||
}
|
||||
if (fileOpenMode == 1) { writeMode = true; appendMode = false }
|
||||
else if (fileOpenMode == 2) { writeMode = false; appendMode = true }
|
||||
writeModeLength = inputString.substring(5, inputString.length).toInt()
|
||||
writeBuffer = ByteArray(writeModeLength)
|
||||
writeBufferUsage = 0
|
||||
statusCode = TestDiskDrive.STATE_CODE_STANDBY
|
||||
}
|
||||
else
|
||||
statusCode = TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun sanitisePath(s: String) = s.replace('\\','/').replace(Regex("""\?<>:\*\|"""),"-")
|
||||
|
||||
// applies a "cap" if the path attemps to access parent directory of the root
|
||||
private fun filterSuperRoot(path: String): String {
|
||||
if (path.isEmpty()) return path
|
||||
|
||||
var parentCount = 0
|
||||
val paths = path.split('/')
|
||||
val newPaths = ArrayList<String>()
|
||||
paths.forEach {
|
||||
if (it.isBlank() || it.isEmpty()) {
|
||||
/*do nothing*/
|
||||
}
|
||||
else if (it == "..") {
|
||||
parentCount -= -1
|
||||
}
|
||||
else if (it != ".") {
|
||||
parentCount += 1
|
||||
}
|
||||
|
||||
if (parentCount < -1) parentCount = -1
|
||||
|
||||
if (parentCount >= 0) {
|
||||
newPaths.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
return newPaths.joinToString("/")
|
||||
}
|
||||
|
||||
private fun getReadableLs(): String {
|
||||
val sb = StringBuilder()
|
||||
val isRoot = (file.entryID == 0)
|
||||
|
||||
if (file.isFile) sb.append(file.name)
|
||||
else {
|
||||
sb.append("Current directory: ")
|
||||
sb.append(if (isRoot) "(root)" else file.path)
|
||||
sb.append('\n')
|
||||
|
||||
sb.append(".\n")
|
||||
if (isRoot) sb.append("..\n")
|
||||
// actual entries
|
||||
file.listFiles()!!.forEach {
|
||||
var filenameLen = it.name.length
|
||||
|
||||
sb.append(it.name)
|
||||
|
||||
if (it.isDirectory) {
|
||||
sb.append("/")
|
||||
filenameLen += 1
|
||||
}
|
||||
|
||||
sb.append(" ".repeat(40 - filenameLen))
|
||||
|
||||
if (it.isFile) {
|
||||
sb.append("${it.length()} B")
|
||||
}
|
||||
|
||||
sb.append('\n')
|
||||
}
|
||||
}
|
||||
|
||||
return if (sb.last() == '\n') sb.substring(0, sb.lastIndex) else sb.toString()
|
||||
}
|
||||
|
||||
private fun getSizeStr(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
if (file.isFile) sb.append(file.length())
|
||||
else sb.append(file.listFiles()!!.size)
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
}
|
||||
125
tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt
Normal file
125
tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt
Normal file
@@ -0,0 +1,125 @@
|
||||
package net.torvald.tsvm.peripheral
|
||||
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
|
||||
import net.torvald.tsvm.VM
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2022-12-17.
|
||||
*/
|
||||
class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
|
||||
|
||||
val path = _pathstr.replace('/', '\\')
|
||||
val vdPath = VDUtil.VDPath(path, VM.CHARSET)
|
||||
|
||||
val entryID: EntryID?
|
||||
get() = VDUtil.getFile(DOM, vdPath)?.entryID
|
||||
|
||||
val canonicalPath: String
|
||||
get() = path
|
||||
val name: String
|
||||
get() = path.substring(path.lastIndexOf('\\') + 1)
|
||||
val nameBytes: ByteArray
|
||||
get() = name.toByteArray(VM.CHARSET)
|
||||
|
||||
|
||||
val isFile: Boolean
|
||||
get() = TODO()
|
||||
|
||||
val isDirectory: Boolean
|
||||
get() = TODO()
|
||||
|
||||
|
||||
private var fileContent: EntryFile? = null
|
||||
|
||||
fun appendBytes(bytes: ByteArray) {
|
||||
fileContent?.getContent()?.appendBytes(bytes)
|
||||
}
|
||||
|
||||
fun writeBytes(bytes: ByteArray) {
|
||||
fileContent?.replaceContent(ByteArray64.fromByteArray(bytes))
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length how many bytes to read
|
||||
* @return actual bytes read, the size may be less than `length` if the actual file size is smaller
|
||||
*/
|
||||
fun getHeadBytes64(length: Long): ByteArray64 {
|
||||
if (fileContent == null) throw IOException("No such file or not a file")
|
||||
return fileContent!!.getContent().sliceArray64(0L until length)
|
||||
}
|
||||
/**
|
||||
* @param length how many bytes to read
|
||||
* @return actual bytes read, the size may be less than `length` if the actual file size is smaller
|
||||
*/
|
||||
fun getHeadBytes(length: Int): ByteArray {
|
||||
if (fileContent == null) throw IOException("No such file or not a file")
|
||||
return fileContent!!.getContent().sliceArray(0 until length)
|
||||
}
|
||||
|
||||
fun exists(): Boolean {
|
||||
return VDUtil.getFile(DOM, vdPath) != null
|
||||
}
|
||||
|
||||
fun delete() {
|
||||
fileContent = null
|
||||
}
|
||||
|
||||
fun length(): Long {
|
||||
return if (isFile) fileContent?.getSizePure() ?: 0L
|
||||
else -1L
|
||||
}
|
||||
|
||||
fun listFiles(): Array<TevdFileDescriptor>? {
|
||||
if (isFile) return null
|
||||
|
||||
entryID.let {
|
||||
if (it == null) return null
|
||||
|
||||
return VDUtil.getDirectoryEntries(DOM, it).map {
|
||||
TevdFileDescriptor(DOM, path + '\\' + it.getFilenameString(VM.CHARSET))
|
||||
}.toTypedArray()
|
||||
}
|
||||
}
|
||||
|
||||
fun readBytes(): ByteArray {
|
||||
if (isDirectory) throw RuntimeException("Not a file")
|
||||
if (!exists()) throw IOException("File not found")
|
||||
return VDUtil.getAsNormalFile(DOM, vdPath).getContent().toByteArray()
|
||||
}
|
||||
|
||||
fun mkdir(): Boolean {
|
||||
return try {
|
||||
VDUtil.addDir(DOM, vdPath.getParent(), nameBytes)
|
||||
true
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun createNewFile(): Boolean {
|
||||
fileContent = EntryFile(ByteArray64())
|
||||
val time_t = System.currentTimeMillis() / 1000
|
||||
val newFile = DiskEntry(-1, -1, nameBytes, time_t, time_t, fileContent!!)
|
||||
return try {
|
||||
VDUtil.addFile(DOM, vdPath.getParent(), newFile)
|
||||
true
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun setLastModified(newTime_t: Long): Boolean {
|
||||
return VDUtil.getFile(DOM, vdPath).let {
|
||||
if (it != null) {
|
||||
it.modificationDate = newTime_t
|
||||
true
|
||||
}
|
||||
else false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user