Schrödinger's file: it's superposition between existent and nonexistent, file and directory. Tried java.nio.file but it seems it's just Java that is broken like vittupää

Former-commit-id: ec938b81d8c4a1385295846b7b3d5178652d93ad
Former-commit-id: 0ff4806c81c94ec5a126894f8d41ca6891bcb1d2
This commit is contained in:
Song Minjae
2016-10-04 02:05:52 +09:00
parent e5bc967ade
commit 862034b6c1
5 changed files with 65 additions and 52 deletions

View File

@@ -21,8 +21,8 @@ class StateVTTest : BasicGameState() {
// HiRes: 100x64, LoRes: 80x25 // HiRes: 100x64, LoRes: 80x25
val computerInside = BaseTerrarumComputer(8) val computerInside = BaseTerrarumComputer(8)
val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25, val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 100, 64,
computerInside, colour = false, hires = false) computerInside, colour = true, hires = true)
val vtUI = Image(vt.displayW, vt.displayH) val vtUI = Image(vt.displayW, vt.displayH)

View File

@@ -91,12 +91,12 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
computerValue["processor"] = -1 // do. computerValue["processor"] = -1 // do.
// as in "dev/hda"; refers hard disk drive (and no partitioning) // as in "dev/hda"; refers hard disk drive (and no partitioning)
computerValue["hda"] = "testhda" // 'UUID rendered as String' or "none" computerValue["hda"] = "uuid_testhda" // 'UUID rendered as String' or "none"
computerValue["hdb"] = "none" computerValue["hdb"] = "uuid_testhdb"
computerValue["hdc"] = "none" computerValue["hdc"] = "none"
computerValue["hdd"] = "none" computerValue["hdd"] = "none"
// as in "dev/fd1"; refers floppy disk drive // as in "dev/fd1"; refers floppy disk drive
computerValue["fd1"] = "none" computerValue["fd1"] = "uuid_testfd1"
computerValue["fd2"] = "none" computerValue["fd2"] = "none"
computerValue["fd3"] = "none" computerValue["fd3"] = "none"
computerValue["fd4"] = "none" computerValue["fd4"] = "none"
@@ -159,7 +159,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
// secure the sandbox // secure the sandbox
luaJ_globals["io"] = LuaValue.NIL //luaJ_globals["io"] = LuaValue.NIL
// dubug should be sandboxed in BOOT.lua (use OpenComputers code) // dubug should be sandboxed in BOOT.lua (use OpenComputers code)
//val sethook = luaJ_globals["debug"]["sethook"] //val sethook = luaJ_globals["debug"]["sethook"]
//luaJ_globals["debug"] = LuaValue.NIL //luaJ_globals["debug"] = LuaValue.NIL
@@ -207,12 +207,13 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
unsetThreadRun() unsetThreadRun()
} }
driveBeepQueueManager(delta)
} }
if (!isHalted) {
if (isHalted) { driveBeepQueueManager(delta)
}
else {
currentExecutionThread.interrupt() currentExecutionThread.interrupt()
} }
} }
@@ -326,7 +327,6 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
// complete emitTone queue // complete emitTone queue
if (beepCursor >= beepQueue.size) { if (beepCursor >= beepQueue.size) {
clearBeepQueue() clearBeepQueue()
if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear")
} }
// actually play queue // actually play queue
@@ -350,6 +350,8 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
beepQueueLineExecTimer = 0 beepQueueLineExecTimer = 0
//AL.destroy() //AL.destroy()
if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear")
} }
fun enqueueBeep(duration: Int, freq: Double) { fun enqueueBeep(duration: Int, freq: Double) {

View File

@@ -10,6 +10,7 @@ import net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
import java.io.* import java.io.*
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths
import java.util.* import java.util.*
/** /**
@@ -20,7 +21,9 @@ import java.util.*
* Created by minjaesong on 16-09-17. * Created by minjaesong on 16-09-17.
* *
* *
* NOTE: Don't convert '\' to '/'! Rev-slash is used for escape character in sh, and we're sh-compatible! * NOTES:
* Don't convert '\' to '/'! Rev-slash is used for escape character in sh, and we're sh-compatible!
* Use .absoluteFile whenever possible; there's fuckin oddity! (http://bugs.java.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097)
*/ */
internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) { internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
@@ -40,7 +43,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
globals["fs"]["concat"] = ConcatPath(computer) // OC compliant globals["fs"]["concat"] = ConcatPath(computer) // OC compliant
globals["fs"]["open"] = OpenFile(computer) //CC compliant globals["fs"]["open"] = OpenFile(computer) //CC compliant
globals["fs"]["parent"] = GetParentDir(computer) globals["fs"]["parent"] = GetParentDir(computer)
// fs.dofile defined in ROMLIB // fs.dofile defined in BOOT
// fs.fetchText defined in ROMLIB // fs.fetchText defined in ROMLIB
} }
@@ -48,29 +51,34 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
fun ensurePathSanity(path: LuaValue) { fun ensurePathSanity(path: LuaValue) {
if (path.checkIBM437().contains(Regex("""\.\."""))) if (path.checkIBM437().contains(Regex("""\.\.""")))
throw LuaError("'..' on path is not supported.") throw LuaError("'..' on path is not supported.")
if (!isValidFilename(path.checkIBM437()))
throw IOException("path contains invalid characters")
} }
val isCaseInsensitive: Boolean val isCaseInsensitive: Boolean
get() {
// TODO add: force case insensitive in config init {
try { try {
val uuid = UUID.randomUUID().toString() val uuid = UUID.randomUUID().toString()
val lowerCase = File(Terrarum.currentSaveDir, uuid + "oc_rox") val lowerCase = File(Terrarum.currentSaveDir, uuid + "oc_rox")
val upperCase = File(Terrarum.currentSaveDir, uuid + "OC_ROX") val upperCase = File(Terrarum.currentSaveDir, uuid + "OC_ROX")
// This should NEVER happen but could also lead to VERY weird bugs, so we // This should NEVER happen but could also lead to VERY weird bugs, so we
// make sure the files don't exist. // make sure the files don't exist.
lowerCase.exists() && lowerCase.delete() if (lowerCase.exists()) lowerCase.delete()
upperCase.exists() && upperCase.delete() if (upperCase.exists()) upperCase.delete()
lowerCase.createNewFile()
val insensitive = upperCase.exists() lowerCase.createNewFile()
lowerCase.delete()
return insensitive val insensitive = upperCase.exists()
} lowerCase.delete()
catch (e: IOException) {
println("[Filesystem] Couldn't determine if file system is case sensitive, falling back to insensitive.") isCaseInsensitive = insensitive
return true
}
} }
catch (e: IOException) {
println("[Filesystem] Couldn't determine if file system is case sensitive, falling back to insensitive.")
isCaseInsensitive = true
}
}
// Worst-case: we're on Windows or using a FAT32 partition mounted in *nix. // Worst-case: we're on Windows or using a FAT32 partition mounted in *nix.
// Note: we allow / as the path separator and expect all \s to be converted // Note: we allow / as the path separator and expect all \s to be converted
@@ -79,11 +87,11 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
fun isValidFilename(name: String) = !name.contains(invalidChars) fun isValidFilename(name: String) = !name.contains(invalidChars)
fun validatePath(path: String) : String { fun String.validatePath() : String {
if (!isValidFilename(path)) { if (!isValidFilename(this)) {
throw IOException("path contains invalid characters") throw IOException("path contains invalid characters")
} }
return path return this
} }
/** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/ /** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
@@ -103,7 +111,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
*/ */
// remove first '/' in path // remove first '/' in path
var path = luapath.checkIBM437() var path = luapath.checkIBM437().validatePath()
if (path.startsWith('/')) path = path.substring(1) if (path.startsWith('/')) path = path.substring(1)
if (path.startsWith("media/")) { if (path.startsWith("media/")) {
@@ -131,7 +139,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
val table = LuaTable() val table = LuaTable()
val file = File(computer.getRealPath(path)) val file = File(computer.getRealPath(path)).absoluteFile
file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) } file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) }
return table return table
} }
@@ -141,7 +149,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).exists()) return LuaValue.valueOf(Files.exists(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
} }
} }
@@ -149,7 +157,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).isDirectory) return LuaValue.valueOf(Files.isDirectory(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
} }
} }
@@ -157,7 +165,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).isFile) return LuaValue.valueOf(!Files.isDirectory(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
} }
} }
@@ -165,7 +173,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(!File(computer.getRealPath(path)).canWrite()) return LuaValue.valueOf(!Files.isWritable(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
} }
} }
@@ -174,7 +182,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).length().toInt()) return LuaValue.valueOf(Files.size(Paths.get(computer.getRealPath(path)).toAbsolutePath()).toInt())
} }
} }
@@ -187,7 +195,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).mkdir()) return LuaValue.valueOf(File(computer.getRealPath(path)).absoluteFile.mkdir())
} }
} }
@@ -199,11 +207,12 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
Filesystem.ensurePathSanity(from) Filesystem.ensurePathSanity(from)
Filesystem.ensurePathSanity(to) Filesystem.ensurePathSanity(to)
val fromFile = File(computer.getRealPath(from)) val fromFile = File(computer.getRealPath(from)).absoluteFile
var success = fromFile.copyRecursively( var success = fromFile.copyRecursively(
File(computer.getRealPath(to)), overwrite = true File(computer.getRealPath(to)).absoluteFile, overwrite = true
) // ignore IntelliJ's observation; it's opposite from redundant )
success = fromFile.deleteRecursively() if (success) success = fromFile.deleteRecursively()
else return LuaValue.valueOf(false)
return LuaValue.valueOf(success) return LuaValue.valueOf(success)
} }
} }
@@ -218,8 +227,8 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
Filesystem.ensurePathSanity(to) Filesystem.ensurePathSanity(to)
return LuaValue.valueOf( return LuaValue.valueOf(
File(computer.getRealPath(from)).copyRecursively( File(computer.getRealPath(from)).absoluteFile.copyRecursively(
File(computer.getRealPath(to)), overwrite = true File(computer.getRealPath(to)).absoluteFile, overwrite = true
) )
) )
} }
@@ -233,7 +242,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
return LuaValue.valueOf( return LuaValue.valueOf(
File(computer.getRealPath(path)).deleteRecursively() File(computer.getRealPath(path)).absoluteFile.deleteRecursively()
) )
} }
} }
@@ -243,7 +252,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
Filesystem.ensurePathSanity(base) Filesystem.ensurePathSanity(base)
Filesystem.ensurePathSanity(local) Filesystem.ensurePathSanity(local)
val combinedPath = combinePath(base.checkIBM437(), local.checkIBM437()) val combinedPath = combinePath(base.checkIBM437().validatePath(), local.checkIBM437().validatePath())
return LuaValue.valueOf(combinedPath) return LuaValue.valueOf(combinedPath)
} }
} }
@@ -282,9 +291,9 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
val mode = mode.checkIBM437().toLowerCase() val mode = mode.checkIBM437().toLowerCase()
val luaClass = LuaTable() val luaClass = LuaTable()
val file = File(computer.getRealPath(path)) val file = File(computer.getRealPath(path)).absoluteFile
if (mode.contains("[aw]") && !file.canWrite()) if (mode.contains(Regex("""[aw]""")) && !file.canWrite())
throw LuaError("Cannot open file for " + throw LuaError("Cannot open file for " +
"${if (mode.startsWith('w')) "read" else "append"} mode" + "${if (mode.startsWith('w')) "read" else "append"} mode" +
": is readonly.") ": is readonly.")

View File

@@ -15,6 +15,7 @@ class Input(globals: Globals, computer: BaseTerrarumComputer) {
init { init {
globals["input"] = LuaTable() globals["input"] = LuaTable()
globals["input"]["isKeyDown"] = IsKeyDown(computer) globals["input"]["isKeyDown"] = IsKeyDown(computer)
// input.readLine defined in ROMLIB
} }
companion object { companion object {

View File

@@ -118,6 +118,7 @@ internal class Term(globals: Globals, term: Teletype) {
} }
} }
// emitchar
class Emit(val term: Terminal) : ThreeArgFunction() { class Emit(val term: Terminal) : ThreeArgFunction() {
override fun call(p0: LuaValue, x: LuaValue, y: LuaValue): LuaValue { override fun call(p0: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
term.emitChar(p0.checkint().toChar(), x.checkint() - 1, y.checkint() - 1) term.emitChar(p0.checkint().toChar(), x.checkint() - 1, y.checkint() - 1)