Rizin
unix-like reverse engineering framework and cli tools
ziptool_regress.c
Go to the documentation of this file.
1 #include "zip.h"
2 
3 #include <sys/stat.h>
4 
5 #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
6 
7 #define FOR_REGRESS
8 
10 
13 
14 static int add_nul(char *argv[]);
15 static int cancel(char *argv[]);
16 static int is_seekable(char *argv[]);
17 static int seek(char *argv[]);
18 static int unchange_one(char *argv[]);
19 static int unchange_all(char *argv[]);
20 static int zin_close(char *argv[]);
21 
22 #define OPTIONS_REGRESS "F:Hm"
23 
24 #define USAGE_REGRESS " [-Hm] [-F fragment-size]"
25 
26 #define GETOPT_REGRESS \
27  case 'H': \
28  source_type = SOURCE_TYPE_HOLE; \
29  break; \
30  case 'm': \
31  source_type = SOURCE_TYPE_IN_MEMORY; \
32  break; \
33  case 'F': \
34  fragment_size = strtoull(optarg, NULL, 10); \
35  break;
36 
37 /* clang-format off */
38 
39 #define DISPATCH_REGRESS \
40  {"add_nul", 2, "name length", "add NUL bytes", add_nul}, \
41  {"cancel", 1, "limit", "cancel writing archive when limit% have been written (calls print_progress)", cancel}, \
42  {"is_seekable", 1, "index", "report if entry is seekable", is_seekable}, \
43  {"seek", 2, "index offset", "seek in entry to offset", seek}, \
44  {"unchange", 1, "index", "revert changes for entry", unchange_one}, \
45  {"unchange_all", 0, "", "revert all changes", unchange_all}, \
46  { "zin_close", 1, "index", "close input zip_source (for internal tests)", zin_close }
47 
48 /* clang-format on */
49 
50 
52 
53 
54 #include "ziptool.c"
55 
56 
58 
59 zip_source_t *source_hole_create(const char *, int flags, zip_error_t *);
60 
61 static zip_t *read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp);
63 
64 
65 static int
66 add_nul(char *argv[]) {
67  zip_source_t *zs;
68  zip_uint64_t length = strtoull(argv[1], NULL, 10);
69 
70  if ((zs = source_nul(za, length)) == NULL) {
71  fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za));
72  return -1;
73  }
74 
75  if (zip_add(za, argv[0], zs) == -1) {
76  zip_source_free(zs);
77  fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
78  return -1;
79  }
80  return 0;
81 }
82 
83 static int
86  return -1;
87  }
88  return 0;
89 }
90 
91 static int
92 cancel(char *argv[]) {
93  zip_int64_t percent;
94  percent = strtoll(argv[0], NULL, 10);
95  if (percent > 100 || percent < 0) {
96  fprintf(stderr, "invalid percentage '%" PRId64 "' for cancel (valid: 0 <= x <= 100)\n", percent);
97  return -1;
98  }
99  progress_userdata.limit = ((double)percent) / 100;
100 
102 
103  /* needs the percentage updates from print_progress */
105  return 0;
106 }
107 
108 static int
109 is_seekable(char *argv[]) {
111  zip_file_t *zf;
112 
113  idx = strtoull(argv[0], NULL, 10);
114  if ((zf = zip_fopen_index(za, idx, 0)) == NULL) {
115  fprintf(stderr, "can't open file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
116  return -1;
117  }
118  switch (zip_file_is_seekable(zf)) {
119  case -1:
120  fprintf(stderr, "can't check if file %" PRIu64 " is seekable: %s\n", idx, zip_strerror(za));
121  return -1;
122  case 0:
123  printf("%" PRIu64 ": NOT seekable\n", idx);
124  break;
125  case 1:
126  printf("%" PRIu64 ": seekable\n", idx);
127  break;
128  }
129  return 0;
130 }
131 
132 static int
133 seek(char *argv[]) {
135  zip_file_t *zf;
137 
138  idx = strtoull(argv[0], NULL, 10);
139  offset = strtoull(argv[1], NULL, 10);
140  if ((zf = zip_fopen_index(za, idx, 0)) == NULL) {
141  fprintf(stderr, "can't open file at index '%" PRIu64 "': %s\n", idx, zip_strerror(za));
142  return -1;
143  }
144  if (zip_fseek(zf, offset, SEEK_SET) == -1) {
145  fprintf(stderr, "can't seek in file %" PRIu64 ": %s\n", idx, zip_strerror(za));
146  return -1;
147  }
148  return 0;
149 }
150 
151 static int
152 unchange_all(char *argv[]) {
153  if (zip_unchange_all(za) < 0) {
154  fprintf(stderr, "can't revert changes to archive: %s\n", zip_strerror(za));
155  return -1;
156  }
157  return 0;
158 }
159 
160 
161 static int
162 unchange_one(char *argv[]) {
164 
165  idx = strtoull(argv[0], NULL, 10);
166 
167  if (zip_unchange(za, idx) < 0) {
168  fprintf(stderr, "can't revert changes for entry %" PRIu64 ": %s", idx, zip_strerror(za));
169  return -1;
170  }
171 
172  return 0;
173 }
174 
175 static int
176 zin_close(char *argv[]) {
178 
179  idx = strtoull(argv[0], NULL, 10);
180  if (idx >= z_in_count) {
181  fprintf(stderr, "invalid argument '%" PRIu64 "', only %u zip sources open\n", idx, z_in_count);
182  return -1;
183  }
184  if (zip_close(z_in[idx]) < 0) {
185  fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in[idx]));
186  return -1;
187  }
188  z_in[idx] = z_in[z_in_count];
189  z_in_count--;
190 
191  return 0;
192 }
193 
194 
195 static zip_t *
196 read_hole(const char *archive, int flags, zip_error_t *error) {
197  zip_source_t *src = NULL;
198  zip_t *zs = NULL;
199 
200  if (strcmp(archive, "/dev/stdin") == 0) {
202  return NULL;
203  }
204 
207  }
208 
209  return zs;
210 }
211 
212 
213 static zip_t *
215  zip_source_t *src;
216  zip_t *zb;
217  FILE *fp;
218 
219  if (strcmp(archive, "/dev/stdin") == 0) {
221  return NULL;
222  }
223 
224  if ((fp = fopen(archive, "rb")) == NULL) {
225  if (errno == ENOENT) {
227  }
228  else {
230  return NULL;
231  }
232  }
233  else {
234  struct stat st;
235 
236  if (fstat(fileno(fp), &st) < 0) {
237  fclose(fp);
239  return NULL;
240  }
241  if (fragment_size == 0) {
242  char *buf;
243  if ((buf = malloc((size_t)st.st_size)) == NULL) {
244  fclose(fp);
246  return NULL;
247  }
248  if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
249  free(buf);
250  fclose(fp);
252  return NULL;
253  }
254  src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
255  if (src == NULL) {
256  free(buf);
257  }
258  }
259  else {
260  zip_uint64_t nfragments, i, left;
261  zip_buffer_fragment_t *fragments;
262 
263  nfragments = ((size_t)st.st_size + fragment_size - 1) / fragment_size;
264  if ((fragments = malloc(sizeof(fragments[0]) * nfragments)) == NULL) {
265  fclose(fp);
267  return NULL;
268  }
269  for (i = 0; i < nfragments; i++) {
270  left = ZIP_MIN(fragment_size, (size_t)st.st_size - i * fragment_size);
271  if ((fragments[i].data = malloc(left)) == NULL) {
272 #ifndef __clang_analyzer__
273  /* fragments is initialized up to i - 1*/
274  while (--i > 0) {
275  free(fragments[i].data);
276  }
277 #endif
278  free(fragments);
279  fclose(fp);
281  return NULL;
282  }
283  fragments[i].length = left;
284  if (fread(fragments[i].data, left, 1, fp) < 1) {
285 #ifndef __clang_analyzer__
286  /* fragments is initialized up to i - 1*/
287  while (--i > 0) {
288  free(fragments[i].data);
289  }
290 #endif
291  free(fragments);
292  fclose(fp);
294  return NULL;
295  }
296  }
297  src = zip_source_buffer_fragment_create(fragments, nfragments, 1, error);
298  if (src == NULL) {
299  for (i = 0; i < nfragments; i++) {
300  free(fragments[i].data);
301  }
302  free(fragments);
303  fclose(fp);
304  return NULL;
305  }
306  free(fragments);
307  }
308  fclose(fp);
309  }
310  if (src == NULL) {
311  return NULL;
312  }
314  if (zb == NULL) {
316  return NULL;
317  }
319  *srcp = src;
320  return zb;
321 }
322 
323 
324 typedef struct source_nul {
329 
330 static zip_int64_t
332  source_nul_t *ctx = (source_nul_t *)ud;
333 
334  switch (command) {
335  case ZIP_SOURCE_CLOSE:
336  return 0;
337 
338  case ZIP_SOURCE_ERROR:
339  return zip_error_to_data(&ctx->error, data, length);
340 
341  case ZIP_SOURCE_FREE:
342  free(ctx);
343  return 0;
344 
345  case ZIP_SOURCE_OPEN:
346  ctx->offset = 0;
347  return 0;
348 
349  case ZIP_SOURCE_READ:
350  if (length > ZIP_INT64_MAX) {
352  return -1;
353  }
354 
355  if (length > ctx->length - ctx->offset) {
356  length = ctx->length - ctx->offset;
357  }
358 
359  memset(data, 0, length);
360  ctx->offset += length;
361  return (zip_int64_t)length;
362 
363  case ZIP_SOURCE_STAT: {
365 
366  if (st == NULL) {
367  return -1;
368  }
369 
370  st->valid |= ZIP_STAT_SIZE;
371  st->size = ctx->length;
372 
373  return 0;
374  }
375 
376  case ZIP_SOURCE_SUPPORTS:
378 
379  default:
381  return -1;
382  }
383 }
384 
385 static zip_source_t *
387  source_nul_t *ctx;
388  zip_source_t *src;
389 
390  if ((ctx = (source_nul_t *)malloc(sizeof(*ctx))) == NULL) {
392  return NULL;
393  }
394 
396  ctx->length = length;
397  ctx->offset = 0;
398 
399  if ((src = zip_source_function(zs, source_nul_cb, ctx)) == NULL) {
400  free(ctx);
401  return NULL;
402  }
403 
404  return src;
405 }
406 
407 
408 static int
410  zip_stat_t zst;
411  char *buf;
412  FILE *fp;
413 
414  if (zip_source_stat(src, &zst) < 0) {
415  fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
416  return -1;
417  }
418  if (zip_source_open(src) < 0) {
420  if (unlink(archive) < 0 && errno != ENOENT) {
421  fprintf(stderr, "unlink failed: %s\n", strerror(errno));
422  return -1;
423  }
424  return 0;
425  }
426  fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
427  return -1;
428  }
429  if ((buf = malloc(zst.size)) == NULL) {
430  fprintf(stderr, "malloc failed: %s\n", strerror(errno));
432  return -1;
433  }
434  if (zip_source_read(src, buf, zst.size) < (zip_int64_t)zst.size) {
435  fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
437  free(buf);
438  return -1;
439  }
441  if ((fp = fopen(archive, "wb")) == NULL) {
442  fprintf(stderr, "fopen failed: %s\n", strerror(errno));
443  free(buf);
444  return -1;
445  }
446  if (fwrite(buf, zst.size, 1, fp) < 1) {
447  fprintf(stderr, "fwrite failed: %s\n", strerror(errno));
448  free(buf);
449  fclose(fp);
450  return -1;
451  }
452  free(buf);
453  if (fclose(fp) != 0) {
454  fprintf(stderr, "fclose failed: %s\n", strerror(errno));
455  return -1;
456  }
457  return 0;
458 }
459 
460 
461 zip_t *
463  switch (source_type) {
464  case SOURCE_TYPE_NONE:
466  break;
467 
470  break;
471 
472  case SOURCE_TYPE_HOLE:
474  break;
475  }
476 
477  return za;
478 }
479 
480 
481 int
485  return -1;
486  }
488  }
489 
490  return 0;
491 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
#define NULL
Definition: cris-opc.c:27
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
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 fstat
Definition: sflib.h:107
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
voidpf void * buf
Definition: ioapi.h:138
return memset(p, 0, total)
#define PRIu64
Definition: macros.h:18
#define PRId64
Definition: macros.h:17
ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull)
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_ER_OPEN
Definition: zip.h:116
ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull)
Definition: zip_fseek.c:55
#define ZIP_ER_MEMORY
Definition: zip.h:119
ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable)
Definition: zip_open.c:79
ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t)
#define ZIP_STAT_SIZE
Definition: zip.h:292
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable)
ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t)
Definition: zip_unchange.c:41
#define ZIP_ER_DELETED
Definition: zip.h:128
ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull)
Definition: zip_add.c:47
ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable)
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull)
Definition: zip_error.c:59
ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull)
ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int)
Definition: zip_fseek.c:38
ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull)
enum zip_source_cmd zip_source_cmd_t
Definition: zip.h:241
ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull)
Definition: zip_error_get.c:46
ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void(*_Nullable)(void *_Nullable), void *_Nullable)
ZIP_EXTERN int zip_close(zip_t *_Nonnull)
Definition: zip_close.c:52
@ ZIP_SOURCE_CLOSE
Definition: zip.h:222
@ ZIP_SOURCE_READ
Definition: zip.h:221
@ ZIP_SOURCE_FREE
Definition: zip.h:225
@ ZIP_SOURCE_SUPPORTS
Definition: zip.h:234
@ ZIP_SOURCE_STAT
Definition: zip.h:223
@ ZIP_SOURCE_OPEN
Definition: zip.h:220
@ ZIP_SOURCE_ERROR
Definition: zip.h:224
ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull)
ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull)
#define ZIP_ER_INVAL
Definition: zip.h:123
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t,...)
ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable)
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull)
Definition: zip_error.c:46
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable)
#define ZIP_ER_OPNOTSUPP
Definition: zip.h:133
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull)
ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t)
ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull)
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t)
Definition: zip_error.c:141
#define ZIP_ER_READ
Definition: zip.h:110
ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull)
Definition: zip_strerror.c:39
#define ZIP_SOURCE_GET_ARGS(type, data, len, error)
Definition: zip.h:279
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 argv
Definition: sflib.h:40
static static fork const void static count static fd const char static mode unlink
Definition: sflib.h:41
string FILE
Definition: benchmark.py:21
int idx
Definition: setup.py:197
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define ENOENT
Definition: sftypes.h:112
int size_t
Definition: sftypes.h:40
Definition: zipcmp.c:60
zip_error_t * error
zip_uint64_t offset
zip_uint64_t length
zip_error_t error
Definition: sftypes.h:80
zip_uint64_t length
Definition: zip.h:315
Definition: zip.h:284
Definition: zip.h:300
zip_uint64_t valid
Definition: zip.h:301
zip_uint64_t size
Definition: zip.h:304
Definition: zipint.h:278
const char * command
Definition: main.c:7
void print_progress(uv_async_t *handle)
Definition: main.c:31
void error(const char *msg)
Definition: untgz.c:593
#define SEEK_SET
Definition: zip.c:88
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
zip_t * z_in[16]
Definition: ziptool.c:79
struct progress_userdata_s progress_userdata
Definition: ziptool.c:395
zip_t * za
Definition: ziptool.c:79
static zip_t * read_from_file(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t length)
Definition: ziptool.c:706
unsigned int z_in_count
Definition: ziptool.c:80
zip_uint64_t fragment_size
static int cancel(char *argv[])
source_type_t
@ SOURCE_TYPE_IN_MEMORY
@ SOURCE_TYPE_NONE
@ SOURCE_TYPE_HOLE
static int unchange_all(char *argv[])
zip_source_t * source_hole_create(const char *, int flags, zip_error_t *)
Definition: source_hole.c:94
struct source_nul source_nul_t
zip_source_t * memory_src
static int write_memory_src_to_file(const char *archive, zip_source_t *src)
int ziptool_post_close(const char *archive)
source_type_t source_type
static int add_nul(char *argv[])
static zip_t * read_hole(const char *archive, int flags, zip_error_t *error)
static zip_int64_t source_nul_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command)
static zip_source_t * source_nul(zip_t *za, zip_uint64_t length)
static int cancel_callback(zip_t *archive, void *ud)
#define ZIP_MIN(a, b)
static int seek(char *argv[])
static int zin_close(char *argv[])
static int unchange_one(char *argv[])
static int is_seekable(char *argv[])
zip_t * ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len)
static zip_t * read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp)