static zip_flags_t get_flags(const char *arg);
static zip_int32_t get_compression_method(const char *arg);
+static zip_uint16_t get_encryption_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_t *read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp);
static zip_source_t *source_nul(zip_t *za, zip_uint64_t length);
zip_t *za, *z_in[16];
}
}
if (n == -1) {
- zip_fclose(zf);
fprintf(stderr, "can't read file at index '%" PRIu64 "': %s\n", idx, zip_file_strerror(zf));
+ zip_fclose(zf);
return -1;
}
if ((err = zip_fclose(zf)) != 0) {
eid = (zip_uint16_t)strtoull(argv[1], NULL, 10);
ceflags = get_flags(argv[2]);
if ((count=zip_file_extra_fields_count_by_id(za, idx, eid, ceflags)) < 0) {
- fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "' and for id `%d': %s\n", idx, eid, zip_strerror(za));
+ fprintf(stderr, "can't get extra field count for file at index '%" PRIu64 "' and for id '%d': %s\n", idx, eid, zip_strerror(za));
return -1;
} else {
printf("Extra field count: %d\n", count);
eid = (zip_uint16_t)strtoull(argv[1], NULL, 10);
geflags = get_flags(argv[2]);
if ((zip_file_extra_field_delete(za, idx, eid, geflags)) < 0) {
- fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id `%d': %s\n", idx, eid, zip_strerror(za));
+ fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d': %s\n", idx, eid, zip_strerror(za));
return -1;
}
return 0;
eidx = (zip_uint16_t)strtoull(argv[2], NULL, 10);
geflags = get_flags(argv[3]);
if ((zip_file_extra_field_delete_by_id(za, idx, eid, eidx, geflags)) < 0) {
- fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id `%d', extra field idx `%d': %s\n", idx, eid, eidx, zip_strerror(za));
+ fprintf(stderr, "can't delete extra field data for file at index '%" PRIu64 "', extra field id '%d', extra field idx '%d': %s\n", idx, eid, eidx, zip_strerror(za));
return -1;
}
return 0;
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;
idx = strtoull(argv[0], NULL, 10);
if (zip_rename(za, idx, argv[1]) < 0) {
- fprintf(stderr, "can't rename file at index '%" PRIu64 "' to `%s': %s\n", idx, argv[1], zip_strerror(za));
+ fprintf(stderr, "can't rename file at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
return -1;
}
return 0;
geflags = get_flags(argv[3]);
efdata = (zip_uint8_t *)argv[4];
if ((zip_file_extra_field_set(za, idx, eid, eidx, efdata, (zip_uint16_t)strlen((const char *)efdata), geflags)) < 0) {
- fprintf(stderr, "can't set extra field data for file at index '%" PRIu64 "', extra field id `%d', index `%d': %s\n", idx, eid, eidx, zip_strerror(za));
+ fprintf(stderr, "can't set extra field data for file at index '%" PRIu64 "', extra field id '%d', index '%d': %s\n", idx, eid, eidx, zip_strerror(za));
return -1;
}
return 0;
static int
set_archive_comment(int argc, char *argv[]) {
if (zip_set_archive_comment(za, argv[0], (zip_uint16_t)strlen(argv[0])) < 0) {
- fprintf(stderr, "can't set archive comment to `%s': %s\n", argv[0], zip_strerror(za));
+ fprintf(stderr, "can't set archive comment to '%s': %s\n", argv[0], zip_strerror(za));
return -1;
}
return 0;
zip_uint64_t idx;
idx = strtoull(argv[0], NULL, 10);
if (zip_file_set_comment(za, idx, argv[1], (zip_uint16_t)strlen(argv[1]), 0) < 0) {
- fprintf(stderr, "can't set file comment at index '%" PRIu64 "' to `%s': %s\n", idx, argv[1], zip_strerror(za));
+ fprintf(stderr, "can't set file comment at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
return -1;
}
return 0;
method = get_compression_method(argv[1]);
flags = (zip_uint32_t)strtoull(argv[2], NULL, 10);
if (zip_set_file_compression(za, idx, method, flags) < 0) {
- fprintf(stderr, "can't set file compression method at index '%" PRIu64 "' to `%s', flags `%d': %s\n", idx, argv[1], flags, zip_strerror(za));
+ fprintf(stderr, "can't set file compression method at index '%" PRIu64 "' to '%s', flags '%d': %s\n", idx, argv[1], flags, zip_strerror(za));
+ return -1;
+ }
+ return 0;
+}
+
+static int
+set_file_encryption(int argc, char *argv[]) {
+ zip_int32_t method;
+ zip_uint64_t idx;
+ char *password;
+ idx = strtoull(argv[0], NULL, 10);
+ method = get_encryption_method(argv[1]);
+ password = argv[2];
+ if (strlen(password) == 0) {
+ password = NULL;
+ }
+ if (zip_file_set_encryption(za, idx, method, password) < 0) {
+ fprintf(stderr, "can't set file encryption method at index '%" PRIu64 "' to '%s': %s\n", idx, argv[1], zip_strerror(za));
return -1;
}
return 0;
idx = strtoull(argv[0], NULL, 10);
mtime = (time_t)strtoull(argv[1], NULL, 10);
if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
- fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to `%ld': %s\n", idx, mtime, zip_strerror(za));
+ fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%ld': %s\n", idx, mtime, zip_strerror(za));
return -1;
}
return 0;
zip_int64_t num_entries;
zip_uint64_t idx;
mtime = (time_t)strtoull(argv[0], NULL, 10);
-
+
if ((num_entries = zip_get_num_entries(za, 0)) < 0) {
fprintf(stderr, "can't get number of entries: %s\n", zip_strerror(za));
return -1;
}
for (idx = 0; idx < (zip_uint64_t)num_entries; idx++) {
if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
- fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to `%ld': %s\n", idx, mtime, zip_strerror(za));
+ fprintf(stderr, "can't set file mtime at index '%" PRIu64 "' to '%ld': %s\n", idx, mtime, zip_strerror(za));
return -1;
}
}
set_password(int argc, char *argv[]) {
/* set default password */
if (zip_set_default_password(za, argv[0]) < 0) {
- fprintf(stderr, "can't set default password to `%s'", argv[0]);
+ fprintf(stderr, "can't set default password to '%s'\n", argv[0]);
return -1;
}
return 0;
return ZIP_CM_DEFAULT;
else if (strcmp(arg, "store") == 0)
return ZIP_CM_STORE;
- else if (strcmp(arg, "deflate") ==0)
+ else if (strcmp(arg, "deflate") == 0)
return ZIP_CM_DEFLATE;
- else if (strcmp(arg, "unknown") ==0)
- return 99;
+ else if (strcmp(arg, "unknown") == 0)
+ return 100;
return 0; /* TODO: error handling */
}
+static zip_uint16_t
+get_encryption_method(const char *arg)
+{
+ if (strcmp(arg, "none") == 0)
+ return ZIP_EM_NONE;
+ else if (strcmp(arg, "AES-128") == 0)
+ return ZIP_EM_AES_128;
+ else if (strcmp(arg, "AES-192") == 0)
+ return ZIP_EM_AES_192;
+ else if (strcmp(arg, "AES-256") == 0)
+ return ZIP_EM_AES_256;
+ else if (strcmp(arg, "unknown") == 0)
+ return 100;
+ return (zip_uint16_t)-1; /* TODO: error handling */
+}
+
static void
hexdump(const zip_uint8_t *data, zip_uint16_t len)
{
static zip_t *
-read_hole(const char *archive, int flags, int *err)
+read_from_file(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t length)
+{
+ zip_t *zaa;
+ zip_source_t *source;
+ int err;
+
+ if (offset == 0 && length == 0) {
+ if ((zaa = zip_open(archive, flags, &err)) == NULL) {
+ zip_error_set(error, err, errno);
+ return NULL;
+ }
+ }
+ else {
+ if (length > ZIP_INT64_MAX) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
+ }
+ if ((source = zip_source_file_create(archive, offset, (zip_int64_t)length, error)) == NULL
+ || (zaa = zip_open_from_source(source, flags, error)) == NULL) {
+ zip_source_free(source);
+ return NULL;
+ }
+ }
+
+ return zaa;
+}
+
+
+static zip_t *
+read_hole(const char *archive, int flags, zip_error_t *error)
{
- zip_error_t error;
zip_source_t *src = NULL;
zip_t *zs = NULL;
- zip_error_init(&error);
-
- if ((src = source_hole_create(archive, flags, &error)) == NULL
- || (zs = zip_open_from_source(src, flags, &error)) == NULL) {
+ if ((src = source_hole_create(archive, flags, error)) == NULL
+ || (zs = zip_open_from_source(src, flags, error)) == NULL) {
zip_source_free(src);
- *err = zip_error_code_zip(&error);
- errno = zip_error_code_system(&error);
}
return zs;
static zip_t *
-read_to_memory(const char *archive, int flags, int *err, zip_source_t **srcp)
+read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp)
{
struct stat st;
zip_source_t *src;
zip_t *zb;
- zip_error_t error;
if (stat(archive, &st) < 0) {
if (errno == ENOENT) {
- src = zip_source_buffer_create(NULL, 0, 0, &error);
+ src = zip_source_buffer_create(NULL, 0, 0, error);
}
else {
- *err = ZIP_ER_OPEN;
+ zip_error_set(error, ZIP_ER_OPEN, errno);
return NULL;
}
}
char *buf;
FILE *fp;
if ((buf=malloc((size_t)st.st_size)) == NULL) {
- *err = ZIP_ER_MEMORY;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if ((fp=fopen(archive, "r")) == NULL) {
free(buf);
- *err = ZIP_ER_READ;
+ zip_error_set(error, ZIP_ER_READ, errno);
return NULL;
}
if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
free(buf);
fclose(fp);
- *err = ZIP_ER_READ;
+ zip_error_set(error, ZIP_ER_READ, errno);
return NULL;
}
fclose(fp);
- src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, &error);
+ src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
if (src == NULL) {
free(buf);
}
}
if (src == NULL) {
- *err = zip_error_code_zip(&error);
- errno = zip_error_code_system(&error);
return NULL;
}
- zb = zip_open_from_source(src, flags, &error);
+ zb = zip_open_from_source(src, flags, error);
if (zb == NULL) {
- *err = zip_error_code_zip(&error);
- errno = zip_error_code_system(&error);
zip_source_free(src);
return NULL;
}
{ "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 },
{ "set_extra", 5, "index extra_id extra_index flags value", "set extra field", set_extra },
{ "set_file_comment", 2, "index comment", "set file comment", set_file_comment },
{ "set_file_compression", 3, "index method compression_flags", "set file compression method", set_file_compression },
+ { "set_file_encryption", 3, "index method password", "set file encryption method", set_file_encryption },
{ "set_file_mtime", 2, "index timestamp", "set file modification time", set_file_mtime },
{ "set_file_mtime_all", 1, "timestamp", "set file modification time for all files", set_file_mtime_all },
{ "set_password", 1, "password", "set default password for encryption", set_password },
out = stdout;
else
out = stderr;
- fprintf(out, "usage: %s [-cegHhmnrst] archive command1 [args] [command2 [args] ...]\n", progname);
+ fprintf(out, "usage: %s [-cegHhmnrst] [-l len] [-o offset] archive command1 [args] [command2 [args] ...]\n", progname);
if (reason != NULL) {
fprintf(out, "%s\n", reason);
exit(1);
}
fprintf(out, "\nSupported options are:\n"
- "\t-c\tcheck consistency\n"
- "\t-e\terror if archive already exists (only useful with -n)\n"
- "\t-g\tguess file name encoding (for stat)\n"
- "\t-H\twrite files with holes compactly\n"
- "\t-h\tdisplay this usage\n"
- "\t-m\tread archive into memory, and modify there; write out at end\n"
- "\t-n\tcreate archive if it doesn't exist\n"
- "\t-r\tprint raw file name encoding without translation (for stat)\n"
- "\t-s\tfollow file name convention strictly (for stat)\n"
- "\t-t\tdisregard current archive contents, if any\n");
+ "\t-c\t\tcheck consistency\n"
+ "\t-e\t\terror if archive already exists (only useful with -n)\n"
+ "\t-g\t\tguess file name encoding (for stat)\n"
+ "\t-H\t\twrite files with holes compactly\n"
+ "\t-h\t\tdisplay this usage\n"
+ "\t-l len\t\tonly use len bytes of file\n"
+ "\t-m\t\tread archive into memory, and modify there; write out at end\n"
+ "\t-n\t\tcreate archive if it doesn't exist\n"
+ "\t-o offset\tstart reading file at offset\n"
+ "\t-r\t\tprint raw file name encoding without translation (for stat)\n"
+ "\t-s\t\tfollow file name convention strictly (for stat)\n"
+ "\t-t\t\tdisregard current archive contents, if any\n");
fprintf(out, "\nSupported commands and arguments are:\n");
for (i=0; i<sizeof(dispatch_table)/sizeof(dispatch_table_t); i++) {
fprintf(out, "\t%s %s\n\t %s\n\n", dispatch_table[i].cmdline_name, dispatch_table[i].arg_names, dispatch_table[i].description);
}
fprintf(out, "\nSupported flags are:\n"
+ "\t0\t(no flags)\n"
"\tC\tZIP_FL_NOCASE\n"
"\tc\tZIP_FL_CENTRAL\n"
"\td\tZIP_FL_NODIR\n"
"\tdefault\n"
"\tdeflate\n"
"\tstore\n");
+ fprintf(out, "\nSupported compression methods are:\n"
+ "\tnone\n"
+ "\tAES-128\n"
+ "\tAES-192\n"
+ "\tAES-256\n");
fprintf(out, "\nThe index is zero-based.\n");
exit(0);
}
int c, arg, err, flags;
const char *prg;
source_type_t source_type = SOURCE_TYPE_NONE;
+ zip_uint64_t len = 0, offset = 0;
+ zip_error_t error;
flags = 0;
prg = argv[0];
- if (argc < 2)
- usage(prg, "too few arguments");
-
- while ((c=getopt(argc, argv, "cegHhmnrst")) != -1) {
+ while ((c=getopt(argc, argv, "cegHhl:mno:rst")) != -1) {
switch (c) {
case 'c':
flags |= ZIP_CHECKCONS;
case 'h':
usage(prg, NULL);
break;
+ case 'l':
+ len = strtoull(optarg, NULL, 10);
+ break;
case 'm':
source_type = SOURCE_TYPE_IN_MEMORY;
break;
case 'n':
flags |= ZIP_CREATE;
break;
+ case 'o':
+ offset = strtoull(optarg, NULL, 10);
+ break;
case 'r':
stat_flags = ZIP_FL_ENC_RAW;
break;
}
}
+ if (optind >= argc-1)
+ usage(prg, "too few arguments");
+
arg = optind;
archive = argv[arg++];
if (flags == 0)
flags = ZIP_CREATE;
+ zip_error_init(&error);
switch (source_type) {
- case SOURCE_TYPE_NONE:
- za = zip_open(archive, flags, &err);
- break;
+ case SOURCE_TYPE_NONE:
+ za = read_from_file(archive, flags, &error, offset, len);
+ break;
case SOURCE_TYPE_IN_MEMORY:
- za = read_to_memory(archive, flags, &err, &memory_src);
+ za = read_to_memory(archive, flags, &error, &memory_src);
break;
- case SOURCE_TYPE_HOLE: {
- za = read_hole(archive, flags, &err);
+ case SOURCE_TYPE_HOLE:
+ za = read_hole(archive, flags, &error);
break;
- }
}
if (za == NULL) {
- zip_error_t error;
- zip_error_init_with_code(&error, err);
fprintf(stderr, "can't open zip archive '%s': %s\n", archive, zip_error_strerror(&error));
zip_error_fini(&error);
return 1;
}
+ zip_error_fini(&error);
err = 0;
while (arg < argc) {