194 lines
5.8 KiB
Plaintext
194 lines
5.8 KiB
Plaintext
--:Minify:--
|
|
local cloptions = {
|
|
a = false,
|
|
h = false,
|
|
l = false,
|
|
help = false,
|
|
}
|
|
local inpArgs = { ... }
|
|
local args = {}
|
|
local name = syscall.getTask(syscall.getpid()).name
|
|
|
|
for _, v in pairs(inpArgs) do
|
|
if v:sub(1, 2) == "--" then
|
|
local opt = v:sub(3)
|
|
if cloptions[opt] == nil then
|
|
print(name .. ": unrecognized option '" .. v .. "'.")
|
|
print("try '" .. name .. " --help' for more information.")
|
|
return
|
|
end
|
|
cloptions[opt] = true
|
|
elseif v:sub(1, 1) == "-" then
|
|
for i = 2, #v do
|
|
local opt = v:sub(i, i)
|
|
if cloptions[opt] == nil then
|
|
print(name .. ": invalid option '-" .. opt .. "'.")
|
|
print("try '" .. name .. " --help' for more information.")
|
|
return
|
|
end
|
|
cloptions[opt] = true
|
|
end
|
|
else
|
|
table.insert(args, v)
|
|
end
|
|
end
|
|
|
|
if cloptions.help then
|
|
print("Usage: " .. name .. " [OPTION]... [DIR]")
|
|
print("List all entries in the specified DIRectory, or cwd if not specified.")
|
|
print("")
|
|
print("Options:")
|
|
print(" -a do not ignore entries starting with .")
|
|
print(" -h with -l, print sizes in human readable format")
|
|
print(" -l use a long listing format")
|
|
print(" --help display this help and exit")
|
|
return
|
|
end
|
|
|
|
local fs = require("fs")
|
|
local dir = args[1] or ""
|
|
if dir:sub(1, 1) ~= "/" then
|
|
dir = syscall.getcwd() .. "/" .. dir
|
|
end
|
|
if dir:sub(-1) ~= "/" then dir = dir .. "/" end
|
|
|
|
if not fs.isDir(dir) then
|
|
print(name .. ": cannot access '" .. (args[1] or dir) .. "': no such directory")
|
|
return
|
|
end
|
|
|
|
local function permStr(perms, etype)
|
|
local function b(n) return math.floor(perms / (2^n)) % 2 == 1 end
|
|
local t
|
|
if etype == 0x01 then t = "l"
|
|
elseif etype == nil then t = "-"
|
|
else t = "-" end
|
|
|
|
local ur = b(5) and "r" or "-"
|
|
local uw = b(4) and "w" or "-"
|
|
local ux = b(9) and (b(6) and "s" or "x") or (b(6) and "S" or "-")
|
|
local gr = b(3) and "r" or "-"
|
|
local gw = b(2) and "w" or "-"
|
|
local gx = b(8) and "x" or "-"
|
|
local wr = b(1) and "r" or "-"
|
|
local ww = b(0) and "w" or "-"
|
|
local wx = b(7) and "x" or "-"
|
|
|
|
return t .. ur .. uw .. ux .. gr .. gw .. gx .. wr .. ww .. wx
|
|
end
|
|
|
|
local sizePrefixes = { "K", "M", "G", "T" }
|
|
local function humanSize(size)
|
|
local scale = 0
|
|
while size >= 1024 and scale < #sizePrefixes do
|
|
size = size / 1024
|
|
scale = scale + 1
|
|
end
|
|
if scale == 0 then return tostring(size).."B" end
|
|
if size < 10 then
|
|
return string.format("%.1f%s", size, sizePrefixes[scale])
|
|
end
|
|
return math.floor(size) .. sizePrefixes[scale]
|
|
end
|
|
|
|
local screenSizeStr = syscall.devctl(1, "size")
|
|
local sizeX = tonumber(screenSizeStr:match("^(%d+)")) or 80
|
|
|
|
local list = fs.list(dir)
|
|
if not cloptions.a then
|
|
for i = #list, 1, -1 do
|
|
if list[i]:sub(1, 1) == "." then table.remove(list, i) end
|
|
end
|
|
end
|
|
table.sort(list)
|
|
|
|
if #list == 0 then return end
|
|
|
|
if cloptions.l then
|
|
for _, v in ipairs(list) do
|
|
local fullPath = dir .. v
|
|
local stat = syscall.lstat and syscall.lstat(fullPath) or syscall.stat(fullPath)
|
|
local isDir = fs.isDir(fullPath)
|
|
local isSym = stat and stat.etype == 0x01
|
|
|
|
local typeChar
|
|
if isSym then typeChar = "l"
|
|
elseif isDir then typeChar = "d"
|
|
else typeChar = "-" end
|
|
|
|
local pstr
|
|
if stat and stat.perms then
|
|
pstr = permStr(stat.perms, stat.etype)
|
|
else
|
|
pstr = typeChar .. "---------"
|
|
end
|
|
|
|
local size = (stat and stat.size) or 0
|
|
local sizeStr = cloptions.h and humanSize(size) or tostring(size)
|
|
|
|
local mtime = (stat and stat.modified) and math.floor(stat.modified / 1000) or 0
|
|
|
|
local owner = (stat and tostring(stat.owner)) or "0"
|
|
local group = (stat and tostring(stat.group)) or "0"
|
|
|
|
printInline(pstr .. " " .. owner .. " " .. group .. " ")
|
|
printInline(string.format("%6s", sizeStr) .. " ")
|
|
printInline(tostring(mtime) .. " ")
|
|
|
|
if isSym then
|
|
syscall.devctl(1, "sfgc", 6)
|
|
printInline(v)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
local ok, target = pcall(syscall.readlink, fullPath)
|
|
if ok then
|
|
printInline(" -> ")
|
|
local targetExists = pcall(syscall.stat, fullPath)
|
|
syscall.devctl(1, "sfgc", targetExists and 6 or 2)
|
|
printInline(target)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
end
|
|
elseif isDir then
|
|
syscall.devctl(1, "sfgc", 14)
|
|
printInline(v)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
else
|
|
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
|
syscall.devctl(1, "sfgc", isExec and 3 or 1)
|
|
printInline(v)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
end
|
|
print("")
|
|
end
|
|
return
|
|
end
|
|
|
|
local colWidth = 0
|
|
for _, v in ipairs(list) do
|
|
if #v + 2 > colWidth then colWidth = #v + 2 end
|
|
end
|
|
local numCols = math.max(1, math.floor(sizeX / colWidth))
|
|
|
|
for i, v in ipairs(list) do
|
|
local fullPath = dir .. v
|
|
local isDir = fs.isDir(fullPath)
|
|
local stat = syscall.lstat and syscall.lstat(fullPath) or syscall.stat(fullPath)
|
|
local isSym = stat and stat.etype == 0x01
|
|
|
|
if isSym then
|
|
syscall.devctl(1, "sfgc", 6)
|
|
elseif isDir then
|
|
syscall.devctl(1, "sfgc", 14)
|
|
else
|
|
local isExec = stat and stat.perms and (math.floor(stat.perms / (2^9)) % 2 == 1)
|
|
syscall.devctl(1, "sfgc", isExec and 3 or 1)
|
|
end
|
|
|
|
printInline(v)
|
|
syscall.devctl(1, "sfgc", 1)
|
|
printInline((" "):rep(colWidth - #v))
|
|
|
|
if i % numCols == 0 then print("") end
|
|
end
|
|
|
|
if #list % numCols ~= 0 then print("") end
|