VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/libzip/zip_close.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/libzip/zip_close.c')
-rw-r--r--src/Common/libzip/zip_close.c87
1 files changed, 66 insertions, 21 deletions
diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c
index 2a9fed25..816fcefa 100644
--- a/src/Common/libzip/zip_close.c
+++ b/src/Common/libzip/zip_close.c
@@ -36,25 +36,17 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
-static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
+static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
+static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
ZIP_EXTERN int
zip_close(zip_t *za) {
@@ -204,6 +196,7 @@ zip_close(zip_t *za) {
}
if ((off = zip_source_tell_write(za->src)) < 0) {
+ _zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
@@ -221,7 +214,7 @@ zip_close(zip_t *za) {
}
/* add_data writes dirent */
- if (add_data(za, zs ? zs : entry->source, de) < 0) {
+ if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
@@ -233,8 +226,11 @@ zip_close(zip_t *za) {
else {
zip_uint64_t offset;
- /* when copying data, all sizes are known -> no data descriptor needed */
- de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
+ if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
+ /* when copying data, all sizes are known -> no data descriptor needed */
+ /* except for PKWare encryption, where removing the data descriptor breaks password validation */
+ de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
+ }
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
error = 1;
break;
@@ -245,13 +241,20 @@ zip_close(zip_t *za) {
}
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
- error = 1;
+ error = 1;
break;
}
if (copy_data(za, de->comp_size) < 0) {
- error = 1;
+ error = 1;
break;
}
+
+ if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
+ if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
+ error = 1;
+ break;
+ }
+ }
}
}
@@ -282,14 +285,14 @@ zip_close(zip_t *za) {
static int
-add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
+add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
zip_int64_t offstart, offdata, offend, data_length;
- struct zip_stat st;
+ zip_stat_t st;
+ zip_file_attributes_t attributes;
zip_source_t *src_final, *src_tmp;
int ret;
int is_zip64;
zip_flags_t flags;
- zip_int8_t compression_flags;
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (zip_source_stat(src, &st) < 0) {
@@ -453,6 +456,9 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
zip_source_free(src_final);
return -1;
}
+ if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
+ de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
+ }
zip_source_free(src_final);
src_final = src_tmp;
@@ -471,7 +477,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
ret = -1;
}
- if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) {
+ if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
@@ -507,8 +513,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
de->crc = st.crc;
de->uncomp_size = st.size;
de->comp_size = (zip_uint64_t)(offend - offdata);
- de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
- _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
+ _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
@@ -524,6 +529,12 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
return -1;
}
+ if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
+ if (write_data_descriptor(za, de, is_zip64) < 0) {
+ return -1;
+ }
+ }
+
return 0;
}
@@ -656,3 +667,37 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
return changed;
}
+
+static int
+write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
+ zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH);
+ int ret = 0;
+
+ if (buffer == NULL) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+
+ _zip_buffer_put(buffer, DATADES_MAGIC, 4);
+ _zip_buffer_put_32(buffer, de->crc);
+ if (is_zip64) {
+ _zip_buffer_put_64(buffer, de->comp_size);
+ _zip_buffer_put_64(buffer, de->uncomp_size);
+ }
+ else {
+ _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
+ _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
+ }
+
+ if (!_zip_buffer_ok(buffer)) {
+ zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+ ret = -1;
+ }
+ else {
+ ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
+ }
+
+ _zip_buffer_free(buffer);
+
+ return ret;
+}