Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : time handling functions
4 :
5 : Copyright (C) Andrew Tridgell 1992-2004
6 : Copyright (C) Stefan (metze) Metzmacher 2002
7 : Copyright (C) Jeremy Allison 2007
8 : Copyright (C) Andrew Bartlett 2011
9 :
10 : This program is free software; you can redistribute it and/or modify
11 : it under the terms of the GNU General Public License as published by
12 : the Free Software Foundation; either version 3 of the License, or
13 : (at your option) any later version.
14 :
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "replace.h"
25 : #include "system/time.h"
26 : #include "byteorder.h"
27 : #include "time_basic.h"
28 : #include "lib/util/time.h" /* Avoid /usr/include/time.h */
29 : #include <sys/stat.h>
30 : #ifndef NO_CONFIG_H
31 : #include "config.h"
32 : #endif
33 :
34 : /**
35 : * @file
36 : * @brief time handling functions
37 : */
38 :
39 : #define TIME_FIXUP_CONSTANT_INT INT64_C(11644473600)
40 :
41 :
42 : #define NSEC_PER_SEC 1000000000
43 :
44 : /**
45 : External access to time_t_min and time_t_max.
46 : **/
47 395819 : _PUBLIC_ time_t get_time_t_max(void)
48 : {
49 395819 : return TIME_T_MAX;
50 : }
51 :
52 : /**
53 : a wrapper to preferably get the monotonic time
54 : **/
55 429481136 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
56 : {
57 : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
58 : #ifdef CLOCK_BOOTTIME
59 429481136 : if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
60 429083262 : return;
61 : }
62 : #endif
63 : /* then try the monotonic clock: */
64 : #ifndef CUSTOM_CLOCK_MONOTONIC_IS_REALTIME
65 0 : if (clock_gettime(CUSTOM_CLOCK_MONOTONIC,tp) == 0) {
66 0 : return;
67 : }
68 : #endif
69 0 : clock_gettime(CLOCK_REALTIME,tp);
70 : }
71 :
72 : /**
73 : a wrapper to preferably get the monotonic time in seconds
74 : **/
75 7788 : _PUBLIC_ time_t time_mono(time_t *t)
76 : {
77 0 : struct timespec tp;
78 :
79 7788 : clock_gettime_mono(&tp);
80 7788 : if (t != NULL) {
81 0 : *t = tp.tv_sec;
82 : }
83 7788 : return tp.tv_sec;
84 : }
85 :
86 :
87 : #define TIME_FIXUP_CONSTANT 11644473600LL
88 :
89 3223022 : time_t convert_timespec_to_time_t(struct timespec ts)
90 : {
91 : /* Ensure tv_nsec is less than 1sec. */
92 3223022 : normalize_timespec(&ts);
93 :
94 : /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
95 : increment if it's greater than 500 millionth of a second. */
96 :
97 3223022 : if (ts.tv_nsec > 500000000) {
98 287963 : return ts.tv_sec + 1;
99 : }
100 2935059 : return ts.tv_sec;
101 : }
102 :
103 0 : struct timespec convert_time_t_to_timespec(time_t t)
104 : {
105 0 : struct timespec ts;
106 0 : ts.tv_sec = t;
107 0 : ts.tv_nsec = 0;
108 0 : return ts;
109 : }
110 :
111 :
112 :
113 : /**
114 : Interpret an 8 byte "filetime" structure to a time_t
115 : It's originally in "100ns units since jan 1st 1601"
116 :
117 : An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
118 :
119 : tv_sec = 0
120 : tv_nsec = 0;
121 :
122 : Returns GMT.
123 : **/
124 2733399 : time_t nt_time_to_unix(NTTIME nt)
125 : {
126 2733399 : return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
127 : }
128 :
129 :
130 : /**
131 : put a 8 byte filetime from a time_t
132 : This takes GMT as input
133 : **/
134 7002284 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
135 : {
136 265057 : uint64_t t2;
137 :
138 7002284 : if (t == (time_t)-1) {
139 1 : *nt = UINT64_MAX;
140 1 : return;
141 : }
142 :
143 7002283 : if (t == TIME_T_MAX || t == INT64_MAX) {
144 60760 : *nt = 0x7fffffffffffffffLL;
145 60760 : return;
146 : }
147 :
148 6941523 : if (t == 0) {
149 21784 : *nt = 0;
150 21784 : return;
151 : }
152 :
153 6919739 : t2 = t;
154 6919739 : t2 += TIME_FIXUP_CONSTANT_INT;
155 6919739 : t2 *= 1000*1000*10;
156 :
157 6919739 : *nt = t2;
158 : }
159 :
160 :
161 : /**
162 : check if it's a null unix time
163 : **/
164 913025 : _PUBLIC_ bool null_time(time_t t)
165 : {
166 84927 : return t == 0 ||
167 996462 : t == (time_t)0xFFFFFFFF ||
168 : t == (time_t)-1;
169 : }
170 :
171 :
172 : /**
173 : check if it's a null NTTIME
174 : **/
175 2500419 : _PUBLIC_ bool null_nttime(NTTIME t)
176 : {
177 2500419 : return t == 0;
178 : }
179 :
180 : /*******************************************************************
181 : create a 16 bit dos packed date
182 : ********************************************************************/
183 440962 : static uint16_t make_dos_date1(struct tm *t)
184 : {
185 440962 : uint16_t ret=0;
186 440962 : ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
187 440962 : ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
188 440962 : return ret;
189 : }
190 :
191 : /*******************************************************************
192 : create a 16 bit dos packed time
193 : ********************************************************************/
194 440962 : static uint16_t make_dos_time1(struct tm *t)
195 : {
196 440962 : uint16_t ret=0;
197 440962 : ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
198 440962 : ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
199 440962 : return ret;
200 : }
201 :
202 : /*******************************************************************
203 : create a 32 bit dos packed date/time from some parameters
204 : This takes a GMT time and returns a packed localtime structure
205 : ********************************************************************/
206 441090 : static uint32_t make_dos_date(time_t unixdate, int zone_offset)
207 : {
208 223 : struct tm *t;
209 441090 : uint32_t ret=0;
210 :
211 441090 : if (unixdate == 0) {
212 111 : return 0;
213 : }
214 :
215 440962 : unixdate -= zone_offset;
216 :
217 440962 : t = gmtime(&unixdate);
218 440962 : if (!t) {
219 0 : return 0xFFFFFFFF;
220 : }
221 :
222 440962 : ret = make_dos_date1(t);
223 440962 : ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
224 :
225 440962 : return ret;
226 : }
227 :
228 : /**
229 : put a dos date into a buffer (time/date format)
230 : This takes GMT time and puts local time in the buffer
231 : **/
232 33632 : _PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
233 : {
234 33632 : uint32_t x = make_dos_date(unixdate, zone_offset);
235 33632 : SIVAL(buf,offset,x);
236 33632 : }
237 :
238 : /**
239 : put a dos date into a buffer (date/time format)
240 : This takes GMT time and puts local time in the buffer
241 : **/
242 407458 : _PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
243 : {
244 206 : uint32_t x;
245 407458 : x = make_dos_date(unixdate, zone_offset);
246 407458 : x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
247 407458 : SIVAL(buf,offset,x);
248 407458 : }
249 :
250 : /**
251 : put a dos 32 bit "unix like" date into a buffer. This routine takes
252 : GMT and converts it to LOCAL time before putting it (most SMBs assume
253 : localtime for this sort of date)
254 : **/
255 169215 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
256 : {
257 169215 : if (!null_time(unixdate)) {
258 29168 : unixdate -= zone_offset;
259 : }
260 169215 : SIVAL(buf,offset,unixdate);
261 169215 : }
262 :
263 : /*******************************************************************
264 : interpret a 32 bit dos packed date/time to some parameters
265 : ********************************************************************/
266 440823 : void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
267 : {
268 195 : uint32_t p0,p1,p2,p3;
269 :
270 440823 : p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
271 440823 : p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
272 :
273 440823 : *second = 2*(p0 & 0x1F);
274 440823 : *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
275 440823 : *hour = (p1>>3)&0xFF;
276 440823 : *day = (p2&0x1F);
277 440823 : *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
278 440823 : *year = ((p3>>1)&0xFF) + 80;
279 440823 : }
280 :
281 : /**
282 : create a unix date (int GMT) from a dos date (which is actually in
283 : localtime)
284 : **/
285 440894 : _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
286 : {
287 440894 : uint32_t dos_date=0;
288 195 : struct tm t;
289 195 : time_t ret;
290 :
291 440894 : dos_date = IVAL(date_ptr,0);
292 :
293 440894 : if (dos_date == 0) return (time_t)0;
294 :
295 440823 : interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
296 : &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
297 440823 : t.tm_isdst = -1;
298 :
299 440823 : ret = timegm(&t);
300 :
301 440823 : ret += zone_offset;
302 :
303 440823 : return ret;
304 : }
305 :
306 : /**
307 : like make_unix_date() but the words are reversed
308 : **/
309 407355 : _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
310 : {
311 195 : uint32_t x,x2;
312 :
313 407355 : x = IVAL(date_ptr,0);
314 407355 : x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
315 407355 : SIVAL(&x,0,x2);
316 :
317 407355 : return pull_dos_date((const uint8_t *)&x, zone_offset);
318 : }
319 :
320 : /**
321 : create a unix GMT date from a dos date in 32 bit "unix like" format
322 : these generally arrive as localtimes, with corresponding DST
323 : **/
324 147547 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
325 : {
326 147547 : time_t t = (time_t)IVAL(date_ptr,0);
327 :
328 147547 : if (t == (time_t)0xFFFFFFFF) {
329 4096 : t = (time_t)-1;
330 : }
331 :
332 147547 : if (!null_time(t)) {
333 27784 : t += zone_offset;
334 : }
335 147547 : return t;
336 : }
337 :
338 : /****************************************************************************
339 : Return the date and time as a string
340 : ****************************************************************************/
341 :
342 218 : char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
343 : {
344 36 : struct timeval_buf tmp;
345 36 : char *result;
346 :
347 218 : result = talloc_strdup(ctx, timeval_str_buf(tp, false, hires, &tmp));
348 218 : if (result == NULL) {
349 0 : return NULL;
350 : }
351 :
352 : /*
353 : * beautify the talloc_report output
354 : *
355 : * This is not just cosmetics. A C compiler might in theory make the
356 : * talloc_strdup call above a tail call with the tail call
357 : * optimization. This would render "tmp" invalid while talloc_strdup
358 : * tries to duplicate it. The talloc_set_name_const call below puts
359 : * the talloc_strdup call into non-tail position.
360 : */
361 218 : talloc_set_name_const(result, result);
362 218 : return result;
363 : }
364 :
365 : /****************************************************************************
366 : Return the date and time as a string
367 : ****************************************************************************/
368 :
369 173 : const char *timespec_string_buf(const struct timespec *tp,
370 : bool hires,
371 : struct timeval_buf *buf)
372 : {
373 1 : time_t t;
374 173 : struct tm *tm = NULL;
375 1 : int len;
376 :
377 173 : if (is_omit_timespec(tp)) {
378 0 : strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf));
379 0 : return buf->buf;
380 : }
381 :
382 173 : t = (time_t)tp->tv_sec;
383 173 : tm = localtime(&t);
384 :
385 173 : if (tm == NULL) {
386 0 : if (hires) {
387 0 : len = snprintf(buf->buf, sizeof(buf->buf),
388 : "%ld.%09ld seconds since the Epoch",
389 0 : (long)tp->tv_sec, (long)tp->tv_nsec);
390 : } else {
391 0 : len = snprintf(buf->buf, sizeof(buf->buf),
392 : "%ld seconds since the Epoch", (long)t);
393 : }
394 173 : } else if (!hires) {
395 0 : len = snprintf(buf->buf, sizeof(buf->buf),
396 : "%04d-%02d-%02d %02d:%02d:%02d",
397 0 : 1900 + tm->tm_year,
398 0 : tm->tm_mon + 1,
399 : tm->tm_mday,
400 : tm->tm_hour,
401 : tm->tm_min,
402 : tm->tm_sec);
403 : } else {
404 173 : len = snprintf(buf->buf, sizeof(buf->buf),
405 : "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
406 173 : 1900 + tm->tm_year,
407 173 : tm->tm_mon + 1,
408 : tm->tm_mday,
409 : tm->tm_hour,
410 : tm->tm_min,
411 : tm->tm_sec,
412 173 : (long)tp->tv_nsec);
413 : }
414 173 : if (len == -1) {
415 0 : return "";
416 : }
417 :
418 173 : return buf->buf;
419 : }
420 :
421 218 : char *current_timestring(TALLOC_CTX *ctx, bool hires)
422 : {
423 36 : struct timeval tv;
424 :
425 218 : GetTimeOfDay(&tv);
426 218 : return timeval_string(ctx, &tv, hires);
427 : }
428 :
429 : /*
430 : * Return date and time as a minimal string avoiding funny characters
431 : * that may cause trouble in file names. We only use digits and
432 : * underscore ... or a minus/hyphen if we got negative time.
433 : */
434 166 : char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
435 : {
436 2 : time_t t;
437 2 : struct tm *tm;
438 :
439 166 : t = (time_t)tp->tv_sec;
440 166 : tm = localtime(&t);
441 166 : if (!tm) {
442 0 : if (hires) {
443 0 : return talloc_asprintf(ctx, "%ld_%06ld",
444 0 : (long)tp->tv_sec,
445 0 : (long)tp->tv_usec);
446 : } else {
447 0 : return talloc_asprintf(ctx, "%ld", (long)t);
448 : }
449 : } else {
450 166 : if (hires) {
451 1 : return talloc_asprintf(ctx,
452 : "%04d%02d%02d_%02d%02d%02d_%06ld",
453 1 : tm->tm_year+1900,
454 1 : tm->tm_mon+1,
455 : tm->tm_mday,
456 : tm->tm_hour,
457 : tm->tm_min,
458 : tm->tm_sec,
459 1 : (long)tp->tv_usec);
460 : } else {
461 165 : return talloc_asprintf(ctx,
462 : "%04d%02d%02d_%02d%02d%02d",
463 165 : tm->tm_year+1900,
464 165 : tm->tm_mon+1,
465 : tm->tm_mday,
466 : tm->tm_hour,
467 : tm->tm_min,
468 : tm->tm_sec);
469 : }
470 : }
471 : }
472 :
473 164 : char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
474 : {
475 0 : struct timeval tv;
476 :
477 164 : GetTimeOfDay(&tv);
478 164 : return minimal_timeval_string(ctx, &tv, hires);
479 : }
480 :
481 : /**
482 : return a HTTP/1.0 time string
483 : **/
484 545 : _PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t)
485 : {
486 2 : char *buf;
487 2 : char tempTime[60];
488 545 : struct tm *tm = localtime(&t);
489 :
490 545 : if (t == TIME_T_MAX) {
491 7 : return talloc_strdup(mem_ctx, "never");
492 : }
493 :
494 538 : if (!tm) {
495 0 : return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t);
496 : }
497 :
498 : #ifndef HAVE_STRFTIME
499 : buf = talloc_strdup(mem_ctx, asctime(tm));
500 : if (buf[strlen(buf)-1] == '\n') {
501 : buf[strlen(buf)-1] = 0;
502 : }
503 : #else
504 538 : strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
505 538 : buf = talloc_strdup(mem_ctx, tempTime);
506 : #endif /* !HAVE_STRFTIME */
507 :
508 538 : return buf;
509 : }
510 :
511 : /**
512 : Return the date and time as a string
513 : **/
514 285691 : _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t)
515 : {
516 4224 : char *TimeBuf;
517 4224 : char tempTime[80];
518 4224 : struct tm *tm;
519 :
520 285691 : tm = localtime(&t);
521 285691 : if (!tm) {
522 0 : return talloc_asprintf(mem_ctx,
523 : "%ld seconds since the Epoch",
524 : (long)t);
525 : }
526 :
527 : #ifdef HAVE_STRFTIME
528 : /* Some versions of gcc complain about using some special format
529 : * specifiers. This is a bug in gcc, not a bug in this code. See a
530 : * recent strftime() manual page for details. */
531 285691 : strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
532 285691 : TimeBuf = talloc_strdup(mem_ctx, tempTime);
533 : #else
534 : TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
535 : if (TimeBuf == NULL) {
536 : return NULL;
537 : }
538 : if (TimeBuf[0] != '\0') {
539 : size_t len = strlen(TimeBuf);
540 : if (TimeBuf[len - 1] == '\n') {
541 : TimeBuf[len - 1] = '\0';
542 : }
543 : }
544 : #endif
545 :
546 285691 : return TimeBuf;
547 : }
548 :
549 : /**
550 : return a talloced string representing a NTTIME for human consumption
551 : */
552 264737 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
553 : {
554 5318 : time_t t;
555 264737 : if (nt == 0) {
556 6998 : return "NTTIME(0)";
557 : }
558 256403 : t = nt_time_to_full_time_t(nt);
559 256403 : return timestring(mem_ctx, t);
560 : }
561 :
562 :
563 : /**
564 : put a NTTIME into a packet
565 : */
566 426092 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
567 : {
568 426092 : SBVAL(base, offset, t);
569 426092 : }
570 :
571 : /**
572 : pull a NTTIME from a packet
573 : */
574 2204 : _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
575 : {
576 2204 : NTTIME ret = BVAL(base, offset);
577 2204 : return ret;
578 : }
579 :
580 : /**
581 : return (tv1 - tv2) in microseconds
582 : */
583 395053 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
584 : {
585 395053 : int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
586 395053 : return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
587 : }
588 :
589 : /**
590 : return (tp1 - tp2) in nanoseconds
591 : */
592 214410326 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
593 : {
594 214410326 : int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
595 214410326 : return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
596 : }
597 :
598 :
599 : /**
600 : return a zero timeval
601 : */
602 139029 : _PUBLIC_ struct timeval timeval_zero(void)
603 : {
604 2476 : struct timeval tv;
605 139029 : tv.tv_sec = 0;
606 139029 : tv.tv_usec = 0;
607 139029 : return tv;
608 : }
609 :
610 : /**
611 : return true if a timeval is zero
612 : */
613 1301307 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
614 : {
615 1301307 : return tv->tv_sec == 0 && tv->tv_usec == 0;
616 : }
617 :
618 : /**
619 : return a timeval for the current time
620 : */
621 15501715 : _PUBLIC_ struct timeval timeval_current(void)
622 : {
623 715315 : struct timeval tv;
624 15501715 : GetTimeOfDay(&tv);
625 15501715 : return tv;
626 : }
627 :
628 : /**
629 : return a timeval struct with the given elements
630 : */
631 93788 : _PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs)
632 : {
633 2526 : struct timeval tv;
634 93788 : tv.tv_sec = secs;
635 93788 : tv.tv_usec = usecs;
636 93788 : return tv;
637 : }
638 :
639 :
640 : /**
641 : return a timeval ofs microseconds after tv
642 : */
643 8074167 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
644 : uint32_t secs, uint32_t usecs)
645 : {
646 8074167 : struct timeval tv2 = *tv;
647 8074167 : const unsigned int million = 1000000;
648 8074167 : tv2.tv_sec += secs;
649 8074167 : tv2.tv_usec += usecs;
650 8074167 : tv2.tv_sec += tv2.tv_usec / million;
651 8074167 : tv2.tv_usec = tv2.tv_usec % million;
652 8074167 : return tv2;
653 : }
654 :
655 : /**
656 : return the sum of two timeval structures
657 : */
658 111160 : struct timeval timeval_sum(const struct timeval *tv1,
659 : const struct timeval *tv2)
660 : {
661 111160 : return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
662 : }
663 :
664 : /**
665 : return a timeval secs/usecs into the future
666 : */
667 2611690 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
668 : {
669 2611690 : struct timeval tv = timeval_current();
670 2611690 : return timeval_add(&tv, secs, usecs);
671 : }
672 :
673 : /**
674 : return a timeval milliseconds into the future
675 : */
676 4494047 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
677 : {
678 4494047 : struct timeval tv = timeval_current();
679 4494047 : return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
680 : }
681 :
682 : /**
683 : return a timeval microseconds into the future
684 : */
685 461209 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
686 : {
687 461209 : struct timeval tv = timeval_current();
688 461209 : return timeval_add(&tv, usecs / 1000000, usecs % 1000000);
689 : }
690 :
691 : /**
692 : compare two timeval structures.
693 : Return -1 if tv1 < tv2
694 : Return 0 if tv1 == tv2
695 : Return 1 if tv1 > tv2
696 : */
697 8353 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
698 : {
699 8353 : if (tv1->tv_sec > tv2->tv_sec) return 1;
700 7416 : if (tv1->tv_sec < tv2->tv_sec) return -1;
701 7269 : if (tv1->tv_usec > tv2->tv_usec) return 1;
702 3750 : if (tv1->tv_usec < tv2->tv_usec) return -1;
703 8 : return 0;
704 : }
705 :
706 : /**
707 : return true if a timer is in the past
708 : */
709 1013318 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
710 : {
711 1013318 : struct timeval tv2 = timeval_current();
712 1013318 : if (tv2.tv_sec > tv->tv_sec) return true;
713 1013250 : if (tv2.tv_sec < tv->tv_sec) return false;
714 3021 : return (tv2.tv_usec >= tv->tv_usec);
715 : }
716 :
717 : /**
718 : return the number of seconds elapsed between two times
719 : */
720 786177 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
721 : {
722 984058 : return (tv2->tv_sec - tv1->tv_sec) +
723 786177 : (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
724 : }
725 :
726 : /**
727 : return the number of seconds elapsed since a given time
728 : */
729 785730 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
730 : {
731 785730 : struct timeval tv2 = timeval_current();
732 785730 : return timeval_elapsed2(tv, &tv2);
733 : }
734 : /**
735 : * return the number of seconds elapsed between two times
736 : **/
737 535 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
738 : const struct timespec *ts2)
739 : {
740 1063 : return (ts2->tv_sec - ts1->tv_sec) +
741 535 : (ts2->tv_nsec - ts1->tv_nsec)*1.0e-9;
742 : }
743 :
744 : /**
745 : * return the number of seconds elapsed since a given time
746 : */
747 12 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
748 : {
749 12 : struct timespec ts2 = timespec_current();
750 12 : return timespec_elapsed2(ts, &ts2);
751 : }
752 :
753 : /**
754 : return the lesser of two timevals
755 : */
756 3977 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
757 : const struct timeval *tv2)
758 : {
759 3977 : if (tv1->tv_sec < tv2->tv_sec) return *tv1;
760 3597 : if (tv1->tv_sec > tv2->tv_sec) return *tv2;
761 3507 : if (tv1->tv_usec < tv2->tv_usec) return *tv1;
762 0 : return *tv2;
763 : }
764 :
765 : /**
766 : return the greater of two timevals
767 : */
768 0 : _PUBLIC_ struct timeval timeval_max(const struct timeval *tv1,
769 : const struct timeval *tv2)
770 : {
771 0 : if (tv1->tv_sec > tv2->tv_sec) return *tv1;
772 0 : if (tv1->tv_sec < tv2->tv_sec) return *tv2;
773 0 : if (tv1->tv_usec > tv2->tv_usec) return *tv1;
774 0 : return *tv2;
775 : }
776 :
777 : /**
778 : return the difference between two timevals as a timeval
779 : if tv1 comes after tv2, then return a zero timeval
780 : (this is *tv2 - *tv1)
781 : */
782 135 : _PUBLIC_ struct timeval timeval_until(const struct timeval *tv1,
783 : const struct timeval *tv2)
784 : {
785 0 : struct timeval t;
786 135 : if (timeval_compare(tv1, tv2) >= 0) {
787 0 : return timeval_zero();
788 : }
789 135 : t.tv_sec = tv2->tv_sec - tv1->tv_sec;
790 135 : if (tv1->tv_usec > tv2->tv_usec) {
791 0 : t.tv_sec--;
792 0 : t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
793 : } else {
794 135 : t.tv_usec = tv2->tv_usec - tv1->tv_usec;
795 : }
796 135 : return t;
797 : }
798 :
799 :
800 : /**
801 : convert a timeval to a NTTIME
802 : */
803 7832631 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
804 : {
805 15590813 : return 10*(tv->tv_usec +
806 7832631 : ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
807 : }
808 :
809 : /**
810 : convert a NTTIME to a timeval
811 : */
812 75682 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
813 : {
814 75682 : if (tv == NULL) return;
815 :
816 75682 : t += 10/2;
817 75682 : t /= 10;
818 75682 : t -= TIME_FIXUP_CONSTANT*1000*1000;
819 :
820 75682 : tv->tv_sec = t / 1000000;
821 :
822 75682 : if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) {
823 0 : tv->tv_sec = 0;
824 0 : tv->tv_usec = 0;
825 0 : return;
826 : }
827 :
828 75682 : tv->tv_usec = t - tv->tv_sec*1000000;
829 : }
830 :
831 : /*******************************************************************
832 : yield the difference between *A and *B, in seconds, ignoring leap seconds
833 : ********************************************************************/
834 15196 : static int tm_diff(struct tm *a, struct tm *b)
835 : {
836 15196 : int ay = a->tm_year + (1900 - 1);
837 15196 : int by = b->tm_year + (1900 - 1);
838 15196 : int intervening_leap_days =
839 15196 : (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
840 15196 : int years = ay - by;
841 15196 : int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
842 15196 : int hours = 24*days + (a->tm_hour - b->tm_hour);
843 15196 : int minutes = 60*hours + (a->tm_min - b->tm_min);
844 15196 : int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
845 :
846 15196 : return seconds;
847 : }
848 :
849 :
850 : /**
851 : return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
852 : */
853 15196 : _PUBLIC_ int get_time_zone(time_t t)
854 : {
855 15196 : struct tm *tm = gmtime(&t);
856 268 : struct tm tm_utc;
857 15196 : if (!tm)
858 0 : return 0;
859 15196 : tm_utc = *tm;
860 15196 : tm = localtime(&t);
861 15196 : if (!tm)
862 0 : return 0;
863 15196 : return tm_diff(&tm_utc,tm);
864 : }
865 :
866 : /*
867 : * Raw convert an NTTIME to a unix timespec.
868 : */
869 :
870 5160990 : struct timespec nt_time_to_unix_timespec_raw(
871 : NTTIME nt)
872 : {
873 156266 : int64_t d;
874 156266 : struct timespec ret;
875 :
876 5160990 : d = (int64_t)nt;
877 : /* d is now in 100ns units, since jan 1st 1601".
878 : Save off the ns fraction. */
879 :
880 : /*
881 : * Take the last seven decimal digits and multiply by 100.
882 : * to convert from 100ns units to 1ns units.
883 : */
884 5160990 : ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
885 :
886 : /* Convert to seconds */
887 5160990 : d /= 1000*1000*10;
888 :
889 : /* Now adjust by 369 years to make the secs since 1970 */
890 5160990 : d -= TIME_FIXUP_CONSTANT_INT;
891 :
892 5160990 : ret.tv_sec = (time_t)d;
893 5160990 : return ret;
894 : }
895 :
896 2744859 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
897 : {
898 148754 : struct timespec ret;
899 :
900 2744859 : if (nt == 0 || nt == UINT64_MAX) {
901 7921 : ret.tv_sec = 0;
902 7921 : ret.tv_nsec = 0;
903 7921 : return ret;
904 : }
905 :
906 2736938 : ret = nt_time_to_unix_timespec_raw(nt);
907 :
908 2736938 : if (ret.tv_sec <= TIME_T_MIN) {
909 383 : ret.tv_sec = TIME_T_MIN;
910 383 : ret.tv_nsec = 0;
911 383 : return ret;
912 : }
913 :
914 2736555 : if (ret.tv_sec >= TIME_T_MAX) {
915 0 : ret.tv_sec = TIME_T_MAX;
916 0 : ret.tv_nsec = 0;
917 0 : return ret;
918 : }
919 2736555 : return ret;
920 : }
921 :
922 :
923 : /**
924 : check if 2 NTTIMEs are equal.
925 : */
926 72 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
927 : {
928 72 : return *t1 == *t2;
929 : }
930 :
931 : /**
932 : Check if it's a null timespec.
933 : **/
934 :
935 78870718 : bool null_timespec(struct timespec ts)
936 : {
937 157468925 : return ts.tv_sec == 0 ||
938 157468925 : ts.tv_sec == (time_t)0xFFFFFFFF ||
939 78598207 : ts.tv_sec == (time_t)-1;
940 : }
941 :
942 : /****************************************************************************
943 : Convert a normalized timeval to a timespec.
944 : ****************************************************************************/
945 :
946 8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
947 : {
948 0 : struct timespec ts;
949 8 : ts.tv_sec = tv.tv_sec;
950 8 : ts.tv_nsec = tv.tv_usec * 1000;
951 8 : return ts;
952 : }
953 :
954 : /****************************************************************************
955 : Convert a normalized timespec to a timeval.
956 : ****************************************************************************/
957 :
958 8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
959 : {
960 0 : struct timeval tv;
961 8 : tv.tv_sec = ts.tv_sec;
962 8 : tv.tv_usec = ts.tv_nsec / 1000;
963 8 : return tv;
964 : }
965 :
966 : /****************************************************************************
967 : Return a timespec for the current time
968 : ****************************************************************************/
969 :
970 325137 : _PUBLIC_ struct timespec timespec_current(void)
971 : {
972 983 : struct timespec ts;
973 325137 : clock_gettime(CLOCK_REALTIME, &ts);
974 325137 : return ts;
975 : }
976 :
977 : /****************************************************************************
978 : Return the lesser of two timespecs.
979 : ****************************************************************************/
980 :
981 0 : struct timespec timespec_min(const struct timespec *ts1,
982 : const struct timespec *ts2)
983 : {
984 0 : if (ts1->tv_sec < ts2->tv_sec) return *ts1;
985 0 : if (ts1->tv_sec > ts2->tv_sec) return *ts2;
986 0 : if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
987 0 : return *ts2;
988 : }
989 :
990 : /****************************************************************************
991 : compare two timespec structures.
992 : Return -1 if ts1 < ts2
993 : Return 0 if ts1 == ts2
994 : Return 1 if ts1 > ts2
995 : ****************************************************************************/
996 :
997 81165532 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
998 : {
999 81165532 : if (ts1->tv_sec > ts2->tv_sec) return 1;
1000 78764959 : if (ts1->tv_sec < ts2->tv_sec) return -1;
1001 77665047 : if (ts1->tv_nsec > ts2->tv_nsec) return 1;
1002 69135052 : if (ts1->tv_nsec < ts2->tv_nsec) return -1;
1003 57817178 : return 0;
1004 : }
1005 :
1006 : /****************************************************************************
1007 : Round up a timespec if nsec > 500000000, round down if lower,
1008 : then zero nsec.
1009 : ****************************************************************************/
1010 :
1011 65876 : void round_timespec_to_sec(struct timespec *ts)
1012 : {
1013 65876 : ts->tv_sec = convert_timespec_to_time_t(*ts);
1014 65876 : ts->tv_nsec = 0;
1015 65876 : }
1016 :
1017 : /****************************************************************************
1018 : Round a timespec to usec value.
1019 : ****************************************************************************/
1020 :
1021 0 : void round_timespec_to_usec(struct timespec *ts)
1022 : {
1023 0 : struct timeval tv = convert_timespec_to_timeval(*ts);
1024 0 : *ts = convert_timeval_to_timespec(tv);
1025 0 : normalize_timespec(ts);
1026 0 : }
1027 :
1028 : /****************************************************************************
1029 : Round a timespec to NTTIME resolution.
1030 : ****************************************************************************/
1031 :
1032 0 : void round_timespec_to_nttime(struct timespec *ts)
1033 : {
1034 0 : ts->tv_nsec = (ts->tv_nsec / 100) * 100;
1035 0 : }
1036 :
1037 : /****************************************************************************
1038 : Put a 8 byte filetime from a struct timespec. Uses GMT.
1039 : ****************************************************************************/
1040 :
1041 15946 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
1042 : {
1043 0 : uint64_t d;
1044 :
1045 15946 : if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
1046 0 : return 0;
1047 : }
1048 15946 : if (ts.tv_sec == TIME_T_MAX) {
1049 0 : return 0x7fffffffffffffffLL;
1050 : }
1051 15946 : if (ts.tv_sec == (time_t)-1) {
1052 0 : return UINT64_MAX;
1053 : }
1054 :
1055 15946 : d = ts.tv_sec;
1056 15946 : d += TIME_FIXUP_CONSTANT_INT;
1057 15946 : d *= 1000*1000*10;
1058 : /* d is now in 100ns units. */
1059 15946 : d += (ts.tv_nsec / 100);
1060 :
1061 15946 : return d;
1062 : }
1063 :
1064 : /*
1065 : * Functions supporting the full range of time_t and struct timespec values,
1066 : * including 0, -1 and all other negative values. These functions don't use 0 or
1067 : * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
1068 : * define UTIME_OMIT from utimensat(2).
1069 : */
1070 :
1071 : /**
1072 : * Check if it's a to be omitted timespec.
1073 : **/
1074 13528208 : bool is_omit_timespec(const struct timespec *ts)
1075 : {
1076 13528208 : return ts->tv_nsec == SAMBA_UTIME_OMIT;
1077 : }
1078 :
1079 : /**
1080 : * Return a to be omitted timespec.
1081 : **/
1082 8668287 : struct timespec make_omit_timespec(void)
1083 : {
1084 8668287 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1085 : }
1086 :
1087 : /**
1088 : * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
1089 : * and -1. Also dealing with SAMBA_UTIME_OMIT.
1090 : **/
1091 6270945 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
1092 : {
1093 6270945 : struct timespec ts = *_ts;
1094 9645 : uint64_t d;
1095 :
1096 6270945 : if (is_omit_timespec(_ts)) {
1097 1531232 : return NTTIME_OMIT;
1098 : }
1099 :
1100 : /* Ensure tv_nsec is less than 1 sec. */
1101 4737357 : while (ts.tv_nsec > 1000000000) {
1102 0 : if (ts.tv_sec > TIME_T_MAX) {
1103 0 : return NTTIME_MAX;
1104 : }
1105 0 : ts.tv_sec += 1;
1106 0 : ts.tv_nsec -= 1000000000;
1107 : }
1108 :
1109 4737357 : if (ts.tv_sec >= TIME_T_MAX) {
1110 0 : return NTTIME_MAX;
1111 : }
1112 4737357 : if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
1113 0 : return NTTIME_MIN;
1114 : }
1115 :
1116 4737357 : d = TIME_FIXUP_CONSTANT_INT;
1117 4737357 : d += ts.tv_sec;
1118 :
1119 4737357 : d *= 1000*1000*10;
1120 : /* d is now in 100ns units. */
1121 4737357 : d += (ts.tv_nsec / 100);
1122 :
1123 4737357 : return d;
1124 : }
1125 :
1126 : /**
1127 : * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
1128 : * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
1129 : *
1130 : * See also: is_omit_timespec().
1131 : **/
1132 2517706 : struct timespec nt_time_to_full_timespec(NTTIME nt)
1133 : {
1134 8507 : struct timespec ret;
1135 :
1136 2517706 : if (nt == NTTIME_OMIT) {
1137 89493 : return make_omit_timespec();
1138 : }
1139 2428213 : if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) {
1140 : /*
1141 : * This should be returned as SAMBA_UTIME_FREEZE or
1142 : * SAMBA_UTIME_THAW in the future.
1143 : */
1144 4161 : return make_omit_timespec();
1145 : }
1146 2424052 : if (nt > NTTIME_MAX) {
1147 2 : nt = NTTIME_MAX;
1148 : }
1149 :
1150 2424052 : ret = nt_time_to_unix_timespec_raw(nt);
1151 :
1152 2424052 : if (ret.tv_sec >= TIME_T_MAX) {
1153 0 : ret.tv_sec = TIME_T_MAX;
1154 0 : ret.tv_nsec = 0;
1155 0 : return ret;
1156 : }
1157 :
1158 2424052 : return ret;
1159 : }
1160 :
1161 : /**
1162 : * Note: this function uses the full time_t range as valid date values including
1163 : * (time_t)0 and -1. That means that struct timespec sentinel values (cf
1164 : * is_omit_timespec()) can't be converted to sentinel values in a time_t
1165 : * representation. Callers should therefore check the NTTIME value with
1166 : * null_nttime() before calling this function.
1167 : **/
1168 256403 : time_t full_timespec_to_time_t(const struct timespec *_ts)
1169 : {
1170 256403 : struct timespec ts = *_ts;
1171 :
1172 256403 : if (is_omit_timespec(_ts)) {
1173 : /*
1174 : * Unfortunately there's no sensible sentinel value in the
1175 : * time_t range that is not conflicting with a valid time value
1176 : * ((time_t)0 and -1 are valid time values). Bite the bullit and
1177 : * return 0.
1178 : */
1179 0 : return 0;
1180 : }
1181 :
1182 : /* Ensure tv_nsec is less than 1sec. */
1183 256403 : while (ts.tv_nsec > 1000000000) {
1184 0 : ts.tv_sec += 1;
1185 0 : ts.tv_nsec -= 1000000000;
1186 : }
1187 :
1188 : /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
1189 : increment if it's greater than 500 millionth of a second. */
1190 :
1191 256403 : if (ts.tv_nsec > 500000000) {
1192 16898 : return ts.tv_sec + 1;
1193 : }
1194 235593 : return ts.tv_sec;
1195 : }
1196 :
1197 : /**
1198 : * Like nt_time_to_unix() but supports negative time_t values.
1199 : *
1200 : * Note: this function uses the full time_t range as valid date values including
1201 : * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
1202 : * represent a "not-set" value, can't be converted to sentinel values in a
1203 : * time_t representation. Callers should therefore check the NTTIME value with
1204 : * null_nttime() before calling this function.
1205 : **/
1206 256403 : time_t nt_time_to_full_time_t(NTTIME nt)
1207 : {
1208 3982 : struct timespec ts;
1209 :
1210 256403 : ts = nt_time_to_full_timespec(nt);
1211 256403 : return full_timespec_to_time_t(&ts);
1212 : }
1213 :
1214 : /**
1215 : * Like time_t_to_unix_timespec() but supports negative time_t values.
1216 : *
1217 : * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
1218 : * can't be used as valid date values. The function supports values < -1 though.
1219 : **/
1220 32452 : struct timespec time_t_to_full_timespec(time_t t)
1221 : {
1222 32452 : if (null_time(t)) {
1223 32262 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1224 : }
1225 190 : return (struct timespec){.tv_sec = t};
1226 : }
1227 :
1228 : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1229 :
1230 : /* Old system - no ns timestamp. */
1231 : time_t get_atimensec(const struct stat *st)
1232 : {
1233 : return 0;
1234 : }
1235 :
1236 : time_t get_mtimensec(const struct stat *st)
1237 : {
1238 : return 0;
1239 : }
1240 :
1241 : time_t get_ctimensec(const struct stat *st)
1242 : {
1243 : return 0;
1244 : }
1245 :
1246 : /* Set does nothing with no ns timestamp. */
1247 : void set_atimensec(struct stat *st, time_t ns)
1248 : {
1249 : return;
1250 : }
1251 :
1252 : void set_mtimensec(struct stat *st, time_t ns)
1253 : {
1254 : return;
1255 : }
1256 :
1257 : void set_ctimensec(struct stat *st, time_t ns)
1258 : {
1259 : return;
1260 : }
1261 :
1262 : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1263 :
1264 : time_t get_atimensec(const struct stat *st)
1265 : {
1266 : return st->st_atimespec.tv_nsec;
1267 : }
1268 :
1269 : time_t get_mtimensec(const struct stat *st)
1270 : {
1271 : return st->st_mtimespec.tv_nsec;
1272 : }
1273 :
1274 : time_t get_ctimensec(const struct stat *st)
1275 : {
1276 : return st->st_ctimespec.tv_nsec;
1277 : }
1278 :
1279 : void set_atimensec(struct stat *st, time_t ns)
1280 : {
1281 : st->st_atimespec.tv_nsec = ns;
1282 : }
1283 :
1284 : void set_mtimensec(struct stat *st, time_t ns)
1285 : {
1286 : st->st_mtimespec.tv_nsec = ns;
1287 : }
1288 :
1289 : void set_ctimensec(struct stat *st, time_t ns)
1290 : {
1291 : st->st_ctimespec.tv_nsec = ns;
1292 : }
1293 :
1294 : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1295 :
1296 79659850 : time_t get_atimensec(const struct stat *st)
1297 : {
1298 79659850 : return st->st_atim.tv_nsec;
1299 : }
1300 :
1301 80454460 : time_t get_mtimensec(const struct stat *st)
1302 : {
1303 80454460 : return st->st_mtim.tv_nsec;
1304 : }
1305 :
1306 80465776 : time_t get_ctimensec(const struct stat *st)
1307 : {
1308 80465776 : return st->st_ctim.tv_nsec;
1309 : }
1310 :
1311 205 : void set_atimensec(struct stat *st, time_t ns)
1312 : {
1313 205 : st->st_atim.tv_nsec = ns;
1314 205 : }
1315 :
1316 205 : void set_mtimensec(struct stat *st, time_t ns)
1317 : {
1318 205 : st->st_mtim.tv_nsec = ns;
1319 205 : }
1320 205 : void set_ctimensec(struct stat *st, time_t ns)
1321 : {
1322 205 : st->st_ctim.tv_nsec = ns;
1323 205 : }
1324 :
1325 : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
1326 :
1327 : time_t get_atimensec(const struct stat *st)
1328 : {
1329 : return st->st_atimensec;
1330 : }
1331 :
1332 : time_t get_mtimensec(const struct stat *st)
1333 : {
1334 : return st->st_mtimensec;
1335 : }
1336 :
1337 : time_t get_ctimensec(const struct stat *st)
1338 : {
1339 : return st->st_ctimensec;
1340 : }
1341 :
1342 : void set_atimensec(struct stat *st, time_t ns)
1343 : {
1344 : st->st_atimensec = ns;
1345 : }
1346 :
1347 : void set_mtimensec(struct stat *st, time_t ns)
1348 : {
1349 : st->st_mtimensec = ns;
1350 : }
1351 :
1352 : void set_ctimensec(struct stat *st, time_t ns)
1353 : {
1354 : st->st_ctimensec = ns;
1355 : }
1356 :
1357 : #elif HAVE_STRUCT_STAT_ST_MTIME_N
1358 :
1359 : time_t get_atimensec(const struct stat *st)
1360 : {
1361 : return st->st_atime_n;
1362 : }
1363 :
1364 : time_t get_mtimensec(const struct stat *st)
1365 : {
1366 : return st->st_mtime_n;
1367 : }
1368 :
1369 : time_t get_ctimensec(const struct stat *st)
1370 : {
1371 : return st->st_ctime_n;
1372 : }
1373 :
1374 : void set_atimensec(struct stat *st, time_t ns)
1375 : {
1376 : st->st_atime_n = ns;
1377 : }
1378 :
1379 : void set_mtimensec(struct stat *st, time_t ns)
1380 : {
1381 : st->st_mtime_n = ns;
1382 : }
1383 :
1384 : void set_ctimensec(struct stat *st, time_t ns)
1385 : {
1386 : st->st_ctime_n = ns;
1387 : }
1388 :
1389 : #elif HAVE_STRUCT_STAT_ST_UMTIME
1390 :
1391 : /* Only usec timestamps available. Convert to/from nsec. */
1392 :
1393 : time_t get_atimensec(const struct stat *st)
1394 : {
1395 : return st->st_uatime * 1000;
1396 : }
1397 :
1398 : time_t get_mtimensec(const struct stat *st)
1399 : {
1400 : return st->st_umtime * 1000;
1401 : }
1402 :
1403 : time_t get_ctimensec(const struct stat *st)
1404 : {
1405 : return st->st_uctime * 1000;
1406 : }
1407 :
1408 : void set_atimensec(struct stat *st, time_t ns)
1409 : {
1410 : st->st_uatime = ns / 1000;
1411 : }
1412 :
1413 : void set_mtimensec(struct stat *st, time_t ns)
1414 : {
1415 : st->st_umtime = ns / 1000;
1416 : }
1417 :
1418 : void set_ctimensec(struct stat *st, time_t ns)
1419 : {
1420 : st->st_uctime = ns / 1000;
1421 : }
1422 :
1423 : #else
1424 : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1425 : #endif
1426 :
1427 78853920 : struct timespec get_atimespec(const struct stat *pst)
1428 : {
1429 271098 : struct timespec ret;
1430 :
1431 78853920 : ret.tv_sec = pst->st_atime;
1432 78853920 : ret.tv_nsec = get_atimensec(pst);
1433 78853920 : return ret;
1434 : }
1435 :
1436 79648526 : struct timespec get_mtimespec(const struct stat *pst)
1437 : {
1438 275747 : struct timespec ret;
1439 :
1440 79648526 : ret.tv_sec = pst->st_mtime;
1441 79648526 : ret.tv_nsec = get_mtimensec(pst);
1442 79648526 : return ret;
1443 : }
1444 :
1445 78853916 : struct timespec get_ctimespec(const struct stat *pst)
1446 : {
1447 271098 : struct timespec ret;
1448 :
1449 78853916 : ret.tv_sec = pst->st_mtime;
1450 78853916 : ret.tv_nsec = get_ctimensec(pst);
1451 78853916 : return ret;
1452 : }
1453 :
1454 : /****************************************************************************
1455 : Deal with nanoseconds overflow.
1456 : ****************************************************************************/
1457 :
1458 3223048 : void normalize_timespec(struct timespec *ts)
1459 : {
1460 151576 : lldiv_t dres;
1461 :
1462 : /* most likely case: nsec is valid */
1463 3223048 : if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
1464 3223048 : return;
1465 : }
1466 :
1467 21582 : dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
1468 :
1469 : /* if the operation would result in overflow, max out values and bail */
1470 21582 : if (dres.quot > 0) {
1471 21570 : if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
1472 1 : ts->tv_sec = LONG_MAX;
1473 1 : ts->tv_nsec = NSEC_PER_SEC - 1;
1474 1 : return;
1475 : }
1476 : } else {
1477 12 : if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
1478 1 : ts->tv_sec = LONG_MIN;
1479 1 : ts->tv_nsec = 0;
1480 1 : return;
1481 : }
1482 : }
1483 :
1484 21580 : ts->tv_nsec = dres.rem;
1485 21580 : ts->tv_sec += dres.quot;
1486 :
1487 : /* if the ns part was positive or a multiple of -1000000000, we're done */
1488 21580 : if (ts->tv_nsec > 0 || dres.rem == 0) {
1489 21562 : return;
1490 : }
1491 :
1492 9 : ts->tv_nsec += NSEC_PER_SEC;
1493 9 : --ts->tv_sec;
1494 : }
|