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 {