/src/CMake/Utilities/cmlibarchive/libarchive/archive_time.c
Line | Count | Source |
1 | | /*- |
2 | | * Copyright © 2025 ARJANEN Loïc Jean David |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without |
6 | | * modification, are permitted provided that the following conditions |
7 | | * are met: |
8 | | * 1. Redistributions of source code must retain the above copyright |
9 | | * notice, this list of conditions and the following disclaimer. |
10 | | * 2. Redistributions in binary form must reproduce the above copyright |
11 | | * notice, this list of conditions and the following disclaimer in the |
12 | | * documentation and/or other materials provided with the distribution. |
13 | | * |
14 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR |
15 | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
16 | | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
17 | | * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, |
18 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
19 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
20 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
21 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
23 | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | | */ |
25 | | |
26 | | #include "archive_platform.h" |
27 | | #include "archive_private.h" |
28 | | #include "archive_time_private.h" |
29 | | #include <limits.h> |
30 | | #include <stdlib.h> |
31 | | #include <string.h> |
32 | | |
33 | 324 | #define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600) |
34 | 798 | #define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000) |
35 | 324 | #define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS) |
36 | 0 | #define DOS_MIN_TIME 0x00210000U |
37 | 0 | #define DOS_MAX_TIME 0xff9fbf7dU |
38 | | |
39 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
40 | | #include <winnt.h> |
41 | | /* Windows FILETIME to NTFS time. */ |
42 | | uint64_t |
43 | | FILETIME_to_ntfs(const FILETIME* filetime) |
44 | | { |
45 | | ULARGE_INTEGER utc; |
46 | | utc.HighPart = filetime->dwHighDateTime; |
47 | | utc.LowPart = filetime->dwLowDateTime; |
48 | | return utc.QuadPart; |
49 | | } |
50 | | #endif |
51 | | |
52 | | /* Convert an MSDOS-style date/time into Unix-style time. */ |
53 | | int64_t |
54 | | dos_to_unix(uint32_t dos_time) |
55 | 4.98k | { |
56 | 4.98k | uint16_t msTime, msDate; |
57 | 4.98k | struct tm ts; |
58 | 4.98k | time_t t; |
59 | | |
60 | 4.98k | msTime = (0xFFFF & dos_time); |
61 | 4.98k | msDate = (dos_time >> 16); |
62 | | |
63 | 4.98k | memset(&ts, 0, sizeof(ts)); |
64 | 4.98k | ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ |
65 | 4.98k | ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ |
66 | 4.98k | ts.tm_mday = msDate & 0x1f; /* Day of month. */ |
67 | 4.98k | ts.tm_hour = (msTime >> 11) & 0x1f; |
68 | 4.98k | ts.tm_min = (msTime >> 5) & 0x3f; |
69 | 4.98k | ts.tm_sec = (msTime << 1) & 0x3e; |
70 | 4.98k | ts.tm_isdst = -1; |
71 | 4.98k | t = mktime(&ts); |
72 | 4.98k | return (int64_t)(t == (time_t)-1 ? INT32_MAX : t); |
73 | 4.98k | } |
74 | | |
75 | | /* Convert into MSDOS-style date/time. */ |
76 | | uint32_t |
77 | | unix_to_dos(int64_t unix_time) |
78 | 0 | { |
79 | 0 | struct tm *t; |
80 | 0 | uint32_t dt; |
81 | 0 | time_t ut = unix_time; |
82 | 0 | #if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S) |
83 | 0 | struct tm tmbuf; |
84 | 0 | #endif |
85 | |
|
86 | 0 | if (sizeof(time_t) < sizeof(int64_t) && (int64_t)ut != unix_time) { |
87 | 0 | ut = (time_t)(unix_time > 0 ? INT32_MAX : INT32_MIN); |
88 | 0 | } |
89 | |
|
90 | | #if defined(HAVE_LOCALTIME_S) |
91 | | t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf; |
92 | | #elif defined(HAVE_LOCALTIME_R) |
93 | | t = localtime_r(&ut, &tmbuf); |
94 | | #else |
95 | | t = localtime(&ut); |
96 | | #endif |
97 | 0 | dt = 0; |
98 | 0 | if (t != NULL && t->tm_year >= INT_MIN + 80) { |
99 | 0 | const int year = t->tm_year - 80; |
100 | |
|
101 | 0 | if (year & ~0x7f) { |
102 | 0 | dt = year > 0 ? DOS_MAX_TIME : DOS_MIN_TIME; |
103 | 0 | } |
104 | 0 | else { |
105 | 0 | dt += (year & 0x7f) << 9; |
106 | 0 | dt += ((t->tm_mon + 1) & 0x0f) << 5; |
107 | 0 | dt += (t->tm_mday & 0x1f); |
108 | 0 | dt <<= 16; |
109 | 0 | dt += (t->tm_hour & 0x1f) << 11; |
110 | 0 | dt += (t->tm_min & 0x3f) << 5; |
111 | | /* Only counting every 2 seconds. */ |
112 | 0 | dt += (t->tm_sec & 0x3e) >> 1; |
113 | 0 | } |
114 | 0 | } |
115 | 0 | if (dt > DOS_MAX_TIME) { |
116 | 0 | dt = DOS_MAX_TIME; |
117 | 0 | } |
118 | 0 | else if (dt < DOS_MIN_TIME) { |
119 | 0 | dt = DOS_MIN_TIME; |
120 | 0 | } |
121 | 0 | return dt; |
122 | 0 | } |
123 | | |
124 | | /* Convert NTFS time to Unix sec/nsec */ |
125 | | void |
126 | | ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs) |
127 | 324 | { |
128 | 324 | if (ntfs > INT64_MAX) { |
129 | 150 | ntfs -= NTFS_EPOC_TICKS; |
130 | 150 | *secs = ntfs / NTFS_TICKS; |
131 | 150 | *nsecs = 100 * (ntfs % NTFS_TICKS); |
132 | 150 | } |
133 | 174 | else { |
134 | 174 | lldiv_t tdiv; |
135 | 174 | int64_t value = (int64_t)ntfs - (int64_t)NTFS_EPOC_TICKS; |
136 | | |
137 | 174 | tdiv = lldiv(value, NTFS_TICKS); |
138 | 174 | *secs = tdiv.quot; |
139 | 174 | *nsecs = (uint32_t)(tdiv.rem * 100); |
140 | 174 | } |
141 | 324 | } |
142 | | |
143 | | /* Convert Unix sec/nsec to NTFS time */ |
144 | | uint64_t |
145 | | unix_to_ntfs(int64_t secs, uint32_t nsecs) |
146 | 0 | { |
147 | 0 | uint64_t ntfs; |
148 | |
|
149 | 0 | if (secs < -(int64_t)NTFS_EPOC_TIME) |
150 | 0 | return 0; |
151 | | |
152 | 0 | ntfs = secs + NTFS_EPOC_TIME; |
153 | |
|
154 | 0 | if (ntfs > UINT64_MAX / NTFS_TICKS) |
155 | 0 | return UINT64_MAX; |
156 | | |
157 | 0 | ntfs *= NTFS_TICKS; |
158 | |
|
159 | 0 | if (ntfs > UINT64_MAX - nsecs/100) |
160 | 0 | return UINT64_MAX; |
161 | | |
162 | 0 | return ntfs + nsecs/100; |
163 | 0 | } |