annotate libzip/lib/zip_close.c @ 4:2306f4b04790

libzip: import 1.1.2
author David Demelier <markand@malikania.fr>
date Wed, 24 Feb 2016 21:19:28 +0100
parents
children 056ee6b5913e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 zip_close.c -- close zip archive and update changes
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
4
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 This file is part of libzip, a library to manipulate ZIP archives.
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 The authors can be contacted at <libzip@nih.at>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
7
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 Redistribution and use in source and binary forms, with or without
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 modification, are permitted provided that the following conditions
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 are met:
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 1. Redistributions of source code must retain the above copyright
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 notice, this list of conditions and the following disclaimer.
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 2. Redistributions in binary form must reproduce the above copyright
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 notice, this list of conditions and the following disclaimer in
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 the documentation and/or other materials provided with the
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 distribution.
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 3. The names of the authors may not be used to endorse or promote
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
18 products derived from this software without specific prior
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 written permission.
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
20
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
33
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
34
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 #include "zipint.h"
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
36
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 #include <stdio.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 #include <stdlib.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 #include <string.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 #ifdef HAVE_STRINGS_H
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 #include <strings.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 #endif
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 #ifdef HAVE_UNISTD_H
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 #include <unistd.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 #endif
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 #include <sys/types.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 #include <sys/stat.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 #ifdef _WIN32
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 #include <io.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 #include <fcntl.h>
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 #endif
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
52
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
53
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 /* max deflate size increase: size + ceil(size/16k)*5+6 */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 #define MAX_DEFLATE_SIZE_32 4293656963u
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
56
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 static int copy_data(zip_t *, zip_uint64_t);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 static int copy_source(zip_t *, zip_source_t *);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
61
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
62
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 ZIP_EXTERN int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 zip_close(zip_t *za)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 zip_uint64_t i, j, survivors;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 zip_int64_t off;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 int error;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 zip_filelist_t *filelist;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 int changed;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
71
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 if (za == NULL)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
74
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 changed = _zip_changed(za, &survivors);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
76
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 /* don't create zip files with no entries */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 if (survivors == 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 if ((za->open_flags & ZIP_TRUNCATE) || changed) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 if (zip_source_remove(za->src) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 zip_discard(za);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
88
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 if (!changed) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 zip_discard(za);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
93
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 if (survivors > za->nentry) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
98
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
99 if ((filelist=(zip_filelist_t *)malloc(sizeof(filelist[0])*(size_t)survivors)) == NULL)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
101
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 /* create list of files with index into original archive */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 for (i=j=0; i<za->nentry; i++) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 if (za->entry[i].deleted)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 continue;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
106
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 if (j >= survivors) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 free(filelist);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
112
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 filelist[j].idx = i;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 j++;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 if (j < survivors) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 free(filelist);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
118 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
121
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 if (zip_source_begin_write(za->src) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 free(filelist);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
127
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 error = 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 for (j=0; j<survivors; j++) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 int new_data;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 zip_entry_t *entry;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 zip_dirent_t *de;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
133
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 i = filelist[j].idx;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 entry = za->entry+i;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
136
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD));
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
138
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 /* create new local directory entry */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 if (entry->changes == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 if ((entry->changes=_zip_dirent_clone(entry->orig)) == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 de = entry->changes;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
148
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 if (_zip_read_local_ef(za, i) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
153
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 if ((off = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 de->offset = (zip_uint64_t)off;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
159
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 if (new_data) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 zip_source_t *zs;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
162
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 zs = NULL;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
165 if ((zs=_zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
169 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
170
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 /* add_data writes dirent */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 if (add_data(za, zs ? zs : entry->source, de) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 if (zs)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 zip_source_free(zs);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 if (zs)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
179 zip_source_free(zs);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 zip_uint64_t offset;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
183
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 /* when copying data, all sizes are known -> no data descriptor needed */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
185 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
186 if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
187 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
189 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 if ((offset=_zip_file_get_offset(za, i, &za->error)) == 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
192 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
195 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
197 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
198 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 if (copy_data(za, de->comp_size) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
200 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
201 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
202 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
203 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
205
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 if (!error) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
207 if (write_cdir(za, filelist, survivors) < 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
210
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 free(filelist);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
212
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 if (!error) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 if (zip_source_commit_write(za->src) != 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 error = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
218 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
219
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
220 if (error) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 zip_source_rollback_write(za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
224
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 zip_discard(za);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
226
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
229
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
230
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
231 static int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 zip_int64_t offstart, offdata, offend;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 struct zip_stat st;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 zip_source_t *s2;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 int ret;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 int is_zip64;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 zip_flags_t flags;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
240
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 if (zip_source_stat(src, &st) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 _zip_error_set_from_source(&za->error, src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
244 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
245
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
247 st.valid |= ZIP_STAT_COMP_METHOD;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 st.comp_method = ZIP_CM_STORE;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
249 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
250
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 de->comp_method = st.comp_method;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 st.valid |= ZIP_STAT_COMP_SIZE;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 st.comp_size = st.size;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 /* we'll recompress */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 st.valid &= ~ZIP_STAT_COMP_SIZE;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
261
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
262
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 flags = ZIP_EF_LOCAL;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
264
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 if ((st.valid & ZIP_STAT_SIZE) == 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 flags |= ZIP_FL_FORCE_ZIP64;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
267 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 de->uncomp_size = st.size;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
269
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method))))
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
273 flags |= ZIP_FL_FORCE_ZIP64;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 else
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 de->comp_size = st.comp_size;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
278
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
279 if ((offstart = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
280 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
282
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
283 /* as long as we don't support non-seekable output, clear data descriptor bit */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
284 de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
286 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
287
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
288
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
289 if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 zip_source_t *s_store, *s_crc;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
291 zip_compression_implementation comp_impl;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
292
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
293 if (st.comp_method != ZIP_CM_STORE) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
294 if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
296 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
298 if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
299 /* error set by comp_impl */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
300 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
302 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
303 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
304 /* to have the same reference count to src as in the case where it's not stored */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 zip_source_keep(src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
306 s_store = src;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
307 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
308
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 s_crc = zip_source_crc(za, s_store, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
310 zip_source_free(s_store);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 if (s_crc == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
312 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
313 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
314
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
315 if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
318 zip_source_free(s_crc);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
319 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
321 s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
322 zip_source_free(s_crc);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 if (s2 == NULL) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
324 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
325 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
326 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
327 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
328 s2 = s_crc;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
330 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 else {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 zip_source_keep(src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
333 s2 = src;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
335
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 if ((offdata = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
337 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
338 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
339
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
340 ret = copy_source(za, s2);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
341
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 if (zip_source_stat(s2, &st) < 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
343 ret = -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
344
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
345 zip_source_free(s2);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
346
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 if (ret < 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
348 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
349
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 if ((offend = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
351 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
352 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
353
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
355 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
356 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
357 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
358
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
359 if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
361 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
362 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
363
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
364 if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 if (st.valid & ZIP_STAT_MTIME)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
366 de->last_mod = st.mtime;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
367 else
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 time(&de->last_mod);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
369 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
370 de->comp_method = st.comp_method;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 de->crc = st.crc;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 de->uncomp_size = st.size;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
373 de->comp_size = (zip_uint64_t)(offend - offdata);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
374
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
375 if ((ret=_zip_dirent_write(za, de, flags)) < 0)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
377
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
378 if (is_zip64 != ret) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
381 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
382 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
383
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
384
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
385 if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
386 _zip_error_set_from_source(&za->error, za->src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
387 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
388 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
389
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
390 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
391 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
392
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
393
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
394 static int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
395 copy_data(zip_t *za, zip_uint64_t len)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
396 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
397 zip_uint8_t buf[BUFSIZE];
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
398 size_t n;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
399
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
400 while (len > 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
401 n = len > sizeof(buf) ? sizeof(buf) : len;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
402 if (_zip_read(za->src, buf, n, &za->error) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
403 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
404 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
405
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
406 if (_zip_write(za, buf, n) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
407 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
408 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
409
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
410 len -= n;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
411 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
412
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
413 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
414 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
415
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
416
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
417 static int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
418 copy_source(zip_t *za, zip_source_t *src)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
419 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
420 zip_uint8_t buf[BUFSIZE];
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
421 zip_int64_t n;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
422 int ret;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
423
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
424 if (zip_source_open(src) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
425 _zip_error_set_from_source(&za->error, src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
426 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
427 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
428
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
429 ret = 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
430 while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
431 if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
432 ret = -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
433 break;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
434 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
435 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
436
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
437 if (n < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
438 _zip_error_set_from_source(&za->error, src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
439 ret = -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
440 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
441
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
442 zip_source_close(src);
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
443
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
444 return ret;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
445 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
446
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
447
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
448 static int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
449 write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
450 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
451 zip_int64_t cd_start, end, size;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
452
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
453 if ((cd_start = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
454 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
455 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
456
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
457 if ((size=_zip_cdir_write(za, filelist, survivors)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
458 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
459 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
460
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
461 if ((end = zip_source_tell_write(za->src)) < 0) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
462 return -1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
463 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
464
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
465 return 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
466 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
467
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
468
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
469 int
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
470 _zip_changed(const zip_t *za, zip_uint64_t *survivorsp)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
471 {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
472 int changed;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
473 zip_uint64_t i, survivors;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
474
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
475 changed = 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
476 survivors = 0;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
477
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
478 if (za->comment_changed || za->ch_flags != za->flags)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
479 changed = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
480
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
481 for (i=0; i<za->nentry; i++) {
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
482 if (za->entry[i].deleted || za->entry[i].source || (za->entry[i].changes && za->entry[i].changes->changed != 0))
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
483 changed = 1;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
484 if (!za->entry[i].deleted)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
485 survivors++;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
486 }
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
487
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
488 if (survivorsp)
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
489 *survivorsp = survivors;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
490
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
491 return changed;
2306f4b04790 libzip: import 1.1.2
David Demelier <markand@malikania.fr>
parents:
diff changeset
492 }