3 #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
13 source_type_t source_type = SOURCE_TYPE_NONE;
14 zip_uint64_t fragment_size = 0;
16 static int add_nul(int argc, char *argv[]);
17 static int unchange_all(int argc, char *argv[]);
18 static int zin_close(int argc, char *argv[]);
20 #define OPTIONS_REGRESS "F:Hm"
22 #define USAGE_REGRESS " [-Hm] [-F fragment-size]"
24 #define GETOPT_REGRESS \
26 source_type = SOURCE_TYPE_HOLE; \
29 source_type = SOURCE_TYPE_IN_MEMORY; \
32 fragment_size = strtoull(optarg, NULL, 10); \
35 #define DISPATCH_REGRESS \
36 { "add_nul", 2, "name length", "add NUL bytes", add_nul }, \
37 { "unchange_all", 0, "", "revert all changes", unchange_all }, \
38 { "zin_close", 1, "index", "close input zip_source (for internal tests)", zin_close }
41 zip_t *ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len);
47 zip_source_t *memory_src = NULL;
49 zip_source_t *source_hole_create(const char *, int flags, zip_error_t *);
51 static zip_t *read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp);
52 static zip_source_t *source_nul(zip_t *za, zip_uint64_t length);
56 add_nul(int argc, char *argv[]) {
58 zip_uint64_t length = strtoull(argv[1], NULL, 10);
60 if ((zs=source_nul(za, length)) == NULL) {
61 fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za));
65 if (zip_add(za, argv[0], zs) == -1) {
67 fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
74 unchange_all(int argc, char *argv[]) {
75 if (zip_unchange_all(za) < 0) {
76 fprintf(stderr, "can't revert changes to archive: %s\n", zip_strerror(za));
83 zin_close(int argc, char *argv[]) {
86 idx = strtoull(argv[0], NULL, 10);
87 if (idx >= z_in_count) {
88 fprintf(stderr, "invalid argument '%" PRIu64 "', only %d zip sources open\n", idx, z_in_count);
91 if (zip_close(z_in[idx]) < 0) {
92 fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in[idx]));
95 z_in[idx] = z_in[z_in_count];
103 read_hole(const char *archive, int flags, zip_error_t *error)
105 zip_source_t *src = NULL;
108 if (strcmp(archive, "/dev/stdin") == 0) {
109 zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
113 if ((src = source_hole_create(archive, flags, error)) == NULL
114 || (zs = zip_open_from_source(src, flags, error)) == NULL) {
115 zip_source_free(src);
123 read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp)
129 if (strcmp(archive, "/dev/stdin") == 0) {
130 zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
134 if ((fp=fopen(archive, "r")) == NULL) {
135 if (errno == ENOENT) {
136 src = zip_source_buffer_create(NULL, 0, 0, error);
139 zip_error_set(error, ZIP_ER_OPEN, errno);
146 if (fstat(fileno(fp), &st) < 0) {
148 zip_error_set(error, ZIP_ER_OPEN, errno);
151 if (fragment_size == 0) {
153 if ((buf=malloc((size_t)st.st_size)) == NULL) {
155 zip_error_set(error, ZIP_ER_MEMORY, 0);
158 if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
161 zip_error_set(error, ZIP_ER_READ, errno);
164 src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
170 zip_uint64_t nfragments, i, left;
171 zip_buffer_fragment_t *fragments;
173 nfragments = ((size_t)st.st_size + fragment_size - 1) / fragment_size;
174 if ((fragments = malloc(sizeof(fragments[0]) * nfragments)) == NULL) {
176 zip_error_set(error, ZIP_ER_MEMORY, 0);
179 for (i = 0; i < nfragments; i++) {
180 left = ZIP_MIN(fragment_size, (size_t)st.st_size - i * fragment_size);
181 if ((fragments[i].data = malloc(left)) == NULL) {
183 free(fragments[i].data);
187 zip_error_set(error, ZIP_ER_MEMORY, 0);
190 fragments[i].length = left;
191 if (fread(fragments[i].data, left, 1, fp) < 1) {
193 free(fragments[i].data);
197 zip_error_set(error, ZIP_ER_READ, errno);
201 src = zip_source_buffer_fragment_create(fragments, nfragments, 1, error);
203 for (i = 0; i < nfragments; i++) {
204 free(fragments[i].data);
216 zb = zip_open_from_source(src, flags, error);
218 zip_source_free(src);
221 zip_source_keep(src);
227 typedef struct source_nul {
234 source_nul_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command)
236 source_nul_t *ctx = (source_nul_t *)ud;
239 case ZIP_SOURCE_CLOSE:
242 case ZIP_SOURCE_ERROR:
243 return zip_error_to_data(&ctx->error, data, length);
245 case ZIP_SOURCE_FREE:
249 case ZIP_SOURCE_OPEN:
253 case ZIP_SOURCE_READ:
254 if (length > ZIP_INT64_MAX) {
255 zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
259 if (length > ctx->length - ctx->offset) {
260 length =ctx->length - ctx->offset;
263 memset(data, 0, length);
264 ctx->offset += length;
265 return (zip_int64_t)length;
267 case ZIP_SOURCE_STAT: {
268 zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
274 st->valid |= ZIP_STAT_SIZE;
275 st->size = ctx->length;
280 case ZIP_SOURCE_SUPPORTS:
281 return zip_source_make_command_bitmap(ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_STAT, -1);
284 zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
289 static zip_source_t *
290 source_nul(zip_t *zs, zip_uint64_t length)
295 if ((ctx = (source_nul_t *)malloc(sizeof(*ctx))) == NULL) {
296 zip_error_set(zip_get_error(zs), ZIP_ER_MEMORY, 0);
300 zip_error_init(&ctx->error);
301 ctx->length = length;
304 if ((src = zip_source_function(zs, source_nul_cb, ctx)) == NULL) {
314 write_memory_src_to_file(const char *archive, zip_source_t *src)
320 if (zip_source_stat(src, &zst) < 0) {
321 fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
324 if (zip_source_open(src) < 0) {
325 if (zip_error_code_zip(zip_source_error(src)) == ZIP_ER_DELETED) {
326 if (unlink(archive) < 0 && errno != ENOENT) {
327 fprintf(stderr, "unlink failed: %s\n", strerror(errno));
332 fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
335 if ((buf=malloc(zst.size)) == NULL) {
336 fprintf(stderr, "malloc failed: %s\n", strerror(errno));
337 zip_source_close(src);
340 if (zip_source_read(src, buf, zst.size) < (zip_int64_t)zst.size) {
341 fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
342 zip_source_close(src);
346 zip_source_close(src);
347 if ((fp=fopen(archive, "wb")) == NULL) {
348 fprintf(stderr, "fopen failed: %s\n", strerror(errno));
352 if (fwrite(buf, zst.size, 1, fp) < 1) {
353 fprintf(stderr, "fwrite failed: %s\n", strerror(errno));
359 if (fclose(fp) != 0) {
360 fprintf(stderr, "fclose failed: %s\n", strerror(errno));
368 ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len) {
369 switch (source_type) {
370 case SOURCE_TYPE_NONE:
371 za = read_from_file(archive, flags, error, offset, len);
374 case SOURCE_TYPE_IN_MEMORY:
375 za = read_to_memory(archive, flags, error, &memory_src);
378 case SOURCE_TYPE_HOLE:
379 za = read_hole(archive, flags, error);
388 ziptool_post_close(const char *archive) {
389 if (source_type == SOURCE_TYPE_IN_MEMORY) {
390 if (write_memory_src_to_file(archive, memory_src) < 0) {
393 zip_source_free(memory_src);