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