This source file includes following definitions.
- zip_close
- add_data
- copy_data
- copy_source
- write_cdir
- _zip_changed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
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
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
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
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
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
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
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
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
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
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
300 return -1;
301 }
302 }
303 else {
304
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
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
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
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
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
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 }