Mercurial > embed
comparison libzip/lib/zip_extra_field_api.c @ 20:3b18afe43c9d
libzip: reimport version 1.1.3
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 29 Jun 2016 09:24:55 +0200 |
parents | 2306f4b04790 |
children |
comparison
equal
deleted
inserted
replaced
19:07f2cdc6e430 | 20:3b18afe43c9d |
---|---|
1 /* | |
2 zip_extra_field_api.c -- public extra fields API functions | |
3 Copyright (C) 2012-2014 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 | |
38 ZIP_EXTERN int | |
39 zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) | |
40 { | |
41 zip_dirent_t *de; | |
42 | |
43 if ((flags & ZIP_EF_BOTH) == 0) { | |
44 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
45 return -1; | |
46 } | |
47 | |
48 if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { | |
49 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
50 return -1; | |
51 } | |
52 | |
53 if (_zip_get_dirent(za, idx, 0, NULL) == NULL) | |
54 return -1; | |
55 | |
56 if (ZIP_IS_RDONLY(za)) { | |
57 zip_error_set(&za->error, ZIP_ER_RDONLY, 0); | |
58 return -1; | |
59 } | |
60 | |
61 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) | |
62 return -1; | |
63 | |
64 de = za->entry[idx].changes; | |
65 | |
66 de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags); | |
67 return 0; | |
68 } | |
69 | |
70 | |
71 ZIP_EXTERN int | |
72 zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) | |
73 { | |
74 zip_dirent_t *de; | |
75 | |
76 if ((flags & ZIP_EF_BOTH) == 0) { | |
77 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
78 return -1; | |
79 } | |
80 | |
81 if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { | |
82 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
83 return -1; | |
84 } | |
85 | |
86 if (_zip_get_dirent(za, idx, 0, NULL) == NULL) | |
87 return -1; | |
88 | |
89 if (ZIP_IS_RDONLY(za)) { | |
90 zip_error_set(&za->error, ZIP_ER_RDONLY, 0); | |
91 return -1; | |
92 } | |
93 | |
94 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) | |
95 return -1; | |
96 | |
97 de = za->entry[idx].changes; | |
98 | |
99 de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags); | |
100 return 0; | |
101 } | |
102 | |
103 | |
104 ZIP_EXTERN const zip_uint8_t * | |
105 zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) | |
106 { | |
107 static const zip_uint8_t empty[1] = { '\0' }; | |
108 | |
109 zip_dirent_t *de; | |
110 zip_extra_field_t *ef; | |
111 int i; | |
112 | |
113 if ((flags & ZIP_EF_BOTH) == 0) { | |
114 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
115 return NULL; | |
116 } | |
117 | |
118 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) | |
119 return NULL; | |
120 | |
121 if (flags & ZIP_FL_LOCAL) | |
122 if (_zip_read_local_ef(za, idx) < 0) | |
123 return NULL; | |
124 | |
125 i = 0; | |
126 for (ef=de->extra_fields; ef; ef=ef->next) { | |
127 if (ef->flags & flags & ZIP_EF_BOTH) { | |
128 if (i < ef_idx) { | |
129 i++; | |
130 continue; | |
131 } | |
132 | |
133 if (idp) | |
134 *idp = ef->id; | |
135 if (lenp) | |
136 *lenp = ef->size; | |
137 if (ef->size > 0) | |
138 return ef->data; | |
139 else | |
140 return empty; | |
141 } | |
142 } | |
143 | |
144 zip_error_set(&za->error, ZIP_ER_NOENT, 0); | |
145 return NULL; | |
146 | |
147 } | |
148 | |
149 | |
150 ZIP_EXTERN const zip_uint8_t * | |
151 zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) | |
152 { | |
153 zip_dirent_t *de; | |
154 | |
155 if ((flags & ZIP_EF_BOTH) == 0) { | |
156 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
157 return NULL; | |
158 } | |
159 | |
160 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) | |
161 return NULL; | |
162 | |
163 if (flags & ZIP_FL_LOCAL) | |
164 if (_zip_read_local_ef(za, idx) < 0) | |
165 return NULL; | |
166 | |
167 return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error); | |
168 } | |
169 | |
170 | |
171 ZIP_EXTERN zip_int16_t | |
172 zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) | |
173 { | |
174 zip_dirent_t *de; | |
175 zip_extra_field_t *ef; | |
176 zip_uint16_t n; | |
177 | |
178 if ((flags & ZIP_EF_BOTH) == 0) { | |
179 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
180 return -1; | |
181 } | |
182 | |
183 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) | |
184 return -1; | |
185 | |
186 if (flags & ZIP_FL_LOCAL) | |
187 if (_zip_read_local_ef(za, idx) < 0) | |
188 return -1; | |
189 | |
190 n = 0; | |
191 for (ef=de->extra_fields; ef; ef=ef->next) | |
192 if (ef->flags & flags & ZIP_EF_BOTH) | |
193 n++; | |
194 | |
195 return (zip_int16_t)n; | |
196 } | |
197 | |
198 | |
199 ZIP_EXTERN zip_int16_t | |
200 zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) | |
201 { | |
202 zip_dirent_t *de; | |
203 zip_extra_field_t *ef; | |
204 zip_uint16_t n; | |
205 | |
206 if ((flags & ZIP_EF_BOTH) == 0) { | |
207 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
208 return -1; | |
209 } | |
210 | |
211 if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL) | |
212 return -1; | |
213 | |
214 if (flags & ZIP_FL_LOCAL) | |
215 if (_zip_read_local_ef(za, idx) < 0) | |
216 return -1; | |
217 | |
218 n = 0; | |
219 for (ef=de->extra_fields; ef; ef=ef->next) | |
220 if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) | |
221 n++; | |
222 | |
223 return (zip_int16_t)n; | |
224 } | |
225 | |
226 | |
227 ZIP_EXTERN int | |
228 zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) | |
229 { | |
230 zip_dirent_t *de; | |
231 zip_uint16_t ls, cs; | |
232 zip_extra_field_t *ef, *ef_prev, *ef_new; | |
233 int i, found, new_len; | |
234 | |
235 if ((flags & ZIP_EF_BOTH) == 0) { | |
236 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
237 return -1; | |
238 } | |
239 | |
240 if (_zip_get_dirent(za, idx, 0, NULL) == NULL) | |
241 return -1; | |
242 | |
243 if (ZIP_IS_RDONLY(za)) { | |
244 zip_error_set(&za->error, ZIP_ER_RDONLY, 0); | |
245 return -1; | |
246 } | |
247 | |
248 if (ZIP_EF_IS_INTERNAL(ef_id)) { | |
249 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
250 return -1; | |
251 } | |
252 | |
253 if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) | |
254 return -1; | |
255 | |
256 de = za->entry[idx].changes; | |
257 | |
258 ef = de->extra_fields; | |
259 ef_prev = NULL; | |
260 i = 0; | |
261 found = 0; | |
262 | |
263 for (; ef; ef=ef->next) { | |
264 if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { | |
265 if (i == ef_idx) { | |
266 found = 1; | |
267 break; | |
268 } | |
269 i++; | |
270 } | |
271 ef_prev = ef; | |
272 } | |
273 | |
274 if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { | |
275 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
276 return -1; | |
277 } | |
278 | |
279 if (flags & ZIP_EF_LOCAL) | |
280 ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); | |
281 else | |
282 ls = 0; | |
283 if (flags & ZIP_EF_CENTRAL) | |
284 cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); | |
285 else | |
286 cs = 0; | |
287 | |
288 new_len = ls > cs ? ls : cs; | |
289 if (found) | |
290 new_len -= ef->size + 4; | |
291 new_len += len + 4; | |
292 | |
293 if (new_len > ZIP_UINT16_MAX) { | |
294 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
295 return -1; | |
296 } | |
297 | |
298 if ((ef_new=_zip_ef_new(ef_id, len, data, flags)) == NULL) { | |
299 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); | |
300 return -1; | |
301 } | |
302 | |
303 if (found) { | |
304 if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { | |
305 ef_new->next = ef->next; | |
306 ef->next = NULL; | |
307 _zip_ef_free(ef); | |
308 if (ef_prev) | |
309 ef_prev->next = ef_new; | |
310 else | |
311 de->extra_fields = ef_new; | |
312 } | |
313 else { | |
314 ef->flags &= ~(flags & ZIP_EF_BOTH); | |
315 ef_new->next = ef->next; | |
316 ef->next = ef_new; | |
317 } | |
318 } | |
319 else if (ef_prev) { | |
320 ef_new->next = ef_prev->next; | |
321 ef_prev->next = ef_new; | |
322 } | |
323 else | |
324 de->extra_fields = ef_new; | |
325 | |
326 return 0; | |
327 } | |
328 | |
329 | |
330 | |
331 int | |
332 _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) | |
333 { | |
334 zip_entry_t *e; | |
335 | |
336 if (idx >= za->nentry) { | |
337 zip_error_set(&za->error, ZIP_ER_INVAL, 0); | |
338 return -1; | |
339 } | |
340 | |
341 e = za->entry+idx; | |
342 | |
343 if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD)) | |
344 return 0; | |
345 | |
346 if (e->orig) { | |
347 if (_zip_read_local_ef(za, idx) < 0) | |
348 return -1; | |
349 } | |
350 | |
351 if (e->changes == NULL) { | |
352 if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { | |
353 zip_error_set(&za->error, ZIP_ER_MEMORY, 0); | |
354 return -1; | |
355 } | |
356 } | |
357 | |
358 if (e->orig && e->orig->extra_fields) { | |
359 if ((e->changes->extra_fields=_zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) | |
360 return -1; | |
361 } | |
362 e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD; | |
363 | |
364 return 0; | |
365 } | |
366 |