Operating system for OpenComputers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.9KB

  1. do
  2. fs = {}
  3. local fsmounts = {}
  4. -- basics
  5. function fs.segments(path) -- string -- table -- Splits *path* on each /
  6. local segments = {}
  7. for segment in path:gmatch("[^/]+") do
  8. segments[#segments+1] = segment
  9. end
  10. return segments
  11. end
  12. function fs.resolve(path) -- string -- string string -- Resolves *path* to a specific filesystem mount and path
  13. if not path or path == "." then path = os.getenv("PWD") end
  14. if path:sub(1,1) ~= "/" then path=(os.getenv("PWD") or "").."/"..path end
  15. local segments, rpath, rfs= fs.segments(path)
  16. local rc = #segments
  17. for i = #segments, 1, -1 do
  18. if fsmounts[table.concat(segments, "/", 1, i)] ~= nil then
  19. return table.concat(segments, "/", 1, i), table.concat(segments, "/", i+1)
  20. end
  21. end
  22. return "/", table.concat(segments,"/")
  23. end
  24. -- generate some simple functions
  25. for k,v in pairs({"makeDirectory","exists","isDirectory","list","lastModified","remove","size","spaceUsed","spaceTotal","isReadOnly","getLabel"}) do
  26. fs[v] = function(path)
  27. local fsi,path = fs.resolve(path)
  28. return fsmounts[fsi][v](path)
  29. end
  30. end
  31. local function fread(self,length)
  32. return fsmounts[self.fs].read(self.fid,length)
  33. end
  34. local function fwrite(self,data)
  35. return fsmounts[self.fs].write(self.fid,data)
  36. end
  37. local function fseek(self,dist)
  38. return fsmounts[self.fs].seek(self.fid,dist)
  39. end
  40. local function fclose(self)
  41. return fsmounts[self.fs].close(self.fid)
  42. end
  43. function fs.open(path,mode) -- string string -- table -- Opens file *path* with mode *mode*, returning a file object.
  44. mode = mode or "rb"
  45. local fsi,path = fs.resolve(path)
  46. if not fsmounts[fsi] then return false end
  47. local fid = fsmounts[fsi].open(path,mode)
  48. if fid then
  49. local fobj = {["fs"]=fsi,["fid"]=fid,["seek"]=fseek,["close"]=fclose}
  50. if mode:find("r") then
  51. fobj.read = fread
  52. end
  53. if mode:find("w") or mode:find("a") then
  54. fobj.write = fwrite
  55. end
  56. return fobj
  57. end
  58. return false
  59. end
  60. function fs.copy(from,to) -- string string -- boolean -- copies a file from *from* to *to*
  61. local of = fs.open(from,"rb")
  62. local df = fs.open(to,"wb")
  63. if not of or not df then
  64. return false
  65. end
  66. local tmp
  67. repeat
  68. tmp = of:read(2048)
  69. df:write(tmp or "")
  70. until not tmp
  71. df:close()
  72. of:close()
  73. return true
  74. end
  75. function fs.rename(from,to) -- string string -- boolean -- Moves file *from* to *to*
  76. local ofsi, opath = fs.resolve(from)
  77. local dfsi, dpath = fs.resolve(to)
  78. if ofsi == dfsi then
  79. fsmounts[ofsi].rename(opath,dpath)
  80. return true
  81. end
  82. if not fs.copy(from,to) then return false end
  83. if not fs.remove(from) then return false end
  84. return true
  85. end
  86. function fs.mount(path,proxy) -- string table -- boolean -- Mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy.
  87. if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then
  88. fsmounts[table.concat(fs.segments(path),"/")] = proxy
  89. return true
  90. end
  91. return false, "path is not a directory"
  92. end
  93. function fs.umount(path) -- string -- -- Unmounts filesystem from *path*.
  94. local fsi,_ = fs.resolve(path)
  95. fsmounts[fsi] = nil
  96. end
  97. function fs.mounts() -- -- table -- Returns a table containing the mount points of all mounted filesystems
  98. local rt = {}
  99. for k,v in pairs(fsmounts) do
  100. rt[#rt+1] = k,v.address or "unknown"
  101. end
  102. table.sort(rt)
  103. return rt
  104. end
  105. function fs.address(path) -- string -- string -- Returns the address of the filesystem at a given path, if applicable; do not expect a sensical response
  106. local fsi,_ = fs.resolve(path)
  107. return fsmounts[fsi].address
  108. end
  109. function fs.type(path) -- string -- string -- Returns the component type of the filesystem at a given path, if applicable
  110. local fsi,_ = fs.resolve(path)
  111. return fsmounts[fsi].fstype or fsmounts[fsi].type or "filesystem"
  112. end
  113. fsmounts["/"] = component.proxy(computer.tmpAddress())
  114. fs.makeDirectory("temp")
  115. if computer.getBootAddress and component.type(computer.getBootAddress()) == "filesystem" then
  116. fs.makeDirectory("boot")
  117. fs.mount("boot",component.proxy(computer.getBootAddress()))
  118. end
  119. end