clustered test

This commit is contained in:
minjaesong
2023-05-30 16:10:35 +09:00
parent c818cdd02e
commit 6bca526f84
4 changed files with 181 additions and 267 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,61 +1,95 @@
package net.torvald.tsvm.peripheral
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil.checkReadOnly
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile
import net.torvald.tsvm.VM
import java.io.*
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
/**
* Created by minjaesong on 2022-12-15.
* @param driveNum 0 for COM drive number 1, but the file path will still be zero-based
*/
class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val theTevdPath: String, val diskUUIDstr: String) : BlockTransferInterface(false, true) {
class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath: String) : BlockTransferInterface(false, true) {
companion object {
const val STATE_CODE_STANDBY = 0
const val STATE_CODE_OPERATION_FAILED = 1
const val STATE_CODE_ILLEGAL_COMMAND = 128
const val STATE_CODE_NO_SUCH_FILE_EXISTS = 129
const val STATE_CODE_FILE_ALREADY_OPENED = 130
const val STATE_CODE_OPERATION_NOT_PERMITTED = 131
const val STATE_CODE_READ_ONLY = 132
const val STATE_CODE_NOT_A_FILE = 133
const val STATE_CODE_NOT_A_DIRECTORY = 134
const val STATE_CODE_NO_FILE_OPENED = 135
const val STATE_CODE_SYSTEM_IO_ERROR = 192
const val STATE_CODE_SYSTEM_SECURITY_ERROR = 193
private val DBGPRN = true
val errorMsgs = Array(256) { "" }
val diskID: UUID = UUID.fromString(diskUUIDstr)
init {
errorMsgs[STATE_CODE_STANDBY] = "READY"
errorMsgs[STATE_CODE_OPERATION_FAILED] = "OPERATION FAILED"
errorMsgs[STATE_CODE_ILLEGAL_COMMAND] = "SYNTAX ERROR"
errorMsgs[STATE_CODE_NO_SUCH_FILE_EXISTS] = "NO SUCH FILE EXISTS"
errorMsgs[STATE_CODE_FILE_ALREADY_OPENED] = "FILE ALREADY OPENED"
errorMsgs[STATE_CODE_SYSTEM_IO_ERROR] = "IO ERROR ON SIMULATED DRIVE"
errorMsgs[STATE_CODE_SYSTEM_SECURITY_ERROR] = "SECURITY ERROR ON SIMULATED DRIVE"
errorMsgs[STATE_CODE_OPERATION_NOT_PERMITTED] = "OPERATION NOT PERMITTED"
errorMsgs[STATE_CODE_NOT_A_FILE] = "NOT A FILE"
errorMsgs[STATE_CODE_NOT_A_DIRECTORY] = "NOT A DIRECTORY"
errorMsgs[STATE_CODE_NO_FILE_OPENED] = "NO FILE OPENED"
}
fun composePositiveAns(vararg msg: String): ByteArray {
val sb = ArrayList<Byte>()
sb.addAll(msg[0].toByteArray().toTypedArray())
for (k in 1 until msg.size) {
sb.add(UNIT_SEP)
sb.addAll(msg[k].toByteArray().toTypedArray())
}
sb.add(END_OF_SEND_BLOCK)
return sb.toByteArray()
}
}
private val DBGPRN = false
private fun printdbg(msg: Any) {
if (DBGPRN) println("[TevDiskDrive] $msg")
}
private val tevdPath = File(theTevdPath)
private val DOM = PartialDOM(tevdPath, VM.CHARSET)//VDUtil.readDiskArchive(tevdPath, charset = VM.CHARSET)
private val DOM = ClusteredFormatDOM(RandomAccessFile(theTevdPath, "rw"))
private var fileOpen = false
private var fileOpenMode = -1 // 1: 'W", 2: 'A'
private var file: TevdFileDescriptor = TevdFileDescriptor(DOM, "")
private var file = Clustfile(DOM, "")
//private var readModeLength = -1 // always 4096
private val writeMode
get() = fileOpenMode == 1
private val appendMode
get() = fileOpenMode == 2
private var writeMode = false
private var appendMode = false
private var writeModeLength = -1
private val messageComposeBuffer = ByteArrayOutputStream(BLOCK_SIZE) // always use this and don't alter blockSendBuffer please
private var blockSendBuffer = ByteArray(1)
private var blockSendCount = 0
/*set(value) {
println("[TevDiskDrive] blockSendCount $field -> $value")
val indentation = " ".repeat(this.javaClass.simpleName.length + 4)
Thread.currentThread().stackTrace.forEachIndexed { index, it ->
if (index == 1)
println("[${this.javaClass.simpleName}]> $it")
else if (index in 1..8)
println("$indentation$it")
}
field = value
}*/
init {
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
if (!tevdPath.exists()) {
throw FileNotFoundException("Disk file '${theTevdPath}' not found")
}
}
private var tevdSyncFilteringCounter = 0
fun notifyDiskCommit() {
vm.watchdogs["TEVD_COMMIT"]?.addMessage(arrayOf(tevdPath, DOM))
if (tevdSyncFilteringCounter >= 1) {
vm.watchdogs["TEVD_SYNC"]?.addMessage(arrayOf(tevdPath, DOM))
tevdSyncFilteringCounter = 0
}
tevdSyncFilteringCounter += 1
statusCode.set(STATE_CODE_STANDBY)
}
@@ -84,6 +118,8 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
blockSendBuffer.size % BLOCK_SIZE
else BLOCK_SIZE
// println("blockSendCount = ${blockSendCount}; sendSize = $sendSize; blockSendBuffer.size = ${blockSendBuffer.size}")
recipient.writeout(ByteArray(sendSize) {
blockSendBuffer[blockSendCount * BLOCK_SIZE + it]
})
@@ -102,93 +138,64 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
* Disk drive must create desired side effects in accordance with the input message.
*/
override fun writeoutImpl(inputData: ByteArray) {
printdbg("inputString=${inputData.trimNull().toString(VM.CHARSET)}")
if ((writeMode || appendMode) && writeModeLength >= 0) {
printdbg("writeout with inputdata length of ${inputData.size}")
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")
if (!file.exists()) {
printdbg("File '${file.path}' not exists, creating new...")
val (result, failReason) = file.createNewFile()
if (failReason != null) {
throw failReason
}
else {
printdbg("Operation successful")
}
}
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)
if (appendMode) {
val filesize = file.length()
file.pwrite(writeBuffer, 0, writeBuffer.size, filesize)
}
else if (writeMode)
file.writeBytes(writeBuffer)
fileOpenMode = -1
printdbg("Notifying disk commit (end of write)")
notifyDiskCommit()
writeMode = false
appendMode = false
}
}
else if (fileOpenMode == 17) {
printdbg("File open mode 17")
if (!fileOpen) throw InternalError("Bootloader file is not open but the drive is in boot write mode")
val inputData = if (inputData.size != BLOCK_SIZE) ByteArray(BLOCK_SIZE) { if (it < inputData.size) inputData[it] else 0 }
else inputData
val creationTime = VDUtil.currentUnixtime
DOM.checkReadOnly()
val file = EntryFile(BLOCK_SIZE.toLong())
file.getContent().appendBytes(inputData)
DOM.addNewFile(DiskEntry(1, 1, "TEVDBOOT".toByteArray(VM.CHARSET), creationTime, creationTime, file))
file.writeBytes(inputData)
fileOpenMode = -1
printdbg("Notifying disk commit (end of bootloader write)")
notifyDiskCommit()
}
else {
printdbg("(cmd mode)")
val inputString = inputData.trimNull().toString(VM.CHARSET)
// println("[TevDiskDrive] $inputString")
if (inputString.startsWith("DEVRST\u0017")) {
printdbg("Device Reset")
//readModeLength = -1
fileOpen = false
fileOpenMode = -1
file = TevdFileDescriptor(DOM, "")
file = Clustfile(DOM, "")
blockSendCount = 0
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
writeMode = false
writeModeLength = -1
}
else if (inputString.startsWith("DEVSTU\u0017"))
recipient?.writeout(
TestDiskDrive.composePositiveAns(
"${statusCode.get().toChar()}",
TestDiskDrive.errorMsgs[statusCode.get()]
)
)
recipient?.writeout(composePositiveAns("${statusCode.get().toChar()}", errorMsgs[statusCode.get()]))
else if (inputString.startsWith("DEVTYP\u0017"))
recipient?.writeout(TestDiskDrive.composePositiveAns("STOR"))
recipient?.writeout(composePositiveAns("STOR"))
else if (inputString.startsWith("DEVNAM\u0017"))
recipient?.writeout(TestDiskDrive.composePositiveAns("Generic Disk Drive"))
recipient?.writeout(composePositiveAns("Testtec Virtual Disk Drive"))
else if (inputString.startsWith("OPENR\"") || inputString.startsWith("OPENW\"") || inputString.startsWith("OPENA\"")) {
if (fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_FILE_ALREADY_OPENED)
statusCode.set(STATE_CODE_FILE_ALREADY_OPENED)
return
}
@@ -205,7 +212,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
}
// sanity check if path is actually enclosed with double-quote
if (commaIndex != 6 && inputString[commaIndex - 1] != '"') {
statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND)
statusCode.set(STATE_CODE_ILLEGAL_COMMAND)
return
}
val pathStr = inputString.substring(6, if (commaIndex == 6) inputString.lastIndex else commaIndex - 1)
@@ -215,21 +222,16 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
// 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")
file = Clustfile(DOM, filePath)
printdbg("file path: ${file.path}, drive num: $driveNum")
if (openMode == 'R' && !file.exists()) {
printdbg("! file not found")
statusCode.set(TestDiskDrive.STATE_CODE_NO_SUCH_FILE_EXISTS)
return
}
else if (DOM.isReadOnly && (openMode == 'W' || openMode == 'A')) {
printdbg("! disk is read-only")
statusCode.set(TestDiskDrive.STATE_CODE_READ_ONLY)
statusCode.set(STATE_CODE_NO_SUCH_FILE_EXISTS)
return
}
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
fileOpen = true
fileOpenMode = when (openMode) {
'W' -> 1
@@ -240,24 +242,18 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
}
else if (inputString.startsWith("DELETE")) {
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
try {
val (successful, whyFailed) = file.delete()
if (!successful) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_FAILED)
return
}
printdbg("Notifying disk commit (file deleted)")
notifyDiskCommit()
file.delete()
}
catch (e: SecurityException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR)
statusCode.set(STATE_CODE_SYSTEM_SECURITY_ERROR)
return
}
catch (e1: IOException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
return
}
}
@@ -265,7 +261,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
// TODO temporary behaviour to ignore any arguments
resetBuf()
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
try {
@@ -276,19 +272,19 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
messageComposeBuffer.write(lsfile.name.toByteArray(VM.CHARSET))
}
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
else {
statusCode.set(TestDiskDrive.STATE_CODE_NOT_A_DIRECTORY)
statusCode.set(STATE_CODE_NOT_A_DIRECTORY)
return
}
}
catch (e: SecurityException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR)
statusCode.set(STATE_CODE_SYSTEM_SECURITY_ERROR)
return
}
catch (e1: IOException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
return
}
}
@@ -296,28 +292,28 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
// TODO temporary behaviour to ignore any arguments
resetBuf()
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
messageComposeBuffer.write(getSizeStr().toByteArray(VM.CHARSET))
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
else if (inputString.startsWith("LIST")) {
// TODO temporary behaviour to ignore any arguments
resetBuf()
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
messageComposeBuffer.write(getReadableLs().toByteArray(VM.CHARSET))
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
else if (inputString.startsWith("CLOSE")) {
fileOpen = false
fileOpenMode = -1
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
else if (inputString.startsWith("READ")) {
//readModeLength = inputString.substring(4 until inputString.length).toInt()
@@ -326,14 +322,14 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
if (file.isFile) {
try {
messageComposeBuffer.write(file.readBytes())
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
catch (e: IOException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
}
}
else {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED)
statusCode.set(STATE_CODE_OPERATION_NOT_PERMITTED)
return
}
}
@@ -347,13 +343,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
if (DOM.isReadOnly) {
printdbg("! disk is read-only")
statusCode.set(TestDiskDrive.STATE_CODE_READ_ONLY)
return
}
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
fileOpen = true
fileOpenMode = 17
blockSendCount = 0
@@ -368,163 +358,146 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
val bootFile = DOM.requestFile(1)
printdbg("bootFile = $bootFile, ID: 1, exists = ${bootFile != null}")
if (bootFile == null) {
printdbg("bootfile not exists!")
statusCode.set(TestDiskDrive.STATE_CODE_NO_SUCH_FILE_EXISTS)
return
}
try {
val retMsg = (bootFile.contents as EntryFile).getContent().sliceArray(0 until BLOCK_SIZE) //VDUtil.getAsNormalFile(DOM, 1).getContent().sliceArray(0 until BLOCK_SIZE)
printdbg("retMsg = ${retMsg.toString(VM.CHARSET)}")
val retMsg = DOM.readBoot()
recipient?.writeout(retMsg)
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
catch (e: IOException) {
printdbg("exception:")
e.printStackTrace()
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
return
}
}
else if (inputString.startsWith("MKDIR")) {
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
if (fileOpenMode < 1) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED)
statusCode.set(STATE_CODE_OPERATION_NOT_PERMITTED)
return
}
try {
val (status, whyFailed) = file.mkdir()
val status = file.mkdir()
statusCode.set(if (status) 0 else 1)
if (status) {
printdbg("Notifying disk commit (mkdir)")
notifyDiskCommit()
}
}
catch (e: SecurityException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR)
statusCode.set(STATE_CODE_SYSTEM_SECURITY_ERROR)
}
}
else if (inputString.startsWith("MKFILE")) {
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
if (fileOpenMode < 1) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED)
statusCode.set(STATE_CODE_OPERATION_NOT_PERMITTED)
return
}
try {
val (f1, whyFailed) = file.createNewFile()
statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (f1) {
printdbg("Notifying disk commit (mkfile)")
notifyDiskCommit()
}
val f1 = file.createNewFile()
statusCode.set(if (f1) STATE_CODE_STANDBY else STATE_CODE_OPERATION_FAILED)
return
}
catch (e: IOException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
}
catch (e1: SecurityException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR)
statusCode.set(STATE_CODE_SYSTEM_SECURITY_ERROR)
}
}
else if (inputString.startsWith("TOUCH")) {
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
if (fileOpenMode < 1) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED)
statusCode.set(STATE_CODE_OPERATION_NOT_PERMITTED)
return
}
try {
val (f1, whyFailed) = file.setLastModified(vm.worldInterface.currentTimeInMills())
statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (f1) {
printdbg("Notifying disk commit (touch)")
notifyDiskCommit()
}
val f1 = file.setLastModified(vm.worldInterface.currentTimeInMills())
statusCode.set(if (f1) STATE_CODE_STANDBY else STATE_CODE_OPERATION_FAILED)
return
}
catch (e: IOException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_IO_ERROR)
statusCode.set(STATE_CODE_SYSTEM_IO_ERROR)
}
catch (e1: SecurityException) {
statusCode.set(TestDiskDrive.STATE_CODE_SYSTEM_SECURITY_ERROR)
statusCode.set(STATE_CODE_SYSTEM_SECURITY_ERROR)
}
}
else if (inputString.startsWith("WRITE")) {
if (!fileOpen) {
statusCode.set(TestDiskDrive.STATE_CODE_NO_FILE_OPENED)
statusCode.set(STATE_CODE_NO_FILE_OPENED)
return
}
if (fileOpenMode < 0) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_NOT_PERMITTED)
statusCode.set(STATE_CODE_OPERATION_NOT_PERMITTED)
return
}
if (!file.exists()) {
val (f1, whyFailed) = file.createNewFile()
statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (!f1) { return }
}
// if (fileOpenMode == 1) { writeMode = true; appendMode = false }
// else if (fileOpenMode == 2) { writeMode = false; appendMode = true }
if (fileOpenMode == 1) { writeMode = true; appendMode = false }
else if (fileOpenMode == 2) { writeMode = false; appendMode = true }
writeModeLength = inputString.substring(5, inputString.length).toInt()
printdbg("WRITE issued with len $writeModeLength")
writeBuffer = ByteArray(writeModeLength)
writeBufferUsage = 0
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
statusCode.set(STATE_CODE_STANDBY)
}
else if (inputString.startsWith("USAGE")) {
recipient?.writeout(TestDiskDrive.composePositiveAns("USED${DOM.usedBytes}/TOTAL${DOM.capacity}"))
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY)
recipient?.writeout(composePositiveAns("USED123456/TOTAL654321"))
statusCode.set(STATE_CODE_STANDBY)
}
else if (inputString.startsWith("TEVDDISCARDDRIVE\"")) {
// the actual capacity of the floppy must be determined when the floppy gameitem was created
else
statusCode.set(STATE_CODE_ILLEGAL_COMMAND)
}
}
if (DOM.isReadOnly) {
printdbg("! disk is read-only")
statusCode.set(TestDiskDrive.STATE_CODE_READ_ONLY)
return
val diskID: UUID = UUID(0, 0)
private fun getReadableLs(): String {
val sb = StringBuilder()
val isRoot = (file.path == "")
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
}
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.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND)
return
}
val newName = 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()
sb.append(" ".repeat(40 - filenameLen))
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
if (it.isFile) {
sb.append("${it.length()} B")
}
TODO()
// DOM.entries.clear()
// DOM.diskName = newName.toByteArray(VM.CHARSET)
}
else {
printdbg("Illegal command: ${inputString}")
statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND)
sb.append('\n')
}
}
return if (sb.last() == '\n') sb.substring(0, sb.lastIndex) else sb.toString()
}
private fun getSizeStr(): String {
val sb = StringBuilder()
// val isRoot = (file.absolutePath == rootPath.absolutePath)
if (file.isFile) sb.append(file.length())
else sb.append(file.listFiles()!!.size)
return sb.toString()
}
private fun sanitisePath(s: String) = s.replace('\\','/').replace(Regex("""\?<>:\*\|"""),"-")
@@ -557,63 +530,4 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return newPaths.joinToString("/")
}
private fun getReadableLs(): String {
val sb = StringBuilder()
val isRoot = (file.entryID == 0)
if (file.isFile) sb.append(file.name)
else {
var filesCount = 0
var dirsCount = 0
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
dirsCount += 1
}
sb.append(" ".repeat(40 - filenameLen))
if (it.isFile) {
sb.append("${it.length()} B")
filesCount += 1
}
sb.append('\n')
}
sb.append("\n")
sb.append("\n$filesCount Files, $dirsCount, Directories")
sb.append("\nDisk used ${DOM.usedBytes} bytes")
sb.append("\n${DOM.capacity - DOM.usedBytes} bytes free")
if (DOM.isReadOnly)
sb.append("\nThe disk is read-only!")
}
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()
}
}

View File

@@ -64,12 +64,12 @@ class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var pa
*/
class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: Int, var panelsY: Int, val diskPathRoot: String) : ApplicationAdapter() {
val TEVD_COMMIT = TevdPartialDomCommitWatchdog
val TEVD_SYNC = TevdPartialDomCommitWatchdog
// val TEVD_COMMIT = TevdPartialDomCommitWatchdog
// val TEVD_SYNC = TevdPartialDomCommitWatchdog
val watchdogs = hashMapOf<String, VMWatchdog>(
"TEVD_COMMIT" to TEVD_COMMIT,
"TEVD_SYNC" to TEVD_SYNC
// "TEVD_COMMIT" to TEVD_COMMIT,
// "TEVD_SYNC" to TEVD_SYNC
)
data class VMRunnerInfo(val vm: VM, val profileName: String)