From: ARJANEN Loïc Jean David Date: Fri, 28 Mar 2025 14:23:43 +0000 (+0100) Subject: Commonalising time-related functions. (#2553) X-Git-Tag: v3.8.0~58 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=6bb0952602e06e593d576eb70ce7dbf369d385a8;p=thirdparty%2Flibarchive.git Commonalising time-related functions. (#2553) Putting the time format conversion functions in one file and using the common functions in the various formats. --- diff --git a/Makefile.am b/Makefile.am index 8cd7a1a2e..7860c5c50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -197,6 +197,8 @@ libarchive_la_SOURCES= \ libarchive/archive_string.h \ libarchive/archive_string_composition.h \ libarchive/archive_string_sprintf.c \ + libarchive/archive_time.c \ + libarchive/archive_time_private.h \ libarchive/archive_util.c \ libarchive/archive_version_details.c \ libarchive/archive_virtual.c \ diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index dd0b2808d..fe13be1be 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -117,6 +117,8 @@ SET(libarchive_SOURCES archive_string.h archive_string_composition.h archive_string_sprintf.c + archive_time.c + archive_time_private.h archive_util.c archive_version_details.c archive_virtual.c diff --git a/libarchive/archive_entry_copy_bhfi.c b/libarchive/archive_entry_copy_bhfi.c index d5317a5ea..c1a9e19c2 100644 --- a/libarchive/archive_entry_copy_bhfi.c +++ b/libarchive/archive_entry_copy_bhfi.c @@ -24,43 +24,24 @@ */ #include "archive_platform.h" - +#include "archive_time_private.h" #include "archive_private.h" #include "archive_entry.h" #if defined(_WIN32) && !defined(__CYGWIN__) -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) - -__inline static void -fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) -{ - ULARGE_INTEGER utc; - - utc.HighPart = filetime->dwHighDateTime; - utc.LowPart = filetime->dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ - *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ - } else { - *t = 0; - *ns = 0; - } -} - void archive_entry_copy_bhfi(struct archive_entry *entry, BY_HANDLE_FILE_INFORMATION *bhfi) { - time_t secs; - long nsecs; + int64_t secs; + uint32_t nsecs; - fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs); archive_entry_set_atime(entry, secs, nsecs); - fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs); archive_entry_set_mtime(entry, secs, nsecs); - fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs); archive_entry_set_birthtime(entry, secs, nsecs); archive_entry_set_ctime(entry, secs, nsecs); archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber); @@ -71,4 +52,4 @@ archive_entry_copy_bhfi(struct archive_entry *entry, + bhfi->nFileSizeLow); /* archive_entry_set_mode(entry, st->st_mode); */ } -#endif +#endif \ No newline at end of file diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c index 446417a9a..40a083ae5 100644 --- a/libarchive/archive_match.c +++ b/libarchive/archive_match.c @@ -43,6 +43,7 @@ #include "archive_pathmatch.h" #include "archive_rb.h" #include "archive_string.h" +#include "archive_time_private.h" struct match { struct match *next; @@ -1145,36 +1146,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype, } #if defined(_WIN32) && !defined(__CYGWIN__) -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) static int set_timefilter_find_data(struct archive_match *a, int timetype, - DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime, - DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime) + const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime) { - ULARGE_INTEGER utc; time_t ctime_sec, mtime_sec; - long ctime_ns, mtime_ns; + uint32_t ctime_ns, mtime_ns; - utc.HighPart = ftCreationTime_dwHighDateTime; - utc.LowPart = ftCreationTime_dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - ctime_sec = (time_t)(utc.QuadPart / 10000000); - ctime_ns = (long)(utc.QuadPart % 10000000) * 100; - } else { - ctime_sec = 0; - ctime_ns = 0; - } - utc.HighPart = ftLastWriteTime_dwHighDateTime; - utc.LowPart = ftLastWriteTime_dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - mtime_sec = (time_t)(utc.QuadPart / 10000000); - mtime_ns = (long)(utc.QuadPart % 10000000) * 100; - } else { - mtime_sec = 0; - mtime_ns = 0; - } + ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns); + ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns); return set_timefilter(a, timetype, mtime_sec, mtime_ns, ctime_sec, ctime_ns); } @@ -1199,9 +1179,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype, return (ARCHIVE_FAILED); } FindClose(h); - return set_timefilter_find_data(a, timetype, - d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, - d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); + return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime); } static int @@ -1223,9 +1201,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype, return (ARCHIVE_FAILED); } FindClose(h); - return set_timefilter_find_data(a, timetype, - d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime, - d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime); + return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime); } #else /* _WIN32 && !__CYGWIN__ */ @@ -1870,5 +1846,4 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry) return (r); } return (0); -} - +} \ No newline at end of file diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index ba7dbc6d0..48338fa9b 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -41,6 +41,7 @@ #include "archive_entry.h" #include "archive_private.h" #include "archive_read_disk_private.h" +#include "archive_time_private.h" #ifndef O_BINARY #define O_BINARY 0 @@ -1983,40 +1984,20 @@ tree_dir_next_windows(struct tree *t, const wchar_t *pattern) } } -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) -static void -fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) -{ - ULARGE_INTEGER utc; - - utc.HighPart = filetime->dwHighDateTime; - utc.LowPart = filetime->dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - /* milli seconds base */ - *t = (time_t)(utc.QuadPart / 10000000); - /* nano seconds base */ - *ns = (long)(utc.QuadPart % 10000000) * 100; - } else { - *t = 0; - *ns = 0; - } -} - static void entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path, const WIN32_FIND_DATAW *findData, const BY_HANDLE_FILE_INFORMATION *bhfi) { - time_t secs; - long nsecs; + int64_t secs; + uint32_t nsecs; mode_t mode; - fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs); archive_entry_set_atime(entry, secs, nsecs); - fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs); archive_entry_set_mtime(entry, secs, nsecs); - fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs); + ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs); archive_entry_set_birthtime(entry, secs, nsecs); archive_entry_set_ctime(entry, secs, nsecs); archive_entry_set_dev(entry, bhfi_dev(bhfi)); @@ -2551,4 +2532,4 @@ exit_setup_sparse: return (exit_sts); } -#endif +#endif \ No newline at end of file diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index b6e82e68c..653250a31 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -53,6 +53,7 @@ #include "archive_ppmd7_private.h" #include "archive_private.h" #include "archive_read_private.h" +#include "archive_time_private.h" #include "archive_endian.h" #ifndef HAVE_ZLIB_H @@ -63,7 +64,6 @@ #define SFX_MIN_ADDR 0x27000 #define SFX_MAX_ADDR 0x60000 - /* * Codec ID */ @@ -148,7 +148,6 @@ struct _7z_digests { uint32_t *digests; }; - struct _7z_folder { uint64_t numCoders; struct _7z_coder { @@ -228,12 +227,12 @@ struct _7zip_entry { #define CRC32_IS_SET (1<<3) #define HAS_STREAM (1<<4) - time_t mtime; - time_t atime; - time_t ctime; - long mtime_ns; - long atime_ns; - long ctime_ns; + int64_t mtime; + int64_t atime; + int64_t ctime; + uint32_t mtime_ns; + uint32_t atime_ns; + uint32_t ctime_ns; uint32_t mode; uint32_t attr; }; @@ -392,7 +391,6 @@ static int decode_encoded_header_info(struct archive_read *, static int decompress(struct archive_read *, struct _7zip *, void *, size_t *, const void *, size_t *); static ssize_t extract_pack_stream(struct archive_read *, size_t); -static void fileTimeToUtc(uint64_t, time_t *, long *); static uint64_t folder_uncompressed_size(struct _7z_folder *); static void free_CodersInfo(struct _7z_coders_info *); static void free_Digest(struct _7z_digests *); @@ -2860,23 +2858,6 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (0); } -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) -static void -fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns) -{ - - if (fileTime >= EPOC_TIME) { - fileTime -= EPOC_TIME; - /* milli seconds base */ - *timep = (time_t)(fileTime / 10000000); - /* nano seconds base */ - *ns = (long)(fileTime % 10000000) * 100; - } else { - *timep = 0; - *ns = 0; - } -} - static int read_Times(struct archive_read *a, struct _7z_header_info *h, int type) { @@ -2919,19 +2900,19 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type) goto failed; switch (type) { case kCTime: - fileTimeToUtc(archive_le64dec(p), + ntfs_to_unix(archive_le64dec(p), &(entries[i].ctime), &(entries[i].ctime_ns)); entries[i].flg |= CTIME_IS_SET; break; case kATime: - fileTimeToUtc(archive_le64dec(p), + ntfs_to_unix(archive_le64dec(p), &(entries[i].atime), &(entries[i].atime_ns)); entries[i].flg |= ATIME_IS_SET; break; case kMTime: - fileTimeToUtc(archive_le64dec(p), + ntfs_to_unix(archive_le64dec(p), &(entries[i].mtime), &(entries[i].mtime_ns)); entries[i].flg |= MTIME_IS_SET; @@ -4319,5 +4300,4 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) zip->bcj2_outPos += outPos; return ((ssize_t)outPos); -} - +} \ No newline at end of file diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index c7cbad272..3eb4c577e 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -43,6 +43,7 @@ #include "archive_entry_locale.h" #include "archive_private.h" #include "archive_read_private.h" +#include "archive_time_private.h" #include "archive_endian.h" @@ -162,12 +163,12 @@ struct lha { #define ATIME_IS_SET 2 #define UNIX_MODE_IS_SET 4 #define CRC_IS_SET 8 - time_t birthtime; - long birthtime_tv_nsec; - time_t mtime; - long mtime_tv_nsec; - time_t atime; - long atime_tv_nsec; + int64_t birthtime; + uint32_t birthtime_tv_nsec; + int64_t mtime; + uint32_t mtime_tv_nsec; + int64_t atime; + uint32_t atime_tv_nsec; mode_t mode; int64_t uid; int64_t gid; @@ -230,8 +231,6 @@ static int lha_read_file_extended_header(struct archive_read *, struct lha *, uint16_t *, int, uint64_t, size_t *); static size_t lha_check_header_format(const void *); static int lha_skip_sfx(struct archive_read *); -static time_t lha_dos_time(const unsigned char *); -static time_t lha_win_time(uint64_t, long *); static unsigned char lha_calcsum(unsigned char, const void *, int, size_t); static int lha_parse_linkname(struct archive_wstring *, @@ -819,7 +818,7 @@ lha_read_file_header_0(struct archive_read *a, struct lha *lha) headersum = p[H0_HEADER_SUM_OFFSET]; lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); - lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); + lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET)); namelen = p[H0_NAME_LEN_OFFSET]; extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; if ((namelen > 221 || extdsize < 0) && extdsize != -2) { @@ -919,7 +918,7 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha) /* Note: An extended header size is included in a compsize. */ lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); - lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); + lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET)); namelen = p[H1_NAME_LEN_OFFSET]; /* Calculate a padding size. The result will be normally 0 only(?) */ padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; @@ -1090,7 +1089,7 @@ lha_read_file_header_3(struct archive_read *a, struct lha *lha) if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) goto invalid; - lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); + lha->header_size = archive_le32dec(p + H3_HEADER_SIZE_OFFSET); lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); @@ -1326,16 +1325,16 @@ lha_read_file_extended_header(struct archive_read *a, struct lha *lha, break; case EXT_TIMESTAMP: if (datasize == (sizeof(uint64_t) * 3)) { - lha->birthtime = lha_win_time( - archive_le64dec(extdheader), + ntfs_to_unix(archive_le64dec(extdheader), + &lha->birthtime, &lha->birthtime_tv_nsec); extdheader += sizeof(uint64_t); - lha->mtime = lha_win_time( - archive_le64dec(extdheader), + ntfs_to_unix(archive_le64dec(extdheader), + &lha->mtime, &lha->mtime_tv_nsec); extdheader += sizeof(uint64_t); - lha->atime = lha_win_time( - archive_le64dec(extdheader), + ntfs_to_unix(archive_le64dec(extdheader), + &lha->atime, &lha->atime_tv_nsec); lha->setflag |= BIRTHTIME_IS_SET | ATIME_IS_SET; @@ -1716,45 +1715,6 @@ lha_parse_linkname(struct archive_wstring *linkname, return (0); } -/* Convert an MSDOS-style date/time into Unix-style time. */ -static time_t -lha_dos_time(const unsigned char *p) -{ - int msTime, msDate; - struct tm ts; - - msTime = archive_le16dec(p); - msDate = archive_le16dec(p+2); - - memset(&ts, 0, sizeof(ts)); - ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ - ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ - ts.tm_mday = msDate & 0x1f; /* Day of month. */ - ts.tm_hour = (msTime >> 11) & 0x1f; - ts.tm_min = (msTime >> 5) & 0x3f; - ts.tm_sec = (msTime << 1) & 0x3e; - ts.tm_isdst = -1; - return (mktime(&ts)); -} - -/* Convert an MS-Windows-style date/time into Unix-style time. */ -static time_t -lha_win_time(uint64_t wintime, long *ns) -{ -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) - - if (wintime >= EPOC_TIME) { - wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ - if (ns != NULL) - *ns = (long)(wintime % 10000000) * 100; - return (wintime / 10000000); - } else { - if (ns != NULL) - *ns = 0; - return (0); - } -} - static unsigned char lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) { @@ -2916,5 +2876,4 @@ lzh_decode_huffman(struct huffman *hf, unsigned rbits) return (c); /* This bit pattern needs to be found out at a huffman tree. */ return (lzh_decode_huffman_tree(hf, rbits, c)); -} - +} \ No newline at end of file diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index 167d7e4f4..6cf6fa3de 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -46,6 +46,7 @@ #include "archive_entry_locale.h" #include "archive_ppmd7_private.h" #include "archive_entry_private.h" +#include "archive_time_private.h" #ifdef HAVE_BLAKE2_H #include @@ -100,10 +101,12 @@ struct file_header { uint8_t dir : 1; /* Is this file entry a directory? */ /* Optional time fields. */ - uint64_t e_mtime; - uint64_t e_ctime; - uint64_t e_atime; - uint32_t e_unix_ns; + int64_t e_mtime; + int64_t e_ctime; + int64_t e_atime; + uint32_t e_mtime_ns; + uint32_t e_ctime_ns; + uint32_t e_atime_ns; /* Optional hash fields. */ uint32_t stored_crc32; @@ -1101,22 +1104,22 @@ static int read_consume_bits(struct archive_read* a, struct rar5* rar, return ARCHIVE_OK; } -static int read_u32(struct archive_read* a, uint32_t* pvalue) { +static char read_u32(struct archive_read* a, uint32_t* pvalue) { const uint8_t* p; if(!read_ahead(a, 4, &p)) return 0; *pvalue = archive_le32dec(p); - return ARCHIVE_OK == consume(a, 4) ? 1 : 0; + return ARCHIVE_OK == consume(a, 4); } -static int read_u64(struct archive_read* a, uint64_t* pvalue) { +static char read_u64(struct archive_read* a, uint64_t* pvalue) { const uint8_t* p; if(!read_ahead(a, 8, &p)) return 0; *pvalue = archive_le64dec(p); - return ARCHIVE_OK == consume(a, 8) ? 1 : 0; + return ARCHIVE_OK == consume(a, 8); } static int bid_standard(struct archive_read* a) { @@ -1301,14 +1304,8 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar, return ARCHIVE_OK; } -static uint64_t time_win_to_unix(uint64_t win_time) { - const size_t ns_in_sec = 10000000; - const uint64_t sec_to_unix = 11644473600LL; - return win_time / ns_in_sec - sec_to_unix; -} - static int parse_htime_item(struct archive_read* a, char unix_time, - uint64_t* where, int64_t* extra_data_size) + int64_t* sec, uint32_t* nsec, int64_t* extra_data_size) { if(unix_time) { uint32_t time_val; @@ -1316,13 +1313,13 @@ static int parse_htime_item(struct archive_read* a, char unix_time, return ARCHIVE_EOF; *extra_data_size -= 4; - *where = (uint64_t) time_val; + *sec = (int64_t) time_val; } else { uint64_t windows_time; if(!read_u64(a, &windows_time)) return ARCHIVE_EOF; - *where = time_win_to_unix(windows_time); + ntfs_to_unix(windows_time, sec, nsec); *extra_data_size -= 8; } @@ -1386,7 +1383,7 @@ static int parse_file_extra_version(struct archive_read* a, static int parse_file_extra_htime(struct archive_read* a, struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size) { - char unix_time = 0; + char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime; size_t flags = 0; size_t value_len; @@ -1407,32 +1404,62 @@ static int parse_file_extra_htime(struct archive_read* a, } unix_time = flags & IS_UNIX; + has_unix_ns = unix_time && (flags & HAS_UNIX_NS); + has_mtime = flags & HAS_MTIME; + has_atime = flags & HAS_ATIME; + has_ctime = flags & HAS_CTIME; + rar->file.e_atime_ns = rar->file.e_ctime_ns = rar->file.e_mtime_ns = 0; - if(flags & HAS_MTIME) { + if(has_mtime) { parse_htime_item(a, unix_time, &rar->file.e_mtime, - extra_data_size); - archive_entry_set_mtime(e, rar->file.e_mtime, 0); + &rar->file.e_mtime_ns, extra_data_size); } - if(flags & HAS_CTIME) { + if(has_ctime) { parse_htime_item(a, unix_time, &rar->file.e_ctime, - extra_data_size); - archive_entry_set_ctime(e, rar->file.e_ctime, 0); + &rar->file.e_ctime_ns, extra_data_size); } - if(flags & HAS_ATIME) { + if(has_atime) { parse_htime_item(a, unix_time, &rar->file.e_atime, - extra_data_size); - archive_entry_set_atime(e, rar->file.e_atime, 0); + &rar->file.e_atime_ns, extra_data_size); + } + + if(has_mtime && has_unix_ns) { + if(!read_u32(a, &rar->file.e_mtime_ns)) + return ARCHIVE_EOF; + + *extra_data_size -= 4; + } + + if(has_ctime && has_unix_ns) { + if(!read_u32(a, &rar->file.e_ctime_ns)) + return ARCHIVE_EOF; + + *extra_data_size -= 4; } - if(flags & HAS_UNIX_NS) { - if(!read_u32(a, &rar->file.e_unix_ns)) + if(has_atime && has_unix_ns) { + if(!read_u32(a, &rar->file.e_atime_ns)) return ARCHIVE_EOF; *extra_data_size -= 4; } + /* The seconds and nanoseconds are either together, or separated in two + * fields so we parse them, then set the archive_entry's times. */ + if(has_mtime) { + archive_entry_set_mtime(e, rar->file.e_mtime, rar->file.e_mtime_ns); + } + + if(has_ctime) { + archive_entry_set_ctime(e, rar->file.e_ctime, rar->file.e_ctime_ns); + } + + if(has_atime) { + archive_entry_set_atime(e, rar->file.e_atime, rar->file.e_atime_ns); + } + return ARCHIVE_OK; } @@ -4333,4 +4360,4 @@ int archive_read_support_format_rar5(struct archive *_a) { } return ret; -} +} \ No newline at end of file diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 27e6bc051..bdfac2300 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -71,6 +71,7 @@ #include "archive_private.h" #include "archive_rb.h" #include "archive_read_private.h" +#include "archive_time_private.h" #include "archive_ppmd8_private.h" #ifndef HAVE_ZLIB_H @@ -465,27 +466,6 @@ compression_name(const int compression) return "??"; } -/* Convert an MSDOS-style date/time into Unix-style time. */ -static time_t -zip_time(const char *p) -{ - int msTime, msDate; - struct tm ts; - - msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]); - msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]); - - memset(&ts, 0, sizeof(ts)); - ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ - ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ - ts.tm_mday = msDate & 0x1f; /* Day of month. */ - ts.tm_hour = (msTime >> 11) & 0x1f; - ts.tm_min = (msTime >> 5) & 0x3f; - ts.tm_sec = (msTime << 1) & 0x3e; - ts.tm_isdst = -1; - return mktime(&ts); -} - /* * The extra data is stored as a list of * id1+size1+data1 + id2+size2+data2 ... @@ -978,7 +958,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, } zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED); zip_entry->compression = (char)archive_le16dec(p + 8); - zip_entry->mtime = zip_time(p + 10); + zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10)); zip_entry->crc32 = archive_le32dec(p + 14); if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) zip_entry->decdat = p[11]; @@ -3986,7 +3966,7 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry, zip->has_encrypted_entries = 1; } zip_entry->compression = (char)archive_le16dec(p + 10); - zip_entry->mtime = zip_time(p + 12); + zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12)); zip_entry->crc32 = archive_le32dec(p + 16); if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) zip_entry->decdat = p[13]; @@ -4423,4 +4403,4 @@ archive_read_support_format_zip_seekable(struct archive *_a) return (ARCHIVE_OK); } -/*# vim:set noet:*/ +/*# vim:set noet:*/ \ No newline at end of file diff --git a/libarchive/archive_time.c b/libarchive/archive_time.c new file mode 100644 index 000000000..cc5dc520d --- /dev/null +++ b/libarchive/archive_time.c @@ -0,0 +1,133 @@ +/*- + * Copyright © 2025 ARJANEN Loïc Jean David + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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 "archive_platform.h" +#include "archive_private.h" +#include "archive_time_private.h" +#include + +#define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600) +#define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000) +#define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS) +#define DOS_MIN_TIME 0x00210000U +#define DOS_MAX_TIME 0xff9fbf7dU +/* The min/max DOS Unix time are locale-dependant, so they're static variables, + * initialised on first use. */ +static char dos_initialised = 0; +static int64_t dos_max_unix; +static int64_t dos_min_unix; + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +/* Windows FILETIME to NTFS time. */ +uint64_t +FILETIME_to_ntfs(const FILETIME* filetime) +{ + ULARGE_INTEGER utc; + utc.HighPart = filetime->dwHighDateTime; + utc.LowPart = filetime->dwLowDateTime; + return utc.QuadPart; +} +#endif + +/* Convert an MSDOS-style date/time into Unix-style time. */ +int64_t +dos_to_unix(uint32_t dos_time) +{ + uint16_t msTime, msDate; + struct tm ts; + + msTime = (0xFFFF & dos_time); + msDate = (dos_time >> 16); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return mktime(&ts); +} + +/* Convert into MSDOS-style date/time. */ +uint32_t +unix_to_dos(int64_t unix_time) +{ + struct tm *t; + uint32_t dt; + time_t ut = unix_time; +#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S) + struct tm tmbuf; +#endif + + if (!dos_initialised) { + dos_max_unix = dos_to_unix(DOS_MAX_TIME); + dos_min_unix = dos_to_unix(DOS_MIN_TIME); + dos_initialised = 1; + } + if (unix_time >= dos_max_unix) { + return DOS_MAX_TIME; + } + else if(unix_time <= dos_min_unix) { + return DOS_MIN_TIME; + } + else { +#if defined(HAVE_LOCALTIME_S) + t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf; +#elif defined(HAVE_LOCALTIME_R) + t = localtime_r(&ut, &tmbuf); +#else + t = localtime(&ut); +#endif + dt = 0; + dt += ((t->tm_year - 80) & 0x7f) << 9; + dt += ((t->tm_mon + 1) & 0x0f) << 5; + dt += (t->tm_mday & 0x1f); + dt <<= 16; + dt += (t->tm_hour & 0x1f) << 11; + dt += (t->tm_min & 0x3f) << 5; + dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ + return dt; + } +} + +/* Convert NTFS time to Unix sec/ncse */ +void +ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs) +{ + ntfs -= NTFS_EPOC_TICKS; + lldiv_t tdiv = lldiv(ntfs, NTFS_TICKS); + *secs = tdiv.quot; + *nsecs = tdiv.rem * 100; +} + +/* Convert Unix sec/nsec to NTFS time */ +uint64_t +unix_to_ntfs(int64_t secs, uint32_t nsecs) +{ + uint64_t ntfs = secs + NTFS_EPOC_TIME; + ntfs *= NTFS_TICKS; + return ntfs + nsecs/100; +} \ No newline at end of file diff --git a/libarchive/archive_time_private.h b/libarchive/archive_time_private.h new file mode 100644 index 000000000..63298c5a9 --- /dev/null +++ b/libarchive/archive_time_private.h @@ -0,0 +1,47 @@ +/*- + * Copyright © 2025 ARJANEN Loïc Jean David + * All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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. + */ +#ifndef ARCHIVE_TIME_PRIVATE_H_INCLUDED +#define ARCHIVE_TIME_PRIVATE_H_INCLUDED + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif +#include + +/* NTFS time to Unix sec/nsec. */ +void ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs); +/* DOS time to Unix sec. */ +int64_t dos_to_unix(uint32_t dos); +/* Unix sec/nsec to NTFS time. */ +uint64_t unix_to_ntfs(int64_t secs, uint32_t nsecs); +/* Unix sec to DOS time. */ +uint32_t unix_to_dos(int64_t secs); +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +/* Windows FILETIME to NTFS time. */ +uint64_t FILETIME_to_ntfs(const FILETIME* filetime); +#endif +#endif /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */ \ No newline at end of file diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index bb540da01..03c9736c0 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -47,6 +47,7 @@ #include "archive_platform.h" #include "archive_private.h" #include "archive_entry.h" +#include "archive_time_private.h" #include #include #include @@ -61,8 +62,6 @@ #include #include -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) - #if defined(__LA_LSEEK_NEEDED) static BOOL SetFilePointerEx_perso(HANDLE hFile, LARGE_INTEGER liDistanceToMove, @@ -450,24 +449,6 @@ __la_read(int fd, void *buf, size_t nbytes) return ((ssize_t)bytes_read); } -/* Convert Windows FILETIME to UTC */ -__inline static void -fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns) -{ - ULARGE_INTEGER utc; - - utc.HighPart = filetime->dwHighDateTime; - utc.LowPart = filetime->dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */ - *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */ - } else { - *t = 0; - *ns = 0; - } -} - /* Stat by handle * Windows' stat() does not accept the path added "\\?\" especially "?" * character. @@ -487,8 +468,6 @@ __hstat(HANDLE handle, struct ustat *st) ULARGE_INTEGER ino64; DWORD ftype; mode_t mode; - time_t t; - long ns; switch (ftype = GetFileType(handle)) { case FILE_TYPE_UNKNOWN: @@ -544,15 +523,9 @@ __hstat(HANDLE handle, struct ustat *st) mode |= S_IFREG; st->st_mode = mode; - fileTimeToUTC(&info.ftLastAccessTime, &t, &ns); - st->st_atime = t; - st->st_atime_nsec = ns; - fileTimeToUTC(&info.ftLastWriteTime, &t, &ns); - st->st_mtime = t; - st->st_mtime_nsec = ns; - fileTimeToUTC(&info.ftCreationTime, &t, &ns); - st->st_ctime = t; - st->st_ctime_nsec = ns; + ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastAccessTime), &st->st_atime, &st->st_atime_nsec); + ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastWriteTime), &st->st_mtime, &st->st_mtime_nsec); + ntfs_to_unix(FILETIME_to_ntfs(&info.ftCreationTime), &st->st_ctime, &st->st_ctime_nsec); st->st_size = ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1)) + (int64_t)(info.nFileSizeLow); diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 472fd7310..86ea2ed8d 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -60,6 +60,7 @@ #include "archive_string.h" #include "archive_entry.h" #include "archive_private.h" +#include "archive_time_private.h" #ifndef O_BINARY #define O_BINARY 0 @@ -2605,10 +2606,6 @@ set_times(struct archive_write_disk *a, time_t mtime, long mtime_nanos, time_t ctime_sec, long ctime_nanos) { -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) -#define WINTIME(sec, nsec) (((sec * 10000000LL) + EPOC_TIME)\ - + ((nsec)/100)) - HANDLE hw = 0; ULARGE_INTEGER wintm; FILETIME *pfbtime; @@ -2646,17 +2643,17 @@ set_times(struct archive_write_disk *a, h = hw; } - wintm.QuadPart = WINTIME(atime, atime_nanos); + wintm.QuadPart = unix_to_ntfs(atime, atime_nanos); fatime.dwLowDateTime = wintm.LowPart; fatime.dwHighDateTime = wintm.HighPart; - wintm.QuadPart = WINTIME(mtime, mtime_nanos); + wintm.QuadPart = unix_to_ntfs(mtime, mtime_nanos); fmtime.dwLowDateTime = wintm.LowPart; fmtime.dwHighDateTime = wintm.HighPart; /* * SetFileTime() supports birthtime. */ if (birthtime > 0 || birthtime_nanos > 0) { - wintm.QuadPart = WINTIME(birthtime, birthtime_nanos); + wintm.QuadPart = unix_to_ntfs(birthtime, birthtime_nanos); fbtime.dwLowDateTime = wintm.LowPart; fbtime.dwHighDateTime = wintm.HighPart; pfbtime = &fbtime; @@ -2878,34 +2875,16 @@ set_xattrs(struct archive_write_disk *a) return (ARCHIVE_OK); } -static void -fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns) -{ - ULARGE_INTEGER utc; - - utc.HighPart = filetime->dwHighDateTime; - utc.LowPart = filetime->dwLowDateTime; - if (utc.QuadPart >= EPOC_TIME) { - utc.QuadPart -= EPOC_TIME; - /* milli seconds base */ - *t = (time_t)(utc.QuadPart / 10000000); - /* nano seconds base */ - *ns = (long)(utc.QuadPart % 10000000) * 100; - } else { - *t = 0; - *ns = 0; - } -} /* * Test if file on disk is older than entry. */ static int older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry) { - time_t sec; - long nsec; + int64_t sec; + uint32_t nsec; - fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec); + ntfs_to_unix(FILETIME_to_ntfs(&st->ftLastWriteTime), &sec, &nsec); /* First, test the seconds and return if we have a definite answer. */ /* Definitely older. */ if (sec < archive_entry_mtime(entry)) @@ -2913,11 +2892,10 @@ older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry) /* Definitely younger. */ if (sec > archive_entry_mtime(entry)) return (0); - if (nsec < archive_entry_mtime_nsec(entry)) + if ((long)nsec < archive_entry_mtime_nsec(entry)) return (1); /* Same age or newer, so not older. */ return (0); } -#endif /* _WIN32 && !__CYGWIN__ */ - +#endif /* _WIN32 && !__CYGWIN__ */ \ No newline at end of file diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index 7c95ef93b..e4d4ffd51 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -58,6 +58,7 @@ #include "archive_private.h" #include "archive_rb.h" #include "archive_string.h" +#include "archive_time_private.h" #include "archive_write_private.h" #include "archive_write_set_format_private.h" @@ -1290,20 +1291,6 @@ make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, return (ARCHIVE_OK); } - -#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) -static uint64_t -utcToFiletime(time_t t, long ns) -{ - uint64_t fileTime; - - fileTime = t; - fileTime *= 10000000; - fileTime += ns / 100; - fileTime += EPOC_TIME; - return (fileTime); -} - static int make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) { @@ -1375,7 +1362,6 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) if (r < 0) return (r); - /* * Make Times. */ @@ -1383,7 +1369,7 @@ make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) for (;file != NULL; file = file->next) { if ((file->flg & flg) == 0) continue; - archive_le64enc(filetime, utcToFiletime(file->times[ti].time, + archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time, file->times[ti].time_ns)); r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN); if (r < 0) @@ -2594,4 +2580,4 @@ compression_end(struct archive *a, struct la_zstream *lastrm) return (lastrm->end(a, lastrm)); } return (ARCHIVE_OK); -} +} \ No newline at end of file diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index 9f5b76fb9..cbf97c5b4 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -70,6 +70,7 @@ #include "archive_hmac_private.h" #include "archive_private.h" #include "archive_random_private.h" +#include "archive_time_private.h" #include "archive_write_private.h" #include "archive_write_set_format_private.h" @@ -234,7 +235,6 @@ static int archive_write_zip_header(struct archive_write *, struct archive_entry *); static int archive_write_zip_options(struct archive_write *, const char *, const char *); -static unsigned int dos_time(const time_t); static size_t path_length(struct archive_entry *); static int write_path(struct archive_entry *, struct archive_write *); static void copy_path(struct archive_entry *, unsigned char *); @@ -1127,7 +1127,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) else archive_le16enc(local_header + 8, zip->entry_compression); archive_le32enc(local_header + 10, - dos_time(archive_entry_mtime(zip->entry))); + unix_to_dos(archive_entry_mtime(zip->entry))); if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) == 0) { archive_le32enc(local_header + 14, zip->entry_crc32); archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); @@ -1158,7 +1158,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) else archive_le16enc(zip->file_header + 10, zip->entry_compression); archive_le32enc(zip->file_header + 12, - dos_time(archive_entry_mtime(zip->entry))); + unix_to_dos(archive_entry_mtime(zip->entry))); archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); /* Following Info-Zip, store mode in the "external attributes" field. */ archive_le32enc(zip->file_header + 38, @@ -2227,44 +2227,6 @@ archive_write_zip_free(struct archive_write *a) return (ARCHIVE_OK); } -/* Convert into MSDOS-style date/time. */ -static unsigned int -dos_time(const time_t unix_time) -{ - struct tm *t; - unsigned int dt; -#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S) - struct tm tmbuf; -#endif - -#if defined(HAVE_LOCALTIME_S) - t = localtime_s(&tmbuf, &unix_time) ? NULL : &tmbuf; -#elif defined(HAVE_LOCALTIME_R) - t = localtime_r(&unix_time, &tmbuf); -#else - t = localtime(&unix_time); -#endif - - /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ - if (t->tm_year < 1980 - 1900) - /* Set minimum date/time '1980-01-01 00:00:00'. */ - dt = 0x00210000U; - else if (t->tm_year > 2107 - 1900) - /* Set maximum date/time '2107-12-31 23:59:58'. */ - dt = 0xff9fbf7dU; - else { - dt = 0; - dt += ((t->tm_year - 80) & 0x7f) << 9; - dt += ((t->tm_mon + 1) & 0x0f) << 5; - dt += (t->tm_mday & 0x1f); - dt <<= 16; - dt += (t->tm_hour & 0x1f) << 11; - dt += (t->tm_min & 0x3f) << 5; - dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ - } - return dt; -} - static size_t path_length(struct archive_entry *entry) { @@ -2539,4 +2501,4 @@ is_winzip_aes_encryption_supported(int encryption) return (0); archive_hmac_sha1_cleanup(&hctx); return (1); -} +} \ No newline at end of file