Advertisement
Guest User

untar.lua

a guest
Sep 20th, 2017
698
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.18 KB | None | 0 0
  1. -- Tar extraction module based off LUARocks : github.com/keplerproject/luarocks
  2. -- By Danny @ anscamobile
  3. --
  4. -- Restored directory creation
  5. -- Handles space-padded numbers, e.g. in the size field, so it can handle a TAR file
  6. -- created by the OS X UNIX tar.
  7. -- By David Gross
  8.  
  9. -- Adapted for Gideros Mobile by Emanuel Braz - fastencoding@gmail.com
  10. -- test mock
  11. -- delete tar file after unpacking
  12. -- callback function if needed
  13.  
  14. --local lfs = require "lfs"
  15.  
  16. local blocksize = 512
  17. local _ceil = math.ceil
  18. local _tonumber = tonumber
  19. local _ioOpen = io.open
  20. local byte = string.byte
  21.  
  22. -- trim from http://lua-users.org/wiki/StringTrim
  23. function trim(s)
  24. return s:match'^%s*(.*%S)' or ''
  25. end
  26.  
  27. local function get_typeflag(flag)
  28. if flag == "0" or flag == "\0" then return "file"
  29. elseif flag == "1" then return "link"
  30. elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU
  31. elseif flag == "3" then return "character"
  32. elseif flag == "4" then return "block"
  33. elseif flag == "5" then return "directory"
  34. elseif flag == "6" then return "fifo"
  35. elseif flag == "7" then return "contiguous" -- "reserved" in POSIX, "contiguous" in GNU
  36. elseif flag == "x" then return "next file"
  37. elseif flag == "g" then return "global extended header"
  38. elseif flag == "L" then return "long name"
  39. elseif flag == "K" then return "long link name"
  40. end
  41. return "unknown"
  42. end
  43.  
  44. local function octal_to_number(octal)
  45. local exp = 0
  46. local number = 0
  47. octal = trim(octal)
  48. for i = #octal,1,-1 do
  49. local digit = _tonumber(octal:sub(i,i))
  50. if not digit then break end
  51. number = number + (digit * 8^exp)
  52. exp = exp + 1
  53. end
  54. return number
  55. end
  56.  
  57. -- Checksum
  58. local function checksum_header(block)
  59. local sum = 256
  60. for i = 1,148 do
  61. sum = sum + block:byte(i)
  62. end
  63. for i = 157,500 do
  64. sum = sum + block:byte(i)
  65. end
  66. return sum
  67. end
  68.  
  69. local function nullterm(s)
  70. return s:match("^[^%z]*")
  71. end
  72.  
  73. local function read_header_block(block)
  74. local header = {}
  75. header.name = nullterm(block:sub(1,100))
  76. header.mode = nullterm(block:sub(101,108))
  77. header.uid = octal_to_number(nullterm(block:sub(109,116)))
  78. header.gid = octal_to_number(nullterm(block:sub(117,124)))
  79. header.size = octal_to_number(nullterm(block:sub(125,136)))
  80. header.mtime = octal_to_number(nullterm(block:sub(137,148)))
  81. header.chksum = octal_to_number(nullterm(block:sub(149,156)))
  82. header.typeflag = get_typeflag(block:sub(157,157))
  83. header.linkname = nullterm(block:sub(158,257))
  84. header.magic = block:sub(258,263)
  85. header.version = block:sub(264,265)
  86. header.uname = nullterm(block:sub(266,297))
  87. header.gname = nullterm(block:sub(298,329))
  88. header.devmajor = octal_to_number(nullterm(block:sub(330,337)))
  89. header.devminor = octal_to_number(nullterm(block:sub(338,345)))
  90. header.prefix = block:sub(346,500)
  91. header.pad = block:sub(501,512)
  92. if header.magic ~= "ustar " and header.magic ~= "ustar\0" then
  93. return false, "Invalid header magic "..header.magic
  94. end
  95. if header.version ~= "00" and header.version ~= " \0" then
  96. return false, "Unknown version "..header.version
  97. end
  98. if not checksum_header(block) == header.chksum then
  99. return false, "Failed header checksum"
  100. end
  101. return header
  102. end
  103.  
  104. --[[
  105. Untar file - Descompacta arquivo
  106. param(string) path for tar file
  107. param(string) path for destination folder
  108. param(bool) To delete after unpack
  109. param(function) callbak function
  110. --]]
  111.  
  112. function untar(filePath, destPath, removeOldFiles)
  113.  
  114. if filePath == "mock" then
  115. return true
  116. end
  117.  
  118. local tar_handle = io.open(filePath, "rb")
  119. if not tar_handle then return nil, "Error opening file" end
  120.  
  121. local long_name, long_link_name
  122. while true do
  123. local block
  124.  
  125. -- Read a header
  126. repeat
  127. block = tar_handle:read(blocksize)
  128. until (not block) or checksum_header(block) > 256
  129. if not block then break end
  130. local header, err = read_header_block(block)
  131. if not header then
  132. print(err)
  133. end
  134.  
  135. -- read entire file that follows header
  136. local file_data = tar_handle:read(_ceil(header.size / blocksize) * blocksize):sub(1,header.size)
  137.  
  138. if header.typeflag == "long name" then
  139. long_name = nullterm(file_data)
  140. elseif header.typeflag == "long link name" then
  141. long_link_name = nullterm(file_data)
  142. else
  143. if long_name then
  144. header.name = long_name
  145. long_name = nil
  146. end
  147. if long_link_name then
  148. header.name = long_link_name
  149. long_link_name = nil
  150. end
  151. end
  152.  
  153. local pathname
  154.  
  155. if (destPath and string.sub(destPath,-1) ~= "/") then
  156. pathname = destPath.."/"..header.name
  157. else
  158. pathname = destPath..header.name
  159. end
  160.  
  161. if header.typeflag == "directory" then
  162. os.execute("mkdir " .. pathname) -- lfs.mkdir( pathname )
  163. elseif header.typeflag == "file" then
  164. file_handle = io.open(pathname, "wb")
  165. file_handle:write(file_data)
  166. file_handle:close()
  167.  
  168. end
  169. end
  170. tar_handle:close()
  171.  
  172. if removeOldFiles == true then
  173. local ok, err = os.remove(filePath)
  174. if not ok then return nil, err end
  175. end
  176.  
  177. -- if onComplete then
  178. -- if type(onComplete) == "function" then
  179. -- print ("TAR COMPLETED...")
  180. -- onComplete()
  181. -- else
  182. -- print("TAR ERROR : OnComplete must be a function")
  183. -- end
  184. -- end
  185.  
  186. return true
  187. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement