|
18 | 18 | #include <unistd.h> |
19 | 19 | #include "otezip.h" |
20 | 20 | #include "../include/zstream.h" |
| 21 | +#include "time.inc.c" |
21 | 22 |
|
22 | 23 | #if defined(_WIN32) || defined(_WIN64) |
23 | 24 | /* Ensure we have thread-safe fallback for localtime on Windows builds */ |
@@ -84,119 +85,6 @@ int otezip_ignore_zipbomb = 0; |
84 | 85 |
|
85 | 86 | /* helper: little-endian readers/writers (ZIP format is little-endian) */ |
86 | 87 |
|
87 | | -/* Date/time conversion for ZIP entries */ |
88 | | -/* Convert current time to DOS date/time fields. |
89 | | - * The DOS date format stores year as an offset from 1980 in 7 bits |
90 | | - *(0..127 -> 1980..2107). To avoid generating out-of-range values or |
91 | | - * relying on unchecked `time_t` behaviour on 32-bit platforms, this |
92 | | - * implementation validates and clamps fields. If time retrieval or |
93 | | - * conversion fails, it falls back to 1980-01-01 00:00:00. |
94 | | - */ |
95 | | -/* Provide a small portable wrapper for thread-safe localtime when possible. |
96 | | - * On POSIX systems prefer `localtime_r`; on Windows or when not available, |
97 | | - * fall back to `localtime ()` and copy the result into the caller buffer. */ |
98 | | -static struct tm *otezip_localtime_r(const time_t *t, struct tm *out) { |
99 | | - /* Portable fallback: use non-reentrant `localtime ()` and copy the result. |
100 | | - * This avoids implicit declaration issues on platforms that don't expose |
101 | | - * `localtime_r` while remaining simple for this small utility. */ |
102 | | - struct tm *tmp = localtime (t); |
103 | | - if (!tmp) { |
104 | | - return NULL; |
105 | | - } |
106 | | - *out = *tmp; |
107 | | - return out; |
108 | | -} |
109 | | - |
110 | | -static void otezip_get_dostime(uint16_t *dos_time, uint16_t *dos_date) { |
111 | | - time_t now = time (NULL); |
112 | | - struct tm tm_buf; |
113 | | - struct tm *tm_ptr = NULL; |
114 | | - |
115 | | - /* Prefer reentrant version when available */ |
116 | | - if (now != (time_t)-1 && otezip_localtime_r (&now, &tm_buf) != NULL) { |
117 | | - tm_ptr = &tm_buf; |
118 | | - } |
119 | | - if (!tm_ptr && now != (time_t)-1) { |
120 | | - struct tm *tmp = localtime (&now); |
121 | | - if (tmp) { |
122 | | - /* copy into stack buffer to have a consistent pointer */ |
123 | | - tm_buf = *tmp; |
124 | | - tm_ptr = &tm_buf; |
125 | | - } |
126 | | - } |
127 | | - |
128 | | - /* Default to DOS epoch start if anything fails */ |
129 | | - if (!tm_ptr) { |
130 | | - *dos_time = 0; /* 00:00:00 -> all zero */ |
131 | | - *dos_date = 0; /* 1980-01-01 -> year offset 0, month 1, day 1 */ |
132 | | - /* encode date: year offset 0, month 1, day 1 */ |
133 | | - *dos_date = (uint16_t) (((0) << 9) | ((1) << 5) | 1); |
134 | | - return; |
135 | | - } |
136 | | - |
137 | | - /* Extract and clamp fields to valid ranges to avoid overflow or |
138 | | - * nonsensical dates on platforms with limited time_t ranges. */ |
139 | | - int year = tm_ptr->tm_year + 1900; /* full year */ |
140 | | - int year_off = year - 1980; |
141 | | - if (year_off < 0) { |
142 | | - year_off = 0; |
143 | | - } |
144 | | - if (year_off > 127) { |
145 | | - year_off = 127; /* DOS stores 7 bits */ |
146 | | - } |
147 | | - |
148 | | - int mon = tm_ptr->tm_mon + 1; |
149 | | - if (mon < 1) { |
150 | | - mon = 1; |
151 | | - } |
152 | | - if (mon > 12) { |
153 | | - mon = 12; |
154 | | - } |
155 | | - |
156 | | - int day = tm_ptr->tm_mday; |
157 | | - if (day < 1) { |
158 | | - day = 1; |
159 | | - } |
160 | | - if (day > 31) { |
161 | | - day = 31; |
162 | | - } |
163 | | - |
164 | | - int hour = tm_ptr->tm_hour; |
165 | | - if (hour < 0) { |
166 | | - hour = 0; |
167 | | - } |
168 | | - if (hour > 23) { |
169 | | - hour = 23; |
170 | | - } |
171 | | - |
172 | | - int min = tm_ptr->tm_min; |
173 | | - if (min < 0) { |
174 | | - min = 0; |
175 | | - } |
176 | | - if (min > 59) { |
177 | | - min = 59; |
178 | | - } |
179 | | - |
180 | | - int sec = tm_ptr->tm_sec; |
181 | | - if (sec < 0) { |
182 | | - sec = 0; |
183 | | - } |
184 | | - if (sec > 59) { |
185 | | - sec = 59; |
186 | | - } |
187 | | - |
188 | | - /* DOS time stores seconds divided by 2 */ |
189 | | - int sec2 = sec / 2; |
190 | | - if (sec2 < 0) { |
191 | | - sec2 = 0; |
192 | | - } |
193 | | - if (sec2 > 29) { |
194 | | - sec2 = 29; |
195 | | - } |
196 | | - |
197 | | - *dos_time = (uint16_t) ((hour << 11) | (min << 5) | sec2); |
198 | | - *dos_date = (uint16_t) ((year_off << 9) | (mon << 5) | day); |
199 | | -} |
200 | 88 | static uint16_t otezip_rd16(const uint8_t *p) { |
201 | 89 | return (uint16_t) (p[0] | (p[1] << 8)); |
202 | 90 | } |
|
0 commit comments