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