Mercurial > embed
comparison libzip/lib/zip_close.c @ 56:056ee6b5913e
libzip: update to 1.3.0, closes #654
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 10 Oct 2017 20:43:12 +0200 |
parents | 2306f4b04790 |
children |
comparison
equal
deleted
inserted
replaced
55:a7a33cbf3e52 | 56:056ee6b5913e |
---|---|
1 /* | 1 /* |
2 zip_close.c -- close zip archive and update changes | 2 zip_close.c -- close zip archive and update changes |
3 Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner | 3 Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner |
4 | 4 |
5 This file is part of libzip, a library to manipulate ZIP archives. | 5 This file is part of libzip, a library to manipulate ZIP archives. |
6 The authors can be contacted at <libzip@nih.at> | 6 The authors can be contacted at <libzip@nih.at> |
7 | 7 |
8 Redistribution and use in source and binary forms, with or without | 8 Redistribution and use in source and binary forms, with or without |
49 #include <io.h> | 49 #include <io.h> |
50 #include <fcntl.h> | 50 #include <fcntl.h> |
51 #endif | 51 #endif |
52 | 52 |
53 | 53 |
54 /* max deflate size increase: size + ceil(size/16k)*5+6 */ | |
55 #define MAX_DEFLATE_SIZE_32 4293656963u | |
56 | |
57 static int add_data(zip_t *, zip_source_t *, zip_dirent_t *); | 54 static int add_data(zip_t *, zip_source_t *, zip_dirent_t *); |
58 static int copy_data(zip_t *, zip_uint64_t); | 55 static int copy_data(zip_t *, zip_uint64_t); |
59 static int copy_source(zip_t *, zip_source_t *); | 56 static int copy_source(zip_t *, zip_source_t *, zip_int64_t); |
60 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); | 57 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); |
61 | |
62 | 58 |
63 ZIP_EXTERN int | 59 ZIP_EXTERN int |
64 zip_close(zip_t *za) | 60 zip_close(zip_t *za) |
65 { | 61 { |
66 zip_uint64_t i, j, survivors; | 62 zip_uint64_t i, j, survivors; |
122 if (zip_source_begin_write(za->src) < 0) { | 118 if (zip_source_begin_write(za->src) < 0) { |
123 _zip_error_set_from_source(&za->error, za->src); | 119 _zip_error_set_from_source(&za->error, za->src); |
124 free(filelist); | 120 free(filelist); |
125 return -1; | 121 return -1; |
126 } | 122 } |
127 | 123 |
124 _zip_progress_start(za->progress); | |
128 error = 0; | 125 error = 0; |
129 for (j=0; j<survivors; j++) { | 126 for (j=0; j<survivors; j++) { |
130 int new_data; | 127 int new_data; |
131 zip_entry_t *entry; | 128 zip_entry_t *entry; |
132 zip_dirent_t *de; | 129 zip_dirent_t *de; |
133 | 130 |
131 _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)survivors); | |
132 | |
134 i = filelist[j].idx; | 133 i = filelist[j].idx; |
135 entry = za->entry+i; | 134 entry = za->entry+i; |
136 | 135 |
137 new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD)); | 136 new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); |
138 | 137 |
139 /* create new local directory entry */ | 138 /* create new local directory entry */ |
140 if (entry->changes == NULL) { | 139 if (entry->changes == NULL) { |
141 if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) { | 140 if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) { |
142 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); | 141 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); |
220 if (error) { | 219 if (error) { |
221 zip_source_rollback_write(za->src); | 220 zip_source_rollback_write(za->src); |
222 return -1; | 221 return -1; |
223 } | 222 } |
224 | 223 |
224 _zip_progress_end(za->progress); | |
225 | |
225 zip_discard(za); | 226 zip_discard(za); |
226 | 227 |
227 return 0; | 228 return 0; |
228 } | 229 } |
229 | 230 |
230 | 231 |
231 static int | 232 static int |
232 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) | 233 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) |
233 { | 234 { |
234 zip_int64_t offstart, offdata, offend; | 235 zip_int64_t offstart, offdata, offend, data_length; |
235 struct zip_stat st; | 236 struct zip_stat st; |
236 zip_source_t *s2; | 237 zip_source_t *src_final, *src_tmp; |
237 int ret; | 238 int ret; |
238 int is_zip64; | 239 int is_zip64; |
239 zip_flags_t flags; | 240 zip_flags_t flags; |
240 | 241 zip_int8_t compression_flags; |
242 bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; | |
243 | |
241 if (zip_source_stat(src, &st) < 0) { | 244 if (zip_source_stat(src, &st) < 0) { |
242 _zip_error_set_from_source(&za->error, src); | 245 _zip_error_set_from_source(&za->error, src); |
243 return -1; | 246 return -1; |
244 } | 247 } |
245 | 248 |
257 else { | 260 else { |
258 /* we'll recompress */ | 261 /* we'll recompress */ |
259 st.valid &= ~ZIP_STAT_COMP_SIZE; | 262 st.valid &= ~ZIP_STAT_COMP_SIZE; |
260 } | 263 } |
261 | 264 |
265 if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) { | |
266 st.valid |= ZIP_STAT_ENCRYPTION_METHOD; | |
267 st.encryption_method = ZIP_EM_NONE; | |
268 } | |
262 | 269 |
263 flags = ZIP_EF_LOCAL; | 270 flags = ZIP_EF_LOCAL; |
264 | 271 |
265 if ((st.valid & ZIP_STAT_SIZE) == 0) | 272 if ((st.valid & ZIP_STAT_SIZE) == 0) { |
266 flags |= ZIP_FL_FORCE_ZIP64; | 273 flags |= ZIP_FL_FORCE_ZIP64; |
274 data_length = -1; | |
275 } | |
267 else { | 276 else { |
268 de->uncomp_size = st.size; | 277 de->uncomp_size = st.size; |
278 /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */ | |
279 data_length = (zip_int64_t)st.size; | |
269 | 280 |
270 if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { | 281 if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { |
271 if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32) | 282 zip_uint64_t max_size; |
272 || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method)))) | 283 |
284 switch (ZIP_CM_ACTUAL(de->comp_method)) { | |
285 case ZIP_CM_BZIP2: | |
286 /* computed by looking at increase of 10 random files of size 1MB when | |
287 * compressed with bzip2, rounded up: 1.006 */ | |
288 max_size = 4269351188u; | |
289 break; | |
290 | |
291 case ZIP_CM_DEFLATE: | |
292 /* max deflate size increase: size + ceil(size/16k)*5+6 */ | |
293 max_size = 4293656963u; | |
294 break; | |
295 | |
296 case ZIP_CM_STORE: | |
297 max_size = 0xffffffffu; | |
298 break; | |
299 | |
300 default: | |
301 max_size = 0; | |
302 } | |
303 | |
304 if (st.size > max_size) { | |
273 flags |= ZIP_FL_FORCE_ZIP64; | 305 flags |= ZIP_FL_FORCE_ZIP64; |
306 } | |
274 } | 307 } |
275 else | 308 else |
276 de->comp_size = st.comp_size; | 309 de->comp_size = st.comp_size; |
277 } | 310 } |
278 | 311 |
279 if ((offstart = zip_source_tell_write(za->src)) < 0) { | 312 if ((offstart = zip_source_tell_write(za->src)) < 0) { |
313 _zip_error_set_from_source(&za->error, za->src); | |
280 return -1; | 314 return -1; |
281 } | 315 } |
282 | 316 |
283 /* as long as we don't support non-seekable output, clear data descriptor bit */ | 317 /* as long as we don't support non-seekable output, clear data descriptor bit */ |
284 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; | 318 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; |
285 if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) | 319 if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) { |
286 return -1; | 320 return -1; |
287 | 321 } |
288 | 322 |
289 if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) { | 323 needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method); |
290 zip_source_t *s_store, *s_crc; | 324 needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); |
291 zip_compression_implementation comp_impl; | 325 needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; |
326 needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE); | |
327 | |
328 needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method); | |
329 needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE); | |
330 needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE); | |
331 | |
332 src_final = src; | |
333 zip_source_keep(src_final); | |
334 | |
335 if (needs_decrypt) { | |
336 zip_encryption_implementation impl; | |
292 | 337 |
293 if (st.comp_method != ZIP_CM_STORE) { | 338 if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { |
294 if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { | 339 zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); |
295 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); | 340 zip_source_free(src_final); |
296 return -1; | 341 return -1; |
297 } | 342 } |
298 if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) { | 343 if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { |
299 /* error set by comp_impl */ | 344 /* error set by impl */ |
300 return -1; | 345 zip_source_free(src_final); |
301 } | 346 return -1; |
302 } | 347 } |
303 else { | 348 |
304 /* to have the same reference count to src as in the case where it's not stored */ | 349 zip_source_free(src_final); |
305 zip_source_keep(src); | 350 src_final = src_tmp; |
306 s_store = src; | 351 } |
307 } | 352 |
308 | 353 if (needs_decompress) { |
309 s_crc = zip_source_crc(za, s_store, 0); | 354 if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) { |
310 zip_source_free(s_store); | 355 zip_source_free(src_final); |
311 if (s_crc == NULL) { | 356 return -1; |
312 return -1; | 357 } |
313 } | 358 |
314 | 359 zip_source_free(src_final); |
315 if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { | 360 src_final = src_tmp; |
316 if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) { | 361 } |
317 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); | 362 |
318 zip_source_free(s_crc); | 363 if (needs_crc) { |
319 return -1; | 364 if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) { |
320 } | 365 zip_source_free(src_final); |
321 s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE); | 366 return -1; |
322 zip_source_free(s_crc); | 367 } |
323 if (s2 == NULL) { | 368 |
324 return -1; | 369 zip_source_free(src_final); |
325 } | 370 src_final = src_tmp; |
326 } | 371 } |
327 else { | 372 |
328 s2 = s_crc; | 373 if (needs_compress) { |
329 } | 374 if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) { |
330 } | 375 zip_source_free(src_final); |
331 else { | 376 return -1; |
332 zip_source_keep(src); | 377 } |
333 s2 = src; | 378 |
334 } | 379 zip_source_free(src_final); |
380 src_final = src_tmp; | |
381 } | |
382 | |
383 | |
384 if (needs_encrypt) { | |
385 zip_encryption_implementation impl; | |
386 const char *password = NULL; | |
387 | |
388 if (de->password) { | |
389 password = de->password; | |
390 } else if (za->default_password) { | |
391 password = za->default_password; | |
392 } | |
393 | |
394 if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) { | |
395 zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); | |
396 zip_source_free(src_final); | |
397 return -1; | |
398 } | |
399 if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) { | |
400 /* error set by impl */ | |
401 zip_source_free(src_final); | |
402 return -1; | |
403 } | |
404 | |
405 zip_source_free(src_final); | |
406 src_final = src_tmp; | |
407 } | |
408 | |
335 | 409 |
336 if ((offdata = zip_source_tell_write(za->src)) < 0) { | 410 if ((offdata = zip_source_tell_write(za->src)) < 0) { |
337 return -1; | 411 _zip_error_set_from_source(&za->error, za->src); |
338 } | 412 return -1; |
339 | 413 } |
340 ret = copy_source(za, s2); | 414 |
415 ret = copy_source(za, src_final, data_length); | |
341 | 416 |
342 if (zip_source_stat(s2, &st) < 0) | 417 if (zip_source_stat(src_final, &st) < 0) { |
418 _zip_error_set_from_source(&za->error, src_final); | |
343 ret = -1; | 419 ret = -1; |
344 | 420 } |
345 zip_source_free(s2); | 421 |
346 | 422 if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) { |
347 if (ret < 0) | 423 _zip_error_set_from_source(&za->error, src_final); |
348 return -1; | 424 ret = -1; |
425 } | |
426 | |
427 zip_source_free(src_final); | |
428 | |
429 if (ret < 0) { | |
430 return -1; | |
431 } | |
349 | 432 |
350 if ((offend = zip_source_tell_write(za->src)) < 0) { | 433 if ((offend = zip_source_tell_write(za->src)) < 0) { |
434 _zip_error_set_from_source(&za->error, za->src); | |
351 return -1; | 435 return -1; |
352 } | 436 } |
353 | 437 |
354 if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { | 438 if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { |
355 _zip_error_set_from_source(&za->error, za->src); | 439 _zip_error_set_from_source(&za->error, za->src); |
369 } | 453 } |
370 de->comp_method = st.comp_method; | 454 de->comp_method = st.comp_method; |
371 de->crc = st.crc; | 455 de->crc = st.crc; |
372 de->uncomp_size = st.size; | 456 de->uncomp_size = st.size; |
373 de->comp_size = (zip_uint64_t)(offend - offdata); | 457 de->comp_size = (zip_uint64_t)(offend - offdata); |
374 | 458 de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1)); |
459 _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0); | |
460 | |
375 if ((ret=_zip_dirent_write(za, de, flags)) < 0) | 461 if ((ret=_zip_dirent_write(za, de, flags)) < 0) |
376 return -1; | 462 return -1; |
377 | 463 |
378 if (is_zip64 != ret) { | 464 if (is_zip64 != ret) { |
379 /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ | 465 /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ |
380 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); | 466 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); |
381 return -1; | 467 return -1; |
382 } | 468 } |
383 | |
384 | 469 |
385 if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { | 470 if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { |
386 _zip_error_set_from_source(&za->error, za->src); | 471 _zip_error_set_from_source(&za->error, za->src); |
387 return -1; | 472 return -1; |
388 } | 473 } |
394 static int | 479 static int |
395 copy_data(zip_t *za, zip_uint64_t len) | 480 copy_data(zip_t *za, zip_uint64_t len) |
396 { | 481 { |
397 zip_uint8_t buf[BUFSIZE]; | 482 zip_uint8_t buf[BUFSIZE]; |
398 size_t n; | 483 size_t n; |
484 double total = (double)len; | |
399 | 485 |
400 while (len > 0) { | 486 while (len > 0) { |
401 n = len > sizeof(buf) ? sizeof(buf) : len; | 487 n = len > sizeof(buf) ? sizeof(buf) : len; |
402 if (_zip_read(za->src, buf, n, &za->error) < 0) { | 488 if (_zip_read(za->src, buf, n, &za->error) < 0) { |
403 return -1; | 489 return -1; |
406 if (_zip_write(za, buf, n) < 0) { | 492 if (_zip_write(za, buf, n) < 0) { |
407 return -1; | 493 return -1; |
408 } | 494 } |
409 | 495 |
410 len -= n; | 496 len -= n; |
497 | |
498 _zip_progress_update(za->progress, (total - (double)len) / total); | |
411 } | 499 } |
412 | 500 |
413 return 0; | 501 return 0; |
414 } | 502 } |
415 | 503 |
416 | 504 |
417 static int | 505 static int |
418 copy_source(zip_t *za, zip_source_t *src) | 506 copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) |
419 { | 507 { |
420 zip_uint8_t buf[BUFSIZE]; | 508 zip_uint8_t buf[BUFSIZE]; |
421 zip_int64_t n; | 509 zip_int64_t n, current; |
422 int ret; | 510 int ret; |
423 | 511 |
424 if (zip_source_open(src) < 0) { | 512 if (zip_source_open(src) < 0) { |
425 _zip_error_set_from_source(&za->error, src); | 513 _zip_error_set_from_source(&za->error, src); |
426 return -1; | 514 return -1; |
427 } | 515 } |
428 | 516 |
429 ret = 0; | 517 ret = 0; |
518 current = 0; | |
430 while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { | 519 while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { |
431 if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { | 520 if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { |
432 ret = -1; | 521 ret = -1; |
433 break; | 522 break; |
434 } | 523 } |
524 if (n == sizeof(buf) && za->progress && data_length > 0) { | |
525 current += n; | |
526 _zip_progress_update(za->progress, (double)current/(double)data_length); | |
527 } | |
435 } | 528 } |
436 | 529 |
437 if (n < 0) { | 530 if (n < 0) { |
438 _zip_error_set_from_source(&za->error, src); | 531 _zip_error_set_from_source(&za->error, src); |
439 ret = -1; | 532 ret = -1; |
441 | 534 |
442 zip_source_close(src); | 535 zip_source_close(src); |
443 | 536 |
444 return ret; | 537 return ret; |
445 } | 538 } |
446 | |
447 | 539 |
448 static int | 540 static int |
449 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) | 541 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) |
450 { | 542 { |
451 zip_int64_t cd_start, end, size; | 543 zip_int64_t cd_start, end, size; |