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.

146 lines
3.8KB

  1. do
  2. fs = {}
  3. local fsmounts = {}
  4. -- basics
  5. function fs.segments(path) -- 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) -- 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. if length == "*a" then
  33. length = math.huge
  34. end
  35. if type(length) == "number" then
  36. local rstr, lstr = "", ""
  37. repeat
  38. lstr = fsmounts[self.fs].read(self.fid,math.min(2^16,length-rstr:len())) or ""
  39. rstr = rstr .. lstr
  40. until rstr:len() == length or lstr == ""
  41. return rstr
  42. elseif type(length) == "string" then
  43. local buf = ""
  44. if length == "*l" then
  45. length = "\n"
  46. end
  47. repeat
  48. local rb = fsmounts[self.fs].read(self.fid,1) or ""
  49. buf = buf .. rb
  50. until buf:match(length) or rb == ""
  51. return buf:match("(.*)"..length)
  52. end
  53. return fsmounts[self.fs].read(self.fid,length)
  54. end
  55. local function fwrite(self,data)
  56. fsmounts[self.fs].write(self.fid,data)
  57. end
  58. local function fseek(self,dist)
  59. fsmounts[self.fs].seek(self.fid,dist)
  60. end
  61. local function fclose(self)
  62. fsmounts[self.fs].close(self.fid)
  63. end
  64. function fs.open(path,mode) -- opens file *path* with mode *mode*
  65. mode = mode or "rb"
  66. local fsi,path = fs.resolve(path)
  67. if not fsmounts[fsi] then return false end
  68. local fid = fsmounts[fsi].open(path,mode)
  69. if fid then
  70. local fobj = {["fs"]=fsi,["fid"]=fid,["seek"]=fseek,["close"]=fclose}
  71. if mode:find("r") then
  72. fobj.read = fread
  73. end
  74. if mode:find("w") then
  75. fobj.write = fwrite
  76. end
  77. return fobj
  78. end
  79. return false
  80. end
  81. function fs.copy(from,to) -- copies a file from *from* to *to*
  82. local of = fs.open(from,"rb")
  83. local df = fs.open(to,"wb")
  84. if not of or not df then
  85. return false
  86. end
  87. df:write(of:read("*a"))
  88. df:close()
  89. of:close()
  90. end
  91. function fs.rename(from,to) -- moves file *from* to *to*
  92. local ofsi, opath = fs.resolve(from)
  93. local dfsi, dpath = fs.resolve(to)
  94. if ofsi == dfsi then
  95. fsmounts[ofsi].rename(opath,dpath)
  96. return true
  97. end
  98. fs.copy(from,to)
  99. fs.remove(from)
  100. return true
  101. end
  102. function fs.mount(path,proxy) -- mounts the filesystem *proxy* to the mount point *path* if it is a directory. BYO proxy.
  103. if fs.isDirectory(path) and not fsmounts[table.concat(fs.segments(path),"/")] then
  104. fsmounts[table.concat(fs.segments(path),"/")] = proxy
  105. return true
  106. end
  107. return false, "path is not a directory"
  108. end
  109. function fs.umount(path)
  110. local fsi,_ = fs.resolve(path)
  111. fsmounts[fsi] = nil
  112. end
  113. function fs.mounts() -- returns a table containing the mount points of all mounted filesystems
  114. local rt = {}
  115. for k,v in pairs(fsmounts) do
  116. rt[#rt+1] = k,v.address or "unknown"
  117. end
  118. return rt
  119. end
  120. function fs.address(path) -- returns the address of the filesystem at a given path, if applicable
  121. local fsi,_ = fs.resolve(path)
  122. return fsmounts[fsi].address
  123. end
  124. function fs.type(path) -- returns the component type of the filesystem at a given path, if applicable
  125. local fsi,_ = fs.resolve(path)
  126. return fsmounts[fsi].type
  127. end
  128. fsmounts["/"] = component.proxy(computer.tmpAddress())
  129. fs.makeDirectory("temp")
  130. if computer.getBootAddress then
  131. fs.makeDirectory("boot")
  132. fs.mount("boot",component.proxy(computer.getBootAddress()))
  133. end
  134. end