do _G.fs = {} local fT,hT = {},{["_c"]=0} function fs.mount(mp,pr) fT[mp] = pr end function fs.simplify(p) local pt,npt,rp = {},{},"" for P in p:gmatch("[^/]+") do pt[#pt+1] = P end for k,v in pairs(pt) do if v == ".." then npt[#npt] = nil elseif v ~= "." then npt[#npt+1] = v end end for k,v in pairs(npt) do rp=rp.."/"..v end if p:sub(1,1) ~= "/" then rp = rp:sub(2) end return rp end function fs.resolve(p) if p:sub(1,1) ~= "/" then -- absolute/relative path p=(os.getenv("PWD") or "").."/"..p end p=fs.simplify(p) local pt,spt = {},"" for P in p:gmatch("[^/]+") do pt[#pt+1] = P end for i = 2, #pt do spt=spt.."/"..pt[i] end return pt, pt[1], spt end function fs.exec(fc,m,...) return fT[fc][m](...) end function fs.open(p,m) local _,d,p = fs.resolve(p) local d = fT[d] local f,C=d.open(p,m),hT._c if f then hT._c = C + 1 hT[C] = {d,f} return C end return false end function fs.close(h) if hT[h] then hT[h][1].close(hT[h][2]) end return false end function fs.read(h,n) if hT[h] then return hT[h][1].read(hT[h][2],n) end return false end function fs.readall(f) local s="" repeat c=fs.read(f,2048) s=s..c until c=="" return s end function fs.write(h,d) if hT[h] then return hT[h][1].write(hT[h][2],d) end return false end function fs.list(s) s=s or "" local _,d,p = fs.resolve(s) if not d then local kt = {} for k,v in pairs(fT) do kt[#kt+1] = k end return kt end return fT[d].list(p or "/") end function fs.mkdir(s) local _,d,p = fs.resolve(s) return fT[d].makeDirectory(p or "/") end function fs.rm(s) local _,d,p = fs.resolve(s) return fT[d].remove(p) end function fs.exists(s) local _,d,p = fs.resolve(s) return fT[d].exists(p) end function fs.isdir(s) local _,d,p = fs.resolve(s) return fT[d].isDirectory(p) end end function fs.cd(p) if p:sub(1,1) ~= "/" then p=(os.getenv("PWD") or "").."/"..p end p=fs.simplify(p) if fs.exists(p) and fs.isdir(p) then os.setenv("PWD",p) else error("non-existent/not a dir") end end