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 },