diff --git a/lib/zip_close.c b/lib/zip_close.c index bb75ca6d6..d0e3ba8a1 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c @@ -471,7 +471,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { zip_stat_t st_mtime; zip_stat_init(&st_mtime); st_mtime.valid = ZIP_STAT_MTIME; - st_mtime.mtime = de->last_mod; + st_mtime.mtime = _zip_d2u_time(de->last_mod_time, de->last_mod_date); if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, 0, NULL, NULL, 0, true, &za->error)) == NULL) { zip_source_free(src_final); return -1; @@ -529,10 +529,16 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { } if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { - if (st.valid & ZIP_STAT_MTIME) - de->last_mod = st.mtime; - else - time(&de->last_mod); + time_t mtime; + if (st.valid & ZIP_STAT_MTIME) { + mtime = st.mtime; + } + else { + time(&mtime); + } + if (_zip_u2d_time(st.mtime, &de->last_mod_time, &de->last_mod_date, &za->error) < 0) { + return -1; + } } de->comp_method = st.comp_method; de->crc = st.crc; @@ -748,4 +754,4 @@ static int torrentzip_compare_names(const void *a, const void *b) { } return strcasecmp(aname, bname); -} \ No newline at end of file +} diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index 419ed64bd..57efcaa87 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c @@ -39,6 +39,7 @@ #include #include +#include "zip.h" #include "zipint.h" static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str); @@ -289,7 +290,8 @@ _zip_dirent_init(zip_dirent_t *de) { de->version_needed = 10; /* 1.0 */ de->bitflags = 0; de->comp_method = ZIP_CM_DEFAULT; - de->last_mod = 0; + de->last_mod_date = 0; + de->last_mod_time = 0; de->crc = 0; de->comp_size = 0; de->uncomp_size = 0; @@ -340,7 +342,6 @@ _zip_dirent_new(void) { zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error) { zip_uint8_t buf[CDENTRYSIZE]; - zip_uint16_t dostime, dosdate; zip_uint32_t size, variable_size; zip_uint16_t filename_len, comment_len, ef_len; @@ -380,9 +381,8 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zde->comp_method = _zip_buffer_get_16(buffer); /* convert to time_t */ - dostime = _zip_buffer_get_16(buffer); - dosdate = _zip_buffer_get_16(buffer); - zde->last_mod = _zip_d2u_time(dostime, dosdate); + zde->last_mod_time = _zip_buffer_get_16(buffer); + zde->last_mod_date = _zip_buffer_get_16(buffer); zde->crc = _zip_buffer_get_32(buffer); zde->comp_size = _zip_buffer_get_32(buffer); @@ -921,7 +921,8 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { dosdate = 0x2198; } else { - _zip_u2d_time(de->last_mod, &dostime, &dosdate); + dostime = de->last_mod_time; + dosdate = de->last_mod_date; } _zip_buffer_put_16(buffer, dostime); _zip_buffer_put_16(buffer, dosdate); @@ -1110,8 +1111,8 @@ _zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *err } -void -_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { +int +_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate, zip_error_t *ze) { struct tm *tpm; struct tm tm; tpm = zip_localtime(&intime, &tm); @@ -1119,7 +1120,10 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { /* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */ *ddate = (1 << 5) + 1; *dtime = 0; - return; + if (ze) { + zip_error_set(ze, ZIP_ER_INVAL, errno); + } + return -1; } if (tpm->tm_year < 80) { tpm->tm_year = 80; @@ -1127,6 +1131,8 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { *ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday); *dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1)); + + return 0; } diff --git a/lib/zip_file_set_mtime.c b/lib/zip_file_set_mtime.c index 4126f5a16..d900c503b 100644 --- a/lib/zip_file_set_mtime.c +++ b/lib/zip_file_set_mtime.c @@ -31,21 +31,16 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "zip.h" #include "zipint.h" ZIP_EXTERN int zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) { - time_t mtime; - mtime = _zip_d2u_time(dtime, ddate); - return zip_file_set_mtime(za, idx, mtime, flags); -} - -ZIP_EXTERN int -zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) { zip_entry_t *e; - if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + 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); @@ -70,8 +65,20 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) } } - e->changes->last_mod = mtime; + e->changes->last_mod_time = dtime; + e->changes->last_mod_date = ddate; e->changes->changed |= ZIP_DIRENT_LAST_MOD; return 0; } + +ZIP_EXTERN int +zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) { + zip_uint16_t ddate, dtime; + + if (_zip_u2d_time(mtime, &dtime, &ddate, &za->error) < 0) { + return -1; + } + + return zip_file_set_dostime(za, idx, dtime, ddate, flags); +} diff --git a/lib/zip_open.c b/lib/zip_open.c index 5540cba8d..38a0157c3 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c @@ -524,7 +524,10 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) { and global headers for the bitflags */ || (central->bitflags != local->bitflags) #endif - || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename)) + || (central->comp_method != local->comp_method) + || (central->last_mod_date != local->last_mod_date) + || (central->last_mod_time != local->last_mod_time) + || !_zip_string_equal(central->filename, local->filename)) return -1; if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) { diff --git a/lib/zip_source_pkware_decode.c b/lib/zip_source_pkware_decode.c index b4c482b31..8147ed7e9 100644 --- a/lib/zip_source_pkware_decode.c +++ b/lib/zip_source_pkware_decode.c @@ -108,7 +108,9 @@ decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { if (st.valid & ZIP_STAT_MTIME) { unsigned short dostime, dosdate; - _zip_u2d_time(st.mtime, &dostime, &dosdate); + if (_zip_u2d_time(st.mtime, &dostime, &dosdate, &ctx->error) < 0) { + return -1; + } if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) { ok = true; } diff --git a/lib/zip_source_pkware_encode.c b/lib/zip_source_pkware_encode.c index d89b9f4e8..0f5bf1f44 100644 --- a/lib/zip_source_pkware_encode.c +++ b/lib/zip_source_pkware_encode.c @@ -95,7 +95,9 @@ encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { set_mtime(ctx, &st); } - _zip_u2d_time(ctx->mtime, &dostime, &dosdate); + if (_zip_u2d_time(ctx->mtime, &dostime, &dosdate, &ctx->error) < 0) { + return -1; + } if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) { zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); diff --git a/lib/zip_stat_index.c b/lib/zip_stat_index.c index da33c09eb..ef7989574 100644 --- a/lib/zip_stat_index.c +++ b/lib/zip_stat_index.c @@ -77,7 +77,7 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) } if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) { - st->mtime = de->last_mod; + st->mtime = _zip_d2u_time(de->last_mod_time, de->last_mod_date); st->valid |= ZIP_STAT_MTIME; } } @@ -86,7 +86,7 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) st->crc = de->crc; st->size = de->uncomp_size; - st->mtime = de->last_mod; + st->mtime = _zip_d2u_time(de->last_mod_time, de->last_mod_date); st->comp_size = de->comp_size; st->comp_method = (zip_uint16_t)de->comp_method; st->encryption_method = de->encryption_method; diff --git a/lib/zipint.h b/lib/zipint.h index 4887b6c5c..82812fa67 100644 --- a/lib/zipint.h +++ b/lib/zipint.h @@ -339,7 +339,8 @@ struct zip_dirent { zip_uint16_t version_needed; /* (cl) version needed to extract */ zip_uint16_t bitflags; /* (cl) general purpose bit flag */ zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ - time_t last_mod; /* (cl) time of last modification */ + zip_uint16_t last_mod_time; /* (cl) time of last modification */ + zip_uint16_t last_mod_date; /* (cl) date of last modification */ zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ zip_uint64_t comp_size; /* (cl) size of compressed data */ zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ @@ -647,7 +648,7 @@ zip_t *_zip_new(zip_error_t *); zip_int64_t _zip_file_replace(zip_t *, zip_uint64_t, const char *, zip_source_t *, zip_flags_t); int _zip_set_name(zip_t *, zip_uint64_t, const char *, zip_flags_t); -void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); +int _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *, zip_error_t *); int _zip_unchange(zip_t *, zip_uint64_t, int); void _zip_unchange_data(zip_entry_t *); int _zip_write(zip_t *za, const void *data, zip_uint64_t length);