| /* |
| fread.c -- test cases for reading from zip archives |
| Copyright (C) 2004-2021 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 "config.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #ifndef HAVE_GETOPT |
| #include "getopt.h" |
| #endif |
| |
| #include "zip.h" |
| |
| enum when { WHEN_NEVER, WHEN_OPEN, WHEN_READ, WHEN_CLOSE }; |
| |
| const char *when_name[] = {"no", "zip_fopen", "zip_fread", "zip_fclose"}; |
| |
| static int do_read(zip_t *z, const char *name, zip_flags_t flags, enum when when_ex, int ze_ex, int se_ex); |
| |
| int verbose; |
| |
| const char *progname; |
| #define USAGE "usage: %s [-v] archive\n" |
| |
| int |
| main(int argc, char *argv[]) { |
| int fail, ze; |
| int c; |
| zip_t *z; |
| zip_source_t *zs; |
| char *archive; |
| zip_int64_t idx; |
| |
| verbose = 0; |
| fail = 0; |
| |
| progname = argv[0]; |
| |
| while ((c = getopt(argc, argv, "v")) != -1) { |
| switch (c) { |
| case 'v': |
| verbose = 1; |
| break; |
| |
| default: |
| fprintf(stderr, USAGE, progname); |
| return 1; |
| } |
| } |
| |
| |
| if (argc - optind != 1) { |
| fprintf(stderr, USAGE, progname); |
| return 1; |
| } |
| |
| archive = argv[optind]; |
| |
| 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", progname, archive, zip_error_strerror(&error)); |
| zip_error_fini(&error); |
| return 1; |
| } |
| |
| fail += do_read(z, "storedok", 0, WHEN_NEVER, 0, 0); |
| fail += do_read(z, "deflateok", 0, WHEN_NEVER, 0, 0); |
| fail += do_read(z, "storedcrcerror", 0, WHEN_READ, ZIP_ER_CRC, 0); |
| fail += do_read(z, "deflatecrcerror", 0, WHEN_READ, ZIP_ER_CRC, 0); |
| fail += do_read(z, "deflatezliberror", 0, WHEN_READ, ZIP_ER_ZLIB, -3); |
| #ifndef __clang_analyzer__ /* This test intentionally violates nullability. */ |
| fail += do_read(z, NULL, 0, WHEN_OPEN, ZIP_ER_INVAL, 0); |
| #endif |
| fail += do_read(z, "nosuchfile", 0, WHEN_OPEN, ZIP_ER_NOENT, 0); |
| fail += do_read(z, "deflatezliberror", ZIP_FL_COMPRESSED, WHEN_NEVER, 0, 0); |
| fail += do_read(z, "deflatecrcerror", ZIP_FL_COMPRESSED, WHEN_NEVER, 0, 0); |
| fail += do_read(z, "storedcrcerror", ZIP_FL_COMPRESSED, WHEN_READ, ZIP_ER_CRC, 0); |
| fail += do_read(z, "storedok", ZIP_FL_COMPRESSED, WHEN_NEVER, 0, 0); |
| |
| fail += do_read(z, "cryptok", 0, WHEN_OPEN, ZIP_ER_NOPASSWD, 0); |
| zip_set_default_password(z, "crypt"); |
| fail += do_read(z, "cryptok", 0, WHEN_NEVER, 0, 0); |
| zip_set_default_password(z, "wrong"); |
| fail += do_read(z, "cryptok", 0, WHEN_OPEN, ZIP_ER_WRONGPASSWD, 0); |
| zip_set_default_password(z, NULL); |
| |
| zs = zip_source_buffer(z, "asdf", 4, 0); |
| if ((idx = zip_name_locate(z, "storedok", 0)) < 0) { |
| fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| fail++; |
| } |
| else { |
| if (zip_replace(z, (zip_uint64_t)idx, zs) < 0) { |
| fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| fail++; |
| } |
| else { |
| fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); |
| fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); |
| } |
| } |
| if ((idx = zip_name_locate(z, "storedok", 0)) < 0) { |
| fprintf(stderr, "%s: can't locate 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| fail++; |
| } |
| else { |
| if (zip_delete(z, (zip_uint64_t)idx) < 0) { |
| fprintf(stderr, "%s: can't replace 'storedok' in zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| fail++; |
| } |
| else { |
| fail += do_read(z, "storedok", 0, WHEN_OPEN, ZIP_ER_NOENT, 0); |
| fail += do_read(z, "storedok", ZIP_FL_UNCHANGED, WHEN_NEVER, 0, 0); |
| } |
| } |
| zs = zip_source_buffer(z, "asdf", 4, 0); |
| if (zip_file_add(z, "new_file", zs, 0) < 0) { |
| fprintf(stderr, "%s: can't add file to zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| fail++; |
| } |
| else { |
| fail += do_read(z, "new_file", 0, WHEN_OPEN, ZIP_ER_CHANGED, 0); |
| } |
| |
| zip_unchange_all(z); |
| if (zip_close(z) == -1) { |
| fprintf(stderr, "%s: can't close zip archive '%s': %s\n", progname, archive, zip_strerror(z)); |
| return 1; |
| } |
| |
| exit(fail ? 1 : 0); |
| } |
| |
| |
| static int |
| do_read(zip_t *z, const char *name, zip_flags_t flags, enum when when_ex, int ze_ex, int se_ex) { |
| zip_file_t *zf; |
| enum when when_got; |
| zip_error_t error_got, error_ex; |
| zip_error_t *zf_error; |
| int err; |
| char b[8192]; |
| zip_int64_t n; |
| |
| when_got = WHEN_NEVER; |
| zip_error_init(&error_got); |
| zip_error_init(&error_ex); |
| zip_error_set(&error_ex, ze_ex, se_ex); |
| |
| if ((zf = zip_fopen(z, name, flags)) == NULL) { |
| when_got = WHEN_OPEN; |
| zf_error = zip_get_error(z); |
| zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error)); |
| } |
| else { |
| while ((n = zip_fread(zf, b, sizeof(b))) > 0) |
| ; |
| if (n < 0) { |
| when_got = WHEN_READ; |
| zf_error = zip_file_get_error(zf); |
| zip_error_set(&error_got, zip_error_code_zip(zf_error), zip_error_code_system(zf_error)); |
| } |
| err = zip_fclose(zf); |
| if (when_got == WHEN_NEVER && err != 0) { |
| when_got = WHEN_CLOSE; |
| zip_error_init_with_code(&error_got, err); |
| } |
| } |
| |
| if (when_got != when_ex || zip_error_code_zip(&error_got) != zip_error_code_zip(&error_ex) || zip_error_code_system(&error_got) != zip_error_code_system(&error_ex)) { |
| printf("%s: %s: got %s error (%s), expected %s error (%s)\n", progname, name, when_name[when_got], zip_error_strerror(&error_got), when_name[when_ex], zip_error_strerror(&error_ex)); |
| zip_error_fini(&error_got); |
| zip_error_fini(&error_ex); |
| return 1; |
| } |
| else if (verbose) |
| printf("%s: %s: passed\n", progname, name); |
| |
| return 0; |
| } |