diff options
| -rw-r--r-- | src/luarocks/tools/tar.tl (renamed from src/luarocks/tools/tar.lua) | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.tl index bac7b2a9..a156bf9f 100644 --- a/src/luarocks/tools/tar.lua +++ b/src/luarocks/tools/tar.tl | |||
| @@ -1,14 +1,35 @@ | |||
| 1 | 1 | ||
| 2 | --- A pure-Lua implementation of untar (unpacking .tar archives) | 2 | --- A pure-Lua implementation of untar (unpacking .tar archives) |
| 3 | local tar = {} | 3 | local record tar |
| 4 | record Header | ||
| 5 | name: string | ||
| 6 | mode: string | ||
| 7 | uid: integer | ||
| 8 | gid: integer | ||
| 9 | size: integer | ||
| 10 | mtime: integer | ||
| 11 | chksum: integer | ||
| 12 | typeflag: string | ||
| 13 | linkname: string | ||
| 14 | magic: string | ||
| 15 | version: string | ||
| 16 | uname: string | ||
| 17 | gname: string | ||
| 18 | devmajor: integer | ||
| 19 | devminor: integer | ||
| 20 | prefix: string | ||
| 21 | end | ||
| 22 | end | ||
| 4 | 23 | ||
| 5 | local fs = require("luarocks.fs") | 24 | local fs = require("luarocks.fs") |
| 6 | local dir = require("luarocks.dir") | 25 | local dir = require("luarocks.dir") |
| 7 | local fun = require("luarocks.fun") | 26 | local fun = require("luarocks.fun") |
| 8 | 27 | ||
| 28 | local type Header = tar.Header | ||
| 29 | |||
| 9 | local blocksize = 512 | 30 | local blocksize = 512 |
| 10 | 31 | ||
| 11 | local function get_typeflag(flag) | 32 | local function get_typeflag(flag: string): string |
| 12 | if flag == "0" or flag == "\0" then return "file" | 33 | if flag == "0" or flag == "\0" then return "file" |
| 13 | elseif flag == "1" then return "link" | 34 | elseif flag == "1" then return "link" |
| 14 | elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU | 35 | elseif flag == "2" then return "symlink" -- "reserved" in POSIX, "symlink" in GNU |
| @@ -25,22 +46,22 @@ local function get_typeflag(flag) | |||
| 25 | return "unknown" | 46 | return "unknown" |
| 26 | end | 47 | end |
| 27 | 48 | ||
| 28 | local function octal_to_number(octal) | 49 | local function octal_to_number(octal: string): integer |
| 29 | local exp = 0 | 50 | local exp = 0 |
| 30 | local number = 0 | 51 | local number: integer = 0 |
| 31 | octal = octal:gsub("%s", "") | 52 | octal = octal:gsub("%s", "") |
| 32 | for i = #octal,1,-1 do | 53 | for i = #octal,1,-1 do |
| 33 | local digit = tonumber(octal:sub(i,i)) | 54 | local digit = math.tointeger(octal:sub(i,i)) |
| 34 | if not digit then | 55 | if not digit then |
| 35 | break | 56 | break |
| 36 | end | 57 | end |
| 37 | number = number + (digit * 8^exp) | 58 | number = number + (digit * math.tointeger(8^exp)) |
| 38 | exp = exp + 1 | 59 | exp = exp + 1 |
| 39 | end | 60 | end |
| 40 | return number | 61 | return number |
| 41 | end | 62 | end |
| 42 | 63 | ||
| 43 | local function checksum_header(block) | 64 | local function checksum_header(block: string): number |
| 44 | local sum = 256 | 65 | local sum = 256 |
| 45 | 66 | ||
| 46 | if block:byte(1) == 0 then | 67 | if block:byte(1) == 0 then |
| @@ -59,12 +80,12 @@ local function checksum_header(block) | |||
| 59 | return sum | 80 | return sum |
| 60 | end | 81 | end |
| 61 | 82 | ||
| 62 | local function nullterm(s) | 83 | local function nullterm(s: string): string |
| 63 | return s:match("^[^%z]*") | 84 | return s:match("^[^%z]*") |
| 64 | end | 85 | end |
| 65 | 86 | ||
| 66 | local function read_header_block(block) | 87 | local function read_header_block(block: string): boolean | Header, string |
| 67 | local header = {} | 88 | local header: Header = {} |
| 68 | header.name = nullterm(block:sub(1,100)) | 89 | header.name = nullterm(block:sub(1,100)) |
| 69 | header.mode = nullterm(block:sub(101,108)):gsub(" ", "") | 90 | header.mode = nullterm(block:sub(101,108)):gsub(" ", "") |
| 70 | header.uid = octal_to_number(nullterm(block:sub(109,116))) | 91 | header.uid = octal_to_number(nullterm(block:sub(109,116))) |
| @@ -96,18 +117,16 @@ local function read_header_block(block) | |||
| 96 | return header | 117 | return header |
| 97 | end | 118 | end |
| 98 | 119 | ||
| 99 | function tar.untar(filename, destdir) | 120 | function tar.untar(filename: string, destdir: string): boolean, string |
| 100 | assert(type(filename) == "string") | ||
| 101 | assert(type(destdir) == "string") | ||
| 102 | 121 | ||
| 103 | local tar_handle = io.open(filename, "rb") | 122 | local tar_handle = io.open(filename, "rb") |
| 104 | if not tar_handle then return nil, "Error opening file "..filename end | 123 | if not tar_handle then return nil, "Error opening file "..filename end |
| 105 | 124 | ||
| 106 | local long_name, long_link_name | 125 | local long_name, long_link_name: string, string |
| 107 | local ok, err | 126 | local ok, err: boolean, string |
| 108 | local make_dir = fun.memoize(fs.make_dir) | 127 | local make_dir = fun.memoize(fs.make_dir) |
| 109 | while true do | 128 | while true do |
| 110 | local block | 129 | local block: string |
| 111 | repeat | 130 | repeat |
| 112 | block = tar_handle:read(blocksize) | 131 | block = tar_handle:read(blocksize) |
| 113 | until (not block) or block:byte(1) > 0 | 132 | until (not block) or block:byte(1) > 0 |
| @@ -117,13 +136,13 @@ function tar.untar(filename, destdir) | |||
| 117 | break | 136 | break |
| 118 | end | 137 | end |
| 119 | 138 | ||
| 120 | local header | 139 | local headerp: boolean | Header |
| 121 | header, err = read_header_block(block) | 140 | headerp, err = read_header_block(block) |
| 122 | if not header then | 141 | if not headerp then |
| 123 | ok = false | 142 | ok = false |
| 124 | break | 143 | break |
| 125 | end | 144 | end |
| 126 | 145 | local header: Header = headerp as Header --! cast | |
| 127 | local file_data = "" | 146 | local file_data = "" |
| 128 | if header.size > 0 then | 147 | if header.size > 0 then |
| 129 | local nread = math.ceil(header.size / blocksize) * blocksize | 148 | local nread = math.ceil(header.size / blocksize) * blocksize |
| @@ -162,7 +181,7 @@ function tar.untar(filename, destdir) | |||
| 162 | break | 181 | break |
| 163 | end | 182 | end |
| 164 | end | 183 | end |
| 165 | local file_handle | 184 | local file_handle: FILE |
| 166 | file_handle, err = io.open(pathname, "wb") | 185 | file_handle, err = io.open(pathname, "wb") |
| 167 | if not file_handle then | 186 | if not file_handle then |
| 168 | ok = nil | 187 | ok = nil |
