CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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