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.

61 lines
1.4KB

  1. local mtar = {}
  2. local function toint(s)
  3. local n = 0
  4. local i = 1
  5. for p in s:gmatch(".") do
  6. n = n << 8
  7. n = n | string.byte(p)
  8. i=i+1
  9. end
  10. return n
  11. end
  12. local function cint(n,l)
  13. local t={}
  14. for i = 0, 7 do
  15. t[i+1] = (n >> (i * 8)) & 0xFF
  16. end
  17. return string.reverse(string.char(table.unpack(t)):sub(1,l))
  18. end
  19. local function cleanPath(path)
  20. local pt = {}
  21. for segment in path:gmatch("[^/]+") do
  22. if segment == ".." then
  23. pt[#pt] = nil
  24. elseif segment ~= "." then
  25. pt[#pt+1] = segment
  26. end
  27. end
  28. return table.concat(pt,"/")
  29. end
  30. function mtar.genHeader(fname,len) -- string number -- string -- generate a header for file *fname* when provided with file length *len*
  31. return string.format("%s%s%s",cint(fname:len(),2),fname,cint(len,2))
  32. end
  33. function mtar.iter(stream) -- table -- function -- Given buffer *stream*, returns an iterator suitable for use with *for* that returns, for each iteration, the file name, a function to read from the file, and the length of the file.
  34. local remain = 0
  35. local function read(n)
  36. local rb = stream:read(math.min(n,remain))
  37. remain = remain - rb:len()
  38. return rb
  39. end
  40. return function()
  41. while remain > 0 do
  42. remain=remain-#stream:read(math.min(remain,2048))
  43. end
  44. local nlen = toint(stream:read(2) or "\0\0")
  45. if nlen == 0 then
  46. return
  47. end
  48. local name = cleanPath(stream:read(nlen))
  49. local fsize = toint(stream:read(2))
  50. remain = fsize
  51. return name, read, fsize
  52. end
  53. end
  54. return mtar