diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2010-11-08 14:58:18 -0200 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2010-11-08 14:58:18 -0200 |
| commit | 6ecf9ab8ee490cc562cdd199f1533a4cf3f1b918 (patch) | |
| tree | 6855ab8ddf5f4aee657390e4d6687d3cb5536c92 | |
| parent | 1725c68ca1f6f4b82f3adf2d2b791091c197230a (diff) | |
| download | luarocks-6ecf9ab8ee490cc562cdd199f1533a4cf3f1b918.tar.gz luarocks-6ecf9ab8ee490cc562cdd199f1533a4cf3f1b918.tar.bz2 luarocks-6ecf9ab8ee490cc562cdd199f1533a4cf3f1b918.zip | |
Fixes for native zip packing module.
| -rw-r--r-- | src/luarocks/tools/zip.lua | 187 |
1 files changed, 100 insertions, 87 deletions
diff --git a/src/luarocks/tools/zip.lua b/src/luarocks/tools/zip.lua index 18ad967e..caeb4ac9 100644 --- a/src/luarocks/tools/zip.lua +++ b/src/luarocks/tools/zip.lua | |||
| @@ -1,7 +1,11 @@ | |||
| 1 | 1 | ||
| 2 | module("luarocks.tools.zip", package.seeall) | 2 | module("luarocks.tools.zip", package.seeall) |
| 3 | 3 | ||
| 4 | local zlib = require "zlib" | 4 | local zlib = require("zlib") |
| 5 | local fs = require("luarocks.fs") | ||
| 6 | local dir = require("luarocks.dir") | ||
| 7 | |||
| 8 | local size_buf = 65535 | ||
| 5 | 9 | ||
| 6 | local function number_to_bytestring(number, nbytes) | 10 | local function number_to_bytestring(number, nbytes) |
| 7 | local out = {} | 11 | local out = {} |
| @@ -13,34 +17,17 @@ local function number_to_bytestring(number, nbytes) | |||
| 13 | return table.concat(out) | 17 | return table.concat(out) |
| 14 | end | 18 | end |
| 15 | 19 | ||
| 16 | --- Return a zip handle open for writing. | ||
| 17 | -- @param name filename of the zipfile to be created. | ||
| 18 | -- @return a zip handle, or nil in case of error. | ||
| 19 | function write_open(name) | ||
| 20 | |||
| 21 | local zf = {} | ||
| 22 | |||
| 23 | zf.ziphandle = io.open(name, "w") | ||
| 24 | if not zf.ziphandle then | ||
| 25 | return nil | ||
| 26 | end | ||
| 27 | zf.files = {} | ||
| 28 | zf.in_open_file = false | ||
| 29 | |||
| 30 | return zf | ||
| 31 | end | ||
| 32 | |||
| 33 | --- Begin a new file to be stored inside the zipfile. | 20 | --- Begin a new file to be stored inside the zipfile. |
| 34 | -- @param zf handle of the zipfile being written. | 21 | -- @param self handle of the zipfile being written. |
| 35 | -- @param filename filenome of the file to be added to the zipfile. | 22 | -- @param filename filenome of the file to be added to the zipfile. |
| 36 | -- @return true if succeeded, nil in case of failure. | 23 | -- @return true if succeeded, nil in case of failure. |
| 37 | function write_open_new_file_in_zip(zf, filename) | 24 | local function zipwriter_open_new_file_in_zip(self, filename) |
| 38 | if zf.in_open_file then | 25 | if self.in_open_file then |
| 39 | close_file_in_zip(zf) | 26 | self:close_file_in_zip() |
| 40 | return nil | 27 | return nil |
| 41 | end | 28 | end |
| 42 | local lfh = {} | 29 | local lfh = {} |
| 43 | zf.local_file_header = lfh | 30 | self.local_file_header = lfh |
| 44 | lfh.last_mod_file_time = 0 -- TODO | 31 | lfh.last_mod_file_time = 0 -- TODO |
| 45 | lfh.last_mod_file_date = 0 -- TODO | 32 | lfh.last_mod_file_date = 0 -- TODO |
| 46 | lfh.crc32 = 0 -- initial value | 33 | lfh.crc32 = 0 -- initial value |
| @@ -49,40 +36,41 @@ function write_open_new_file_in_zip(zf, filename) | |||
| 49 | lfh.file_name_length = #filename | 36 | lfh.file_name_length = #filename |
| 50 | lfh.extra_field_length = 0 | 37 | lfh.extra_field_length = 0 |
| 51 | lfh.file_name = filename:gsub("\\", "/") | 38 | lfh.file_name = filename:gsub("\\", "/") |
| 52 | zf.in_open_file = true | 39 | lfh.external_attr = 0 -- TODO properly store permissions |
| 53 | zf.data = {} | 40 | self.in_open_file = true |
| 41 | self.data = {} | ||
| 54 | return true | 42 | return true |
| 55 | end | 43 | end |
| 56 | 44 | ||
| 57 | --- Write data to the file currently being stored in the zipfile. | 45 | --- Write data to the file currently being stored in the zipfile. |
| 58 | -- @param zf handle of the zipfile being written. | 46 | -- @param self handle of the zipfile being written. |
| 59 | -- @param buf string containing data to be written. | 47 | -- @param buf string containing data to be written. |
| 60 | -- @return true if succeeded, nil in case of failure. | 48 | -- @return true if succeeded, nil in case of failure. |
| 61 | function write_in_file_in_zip(zf, buf) | 49 | local function zipwriter_write_file_in_zip(self, buf) |
| 62 | if not zf.in_open_file then | 50 | if not self.in_open_file then |
| 63 | return nil | 51 | return nil |
| 64 | end | 52 | end |
| 65 | local lfh = zf.local_file_header | 53 | local lfh = self.local_file_header |
| 66 | local cbuf = zlib.compress(buf):sub(3, -5) | 54 | local cbuf = zlib.compress(buf):sub(3, -5) |
| 67 | lfh.crc32 = zlib.crc32(lfh.crc32, buf) | 55 | lfh.crc32 = zlib.crc32(lfh.crc32, buf) |
| 68 | lfh.compressed_size = lfh.compressed_size + #cbuf | 56 | lfh.compressed_size = lfh.compressed_size + #cbuf |
| 69 | lfh.uncompressed_size = lfh.uncompressed_size + #buf | 57 | lfh.uncompressed_size = lfh.uncompressed_size + #buf |
| 70 | table.insert(zf.data, cbuf) | 58 | table.insert(self.data, cbuf) |
| 71 | return true | 59 | return true |
| 72 | end | 60 | end |
| 73 | 61 | ||
| 74 | --- Complete the writing of a file stored in the zipfile. | 62 | --- Complete the writing of a file stored in the zipfile. |
| 75 | -- @param zf handle of the zipfile being written. | 63 | -- @param self handle of the zipfile being written. |
| 76 | -- @return true if succeeded, nil in case of failure. | 64 | -- @return true if succeeded, nil in case of failure. |
| 77 | function write_close_file_in_zip(zf) | 65 | local function zipwriter_close_file_in_zip(self) |
| 78 | local zh = zf.ziphandle | 66 | local zh = self.ziphandle |
| 79 | 67 | ||
| 80 | if not zf.in_open_file then | 68 | if not self.in_open_file then |
| 81 | return nil | 69 | return nil |
| 82 | end | 70 | end |
| 83 | 71 | ||
| 84 | -- Local file header | 72 | -- Local file header |
| 85 | local lfh = zf.local_file_header | 73 | local lfh = self.local_file_header |
| 86 | lfh.offset = zh:seek() | 74 | lfh.offset = zh:seek() |
| 87 | zh:write(number_to_bytestring(0x04034b50, 4)) -- signature | 75 | zh:write(number_to_bytestring(0x04034b50, 4)) -- signature |
| 88 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 | 76 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 |
| @@ -98,7 +86,7 @@ function write_close_file_in_zip(zf) | |||
| 98 | zh:write(lfh.file_name) | 86 | zh:write(lfh.file_name) |
| 99 | 87 | ||
| 100 | -- File data | 88 | -- File data |
| 101 | for _, cbuf in ipairs(zf.data) do | 89 | for _, cbuf in ipairs(self.data) do |
| 102 | zh:write(cbuf) | 90 | zh:write(cbuf) |
| 103 | end | 91 | end |
| 104 | 92 | ||
| @@ -107,23 +95,59 @@ function write_close_file_in_zip(zf) | |||
| 107 | zh:write(number_to_bytestring(lfh.compressed_size, 4)) | 95 | zh:write(number_to_bytestring(lfh.compressed_size, 4)) |
| 108 | zh:write(number_to_bytestring(lfh.uncompressed_size, 4)) | 96 | zh:write(number_to_bytestring(lfh.uncompressed_size, 4)) |
| 109 | 97 | ||
| 110 | table.insert(zf.files, lfh) | 98 | table.insert(self.files, lfh) |
| 111 | zf.in_open_file = false | 99 | self.in_open_file = false |
| 112 | 100 | ||
| 113 | return true | 101 | return true |
| 114 | end | 102 | end |
| 115 | 103 | ||
| 104 | -- @return boolean or (boolean, string): true on success, | ||
| 105 | -- false and an error message on failure. | ||
| 106 | local function zipwriter_add(self, file) | ||
| 107 | local fin | ||
| 108 | local ok, err = self:open_new_file_in_zip(file) | ||
| 109 | if not ok then | ||
| 110 | err = "error in opening "..file.." in zipfile" | ||
| 111 | else | ||
| 112 | fin = io.open(file, "rb") | ||
| 113 | if not fin then | ||
| 114 | ok = false | ||
| 115 | err = "error opening "..file.." for reading" | ||
| 116 | end | ||
| 117 | end | ||
| 118 | while ok do | ||
| 119 | local buf = fin:read(size_buf) | ||
| 120 | if not buf then | ||
| 121 | break | ||
| 122 | end | ||
| 123 | ok = self:write_file_in_zip(buf) | ||
| 124 | if not ok then | ||
| 125 | err = "error in writing "..file.." in the zipfile" | ||
| 126 | end | ||
| 127 | end | ||
| 128 | if fin then | ||
| 129 | fin:close() | ||
| 130 | end | ||
| 131 | if ok then | ||
| 132 | ok = self:close_file_in_zip() | ||
| 133 | if not ok then | ||
| 134 | err = "error in writing "..file.." in the zipfile" | ||
| 135 | end | ||
| 136 | end | ||
| 137 | return ok == true, err | ||
| 138 | end | ||
| 139 | |||
| 116 | --- Complete the writing of the zipfile. | 140 | --- Complete the writing of the zipfile. |
| 117 | -- @param zf handle of the zipfile being written. | 141 | -- @param self handle of the zipfile being written. |
| 118 | -- @return true if succeeded, nil in case of failure. | 142 | -- @return true if succeeded, nil in case of failure. |
| 119 | function write_close(zf) | 143 | local function zipwriter_close(self) |
| 120 | local zh = zf.ziphandle | 144 | local zh = self.ziphandle |
| 121 | 145 | ||
| 122 | local central_directory_offset = zh:seek() | 146 | local central_directory_offset = zh:seek() |
| 123 | 147 | ||
| 124 | local size_of_central_directory = 0 | 148 | local size_of_central_directory = 0 |
| 125 | -- Central directory structure | 149 | -- Central directory structure |
| 126 | for _, lfh in ipairs(zf.files) do | 150 | for _, lfh in ipairs(self.files) do |
| 127 | zh:write(number_to_bytestring(0x02014b50, 4)) -- signature | 151 | zh:write(number_to_bytestring(0x02014b50, 4)) -- signature |
| 128 | zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX | 152 | zh:write(number_to_bytestring(3, 2)) -- version made by: UNIX |
| 129 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 | 153 | zh:write(number_to_bytestring(20, 2)) -- version needed to extract: 2.0 |
| @@ -139,7 +163,7 @@ function write_close(zf) | |||
| 139 | zh:write(number_to_bytestring(0, 2)) -- file comment length | 163 | zh:write(number_to_bytestring(0, 2)) -- file comment length |
| 140 | zh:write(number_to_bytestring(0, 2)) -- disk number start | 164 | zh:write(number_to_bytestring(0, 2)) -- disk number start |
| 141 | zh:write(number_to_bytestring(0, 2)) -- internal file attributes | 165 | zh:write(number_to_bytestring(0, 2)) -- internal file attributes |
| 142 | zh:write(number_to_bytestring(0, 4)) -- external file attributes | 166 | zh:write(number_to_bytestring(lfh.external_attr, 4)) -- external file attributes |
| 143 | zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header | 167 | zh:write(number_to_bytestring(lfh.offset, 4)) -- relative offset of local header |
| 144 | zh:write(lfh.file_name) | 168 | zh:write(lfh.file_name) |
| 145 | size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length | 169 | size_of_central_directory = size_of_central_directory + 46 + lfh.file_name_length |
| @@ -149,8 +173,8 @@ function write_close(zf) | |||
| 149 | zh:write(number_to_bytestring(0x06054b50, 4)) -- signature | 173 | zh:write(number_to_bytestring(0x06054b50, 4)) -- signature |
| 150 | zh:write(number_to_bytestring(0, 2)) -- number of this disk | 174 | zh:write(number_to_bytestring(0, 2)) -- number of this disk |
| 151 | zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory | 175 | zh:write(number_to_bytestring(0, 2)) -- number of disk with start of central directory |
| 152 | zh:write(number_to_bytestring(#zf.files, 2)) -- total number of entries in the central dir on this disk | 176 | zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir on this disk |
| 153 | zh:write(number_to_bytestring(#zf.files, 2)) -- total number of entries in the central dir | 177 | zh:write(number_to_bytestring(#self.files, 2)) -- total number of entries in the central dir |
| 154 | zh:write(number_to_bytestring(size_of_central_directory, 4)) | 178 | zh:write(number_to_bytestring(size_of_central_directory, 4)) |
| 155 | zh:write(number_to_bytestring(central_directory_offset, 4)) | 179 | zh:write(number_to_bytestring(central_directory_offset, 4)) |
| 156 | zh:write(number_to_bytestring(0, 2)) -- zip file comment length | 180 | zh:write(number_to_bytestring(0, 2)) -- zip file comment length |
| @@ -159,40 +183,27 @@ function write_close(zf) | |||
| 159 | return true | 183 | return true |
| 160 | end | 184 | end |
| 161 | 185 | ||
| 162 | -- @return boolean or (boolean, string): true on success, | 186 | --- Return a zip handle open for writing. |
| 163 | -- false and an error message on failure. | 187 | -- @param name filename of the zipfile to be created. |
| 164 | local function add_to_zip(zf, file) | 188 | -- @return a zip handle, or nil in case of error. |
| 165 | local fin | 189 | function new_zipwriter(name) |
| 166 | local ok, err = write_open_new_file_in_zip(zf, file) | 190 | |
| 167 | if not ok then | 191 | local zw = {} |
| 168 | err = "error in opening "..file.." in zipfile" | 192 | |
| 169 | else | 193 | zw.ziphandle = io.open(name, "w") |
| 170 | fin = io.open(file, "rb") | 194 | if not zw.ziphandle then |
| 171 | if not fin then | 195 | return nil |
| 172 | ok = false | ||
| 173 | err = "error opening "..file.." for reading" | ||
| 174 | end | ||
| 175 | end | ||
| 176 | while ok do | ||
| 177 | local buf = fin:read(size_buf) | ||
| 178 | if not buf then | ||
| 179 | break | ||
| 180 | end | ||
| 181 | ok = write_in_file_in_zip(zf, buf) | ||
| 182 | if not ok then | ||
| 183 | err = "error in writing "..file.." in the zipfile" | ||
| 184 | end | ||
| 185 | end | ||
| 186 | if fin then | ||
| 187 | fin:close() | ||
| 188 | end | ||
| 189 | if ok then | ||
| 190 | ok = write_close_file_in_zip(zf) | ||
| 191 | if not ok then | ||
| 192 | err = "error in writing "..file.." in the zipfile" | ||
| 193 | end | ||
| 194 | end | 196 | end |
| 195 | return ok == true, err | 197 | zw.files = {} |
| 198 | zw.in_open_file = false | ||
| 199 | |||
| 200 | zw.add = zipwriter_add | ||
| 201 | zw.close = zipwriter_close | ||
| 202 | zw.open_new_file_in_zip = zipwriter_open_new_file_in_zip | ||
| 203 | zw.write_file_in_zip = zipwriter_write_file_in_zip | ||
| 204 | zw.close_file_in_zip = zipwriter_close_file_in_zip | ||
| 205 | |||
| 206 | return zw | ||
| 196 | end | 207 | end |
| 197 | 208 | ||
| 198 | --- Compress files in a .zip archive. | 209 | --- Compress files in a .zip archive. |
| @@ -202,29 +213,31 @@ end | |||
| 202 | -- @return boolean or (boolean, string): true on success, | 213 | -- @return boolean or (boolean, string): true on success, |
| 203 | -- false and an error message on failure. | 214 | -- false and an error message on failure. |
| 204 | function zip(zipfile, ...) | 215 | function zip(zipfile, ...) |
| 205 | local zf = write_open(filename) | 216 | local zw = new_zipwriter(zipfile) |
| 206 | if not zf then | 217 | if not zw then |
| 207 | return nil, "error opening "..filename | 218 | return nil, "error opening "..zipfile |
| 208 | end | 219 | end |
| 209 | 220 | ||
| 210 | local ok, err | 221 | local ok, err |
| 211 | for _, file in pairs({...}) do | 222 | for _, file in pairs({...}) do |
| 212 | if fs.is_dir(file) then | 223 | if fs.is_dir(file) then |
| 213 | for _, file in pairs(fs.find(file)) do | 224 | for _, entry in pairs(fs.find(file)) do |
| 214 | if fs.is_file(file) then | 225 | local fullname = dir.path(file, entry) |
| 215 | ok, err = add_to_zip(file) | 226 | if fs.is_file(fullname) then |
| 227 | ok, err = zw:add(fullname) | ||
| 216 | if not ok then break end | 228 | if not ok then break end |
| 217 | end | 229 | end |
| 218 | end | 230 | end |
| 219 | else | 231 | else |
| 220 | ok, err = add_to_zip(file) | 232 | ok, err = zw:add(file) |
| 221 | if not ok then break end | 233 | if not ok then break end |
| 222 | end | 234 | end |
| 223 | end | 235 | end |
| 224 | 236 | ||
| 225 | local ok = write_close(zf) | 237 | local ok = zw:close() |
| 226 | if not ok then | 238 | if not ok then |
| 227 | return false, "error closing "..filename | 239 | return false, "error closing "..zipfile |
| 228 | end | 240 | end |
| 229 | return ok, err | 241 | return ok, err |
| 230 | end | 242 | end |
| 243 | |||
