1 /*
2 zip_close.c -- close zip archive and update changes
3 Copyright (C) 1999-2015 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 /* 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 *);
58 static int copy_data(zip_t *, zip_uint64_t);
59 static int copy_source(zip_t *, zip_source_t *);
60 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
61
62
63 ZIP_EXTERN int
zip_close(zip_t * za)64 zip_close(zip_t *za)
65 {
66 zip_uint64_t i, j, survivors;
67 zip_int64_t off;
68 int error;
69 zip_filelist_t *filelist;
70 int changed;
71
72 if (za == NULL)
73 return -1;
74
75 changed = _zip_changed(za, &survivors);
76
77 /* don't create zip files with no entries */
78 if (survivors == 0) {
79 if ((za->open_flags & ZIP_TRUNCATE) || changed) {
80 if (zip_source_remove(za->src) < 0) {
81 _zip_error_set_from_source(&za->error, za->src);
82 return -1;
83 }
84 }
85 zip_discard(za);
86 return 0;
87 }
88
89 if (!changed) {
90 zip_discard(za);
91 return 0;
92 }
93
94 if (survivors > za->nentry) {
95 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
96 return -1;
97 }
98
99 if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
100 return -1;
101
102 /* create list of files with index into original archive */
103 for (i=j=0; i<za->nentry; i++) {
104 if (za->entry[i].deleted)
105 continue;
106
107 if (j >= survivors) {
108 free(filelist);
109 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
110 return -1;
111 }
112
113 filelist[j].idx = i;
114 j++;
115 }
116 if (j < survivors) {
117 free(filelist);
118 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
119 return -1;
120 }
121
122 if (zip_source_begin_write(za->src) < 0) {
123 _zip_error_set_from_source(&za->error, za->src);
124 free(filelist);
125 return -1;
126 }
127
128 error = 0;
129 for (j=0; j<survivors; j++) {
130 int new_data;
131 zip_entry_t *entry;
132 zip_dirent_t *de;
133
134 i = filelist[j].idx;
135 entry = za->entry+i;
136
137 new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
138
139 /* create new local directory entry */
140 if (entry->changes == NULL) {
141 if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
142 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
143 error = 1;
144 break;
145 }
146 }
147 de = entry->changes;
148
149 if (_zip_read_local_ef(za, i) < 0) {
150 error = 1;
151 break;
152 }
153
154 if ((off = zip_source_tell_write(za->src)) < 0) {
155 error = 1;
156 break;
157 }
158 de->offset = (zip_uint64_t)off;
159
160 if (new_data) {
161 zip_source_t *zs;
162
163 zs = NULL;
164 if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
165 if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
166 error = 1;
167 break;
168 }
169 }
170
171 /* add_data writes dirent */
172 if (add_data(za, zs ? zs : entry->source, de) < 0) {
173 error = 1;
174 if (zs)
175 zip_source_free(zs);
176 break;
177 }
178 if (zs)
179 zip_source_free(zs);
180 }
181 else {
182 zip_uint64_t offset;
183
184 /* when copying data, all sizes are known -> no data descriptor needed */
185 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
186 if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
187 error = 1;
188 break;
189 }
190 if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
191 error = 1;
192 break;
193 }
194 if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
195 _zip_error_set_from_source(&za->error, za->src);
196 error = 1;
197 break;
198 }
199 if (copy_data(za, de->comp_size) < 0) {
200 error = 1;
201 break;
202 }
203 }
204 }
205
206 if (!error) {
207 if (write_cdir(za, filelist, survivors) < 0)
208 error = 1;
209 }
210
211 free(filelist);
212
213 if (!error) {
214 if (zip_source_commit_write(za->src) != 0) {
215 _zip_error_set_from_source(&za->error, za->src);
216 error = 1;
217 }
218 }
219
220 if (error) {
221 zip_source_rollback_write(za->src);
222 return -1;
223 }
224
225 zip_discard(za);
226
227 return 0;
228 }
229
230
231 static int
add_data(zip_t * za,zip_source_t * src,zip_dirent_t * de)232 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
233 {
234 zip_int64_t offstart, offdata, offend;
235 struct zip_stat st;
236 zip_source_t *s2;
237 int ret;
238 int is_zip64;
239 zip_flags_t flags;
240
241 if (zip_source_stat(src, &st) < 0) {
242 _zip_error_set_from_source(&za->error, src);
243 return -1;
244 }
245
246 if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
247 st.valid |= ZIP_STAT_COMP_METHOD;
248 st.comp_method = ZIP_CM_STORE;
249 }
250
251 if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
252 de->comp_method = st.comp_method;
253 else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
254 st.valid |= ZIP_STAT_COMP_SIZE;
255 st.comp_size = st.size;
256 }
257 else {
258 /* we'll recompress */
259 st.valid &= ~ZIP_STAT_COMP_SIZE;
260 }
261
262
263 flags = ZIP_EF_LOCAL;
264
265 if ((st.valid & ZIP_STAT_SIZE) == 0)
266 flags |= ZIP_FL_FORCE_ZIP64;
267 else {
268 de->uncomp_size = st.size;
269
270 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)
272 || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
273 flags |= ZIP_FL_FORCE_ZIP64;
274 }
275 else
276 de->comp_size = st.comp_size;
277 }
278
279 if ((offstart = zip_source_tell_write(za->src)) < 0) {
280 return -1;
281 }
282
283 /* as long as we don't support non-seekable output, clear data descriptor bit */
284 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
285 if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
286 return -1;
287
288
289 if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
290 zip_source_t *s_store, *s_crc;
291 zip_compression_implementation comp_impl;
292
293 if (st.comp_method != ZIP_CM_STORE) {
294 if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
295 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
296 return -1;
297 }
298 if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
299 /* error set by comp_impl */
300 return -1;
301 }
302 }
303 else {
304 /* to have the same reference count to src as in the case where it's not stored */
305 zip_source_keep(src);
306 s_store = src;
307 }
308
309 s_crc = zip_source_crc(za, s_store, 0);
310 zip_source_free(s_store);
311 if (s_crc == NULL) {
312 return -1;
313 }
314
315 if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
316 if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
317 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
318 zip_source_free(s_crc);
319 return -1;
320 }
321 s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE);
322 zip_source_free(s_crc);
323 if (s2 == NULL) {
324 return -1;
325 }
326 }
327 else {
328 s2 = s_crc;
329 }
330 }
331 else {
332 zip_source_keep(src);
333 s2 = src;
334 }
335
336 if ((offdata = zip_source_tell_write(za->src)) < 0) {
337 return -1;
338 }
339
340 ret = copy_source(za, s2);
341
342 if (zip_source_stat(s2, &st) < 0)
343 ret = -1;
344
345 zip_source_free(s2);
346
347 if (ret < 0)
348 return -1;
349
350 if ((offend = zip_source_tell_write(za->src)) < 0) {
351 return -1;
352 }
353
354 if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
355 _zip_error_set_from_source(&za->error, za->src);
356 return -1;
357 }
358
359 if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
360 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
361 return -1;
362 }
363
364 if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
365 if (st.valid & ZIP_STAT_MTIME)
366 de->last_mod = st.mtime;
367 else
368 time(&de->last_mod);
369 }
370 de->comp_method = st.comp_method;
371 de->crc = st.crc;
372 de->uncomp_size = st.size;
373 de->comp_size = (zip_uint64_t)(offend - offdata);
374
375 if ((ret=_zip_dirent_write(za, de, flags)) < 0)
376 return -1;
377
378 if (is_zip64 != ret) {
379 /* 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);
381 return -1;
382 }
383
384
385 if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
386 _zip_error_set_from_source(&za->error, za->src);
387 return -1;
388 }
389
390 return 0;
391 }
392
393
394 static int
copy_data(zip_t * za,zip_uint64_t len)395 copy_data(zip_t *za, zip_uint64_t len)
396 {
397 zip_uint8_t buf[BUFSIZE];
398 size_t n;
399
400 while (len > 0) {
401 n = len > sizeof(buf) ? sizeof(buf) : len;
402 if (_zip_read(za->src, buf, n, &za->error) < 0) {
403 return -1;
404 }
405
406 if (_zip_write(za, buf, n) < 0) {
407 return -1;
408 }
409
410 len -= n;
411 }
412
413 return 0;
414 }
415
416
417 static int
copy_source(zip_t * za,zip_source_t * src)418 copy_source(zip_t *za, zip_source_t *src)
419 {
420 zip_uint8_t buf[BUFSIZE];
421 zip_int64_t n;
422 int ret;
423
424 if (zip_source_open(src) < 0) {
425 _zip_error_set_from_source(&za->error, src);
426 return -1;
427 }
428
429 ret = 0;
430 while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
431 if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
432 ret = -1;
433 break;
434 }
435 }
436
437 if (n < 0) {
438 _zip_error_set_from_source(&za->error, src);
439 ret = -1;
440 }
441
442 zip_source_close(src);
443
444 return ret;
445 }
446
447
448 static int
write_cdir(zip_t * za,const zip_filelist_t * filelist,zip_uint64_t survivors)449 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
450 {
451 zip_int64_t cd_start, end, size;
452
453 if ((cd_start = zip_source_tell_write(za->src)) < 0) {
454 return -1;
455 }
456
457 if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
458 return -1;
459 }
460
461 if ((end = zip_source_tell_write(za->src)) < 0) {
462 return -1;
463 }
464
465 return 0;
466 }
467
468
469 int
_zip_changed(const zip_t * za,zip_uint64_t * survivorsp)470 _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
471 {
472 int changed;
473 zip_uint64_t i, survivors;
474
475 changed = 0;
476 survivors = 0;
477
478 if (za->comment_changed || za->ch_flags != za->flags)
479 changed = 1;
480
481 for (i=0; i<za->nentry; i++) {
482 if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0))
483 changed = 1;
484 if (!za->entry[i].deleted)
485 survivors++;
486 }
487
488 if (survivorsp)
489 *survivorsp = survivors;
490
491 return changed;
492 }
493