Advertisement
Guest User

filesystem.lua(mini)

a guest
Jul 16th, 2016
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.41 KB | None | 0 0
  1. local b=require("component")local c=require("unicode")local filesystem,fileStream={},{}local isAutorunEnabled=nil;local d={name="",children={},links={}}local function segments(path)path=path:gsub("\\","/")repeat local n;path,n=path:gsub("//","/")until n==0;local e={}for f in path:gmatch("[^/]+")do table.insert(e,f)end;local g=1;while g<=#e do if e[g]=="."then table.remove(e,g)elseif e[g]==".."then table.remove(e,g)g=g-1;if g>0 then table.remove(e,g)else g=1 end else g=g+1 end end;return e end;local function h()local i=filesystem.get("/")if i and not i.isReadOnly()then filesystem.makeDirectory("/etc")local j=io.open("/etc/filesystem.cfg","w")if j then j:write("autorun="..tostring(isAutorunEnabled))j:close()end end end;local function k(path,l,m)checkArg(1,path,"string")m=m or 0;if m>100 then error("link cycle detected")end;local e=segments(path)local o=d;while#e>0 do local f=e[1]if not o.children[f]then if o.links[f]then return k(filesystem.concat(o.links[f],table.concat(e,"/",2)),l,m+1)else if l then o.children[f]={name=f,parent=o,children={},links={}}else local p,q=o,table.concat(e,"/")local rest=q;while o and not o.fs do rest=filesystem.concat(o.name,rest)o=o.parent end;return o,rest,p,q end end end;o=o.children[f]table.remove(e,1)end;local p,q=o,nil;local rest=nil;while o and not o.fs do rest=rest and filesystem.concat(o.name,rest)or o.name;o=o.parent end;return o,rest,p,q end;local function s(o)while o and o.parent and not o.fs and not next(o.children)and not next(o.links)do o.parent.children[o.name]=nil;o=o.parent end end;function filesystem.isAutorunEnabled()if isAutorunEnabled==nil then local t={}local u=loadfile("/etc/filesystem.cfg",nil,t)if u then pcall(u)isAutorunEnabled=not not t.autorun else isAutorunEnabled=true end;h()end;return isAutorunEnabled end;function filesystem.setAutorunEnabled(v)checkArg(1,v,"boolean")isAutorunEnabled=v;h()end;function filesystem.segments(path)return segments(path)end;function filesystem.canonical(path)local x=table.concat(segments(path),"/")if c.sub(path,1,1)=="/"then return"/"..x else return x end end;function filesystem.concat(y,z,...)checkArg(1,y,"string")local function concat(n,a,A,...)if not A then return a end;checkArg(n,A,"string")return concat(n+1,a.."/"..A,...)end;return filesystem.canonical(concat(2,y,z,...))end;function filesystem.get(path)local o,rest=k(path)if o.fs then local proxy=o.fs;path=""while o and o.parent do path=filesystem.concat(o.name,path)o=o.parent end;path=filesystem.canonical(path)if path~="/"then path="/"..path end;return proxy,path end;return nil,"no such file system"end;function filesystem.isLink(path)local o,rest,p,q=k(filesystem.path(path))if not q and p.links[filesystem.name(path)]~=nil then return true,p.links[filesystem.name(path)]end;return false end;function filesystem.link(B,C)checkArg(1,B,"string")checkArg(2,C,"string")if filesystem.exists(C)then return nil,"file already exists"end;local o,rest,p,q=k(filesystem.path(C),true)p.links[filesystem.name(C)]=B;return true end;function filesystem.mount(fs,path)checkArg(1,fs,"string","table")if type(fs)=="string"then fs=filesystem.proxy(fs)end;assert(type(fs)=="table","bad argument #1 (file system proxy or address expected)")checkArg(2,path,"string")if path~="/"and filesystem.exists(path)then return nil,"file already exists"end;local o,rest,p,q=k(path,true)if p.fs then return nil,"another filesystem is already mounted here"end;p.fs=fs;return true end;function filesystem.mounts()local function path(o)local x="/"while o and o.parent do for name,D in pairs(o.parent.children)do if D==o then x="/"..name..x;break end end;o=o.parent end;return x end;local E={d}return function()while#E>0 do local o=table.remove(E)for F,D in pairs(o.children)do table.insert(E,D)end;if o.fs then return o.fs,path(o)end end end end;function filesystem.path(path)local e=segments(path)local x=table.concat(e,"/",1,#e-1).."/"if c.sub(path,1,1)=="/"and c.sub(x,1,1)~="/"then return"/"..x else return x end end;function filesystem.name(path)local e=segments(path)return e[#e]end;function filesystem.proxy(G)checkArg(1,G,"string")local H;for I in b.list("filesystem",true)do if b.invoke(I,"getLabel")==G then H=I;break end;if I:sub(1,G:len())==G then H=I;break end end;if not H then return nil,"no such file system"end;return b.proxy(H)end;function filesystem.umount(J)checkArg(1,J,"string","table")if type(J)=="string"then local o,rest,p,q=k(J)if not q and p.fs then p.fs=nil;s(p)return true end end;local H=type(J)=="table"and J.address or J;local x=false;for proxy,path in filesystem.mounts()do local K=type(proxy)=="table"and proxy.address or proxy;if string.sub(K,1,H:len())==H then local o,rest,p,q=k(path)p.fs=nil;s(p)x=true end end;return x end;function filesystem.exists(path)local o,rest,p,q=k(path)if not q or p.links[q]then return true end;if o and o.fs then return o.fs.exists(rest)end;return false end;function filesystem.size(path)local o,rest,p,q=k(path)if not p.fs and not q or p.links[q]then return 0 end;if o.fs and rest then return o.fs.size(rest)end;return 0 end;function filesystem.isDirectory(path)local o,rest,p,q=k(path)if not p.fs and not q then return true end;if o.fs then return not rest or o.fs.isDirectory(rest)end;return false end;function filesystem.lastModified(path)local o,rest,p,q=k(path)if not p.fs and not q then return 0 end;if o.fs and rest then return o.fs.lastModified(rest)end;return 0 end;function filesystem.list(path)local o,rest,p,q=k(path)if not p.fs and q and not(o and o.fs)then return nil,"no such file or directory"end;local x,L;if o and o.fs then x,L=o.fs.list(rest or"")end;x=x or{}if not q then for M in pairs(p.children)do table.insert(x,M.."/")end;for M in pairs(p.links)do table.insert(x,M)end end;table.sort(x)local g,j=1,nil;while g<=#x do if x[g]==j then table.remove(x,g)else j=x[g]g=g+1 end end;local g=0;return function()g=g+1;return x[g]end end;function filesystem.makeDirectory(path)if filesystem.exists(path)then return nil,"file or directory with that name already exists"end;local o,rest=k(path)if o.fs and rest then return o.fs.makeDirectory(rest)end;if o.fs then return nil,"virtual directory with that name already exists"end;return nil,"cannot create a directory in a virtual directory"end;function filesystem.remove(path)local function N()local o,rest,p,q=k(filesystem.path(path))if not q then local name=filesystem.name(path)if p.children[name]then p.children[name]=nil;s(p)return true elseif p.links[name]then p.links[name]=nil;s(p)return true end end;return false end;local function O()o,rest=k(path)if o.fs and rest then return o.fs.remove(rest)end;return false end;local P=N()P=O()or P;if P then return true else return nil,"no such file or directory"end end;function filesystem.rename(Q,R)if filesystem.isLink(Q)then local o,rest,p,q=k(filesystem.path(Q))local B=p.links[filesystem.name(Q)]local x,L=filesystem.link(B,R)if x then filesystem.remove(Q)end;return x,L else local S,T=k(Q)local U,V=k(R)if S.fs and T and U.fs and V then if S.fs.address==U.fs.address then return S.fs.rename(T,V)else local x,L=filesystem.copy(Q,R)if x then return filesystem.remove(Q)else return nil,L end end end;return nil,"trying to read from or write to virtual directory"end end;function filesystem.copy(W,X)if filesystem.isDirectory(W)then return nil,"cannot copy folders"end;local Y,L=io.open(W,"rb")if not Y then return nil,L end;local Z,L=io.open(X,"wb")if not Z then Y:close()return nil,L end;repeat local buffer,L=Y:read(1024)if not buffer and L then return nil,L elseif buffer then local x,L=Z:write(buffer)if not x then Y:close()Z:close()return nil,L end end until not buffer;Y:close()Z:close()return true end;function fileStream:close()if self.handle then self.fs.close(self.handle)self.handle=nil end end;function fileStream:read(n)if not self.handle then return nil,"file is closed"end;return self.fs.read(self.handle,n)end;function fileStream:seek(_,a0)if not self.handle then return nil,"file is closed"end;return self.fs.seek(self.handle,_,a0)end;function fileStream:write(a1)if not self.handle then return nil,"file is closed"end;return self.fs.write(self.handle,a1)end;function filesystem.open(path,a2)checkArg(1,path,"string")a2=tostring(a2 or"r")checkArg(2,a2,"string")assert(({r=true,rb=true,w=true,wb=true,a=true,ab=true})[a2],"bad argument #2 (r[b], w[b] or a[b] expected, got "..a2 ..")")local o,rest=k(path)if not o.fs or not rest then return nil,"file not found"end;local handle,L=o.fs.open(rest,a2)if not handle then return nil,L end;local a3={fs=o.fs,handle=handle}local a4={__index=fileStream,__metatable="filestream"}return setmetatable(a3,a4)end;return filesystem
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement