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.

113 lines
2.5KB

  1. local mtar = {}
  2. -- detect OS hopefully
  3. if _OSVERSION then
  4. if _OSVERSION:sub(1,8) == "OpenOS" then
  5. OPENOS = true
  6. elseif _OSVERSION:sub(1,9) == "PsychOS" then
  7. PSYCHOS = true
  8. end
  9. else
  10. LINUX = true
  11. end
  12. local function mkdir(dir)
  13. if OPENOS or LINUX then
  14. os.execute("mkdir "..dest.."/"..dir.." &> /dev/null")
  15. elseif PSYCHOS then
  16. -- todo: write PsychOS support
  17. end
  18. end
  19. local function toint(s)
  20. local n = 0
  21. local i = 1
  22. for p in s:gmatch(".") do
  23. n = n << 8
  24. n = n | string.byte(p)
  25. i=i+1
  26. end
  27. return n
  28. end
  29. local function cint(n,l)
  30. local t={}
  31. for i = 0, 7 do
  32. t[i+1] = (n >> (i * 8)) & 0xFF
  33. end
  34. return string.reverse(string.char(table.unpack(t)):sub(1,l))
  35. end
  36. local function cleanPath(path)
  37. local pt = {}
  38. for segment in path:gmatch("[^/]+") do
  39. if segment == ".." then
  40. pt[#pt] = nil
  41. elseif segment ~= "." then
  42. pt[#pt+1] = segment
  43. end
  44. end
  45. return table.concat(pt,"/")
  46. end
  47. function mtar.genHeader(fname,len) -- generate a header for file *fname* when provided with file length *len*
  48. return string.format("%s%s%s",cint(fname:len(),2),fname,cint(len,2))
  49. end
  50. 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.
  51. local remain = 0
  52. local function read(n)
  53. local rb = stream:read(math.min(n,remain))
  54. remain = remain - rb:len()
  55. return rb
  56. end
  57. return function()
  58. stream:read(remain)
  59. local nlen = toint(stream:read(2) or "\0\0")
  60. if nlen == 0 then
  61. return
  62. end
  63. local name = cleanPath(stream:read(nlen))
  64. local fsize = toint(stream:read(2))
  65. remain = fsize
  66. return name, read, fsize
  67. end
  68. end
  69. function mtar.unarchive(stream,dest,verbose) -- Extract mtar archive read from *stream* to *dest*. If *verbose*, print status.
  70. dest = dest or "."
  71. while true do
  72. local nlen = toint(stream:read(2) or "\0\0")
  73. if nlen == 0 then
  74. break
  75. end
  76. local name = cleanPath(stream:read(nlen))
  77. local fsize = toint(stream:read(2))
  78. if verbose then
  79. io.write(name.." "..tostring(fsize).."... ")
  80. end
  81. local dir = name:match("(.+)/.*%.?.+")
  82. if (dir) then
  83. mkdir(dir)
  84. end
  85. local f = io.open(dest.."/"..name,"wb")
  86. local rsize,buf = fsize, ""
  87. if f then
  88. repeat
  89. buf = stream:read(math.min(rsize,2048))
  90. f:write(buf)
  91. rsize = rsize - buf:len()
  92. if verbose then
  93. io.write(tostring(rsize).." ")
  94. end
  95. until rsize <= 1
  96. f:close()
  97. end
  98. if verbose then
  99. print("done.")
  100. end
  101. end
  102. end
  103. return mtar