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.

147 lines
3.4KB

  1. local mtar = require "libmtar"
  2. local w, lz16 = pcall(require, "liblz16")
  3. if not w then lz16 = nil end
  4. pkgfs = {}
  5. pkgfs.files = {}
  6. local findex = {}
  7. local handles = {}
  8. local hc = 0
  9. local function rfalse()
  10. return false
  11. end
  12. local function rzero()
  13. return 0
  14. end
  15. pkgfs.component = {seek = rfalse, makeDirectory = rfalse, write = rfalse, rename = rfalse, setlabel = rfalse, spaceUsed = rzero, spaceTotal = rzero, lastModified = rzero, address = "pkgfs"}
  16. local function fopen(path,comp)
  17. local f
  18. if comp and lz16 then
  19. f = lz16.open(path,"rb")
  20. else
  21. f = io.open(path,"rb")
  22. end
  23. return f
  24. end
  25. local function fnormalize(s)
  26. return table.concat(fs.segments(s),"/")
  27. end
  28. function pkgfs.component.exists(path)
  29. path = fnormalize(path)
  30. return findex[path] and true
  31. end
  32. function pkgfs.component.list(path)
  33. path = fnormalize(path).."/"
  34. local ft,rt = {},{}
  35. for k,v in pairs(findex) do
  36. k="/"..k
  37. if k:match(path.."([^/]+)/.+") then
  38. ft[k:match(path.."([^/]+)/.+").."/"] = true
  39. elseif k:match(path.."([^/]+)") then
  40. ft[k:match(path.."([^/]+)")] = true
  41. end
  42. end
  43. for k,v in pairs(ft) do
  44. rt[#rt+1] = k
  45. end
  46. return rt
  47. end
  48. function pkgfs.component.isDirectory(path)
  49. path = fnormalize(path).."/"
  50. for k,v in pairs(findex) do
  51. k="/"..k
  52. if k:match(path.."([^/]+)/.+") then
  53. return true
  54. end
  55. end
  56. return false
  57. end
  58. function pkgfs.component.size(path)
  59. path=fnormalize(path)
  60. if not findex[path] then return false end
  61. local f = fopen(findex[path][1], findex[path][2])
  62. for fname, read, fsize in mtar.iter(f) do
  63. if fname == path then
  64. return fsize
  65. end
  66. end
  67. return false
  68. end
  69. function pkgfs.component.open(path,mode)
  70. path=fnormalize(path)
  71. if mode:find("w") or mode:find("a") or not findex[path] then
  72. return false
  73. end
  74. local f = fopen(findex[path][1],findex[path][2])
  75. for fname,read,fsize in mtar.iter(f) do
  76. if fname == path then
  77. hc = hc + 1
  78. handles[hc] = {read, f}
  79. return hc
  80. end
  81. end
  82. end
  83. function pkgfs.component.read(handle, n)
  84. if not handles[handle] then return false end
  85. local rv = handles[handle][1](n)
  86. if not rv then return nil end
  87. if rv:len() < 1 then return nil end
  88. return rv
  89. end
  90. function pkgfs.component.close(handle)
  91. if not handles[handle] then return false end
  92. handles[handle][2]:close()
  93. handles[handle] = nil
  94. return true
  95. end
  96. local function index()
  97. findex = {}
  98. for k,v in pairs(pkgfs.files) do
  99. fname, comp = v[1], v[2]
  100. if fname:sub(1,1) ~= "/" then
  101. fname = "/"..fnormalize(os.getenv("PWD").."/"..fname)
  102. end
  103. local f = fopen(fname,comp)
  104. if not f then error("unable to open file "..fname) end
  105. for name, read, fsize in mtar.iter(f) do
  106. findex[fnormalize(name)] = {fname,comp}
  107. end
  108. f:close()
  109. end
  110. return true
  111. end
  112. function pkgfs.add(fname,comp) -- string boolean -- boolean -- Add a package as specified in *fname* to the pkgfs component. If *comp* is true, read it as a LZ16-compressed package.
  113. pkgfs.files[#pkgfs.files+1] = {fname,comp}
  114. return index()
  115. end
  116. function pkgfs.remove(fname) -- string -- boolean -- Removes the package specified by *fname* from the pkgfs index.
  117. for k,v in pairs(pkgfs.files) do
  118. if v[1] == fname then
  119. table.remove(pkgfs.files,k)
  120. end
  121. end
  122. return index()
  123. end
  124. fs.makeDirectory("/pkg")
  125. fs.mount("/pkg",pkgfs.component)
  126. for _,file in ipairs(fs.list("/boot/pkg/")) do
  127. if file:sub(-5) == ".mtar" then
  128. pcall(pkgfs.add,"/boot/pkg/"..file)
  129. elseif file:sub(-9) == ".mtar.lss" then
  130. pcall(pkgfs.add,"/boot/pkg/"..file,true)
  131. end
  132. end
  133. return pkgfs