Add zip_fseek function that allows seeking in uncompressed file data. Add three test cases for it.
diff --git a/.hgignore b/.hgignore index f93664e..8eed2a2 100644 --- a/.hgignore +++ b/.hgignore
@@ -40,6 +40,7 @@ ^regress/bigzero.zip$ ^regress/fopen_unchanged$ ^regress/fread$ +^regress/fseek$ ^regress/manyfiles.zip$ ^regress/manyfiles-133000.zip$ ^regress/manyfiles-65536.zip$
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index feebb62..cfd47f3 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt
@@ -92,6 +92,7 @@ zip_fopen_index.c zip_fopen_index_encrypted.c zip_fread.c + zip_fseek.c zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c
diff --git a/lib/Makefile.am b/lib/Makefile.am index bc9cb03..5e78f28 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -62,6 +62,7 @@ zip_fopen_index.c \ zip_fopen_index_encrypted.c \ zip_fread.c \ + zip_fseek.c \ zip_get_archive_comment.c \ zip_get_archive_flag.c \ zip_get_compression_implementation.c \
diff --git a/lib/zip.h b/lib/zip.h index 27141b3..96ba17c 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -361,6 +361,7 @@ ZIP_EXTERN zip_file_t *zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t); ZIP_EXTERN zip_file_t *zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *); ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t); +ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int); ZIP_EXTERN const char *zip_get_archive_comment(zip_t *, int *, zip_flags_t); ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t); ZIP_EXTERN const char *zip_get_name(zip_t *, zip_uint64_t, zip_flags_t); @@ -377,7 +378,7 @@ ZIP_EXTERN zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); ZIP_EXTERN int zip_source_close(zip_source_t *); ZIP_EXTERN int zip_source_commit_write(zip_source_t *); -ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *src); +ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *); ZIP_EXTERN zip_source_t *zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t); ZIP_EXTERN zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); ZIP_EXTERN zip_source_t *zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
diff --git a/lib/zip_fseek.c b/lib/zip_fseek.c new file mode 100644 index 0000000..83d40dd --- /dev/null +++ b/lib/zip_fseek.c
@@ -0,0 +1,64 @@ +/* + zip_fseek.c -- seek in file + 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. +*/ + + +#include "zipint.h" +#include <stdio.h> + +ZIP_EXTERN zip_int8_t +zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) +{ + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) { + zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((zip_source_supports(zf->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { + zip_error_set(&zf->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (zip_source_seek(zf->src, offset, whence) < 0) { + _zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return 0; +}
diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index b1d3480..a8a8e3d 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt
@@ -35,6 +35,7 @@ zip_fopen.mdoc zip_fopen_encrypted.mdoc zip_fread.mdoc + zip_fseek.mdoc zip_get_archive_comment.mdoc zip_get_archive_flag.mdoc zip_get_error.mdoc
diff --git a/man/Makefile.am b/man/Makefile.am index 9967b4b..418a906 100644 --- a/man/Makefile.am +++ b/man/Makefile.am
@@ -46,6 +46,7 @@ zip_fopen.mdoc \ zip_fopen_encrypted.mdoc \ zip_fread.mdoc \ + zip_fseek.mdoc \ zip_get_archive_comment.mdoc \ zip_get_archive_flag.mdoc \ zip_get_error.mdoc \
diff --git a/man/zip_fclose.mdoc b/man/zip_fclose.mdoc index 07d3035..5417ff0 100644 --- a/man/zip_fclose.mdoc +++ b/man/zip_fclose.mdoc
@@ -29,7 +29,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 3, 2003 +.Dd September 12, 2016 .Dt ZIP_FCLOSE 3 .Os .Sh NAME @@ -53,7 +53,8 @@ .Sh SEE ALSO .Xr libzip 3 , .Xr zip_fopen 3 , -.Xr zip_fread 3 +.Xr zip_fread 3 , +.Xr zip_fseek 3 .Sh AUTHORS .An -nosplit .An Dieter Baron Aq Mt dillo@nih.at
diff --git a/man/zip_fopen.mdoc b/man/zip_fopen.mdoc index 4f8371a..caa9057 100644 --- a/man/zip_fopen.mdoc +++ b/man/zip_fopen.mdoc
@@ -29,7 +29,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 23, 2013 +.Dd September 12, 2016 .Dt ZIP_FOPEN 3 .Os .Sh NAME @@ -131,6 +131,7 @@ .Xr libzip 3 , .Xr zip_fclose 3 , .Xr zip_fread 3 , +.Xr zip_fseek 3 , .Xr zip_get_num_entries 3 , .Xr zip_name_locate 3 , .Xr zip_set_default_password 3
diff --git a/man/zip_fread.mdoc b/man/zip_fread.mdoc index e582ffa..140b657 100644 --- a/man/zip_fread.mdoc +++ b/man/zip_fread.mdoc
@@ -29,7 +29,7 @@ .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN .\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 10, 2009 +.Dd September 12, 2016 .Dt ZIP_FREAD 3 .Os .Sh NAME @@ -56,6 +56,7 @@ .Sh SEE ALSO .Xr libzip 3 , .Xr zip_fclose 3 , +.Xr zip_fseek 3 , .Xr zip_fopen 3 .Sh AUTHORS .An -nosplit
diff --git a/man/zip_fseek.mdoc b/man/zip_fseek.mdoc new file mode 100644 index 0000000..5ca87d1 --- /dev/null +++ b/man/zip_fseek.mdoc
@@ -0,0 +1,71 @@ +.\" zip_fseek.mdoc -- seek in file +.\" 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 September 12, 2016 +.Dt ZIP_FSEEK 3 +.Os +.Sh NAME +.Nm zip_fseek +.Nd seek in file +.Sh LIBRARY +libzip (-lzip) +.Sh SYNOPSIS +.In zip.h +.Ft zip_int8_t +.Fn zip_fseek "zip_file_t *file" "zip_int64_t offset" "int whence" +.Sh DESCRIPTION +The +.Fn zip_fseek +function seeks to the specified +.Ar offset +relative to +.Ar whence , +just like +.Xr fseek 3 . +.Pp +.Nm +only works on uncompressed (stored) data. +When called on compressed data it will return an error. +.Sh RETURN VALUES +If successful, +.Nm +returns 0. +Otherwise, \-1 is returned. +.Sh SEE ALSO +.Xr libzip 3 , +.Xr zip_fclose 3 , +.Xr zip_fread 3 , +.Xr zip_fopen 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 332530f..155bb4f 100644 --- a/regress/CMakeLists.txt +++ b/regress/CMakeLists.txt
@@ -10,7 +10,7 @@ SET(STANDALONE_TEST_PROGRAMS add_from_filep fopen_unchanged -# fread + fseek ) SET(HELPER_TEST_PROGRAMS @@ -63,6 +63,9 @@ file_comment_encmismatch.test fopen_unchanged.test fread.test + fseek_deflated.test + fseek_fail.test + fseek_ok.test get_comment.test name_locate.test open_cons_extrabytes.test
diff --git a/regress/Makefile.am b/regress/Makefile.am index 9ba5276..8c79e55 100644 --- a/regress/Makefile.am +++ b/regress/Makefile.am
@@ -6,6 +6,7 @@ add_from_filep \ fopen_unchanged \ fread \ + fseek \ tryopen pkglib_LTLIBRARIES= malloc.la @@ -176,6 +177,9 @@ file_comment_encmismatch.test \ fopen_unchanged.test \ fread.test \ + fseek_deflated.test \ + fseek_fail.test \ + fseek_ok.test \ get_comment.test \ junk_at_end.test \ junk_at_start.test \
diff --git a/regress/fseek.c b/regress/fseek.c new file mode 100644 index 0000000..d2d132d --- /dev/null +++ b/regress/fseek.c
@@ -0,0 +1,97 @@ +/* + fseek.c -- test tool for seeking in zip archives + 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. +*/ + +#include <stdlib.h> + +#include "zip.h" + +const char *prg; +#define USAGE "usage: %s archive index offset\n" + +int +main(int argc, char *argv[]) +{ + int ze; + zip_t *z; + zip_file_t *zf; + char *archive; + zip_int64_t index, offset, n; + char b[1024]; + + prg = argv[0]; + + if (argc != 4) { + fprintf(stderr, USAGE, prg); + return 1; + } + + archive = argv[1]; + index = strtoull(argv[2], NULL, 10); + offset = strtoull(argv[3], NULL, 10); + + if ((z=zip_open(archive, 0, &ze)) == NULL) { + zip_error_t error; + zip_error_init_with_code(&error, ze); + fprintf(stderr, "%s: can't open zip archive '%s': %s\n", prg, archive, zip_error_strerror(&error)); + zip_error_fini(&error); + return 1; + } + + if ((zf=zip_fopen_index(z, index, 0)) == NULL) { + fprintf(stderr, "%s: can't open file in archive '%s': %s\n", prg, archive, zip_error_strerror(zip_file_get_error(zf))); + zip_close(z); + return 1; + } + + if (zip_fseek(zf, offset, SEEK_SET) < 0) { + fprintf(stderr, "%s: zip_fseek failed: %s\n", prg, zip_error_strerror(zip_file_get_error(zf))); + zip_close(z); + return 1; + } + + while ((n=zip_fread(zf, b, sizeof(b))) > 0) { + printf("%.*s", n, b); + } + if (n < 0) { + fprintf(stderr, "%s: zip_fread failed: %s\n", prg, zip_error_strerror(zip_file_get_error(zf))); + zip_close(z); + return 1; + } + + if (zip_close(z) == -1) { + fprintf(stderr, "%s: can't close zip archive '%s': %s\n", prg, archive, zip_strerror(z)); + return 1; + } + + return 0; +}
diff --git a/regress/fseek_deflated.test b/regress/fseek_deflated.test new file mode 100644 index 0000000..7c560af --- /dev/null +++ b/regress/fseek_deflated.test
@@ -0,0 +1,6 @@ +# unsuccessful fseek test because data is compressed +program fseek +args test.zip 0 2 +return 1 +file test.zip testdeflated.zip testdeflated.zip +stderr zip_fseek failed: Operation not supported
diff --git a/regress/fseek_fail.test b/regress/fseek_fail.test new file mode 100644 index 0000000..be78a9a --- /dev/null +++ b/regress/fseek_fail.test
@@ -0,0 +1,6 @@ +# successful fseek test +program fseek +args test.zip 0 8 +return 1 +file test.zip test.zip test.zip +stderr zip_fseek failed: Invalid argument
diff --git a/regress/fseek_ok.test b/regress/fseek_ok.test new file mode 100644 index 0000000..29cfe67 --- /dev/null +++ b/regress/fseek_ok.test
@@ -0,0 +1,6 @@ +# successful fseek test +program fseek +args test.zip 0 2 +return 0 +file test.zip test.zip test.zip +stdout st