|
|
|
@ -14,6 +14,7 @@ import li.cil.oc.api.machine.Callback
|
|
|
|
|
import li.cil.oc.api.machine.Context
|
|
|
|
|
import li.cil.oc.api.network._
|
|
|
|
|
import li.cil.oc.api.prefab
|
|
|
|
|
import li.cil.oc.api.prefab.AbstractValue
|
|
|
|
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
|
|
|
|
import li.cil.oc.util.ExtendedNBT._
|
|
|
|
|
import net.minecraft.nbt.NBTTagCompound
|
|
|
|
@ -122,21 +123,13 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
|
|
|
|
result(success)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, doc = """function(handle:number) -- Closes an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, doc = """function(handle:userdata) -- Closes an open file descriptor with the specified handle.""")
|
|
|
|
|
def close(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
|
|
|
|
val handle = args.checkInteger(0)
|
|
|
|
|
Option(fileSystem.getHandle(handle)) match {
|
|
|
|
|
case Some(file) =>
|
|
|
|
|
owners.get(context.node.address) match {
|
|
|
|
|
case Some(set) if set.remove(handle) => file.close()
|
|
|
|
|
case _ => throw new IOException("bad file descriptor")
|
|
|
|
|
}
|
|
|
|
|
case _ => throw new IOException("bad file descriptor")
|
|
|
|
|
}
|
|
|
|
|
close(context, checkHandle(args, 0))
|
|
|
|
|
null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(path:string[, mode:string='r']):number -- Opens a new file descriptor and returns its handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(path:string[, mode:string='r']):userdata -- Opens a new file descriptor and returns its handle.""")
|
|
|
|
|
def open(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
|
|
|
|
if (owners.get(context.node.address).fold(false)(_.size >= Settings.get.maxHandles)) {
|
|
|
|
|
throw new IOException("too many open handles")
|
|
|
|
@ -148,11 +141,11 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
|
|
|
|
owners.getOrElseUpdate(context.node.address, mutable.Set.empty[Int]) += handle
|
|
|
|
|
}
|
|
|
|
|
diskActivity()
|
|
|
|
|
result(handle)
|
|
|
|
|
result(new HandleValue(node.address, handle))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def read(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
|
|
|
|
val handle = args.checkInteger(0)
|
|
|
|
|
val handle = checkHandle(args, 0)
|
|
|
|
|
val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1)))
|
|
|
|
|
checkOwner(context.node.address, handle)
|
|
|
|
|
Option(fileSystem.getHandle(handle)) match {
|
|
|
|
@ -183,7 +176,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def seek(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
|
|
|
|
val handle = args.checkInteger(0)
|
|
|
|
|
val handle = checkHandle(args, 0)
|
|
|
|
|
val whence = args.checkString(1)
|
|
|
|
|
val offset = args.checkInteger(2)
|
|
|
|
|
checkOwner(context.node.address, handle)
|
|
|
|
@ -201,7 +194,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def write(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
|
|
|
|
val handle = args.checkInteger(0)
|
|
|
|
|
val handle = checkHandle(args, 0)
|
|
|
|
|
val value = args.checkByteArray(1)
|
|
|
|
|
if (!node.tryChangeBuffer(-Settings.get.hddWriteCost * value.length)) {
|
|
|
|
|
throw new IOException("not enough energy")
|
|
|
|
@ -218,6 +211,28 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label, val host: Option
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
|
|
|
|
|
|
def checkHandle(args: Arguments, index: Int) = {
|
|
|
|
|
if (args.isInteger(index)) {
|
|
|
|
|
args.checkInteger(index)
|
|
|
|
|
} else args.checkAny(0) match {
|
|
|
|
|
case handle: HandleValue => handle.handle
|
|
|
|
|
case _ => throw new IOException("bad file descriptor")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def close(context: Context, handle: Int): Unit = {
|
|
|
|
|
Option(fileSystem.getHandle(handle)) match {
|
|
|
|
|
case Some(file) =>
|
|
|
|
|
owners.get(context.node.address) match {
|
|
|
|
|
case Some(set) if set.remove(handle) => file.close()
|
|
|
|
|
case _ => throw new IOException("bad file descriptor")
|
|
|
|
|
}
|
|
|
|
|
case _ => throw new IOException("bad file descriptor")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
|
|
|
|
|
|
override def onMessage(message: Message) = fileSystem.synchronized {
|
|
|
|
|
super.onMessage(message)
|
|
|
|
|
if (message.name == "computer.stopped" || message.name == "computer.started") {
|
|
|
|
@ -317,64 +332,103 @@ object FileSystem {
|
|
|
|
|
// I really need to come up with a way to make the call limit dynamic...
|
|
|
|
|
def apply(fileSystem: IFileSystem, label: Label, host: Option[EnvironmentHost], sound: Option[String], speed: Int = 1): FileSystem = speed match {
|
|
|
|
|
case 6 => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 15, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 15, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 15, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 15, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 6, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 6, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
case 5 => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 13, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 13, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 13, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 13, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 5, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 5, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
case 4 => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 10, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 10, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 10, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 10, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
case 3 => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 7, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 7, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 7, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 7, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 3, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 3, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
case 2 => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 4, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 2, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 2, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
case _ => new FileSystem(fileSystem, label, host, sound) {
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:number, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:userdata, count:number):string or nil -- Reads up to the specified amount of data from an open file descriptor with the specified handle. Returns nil when EOF is reached.""")
|
|
|
|
|
override def read(context: Context, args: Arguments): Array[AnyRef] = super.read(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:number, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:userdata, whence:string, offset:number):number -- Seeks in an open file descriptor with the specified handle. Returns the new pointer position.""")
|
|
|
|
|
override def seek(context: Context, args: Arguments): Array[AnyRef] = super.seek(context, args)
|
|
|
|
|
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:number, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
@Callback(direct = true, limit = 1, doc = """function(handle:userdata, value:string):boolean -- Writes the specified data to an open file descriptor with the specified handle.""")
|
|
|
|
|
override def write(context: Context, args: Arguments): Array[AnyRef] = super.write(context, args)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final class HandleValue extends AbstractValue {
|
|
|
|
|
def this(owner: String, handle: Int) = {
|
|
|
|
|
this()
|
|
|
|
|
this.owner = owner
|
|
|
|
|
this.handle = handle
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var owner = ""
|
|
|
|
|
var handle = 0
|
|
|
|
|
|
|
|
|
|
override def dispose(context: Context): Unit = {
|
|
|
|
|
super.dispose(context)
|
|
|
|
|
if (context.node() != null && context.node().network() != null) {
|
|
|
|
|
val node = context.node().network().node(owner)
|
|
|
|
|
if (node != null) {
|
|
|
|
|
node.host() match {
|
|
|
|
|
case fs: FileSystem => try fs.close(context, handle) catch {
|
|
|
|
|
case _: Throwable => // Ignore, already closed.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def load(nbt: NBTTagCompound): Unit = {
|
|
|
|
|
super.load(nbt)
|
|
|
|
|
owner = nbt.getString("owner")
|
|
|
|
|
handle = nbt.getInteger("handle")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def save(nbt: NBTTagCompound): Unit = {
|
|
|
|
|
super.save(nbt)
|
|
|
|
|
nbt.setInteger("handle", handle)
|
|
|
|
|
nbt.setString("owner", owner)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def toString: String = handle.toString
|
|
|
|
|
}
|
|
|
|
|