Support setting and querying opsys and external attributes. For newly added files, set operating system to UNIX, permissions to 0666 (0777 for directories).
diff --git a/lib/Makefile.am b/lib/Makefile.am index 5575752..a74f409 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -35,10 +35,12 @@ zip_file_error_clear.c \ zip_file_error_get.c \ zip_file_get_comment.c \ + zip_file_get_external_attributes.c \ zip_file_get_offset.c \ zip_file_rename.c \ zip_file_replace.c \ zip_file_set_comment.c \ + zip_file_set_external_attributes.c \ zip_file_strerror.c \ zip_filerange_crc.c \ zip_fopen.c \
diff --git a/lib/zip.h b/lib/zip.h index 44d0ab8..d9a2b6c 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -177,6 +177,29 @@ #endif #define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */ +#define ZIP_OPSYS_DOS 0x00u +#define ZIP_OPSYS_AMIGA 0x01u +#define ZIP_OPSYS_OPENVMS 0x02u +#define ZIP_OPSYS_UNIX 0x03u +#define ZIP_OPSYS_VM_CMS 0x04u +#define ZIP_OPSYS_ATARI_ST 0x05u +#define ZIP_OPSYS_OS_2 0x06u +#define ZIP_OPSYS_MACINTOSH 0x07u +#define ZIP_OPSYS_Z_SYSTEM 0x08u +#define ZIP_OPSYS_CPM 0x09u +#define ZIP_OPSYS_WINDOWS_NTFS 0x0au +#define ZIP_OPSYS_MVS 0x0bu +#define ZIP_OPSYS_VSE 0x0cu +#define ZIP_OPSYS_ACORN_RISC 0x0du +#define ZIP_OPSYS_VFAT 0x0eu +#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu +#define ZIP_OPSYS_BEOS 0x10u +#define ZIP_OPSYS_TANDEM 0x11u +#define ZIP_OPSYS_OS_400 0x12u +#define ZIP_OPSYS_OS_X 0x13u + +#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX + enum zip_source_cmd { @@ -235,21 +258,32 @@ #endif ZIP_EXTERN int zip_archive_set_tempdir(struct zip *, const char *); -ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t); -ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t); ZIP_EXTERN int zip_close(struct zip *); -ZIP_EXTERN void zip_discard(struct zip *); ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t); -ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); -ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_dir_add(struct zip *, const char *, zip_flags_t); +ZIP_EXTERN void zip_discard(struct zip *); ZIP_EXTERN void zip_error_clear(struct zip *); ZIP_EXTERN void zip_error_get(struct zip *, int *, int *); ZIP_EXTERN int zip_error_get_sys_type(int); ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); ZIP_EXTERN int zip_fclose(struct zip_file *); ZIP_EXTERN struct zip *zip_fdopen(int, int, int *); +ZIP_EXTERN zip_int64_t zip_file_add(struct zip *, const char *, struct zip_source *, zip_flags_t); ZIP_EXTERN void zip_file_error_clear(struct zip_file *); ZIP_EXTERN void zip_file_error_get(struct zip_file *, int *, int *); +ZIP_EXTERN int zip_file_extra_field_delete(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); +ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t); +ZIP_EXTERN int zip_file_get_external_attributes(struct zip *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *); +ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t); +ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t); +ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_external_attributes(struct zip *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); ZIP_EXTERN const char *zip_file_strerror(struct zip_file *); ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, zip_flags_t); ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, zip_flags_t, const char *); @@ -258,23 +292,14 @@ ZIP_EXTERN zip_int64_t zip_fread(struct zip_file *, void *, zip_uint64_t); ZIP_EXTERN const char *zip_get_archive_comment(struct zip *, int *, zip_flags_t); ZIP_EXTERN int zip_get_archive_flag(struct zip *, zip_flags_t, zip_flags_t); -ZIP_EXTERN const char *zip_file_get_comment(struct zip *, zip_uint64_t, zip_uint32_t *, zip_flags_t); -ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); -ZIP_EXTERN const zip_uint8_t *zip_file_extra_field_get_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); -ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(struct zip *, zip_uint64_t, zip_flags_t); -ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(struct zip *, zip_uint64_t, zip_uint16_t, zip_flags_t); ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, zip_flags_t); ZIP_EXTERN zip_int64_t zip_get_num_entries(struct zip *, zip_flags_t); ZIP_EXTERN zip_int64_t zip_name_locate(struct zip *, const char *, zip_flags_t); ZIP_EXTERN struct zip *zip_open(const char *, int, int *); -ZIP_EXTERN int zip_file_rename(struct zip *, zip_uint64_t, const char *, zip_flags_t); -ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t); ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, zip_uint16_t); ZIP_EXTERN int zip_set_archive_flag(struct zip *, zip_flags_t, int); ZIP_EXTERN int zip_set_default_password(struct zip *, const char *); -ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t, zip_int32_t, zip_uint32_t); -ZIP_EXTERN int zip_file_extra_field_set(struct zip *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *, zip_uint64_t, int); ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *, zip_uint64_t, zip_int64_t); ZIP_EXTERN struct zip_source *zip_source_filep(struct zip *, FILE *, zip_uint64_t, zip_int64_t);
diff --git a/lib/zip_dir_add.c b/lib/zip_dir_add.c index 0a74bd6..1a662f4 100644 --- a/lib/zip_dir_add.c +++ b/lib/zip_dir_add.c
@@ -1,6 +1,6 @@ /* zip_dir_add.c -- add directory - Copyright (C) 1999-2012 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2013 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> @@ -46,7 +46,7 @@ zip_dir_add(struct zip *za, const char *name, zip_flags_t flags) { size_t len; - zip_int64_t ret; + zip_int64_t idx; char *s; struct zip_source *source; @@ -78,11 +78,18 @@ return -1; } - ret = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); + idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); free(s); - if (ret < 0) - zip_source_free(source); - return ret; + if (idx < 0) + zip_source_free(source); + else { + if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) { + zip_delete(za, (zip_uint64_t)idx); + return -1; + } + } + + return idx; }
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index 99573a9..77069ae 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c
@@ -260,7 +260,7 @@ de->local_extra_fields_read = 0; de->cloned = 0; - de->version_madeby = 20; + de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8); de->version_needed = 20; /* 2.0 */ de->bitflags = 0; de->comp_method = ZIP_CM_DEFAULT; @@ -273,7 +273,7 @@ de->comment = NULL; de->disk_number = 0; de->int_attrib = 0; - de->ext_attrib = 0; + de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT; de->offset = 0; }
diff --git a/lib/zip_file_get_external_attributes.c b/lib/zip_file_get_external_attributes.c new file mode 100644 index 0000000..f1ad66a --- /dev/null +++ b/lib/zip_file_get_external_attributes.c
@@ -0,0 +1,53 @@ +/* + zip_file_get_external_attributes.c -- get opsys/external attributes + Copyright (C) 2013 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" + +int +zip_file_get_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes) +{ + struct zip_dirent *de; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) + return -1; + + if (opsys) + *opsys = (de->version_madeby >> 8) & 0xff; + + if (attributes) + *attributes = de->ext_attrib; + + return 0; +}
diff --git a/lib/zip_file_set_external_attributes.c b/lib/zip_file_set_external_attributes.c new file mode 100644 index 0000000..0820d6f --- /dev/null +++ b/lib/zip_file_set_external_attributes.c
@@ -0,0 +1,83 @@ +/* + zip_file_set_external_attributes.c -- set external attributes for entry + Copyright (C) 2013 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" + +int +zip_file_set_external_attributes(struct zip *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) +{ + struct zip_entry *e; + int changed; + zip_uint8_t unchanged_opsys; + zip_uint32_t unchanged_attributes; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + _zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + e = za->entry+idx; + + unchanged_opsys = e->orig ? e->orig->version_madeby>>8 : ZIP_OPSYS_DEFAULT; + unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT; + + changed = (opsys != unchanged_opsys || attributes != unchanged_attributes); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + e->changes->version_madeby = (opsys << 8) | (e->changes->version_madeby & 0xff); + e->changes->ext_attrib = attributes; + e->changes->changed |= ZIP_DIRENT_ATTRIBUTES; + } + else if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + e->changes->version_madeby = (unchanged_opsys << 8) | (e->changes->version_madeby & 0xff); + e->changes->ext_attrib = unchanged_attributes; + } + } + + return 0; +}
diff --git a/lib/zipint.h b/lib/zipint.h index c5d0fd4..81c0179 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -157,7 +157,12 @@ #define ZIP_EF_ZIP64 0x0001 #define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64) - + +/* according to unzip-6.0's zipinfo.c, this corresponds to a regular file with rw permissions for everyone */ +#define ZIP_EXT_ATTRIB_DEFAULT 0100666 +/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */ +#define ZIP_EXT_ATTRIB_DEFAULT_DIR 0040777 + /* This section contains API that won't materialize like this. It's placed in the internal section, pending cleanup. */ @@ -302,6 +307,7 @@ #define ZIP_DIRENT_FILENAME 0x0002u #define ZIP_DIRENT_COMMENT 0x0004u #define ZIP_DIRENT_EXTRA_FIELD 0x0008u +#define ZIP_DIRENT_ATTRIBUTES 0x0010u #define ZIP_DIRENT_ALL 0xffffu struct zip_dirent {