Advertisement
Derek1017

VFS API

Jun 19th, 2015
328
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.27 KB | None | 0 0
  1. local function createVFSInstance(oldFS)
  2.         local vfs = {}
  3.  
  4.         --[[
  5.         Structure of a FS object:
  6.         {
  7.                 function isReadOnly(self, path)
  8.                 function exists(self, path)
  9.                 function open(self, path, mode)
  10.                 function isDir(self, path) -- optional, defaults to false
  11.                 function list(self, path) -- optional, defaults to throwing error
  12.                 function getDrive(self, path) -- optional, defaults to "unknown"
  13.                 function mkdir(self, path) -- optional, defaults to throwing error
  14.                 function delete(self, path) -- optional, defaults to throwing error
  15.                 function getSize(self, path) -- optional, defaults to always 512
  16.                 function move(self, from1, from2) -- optional
  17.                 function copy(self, from1, from2) -- optional
  18.                 function getFreeSpace(self, path) -- optional, defaults to 2MiB
  19.         }
  20.         ]]
  21.  
  22.         local _registeredFS = {}
  23.  
  24.         -- factory is a function(mountPoint, options) that returns a FS object
  25.         function vfs.registerFS(name, factory)
  26.                 assert(type(name) == "string", "name must be a string")
  27.                 assert(type(factory) == "function", "factory must be a function")
  28.        
  29.                 if _registeredFS[name] then
  30.                         print("Warning: Re-registering filesystem type "..name)
  31.                         print("Existing mounted filesystems will not be affected.")
  32.                 end
  33.                 _registeredFS[name] = factory
  34.         end
  35.  
  36.         local _mountPoints = {}
  37.  
  38.         -- fsType is the name of a FS previously registered with vfs.registerFS
  39.         function vfs.mount(mountPoint, fsType, options)
  40.                 assert(mountPoint:sub(mountPoint:len()) == "/", "mount point must end with a slash")
  41.                 assert(_mountPoints[mountPoint] == nil, "already mounted")
  42.                 assert(_registeredFS[fsType] ~= nil, "unknown fs type "..tostring(fsType))
  43.  
  44.                 _mountPoints[mountPoint] = _registeredFS[fsType](mountPoint, options)
  45.         end
  46.  
  47.         function vfs.unmount(mountPoint)
  48.                 _mountPoints[mountPoint] = nil
  49.         end
  50.  
  51.         -- returns FS, FS-relative-path
  52.         function vfs._resolve(path)
  53.                 if path:sub(1,1) ~= "/" then
  54.                         path = "/" .. path
  55.                 end
  56.                 if _mountPoints[path .. "/"] then
  57.                         return _mountPoints[path .. "/"], "/"
  58.                 end
  59.                 if _mountPoints[path] then
  60.                         return _mountPoints[path], "/"
  61.                 end
  62.                 local best = ""
  63.                 for k,v in pairs(_mountPoints) do
  64.                         --print(path," ",k," ",path:sub(1,k:len())," ",best)
  65.                                 if path:sub(1, k:len()) == k and k:len() > best:len() then
  66.                                 best = k
  67.                         end
  68.                 end
  69.                 return _mountPoints[best], "/" .. path:sub(best:len() + 1)
  70.         end
  71.        
  72.         vfs.oldFS = oldFS
  73.        
  74.         local fs = {}
  75.        
  76.         function fs.combine(basePath, localPath)
  77.                 return oldFS.combine(basePath, localPath)
  78.         end
  79.        
  80.         function fs.isReadOnly(path)
  81.                 local fs, rel = vfs._resolve(path)
  82.                 if not fs then return true end
  83.                 return fs:isReadOnly(rel)
  84.         end
  85.        
  86.         function fs.getSize(path)
  87.                 local fs, rel = vfs._resolve(path)
  88.                 if not fs then return 0 end
  89.                 if fs.getSize then return fs:getSize(path) else return 512 end
  90.         end
  91.        
  92.         function fs.move(p1, p2)
  93.                 local fs1, rel1 = vfs._resolve(p1)
  94.                 local fs2, rel2 = vfs._resolve(p2)
  95.                 if not fs1 then error("doesn't exist: "..fs1) end
  96.                 if not fs2 then error("Fuck!") end
  97.                 if fs2:exists(rel2) then
  98.                         error("already exists: "..p2)
  99.                 end
  100.                 if fs1 == fs2 and fs1.move then
  101.                         fs1:move(rel1, rel2)
  102.                 elseif fs1:exists(rel1) then
  103.                         fs.copy(p1, p2)
  104.                         fs.delete(p1)
  105.                 end
  106.         end
  107.        
  108.         function fs.exists(path)
  109.                 local fs, rel = vfs._resolve(path)
  110.                 if not fs then return false end
  111.                 return fs:exists(rel)
  112.         end
  113.  
  114.         local function copyFile(p1, p2)
  115.                 local f = fs.open(p1, "r")
  116.                 local d = f.readAll()
  117.                 f.close()
  118.                 f = fs.open(p2, "w")
  119.                 f.write(d)
  120.                 f.close()
  121.         end
  122.  
  123.         local function copyDir(p1, p2)
  124.                 if not fs.exists(p2) then fs.makeDir(p2) end
  125.                 for k,v in ipairs(fs.list(p1)) do
  126.                         local p = fs.combine(p1, v)
  127.                         if fs.isDir(p) then
  128.                                 copyDir(p, fs.combine(p2, v))
  129.                         else
  130.                                 copyFile(p, fs.combine(p2, v))
  131.                         end
  132.                 end
  133.         end
  134.        
  135.         function fs.copy(p1, p2)
  136.                 local fs1, rel1 = vfs._resolve(p1)
  137.                 local fs2, rel2 = vfs._resolve(p2)
  138.                 if not fs1 or not fs1:exists(rel1) then error("doesn't exist: "..p1) end
  139.                 if fs2:exists(rel2) then
  140.                         error("already exists: "..p2)
  141.                 end
  142.                 if fs1 == fs2 and fs1.copy then
  143.                         fs1:copy(rel1, rel2)
  144.                 elseif fs.isDir(p1) then
  145.                         copyDir(p1, p2)
  146.                 else
  147.                         copyFile(p1, p2)
  148.                 end
  149.         end
  150.        
  151.         function fs.getFreeSpace(path)
  152.                 local fs, rel = vfs._resolve(path)
  153.                 if not fs then return 0 end
  154.                 if not fs.getFreeSpace then return 2097152 end
  155.                 return fs:getFreeSpace(rel)
  156.         end
  157.        
  158.         function fs.makeDir(path)
  159.                 local fs, rel = vfs._resolve(path)
  160.                 if not fs or not fs.mkdir then error("Not supported on this device") end
  161.                 if fs:exists(rel) then error("Already exists: "..path) end
  162.                 fs:mkdir(rel)
  163.         end
  164.        
  165.         function fs.delete(path)
  166.                 local fs, rel = vfs._resolve(path)
  167.                 if not fs or not fs.delete then error("Not supported on this device") end
  168.                 fs:delete(rel)
  169.         end
  170.        
  171.         function fs.open(path, mode)
  172.                 local fs, rel = vfs._resolve(path)
  173.                 if not fs then return nil end
  174.                 return fs:open(rel, mode)
  175.         end
  176.        
  177.         local function tablefind(t, v)
  178.                 for _,v2 in ipairs(t) do
  179.                         if v2 == v then return true end
  180.                 end
  181.         end
  182.        
  183.         function fs.list(path)
  184.                 if not fs.isDir(path) then error("Not a directory",2) end
  185.                 local fs, rel = vfs._resolve(path)
  186.                 if not fs.list then error("Not supported on this device") end
  187.                 local rv
  188.                 if fs == nil then
  189.                         rv = {}
  190.                 else
  191.                         rv = fs:list(rel)
  192.                 end
  193.                 -- add mount points to list
  194.                 while path:sub(path:len()) == "/" do path = path:sub(1, path:len() - 1) end
  195.                 path = path .. "/"
  196.                 for k,v in pairs(_mountPoints) do
  197.                         if k:sub(1, path:len()) == path and k ~= path then
  198.                                 local after = k:sub(path:len() + 1)
  199.                                 after = after:sub(1, after:len() - 1)
  200.                                 if after:find("/") == nil and not tablefind(rv, after) then
  201.                                         table.insert(rv, after)
  202.                                 end
  203.                         end
  204.                 end
  205.                 return rv
  206.         end
  207.        
  208.         function fs.getDrive(path)
  209.                 local fs, rel = vfs._resolve(path)
  210.                 if not fs.getDrive then return "unknown" end
  211.                 return fs:getDrive(rel)
  212.         end
  213.        
  214.         function fs.getName(path)
  215.                 return oldFS.getName(path)
  216.         end
  217.        
  218.         function fs.isDir(path)
  219.                 local fs, rel = vfs._resolve(path)
  220.                 if not fs.isDir then return false end
  221.                 return fs:isDir(rel)
  222.         end
  223.        
  224.         local fs_craftos = {
  225.                 isReadOnly = function(self, path) return oldFS.isReadOnly(self.prefix .. path) end,
  226.                 exists = function(self, path) return oldFS.exists(self.prefix .. path) end,
  227.                 open = function(self, path, mode) return oldFS.open(self.prefix .. path, mode) end,
  228.                 isDir = function(self, path) return oldFS.isDir(self.prefix .. path) end,
  229.                 list = function(self, path) return oldFS.list(self.prefix .. path) end,
  230.                 getDrive = function(self, path) return oldFS.getDrive(self.prefix .. path) end,
  231.                 mkdir = function(self, path) return oldFS.makeDir(self.prefix .. path) end,
  232.                 delete = function(self, path) return oldFS.delete(self.prefix .. path) end,
  233.                 getSize = function(self, path) return oldFS.getSize(self.prefix .. path) end,
  234.                 getFreeSpace = function(self, path) return oldFS.getFreeSpace(self.prefix .. path) end,
  235.                 move = function(self, path1, path2) return oldFS.move(self.prefix .. path1, self.prefix .. path2) end,
  236.                 copy = function(self, path1, path2) return oldFS.copy(self.prefix .. path1, self.prefix .. path2) end,
  237.         }
  238.  
  239.         vfs.registerFS("craftos", function(mount, opts)
  240.                 local t = {prefix=opts.prefix or ""}
  241.                 setmetatable(t, {__index=fs_craftos})
  242.                 return t
  243.         end)
  244.        
  245.         vfs.mount("/", "craftos", {})
  246.  
  247.         return vfs, fs
  248. end
  249.  
  250. local vfs, fs = createVFSInstance(fs)
  251.  
  252. rawset(_G, "vfs", vfs)
  253. rawset(_G, "fs", fs)
  254.  
  255. vfs.createVFSInstance = createVFSInstance
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement