mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-17 19:25:20 -04:00
Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8.9
This commit is contained in:
commit
82970cc92f
@ -286,7 +286,7 @@ minecraft {
|
|||||||
mappings = "stable_22"
|
mappings = "stable_22"
|
||||||
|
|
||||||
replace "@VERSION@", project.simpleVersion
|
replace "@VERSION@", project.simpleVersion
|
||||||
replace "@MCVERSION@", config.minecraft.version
|
replace "/*@MCVERSIONDEP@*/", ", acceptedMinecraftVersions = \"[${config.minecraft.version},${config.minecraft.version}+)\""
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
@ -13,9 +13,14 @@ for i = 1, #args do
|
|||||||
io.stderr:write(string.format('cat %s: Is a directory\n', arg))
|
io.stderr:write(string.format('cat %s: Is a directory\n', arg))
|
||||||
ec = 1
|
ec = 1
|
||||||
else
|
else
|
||||||
local file, reason = args[i] == "-" and io.stdin or io.open(shell.resolve(args[i]))
|
local file, reason
|
||||||
|
if args[i] == "-" then
|
||||||
|
file, reason = io.stdin, "missing stdin"
|
||||||
|
else
|
||||||
|
file, reason = io.open(shell.resolve(args[i]))
|
||||||
|
end
|
||||||
if not file then
|
if not file then
|
||||||
io.stderr:write(string.format("cat: %s: %s\n",args[i],tostring(reason)))
|
io.stderr:write(string.format("cat: %s: %s\n", args[i], tostring(reason)))
|
||||||
ec = 1
|
ec = 1
|
||||||
else
|
else
|
||||||
repeat
|
repeat
|
||||||
|
@ -148,12 +148,14 @@ end
|
|||||||
local to = shell.resolve(args[#args])
|
local to = shell.resolve(args[#args])
|
||||||
|
|
||||||
for i = 1, #args - 1 do
|
for i = 1, #args - 1 do
|
||||||
local fromPath, cuts = args[i]:gsub("(/%.%.?)$", "%1")
|
local arg = args[i]
|
||||||
fromPath = shell.resolve(fromPath)
|
local fromPath = shell.resolve(arg)
|
||||||
|
-- a "contents of" copy is where src path ends in . or ..
|
||||||
|
-- a source path ending with . is not sufficient - could be the source filename
|
||||||
|
local contents_of = arg:match("%.$") and not fromPath:match("%.$")
|
||||||
local toPath = to
|
local toPath = to
|
||||||
-- fromPath ending with /. indicates copying the contents of fromPath
|
-- we do not append fromPath name to toPath in case of contents_of copy
|
||||||
-- in which case (cuts>0) we do not append fromPath name to toPath
|
if not contents_of and fs.isDirectory(toPath) then
|
||||||
if cuts == 0 and fs.isDirectory(toPath) then
|
|
||||||
toPath = fs.concat(toPath, fs.name(fromPath))
|
toPath = fs.concat(toPath, fs.name(fromPath))
|
||||||
end
|
end
|
||||||
result, reason = recurse(fromPath, toPath)
|
result, reason = recurse(fromPath, toPath)
|
||||||
|
@ -19,7 +19,7 @@ for i = 1, #args do
|
|||||||
reason = "unknown reason"
|
reason = "unknown reason"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io.stderr:write(path .. ": " .. reason .. "\n")
|
io.stderr:write("mkdir: cannot create directory '" .. tostring(args[i]) .. "': " .. reason .. "\n")
|
||||||
ec = 1
|
ec = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
local guid = require("guid")
|
local uuid = require("uuid")
|
||||||
local shell = require("shell")
|
local shell = require("shell")
|
||||||
local sh = require("sh")
|
local sh = require("sh")
|
||||||
|
|
||||||
local touch = loadfile(shell.resolve("touch", "lua"))
|
local touch = loadfile(shell.resolve("touch", "lua"))
|
||||||
local mkdir = loadfile(shell.resolve("mkdir", "lua"))
|
local mkdir = loadfile(shell.resolve("mkdir", "lua"))
|
||||||
|
|
||||||
if not guid or not touch then
|
if not uuid or not touch then
|
||||||
local errorMessage = "missing tools for mktmp"
|
local errorMessage = "missing tools for mktmp"
|
||||||
io.stderr:write(errorMessage .. '\n')
|
io.stderr:write(errorMessage .. '\n')
|
||||||
return false, errorMessage
|
return false, errorMessage
|
||||||
@ -58,7 +58,7 @@ if not fs.exists(prefix) then
|
|||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local tmp = prefix .. guid.next()
|
local tmp = prefix .. uuid.next()
|
||||||
if not fs.exists(tmp) then
|
if not fs.exists(tmp) then
|
||||||
|
|
||||||
local ok, reason
|
local ok, reason
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
require("filesystem").mount(
|
require("filesystem").mount(
|
||||||
setmetatable({
|
setmetatable({
|
||||||
isReadOnly = function()return false end
|
isReadOnly = function()return false end,
|
||||||
|
address = require("uuid").next()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__index=function(tbl,key)return require("devfs")[key]end
|
__index=function(tbl,key)return require("devfs")[key]end
|
||||||
|
@ -1,111 +1,292 @@
|
|||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
|
local comp = require("component")
|
||||||
|
|
||||||
local proxy = {points={},address=require("guid").next()}
|
local function new_node(parent, name, is_dir, proxy)
|
||||||
|
local node = {parent=parent, name=name, is_dir=is_dir, proxy=proxy}
|
||||||
|
if not proxy then
|
||||||
|
node.children = {}
|
||||||
|
end
|
||||||
|
return node
|
||||||
|
end
|
||||||
|
|
||||||
local nop = function()end
|
local function new_devfs_dir(name)
|
||||||
|
local sys = {}
|
||||||
|
sys.mtab = new_node(nil, name or "/", true)
|
||||||
|
|
||||||
function proxy.getLabel()
|
-- returns: dir, point or path
|
||||||
|
-- node (table): the handler responsible for the path
|
||||||
|
-- this is essentially the device filesystem that is registered for the given path
|
||||||
|
-- point (string): the point name (like a file name)
|
||||||
|
function sys.findNode(path, create)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local segments = fs.segments(path)
|
||||||
|
local node = sys.mtab
|
||||||
|
while #segments > 0 do
|
||||||
|
local name = table.remove(segments, 1)
|
||||||
|
local prev_path = path
|
||||||
|
path = table.concat(segments, "/")
|
||||||
|
|
||||||
|
if not node.children[name] then
|
||||||
|
if not create then
|
||||||
|
path = prev_path
|
||||||
|
break
|
||||||
|
end
|
||||||
|
node.children[name] = new_node(node, name, true, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
node = node.children[name]
|
||||||
|
|
||||||
|
if node.proxy then -- if there is a proxy handler we stop searching here
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- only dirs can have trailing path
|
||||||
|
-- trailing path on a dev point (file) not allowed
|
||||||
|
if path == "" or node.is_dir and node.proxy then
|
||||||
|
return node, path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.invoke(method, path, ...)
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
if not node or -- not found
|
||||||
|
rest == "" and node.is_dir or -- path is dir
|
||||||
|
not node.proxy[method] then -- optional method
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
-- proxy could be a file, which doesn't take an argument, but it can be ignored if passed
|
||||||
|
return node.proxy[method](rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.size(path)
|
||||||
|
return sys.invoke("size", path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.lastModified(path)
|
||||||
|
return sys.invoke("lastModified", path)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.isDirectory(path)
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
if not node then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if rest == "" then
|
||||||
|
return node.is_dir
|
||||||
|
elseif node.proxy then
|
||||||
|
return node.proxy.isDirectory(rest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.open(path, mode)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
checkArg(2, mode, "string", "nil")
|
||||||
|
|
||||||
|
if not sys.exists(path) then
|
||||||
|
return nil, path.." file not found"
|
||||||
|
elseif sys.isDirectory(path) then
|
||||||
|
return nil, path.." is a directory"
|
||||||
|
end
|
||||||
|
|
||||||
|
mode = mode or "r"
|
||||||
|
-- everything at this level should be a binary open
|
||||||
|
mode = mode:gsub("b", "")
|
||||||
|
|
||||||
|
if not ({a=true,w=true,r=true})[mode] then
|
||||||
|
return nil, "invalid mode"
|
||||||
|
end
|
||||||
|
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
-- there must be a node, else exists would have failed
|
||||||
|
|
||||||
|
local args = {}
|
||||||
|
if rest ~= "" then
|
||||||
|
-- having more rest means we expect the proxy fs to open the point
|
||||||
|
args[1] = rest
|
||||||
|
end
|
||||||
|
args[#args+1] = mode
|
||||||
|
|
||||||
|
return node.proxy.open(table.unpack(args))
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.list(path)
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
if not node or (rest ~= "" and not node.is_dir) then-- not found
|
||||||
|
return {}
|
||||||
|
elseif rest == "" and not node.is_dir then -- path is file
|
||||||
|
return {path}
|
||||||
|
elseif node.proxy then
|
||||||
|
-- proxy could be a file, which doesn't take an argument, but it can be ignored if passed
|
||||||
|
return node.proxy.list(rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- rest == "" and node.is_dir
|
||||||
|
local keys = {}
|
||||||
|
for k in pairs(node.children) do
|
||||||
|
table.insert(keys, k)
|
||||||
|
end
|
||||||
|
return keys
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.remove(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
|
||||||
|
if path == "" then
|
||||||
|
return nil, "no such file or directory"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not sys.exists(path) then
|
||||||
|
return nil, path.." file not found"
|
||||||
|
end
|
||||||
|
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
|
||||||
|
if rest ~= "" then -- if rest is not resolved, this isn't our path
|
||||||
|
return node.proxy.remove(rest)
|
||||||
|
end
|
||||||
|
|
||||||
|
node.parent.children[node.name] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.exists(path)
|
||||||
|
checkArg(1, path, "string")
|
||||||
|
local node, rest = sys.findNode(path)
|
||||||
|
|
||||||
|
if not node then
|
||||||
|
return false
|
||||||
|
elseif rest == "" then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return node.proxy.exists(rest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function sys.create(path, handler)
|
||||||
|
if sys.exists(path) then
|
||||||
|
return nil, "path already exists"
|
||||||
|
end
|
||||||
|
|
||||||
|
local segments = fs.segments(path)
|
||||||
|
local target = table.remove(segments)
|
||||||
|
path = table.concat(segments, "/")
|
||||||
|
|
||||||
|
if not target or target == "" then
|
||||||
|
return nil, "missing argument"
|
||||||
|
end
|
||||||
|
|
||||||
|
local node, rest = sys.findNode(path, true)
|
||||||
|
if rest ~= "" then
|
||||||
|
return node.proxy.create(rest, handler)
|
||||||
|
end
|
||||||
|
node.children[target] = new_node(node, target, not not handler.list, handler)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return sys
|
||||||
|
end
|
||||||
|
|
||||||
|
local devfs = new_devfs_dir()
|
||||||
|
|
||||||
|
local bfd = "bad file descriptor"
|
||||||
|
|
||||||
|
function devfs.getLabel()
|
||||||
return "devfs"
|
return "devfs"
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.setLabel(value)
|
function devfs.setLabel(value)
|
||||||
error("drive does not support labeling")
|
error("drive does not support labeling")
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.spaceTotal()
|
function devfs.spaceTotal()
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.spaceUsed()
|
function devfs.spaceUsed()
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.exists(path)
|
function devfs.makeDirectory(path)
|
||||||
return not not proxy.points[path]
|
return false, "to create dirs in devfs use devfs.create"
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.size(path)
|
function devfs.read(h,...)
|
||||||
return 0
|
if not h.read then return nil, bfd end
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.isDirectory(path)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.lastModified(path)
|
|
||||||
return fs.lastModified("/dev/")
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.list()
|
|
||||||
local keys = {}
|
|
||||||
for k,v in pairs(proxy.points) do
|
|
||||||
table.insert(keys, k)
|
|
||||||
end
|
|
||||||
return keys
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.makeDirectory(path)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.remove(path)
|
|
||||||
if not proxy.exists(path) then return false end
|
|
||||||
proxy.points[path] = nil
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.rename(from, to)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
proxy.close = nop
|
|
||||||
|
|
||||||
function proxy.open(path, mode)
|
|
||||||
checkArg(1, path, "string")
|
|
||||||
|
|
||||||
local handle = proxy.points[path]
|
|
||||||
if not handle then return nil, "device point [" .. path .. "] does not exist" end
|
|
||||||
|
|
||||||
local msg = "device point [" .. path .. "] cannot be opened for "
|
|
||||||
|
|
||||||
if mode == "r" then
|
|
||||||
if not handle.read then
|
|
||||||
return nil, msg .. "read"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if not handle.write then
|
|
||||||
return nil, msg .. "write"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return handle
|
|
||||||
end
|
|
||||||
|
|
||||||
function proxy.read(h,...)
|
|
||||||
return h:read(...)
|
return h:read(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.seek(h,...)
|
function devfs.seek(h,...)
|
||||||
|
if not h.seek then return nil, bfd end
|
||||||
return h:seek(...)
|
return h:seek(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.write(h,...)
|
function devfs.write(h,...)
|
||||||
|
if not h.write then return nil, bfd end
|
||||||
return h:write(...)
|
return h:write(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function proxy.create(path, handle)
|
function devfs.close(h, ...)
|
||||||
handle.close = handle.close or nop
|
if not h.close then return nil, bfd end
|
||||||
proxy.points[path] = handle
|
return h:close(...)
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
proxy.create("null", {write = nop})
|
-- devfs.create creates a new dev point at path
|
||||||
proxy.create("random", {read = function(_,n)
|
-- devfs is mounted to /sys by default, and /dev is a symlink to /sys/dev. If you want a devfs point to show up in /dev, specify a path here as "/dev/your_path")
|
||||||
local chars = {}
|
-- the handler can be a single file dev file (called a point), or a devfs dir [which allows it to list its own dynamic list of points and dirs]
|
||||||
for i=1,n do
|
-- note: devfs dirs that list their own child dirs will have to handle directory queries on their own, such as list() and open(path, mode)
|
||||||
table.insert(chars,string.char(math.random(0,255)))
|
|
||||||
end
|
|
||||||
return table.concat(chars)
|
|
||||||
end})
|
|
||||||
|
|
||||||
return proxy
|
-- A handler represents a directory IF it defines list(), which returns a string array of the point names
|
||||||
|
-- a directory handler acts like simplified filesystem of its own.
|
||||||
|
-- note: that when creating new devfs points or dirs, devfs.create will not traverse into dynamic directory children of dev mount points
|
||||||
|
-- Meaning, if you create a devfs dir, which returns dirs children of its own, devfs.create does not support creating dev points
|
||||||
|
-- on those children
|
||||||
|
|
||||||
|
-- see new_devfs_dir() -- it might work for you, /dev uses it
|
||||||
|
|
||||||
|
-- Also note, your own devfs dirs may implement open() however they like -- devfs points' open() is called by the devfs library but dynamic
|
||||||
|
-- dir act as their own library for their own points
|
||||||
|
|
||||||
|
-- ### devfs point methods ###
|
||||||
|
-- Required
|
||||||
|
-- open(mode: string []) file: returns new file handle for point (see "devfs point handle methods")
|
||||||
|
-- Optional
|
||||||
|
-- size(path) number
|
||||||
|
|
||||||
|
-- ### devfs point handle instance methods ###
|
||||||
|
-- Required
|
||||||
|
-- + technicaly, one of the following is not required when the mode is for the other (e.g. no read when in write mode)
|
||||||
|
-- write(self, value, ...) boolean: writes each value (params list) and returns success
|
||||||
|
-- read(self, n: number) string: return string of n bytes, nil when no more bytes available
|
||||||
|
-- Optional
|
||||||
|
-- seek(self, whence [string], offset [number]) number: move file handle from whence by offset, return offset result
|
||||||
|
-- close(self) boolean: close the file handle. Note that if your open method allocated resources, you'll need to release them in close
|
||||||
|
|
||||||
|
-- ### devfs dir methods ###
|
||||||
|
-- Required
|
||||||
|
-- list() string[]: return list of child point names
|
||||||
|
-- if you use new_devfs_dir, set metatable on .points with __pairs and __index if you want a dynamic list of files
|
||||||
|
-- open(path, mode) file (table): return a file handle to path (path is relative)
|
||||||
|
-- it would be nice to make open() optional, but devfs doesn't know where you might store your point handlers, if you even have any
|
||||||
|
-- Optional
|
||||||
|
-- size(path) number
|
||||||
|
-- lastModified(path) number
|
||||||
|
-- isDirectory(path) boolean -- default returns false. Having dynamic dirs is considered advanced
|
||||||
|
-- remove(path) boolean
|
||||||
|
-- rename(path) boolean
|
||||||
|
-- exists(path) boolean -- default checks path against list() results
|
||||||
|
|
||||||
|
-- /dev is a special handler
|
||||||
|
|
||||||
|
local function devfs_load(key)
|
||||||
|
return require("tools/devfs/" .. key)
|
||||||
|
end
|
||||||
|
|
||||||
|
devfs.create("null", devfs_load("null"))
|
||||||
|
devfs.create("random", devfs_load("random"))
|
||||||
|
if comp.isAvailable("eeprom") then
|
||||||
|
devfs.create("eeprom", devfs_load("eeprom"))
|
||||||
|
devfs.create("eeprom-data", devfs_load("eeprom-data"))
|
||||||
|
end
|
||||||
|
|
||||||
|
return devfs
|
||||||
|
@ -112,9 +112,7 @@ function filesystem.setAutorunEnabled(value)
|
|||||||
saveConfig()
|
saveConfig()
|
||||||
end
|
end
|
||||||
|
|
||||||
function filesystem.segments(path)
|
filesystem.segments = segments
|
||||||
return segments(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
function filesystem.canonical(path)
|
function filesystem.canonical(path)
|
||||||
local result = table.concat(segments(path), "/")
|
local result = table.concat(segments(path), "/")
|
||||||
@ -367,7 +365,11 @@ function filesystem.makeDirectory(path)
|
|||||||
end
|
end
|
||||||
local node, rest = findNode(path)
|
local node, rest = findNode(path)
|
||||||
if node.fs and rest then
|
if node.fs and rest then
|
||||||
return node.fs.makeDirectory(rest)
|
local success, reason = node.fs.makeDirectory(rest)
|
||||||
|
if not success and not reason and node.fs.isReadOnly() then
|
||||||
|
reason = "filesystem is readonly"
|
||||||
|
end
|
||||||
|
return success, reason
|
||||||
end
|
end
|
||||||
if node.fs then
|
if node.fs then
|
||||||
return nil, "virtual directory with that name already exists"
|
return nil, "virtual directory with that name already exists"
|
||||||
@ -502,11 +504,12 @@ function filesystem.open(path, mode)
|
|||||||
checkArg(1, path, "string")
|
checkArg(1, path, "string")
|
||||||
mode = tostring(mode or "r")
|
mode = tostring(mode or "r")
|
||||||
checkArg(2, mode, "string")
|
checkArg(2, mode, "string")
|
||||||
|
|
||||||
assert(({r=true, rb=true, w=true, wb=true, a=true, ab=true})[mode],
|
assert(({r=true, rb=true, w=true, wb=true, a=true, ab=true})[mode],
|
||||||
"bad argument #2 (r[b], w[b] or a[b] expected, got " .. mode .. ")")
|
"bad argument #2 (r[b], w[b] or a[b] expected, got " .. mode .. ")")
|
||||||
|
|
||||||
local node, rest = findNode(path)
|
local node, rest = findNode(path)
|
||||||
if not node.fs or not rest then
|
if not node.fs or not rest or (({r=true,rb=true})[mode] and not node.fs.exists(rest)) then
|
||||||
return nil, "file not found"
|
return nil, "file not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
local guid = {}
|
|
||||||
|
|
||||||
function guid.toHex(n)
|
|
||||||
if type(n) ~= 'number' then
|
|
||||||
return nil, string.format("toHex only converts numbers to strings, %s is not a string, but a %s", tostring(n), type(n))
|
|
||||||
end
|
|
||||||
if n == 0 then
|
|
||||||
return '0'
|
|
||||||
end
|
|
||||||
|
|
||||||
local hexchars = "0123456789abcdef"
|
|
||||||
local result = ""
|
|
||||||
local prefix = "" -- maybe later allow for arg to request 0x prefix
|
|
||||||
if n < 0 then
|
|
||||||
prefix = "-"
|
|
||||||
n = -n
|
|
||||||
end
|
|
||||||
|
|
||||||
while n > 0 do
|
|
||||||
local next = math.floor(n % 16) + 1 -- lua has 1 based array indices
|
|
||||||
n = math.floor(n / 16)
|
|
||||||
result = hexchars:sub(next, next) .. result
|
|
||||||
end
|
|
||||||
|
|
||||||
return prefix .. result
|
|
||||||
end
|
|
||||||
|
|
||||||
function guid.next()
|
|
||||||
-- e.g. 3c44c8a9-0613-46a2-ad33-97b6ba2e9d9a
|
|
||||||
-- 8-4-4-4-12
|
|
||||||
local sets = {8, 4, 4, 4, 12}
|
|
||||||
local result = ""
|
|
||||||
|
|
||||||
local i
|
|
||||||
for _,set in ipairs(sets) do
|
|
||||||
if result:len() > 0 then
|
|
||||||
result = result .. "-"
|
|
||||||
end
|
|
||||||
for i = 1,set do
|
|
||||||
result = result .. guid.toHex(math.random(0, 15))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
return guid
|
|
@ -454,7 +454,7 @@ function --[[@delayloaded-start@]] sh.internal.glob(glob_pattern)
|
|||||||
|
|
||||||
local function magical(s)
|
local function magical(s)
|
||||||
for _,glob_rule in ipairs(sh.internal.globbers) do
|
for _,glob_rule in ipairs(sh.internal.globbers) do
|
||||||
if s:match("[^%%]-"..text.escapeMagic(glob_rule[2])) then
|
if (" "..s):match("[^%%]"..text.escapeMagic(glob_rule[2])) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -464,7 +464,6 @@ function --[[@delayloaded-start@]] sh.internal.glob(glob_pattern)
|
|||||||
local root = is_abs and '' or shell.getWorkingDirectory():gsub("([^/])$","%1/")
|
local root = is_abs and '' or shell.getWorkingDirectory():gsub("([^/])$","%1/")
|
||||||
local paths = {is_abs and "/" or ''}
|
local paths = {is_abs and "/" or ''}
|
||||||
local relative_separator = ''
|
local relative_separator = ''
|
||||||
|
|
||||||
for i,segment in ipairs(segments) do
|
for i,segment in ipairs(segments) do
|
||||||
local enclosed_pattern = string.format("^(%s)/?$", segment)
|
local enclosed_pattern = string.format("^(%s)/?$", segment)
|
||||||
local next_paths = {}
|
local next_paths = {}
|
||||||
|
@ -243,14 +243,17 @@ function term.readKeyboard(ops)
|
|||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local killed, name, address, char, code = term.internal.pull(input)
|
local ok, name, address, char, code = term.internal.pull(input)
|
||||||
|
if not term.isAvailable() then
|
||||||
|
return
|
||||||
|
end
|
||||||
-- we have to keep checking what kb is active in case it is switching during use
|
-- we have to keep checking what kb is active in case it is switching during use
|
||||||
-- we could have multiple screens, each with keyboards active
|
-- we could have multiple screens, each with keyboards active
|
||||||
local main_kb = term.keyboard(w)
|
local main_kb = term.keyboard(w)
|
||||||
local main_sc = term.screen(w)
|
local main_sc = term.screen(w)
|
||||||
local c = nil
|
local c
|
||||||
local backup_cache = hints.cache
|
local backup_cache = hints.cache
|
||||||
if name == "interrupted" or name == "term_unavailable" then
|
if name == "interrupted" then
|
||||||
draw("^C\n",true)
|
draw("^C\n",true)
|
||||||
return ""
|
return ""
|
||||||
elseif address == main_kb or address == main_sc then
|
elseif address == main_kb or address == main_sc then
|
||||||
|
@ -288,4 +288,93 @@ function --[[@delayloaded-start@]] text.internal.normalize(words, omitQuotes)
|
|||||||
return norms
|
return norms
|
||||||
end --[[@delayloaded-end@]]
|
end --[[@delayloaded-end@]]
|
||||||
|
|
||||||
|
function --[[@delayloaded-start@]] text.internal.seeker(handle, whence, to)
|
||||||
|
if not handle.txt then
|
||||||
|
return nil, "bad file descriptor"
|
||||||
|
end
|
||||||
|
to = to or 0
|
||||||
|
if whence == "cur" then
|
||||||
|
handle.offset = handle.offset + to
|
||||||
|
elseif whence == "set" then
|
||||||
|
handle.offset = to
|
||||||
|
elseif whence == "end" then
|
||||||
|
handle.offset = handle.len + to
|
||||||
|
end
|
||||||
|
handle.offset = math.max(0, math.min(handle.offset, handle.len))
|
||||||
|
return handle.offset
|
||||||
|
end --[[@delayloaded-end@]]
|
||||||
|
|
||||||
|
function --[[@delayloaded-start@]] text.internal.reader(txt)
|
||||||
|
checkArg(1, txt, "string")
|
||||||
|
local reader =
|
||||||
|
{
|
||||||
|
txt = txt,
|
||||||
|
len = unicode.len(txt),
|
||||||
|
offset = 0,
|
||||||
|
read = function(_, n)
|
||||||
|
checkArg(1, n, "number")
|
||||||
|
if not _.txt then
|
||||||
|
return nil, "bad file descriptor"
|
||||||
|
end
|
||||||
|
if _.offset >= _.len then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
local last_offset = _.offset
|
||||||
|
_:seek("cur", n)
|
||||||
|
local next = unicode.sub(_.txt, last_offset + 1, _.offset)
|
||||||
|
return next
|
||||||
|
end,
|
||||||
|
seek = text.internal.seeker,
|
||||||
|
close = function(_)
|
||||||
|
if not _.txt then
|
||||||
|
return nil, "bad file descriptor"
|
||||||
|
end
|
||||||
|
_.txt = nil
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return reader
|
||||||
|
end --[[@delayloaded-end@]]
|
||||||
|
|
||||||
|
function --[[@delayloaded-start@]] text.internal.writer(ostream, append_txt)
|
||||||
|
if type(ostream) == "table" then
|
||||||
|
local mt = getmetatable(ostream) or {}
|
||||||
|
checkArg(1, mt.__call, "function")
|
||||||
|
end
|
||||||
|
checkArg(1, ostream, "function", "table")
|
||||||
|
checkArg(2, append_txt, "string", "nil")
|
||||||
|
local writer =
|
||||||
|
{
|
||||||
|
txt = "",
|
||||||
|
offset = 0,
|
||||||
|
len = 0,
|
||||||
|
write = function(_, ...)
|
||||||
|
if not _.txt then
|
||||||
|
return nil, "bad file descriptor"
|
||||||
|
end
|
||||||
|
local pre, vs, pos = unicode.sub(_.txt, 1, _.offset), {}, unicode.sub(_.txt, _.offset + 1)
|
||||||
|
for i,v in ipairs({...}) do
|
||||||
|
table.insert(vs, v)
|
||||||
|
end
|
||||||
|
vs = table.concat(vs)
|
||||||
|
_:seek("cur", unicode.len(vs))
|
||||||
|
_.txt = pre .. vs .. pos
|
||||||
|
_.len = unicode.len(_.txt)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
seek = text.internal.seeker,
|
||||||
|
close = function(_)
|
||||||
|
if not _.txt then
|
||||||
|
return nil, "bad file descriptor"
|
||||||
|
end
|
||||||
|
ostream((append_txt or "") .. _.txt)
|
||||||
|
_.txt = nil
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return writer
|
||||||
|
end --[[@delayloaded-end@]]
|
||||||
|
|
||||||
return text, local_env
|
return text, local_env
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
local comp = require("component")
|
||||||
|
local text = require("text")
|
||||||
|
|
||||||
|
if not comp.isAvailable("eeprom") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
open = function(mode)
|
||||||
|
if ({r=true, rb=true})[mode] then
|
||||||
|
return text.internal.reader(comp.eeprom.getData())
|
||||||
|
end
|
||||||
|
return text.internal.writer(comp.eeprom.setData, ({a=true,ab=true})[mode] and comp.eeprom.getData())
|
||||||
|
end,
|
||||||
|
size = function()
|
||||||
|
return string.len(comp.eeprom.getData())
|
||||||
|
end
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
local comp = require("component")
|
||||||
|
local text = require("text")
|
||||||
|
|
||||||
|
if not comp.isAvailable("eeprom") then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
{
|
||||||
|
open = function(mode)
|
||||||
|
if ({r=true, rb=true})[mode] then
|
||||||
|
return text.internal.reader(comp.eeprom.get())
|
||||||
|
end
|
||||||
|
return text.internal.writer(comp.eeprom.set, ({a=true,ab=true})[mode] and comp.eeprom.get())
|
||||||
|
end,
|
||||||
|
size = function()
|
||||||
|
return string.len(comp.eeprom.get())
|
||||||
|
end
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
open = function(mode)
|
||||||
|
if not mode or not mode:match("[wa]") then
|
||||||
|
return nil, "write only"
|
||||||
|
end
|
||||||
|
return
|
||||||
|
{
|
||||||
|
write = function() end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
return
|
||||||
|
{
|
||||||
|
open = function(mode)
|
||||||
|
if mode and not mode:match("r") then
|
||||||
|
return nil, "read only"
|
||||||
|
end
|
||||||
|
return
|
||||||
|
{
|
||||||
|
read = function(self, n)
|
||||||
|
local chars = {}
|
||||||
|
for i=1,n do
|
||||||
|
table.insert(chars,string.char(math.random(0,255)))
|
||||||
|
end
|
||||||
|
return table.concat(chars)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
size = function()
|
||||||
|
return math.huge
|
||||||
|
end
|
||||||
|
}
|
@ -171,16 +171,11 @@ options.setboot = source.prop.setboot and not options.nosetboot
|
|||||||
options.reboot = source.prop.reboot and not options.noreboot
|
options.reboot = source.prop.reboot and not options.noreboot
|
||||||
options.source_dir = fs.canonical(source.prop.fromDir or options.fromDir or "") .. '/.'
|
options.source_dir = fs.canonical(source.prop.fromDir or options.fromDir or "") .. '/.'
|
||||||
|
|
||||||
local installer_path = options.source_root .. "/.install"
|
|
||||||
if fs.exists(installer_path) then
|
|
||||||
os.exit(loadfile("/lib/tools/install_utils.lua", "bt", _G)('install', options))
|
|
||||||
end
|
|
||||||
|
|
||||||
local cp_args =
|
local cp_args =
|
||||||
{
|
{
|
||||||
"-vrx" .. (options.update and "ui" or ""),
|
"-vrx" .. (options.update and "ui" or ""),
|
||||||
options.source_root .. options.source_dir,
|
options.source_root .. options.source_dir,
|
||||||
options.target_root .. options.target_dir
|
options.target_root:gsub("//","/") .. options.target_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
local source_display = (source.prop or {}).label or source.dev.getLabel() or source.path
|
local source_display = (source.prop or {}).label or source.dev.getLabel() or source.path
|
||||||
@ -194,6 +189,11 @@ if not ((io.read() or "n").."y"):match("^%s*[Yy]") then
|
|||||||
os.exit()
|
os.exit()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local installer_path = options.source_root .. "/.install"
|
||||||
|
if fs.exists(installer_path) then
|
||||||
|
os.exit(loadfile("/lib/tools/install_utils.lua", "bt", _G)('install', options))
|
||||||
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
setlabel = options.setlabel,
|
setlabel = options.setlabel,
|
||||||
|
@ -41,18 +41,18 @@ end
|
|||||||
if cmd == 'select' then
|
if cmd == 'select' then
|
||||||
if #options.sources == 0 then
|
if #options.sources == 0 then
|
||||||
if options.source_label then
|
if options.source_label then
|
||||||
io.stderr:write("No install source matched given label: " .. options.source_label .. '\n')
|
io.stderr:write("Nothing to install labeled: " .. options.source_label .. '\n')
|
||||||
elseif options.from then
|
elseif options.from then
|
||||||
io.stderr:write("No install source found: " .. options.from .. '\n')
|
io.stderr:write("Nothing to install from: " .. options.from .. '\n')
|
||||||
else
|
else
|
||||||
io.stderr:write("Could not find any available installations\n")
|
io.stderr:write("Nothing to install\n")
|
||||||
end
|
end
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if #options.targets == 0 then
|
if #options.targets == 0 then
|
||||||
if options.to then
|
if options.to then
|
||||||
io.stderr:write("No such filesystem to install to: " .. options.to .. '\n')
|
io.stderr:write("No such target to install to: " .. options.to .. '\n')
|
||||||
else
|
else
|
||||||
io.stderr:write("No writable disks found, aborting\n")
|
io.stderr:write("No writable disks found, aborting\n")
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
local uuid = {}
|
||||||
|
|
||||||
|
function uuid.next()
|
||||||
|
-- e.g. 3c44c8a9-0613-46a2-ad33-97b6ba2e9d9a
|
||||||
|
-- 8-4-4-4-12 (halved sizes because bytes make hex pairs)
|
||||||
|
local sets = {4, 2, 2, 2, 6}
|
||||||
|
local result = ""
|
||||||
|
|
||||||
|
local i
|
||||||
|
for _,set in ipairs(sets) do
|
||||||
|
if result:len() > 0 then
|
||||||
|
result = result .. "-"
|
||||||
|
end
|
||||||
|
for i = 1,set do
|
||||||
|
result = result .. string.format("%02x", math.random(0, 255))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
return uuid
|
@ -9,10 +9,10 @@ DESCRIPTION
|
|||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
--from=ADDR
|
--from=ADDR
|
||||||
Specifies the source filesystem or its root path. ADDR can be the device guid or a directory path. If this is a directory path, it represents a root path to install from. This option can also be used to specify source paths that would otherwise be ignored, those being devfs, tmpfs, and the rootfs. e.g. --from=/tmp . Note that if both --from and a [name] is given, install expects the source path to have a .prop defining the same name. See .prop for more details.
|
Specifies the source filesystem or its root path. ADDR can be the device uuid or a directory path. If this is a directory path, it represents a root path to install from. This option can also be used to specify source paths that would otherwise be ignored, those being devfs, tmpfs, and the rootfs. e.g. --from=/tmp . Note that if both --from and a [name] is given, install expects the source path to have a .prop defining the same name. See .prop for more details.
|
||||||
|
|
||||||
--to=ADDR
|
--to=ADDR
|
||||||
Same as --from but specifies the target filesystem by guid or its root path. This option can also be used to specify filesystems that are otherwise ignored including tmpfs. i.e. --to=ADDR where ADDR matches the tmpfs device address or its mount point path. e.g. --to=/tmp
|
Same as --from but specifies the target filesystem by uuid or its root path. This option can also be used to specify filesystems that are otherwise ignored including tmpfs. i.e. --to=ADDR where ADDR matches the tmpfs device address or its mount point path. e.g. --to=/tmp
|
||||||
|
|
||||||
--fromDir=PATH
|
--fromDir=PATH
|
||||||
Install PATH from source. PATH is relative to the root of the source filesystem or path given by --from. The default is .
|
Install PATH from source. PATH is relative to the root of the source filesystem or path given by --from. The default is .
|
||||||
|
@ -302,7 +302,7 @@ leashUpgrade {
|
|||||||
}
|
}
|
||||||
navigationUpgrade {
|
navigationUpgrade {
|
||||||
input: [[ingotGold, compass, ingotGold]
|
input: [[ingotGold, compass, ingotGold]
|
||||||
["oc:circuitChip2", {item=map, subID=any}, "oc:circuitChip2"]
|
["oc:circuitChip2", {item=filled_map, subID=any}, "oc:circuitChip2"]
|
||||||
[ingotGold, potion, ingotGold]]
|
[ingotGold, potion, ingotGold]]
|
||||||
}
|
}
|
||||||
pistonUpgrade {
|
pistonUpgrade {
|
||||||
|
@ -144,7 +144,7 @@ generatorUpgrade {
|
|||||||
navigationUpgrade {
|
navigationUpgrade {
|
||||||
# 2 = MV Casing
|
# 2 = MV Casing
|
||||||
input: [[{block="gt.blockcasings", subID=2}, compass, screwStainlessSteel]
|
input: [[{block="gt.blockcasings", subID=2}, compass, screwStainlessSteel]
|
||||||
["oc:circuitChip3", {item=map, subID=any}, "oc:circuitChip3"]
|
["oc:circuitChip3", {item=filled_map, subID=any}, "oc:circuitChip3"]
|
||||||
[screwStainlessSteel, potion, craftingToolScrewdriver]]
|
[screwStainlessSteel, potion, craftingToolScrewdriver]]
|
||||||
}
|
}
|
||||||
signUpgrade {
|
signUpgrade {
|
||||||
@ -341,4 +341,4 @@ screen3 {
|
|||||||
input: [[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolWrench]
|
input: [[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolWrench]
|
||||||
["oc:circuitChip3", "oc:screen2", "oc:circuitChip3"]
|
["oc:circuitChip3", "oc:screen2", "oc:circuitChip3"]
|
||||||
[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolScrewdriver]]
|
[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolScrewdriver]]
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ inventoryControllerUpgrade {
|
|||||||
}
|
}
|
||||||
navigationUpgrade {
|
navigationUpgrade {
|
||||||
input: [[ingotGold, compass, ingotGold]
|
input: [[ingotGold, compass, ingotGold]
|
||||||
["oc:circuitChip3", {item=map, subID=any}, "oc:circuitChip3"]
|
["oc:circuitChip3", {item=filled_map, subID=any}, "oc:circuitChip3"]
|
||||||
[ingotGold, potion, ingotGold]]
|
[ingotGold, potion, ingotGold]]
|
||||||
}
|
}
|
||||||
signUpgrade {
|
signUpgrade {
|
||||||
|
@ -14,7 +14,7 @@ import org.apache.logging.log4j.Logger
|
|||||||
|
|
||||||
@Mod(modid = OpenComputers.ID, name = OpenComputers.Name,
|
@Mod(modid = OpenComputers.ID, name = OpenComputers.Name,
|
||||||
version = OpenComputers.Version,
|
version = OpenComputers.Version,
|
||||||
modLanguage = "scala", useMetadata = true, acceptedMinecraftVersions = "[@MCVERSION@,@MCVERSION@+)")
|
modLanguage = "scala", useMetadata = true /*@MCVERSIONDEP@*/)
|
||||||
object OpenComputers {
|
object OpenComputers {
|
||||||
final val ID = "OpenComputers"
|
final val ID = "OpenComputers"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user