110 lines
3.3 KiB
Lua
110 lines
3.3 KiB
Lua
-- /bin/ls - Lists files in a directory.
|
|
--
|
|
-- Iterate over the 'children' map exposed via C++.
|
|
|
|
local function format_permissions(perms)
|
|
local rwx = { "-", "-", "-", "-", "-", "-", "-", "-", "-" }
|
|
if(perms & 0x100) ~= 0 then rwx[1] = "r" end -- Owner read.
|
|
if(perms & 0x080) ~= 0 then rwx[2] = "w" end -- Owner write.
|
|
if(perms & 0x040) ~= 0 then rwx[3] = "x" end -- Owner execute.
|
|
if(perms & 0x020) ~= 0 then rwx[4] = "r" end -- Group read.
|
|
if(perms & 0x010) ~= 0 then rwx[5] = "w" end -- Group write.
|
|
if(perms & 0x008) ~= 0 then rwx[6] = "x" end -- Group execute.
|
|
if(perms & 0x004) ~= 0 then rwx[7] = "r" end -- Other read.
|
|
if(perms & 0x002) ~= 0 then rwx[8] = "w" end -- Other write.
|
|
if(perms & 0x001) ~= 0 then rwx[9] = "x" end -- Other execute.
|
|
return table.concat(rwx)
|
|
end
|
|
|
|
local function get_username_from_uid(uid)
|
|
local passwd_content = bettola.read_file(context, "/etc/passwd")
|
|
for line in passwd_content:gmatch("(^\n]+)") do
|
|
local parts = {}
|
|
for part in line:gmatch("([^:]+)") do
|
|
table.insert(parts,part)
|
|
end
|
|
if #parts >= 3 and tonumber(parts[3]) == uid then
|
|
return parts[1]
|
|
end
|
|
end
|
|
return tostring(uid)
|
|
end
|
|
|
|
local function get_groupname_from_gid(gid)
|
|
local group_content = bettola.read_file(context, "/etc/group")
|
|
for line in group_content:gmatch("([^\n]+)") do
|
|
local parts = {}
|
|
for part in line:gmatch("([^:]+)") do
|
|
table.insert(parts, part)
|
|
end
|
|
if #parts >= 3 and tonumber(parts[3]) == gid then
|
|
return parts[1]
|
|
end
|
|
end
|
|
return tostring(gid)
|
|
end
|
|
|
|
local function get_file_size(node)
|
|
if node.type == 0 then -- FILE_NODE.
|
|
return #node.content
|
|
else
|
|
return 0 -- Dirs don't have content size in this context.
|
|
end
|
|
end
|
|
|
|
-- Cache for UID/GID to name mappings.
|
|
local uid_to_name_cache = {}
|
|
local gid_to_name_cache = {}
|
|
|
|
local function get_cached_username(uid)
|
|
if not uid_to_name_cache[uid] then
|
|
uid_to_name_cache[uid] = get_username_from_uid(uid)
|
|
end
|
|
return uid_to_name_cache[uid]
|
|
end
|
|
|
|
local function get_cached_groupname(gid)
|
|
if not gid_to_name_cache[gid] then
|
|
gid_to_name_cache[gid] = get_groupname_from_gid(gid)
|
|
end
|
|
return gid_to_name_cache[gid]
|
|
end
|
|
|
|
local function ls_long_format(dir)
|
|
local output = {}
|
|
for name, node in pairs(dir.children) do
|
|
local line_type = (node.type == 1) and "d" or "-"
|
|
local perms = format_permissions(node.permissions)
|
|
local owner_name = get_cached_username(node.owner_id)
|
|
local group_name = get_cached_groupname(node.group_id)
|
|
local size = get_file_size(node)
|
|
table.insert(output, string.format("%s%s %s %s %5d %s", line_type, perms, owner_name,
|
|
group_name, size, name))
|
|
end
|
|
table.sort(output)
|
|
return table.concat(output, "\n")
|
|
end
|
|
|
|
local function ls_short_format(dir)
|
|
local output = {}
|
|
for name, node in pairs(dir.children) do
|
|
local display_name = name
|
|
if node.type == 1 then -- DIR_NODE
|
|
display_name = display_name .. "/"
|
|
elseif node.type == 2 then --EXEC_NODE
|
|
display_name = display_name .. "*"
|
|
end
|
|
table.insert(output, display_name)
|
|
end
|
|
table.sort(output)
|
|
return table.concat(output, "\t") -- Tab separated short format.
|
|
end
|
|
|
|
local current_dir = bettola.get_current_dir(context);
|
|
|
|
if arg[1] == "-l" then
|
|
return ls_long_format(current_dir)
|
|
else
|
|
return ls_short_format(current_dir)
|
|
end
|