2 zip_close.c -- close zip archive and update changes
3 Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
5 This file is part of libzip, a library to manipulate ZIP archives.
6 The authors can be contacted at <libzip@nih.at>
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
17 3. The names of the authors may not be used to endorse or promote
18 products derived from this software without specific prior
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 #include <sys/types.h>
54 static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
55 static int copy_data(zip_t *, zip_uint64_t);
56 static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
57 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
62 zip_uint64_t i, j, survivors;
65 zip_filelist_t *filelist;
71 changed = _zip_changed(za, &survivors);
73 /* don't create zip files with no entries */
75 if ((za->open_flags & ZIP_TRUNCATE) || changed) {
76 if (zip_source_remove(za->src) < 0) {
77 _zip_error_set_from_source(&za->error, za->src);
90 if (survivors > za->nentry) {
91 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
95 if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
98 /* create list of files with index into original archive */
99 for (i=j=0; i<za->nentry; i++) {
100 if (za->entry[i].deleted)
103 if (j >= survivors) {
105 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
114 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
118 if (zip_source_begin_write(za->src) < 0) {
119 _zip_error_set_from_source(&za->error, za->src);
124 _zip_progress_start(za->progress);
126 for (j=0; j<survivors; j++) {
131 _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)survivors);
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 /* create new local directory entry */
139 if (entry->changes == NULL) {
140 if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
141 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
148 if (_zip_read_local_ef(za, i) < 0) {
153 if ((off = zip_source_tell_write(za->src)) < 0) {
157 de->offset = (zip_uint64_t)off;
163 if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
164 if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
170 /* add_data writes dirent */
171 if (add_data(za, zs ? zs : entry->source, de) < 0) {
183 /* when copying data, all sizes are known -> no data descriptor needed */
184 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
185 if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
189 if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
193 if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
194 _zip_error_set_from_source(&za->error, za->src);
198 if (copy_data(za, de->comp_size) < 0) {
206 if (write_cdir(za, filelist, survivors) < 0)
213 if (zip_source_commit_write(za->src) != 0) {
214 _zip_error_set_from_source(&za->error, za->src);
219 _zip_progress_end(za->progress);
222 zip_source_rollback_write(za->src);
233 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
235 zip_int64_t offstart, offdata, offend, data_length;
237 zip_source_t *src_final, *src_tmp;
241 zip_int8_t compression_flags;
242 bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
244 if (zip_source_stat(src, &st) < 0) {
245 _zip_error_set_from_source(&za->error, src);
249 if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
250 st.valid |= ZIP_STAT_COMP_METHOD;
251 st.comp_method = ZIP_CM_STORE;
254 if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
255 de->comp_method = st.comp_method;
256 else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
257 st.valid |= ZIP_STAT_COMP_SIZE;
258 st.comp_size = st.size;
261 /* we'll recompress */
262 st.valid &= ~ZIP_STAT_COMP_SIZE;
265 if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
266 st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
267 st.encryption_method = ZIP_EM_NONE;
270 flags = ZIP_EF_LOCAL;
272 if ((st.valid & ZIP_STAT_SIZE) == 0) {
273 flags |= ZIP_FL_FORCE_ZIP64;
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;
281 if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
282 zip_uint64_t max_size;
284 switch (ZIP_CM_ACTUAL(de->comp_method)) {
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;
292 /* max deflate size increase: size + ceil(size/16k)*5+6 */
293 max_size = 4293656963u;
297 max_size = 0xffffffffu;
304 if (st.size > max_size) {
305 flags |= ZIP_FL_FORCE_ZIP64;
309 de->comp_size = st.comp_size;
312 if ((offstart = zip_source_tell_write(za->src)) < 0) {
313 _zip_error_set_from_source(&za->error, za->src);
317 /* as long as we don't support non-seekable output, clear data descriptor bit */
318 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
319 if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) {
323 needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
324 needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
325 needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
326 needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
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);
333 zip_source_keep(src_final);
336 zip_encryption_implementation impl;
338 if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
339 zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
340 zip_source_free(src_final);
343 if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
344 /* error set by impl */
345 zip_source_free(src_final);
349 zip_source_free(src_final);
353 if (needs_decompress) {
354 if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
355 zip_source_free(src_final);
359 zip_source_free(src_final);
364 if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
365 zip_source_free(src_final);
369 zip_source_free(src_final);
373 if (needs_compress) {
374 if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
375 zip_source_free(src_final);
379 zip_source_free(src_final);
385 zip_encryption_implementation impl;
386 const char *password = NULL;
389 password = de->password;
390 } else if (za->default_password) {
391 password = za->default_password;
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);
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);
405 zip_source_free(src_final);
410 if ((offdata = zip_source_tell_write(za->src)) < 0) {
411 _zip_error_set_from_source(&za->error, za->src);
415 ret = copy_source(za, src_final, data_length);
417 if (zip_source_stat(src_final, &st) < 0) {
418 _zip_error_set_from_source(&za->error, src_final);
422 if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
423 _zip_error_set_from_source(&za->error, src_final);
427 zip_source_free(src_final);
433 if ((offend = zip_source_tell_write(za->src)) < 0) {
434 _zip_error_set_from_source(&za->error, za->src);
438 if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
439 _zip_error_set_from_source(&za->error, za->src);
443 if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
444 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
448 if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
449 if (st.valid & ZIP_STAT_MTIME)
450 de->last_mod = st.mtime;
454 de->comp_method = st.comp_method;
456 de->uncomp_size = st.size;
457 de->comp_size = (zip_uint64_t)(offend - offdata);
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);
461 if ((ret=_zip_dirent_write(za, de, flags)) < 0)
464 if (is_zip64 != ret) {
465 /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
466 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
470 if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
471 _zip_error_set_from_source(&za->error, za->src);
480 copy_data(zip_t *za, zip_uint64_t len)
482 zip_uint8_t buf[BUFSIZE];
484 double total = (double)len;
487 n = len > sizeof(buf) ? sizeof(buf) : len;
488 if (_zip_read(za->src, buf, n, &za->error) < 0) {
492 if (_zip_write(za, buf, n) < 0) {
498 _zip_progress_update(za->progress, (total - (double)len) / total);
506 copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length)
508 zip_uint8_t buf[BUFSIZE];
509 zip_int64_t n, current;
512 if (zip_source_open(src) < 0) {
513 _zip_error_set_from_source(&za->error, src);
519 while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
520 if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
524 if (n == sizeof(buf) && za->progress && data_length > 0) {
526 _zip_progress_update(za->progress, (double)current/(double)data_length);
531 _zip_error_set_from_source(&za->error, src);
535 zip_source_close(src);
541 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
543 zip_int64_t cd_start, end, size;
545 if ((cd_start = zip_source_tell_write(za->src)) < 0) {
549 if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
553 if ((end = zip_source_tell_write(za->src)) < 0) {
562 _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
565 zip_uint64_t i, survivors;
570 if (za->comment_changed || za->ch_flags != za->flags)
573 for (i=0; i<za->nentry; i++) {
574 if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0))
576 if (!za->entry[i].deleted)
581 *survivorsp = survivors;