]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Commonalising time-related functions. (#2553)
authorARJANEN Loïc Jean David <ljd@luigiscorner.mu>
Fri, 28 Mar 2025 14:23:43 +0000 (15:23 +0100)
committerGitHub <noreply@github.com>
Fri, 28 Mar 2025 14:23:43 +0000 (07:23 -0700)
Putting the time format conversion functions in one file and using the
common functions in the various formats.

15 files changed:
Makefile.am
libarchive/CMakeLists.txt
libarchive/archive_entry_copy_bhfi.c
libarchive/archive_match.c
libarchive/archive_read_disk_windows.c
libarchive/archive_read_support_format_7zip.c
libarchive/archive_read_support_format_lha.c
libarchive/archive_read_support_format_rar5.c
libarchive/archive_read_support_format_zip.c
libarchive/archive_time.c [new file with mode: 0644]
libarchive/archive_time_private.h [new file with mode: 0644]
libarchive/archive_windows.c
libarchive/archive_write_disk_windows.c
libarchive/archive_write_set_format_7zip.c
libarchive/archive_write_set_format_zip.c

index 8cd7a1a2edcf6305166fd48659869f95f11768d5..7860c5c50375c768e26b5f5eb96a3a95266da59e 100644 (file)
@@ -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 \
index dd0b2808d9c88a1e0ca86da061397f3b6e577d0c..fe13be1be1e7164a4d342ec6da42ccfb42fbac17 100644 (file)
@@ -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
index d5317a5eab5bdd3ee919c5f0478273e31de0f9bd..c1a9e19c238cbeee6affb660a183f29e528b4876 100644 (file)
  */
 
 #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
index 446417a9a2d45e79d52c7aa9f73979b28e02bbe5..40a083ae5c006dfd7836d435bc352b9f008123ad 100644 (file)
@@ -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
index ba7dbc6d0f0155eff578d9e6150e10c7f9ebc224..48338fa9b24f5a3c3a286235f5e3f21cff92ed76 100644 (file)
@@ -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
index b6e82e68c0efabbab84d4ffcb6245ca17be6558b..653250a3100e794ed09951b25cee339b14fb3dec 100644 (file)
@@ -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
index c7cbad272ead26de677b89a756571486390f0127..3eb4c577eae1da7e17c0a38fbb0cd40adff0e517 100644 (file)
@@ -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
index 167d7e4f42532c4a97018f80adc3999e28977fe1..6cf6fa3de5e775ff13a7f6a73dece08a9865dad5 100644 (file)
@@ -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 <blake2.h>
@@ -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
index 27e6bc051f73b29c2cd0a2031e53878b156583b2..bdfac23003db33821b069a55cb1209a7a5d13b6b 100644 (file)
@@ -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 (file)
index 0000000..cc5dc52
--- /dev/null
@@ -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 <stdlib.h>
+
+#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 <winnt.h>
+/* 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 (file)
index 0000000..63298c5
--- /dev/null
@@ -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 <stdint.h>
+
+/* 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 <windef.h>
+#include <winbase.h>
+/* 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
index bb540da011f738b4c4a960ec7597e961986300ec..03c9736c06a2cb484a6b92d4bb570e9ddeac129f 100644 (file)
@@ -47,6 +47,7 @@
 #include "archive_platform.h"
 #include "archive_private.h"
 #include "archive_entry.h"
+#include "archive_time_private.h"
 #include <ctype.h>
 #include <errno.h>
 #include <stddef.h>
@@ -61,8 +62,6 @@
 #include <windows.h>
 #include <share.h>
 
-#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);
index 472fd7310dbf878e62940aa7c834e2f2c6d6c4bb..86ea2ed8de5494e55bca1889a1f29d3bd7a71271 100644 (file)
@@ -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
index 7c95ef93b96ff3e819cf122b959bb6cda3e0bd9c..e4d4ffd51667f8ac8032a556d63936c255e2ef6b 100644 (file)
@@ -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
index 9f5b76fb96e9ca61bedae882bbb680e1aff61b04..cbf97c5b49908a0d7417db20e3db438df918c2ef 100644 (file)
@@ -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