diff --git a/lib/zip_close.c b/lib/zip_close.c index d0e3ba8a1..015a21b02 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 = _zip_d2u_time(de->last_mod_time, de->last_mod_date); + st_mtime.mtime = _zip_d2u_time(&de->last_mod); 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; @@ -536,7 +536,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { else { time(&mtime); } - if (_zip_u2d_time(st.mtime, &de->last_mod_time, &de->last_mod_date, &za->error) < 0) { + if (_zip_u2d_time(st.mtime, &de->last_mod.time, &de->last_mod.date, &za->error) < 0) { return -1; } } diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c index 57efcaa87..7caafb43a 100644 --- a/lib/zip_dirent.c +++ b/lib/zip_dirent.c @@ -290,8 +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_date = 0; - de->last_mod_time = 0; + de->last_mod.date = 0; + de->last_mod.time = 0; de->crc = 0; de->comp_size = 0; de->uncomp_size = 0; @@ -381,8 +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 */ - zde->last_mod_time = _zip_buffer_get_16(buffer); - zde->last_mod_date = _zip_buffer_get_16(buffer); + 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); @@ -778,7 +778,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) { int _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { - zip_uint16_t dostime, dosdate; + zip_dostime_t dostime; zip_encoding_type_t com_enc, name_enc; zip_extra_field_t *ef; zip_extra_field_t *ef64; @@ -917,15 +917,14 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { } if (ZIP_WANT_TORRENTZIP(za)) { - dostime = 0xbc00; - dosdate = 0x2198; + dostime.time = 0xbc00; + dostime.date = 0x2198; } else { - dostime = de->last_mod_time; - dosdate = de->last_mod_date; + dostime = de->last_mod; } - _zip_buffer_put_16(buffer, dostime); - _zip_buffer_put_16(buffer, dosdate); + _zip_buffer_put_16(buffer, dostime.time); + _zip_buffer_put_16(buffer, dostime.date); if (is_winzip_aes && de->uncomp_size < 20) { _zip_buffer_put_32(buffer, 0); @@ -1026,7 +1025,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { time_t -_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) { +_zip_d2u_time(const zip_dostime_t* dtime) { struct tm tm; memset(&tm, 0, sizeof(tm)); @@ -1034,13 +1033,13 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) { /* let mktime decide if DST is in effect */ tm.tm_isdst = -1; - tm.tm_year = ((ddate >> 9) & 127) + 1980 - 1900; - tm.tm_mon = ((ddate >> 5) & 15) - 1; - tm.tm_mday = ddate & 31; + tm.tm_year = ((dtime->date >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((dtime->date >> 5) & 15) - 1; + tm.tm_mday = dtime->date & 31; - tm.tm_hour = (dtime >> 11) & 31; - tm.tm_min = (dtime >> 5) & 63; - tm.tm_sec = (dtime << 1) & 62; + tm.tm_hour = (dtime->time >> 11) & 31; + tm.tm_min = (dtime->time >> 5) & 63; + tm.tm_sec = (dtime->time << 1) & 62; return mktime(&tm); } diff --git a/lib/zip_file_set_mtime.c b/lib/zip_file_set_mtime.c index d900c503b..26d885914 100644 --- a/lib/zip_file_set_mtime.c +++ b/lib/zip_file_set_mtime.c @@ -65,8 +65,8 @@ zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16 } } - e->changes->last_mod_time = dtime; - e->changes->last_mod_date = ddate; + e->changes->last_mod.time = dtime; + e->changes->last_mod.date = ddate; e->changes->changed |= ZIP_DIRENT_LAST_MOD; return 0; diff --git a/lib/zip_open.c b/lib/zip_open.c index 38a0157c3..e093fa1b8 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c @@ -525,8 +525,8 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) { || (central->bitflags != local->bitflags) #endif || (central->comp_method != local->comp_method) - || (central->last_mod_date != local->last_mod_date) - || (central->last_mod_time != local->last_mod_time) + || (central->last_mod.time != local->last_mod.time) + || (central->last_mod.date != local->last_mod.date) || !_zip_string_equal(central->filename, local->filename)) return -1; diff --git a/lib/zip_source_get_dostime.c b/lib/zip_source_get_dostime.c index 0df837d91..5527256f1 100644 --- a/lib/zip_source_get_dostime.c +++ b/lib/zip_source_get_dostime.c @@ -1,6 +1,6 @@ /* - zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + zip_source_get_dostime.c -- get modification time in DOS format from source + Copyright (C) 2025 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at @@ -34,13 +34,13 @@ #include "zipint.h" - +/* Returns -1 on error, 0 on no dostime avaialable, 1 for dostime returned */ ZIP_EXTERN int -zip_source_get_dos_time(zip_source_t *src, zip_uint16_t *dos_time, zip_uint16_t *dos_date) { +zip_source_get_dos_time(zip_source_t *src, zip_dostime_t *dos_time) { if (src->source_closed) { return -1; } - if (dos_time == NULL || dos_date == NULL) { + if (dos_time == NULL) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } @@ -50,29 +50,23 @@ zip_source_get_dos_time(zip_source_t *src, zip_uint16_t *dos_time, zip_uint16_t } if (zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_DOS_TIME)) { - zip_uint16_t data[2]; - if (_zip_source_call(src, data, sizeof(data), ZIP_SOURCE_GET_DOS_TIME) < 0) { - return -1; - } - *dos_time = data[0]; - *dos_date = data[1]; - return 0; - } - else { - zip_stat_t st; - zip_stat_init(&st); + zip_int64_t n = _zip_source_call(src, dos_time, sizeof(*dos_time), ZIP_SOURCE_GET_DOS_TIME); - if (zip_source_stat(src, &st) < 0) { + if (n < 0) { return -1; } - - if (!(st.valid & ZIP_STAT_MTIME)) { - *dos_time = 0; - *dos_date = 0; + else if (n == 0) { return 0; } + else if (n == sizeof(*dos_time)) { + return 1; + } else { - return _zip_u2d_time(st.mtime, dos_time, dos_date, &src->error); + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + return -1; } } + else { + return 0; + } } diff --git a/lib/zip_stat_index.c b/lib/zip_stat_index.c index ef7989574..8daf388b4 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 = _zip_d2u_time(de->last_mod_time, de->last_mod_date); + st->mtime = _zip_d2u_time(&de->last_mod); 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 = _zip_d2u_time(de->last_mod_time, de->last_mod_date); + st->mtime = _zip_d2u_time(&de->last_mod); st->comp_size = de->comp_size; st->comp_method = (zip_uint16_t)de->comp_method; st->encryption_method = de->encryption_method; @@ -97,8 +97,9 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) } if ((za->ch_flags & ZIP_AFL_WANT_TORRENTZIP) && (flags & ZIP_FL_UNCHANGED) == 0) { + zip_dostime_t dostime = {0xbc00, 0x2198}; st->comp_method = ZIP_CM_DEFLATE; - st->mtime = _zip_d2u_time(0xbc00, 0x2198); + st->mtime = _zip_d2u_time(&dostime); st->valid |= ZIP_STAT_MTIME | ZIP_STAT_COMP_METHOD; st->valid &= ~ZIP_STAT_COMP_SIZE; } diff --git a/lib/zipint.h b/lib/zipint.h index 011fbbbd4..ae28869fc 100644 --- a/lib/zipint.h +++ b/lib/zipint.h @@ -270,6 +270,7 @@ struct zip_hash; struct zip_progress; typedef struct zip_cdir zip_cdir_t; +typedef struct zip_dostime zip_dostime_t; typedef struct zip_dirent zip_dirent_t; typedef struct zip_entry zip_entry_t; typedef struct zip_extra_field zip_extra_field_t; @@ -328,6 +329,11 @@ struct zip_file { #define ZIP_DIRENT_PASSWORD 0x0080u #define ZIP_DIRENT_ALL ZIP_UINT32_MAX +struct zip_dostime { + zip_uint16_t time; + zip_uint16_t date; +}; + struct zip_dirent { zip_uint32_t changed; bool local_extra_fields_read; /* whether we already read in local header extra fields */ @@ -339,8 +345,7 @@ 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)) */ - zip_uint16_t last_mod_time; /* (cl) time of last modification */ - zip_uint16_t last_mod_date; /* (cl) date of last modification */ + zip_dostime_t last_mod; /* (cl) time 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 */ @@ -529,7 +534,7 @@ void _zip_cdir_free(zip_cdir_t *); bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error); zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *); zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors); -time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); +time_t _zip_d2u_time(const zip_dostime_t*); void _zip_deregister_source(zip_t *za, zip_source_t *src); void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t); @@ -612,7 +617,7 @@ void _zip_set_open_error(int *zep, const zip_error_t *err, int ze); bool zip_source_accept_empty(zip_source_t *src); zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command); bool _zip_source_eof(zip_source_t *); -int zip_source_get_dos_time(zip_source_t *src, zip_uint16_t *dos_time, zip_uint16_t *dos_date); +int zip_source_get_dos_time(zip_source_t *src, zip_dostime_t *dos_time); zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error); bool _zip_source_had_error(zip_source_t *);