luajitos

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

ramfs.lua (5218B)


      1 local ramdisk_packed =[[os/
      2 apps/
      3 os/test.lua	osprint("test123! test123! test123!")\nosprint("\_-'-_/")\n]]
      4 
      5 
      6 function string.trimr(str, char)
      7     char = char or " "
      8 
      9     local len, epos = string.len(str), 1
     10     
     11     for i=1,len do
     12         if str:sub(len - epos, len - epos) == char then
     13             epos = epos + 1
     14         end
     15     end
     16 
     17     return str:sub(1, len - epos)
     18 end
     19 
     20 function string.triml(str, char)
     21     char = char or " "
     22 
     23     local len, spos = string.len(str), 1
     24     
     25     for i=1,len do
     26         if str:sub(spos, spos) == char then
     27             spos = spos + 1
     28         end
     29     end 
     30     return str:sub(spos, len)
     31 end
     32 
     33 function string.trim(str, char)
     34     return string.triml(string.trimr(str, char), char)
     35 end
     36 
     37 function ramdisk_followPath(fs, path, curnode)
     38     path = string.trim(path:triml("/"), "/")
     39 
     40     curnode = curnode or fs
     41 
     42     -- Empty path means we're at the target
     43     if string.len(path) == 0 then
     44         return curnode, ""
     45     end
     46 
     47     if path:match("^..") then
     48         if curnode.parent == nil then
     49             return curnode, path
     50         else
     51             curnode = curnode.parent
     52         end
     53     end
     54 
     55     local name = path:match("([^/]+)")
     56     local remaining = path:match("/(.*)$") or ""
     57 
     58     print("DEBUG: path='"..path.."' name='"..name.."' remaining='"..remaining.."'")
     59 
     60     if curnode.dirs[name] then
     61         if string.len(remaining) > 0 then
     62             return ramdisk_followPath(fs, remaining, curnode.dirs[name])
     63         else
     64             return curnode.dirs[name], ""
     65         end
     66     end
     67 
     68     if curnode.files then
     69         if curnode.files[name] then
     70             if string.len(remaining) > 0 then
     71                 return ramdisk_followPath(fs, remaining, curnode.files[name])
     72             else
     73                 return curnode.files[name]
     74             end
     75         end
     76     end
     77 
     78     return curnode, name
     79 end
     80 
     81 
     82 local FSInstance = {
     83     new = function(filesystem, manifest)
     84         if filesystem == nil or manifest == nil or manifest.allowedDirs == nil then
     85            return nil
     86         end
     87         local allowedDirs = manifest.allowedDirs
     88         local instance = {
     89             root = filesystem;
     90             allowedDirs = allowedDirs;
     91             pathHashes = {};
     92         }
     93         return setmetatable(instance, FSInstance)
     94     end
     95 }
     96 FSInstance.__index = FSInstance
     97 
     98 function FSInstance.read(path)
     99     local node, path = ramdisk_followPath(self.root, path)
    100     if node and node.type == "file" then
    101         return node.content
    102     end
    103 end
    104 
    105 
    106 function ramdisk_addDir(filesystem, path)
    107     local node, name = ramdisk_followPath(filesystem, path)
    108 
    109     local dir = {
    110         name = name;
    111         type = "directory";
    112         dirs = {};
    113         files = {};
    114         parent = node;
    115     }
    116 
    117     node.dirs[name] = dir
    118 end
    119 
    120 function ramdisk_addFile(filesystem, path, content)
    121     local node, name = ramdisk_followPath(filesystem, path)
    122     local file = {
    123         name = name;
    124         type = "file";
    125         content = content;
    126         parent = node;
    127     }
    128 
    129     node.files[name] = file
    130 end
    131 
    132 function ramdisk_print(node, path)
    133     if node == nil then return nil end
    134 
    135     local path = path or ""
    136     local fullpath = path..(node.name or "")
    137 
    138     if node.type == "directory" then
    139         fullpath = fullpath.."/"
    140     end
    141 
    142     print(fullpath)
    143 
    144     if node.type == "directory" then
    145         -- Sort keys to ensure consistent ordering
    146         local dirKeys = {}
    147         for k in pairs(node.dirs) do
    148             table.insert(dirKeys, k)
    149         end
    150         table.sort(dirKeys)
    151 
    152         -- Print directories depth-first
    153         for _, k in ipairs(dirKeys) do
    154             ramdisk_print(node.dirs[k], fullpath)
    155         end
    156 
    157         -- Then print files
    158         local fileKeys = {}
    159         for k in pairs(node.files) do
    160             table.insert(fileKeys, k)
    161         end
    162         table.sort(fileKeys)
    163 
    164         for _, k in ipairs(fileKeys) do
    165             ramdisk_print(node.files[k], fullpath)
    166         end
    167     end
    168 end
    169 
    170 --ramdisk_addDir(filesystem, "/os/")
    171 
    172 --ramdisk_addDir(filesystem, "/apps/")
    173 
    174 
    175 
    176 
    177 
    178 function ramdisk_unpack(packed, allowedDirs)
    179     local fs = {
    180         type = "directory";
    181         dirs = {};
    182         files = {};
    183         allowedDirs = allowedDirs;
    184         parent = nil;
    185     }
    186 
    187     while packed and string.len(packed) > 0 do
    188         local line = packed:match("([^\n]*)\n?")
    189         packed = packed:sub(string.len(line) + 2, string.len(packed))
    190 
    191         if string.len(line) <= 1 then
    192             break
    193         end
    194 
    195         local path, content = line:match("([^\t]+)\t(.*)")
    196 
    197         if path == nil and line:match("^.+/$") then
    198             path = line
    199             print("dir: "..path)
    200             ramdisk_addDir(fs, path)
    201         elseif path ~= nil then
    202             print("file: "..path)
    203             print("content: "..(content or ""))
    204             ramdisk_addFile(fs, path, content)
    205         end
    206 
    207     end
    208 
    209     return fs
    210 end
    211 
    212 local unpacked_fs = ramdisk_unpack(ramdisk_packed)
    213 
    214 print("~~~~~~~~~~~~~~~~~~")
    215 print("Manual filesystem:")
    216 ramdisk_print(filesystem)
    217 print("~~~~~~~~~~~~~~~~~~")
    218 print("Unpacked filesystem:")
    219 ramdisk_print(unpacked_fs)
    220 print("~~~~~~~~~~~~~~~~~~")
    221 local fs = FSInstance.new(unpacked_fs, { allowedDirs = "all" })
    222 print("test.lua:", fs:read("/os/test.lua"))
    223 print("~~~~~~~~~~~~~~~~~~")
    224 
    225