Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 1 | /* |
| 2 | zip_extra_field.c -- manipulate extra fields |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 3 | Copyright (C) 2012-2014 Dieter Baron and Thomas Klausner |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 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 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 34 | |
| 35 | #include "zipint.h" |
| 36 | |
| 37 | #include <errno.h> |
| 38 | #include <stdlib.h> |
| 39 | #include <string.h> |
| 40 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 41 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 42 | zip_extra_field_t * |
| 43 | _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 44 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 45 | zip_extra_field_t *head, *prev, *def; |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 46 | |
| 47 | head = prev = NULL; |
| 48 | |
| 49 | while (ef) { |
| 50 | if ((def=_zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 51 | zip_error_set(error, ZIP_ER_MEMORY, 0); |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 52 | _zip_ef_free(head); |
| 53 | return NULL; |
| 54 | } |
| 55 | |
| 56 | if (head == NULL) |
| 57 | head = def; |
| 58 | if (prev) |
| 59 | prev->next = def; |
| 60 | prev = def; |
Thomas Klausner | 95d6fdf | 2013-02-20 11:47:10 +0100 | [diff] [blame] | 61 | |
| 62 | ef = ef->next; |
Dieter Baron | 6fad8b6 | 2012-10-12 15:18:04 +0200 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | return head; |
| 66 | } |
| 67 | |
| 68 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 69 | zip_extra_field_t * |
| 70 | _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 71 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 72 | zip_extra_field_t *head, *prev; |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 73 | int i; |
| 74 | |
| 75 | i = 0; |
| 76 | head = ef; |
| 77 | prev = NULL; |
| 78 | for (; ef; ef=(prev ? prev->next : head)) { |
Thomas Klausner | 17bf6d3 | 2013-07-31 16:29:24 +0200 | [diff] [blame] | 79 | if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 80 | if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { |
| 81 | ef->flags &= ~(flags & ZIP_EF_BOTH); |
| 82 | if ((ef->flags & ZIP_EF_BOTH) == 0) { |
| 83 | if (prev) |
| 84 | prev->next = ef->next; |
| 85 | else |
| 86 | head = ef->next; |
| 87 | ef->next = NULL; |
| 88 | _zip_ef_free(ef); |
| 89 | |
| 90 | if (id_idx == ZIP_EXTRA_FIELD_ALL) |
| 91 | continue; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | i++; |
| 96 | if (i > id_idx) |
| 97 | break; |
| 98 | } |
| 99 | prev = ef; |
| 100 | } |
| 101 | |
| 102 | return head; |
| 103 | } |
| 104 | |
| 105 | |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 106 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 107 | void |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 108 | _zip_ef_free(zip_extra_field_t *ef) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 109 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 110 | zip_extra_field_t *ef2; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 111 | |
| 112 | while (ef) { |
| 113 | ef2 = ef->next; |
| 114 | free(ef->data); |
| 115 | free(ef); |
| 116 | ef = ef2; |
| 117 | } |
| 118 | } |
| 119 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 120 | |
| 121 | const zip_uint8_t * |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 122 | _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 123 | { |
Dieter Baron | 837f5ce | 2013-03-14 12:21:04 +0100 | [diff] [blame] | 124 | static const zip_uint8_t empty[1] = { '\0' }; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 125 | |
| 126 | int i; |
| 127 | |
| 128 | i = 0; |
| 129 | for (; ef; ef=ef->next) { |
| 130 | if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { |
| 131 | if (i < id_idx) { |
| 132 | i++; |
| 133 | continue; |
| 134 | } |
| 135 | |
| 136 | if (lenp) |
| 137 | *lenp = ef->size; |
| 138 | if (ef->size > 0) |
| 139 | return ef->data; |
| 140 | else |
| 141 | return empty; |
| 142 | } |
| 143 | } |
| 144 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 145 | zip_error_set(error, ZIP_ER_NOENT, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 146 | return NULL; |
| 147 | } |
| 148 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 149 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 150 | zip_extra_field_t * |
| 151 | _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 152 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 153 | zip_extra_field_t *ef2, *tt, *tail; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 154 | int duplicate; |
| 155 | |
| 156 | if (to == NULL) |
| 157 | return from; |
| 158 | |
| 159 | for (tail=to; tail->next; tail=tail->next) |
| 160 | ; |
| 161 | |
| 162 | for (; from; from=ef2) { |
| 163 | ef2 = from->next; |
| 164 | |
| 165 | duplicate = 0; |
| 166 | for (tt=to; tt; tt=tt->next) { |
| 167 | if (tt->id == from->id && tt->size == from->size && memcmp(tt->data, from->data, tt->size) == 0) { |
| 168 | tt->flags |= (from->flags & ZIP_EF_BOTH); |
| 169 | duplicate = 1; |
| 170 | break; |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | from->next = NULL; |
| 175 | if (duplicate) |
| 176 | _zip_ef_free(from); |
| 177 | else |
| 178 | tail = tail->next = from; |
| 179 | } |
| 180 | |
| 181 | return to; |
| 182 | } |
| 183 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 184 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 185 | zip_extra_field_t * |
Dieter Baron | 3efab99 | 2012-05-04 09:29:29 +0200 | [diff] [blame] | 186 | _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 187 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 188 | zip_extra_field_t *ef; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 189 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 190 | if ((ef=(zip_extra_field_t *)malloc(sizeof(*ef))) == NULL) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 191 | return NULL; |
| 192 | |
| 193 | ef->next = NULL; |
| 194 | ef->flags = flags; |
| 195 | ef->id = id; |
| 196 | ef->size = size; |
| 197 | if (size > 0) { |
Thomas Klausner | 84c2c08 | 2013-03-17 22:20:14 +0100 | [diff] [blame] | 198 | if ((ef->data=(zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 199 | free(ef); |
| 200 | return NULL; |
| 201 | } |
| 202 | } |
| 203 | else |
| 204 | ef->data = NULL; |
| 205 | |
| 206 | return ef; |
| 207 | } |
| 208 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 209 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 210 | zip_extra_field_t * |
| 211 | _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 212 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 213 | zip_extra_field_t *ef, *ef2, *ef_head; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 214 | const zip_uint8_t *p; |
| 215 | zip_uint16_t fid, flen; |
| 216 | |
Thomas Klausner | d683c12 | 2014-03-10 16:13:59 +0100 | [diff] [blame] | 217 | ef_head = ef = NULL; |
Dieter Baron | abc6fd7 | 2012-07-22 15:49:45 +0200 | [diff] [blame] | 218 | for (p=data; p<data+len; p+=flen) { |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 219 | if (p+4 > data+len) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 220 | zip_error_set(error, ZIP_ER_INCONS, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 221 | _zip_ef_free(ef_head); |
| 222 | return NULL; |
| 223 | } |
| 224 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 225 | fid = _zip_get_16(&p); |
| 226 | flen = _zip_get_16(&p); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 227 | |
Dieter Baron | abc6fd7 | 2012-07-22 15:49:45 +0200 | [diff] [blame] | 228 | if (p+flen > data+len) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 229 | zip_error_set(error, ZIP_ER_INCONS, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 230 | _zip_ef_free(ef_head); |
| 231 | return NULL; |
| 232 | } |
| 233 | |
Dieter Baron | abc6fd7 | 2012-07-22 15:49:45 +0200 | [diff] [blame] | 234 | if ((ef2=_zip_ef_new(fid, flen, p, flags)) == NULL) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 235 | zip_error_set(error, ZIP_ER_MEMORY, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 236 | _zip_ef_free(ef_head); |
| 237 | return NULL; |
| 238 | } |
| 239 | |
| 240 | if (ef_head) { |
| 241 | ef->next = ef2; |
| 242 | ef = ef2; |
| 243 | } |
| 244 | else |
| 245 | ef_head = ef = ef2; |
| 246 | } |
| 247 | |
| 248 | return ef_head; |
| 249 | } |
| 250 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 251 | |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 252 | zip_extra_field_t * |
| 253 | _zip_ef_remove_internal(zip_extra_field_t *ef) |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 254 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 255 | zip_extra_field_t *ef_head; |
| 256 | zip_extra_field_t *prev, *next; |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 257 | |
Dieter Baron | 837f5ce | 2013-03-14 12:21:04 +0100 | [diff] [blame] | 258 | ef_head = ef; |
Dieter Baron | 7f433be | 2012-10-13 18:55:35 +0200 | [diff] [blame] | 259 | prev = NULL; |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 260 | |
| 261 | while (ef) { |
| 262 | if (ZIP_EF_IS_INTERNAL(ef->id)) { |
| 263 | next = ef->next; |
| 264 | if (ef_head == ef) |
| 265 | ef_head = next; |
| 266 | ef->next = NULL; |
| 267 | _zip_ef_free(ef); |
| 268 | if (prev) |
| 269 | prev->next = next; |
| 270 | ef = next; |
| 271 | } |
| 272 | else { |
| 273 | prev = ef; |
| 274 | ef = ef->next; |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | return ef_head; |
| 279 | } |
| 280 | |
| 281 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 282 | zip_uint16_t |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 283 | _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 284 | { |
| 285 | zip_uint16_t size; |
| 286 | |
| 287 | size = 0; |
| 288 | for (; ef; ef=ef->next) { |
| 289 | if (ef->flags & flags & ZIP_EF_BOTH) |
Thomas Klausner | 03ca1c1 | 2014-09-24 01:02:15 +0200 | [diff] [blame] | 290 | size = (zip_uint16_t)(size+4+ef->size); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | return size; |
| 294 | } |
| 295 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 296 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 297 | int |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 298 | _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 299 | { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 300 | zip_uint8_t b[4], *p; |
| 301 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 302 | for (; ef; ef=ef->next) { |
| 303 | if (ef->flags & flags & ZIP_EF_BOTH) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 304 | p = b; |
| 305 | _zip_put_16(&p, ef->id); |
| 306 | _zip_put_16(&p, ef->size); |
| 307 | if (_zip_write(za, b, 4) < 0) { |
| 308 | return -1; |
| 309 | } |
| 310 | if (ef->size > 0) { |
| 311 | if (_zip_write(za, ef->data, ef->size) < 0) { |
| 312 | return -1; |
| 313 | } |
| 314 | } |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 315 | } |
| 316 | } |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 317 | return 0; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 318 | } |
| 319 | |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 320 | |
| 321 | int |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 322 | _zip_read_local_ef(zip_t *za, zip_uint64_t idx) |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 323 | { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 324 | zip_entry_t *e; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 325 | unsigned char b[4]; |
| 326 | const unsigned char *p; |
| 327 | zip_uint16_t fname_len, ef_len; |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 328 | |
| 329 | if (idx >= za->nentry) { |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 330 | zip_error_set(&za->error, ZIP_ER_INVAL, 0); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 331 | return -1; |
| 332 | } |
| 333 | |
| 334 | e = za->entry+idx; |
| 335 | |
| 336 | if (e->orig == NULL || e->orig->local_extra_fields_read) |
| 337 | return 0; |
| 338 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 339 | if (e->orig->offset + 26 > ZIP_INT64_MAX) { |
| 340 | zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); |
| 341 | return -1; |
| 342 | } |
Dieter Baron | abc6fd7 | 2012-07-22 15:49:45 +0200 | [diff] [blame] | 343 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 344 | if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { |
Thomas Klausner | d97f544 | 2014-09-23 17:02:03 +0200 | [diff] [blame] | 345 | _zip_error_set_from_source(&za->error, za->src); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 346 | return -1; |
| 347 | } |
| 348 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 349 | if (_zip_read(za->src, b, sizeof(b), &za->error) < 0) { |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 350 | return -1; |
| 351 | } |
| 352 | |
| 353 | p = b; |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 354 | fname_len = _zip_get_16(&p); |
| 355 | ef_len = _zip_get_16(&p); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 356 | |
| 357 | if (ef_len > 0) { |
Dieter Baron | 1d9dfeb | 2014-09-28 23:02:54 +0200 | [diff] [blame] | 358 | zip_extra_field_t *ef; |
Thomas Klausner | 9244705 | 2013-03-20 00:34:05 +0100 | [diff] [blame] | 359 | zip_uint8_t *ef_raw; |
| 360 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 361 | if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { |
| 362 | zip_error_set(&za->error, ZIP_ER_SEEK, errno); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 363 | return -1; |
| 364 | } |
| 365 | |
Thomas Klausner | ea8ba49 | 2014-09-23 16:54:47 +0200 | [diff] [blame] | 366 | ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 367 | |
| 368 | if (ef_raw == NULL) |
| 369 | return -1; |
| 370 | |
| 371 | if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) { |
| 372 | free(ef_raw); |
| 373 | return -1; |
| 374 | } |
| 375 | free(ef_raw); |
| 376 | |
Dieter Baron | c332cc7 | 2012-10-13 18:32:44 +0200 | [diff] [blame] | 377 | ef = _zip_ef_remove_internal(ef); |
Dieter Baron | 0e5eeab | 2012-04-24 18:47:12 +0200 | [diff] [blame] | 378 | e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); |
| 379 | } |
| 380 | |
| 381 | e->orig->local_extra_fields_read = 1; |
| 382 | |
| 383 | if (e->changes && e->changes->local_extra_fields_read == 0) { |
| 384 | e->changes->extra_fields = e->orig->extra_fields; |
| 385 | e->changes->local_extra_fields_read = 1; |
| 386 | } |
| 387 | |
| 388 | return 0; |
| 389 | } |