Imported Upstream version 1.3.2
[platform/upstream/libzip.git] / lib / zip_close.c
1 /*
2   zip_close.c -- close zip archive and update changes
3   Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
4
5   This file is part of libzip, a library to manipulate ZIP archives.
6   The authors can be contacted at <libzip@nih.at>
7
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions
10   are met:
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
16      distribution.
17   3. The names of the authors may not be used to endorse or promote
18      products derived from this software without specific prior
19      written permission.
20  
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.
32 */
33
34
35 #include "zipint.h"
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #ifdef HAVE_STRINGS_H
41 #include <strings.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #ifdef _WIN32
49 #include <io.h>
50 #include <fcntl.h>
51 #endif
52
53
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);
58
59 ZIP_EXTERN int
60 zip_close(zip_t *za)
61 {
62     zip_uint64_t i, j, survivors;
63     zip_int64_t off;
64     int error;
65     zip_filelist_t *filelist;
66     int changed;
67
68     if (za == NULL)
69         return -1;
70
71     changed = _zip_changed(za, &survivors);
72
73     /* don't create zip files with no entries */
74     if (survivors == 0) {
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);
78                 return -1;
79             }
80         }
81         zip_discard(za);
82         return 0;
83     }          
84
85     if (!changed) {
86         zip_discard(za);
87         return 0;
88     }
89
90     if (survivors > za->nentry) {
91         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
92         return -1;
93     }
94     
95     if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
96         return -1;
97
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)
101             continue;
102
103         if (j >= survivors) {
104             free(filelist);
105             zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
106             return -1;
107         }
108         
109         filelist[j].idx = i;
110         j++;
111     }
112     if (j < survivors) {
113         free(filelist);
114         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
115         return -1;
116     }
117
118     if (zip_source_begin_write(za->src) < 0) {
119         _zip_error_set_from_source(&za->error, za->src);
120         free(filelist);
121         return -1;
122     }
123
124     _zip_progress_start(za->progress);
125     error = 0;
126     for (j=0; j<survivors; j++) {
127         int new_data;
128         zip_entry_t *entry;
129         zip_dirent_t *de;
130
131         _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)survivors);
132
133         i = filelist[j].idx;
134         entry = za->entry+i;
135
136         new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
137
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);
142                 error = 1;
143                 break;
144             }
145         }
146         de = entry->changes;
147
148         if (_zip_read_local_ef(za, i) < 0) {
149             error = 1;
150             break;
151         }
152
153         if ((off = zip_source_tell_write(za->src)) < 0) {
154             error = 1;
155             break;
156         }
157         de->offset = (zip_uint64_t)off;
158
159         if (new_data) {
160             zip_source_t *zs;
161
162             zs = NULL;
163             if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
164                 if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
165                     error = 1;
166                     break;
167                 }
168             }
169
170             /* add_data writes dirent */
171             if (add_data(za, zs ? zs : entry->source, de) < 0) {
172                 error = 1;
173                 if (zs)
174                     zip_source_free(zs);
175                 break;
176             }
177             if (zs)
178                 zip_source_free(zs);
179         }
180         else {
181             zip_uint64_t offset;
182
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) {
186                 error = 1;
187                 break;
188             }
189             if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
190                 error = 1;
191                 break;
192             }
193             if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
194                 _zip_error_set_from_source(&za->error, za->src);
195                 error = 1;
196                 break;
197             }
198             if (copy_data(za, de->comp_size) < 0) {
199                 error = 1;
200                 break;
201             }
202         }
203     }
204
205     if (!error) {
206         if (write_cdir(za, filelist, survivors) < 0)
207             error = 1;
208     }
209
210     free(filelist);
211
212     if (!error) {
213         if (zip_source_commit_write(za->src) != 0) {
214             _zip_error_set_from_source(&za->error, za->src);
215             error = 1;
216         }
217     }
218
219     _zip_progress_end(za->progress);
220
221     if (error) {
222         zip_source_rollback_write(za->src);
223         return -1;
224     }
225
226     zip_discard(za);
227
228     return 0;
229 }
230
231
232 static int
233 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
234 {
235     zip_int64_t offstart, offdata, offend, data_length;
236     struct zip_stat st;
237     zip_source_t *src_final, *src_tmp;
238     int ret;
239     int is_zip64;
240     zip_flags_t flags;
241     zip_int8_t compression_flags;
242     bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
243
244     if (zip_source_stat(src, &st) < 0) {
245         _zip_error_set_from_source(&za->error, src);
246         return -1;
247     }
248
249     if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
250         st.valid |= ZIP_STAT_COMP_METHOD;
251         st.comp_method = ZIP_CM_STORE;
252     }
253
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;
259     }
260     else {
261         /* we'll recompress */
262         st.valid &= ~ZIP_STAT_COMP_SIZE;
263     }
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     }
269
270     flags = ZIP_EF_LOCAL;
271
272     if ((st.valid & ZIP_STAT_SIZE) == 0) {
273         flags |= ZIP_FL_FORCE_ZIP64;
274         data_length = -1;
275     }
276     else {
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;
280         
281         if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
282             zip_uint64_t max_size;
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) {
305                 flags |= ZIP_FL_FORCE_ZIP64;
306             }
307         }
308         else
309             de->comp_size = st.comp_size;
310     }
311
312     if ((offstart = zip_source_tell_write(za->src)) < 0) {
313         _zip_error_set_from_source(&za->error, za->src);
314         return -1;
315     }
316
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) {
320         return -1;
321     }
322
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);
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;
337         
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);
341             return -1;
342         }
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);
346             return -1;
347         }
348
349         zip_source_free(src_final);
350         src_final = src_tmp;
351     }
352     
353     if (needs_decompress) {
354         if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
355             zip_source_free(src_final);
356             return -1;
357         }
358
359         zip_source_free(src_final);
360         src_final = src_tmp;
361     }
362
363     if (needs_crc) {
364         if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
365             zip_source_free(src_final);
366             return -1;
367         }
368
369         zip_source_free(src_final);
370         src_final = src_tmp;
371     }
372
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);
376             return -1;
377         }
378         
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
409
410     if ((offdata = zip_source_tell_write(za->src)) < 0) {
411         _zip_error_set_from_source(&za->error, za->src);
412         return -1;
413     }
414
415     ret = copy_source(za, src_final, data_length);
416         
417     if (zip_source_stat(src_final, &st) < 0) {
418         _zip_error_set_from_source(&za->error, src_final);
419         ret = -1;
420     }
421
422     if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
423         _zip_error_set_from_source(&za->error, src_final);
424         ret = -1;
425     }
426
427     zip_source_free(src_final);
428
429     if (ret < 0) {
430         return -1;
431     }
432
433     if ((offend = zip_source_tell_write(za->src)) < 0) {
434         _zip_error_set_from_source(&za->error, za->src);
435         return -1;
436     }
437
438     if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
439         _zip_error_set_from_source(&za->error, za->src);
440         return -1;
441     }
442
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);
445         return -1;
446     }
447
448     if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
449         if (st.valid & ZIP_STAT_MTIME)
450             de->last_mod = st.mtime;
451         else
452             time(&de->last_mod);
453     }
454     de->comp_method = st.comp_method;
455     de->crc = st.crc;
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);
460     
461     if ((ret=_zip_dirent_write(za, de, flags)) < 0)
462         return -1;
463  
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);
467         return -1;
468     }
469    
470     if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
471         _zip_error_set_from_source(&za->error, za->src);
472         return -1;
473     }
474
475     return 0;
476 }
477
478
479 static int
480 copy_data(zip_t *za, zip_uint64_t len)
481 {
482     zip_uint8_t buf[BUFSIZE];
483     size_t n;
484     double total = (double)len;
485
486     while (len > 0) {
487         n = len > sizeof(buf) ? sizeof(buf) : len;
488         if (_zip_read(za->src, buf, n, &za->error) < 0) {
489             return -1;
490         }
491
492         if (_zip_write(za, buf, n) < 0) {
493             return -1;
494         }
495         
496         len -= n;
497
498         _zip_progress_update(za->progress, (total - (double)len) / total);
499     }
500
501     return 0;
502 }
503
504
505 static int
506 copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length)
507 {
508     zip_uint8_t buf[BUFSIZE];
509     zip_int64_t n, current;
510     int ret;
511
512     if (zip_source_open(src) < 0) {
513         _zip_error_set_from_source(&za->error, src);
514         return -1;
515     }
516
517     ret = 0;
518     current = 0;
519     while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
520         if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
521             ret = -1;
522             break;
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         }
528     }
529     
530     if (n < 0) {
531         _zip_error_set_from_source(&za->error, src);
532         ret = -1;
533     }
534
535     zip_source_close(src);
536     
537     return ret;
538 }
539
540 static int
541 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
542 {
543     zip_int64_t cd_start, end, size;
544     
545     if ((cd_start = zip_source_tell_write(za->src)) < 0) {
546         return -1;
547     }
548
549     if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
550         return -1;
551     }
552     
553     if ((end = zip_source_tell_write(za->src)) < 0) {
554         return -1;
555     }
556
557     return 0;
558 }
559
560
561 int
562 _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
563 {
564     int changed;
565     zip_uint64_t i, survivors;
566
567     changed = 0;
568     survivors = 0;
569
570     if (za->comment_changed || za->ch_flags != za->flags)
571         changed = 1;
572
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))
575             changed = 1;
576         if (!za->entry[i].deleted)
577             survivors++;
578     }
579
580     if (survivorsp)
581         *survivorsp = survivors;
582
583     return changed;
584 }