luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

pack_ramdisk.lua (5642B)


      1 #!/usr/bin/env luajit
      2 -- pack_ramdisk.lua - Generates packed.bin from iso_includes directory
      3 -- Usage: luajit pack_ramdisk.lua <source_dir> <output_file>
      4 
      5 local source_dir = arg[1] or "iso_includes"
      6 local output_file = arg[2] or "OS/packed.bin"
      7 
      8 -- Helper function to check if a file is binary
      9 local function isBinary(content)
     10     for i = 1, #content do
     11         local byte = content:byte(i)
     12         if byte < 32 and byte ~= 9 and byte ~= 10 and byte ~= 13 then
     13             return true
     14         end
     15         if byte > 127 then
     16             return true
     17         end
     18     end
     19     return false
     20 end
     21 
     22 -- Base64 encoding
     23 local function base64Encode(data)
     24     local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
     25     local result = {}
     26 
     27     for i = 1, #data, 3 do
     28         local b1 = data:byte(i)
     29         local b2 = data:byte(i + 1)
     30         local b3 = data:byte(i + 2)
     31 
     32         local c1 = b:sub(bit.rshift(b1, 2) + 1, bit.rshift(b1, 2) + 1)
     33 
     34         if b2 then
     35             local c2 = b:sub(bit.bor(bit.lshift(bit.band(b1, 0x03), 4), bit.rshift(b2, 4)) + 1, bit.bor(bit.lshift(bit.band(b1, 0x03), 4), bit.rshift(b2, 4)) + 1)
     36 
     37             if b3 then
     38                 local c3 = b:sub(bit.bor(bit.lshift(bit.band(b2, 0x0F), 2), bit.rshift(b3, 6)) + 1, bit.bor(bit.lshift(bit.band(b2, 0x0F), 2), bit.rshift(b3, 6)) + 1)
     39                 local c4 = b:sub(bit.band(b3, 0x3F) + 1, bit.band(b3, 0x3F) + 1)
     40                 table.insert(result, c1 .. c2 .. c3 .. c4)
     41             else
     42                 local c3 = b:sub(bit.lshift(bit.band(b2, 0x0F), 2) + 1, bit.lshift(bit.band(b2, 0x0F), 2) + 1)
     43                 table.insert(result, c1 .. c2 .. c3 .. '=')
     44             end
     45         else
     46             local c2 = b:sub(bit.lshift(bit.band(b1, 0x03), 4) + 1, bit.lshift(bit.band(b1, 0x03), 4) + 1)
     47             table.insert(result, c1 .. c2 .. '==')
     48         end
     49     end
     50 
     51     return table.concat(result)
     52 end
     53 
     54 -- Escape text content
     55 local function escapeText(text)
     56     local result = {}
     57     for i = 1, #text do
     58         local c = text:sub(i, i)
     59         if c == "\\" then
     60             table.insert(result, "\\\\")
     61         elseif c == "\n" then
     62             table.insert(result, "\\n")
     63         elseif c == "\t" then
     64             table.insert(result, "\\t")
     65         elseif c == "\r" then
     66             table.insert(result, "\\r")
     67         else
     68             table.insert(result, c)
     69         end
     70     end
     71     return table.concat(result)
     72 end
     73 
     74 -- Recursively scan directory
     75 local function scanDirectory(path, relative_path)
     76     local dirs = {}
     77     local files = {}
     78 
     79     -- Get directory listing
     80     local handle = io.popen("find " .. path .. " -mindepth 1 -maxdepth 1 2>/dev/null")
     81     if not handle then
     82         io.stderr:write("Error: Cannot read directory " .. path .. "\n")
     83         return dirs, files
     84     end
     85 
     86     for entry in handle:lines() do
     87         local name = entry:match("^.+/(.+)$")
     88         local entry_relative = relative_path == "" and name or relative_path .. "/" .. name
     89 
     90         -- Check if it's a directory
     91         local is_dir = os.execute("test -d " .. entry .. " 2>/dev/null") == 0
     92 
     93         if is_dir then
     94             -- Add directory
     95             table.insert(dirs, entry_relative)
     96             -- Recursively scan subdirectory
     97             local subdirs, subfiles = scanDirectory(entry, entry_relative)
     98             for _, d in ipairs(subdirs) do
     99                 table.insert(dirs, d)
    100             end
    101             for _, f in ipairs(subfiles) do
    102                 table.insert(files, f)
    103             end
    104         else
    105             -- Skip init.lua and packed.bin at any level
    106             if entry_relative ~= "os/packed.bin" and entry_relative ~= "packed.bin" then
    107                 -- Add file
    108                 local file_handle = io.open(entry, "rb")
    109                 if file_handle then
    110                     local content = file_handle:read("*a")
    111                     file_handle:close()
    112 
    113                     table.insert(files, {
    114                         path = entry_relative,
    115                         content = content
    116                     })
    117                 end
    118             end
    119         end
    120     end
    121 
    122     handle:close()
    123     return dirs, files
    124 end
    125 
    126 -- Main
    127 print("Packing ramdisk from: " .. source_dir)
    128 print("Output file: " .. output_file)
    129 
    130 local dirs, files = scanDirectory(source_dir, "")
    131 
    132 -- Sort directories and files
    133 table.sort(dirs)
    134 table.sort(files, function(a, b) return a.path < b.path end)
    135 
    136 print("Found " .. #dirs .. " directories and " .. #files .. " files")
    137 
    138 -- Build packed format
    139 local entries = {}
    140 
    141 -- Add directories
    142 for _, dir in ipairs(dirs) do
    143     table.insert(entries, dir .. "/")
    144     print("  DIR:  " .. dir .. "/")
    145 end
    146 
    147 -- Add files
    148 for _, file in ipairs(files) do
    149     local entry
    150     if isBinary(file.content) then
    151         entry = file.path .. "~~~~BIN:" .. base64Encode(file.content)
    152         print("  FILE: " .. file.path .. " (binary, " .. #file.content .. " bytes)")
    153     else
    154         local escaped = escapeText(file.content)
    155         entry = file.path .. "~~~~" .. escaped
    156         print("  FILE: " .. file.path .. " (text, original=" .. #file.content .. " escaped=" .. #escaped .. " entry=" .. #entry .. " bytes)")
    157     end
    158     table.insert(entries, entry)
    159 end
    160 
    161 -- Write output
    162 -- Use null bytes as delimiter (won't appear in text files)
    163 local ENTRY_SEP = "\x00\x00\x00\x00"
    164 local packed = table.concat(entries, ENTRY_SEP)
    165 print("\nDEBUG: Packed size: " .. #packed .. " bytes")
    166 
    167 local out = io.open(output_file, "wb")
    168 if not out then
    169     io.stderr:write("Error: Cannot write to " .. output_file .. "\n")
    170     os.exit(1)
    171 end
    172 
    173 out:write(packed)
    174 out:close()
    175 
    176 print("\nPacked ramdisk created: " .. output_file .. " (" .. #packed .. " bytes)")