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;