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 b05a8b6b0..5a15b1cf9 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/cp.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/cp.lua @@ -7,6 +7,8 @@ if #args < 2 then io.write(" -i: prompt before overwrite (overrides -n option).\n") io.write(" -n: do not overwrite an existing file.\n") io.write(" -r: copy directories recursively.\n") + io.write(" -u: copy only when the SOURCE file differs from the destination\n") + io.write(" file or when the destination file is missing.\n") io.write(" -v: verbose output.") return end @@ -19,7 +21,7 @@ local to = shell.resolve(args[#args]) local function status(from, to) if options.v then - print(from .. " -> " .. to) + io.write(from .. " -> " .. to .. "\n") end os.sleep(0) -- allow interrupting end @@ -27,9 +29,33 @@ end local result, reason local function prompt(message) - io.write(message .. " ") + io.write(message .. " [Y/n]\n") local result = io.read() - return result and result:sub(1, 1):lower() == "y" + return result and (result == "" or result:sub(1, 1):lower() == "y") +end + +local function areEqual(path1, path2) + local f1 = io.open(path1, "rb") + if not f1 then + return nil, "could not open `" .. path1 .. "' for update test" + end + local f2 = io.open(path2, "rb") + if not f2 then + f1:close() + return nil, "could not open `" .. path2 .. "' for update test" + end + local result = true + local chunkSize = 4 * 1024 + repeat + local s1, s2 = f1:read(chunkSize), f2:read(chunkSize) + if s1 ~= s2 then + result = false + break + end + until not s1 or not s2 + f1:close() + f2:close() + return result end local function recurse(fromPath, toPath) @@ -70,6 +96,11 @@ local function recurse(fromPath, toPath) return nil, "cannot overwrite directory `" .. toPath .. "' with non-directory" end else + if options.u then + if areEqual(fromPath, toPath) then + return true + end + end if options.i then if not prompt("overwrite `" .. toPath .. "'?") then return true diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/install.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/install.lua index 44b2fe959..0ded2c5b1 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/install.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/install.lua @@ -1,22 +1,24 @@ local component = require("component") local computer = require("computer") local event = require("event") +local filesystem = require("filesystem") local unicode = require("unicode") local shell = require("shell") local args, options = shell.parse(...) +local fromAddress = options.from and component.get(options.from) or filesystem.get(os.getenv("_")).address local candidates = {} for address in component.list("filesystem") do local dev = component.proxy(address) - if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() then + if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() and dev.address ~= fromAddress then table.insert(candidates, dev) end end if #candidates == 0 then - print("No writable disks found, aborting.") - return + io.write("No writable disks found, aborting.\n") + os.exit() end for i = 1, #candidates do @@ -26,45 +28,53 @@ for i = 1, #candidates do else label = candidates[i].address end - print(i .. ") " .. label) + io.write(i .. ") " .. label .. "\n") end -print("To select the device to install to, please enter a number between 1 and " .. #candidates .. ".") -print("Press 'q' to cancel the installation.") +io.write("To select the device to install to, please enter a number between 1 and " .. #candidates .. ".\n") +io.write("Press 'q' to cancel the installation.\n") local choice while not choice do result = io.read() if result:sub(1, 1):lower() == "q" then - return + os.exit() end local number = tonumber(result) if number and number > 0 and number <= #candidates then choice = candidates[number] else - print("Invalid input, please try again.") + io.write("Invalid input, please try again.\n") + end +end + +local function findMount(address) + for fs, path in filesystem.mounts() do + if fs.address == component.get(address) then + return path + end end end -candidates = nil local name = options.name or "OpenOS" -print("Installing " .. name .." to device " .. (choice.getLabel() or choice.address)) +io.write("Installing " .. name .." to device " .. (choice.getLabel() or choice.address) .. "\n") os.sleep(0.25) -local origin = options.from and options.from:sub(1,3) or computer.getBootAddress():sub(1, 3) -local fromDir = options.fromDir or "/" -local mnt = choice.address:sub(1, 3) -local result, reason = os.execute("/bin/cp -vr /mnt/" .. origin .. fromDir .. "* /mnt/" .. mnt .. "/") +local cpPath = filesystem.concat(findMount(filesystem.get(os.getenv("_")).address), "bin/cp") +local cpOptions = "-vr" .. (options.u and "ui " or "") +local cpSource = filesystem.concat(findMount(fromAddress), options.fromDir or "/", "*") +local cpDest = findMount(choice.address) .. "/" +local result, reason = os.execute(cpPath .. " " .. cpOptions .. " " .. cpSource .. " " .. cpDest) if not result then error(reason, 0) end if not options.nolabelset then pcall(choice.setLabel, name) end if not options.noreboot then - print("All done! " .. ((not options.noboot) and "Set as boot device and r" or "R") .. "eboot now? [Y/n]") + io.write("All done! " .. ((not options.noboot) and "Set as boot device and r" or "R") .. "eboot now? [Y/n]\n") local result = io.read() if not result or result == "" or result:sub(1, 1):lower() == "y" then if not options.noboot then computer.setBootAddress(choice.address)end - print("\nRebooting now!") + io.write("\nRebooting now!\n") computer.shutdown(true) end end -print("Returning to shell.") +io.write("Returning to shell.\n") diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/sh.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/sh.lua index 0a47315a2..01a16118c 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/sh.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/sh.lua @@ -17,6 +17,9 @@ function memoryStream:close() end function memoryStream:seek() + if self.closed then + error("attempt to use a closed stream") + end return nil, "bad file descriptor" end @@ -24,8 +27,9 @@ function memoryStream:read(n) if self.closed then if self.buffer == "" and self.redirect.read then return self.redirect.read:read(n) + else + error("attempt to use a closed stream") end - return nil -- eof end if self.buffer == "" then self.args = table.pack(coroutine.yield(table.unpack(self.result))) @@ -36,19 +40,24 @@ function memoryStream:read(n) end function memoryStream:write(value) - local ok + if not self.redirect.write and self.closed then + error("attempt to use a closed stream") + end if self.redirect.write then - ok = self.redirect.write:write(value) + self.redirect.write:write(value) end if not self.closed then self.buffer = self.buffer .. value self.result = table.pack(coroutine.resume(self.next, table.unpack(self.args))) - ok = true + if coroutine.status(self.next) == "dead" then + self:close() + end + if not self.result[1] then + error(self.result[2], 0) + end + table.remove(self.result, 1) end - if ok then - return true - end - return nil, "stream is closed" + return true end function memoryStream.new() @@ -328,16 +337,15 @@ local function execute(env, command, ...) result = table.pack(coroutine.resume(threads[i], table.unpack(args, 2, args.n))) if coroutine.status(threads[i]) ~= "dead" then args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n))) - elseif not args[1] then - args[2] = debug.traceback(threads[i], args[2]) end end if pipes[i] then - pipes[i]:close() + pcall(pipes[i].close, pipes[i]) end if not result[1] then if type(result[2]) == "table" and result[2].reason == "terminated" then if result[2].code then + result[1] = true result.n = 1 else result[2] = "terminated" @@ -473,7 +481,7 @@ if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then term.write("\n") end if not result then - io.stderr:write((tostring(reason) or "unknown error").. "\n") + io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n") end end end @@ -491,7 +499,7 @@ elseif #args == 0 and (io.input() ~= io.stdin) then elseif command ~= "" then local result, reason = os.execute(command) if not result then - io.stderr:write((tostring(reason) or "unknown error").. "\n") + io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n") end end end diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/unset.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/unset.lua index 8691b8ad6..325327d87 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/bin/unset.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/bin/unset.lua @@ -1,7 +1,7 @@ local args = {...} if #args < 1 then - print("Usage: unset [ [...]]") + io.write("Usage: unset [ [...]]\n") else for _, k in ipairs(args) do os.setenv(k, nil) diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/init.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/init.lua index eb916de41..4edad2a25 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/init.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/init.lua @@ -175,7 +175,7 @@ local function motd() os.execute("/etc/motd") else f:seek("set", 0) - print(f:read("*a")) + io.write(f:read("*a") .. "\n") f:close() end end @@ -185,7 +185,7 @@ while true do local result, reason = os.execute(os.getenv("SHELL")) if not result then io.stderr:write((tostring(reason) or "unknown error") .. "\n") - print("Press any key to continue.") + io.write("Press any key to continue.\n") os.sleep(0.5) require("event").pull("key") end diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/buffer.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/buffer.lua index b1deaf408..7f78cef29 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/buffer.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/buffer.lua @@ -25,7 +25,7 @@ function buffer.new(mode, stream) end function buffer:close() - if self.mode.w or self.mode.a then + if not self.closed and (self.mode.w or self.mode.a) then self:flush() end self.closed = true diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/event.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/event.lua index fa9cbfaaa..c9521395e 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/event.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/event.lua @@ -210,7 +210,6 @@ function event.pullFiltered(...) if not (seconds or filter) or filter == nil or filter(table.unpack(signal, 1, signal.n)) then return table.unpack(signal, 1, signal.n) end - until computer.uptime() >= deadline end 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 617441312..a007f09e9 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/term.lua @@ -383,7 +383,7 @@ function term.read(history, dobreak, hint, pwchar, filter) end term.setCursorBlink(false) if term.getCursor() > 1 and dobreak ~= false then - print() + term.write("\n") end end