apemanzilla

fs proxy

Apr 22nd, 2015
51
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local datafolder = ".data"
  2. local allowedRootFolders = {
  3.     "rom",
  4.     "disk[%d+]?"
  5. }
  6.  
  7. local _fs = fs
  8. vfs = {}
  9.  
  10. local function hardcopy(tbl)
  11.     for k,v in pairs(tbl) do
  12.         if type(v) == "table" then
  13.             if v == tbl then
  14.                 tbl[k] = tbl
  15.             else
  16.                 tbl[k] = hardcopy(v)
  17.             end
  18.         else
  19.             tbl[k] = v
  20.         end
  21.     end
  22.     return tbl
  23. end
  24.  
  25. local function assert(case, message, level)
  26.     if not case then
  27.         error(message, level + 1)
  28.     end
  29. end
  30.  
  31. local function proxyError(fn, args, level)
  32.     local level = level + 1
  33.     local results = { pcall(fn, unpack(args)) }
  34.     if not results[1] then
  35.         error(results[2]:sub(8), level)
  36.     else
  37.         table.remove(results, 1)
  38.         return unpack(results)
  39.     end
  40. end
  41.  
  42. local function clean(path)
  43.     return fs.combine(path, ""):gsub("%.%.","")
  44. end
  45.  
  46. local function split(path)
  47.     local path = clean(path)
  48.     local out = {}
  49.     for part in path:gmatch("([^/]+)") do
  50.         table.insert(out, part)
  51.     end
  52.     return out
  53. end
  54.  
  55. local function isAllowed(path)
  56.     local path = split(path)[1] or "/"
  57.     for i,v in ipairs(allowedRootFolders) do
  58.         if path:find("^"..v.."$") then
  59.             return true
  60.         end
  61.     end
  62.     return false
  63. end
  64.  
  65. function resolve(path)
  66.     local path = clean(path)
  67.     --assert(path ~= "" and path ~= "/", "invalid path", 3)
  68.     if isAllowed(path) then
  69.         return path
  70.     else
  71.         if not _fs.isDir(datafolder) then
  72.             _fs.delete(datafolder)
  73.         end
  74.         if not _fs.exists(datafolder) then
  75.             _fs.makeDir(datafolder)
  76.         end
  77.         return _fs.combine(datafolder,path)
  78.     end
  79. end
  80.  
  81. -- VFS functions --
  82.  
  83. local simpleOverrides = { "exists", "isDir", "isReadOnly", "getDrive", "getSize", "getFreeSpace", "makeDir", "delete" }
  84.  
  85. for k,v in pairs(simpleOverrides) do
  86.     vfs[v] = function(p)
  87.         assert(type(p) == "string", "expected string", 2)
  88.         local p = resolve(p)
  89.  
  90.         return proxyError(_fs[v], {p}, 1)
  91.     end
  92. end
  93.  
  94. function vfs.list(path)
  95.     assert(type(path) == "string", "expected string",2)
  96.     local path = resolve(path)
  97.  
  98.     local out = proxyError(_fs.list, {path}, 2)
  99.     if clean(path) == datafolder then
  100.         for i,v in ipairs(_fs.list("/")) do
  101.             if isAllowed(v) then
  102.                 table.insert(out, v)
  103.             end
  104.         end
  105.     end
  106.     return out
  107. end
  108.  
  109. function vfs.move(p1, p2)
  110.     assert(type(p1) == "string" and type(p2) == "string", "expected string, string", 2)
  111.     local p1, p2 = resolve(p1), resolve(p2)
  112.  
  113.     return proxyError(_fs.move, {p1, p2}, 2)
  114. end
  115.  
  116. function vfs.copy(p1, p2)
  117.     assert(type(p1) == "string" and type(p2) == "string", "expected string, string", 2)
  118.     local p1, p2 = resolve(p1), resolve(p2)
  119.    
  120.     return proxyError(_fs.copy, {p1, p2}, 2)
  121. end
  122.  
  123. function vfs.open(path, mode)
  124.     assert(type(path) == "string" and type(mode) == "string", "expected string, string", 2)
  125.     local path = resolve(path)
  126.  
  127.     return proxyError(_fs.open, {path, mode}, 2)
  128. end
  129.  
  130. local function recurse_spec(results, path, spec)
  131.     local segment = spec:match('([^/]*)'):gsub('/', '')
  132.     local pattern = '^' .. segment:gsub("[%.%[%]%(%)%%%+%-%?%^%$]","%%%1"):gsub("%z","%%z"):gsub("%*","[^/]-") .. '$'
  133.  
  134.     if vfs.isDir(path) then
  135.         for _, file in ipairs(vfs.list(path)) do
  136.             if file:match(pattern) then
  137.                 local f = _fs.combine(path, file)
  138.  
  139.                 if spec == segment then
  140.                     table.insert(results, f)
  141.                 end
  142.                 if vfs.isDir(f) then
  143.                     recurse_spec(results, f, spec:sub(#segment + 2))
  144.                 end
  145.             end
  146.         end
  147.     end
  148. end
  149.  
  150. function vfs.find(spec)
  151.     assert(type(spec) == "string","expected string",2)
  152.     spec = clean(spec)
  153.     local results = {}
  154.     recurse_spec(results, '', spec)
  155.     return results
  156. end
  157.  
  158. for k,v in pairs(_fs) do
  159.     if not vfs[k] then
  160.         vfs[k] = v
  161.     end
  162. end
  163.  
  164. env = hardcopy(getfenv(0))
  165. env.fs = vfs
  166. term.setCursorPos(1,1)
  167. term.clear()
  168. term.redirect(term.native())
  169. setfenv(loadfile("rom/programs/shell"), env)()
  170. os.shutdown()
RAW Paste Data