-- /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