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