Implement zip_register_progress_callback(). This function can be used to provide user interface updates during zip_close().
diff --git a/NEWS.md b/NEWS.md index 0555595..7b50aaa 100644 --- a/NEWS.md +++ b/NEWS.md
@@ -6,6 +6,7 @@ * Fix seeking in zip_source_file if start > 0. * Add zip_fseek() for seeking in uncompressed data. * Add zip_ftell() for telling position in uncompressed data. +* Add zip_register_progress_callback() for UI updates during zip_close() 1.1.3 [2016-05-28] ==================
diff --git a/TODO.md b/TODO.md index 902ac6b..551437f 100644 --- a/TODO.md +++ b/TODO.md
@@ -1,11 +1,5 @@ # API Plans -## Encryption - -````c -int zip_file_set_encryption(struct zip *archive, zip_uint64_t idx, zip_uint16_t method, const char *password); -```` - ## Prefixes For example for adding extractors for self-extracting zip archives. @@ -14,15 +8,6 @@ const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp); ```` -## Progress Callback - -Register callback; will be called from `zip_close()` after each file has been processed. - -````c -typedef void (*zip_progress_callback_t)(double); -void zip_register_progress_callback(zip_t *, zip_progress_callback_t); -```` - # API Issues * `zip_get_archive_comment` has `int *lenp` argument. Cleaner would be `zip_uint32_t *`. @@ -31,6 +16,7 @@ * compression/crypt implementations: how to set error code on failure * compression/crypt error messages a la `ZIP_ER_ZLIB` (no detailed info passing) * check arguments for every entry point into libzip +* remove unused `zip_archive_set_tempdir()` # Features
diff --git a/lib/zip.h b/lib/zip.h index 97f01e5..0e71a55 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -307,6 +307,7 @@ typedef zip_uint32_t zip_flags_t; typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t); +typedef void (*zip_progress_callback_t)(double); #ifndef ZIP_DISABLE_DEPRECATED @@ -376,6 +377,7 @@ ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t); ZIP_EXTERN zip_t *zip_open(const char *, int, int *); ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *); +ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t); ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int); ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
diff --git a/lib/zip_close.c b/lib/zip_close.c index fd5a107..15e2a2f 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c
@@ -131,6 +131,10 @@ zip_entry_t *entry; zip_dirent_t *de; + if (za->progress_callback) { + za->progress_callback((double)j/survivors); + } + i = filelist[j].idx; entry = za->entry+i; @@ -222,6 +226,10 @@ return -1; } + if (za->progress_callback) { + za->progress_callback(1); + } + zip_discard(za); return 0;
diff --git a/lib/zip_new.c b/lib/zip_new.c index 562dd76..08a384e 100644 --- a/lib/zip_new.c +++ b/lib/zip_new.c
@@ -69,6 +69,7 @@ za->nopen_source = za->nopen_source_alloc = 0; za->open_source = NULL; za->tempdir = NULL; + za->progress_callback = NULL; return za; }
diff --git a/lib/zip_open.c b/lib/zip_open.c index ff84a83..38aee49 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c
@@ -177,6 +177,14 @@ return 0; } + +ZIP_EXTERN void +zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) +{ + za->progress_callback = progress_callback; +} + + zip_t * _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
diff --git a/lib/zipint.h b/lib/zipint.h index 6d16caf..1242fe2 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -200,6 +200,7 @@ zip_hash_t *names; /* hash table for name lookup */ char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */ + zip_progress_callback_t progress_callback; /* progress callback for zip_close() */ }; /* file in zip archive, part of API */
diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index 9f893f5..4934f8b 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt
@@ -48,6 +48,7 @@ zip_get_num_files.mdoc zip_name_locate.mdoc zip_open.mdoc + zip_register_progress_callback.mdoc zip_rename.mdoc zip_set_archive_comment.mdoc zip_set_archive_flag.mdoc
diff --git a/man/Makefile.am b/man/Makefile.am index 4e0cc8e..f8fac8e 100644 --- a/man/Makefile.am +++ b/man/Makefile.am
@@ -59,6 +59,7 @@ zip_name_locate.mdoc \ zip_open.mdoc \ zip_rename.mdoc \ + zip_register_progress_callback.mdoc zip_set_archive_comment.mdoc \ zip_set_archive_flag.mdoc \ zip_set_default_password.mdoc \
diff --git a/man/libzip.mdoc b/man/libzip.mdoc index 8640b55..db9d206 100644 --- a/man/libzip.mdoc +++ b/man/libzip.mdoc
@@ -128,6 +128,7 @@ .Ss close archive .Xr zip_close 3 .Ss miscellaneous +.Xr zip_register_progress_callback 3 .Xr zip_set_archive_comment 3 .Xr zip_set_archive_flag 3 .Xr zip_source 3
diff --git a/man/zip_register_progress_callback.mdoc b/man/zip_register_progress_callback.mdoc new file mode 100644 index 0000000..25da988 --- /dev/null +++ b/man/zip_register_progress_callback.mdoc
@@ -0,0 +1,66 @@ +.\" zip_register_progress_callback.mdoc -- provide updates during zip_close +.\" Copyright (C) 2016 Dieter Baron and Thomas Klausner +.\" +.\" This file is part of libzip, a library to manipulate ZIP archives. +.\" The authors can be contacted at <libzip@nih.at> +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in +.\" the documentation and/or other materials provided with the +.\" distribution. +.\" 3. The names of the authors may not be used to endorse or promote +.\" products derived from this software without specific prior +.\" written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 18, 2016 +.Dt ZIP_REGISTER_PROGRESS_CALLBACK 3 +.Os +.Sh NAME +.Nm zip_register_progress_callback +.Nd provide updates during zip_close +.Sh LIBRARY +libzip (-lzip) +.Sh SYNOPSIS +.In zip.h +.Vt typedef void (*zip_progress_callback_t)(double); +.Ft void +.Fn zip_register_progress_callback "zip_t *archive" "zip_progress_callback_t progress_callback" +.Sh DESCRIPTION +The +.Fn zip_register_progress_callback +function registers a callback function +.Ar progress_callback +for the zip archive +.Ar archive . +This function is called during +.Xr zip_close 3 +after every zip archive entry that's completely written to disk. +The value is a +.Vt double +in the range from 0.0 to 1.0. +This can be used to provide progress indicators for user interfaces. +.Sh SEE ALSO +.Xr libzip 3 , +.Xr zip_close 3 +.Sh AUTHORS +.An -nosplit +.An Dieter Baron Aq Mt dillo@nih.at +and +.An Thomas Klausner Aq Mt tk@giga.or.at
diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt index 155bb4f..840cb77 100644 --- a/regress/CMakeLists.txt +++ b/regress/CMakeLists.txt
@@ -85,6 +85,7 @@ open_truncate.test open_zip64_3mf.test open_zip64_ok.test + progress.test rename_ascii.test rename_cp437.test rename_deleted.test
diff --git a/regress/Makefile.am b/regress/Makefile.am index edd9da3..2352c13 100644 --- a/regress/Makefile.am +++ b/regress/Makefile.am
@@ -206,6 +206,7 @@ open_truncate.test \ open_zip64_3mf.test \ open_zip64_ok.test \ + progress.test \ rename_ascii.test \ rename_cp437.test \ rename_deleted.test \
diff --git a/regress/progress.test b/regress/progress.test new file mode 100644 index 0000000..8604db2 --- /dev/null +++ b/regress/progress.test
@@ -0,0 +1,10 @@ +# test default compression stores if smaller; print progress +return 0 +args -n test.zip print_progress add compressable aaaaaaaaaaaaaa add uncompressable uncompressable add_nul large-compressable 8200 add_file large-uncompressable large-uncompressable 0 -1 +file-new test.zip cm-default.zip +file large-uncompressable large-uncompressable large-uncompressable +stdout 0.0% done +stdout 25.0% done +stdout 50.0% done +stdout 75.0% done +stdout 100.0% done
diff --git a/src/ziptool.c b/src/ziptool.c index f7c2704..91310b5 100644 --- a/src/ziptool.c +++ b/src/ziptool.c
@@ -401,6 +401,17 @@ return 0; } +static void +progress_callback(double percentage) { + printf("%.1lf%% done\n", percentage*100); +} + +static int +print_progress(int argc, char *argv[]) { + zip_register_progress_callback(za, progress_callback); + return 0; +} + static int zrename(int argc, char *argv[]) { zip_uint64_t idx; @@ -931,6 +942,7 @@ { "get_file_comment", 1, "index", "get file comment", get_file_comment }, { "get_num_entries", 1, "flags", "get number of entries in archive", get_num_entries }, { "name_locate", 2, "name flags", "find entry in archive", name_locate }, + { "print_progress", 0, "", "print progress during zip_close()", print_progress }, { "rename", 2, "index name", "rename entry", zrename }, { "replace_file_contents", 2, "index data", "replace entry with data", replace_file_contents }, { "set_archive_comment", 1, "comment", "set archive comment", set_archive_comment },