Rizin
unix-like reverse engineering framework and cli tools
zip_source_buffer.c
Go to the documentation of this file.
1 /*
2  zip_source_buffer.c -- create zip data source from buffer
3  Copyright (C) 1999-2022 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 <info@libzip.org>
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 #include <stdlib.h>
35 #include <string.h>
36 
37 #include "zipint.h"
38 
39 #ifndef WRITE_FRAGMENT_SIZE
40 #define WRITE_FRAGMENT_SIZE (64 * 1024)
41 #endif
42 
43 struct buffer {
44  zip_buffer_fragment_t *fragments; /* fragments */
45  zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */
46  zip_uint64_t nfragments; /* number of allocated fragments */
47  zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */
48 
49  zip_uint64_t first_owned_fragment; /* first fragment to free data from */
50 
51  zip_uint64_t shared_fragments; /* number of shared fragments */
52  struct buffer *shared_buffer; /* buffer fragments are shared with */
53  zip_uint64_t size; /* size of buffer */
54 
55  zip_uint64_t offset; /* current offset in buffer */
56  zip_uint64_t current_fragment; /* fragment current offset is in */
57 };
58 
59 typedef struct buffer buffer_t;
60 
61 struct read_data {
67 };
68 
69 #define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments])
70 #define buffer_size(buffer) ((buffer)->size)
71 
74 static void buffer_free(buffer_t *buffer);
76 static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error);
78 static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error);
80 
81 static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
82 
85 
86 
88 zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
89  if (za == NULL)
90  return NULL;
91 
92  return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
93 }
94 
95 
97 zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
99 }
100 
101 
102 zip_source_t *
104  zip_buffer_fragment_t fragment;
105 
106  if (data == NULL) {
107  if (len > 0) {
109  return NULL;
110  }
111 
112  return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
113  }
114 
115  fragment.data = (zip_uint8_t *)data;
116  fragment.length = len;
117 
118  return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error);
119 }
120 
121 
123 zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) {
124  if (za == NULL) {
125  return NULL;
126  }
127 
128  return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
129 }
130 
131 
134  return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error);
135 }
136 
137 zip_source_t *
139  struct read_data *ctx;
140  zip_source_t *zs;
141  buffer_t *buffer;
142 
143  if (fragments == NULL && nfragments > 0) {
145  return NULL;
146  }
147 
148  if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
149  return NULL;
150  }
151 
152  if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) {
155  return NULL;
156  }
157 
158  ctx->in = buffer;
159  ctx->out = NULL;
160  ctx->mtime = time(NULL);
161  if (attributes) {
162  memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
163  }
164  else {
165  zip_file_attributes_init(&ctx->attributes);
166  }
168 
170  buffer_free(ctx->in);
171  free(ctx);
172  return NULL;
173  }
174 
175  return zs;
176 }
177 
178 
179 zip_source_t *
182 }
183 
184 static zip_int64_t
186  struct read_data *ctx = (struct read_data *)state;
187 
188  switch (cmd) {
190  if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
191  return -1;
192  }
193  ctx->out->offset = 0;
194  ctx->out->current_fragment = 0;
195  return 0;
196 
198  if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
199  return -1;
200  }
201  ctx->out->offset = len;
202  ctx->out->current_fragment = ctx->out->nfragments;
203  return 0;
204 
205  case ZIP_SOURCE_CLOSE:
206  return 0;
207 
209  buffer_free(ctx->in);
210  ctx->in = ctx->out;
211  ctx->out = NULL;
212  return 0;
213 
214  case ZIP_SOURCE_ERROR:
215  return zip_error_to_data(&ctx->error, data, len);
216 
217  case ZIP_SOURCE_FREE:
218  buffer_free(ctx->in);
219  buffer_free(ctx->out);
220  free(ctx);
221  return 0;
222 
224  if (len < sizeof(ctx->attributes)) {
226  return -1;
227  }
228 
229  memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
230 
231  return sizeof(ctx->attributes);
232  }
233 
234  case ZIP_SOURCE_OPEN:
235  ctx->in->offset = 0;
236  ctx->in->current_fragment = 0;
237  return 0;
238 
239  case ZIP_SOURCE_READ:
240  if (len > ZIP_INT64_MAX) {
242  return -1;
243  }
244  return buffer_read(ctx->in, data, len);
245 
246  case ZIP_SOURCE_REMOVE: {
247  buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
248  if (empty == NULL) {
249  return -1;
250  }
251 
252  buffer_free(ctx->in);
253  ctx->in = empty;
254  return 0;
255  }
256 
258  buffer_free(ctx->out);
259  ctx->out = NULL;
260  return 0;
261 
262  case ZIP_SOURCE_SEEK:
263  return buffer_seek(ctx->in, data, len, &ctx->error);
264 
266  return buffer_seek(ctx->out, data, len, &ctx->error);
267 
268  case ZIP_SOURCE_STAT: {
269  zip_stat_t *st;
270 
271  if (len < sizeof(*st)) {
273  return -1;
274  }
275 
276  st = (zip_stat_t *)data;
277 
278  zip_stat_init(st);
279  st->mtime = ctx->mtime;
280  st->size = ctx->in->size;
281  st->comp_size = st->size;
285 
286  return sizeof(*st);
287  }
288 
289  case ZIP_SOURCE_SUPPORTS:
291 
292  case ZIP_SOURCE_TELL:
293  if (ctx->in->offset > ZIP_INT64_MAX) {
295  return -1;
296  }
297  return (zip_int64_t)ctx->in->offset;
298 
299 
301  if (ctx->out->offset > ZIP_INT64_MAX) {
303  return -1;
304  }
305  return (zip_int64_t)ctx->out->offset;
306 
307  case ZIP_SOURCE_WRITE:
308  if (len > ZIP_INT64_MAX) {
310  return -1;
311  }
312  return buffer_write(ctx->out, data, len, &ctx->error);
313 
314  default:
316  return -1;
317  }
318 }
319 
320 
321 static buffer_t *
323  zip_uint64_t fragment, fragment_offset, waste;
324  buffer_t *clone;
325 
326  if (offset == 0) {
327  return buffer_new(NULL, 0, 1, error);
328  }
329 
330  if (offset > buffer->size) {
332  return NULL;
333  }
334  if (buffer->shared_buffer != NULL) {
336  return NULL;
337  }
338 
339  fragment = buffer_find_fragment(buffer, offset);
340  fragment_offset = offset - buffer->fragment_offsets[fragment];
341 
342  if (fragment_offset == 0) {
343  fragment--;
344  fragment_offset = buffer->fragments[fragment].length;
345  }
346 
347  waste = buffer->fragments[fragment].length - fragment_offset;
348  if (waste > offset) {
350  return NULL;
351  }
352 
353  if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
354  return NULL;
355  }
356 
357 #ifndef __clang_analyzer__
358  /* clone->fragments can't be null, since it was created with at least one fragment */
359  clone->fragments[clone->nfragments - 1].length = fragment_offset;
360 #endif
361  clone->fragment_offsets[clone->nfragments] = offset;
362  clone->size = offset;
363 
365 
366  buffer->shared_buffer = clone;
367  clone->shared_buffer = buffer;
369  clone->shared_fragments = fragment + 1;
370 
371  return clone;
372 }
373 
374 
375 static zip_uint64_t
377  zip_uint64_t low, high, mid;
378 
379  if (buffer->nfragments == 0) {
380  return 0;
381  }
382 
383  low = 0;
384  high = buffer->nfragments - 1;
385 
386  while (low < high) {
387  mid = (high - low) / 2 + low;
388  if (buffer->fragment_offsets[mid] > offset) {
389  high = mid - 1;
390  }
391  else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
392  return mid;
393  }
394  else {
395  low = mid + 1;
396  }
397  }
398 
399  return low;
400 }
401 
402 
403 static void
405  zip_uint64_t i;
406 
407  if (buffer == NULL) {
408  return;
409  }
410 
411  if (buffer->shared_buffer != NULL) {
414 
416  }
417 
418  for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
420  }
423  free(buffer);
424 }
425 
426 
427 static bool
429  zip_buffer_fragment_t *fragments;
430  zip_uint64_t *offsets;
431 
432  if (capacity < buffer->fragments_capacity) {
433  return true;
434  }
435 
436  if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
438  return false;
439  }
440  buffer->fragments = fragments;
441  if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
443  return false;
444  }
445  buffer->fragment_offsets = offsets;
446  buffer->fragments_capacity = capacity;
447 
448  return true;
449 }
450 
451 
452 static buffer_t *
453 buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) {
454  buffer_t *buffer;
455 
456  if ((buffer = malloc(sizeof(*buffer))) == NULL) {
457  return NULL;
458  }
459 
460  buffer->offset = 0;
462  buffer->size = 0;
463  buffer->fragments = NULL;
465  buffer->nfragments = 0;
469 
470  if (nfragments == 0) {
471  if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
472  free(buffer);
474  return NULL;
475  }
476  buffer->fragment_offsets[0] = 0;
477  }
478  else {
479  zip_uint64_t i, j, offset;
480 
481  if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
484  return NULL;
485  }
486 
487  offset = 0;
488  for (i = 0, j = 0; i < nfragments; i++) {
489  if (fragments[i].length == 0) {
490  continue;
491  }
492  if (fragments[i].data == NULL) {
495  return NULL;
496  }
497  buffer->fragments[j].data = fragments[i].data;
498  buffer->fragments[j].length = fragments[i].length;
500  offset += fragments[i].length;
501  j++;
502  }
503  buffer->nfragments = j;
504  buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
506  buffer->size = offset;
507  }
508 
509  return buffer;
510 }
511 
512 static zip_int64_t
514  zip_uint64_t n, i, fragment_offset;
515 
517 
518  if (length == 0) {
519  return 0;
520  }
521  if (length > ZIP_INT64_MAX) {
522  return -1;
523  }
524 
526  fragment_offset = buffer->offset - buffer->fragment_offsets[i];
527  n = 0;
528  while (n < length) {
529  zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
530 
531  memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
532 
533  if (left == buffer->fragments[i].length - fragment_offset) {
534  i++;
535  }
536  n += left;
537  fragment_offset = 0;
538  }
539 
540  buffer->offset += n;
542  return (zip_int64_t)n;
543 }
544 
545 
546 static int
549 
550  if (new_offset < 0) {
551  return -1;
552  }
553 
554  buffer->offset = (zip_uint64_t)new_offset;
556  return 0;
557 }
558 
559 
560 static zip_int64_t
562  zip_uint64_t n, i, fragment_offset, capacity;
563 
564  if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
566  return -1;
567  }
568 
569  /* grow buffer if needed */
570  capacity = buffer_capacity(buffer);
571  if (buffer->offset + length > capacity) {
572  zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
573 
574  if (needed_fragments > buffer->fragments_capacity) {
575  zip_uint64_t new_capacity = buffer->fragments_capacity;
576 
577  if (new_capacity == 0) {
578  new_capacity = 16;
579  }
580  while (new_capacity < needed_fragments) {
581  new_capacity *= 2;
582  }
583 
584  if (!buffer_grow_fragments(buffer, new_capacity, error)) {
586  return -1;
587  }
588  }
589 
590  while (buffer->nfragments < needed_fragments) {
593  return -1;
594  }
596  buffer->nfragments++;
597  capacity += WRITE_FRAGMENT_SIZE;
599  }
600  }
601 
603  fragment_offset = buffer->offset - buffer->fragment_offsets[i];
604  n = 0;
605  while (n < length) {
606  zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
607 
608  memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
609 
610  if (left == buffer->fragments[i].length - fragment_offset) {
611  i++;
612  }
613  n += left;
614  fragment_offset = 0;
615  }
616 
617  buffer->offset += n;
619  if (buffer->offset > buffer->size) {
620  buffer->size = buffer->offset;
621  }
622 
623  return (zip_int64_t)n;
624 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
struct buffer buffer
#define EOVERFLOW
Definition: compat.h:75
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_CM_STORE
Definition: zip.h:149
ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull)
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_STAT_SIZE
Definition: zip.h:292
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable)
#define ZIP_STAT_COMP_METHOD
Definition: zip.h:296
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull)
Definition: zip_stat_init.c:40
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull)
Definition: zip_error.c:59
#define ZIP_EXTERN
Definition: zip.h:54
enum zip_source_cmd zip_source_cmd_t
Definition: zip.h:241
#define ZIP_STAT_ENCRYPTION_METHOD
Definition: zip.h:297
#define ZIP_STAT_COMP_SIZE
Definition: zip.h:293
#define ZIP_ER_TELL
Definition: zip.h:135
#define ZIP_EM_NONE
Definition: zip.h:177
@ ZIP_SOURCE_CLOSE
Definition: zip.h:222
@ ZIP_SOURCE_READ
Definition: zip.h:221
@ ZIP_SOURCE_GET_FILE_ATTRIBUTES
Definition: zip.h:239
@ ZIP_SOURCE_FREE
Definition: zip.h:225
@ ZIP_SOURCE_BEGIN_WRITE_CLONING
Definition: zip.h:237
@ ZIP_SOURCE_SEEK
Definition: zip.h:226
@ ZIP_SOURCE_SEEK_WRITE
Definition: zip.h:232
@ ZIP_SOURCE_SUPPORTS
Definition: zip.h:234
@ ZIP_SOURCE_STAT
Definition: zip.h:223
@ ZIP_SOURCE_TELL
Definition: zip.h:227
@ ZIP_SOURCE_OPEN
Definition: zip.h:220
@ ZIP_SOURCE_REMOVE
Definition: zip.h:235
@ ZIP_SOURCE_ROLLBACK_WRITE
Definition: zip.h:230
@ ZIP_SOURCE_TELL_WRITE
Definition: zip.h:233
@ ZIP_SOURCE_BEGIN_WRITE
Definition: zip.h:228
@ ZIP_SOURCE_WRITE
Definition: zip.h:231
@ ZIP_SOURCE_ERROR
Definition: zip.h:224
@ ZIP_SOURCE_COMMIT_WRITE
Definition: zip.h:229
#define ZIP_ER_INUSE
Definition: zip.h:134
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable)
#define ZIP_ER_INVAL
Definition: zip.h:123
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t,...)
#define ZIP_STAT_MTIME
Definition: zip.h:294
#define ZIP_ER_OPNOTSUPP
Definition: zip.h:133
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t)
Definition: zip_error.c:141
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
int n
Definition: mipsasm.c:19
int time_t
Definition: sftypes.h:66
Definition: buffer.h:15
zip_uint64_t first_owned_fragment
zip_uint64_t current_fragment
zip_uint64_t offset
zip_uint64_t nfragments
struct buffer * shared_buffer
zip_uint64_t * fragment_offsets
zip_uint64_t size
zip_uint64_t fragments_capacity
zip_buffer_fragment_t * fragments
zip_uint64_t shared_fragments
ZSTD_outBuffer out
zip_error_t * error
ZSTD_inBuffer in
buffer_t * in
zip_error_t error
zip_file_attributes_t attributes
buffer_t * out
Definition: dis.h:43
zip_uint64_t length
Definition: zip.h:315
zip_uint8_t *_Nonnull data
Definition: zip.h:314
Definition: zip.h:284
Definition: zip.h:300
time_t mtime
Definition: zip.h:306
zip_uint16_t encryption_method
Definition: zip.h:309
zip_uint64_t valid
Definition: zip.h:301
zip_uint16_t comp_method
Definition: zip.h:308
zip_uint64_t comp_size
Definition: zip.h:305
zip_uint64_t size
Definition: zip.h:304
Definition: zipint.h:278
zip_error_t error
Definition: zipint.h:281
void error(const char *msg)
Definition: untgz.c:593
static buffer_t * buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error)
static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset)
static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t)
static buffer_t * buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error)
static bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error)
ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep)
static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *)
static void buffer_free(buffer_t *buffer)
zip_source_t * zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes)
ZIP_EXTERN zip_source_t * zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error)
ZIP_EXTERN zip_source_t * zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep)
#define buffer_capacity(buffer)
#define WRITE_FRAGMENT_SIZE
static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
zip_source_t * zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error)
zip_source_t * zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error)
static zip_int64_t buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length)
ZIP_EXTERN zip_source_t * zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error)
uint64_t zip_uint64_t
Definition: zipconf.h:39
uint8_t zip_uint8_t
Definition: zipconf.h:33
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
#define ZIP_MAX(a, b)
Definition: zipint.h:472
#define ZIP_MIN(a, b)
Definition: zipint.h:473
zip_t * za
Definition: ziptool.c:79