#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#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);
fail += do_read(z, NULL, 0, WHEN_OPEN, ZIP_ER_INVAL, 0);
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;
}