TEVD disk drive now uses PartialDOM

This commit is contained in:
minjaesong
2023-02-18 19:38:50 +09:00
parent 7990bcb987
commit 461c30e3e8
5 changed files with 86 additions and 59 deletions

View File

@@ -23,7 +23,7 @@ const actions = {
graphics.setBackground(34,51,68) graphics.setBackground(34,51,68)
sys.poke(-1299460, 20) sys.poke(-1299460, 20)
sys.poke(-1299460, 21) sys.poke(-1299460, 21)
} },
"audio": ()=>{ "audio": ()=>{
for (let k = 0; k < 4; k++) { for (let k = 0; k < 4; k++) {
audio.stop(k) audio.stop(k)
@@ -46,7 +46,7 @@ if (!verb) {
return 10 return 10
} }
let actionfun = actions[verb][target] let actionfun = actions[verb.toLowerCase()][target.toLowerCase()]
if (actionfun) actionfun() if (actionfun) actionfun()
else { else {
printerrln(`sysctl: unknown target ${target}`) printerrln(`sysctl: unknown target ${target}`)

Binary file not shown.

Binary file not shown.

View File

@@ -23,7 +23,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
} }
private val tevdPath = File(theTevdPath) private val tevdPath = File(theTevdPath)
private val DOM = VDUtil.readDiskArchive(tevdPath, charset = VM.CHARSET) private val DOM = PartialDOM(tevdPath, VM.CHARSET)//VDUtil.readDiskArchive(tevdPath, charset = VM.CHARSET)
private var fileOpen = false private var fileOpen = false
private var fileOpenMode = -1 // 1: 'W", 2: 'A' private var fileOpenMode = -1 // 1: 'W", 2: 'A'
@@ -131,7 +131,8 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
val file = EntryFile(BLOCK_SIZE.toLong()) val file = EntryFile(BLOCK_SIZE.toLong())
file.getContent().appendBytes(inputData) file.getContent().appendBytes(inputData)
DOM.entries[1] = DiskEntry(1, 1, "TEVDBOOT".toByteArray(VM.CHARSET), creationTime, creationTime, file) DOM.addNewFile(DiskEntry(1, 1, "TEVDBOOT".toByteArray(VM.CHARSET), creationTime, creationTime, file))
fileOpenMode = -1 fileOpenMode = -1
@@ -345,7 +346,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 // TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
val bootFile = DOM.entries[1] val bootFile = DOM.requestFile(1)
printdbg("bootFile = $bootFile, ID: 1, exists = ${bootFile != null}") printdbg("bootFile = $bootFile, ID: 1, exists = ${bootFile != null}")
@@ -355,7 +356,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
try { try {
val retMsg = VDUtil.getAsNormalFile(DOM, 1).getContent().sliceArray(0 until BLOCK_SIZE) 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)}") printdbg("retMsg = ${retMsg.toString(VM.CHARSET)}")
@@ -488,8 +489,9 @@ 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 // TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
DOM.entries.clear() TODO()
DOM.diskName = newName.toByteArray(VM.CHARSET) // DOM.entries.clear()
// DOM.diskName = newName.toByteArray(VM.CHARSET)
} }
else else
statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND) statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND)

View File

@@ -7,13 +7,13 @@ import java.io.IOException
/** /**
* Created by minjaesong on 2022-12-17. * Created by minjaesong on 2022-12-17.
*/ */
class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) { class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) {
val path = _pathstr.replace('\\', '/') val path = _pathstr.replace('\\', '/')
val vdPath = VDUtil.VDPath(path, VM.CHARSET) val vdPath = VDUtil.VDPath(path, VM.CHARSET)
val entryID: EntryID? val entryID: EntryID?
get() = VDUtil.getFile(DOM, vdPath)?.entryID get() = DOM.requestFile(path)?.entryID
val canonicalPath = path.replace('/', '\\') val canonicalPath = path.replace('/', '\\')
@@ -29,25 +29,34 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
val isFile: Boolean val isFile: Boolean
get() = entryID.let { if (it == null) false else VDUtil.isFileFollowSymlink(DOM, it) } get() = DOM.requestFile(path)?.contents is EntryFile // TODO follow symlink
val isDirectory: Boolean val isDirectory: Boolean
get() = entryID.let { if (it == null) false else VDUtil.isDirectoryFollowSymlink(DOM, it) } get() = DOM.requestFile(path)?.contents is EntryDirectory // TODO follow symlink
private fun requestFile(): Pair<DiskEntry, DiskEntryContent> {
val file = DOM.requestFile(path) ?: throw IOException("File not found")
val fileContent = file.contents
return file to fileContent
}
fun appendBytes(bytes: ByteArray) { fun appendBytes(bytes: ByteArray) {
val fileContent = VDUtil.getAsNormalFile(DOM, vdPath) // this is not an object properties: the reference to the file may have been changed // val fileContent = VDUtil.getAsNormalFile(DOM, vdPath) // this is not an object properties: the reference to the file may have been changed
fileContent.getContent().appendBytes(bytes) val (file, fileContent) = requestFile()
VDUtil.getFile(DOM, vdPath)!!.modificationDate = VDUtil.currentUnixtime (fileContent as EntryFile).getContent().appendBytes(bytes) // TODO follow symlink
file.modificationDate = VDUtil.currentUnixtime
} }
fun writeBytes(bytes: ByteArray) { fun writeBytes(bytes: ByteArray) {
val fileContent = VDUtil.getAsNormalFile(DOM, vdPath) val (file, fileContent) = requestFile()
// println("[TevdFileDesc] ${path} writing ${bytes.size} bytes...") // println("[TevdFileDesc] ${path} writing ${bytes.size} bytes...")
// println("Old: ${fileContent.getContent().toByteArray().toString(VM.CHARSET)}") // println("Old: ${fileContent.getContent().toByteArray().toString(VM.CHARSET)}")
fileContent.replaceContent(ByteArray64.fromByteArray(bytes)) (fileContent as EntryFile).replaceContent(ByteArray64.fromByteArray(bytes)) // TODO follow symlink
// println("New: ${fileContent.getContent().toByteArray().toString(VM.CHARSET)}") // println("New: ${fileContent.getContent().toByteArray().toString(VM.CHARSET)}")
VDUtil.getFile(DOM, vdPath)!!.modificationDate = VDUtil.currentUnixtime file.modificationDate = VDUtil.currentUnixtime
} }
/** /**
@@ -55,12 +64,8 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
* @return actual bytes read, the size may be less than `length` if the actual file size is smaller * @return actual bytes read, the size may be less than `length` if the actual file size is smaller
*/ */
fun getHeadBytes64(length: Long): ByteArray64 { fun getHeadBytes64(length: Long): ByteArray64 {
if (isDirectory) throw RuntimeException("Not a file") val (file, fileContent) = requestFile()
if (!exists()) throw IOException("File not found") return (fileContent as EntryFile).getContent().let {
val fileContent = VDUtil.getAsNormalFile(DOM, vdPath)
return fileContent.getContent().let {
it.sliceArray64(0L until minOf(length, it.size)) it.sliceArray64(0L until minOf(length, it.size))
} }
} }
@@ -69,25 +74,22 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
* @return actual bytes read, the size may be less than `length` if the actual file size is smaller * @return actual bytes read, the size may be less than `length` if the actual file size is smaller
*/ */
fun getHeadBytes(length: Int): ByteArray { fun getHeadBytes(length: Int): ByteArray {
if (isDirectory) throw RuntimeException("Not a file") val (file, fileContent) = requestFile()
if (!exists()) throw IOException("File not found") return (fileContent as EntryFile).getContent().let {
val fileContent = VDUtil.getAsNormalFile(DOM, vdPath)
return fileContent.getContent().let {
it.sliceArray(0 until minOf(length.toLong(), it.size).toInt()) it.sliceArray(0 until minOf(length.toLong(), it.size).toInt())
} }
} }
fun exists(): Boolean { fun exists(): Boolean {
return VDUtil.getFile(DOM, vdPath) != null return (DOM.requestFile(path) != null)
} }
fun delete(): Boolean { fun delete(): Boolean {
return try { return try {
val parentDir = vdPath.getParent() val parentDir = vdPath.getParent().toString()
VDUtil.deleteFile(DOM, vdPath) DOM.removeFile(path)
VDUtil.getFile(DOM, parentDir)!!.modificationDate = VDUtil.currentUnixtime DOM.requestFile(parentDir)!!.modificationDate = VDUtil.currentUnixtime
true true
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
@@ -96,33 +98,43 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
} }
fun length(): Long { fun length(): Long {
return if (isFile) VDUtil.getAsNormalFileOrNull(DOM, vdPath)?.getSizePure() ?: 0L val (file, fileContent) = requestFile()
return if (fileContent is EntryFile)
fileContent.getSizePure()
else -1L else -1L
} }
fun listFiles(): Array<TevdFileDescriptor>? { fun listFiles(): Array<TevdFileDescriptor>? {
if (isFile) return null val (file, fileContent) = requestFile()
return if (fileContent !is EntryDirectory) null // TODO follow symlink
entryID.let { else (DOM.requestFile(path)?.contents as EntryDirectory).getContent().map { id -> DOM.requestFile(id)!! }.map {
if (it == null) return null TevdFileDescriptor(DOM, path + '/' + it.getFilenameString(VM.CHARSET))
}.toTypedArray()
return VDUtil.getDirectoryEntries(DOM, it).map {
TevdFileDescriptor(DOM, path + '/' + it.getFilenameString(VM.CHARSET))
}.toTypedArray()
}
} }
fun readBytes(): ByteArray { fun readBytes(): ByteArray {
if (isDirectory) throw RuntimeException("Not a file") val (file, fileContent) = requestFile()
if (!exists()) throw IOException("File not found") if (fileContent !is EntryFile) throw RuntimeException("Not a file") // TODO follow symlink
return VDUtil.getAsNormalFile(DOM, vdPath).getContent().toByteArray() else
return fileContent.getContent().toByteArray()
} }
fun mkdir(): Boolean { fun mkdir(): Boolean {
return try { return try {
val parentDir = vdPath.getParent() val parentDir = vdPath.getParent().toString()
VDUtil.addDir(DOM, parentDir, nameBytes)
VDUtil.getFile(DOM, parentDir)!!.modificationDate = VDUtil.currentUnixtime val dir = DOM.requestFile(parentDir)!!
val dirContent = dir.contents as EntryDirectory
val newTime = VDUtil.currentUnixtime
val newID = DOM.generateUniqueID()
val newDir = DiskEntry(newID, dir.entryID, nameBytes, newTime, newTime, EntryDirectory())
DOM.addNewFile(newDir)
dirContent.add(newID)
dir.modificationDate = newTime
true true
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
@@ -135,9 +147,22 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
val time_t = System.currentTimeMillis() / 1000 val time_t = System.currentTimeMillis() / 1000
val newFile = DiskEntry(-1, -1, nameBytes, time_t, time_t, fileContent) val newFile = DiskEntry(-1, -1, nameBytes, time_t, time_t, fileContent)
return try { return try {
val parentDir = vdPath.getParent() val parentDir = vdPath.getParent().toString()
VDUtil.addFile(DOM, parentDir, newFile)
VDUtil.getFile(DOM, parentDir)!!.modificationDate = VDUtil.currentUnixtime val dir = DOM.requestFile(parentDir)!!
val dirContent = dir.contents as EntryDirectory
val newTime = VDUtil.currentUnixtime
val newID = DOM.generateUniqueID()
newFile.entryID = newID
newFile.parentEntryID = dir.entryID
DOM.addNewFile(newFile)
dirContent.add(newID)
dir.modificationDate = newTime
true true
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
@@ -146,12 +171,12 @@ class TevdFileDescriptor(val DOM: VirtualDisk, _pathstr: String) {
} }
fun setLastModified(newTime_t: Long): Boolean { fun setLastModified(newTime_t: Long): Boolean {
return VDUtil.getFile(DOM, vdPath).let { return try {
if (it != null) { DOM.requestFile(path)!!.modificationDate = newTime_t
it.modificationDate = newTime_t true
true }
} catch (e: KotlinNullPointerException) {
else false false
} }
} }