diff --git a/build.gradle b/build.gradle index ee3e9504d..3001c6d25 100644 --- a/build.gradle +++ b/build.gradle @@ -286,7 +286,7 @@ minecraft { mappings = "stable_22" replace "@VERSION@", project.simpleVersion - replace "@MCVERSION@", config.minecraft.version + replace "/*@MCVERSIONDEP@*/", ", acceptedMinecraftVersions = \"[${config.minecraft.version},${config.minecraft.version}+)\"" } processResources { diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua index 8772e44e4..6a943ab78 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/cat.lua @@ -13,9 +13,14 @@ for i = 1, #args do io.stderr:write(string.format('cat %s: Is a directory\n', arg)) ec = 1 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 - 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 else repeat diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/cp.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/cp.lua index 82be2fc9c..cd4c8401c 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/cp.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/cp.lua @@ -148,12 +148,14 @@ end local to = shell.resolve(args[#args]) for i = 1, #args - 1 do - local fromPath, cuts = args[i]:gsub("(/%.%.?)$", "%1") - fromPath = shell.resolve(fromPath) + local arg = args[i] + 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 - -- fromPath ending with /. indicates copying the contents of fromPath - -- in which case (cuts>0) we do not append fromPath name to toPath - if cuts == 0 and fs.isDirectory(toPath) then + -- we do not append fromPath name to toPath in case of contents_of copy + if not contents_of and fs.isDirectory(toPath) then toPath = fs.concat(toPath, fs.name(fromPath)) end result, reason = recurse(fromPath, toPath) diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/mkdir.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/mkdir.lua index 49fb40bc0..3e8376327 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/mkdir.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/mkdir.lua @@ -19,7 +19,7 @@ for i = 1, #args do reason = "unknown reason" end end - io.stderr:write(path .. ": " .. reason .. "\n") + io.stderr:write("mkdir: cannot create directory '" .. tostring(args[i]) .. "': " .. reason .. "\n") ec = 1 end end diff --git a/src/main/resources/assets/opencomputers/loot/openos/bin/mktmp.lua b/src/main/resources/assets/opencomputers/loot/openos/bin/mktmp.lua index d01ab987c..7e6327f3c 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/bin/mktmp.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/bin/mktmp.lua @@ -1,12 +1,12 @@ local fs = require("filesystem") -local guid = require("guid") +local uuid = require("uuid") local shell = require("shell") local sh = require("sh") local touch = loadfile(shell.resolve("touch", "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" io.stderr:write(errorMessage .. '\n') return false, errorMessage @@ -58,7 +58,7 @@ if not fs.exists(prefix) then end while true do - local tmp = prefix .. guid.next() + local tmp = prefix .. uuid.next() if not fs.exists(tmp) then local ok, reason diff --git a/src/main/resources/assets/opencomputers/loot/openos/boot/10_devfs.lua b/src/main/resources/assets/opencomputers/loot/openos/boot/10_devfs.lua index 0da8de199..3cb2c8604 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/boot/10_devfs.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/boot/10_devfs.lua @@ -1,6 +1,7 @@ require("filesystem").mount( setmetatable({ - isReadOnly = function()return false end + isReadOnly = function()return false end, + address = require("uuid").next() }, { __index=function(tbl,key)return require("devfs")[key]end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/devfs.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/devfs.lua index bee88b701..8848173cf 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/devfs.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/devfs.lua @@ -1,111 +1,292 @@ 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" end -function proxy.setLabel(value) +function devfs.setLabel(value) error("drive does not support labeling") end -function proxy.spaceTotal() +function devfs.spaceTotal() return 0 end -function proxy.spaceUsed() +function devfs.spaceUsed() return 0 end -function proxy.exists(path) - return not not proxy.points[path] +function devfs.makeDirectory(path) + return false, "to create dirs in devfs use devfs.create" end -function proxy.size(path) - return 0 -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,...) +function devfs.read(h,...) + if not h.read then return nil, bfd end return h:read(...) end -function proxy.seek(h,...) +function devfs.seek(h,...) + if not h.seek then return nil, bfd end return h:seek(...) end -function proxy.write(h,...) +function devfs.write(h,...) + if not h.write then return nil, bfd end return h:write(...) end -function proxy.create(path, handle) - handle.close = handle.close or nop - proxy.points[path] = handle - return true +function devfs.close(h, ...) + if not h.close then return nil, bfd end + return h:close(...) end -proxy.create("null", {write = nop}) -proxy.create("random", {read = function(_,n) - local chars = {} - for i=1,n do - table.insert(chars,string.char(math.random(0,255))) - end - return table.concat(chars) -end}) +-- devfs.create creates a new dev point at path +-- 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") +-- 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] +-- 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) -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 diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/filesystem.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/filesystem.lua index ea6896f67..f46c8212a 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/filesystem.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/filesystem.lua @@ -112,9 +112,7 @@ function filesystem.setAutorunEnabled(value) saveConfig() end -function filesystem.segments(path) - return segments(path) -end +filesystem.segments = segments function filesystem.canonical(path) local result = table.concat(segments(path), "/") @@ -367,7 +365,11 @@ function filesystem.makeDirectory(path) end local node, rest = findNode(path) 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 if node.fs then return nil, "virtual directory with that name already exists" @@ -502,11 +504,12 @@ function filesystem.open(path, mode) checkArg(1, path, "string") mode = tostring(mode or "r") checkArg(2, mode, "string") + 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 .. ")") 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" end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/guid.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/guid.lua deleted file mode 100644 index 13cfc7217..000000000 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/guid.lua +++ /dev/null @@ -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 diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua index 159e9072d..bb90f56d4 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/sh.lua @@ -454,7 +454,7 @@ function --[[@delayloaded-start@]] sh.internal.glob(glob_pattern) local function magical(s) 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 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 paths = {is_abs and "/" or ''} local relative_separator = '' - for i,segment in ipairs(segments) do local enclosed_pattern = string.format("^(%s)/?$", segment) local next_paths = {} diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua index fed3a783c..35770953d 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/term.lua @@ -243,14 +243,17 @@ function term.readKeyboard(ops) end 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 could have multiple screens, each with keyboards active local main_kb = term.keyboard(w) local main_sc = term.screen(w) - local c = nil + local c local backup_cache = hints.cache - if name == "interrupted" or name == "term_unavailable" then + if name == "interrupted" then draw("^C\n",true) return "" elseif address == main_kb or address == main_sc then diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/text.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/text.lua index 3556923b6..353efb132 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/text.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/text.lua @@ -288,4 +288,93 @@ function --[[@delayloaded-start@]] text.internal.normalize(words, omitQuotes) return norms 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 diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom-data.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom-data.lua new file mode 100644 index 000000000..2aea1a0ef --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom-data.lua @@ -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 +} diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom.lua new file mode 100644 index 000000000..dbc9ceafb --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/eeprom.lua @@ -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 +} diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/null.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/null.lua new file mode 100644 index 000000000..c3710917a --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/null.lua @@ -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 +} diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/random.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/random.lua new file mode 100644 index 000000000..15c08617a --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/devfs/random.lua @@ -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 +} diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_basics.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_basics.lua index eaa2c8591..bd4188080 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_basics.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_basics.lua @@ -171,16 +171,11 @@ options.setboot = source.prop.setboot and not options.nosetboot options.reboot = source.prop.reboot and not options.noreboot 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 = { "-vrx" .. (options.update and "ui" or ""), 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 @@ -194,6 +189,11 @@ if not ((io.read() or "n").."y"):match("^%s*[Yy]") then os.exit() 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 { setlabel = options.setlabel, diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_utils.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_utils.lua index cbaae9a70..af48bef83 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_utils.lua +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/tools/install_utils.lua @@ -41,18 +41,18 @@ end if cmd == 'select' then if #options.sources == 0 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 - io.stderr:write("No install source found: " .. options.from .. '\n') + io.stderr:write("Nothing to install from: " .. options.from .. '\n') else - io.stderr:write("Could not find any available installations\n") + io.stderr:write("Nothing to install\n") end os.exit(1) end if #options.targets == 0 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 io.stderr:write("No writable disks found, aborting\n") end diff --git a/src/main/resources/assets/opencomputers/loot/openos/lib/uuid.lua b/src/main/resources/assets/opencomputers/loot/openos/lib/uuid.lua new file mode 100644 index 000000000..ffee13682 --- /dev/null +++ b/src/main/resources/assets/opencomputers/loot/openos/lib/uuid.lua @@ -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 diff --git a/src/main/resources/assets/opencomputers/loot/openos/usr/man/install b/src/main/resources/assets/opencomputers/loot/openos/usr/man/install index 45c3ab25a..03f89af0a 100644 --- a/src/main/resources/assets/opencomputers/loot/openos/usr/man/install +++ b/src/main/resources/assets/opencomputers/loot/openos/usr/man/install @@ -9,10 +9,10 @@ DESCRIPTION OPTIONS --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 - 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 Install PATH from source. PATH is relative to the root of the source filesystem or path given by --from. The default is . diff --git a/src/main/resources/assets/opencomputers/recipes/default.recipes b/src/main/resources/assets/opencomputers/recipes/default.recipes index 66af1dc68..7a9c4ad46 100644 --- a/src/main/resources/assets/opencomputers/recipes/default.recipes +++ b/src/main/resources/assets/opencomputers/recipes/default.recipes @@ -302,7 +302,7 @@ leashUpgrade { } navigationUpgrade { input: [[ingotGold, compass, ingotGold] - ["oc:circuitChip2", {item=map, subID=any}, "oc:circuitChip2"] + ["oc:circuitChip2", {item=filled_map, subID=any}, "oc:circuitChip2"] [ingotGold, potion, ingotGold]] } pistonUpgrade { diff --git a/src/main/resources/assets/opencomputers/recipes/gregtech.recipes b/src/main/resources/assets/opencomputers/recipes/gregtech.recipes index 283d2ee13..2de98266a 100644 --- a/src/main/resources/assets/opencomputers/recipes/gregtech.recipes +++ b/src/main/resources/assets/opencomputers/recipes/gregtech.recipes @@ -144,7 +144,7 @@ generatorUpgrade { navigationUpgrade { # 2 = MV Casing 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]] } signUpgrade { @@ -341,4 +341,4 @@ screen3 { input: [[plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolWrench] ["oc:circuitChip3", "oc:screen2", "oc:circuitChip3"] [plateTitanium, "oc:materialCircuitBoardPrinted", craftingToolScrewdriver]] -} \ No newline at end of file +} diff --git a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes b/src/main/resources/assets/opencomputers/recipes/hardmode.recipes index a7485dcb1..ff093d2cc 100644 --- a/src/main/resources/assets/opencomputers/recipes/hardmode.recipes +++ b/src/main/resources/assets/opencomputers/recipes/hardmode.recipes @@ -169,7 +169,7 @@ inventoryControllerUpgrade { } navigationUpgrade { input: [[ingotGold, compass, ingotGold] - ["oc:circuitChip3", {item=map, subID=any}, "oc:circuitChip3"] + ["oc:circuitChip3", {item=filled_map, subID=any}, "oc:circuitChip3"] [ingotGold, potion, ingotGold]] } signUpgrade { diff --git a/src/main/scala/li/cil/oc/OpenComputers.scala b/src/main/scala/li/cil/oc/OpenComputers.scala index 8cd5866c2..3b3c79b5e 100644 --- a/src/main/scala/li/cil/oc/OpenComputers.scala +++ b/src/main/scala/li/cil/oc/OpenComputers.scala @@ -14,7 +14,7 @@ import org.apache.logging.log4j.Logger @Mod(modid = OpenComputers.ID, name = OpenComputers.Name, version = OpenComputers.Version, - modLanguage = "scala", useMetadata = true, acceptedMinecraftVersions = "[@MCVERSION@,@MCVERSION@+)") + modLanguage = "scala", useMetadata = true /*@MCVERSIONDEP@*/) object OpenComputers { final val ID = "OpenComputers"