Add add_nul command that adds file of given size, with all NUL bytes.
diff --git a/regress/modify.c b/regress/modify.c index 341bc0e..946199f 100644 --- a/regress/modify.c +++ b/regress/modify.c
@@ -60,6 +60,7 @@ static zip_int32_t get_compression_method(const char *arg); static void hexdump(const zip_uint8_t *data, zip_uint16_t len); static zip_t *read_to_memory(const char *archive, int flags, int *err, zip_source_t **srcp); +static zip_source_t *source_nul(zip_t *za, zip_uint64_t length); zip_t *za, *z_in; zip_flags_t stat_flags; @@ -146,6 +147,23 @@ return 0; } +add_nul(int argc, char *argv[]) { + zip_source_t *zs; + zip_uint64_t length = strtoull(argv[1], NULL, 10); + + if ((zs=source_nul(za, length)) == NULL) { + fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za)); + return -1; + } + + if (zip_add(za, argv[0], zs) == -1) { + zip_source_free(zs); + fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za)); + return -1; + } + return 0; +} + static int count_extra(int argc, char *argv[]) { zip_int16_t count; @@ -529,6 +547,87 @@ return zb; } +typedef struct source_nul { + zip_error_t error; + zip_uint64_t length; + zip_uint64_t offset; +} source_nul_t; + +static zip_int64_t +source_nul_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command) +{ + source_nul_t *ctx = (source_nul_t *)ud; + + switch (command) { + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + free(ctx); + return 0; + + case ZIP_SOURCE_OPEN: + ctx->offset = 0; + return 0; + + case ZIP_SOURCE_READ: + if (length > ctx->length - ctx->offset) { + length =ctx->length - ctx->offset; + } + + memset(data, 0, length); + ctx->offset += length; + return length; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error); + + if (st == NULL) { + return -1; + } + + st->valid |= ZIP_STAT_SIZE; + st->size = ctx->length; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + 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); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} + +static zip_source_t * +source_nul(zip_t *za, zip_uint64_t length) +{ + source_nul_t *ctx; + zip_source_t *src; + + if ((ctx = (source_nul_t *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(zip_get_error(za), ZIP_ER_MEMORY, 0); + return NULL; + } + + zip_error_init(&ctx->error); + ctx->length = length; + ctx->offset = 0; + + if ((src = zip_source_function(za, source_nul_cb, ctx)) == NULL) { + free(ctx); + return NULL; + } + + return src; +} + + static int write_memory_src_to_file(const char *archive, zip_source_t *src) { @@ -586,6 +685,7 @@ { "add_dir", 1, "name", "add directory", add_dir }, { "add_file", 4, "name file_to_add offset len", "add file to archive, len bytes starting from offset", add_file }, { "add_from_zip", 5, "name archivename index offset len", "add file from another archive, len bytes starting from offset", add_from_zip }, + { "add_nul", 2, "name length", "add NUL bytes", add_nul }, { "count_extra", 2, "index flags", "show number of extra fields for archive entry", count_extra }, { "count_extra_by_id", 3, "index extra_id flags", "show number of extra fields of type extra_id for archive entry", count_extra_by_id }, { "delete", 1, "index", "remove entry", delete },