|
@@ -13,7 +13,6 @@
|
|
|
#if PHYSFS_SUPPORTS_ZIP
|
|
#if PHYSFS_SUPPORTS_ZIP
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
|
-#include <time.h>
|
|
|
|
|
|
|
|
|
|
#if (PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN)
|
|
#if (PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN)
|
|
|
#define MINIZ_LITTLE_ENDIAN 1
|
|
#define MINIZ_LITTLE_ENDIAN 1
|
|
@@ -969,27 +968,24 @@ static inline int zip_has_symlink_attr(const ZIPentry *entry,
|
|
|
|
|
|
|
|
static PHYSFS_sint64 zip_dos_time_to_physfs_time(PHYSFS_uint32 dostime)
|
|
static PHYSFS_sint64 zip_dos_time_to_physfs_time(PHYSFS_uint32 dostime)
|
|
|
{
|
|
{
|
|
|
- PHYSFS_uint32 dosdate;
|
|
|
|
|
- struct tm unixtime;
|
|
|
|
|
- memset(&unixtime, '\0', sizeof (unixtime));
|
|
|
|
|
-
|
|
|
|
|
- dosdate = (PHYSFS_uint32) ((dostime >> 16) & 0xFFFF);
|
|
|
|
|
|
|
+ const PHYSFS_uint32 dosdate = (PHYSFS_uint32) ((dostime >> 16) & 0xFFFF);
|
|
|
dostime &= 0xFFFF;
|
|
dostime &= 0xFFFF;
|
|
|
|
|
|
|
|
- /* dissect date */
|
|
|
|
|
- unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
|
|
|
|
|
- unixtime.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
|
|
|
|
|
- unixtime.tm_mday = ((dosdate ) & 0x1F);
|
|
|
|
|
-
|
|
|
|
|
- /* dissect time */
|
|
|
|
|
- unixtime.tm_hour = ((dostime >> 11) & 0x1F);
|
|
|
|
|
- unixtime.tm_min = ((dostime >> 5) & 0x3F);
|
|
|
|
|
- unixtime.tm_sec = ((dostime << 1) & 0x3E);
|
|
|
|
|
-
|
|
|
|
|
- /* let mktime calculate daylight savings time. */
|
|
|
|
|
- unixtime.tm_isdst = -1;
|
|
|
|
|
-
|
|
|
|
|
- return ((PHYSFS_sint64) mktime(&unixtime));
|
|
|
|
|
|
|
+ const int m = (int) ((dosdate >> 5) & 0x0F);
|
|
|
|
|
+ const int d = (int) ((dosdate >> 0) & 0x1F) + 1;
|
|
|
|
|
+ const int y = (int) (((dosdate >> 9) & 0x7F) + 1980) - (m <= 2 ? 1 : 0);
|
|
|
|
|
+ const int hour = (int) ((dostime >> 11) & 0x1F);
|
|
|
|
|
+ const int minute = (int) ((dostime >> 5) & 0x3F);
|
|
|
|
|
+ const int sec = (int) ((dostime << 1) & 0x3E);
|
|
|
|
|
+
|
|
|
|
|
+ // days since 1/1/1970: https://howardhinnant.github.io/date_algorithms.html#days_from_civil
|
|
|
|
|
+ const int era = ((y >= 0) ? y : (y - 399)) / 400;
|
|
|
|
|
+ const unsigned int yoe = (unsigned int) (y - era * 400); // [0, 399]
|
|
|
|
|
+ const unsigned int doy = (((153 * ((m > 2) ? (m - 3) : (m + 9))) + 2) / 5) + (d - 1); // [0, 365]
|
|
|
|
|
+ const unsigned int doe = (yoe * 365) + (yoe / 4) - (yoe / 100) + doy; // [0, 146096]
|
|
|
|
|
+ const int days = (era * 146097) + ((int) doe) - 719468;
|
|
|
|
|
+ const int seconds = (hour * (60 * 60)) + (minute * 60) + (sec);
|
|
|
|
|
+ return (((PHYSFS_sint64) days) * 86400) + seconds;
|
|
|
} /* zip_dos_time_to_physfs_time */
|
|
} /* zip_dos_time_to_physfs_time */
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1021,7 +1017,7 @@ static ZIPentry *zip_load_entry(ZIPinfo *info, const int zip64,
|
|
|
BAIL_IF_ERRPASS(!readui16(io, &entry.general_bits), NULL); /* general bits */
|
|
BAIL_IF_ERRPASS(!readui16(io, &entry.general_bits), NULL); /* general bits */
|
|
|
BAIL_IF_ERRPASS(!readui16(io, &entry.compression_method), NULL);
|
|
BAIL_IF_ERRPASS(!readui16(io, &entry.compression_method), NULL);
|
|
|
BAIL_IF_ERRPASS(!readui32(io, &entry.dos_mod_time), NULL);
|
|
BAIL_IF_ERRPASS(!readui32(io, &entry.dos_mod_time), NULL);
|
|
|
- entry.last_mod_time = zip_dos_time_to_physfs_time(entry.dos_mod_time);
|
|
|
|
|
|
|
+ entry.last_mod_time = zip_dos_time_to_physfs_time(entry.dos_mod_time); /* !!! FIXME: there are extended fields that can get you off gross old DOS time format. */
|
|
|
BAIL_IF_ERRPASS(!readui32(io, &entry.crc), NULL);
|
|
BAIL_IF_ERRPASS(!readui32(io, &entry.crc), NULL);
|
|
|
BAIL_IF_ERRPASS(!readui32(io, &ui32), NULL);
|
|
BAIL_IF_ERRPASS(!readui32(io, &ui32), NULL);
|
|
|
entry.compressed_size = (PHYSFS_uint64) ui32;
|
|
entry.compressed_size = (PHYSFS_uint64) ui32;
|