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 394008 : _PUBLIC_ time_t get_time_t_max(void)
52 : {
53 394008 : return TIME_T_MAX;
54 : }
55 :
56 : /**
57 : a wrapper to preferably get the monotonic time
58 : **/
59 428135929 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
60 : {
61 : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
62 : #ifdef CLOCK_BOOTTIME
63 428135929 : if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
64 427737820 : return;
65 : }
66 : #endif
67 : /* then try the monotonic clock: */
68 : #ifndef CUSTOM_CLOCK_MONOTONIC_IS_REALTIME
69 2 : 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 6941 : _PUBLIC_ time_t time_mono(time_t *t)
80 : {
81 0 : struct timespec tp;
82 :
83 6941 : clock_gettime_mono(&tp);
84 6941 : if (t != NULL) {
85 0 : *t = tp.tv_sec;
86 : }
87 6941 : return tp.tv_sec;
88 : }
89 :
90 :
91 : #define TIME_FIXUP_CONSTANT 11644473600LL
92 :
93 5651202 : time_t convert_timespec_to_time_t(struct timespec ts)
94 : {
95 : /* Ensure tv_nsec is less than 1sec. */
96 5651202 : 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 5651202 : if (ts.tv_nsec > 500000000) {
102 1472979 : return ts.tv_sec + 1;
103 : }
104 4178223 : return ts.tv_sec;
105 : }
106 :
107 0 : struct timespec convert_time_t_to_timespec(time_t t)
108 : {
109 0 : 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 2725819 : time_t nt_time_to_unix(NTTIME nt)
129 : {
130 2725819 : 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 7006011 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
139 : {
140 265057 : uint64_t t2;
141 :
142 7006011 : if (t == (time_t)-1) {
143 1 : *nt = (NTTIME)-1LL;
144 1 : return;
145 : }
146 :
147 7006010 : if (t == TIME_T_MAX || t == INT64_MAX) {
148 60652 : *nt = 0x7fffffffffffffffLL;
149 60652 : return;
150 : }
151 :
152 6945358 : if (t == 0) {
153 21748 : *nt = 0;
154 21748 : return;
155 : }
156 :
157 6923610 : t2 = t;
158 6923610 : t2 += TIME_FIXUP_CONSTANT_INT;
159 6923610 : t2 *= 1000*1000*10;
160 :
161 6923610 : *nt = t2;
162 : }
163 :
164 :
165 : /**
166 : check if it's a null unix time
167 : **/
168 913165 : _PUBLIC_ bool null_time(time_t t)
169 : {
170 85031 : return t == 0 ||
171 996706 : t == (time_t)0xFFFFFFFF ||
172 : t == (time_t)-1;
173 : }
174 :
175 :
176 : /**
177 : check if it's a null NTTIME
178 : **/
179 2498458 : _PUBLIC_ bool null_nttime(NTTIME t)
180 : {
181 2498458 : return t == 0;
182 : }
183 :
184 : /*******************************************************************
185 : create a 16 bit dos packed date
186 : ********************************************************************/
187 440962 : static uint16_t make_dos_date1(struct tm *t)
188 : {
189 440962 : uint16_t ret=0;
190 440962 : ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
191 440962 : ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
192 440962 : return ret;
193 : }
194 :
195 : /*******************************************************************
196 : create a 16 bit dos packed time
197 : ********************************************************************/
198 440962 : static uint16_t make_dos_time1(struct tm *t)
199 : {
200 440962 : uint16_t ret=0;
201 440962 : ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
202 440962 : ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
203 440962 : 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 441090 : static uint32_t make_dos_date(time_t unixdate, int zone_offset)
211 : {
212 223 : struct tm *t;
213 441090 : uint32_t ret=0;
214 :
215 441090 : if (unixdate == 0) {
216 111 : return 0;
217 : }
218 :
219 440962 : unixdate -= zone_offset;
220 :
221 440962 : t = gmtime(&unixdate);
222 440962 : if (!t) {
223 0 : return 0xFFFFFFFF;
224 : }
225 :
226 440962 : ret = make_dos_date1(t);
227 440962 : ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
228 :
229 440962 : 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 33632 : _PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
237 : {
238 33632 : uint32_t x = make_dos_date(unixdate, zone_offset);
239 33632 : SIVAL(buf,offset,x);
240 33632 : }
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 407458 : _PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
247 : {
248 206 : uint32_t x;
249 407458 : x = make_dos_date(unixdate, zone_offset);
250 407458 : x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
251 407458 : SIVAL(buf,offset,x);
252 407458 : }
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 169266 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
260 : {
261 169266 : if (!null_time(unixdate)) {
262 29180 : unixdate -= zone_offset;
263 : }
264 169266 : SIVAL(buf,offset,unixdate);
265 169266 : }
266 :
267 : /*******************************************************************
268 : interpret a 32 bit dos packed date/time to some parameters
269 : ********************************************************************/
270 440823 : void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
271 : {
272 195 : uint32_t p0,p1,p2,p3;
273 :
274 440823 : p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
275 440823 : p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
276 :
277 440823 : *second = 2*(p0 & 0x1F);
278 440823 : *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
279 440823 : *hour = (p1>>3)&0xFF;
280 440823 : *day = (p2&0x1F);
281 440823 : *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
282 440823 : *year = ((p3>>1)&0xFF) + 80;
283 440823 : }
284 :
285 : /**
286 : create a unix date (int GMT) from a dos date (which is actually in
287 : localtime)
288 : **/
289 440894 : _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
290 : {
291 440894 : uint32_t dos_date=0;
292 195 : struct tm t;
293 195 : time_t ret;
294 :
295 440894 : dos_date = IVAL(date_ptr,0);
296 :
297 440894 : if (dos_date == 0) return (time_t)0;
298 :
299 440823 : 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 440823 : t.tm_isdst = -1;
302 :
303 440823 : ret = timegm(&t);
304 :
305 440823 : ret += zone_offset;
306 :
307 440823 : return ret;
308 : }
309 :
310 : /**
311 : like make_unix_date() but the words are reversed
312 : **/
313 407355 : _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
314 : {
315 195 : uint32_t x,x2;
316 :
317 407355 : x = IVAL(date_ptr,0);
318 407355 : x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
319 407355 : SIVAL(&x,0,x2);
320 :
321 407355 : 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 147605 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
329 : {
330 147605 : time_t t = (time_t)IVAL(date_ptr,0);
331 :
332 147605 : if (t == (time_t)0xFFFFFFFF) {
333 4092 : t = (time_t)-1;
334 : }
335 :
336 147605 : if (!null_time(t)) {
337 27796 : t += zone_offset;
338 : }
339 147605 : return t;
340 : }
341 :
342 : /****************************************************************************
343 : Return the date and time as a string
344 : ****************************************************************************/
345 :
346 218 : char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
347 : {
348 36 : struct timeval_buf tmp;
349 36 : char *result;
350 :
351 218 : result = talloc_strdup(ctx, timeval_str_buf(tp, false, hires, &tmp));
352 218 : 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 218 : talloc_set_name_const(result, result);
366 218 : return result;
367 : }
368 :
369 : /****************************************************************************
370 : Return the date and time as a string
371 : ****************************************************************************/
372 :
373 173 : const char *timespec_string_buf(const struct timespec *tp,
374 : bool hires,
375 : struct timeval_buf *buf)
376 : {
377 1 : time_t t;
378 173 : struct tm *tm = NULL;
379 1 : int len;
380 :
381 173 : if (is_omit_timespec(tp)) {
382 0 : strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf));
383 0 : return buf->buf;
384 : }
385 :
386 173 : t = (time_t)tp->tv_sec;
387 173 : tm = localtime(&t);
388 :
389 173 : 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 173 : } 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 173 : len = snprintf(buf->buf, sizeof(buf->buf),
409 : "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
410 173 : 1900 + tm->tm_year,
411 173 : tm->tm_mon + 1,
412 : tm->tm_mday,
413 : tm->tm_hour,
414 : tm->tm_min,
415 : tm->tm_sec,
416 173 : (long)tp->tv_nsec);
417 : }
418 173 : if (len == -1) {
419 0 : return "";
420 : }
421 :
422 173 : return buf->buf;
423 : }
424 :
425 218 : char *current_timestring(TALLOC_CTX *ctx, bool hires)
426 : {
427 36 : struct timeval tv;
428 :
429 218 : GetTimeOfDay(&tv);
430 218 : 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 166 : char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
439 : {
440 2 : time_t t;
441 2 : struct tm *tm;
442 :
443 166 : t = (time_t)tp->tv_sec;
444 166 : tm = localtime(&t);
445 166 : 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 166 : if (hires) {
455 1 : 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 165 : return talloc_asprintf(ctx,
466 : "%04d%02d%02d_%02d%02d%02d",
467 165 : tm->tm_year+1900,
468 165 : 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 164 : char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
478 : {
479 0 : struct timeval tv;
480 :
481 164 : GetTimeOfDay(&tv);
482 164 : return minimal_timeval_string(ctx, &tv, hires);
483 : }
484 :
485 : /**
486 : return a HTTP/1.0 time string
487 : **/
488 549 : _PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t)
489 : {
490 2 : char *buf;
491 2 : char tempTime[60];
492 549 : struct tm *tm = localtime(&t);
493 :
494 549 : if (t == TIME_T_MAX) {
495 7 : return talloc_strdup(mem_ctx, "never");
496 : }
497 :
498 542 : 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 542 : strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
509 542 : buf = talloc_strdup(mem_ctx, tempTime);
510 : #endif /* !HAVE_STRFTIME */
511 :
512 542 : return buf;
513 : }
514 :
515 : /**
516 : Return the date and time as a string
517 : **/
518 285653 : _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t)
519 : {
520 4224 : char *TimeBuf;
521 4224 : char tempTime[80];
522 4224 : struct tm *tm;
523 :
524 285653 : tm = localtime(&t);
525 285653 : 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 285653 : strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
536 285653 : 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 285653 : return TimeBuf;
551 : }
552 :
553 : /**
554 : return a talloced string representing a NTTIME for human consumption
555 : */
556 264753 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
557 : {
558 5318 : time_t t;
559 264753 : if (nt == 0) {
560 7016 : return "NTTIME(0)";
561 : }
562 256401 : t = nt_time_to_full_time_t(nt);
563 256401 : return timestring(mem_ctx, t);
564 : }
565 :
566 :
567 : /**
568 : put a NTTIME into a packet
569 : */
570 425428 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
571 : {
572 425428 : SBVAL(base, offset, t);
573 425428 : }
574 :
575 : /**
576 : pull a NTTIME from a packet
577 : */
578 2204 : _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
579 : {
580 2204 : NTTIME ret = BVAL(base, offset);
581 2204 : return ret;
582 : }
583 :
584 : /**
585 : return (tv1 - tv2) in microseconds
586 : */
587 394305 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
588 : {
589 394305 : int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
590 394305 : return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
591 : }
592 :
593 : /**
594 : return (tp1 - tp2) in nanoseconds
595 : */
596 213738538 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
597 : {
598 213738538 : int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
599 213738538 : return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
600 : }
601 :
602 :
603 : /**
604 : return a zero timeval
605 : */
606 139009 : _PUBLIC_ struct timeval timeval_zero(void)
607 : {
608 2476 : struct timeval tv;
609 139009 : tv.tv_sec = 0;
610 139009 : tv.tv_usec = 0;
611 139009 : return tv;
612 : }
613 :
614 : /**
615 : return true if a timeval is zero
616 : */
617 1299145 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
618 : {
619 1299145 : return tv->tv_sec == 0 && tv->tv_usec == 0;
620 : }
621 :
622 : /**
623 : return a timeval for the current time
624 : */
625 15457454 : _PUBLIC_ struct timeval timeval_current(void)
626 : {
627 703861 : struct timeval tv;
628 15457454 : GetTimeOfDay(&tv);
629 15457454 : return tv;
630 : }
631 :
632 : /**
633 : return a timeval struct with the given elements
634 : */
635 93707 : _PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs)
636 : {
637 2526 : struct timeval tv;
638 93707 : tv.tv_sec = secs;
639 93707 : tv.tv_usec = usecs;
640 93707 : return tv;
641 : }
642 :
643 :
644 : /**
645 : return a timeval ofs microseconds after tv
646 : */
647 8059550 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
648 : uint32_t secs, uint32_t usecs)
649 : {
650 8059550 : struct timeval tv2 = *tv;
651 8059550 : const unsigned int million = 1000000;
652 8059550 : tv2.tv_sec += secs;
653 8059550 : tv2.tv_usec += usecs;
654 8059550 : tv2.tv_sec += tv2.tv_usec / million;
655 8059550 : tv2.tv_usec = tv2.tv_usec % million;
656 8059550 : return tv2;
657 : }
658 :
659 : /**
660 : return the sum of two timeval structures
661 : */
662 111790 : struct timeval timeval_sum(const struct timeval *tv1,
663 : const struct timeval *tv2)
664 : {
665 111790 : return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
666 : }
667 :
668 : /**
669 : return a timeval secs/usecs into the future
670 : */
671 2601044 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
672 : {
673 2601044 : struct timeval tv = timeval_current();
674 2601044 : return timeval_add(&tv, secs, usecs);
675 : }
676 :
677 : /**
678 : return a timeval milliseconds into the future
679 : */
680 4490506 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
681 : {
682 4490506 : struct timeval tv = timeval_current();
683 4490506 : return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
684 : }
685 :
686 : /**
687 : return a timeval microseconds into the future
688 : */
689 461635 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
690 : {
691 461635 : struct timeval tv = timeval_current();
692 461635 : 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 8704 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
702 : {
703 8704 : if (tv1->tv_sec > tv2->tv_sec) return 1;
704 7727 : if (tv1->tv_sec < tv2->tv_sec) return -1;
705 7580 : if (tv1->tv_usec > tv2->tv_usec) return 1;
706 3926 : if (tv1->tv_usec < tv2->tv_usec) return -1;
707 10 : return 0;
708 : }
709 :
710 : /**
711 : return true if a timer is in the past
712 : */
713 1010951 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
714 : {
715 1010951 : struct timeval tv2 = timeval_current();
716 1010951 : if (tv2.tv_sec > tv->tv_sec) return true;
717 1010882 : if (tv2.tv_sec < tv->tv_sec) return false;
718 2989 : return (tv2.tv_usec >= tv->tv_usec);
719 : }
720 :
721 : /**
722 : return the number of seconds elapsed between two times
723 : */
724 772653 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
725 : {
726 969478 : return (tv2->tv_sec - tv1->tv_sec) +
727 772653 : (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 772206 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
734 : {
735 772206 : struct timeval tv2 = timeval_current();
736 772206 : return timeval_elapsed2(tv, &tv2);
737 : }
738 : /**
739 : * return the number of seconds elapsed between two times
740 : **/
741 535 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
742 : const struct timespec *ts2)
743 : {
744 1063 : return (ts2->tv_sec - ts1->tv_sec) +
745 535 : (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 12 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
752 : {
753 12 : struct timespec ts2 = timespec_current();
754 12 : return timespec_elapsed2(ts, &ts2);
755 : }
756 :
757 : /**
758 : return the lesser of two timevals
759 : */
760 4152 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
761 : const struct timeval *tv2)
762 : {
763 4152 : if (tv1->tv_sec < tv2->tv_sec) return *tv1;
764 3739 : if (tv1->tv_sec > tv2->tv_sec) return *tv2;
765 3649 : 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 0 : 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 7818769 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
808 : {
809 15560733 : return 10*(tv->tv_usec +
810 7818769 : ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
811 : }
812 :
813 : /**
814 : convert a NTTIME to a timeval
815 : */
816 74749 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
817 : {
818 74749 : if (tv == NULL) return;
819 :
820 74749 : t += 10/2;
821 74749 : t /= 10;
822 74749 : t -= TIME_FIXUP_CONSTANT*1000*1000;
823 :
824 74749 : tv->tv_sec = t / 1000000;
825 :
826 74749 : 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 74749 : 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 15186 : static int tm_diff(struct tm *a, struct tm *b)
839 : {
840 15186 : int ay = a->tm_year + (1900 - 1);
841 15186 : int by = b->tm_year + (1900 - 1);
842 15186 : int intervening_leap_days =
843 15186 : (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
844 15186 : int years = ay - by;
845 15186 : int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
846 15186 : int hours = 24*days + (a->tm_hour - b->tm_hour);
847 15186 : int minutes = 60*hours + (a->tm_min - b->tm_min);
848 15186 : int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
849 :
850 15186 : 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 15186 : _PUBLIC_ int get_time_zone(time_t t)
858 : {
859 15186 : struct tm *tm = gmtime(&t);
860 268 : struct tm tm_utc;
861 15186 : if (!tm)
862 0 : return 0;
863 15186 : tm_utc = *tm;
864 15186 : tm = localtime(&t);
865 15186 : if (!tm)
866 0 : return 0;
867 15186 : return tm_diff(&tm_utc,tm);
868 : }
869 :
870 : /*
871 : * Raw convert an NTTIME to a unix timespec.
872 : */
873 :
874 5152168 : struct timespec nt_time_to_unix_timespec_raw(
875 : NTTIME nt)
876 : {
877 156266 : int64_t d;
878 156266 : struct timespec ret;
879 :
880 5152168 : d = (int64_t)nt;
881 : /* d is now in 100ns units, since jan 1st 1601".
882 : Save off the ns fraction. */
883 :
884 : /*
885 : * Take the last seven decimal digits and multiply by 100.
886 : * to convert from 100ns units to 1ns units.
887 : */
888 5152168 : ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
889 :
890 : /* Convert to seconds */
891 5152168 : d /= 1000*1000*10;
892 :
893 : /* Now adjust by 369 years to make the secs since 1970 */
894 5152168 : d -= TIME_FIXUP_CONSTANT_INT;
895 :
896 5152168 : ret.tv_sec = (time_t)d;
897 5152168 : return ret;
898 : }
899 :
900 2737279 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
901 : {
902 148754 : struct timespec ret;
903 :
904 2737279 : if (nt == 0 || nt == (int64_t)-1) {
905 7921 : ret.tv_sec = 0;
906 7921 : ret.tv_nsec = 0;
907 7921 : return ret;
908 : }
909 :
910 2729358 : ret = nt_time_to_unix_timespec_raw(nt);
911 :
912 2729358 : if (ret.tv_sec <= TIME_T_MIN) {
913 383 : ret.tv_sec = TIME_T_MIN;
914 383 : ret.tv_nsec = 0;
915 383 : return ret;
916 : }
917 :
918 2728975 : if (ret.tv_sec >= TIME_T_MAX) {
919 0 : ret.tv_sec = TIME_T_MAX;
920 0 : ret.tv_nsec = 0;
921 0 : return ret;
922 : }
923 2728975 : return ret;
924 : }
925 :
926 :
927 : /**
928 : check if 2 NTTIMEs are equal.
929 : */
930 72 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
931 : {
932 72 : return *t1 == *t2;
933 : }
934 :
935 : /**
936 : Check if it's a null timespec.
937 : **/
938 :
939 77652638 : bool null_timespec(struct timespec ts)
940 : {
941 155033249 : return ts.tv_sec == 0 ||
942 155033249 : ts.tv_sec == (time_t)0xFFFFFFFF ||
943 77380611 : ts.tv_sec == (time_t)-1;
944 : }
945 :
946 : /****************************************************************************
947 : Convert a normalized timeval to a timespec.
948 : ****************************************************************************/
949 :
950 8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
951 : {
952 0 : struct timespec ts;
953 8 : ts.tv_sec = tv.tv_sec;
954 8 : ts.tv_nsec = tv.tv_usec * 1000;
955 8 : return ts;
956 : }
957 :
958 : /****************************************************************************
959 : Convert a normalized timespec to a timeval.
960 : ****************************************************************************/
961 :
962 8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
963 : {
964 0 : struct timeval tv;
965 8 : tv.tv_sec = ts.tv_sec;
966 8 : tv.tv_usec = ts.tv_nsec / 1000;
967 8 : return tv;
968 : }
969 :
970 : /****************************************************************************
971 : Return a timespec for the current time
972 : ****************************************************************************/
973 :
974 325114 : _PUBLIC_ struct timespec timespec_current(void)
975 : {
976 983 : struct timespec ts;
977 325114 : clock_gettime(CLOCK_REALTIME, &ts);
978 325114 : return ts;
979 : }
980 :
981 : /****************************************************************************
982 : Return the lesser of two timespecs.
983 : ****************************************************************************/
984 :
985 0 : struct timespec timespec_min(const struct timespec *ts1,
986 : const struct timespec *ts2)
987 : {
988 0 : if (ts1->tv_sec < ts2->tv_sec) return *ts1;
989 0 : if (ts1->tv_sec > ts2->tv_sec) return *ts2;
990 0 : if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
991 0 : return *ts2;
992 : }
993 :
994 : /****************************************************************************
995 : compare two timespec structures.
996 : Return -1 if ts1 < ts2
997 : Return 0 if ts1 == ts2
998 : Return 1 if ts1 > ts2
999 : ****************************************************************************/
1000 :
1001 79947033 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
1002 : {
1003 79947033 : if (ts1->tv_sec > ts2->tv_sec) return 1;
1004 77548090 : if (ts1->tv_sec < ts2->tv_sec) return -1;
1005 76448395 : if (ts1->tv_nsec > ts2->tv_nsec) return 1;
1006 67840617 : if (ts1->tv_nsec < ts2->tv_nsec) return -1;
1007 56521372 : return 0;
1008 : }
1009 :
1010 : /****************************************************************************
1011 : Round up a timespec if nsec > 500000000, round down if lower,
1012 : then zero nsec.
1013 : ****************************************************************************/
1014 :
1015 65868 : void round_timespec_to_sec(struct timespec *ts)
1016 : {
1017 65868 : ts->tv_sec = convert_timespec_to_time_t(*ts);
1018 65868 : ts->tv_nsec = 0;
1019 65868 : }
1020 :
1021 : /****************************************************************************
1022 : Round a timespec to usec value.
1023 : ****************************************************************************/
1024 :
1025 0 : void round_timespec_to_usec(struct timespec *ts)
1026 : {
1027 0 : struct timeval tv = convert_timespec_to_timeval(*ts);
1028 0 : *ts = convert_timeval_to_timespec(tv);
1029 0 : normalize_timespec(ts);
1030 0 : }
1031 :
1032 : /****************************************************************************
1033 : Round a timespec to NTTIME resolution.
1034 : ****************************************************************************/
1035 :
1036 0 : void round_timespec_to_nttime(struct timespec *ts)
1037 : {
1038 0 : ts->tv_nsec = (ts->tv_nsec / 100) * 100;
1039 0 : }
1040 :
1041 : /****************************************************************************
1042 : Put a 8 byte filetime from a struct timespec. Uses GMT.
1043 : ****************************************************************************/
1044 :
1045 15946 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
1046 : {
1047 0 : uint64_t d;
1048 :
1049 15946 : if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
1050 0 : return 0;
1051 : }
1052 15946 : if (ts.tv_sec == TIME_T_MAX) {
1053 0 : return 0x7fffffffffffffffLL;
1054 : }
1055 15946 : if (ts.tv_sec == (time_t)-1) {
1056 0 : return (uint64_t)-1;
1057 : }
1058 :
1059 15946 : d = ts.tv_sec;
1060 15946 : d += TIME_FIXUP_CONSTANT_INT;
1061 15946 : d *= 1000*1000*10;
1062 : /* d is now in 100ns units. */
1063 15946 : d += (ts.tv_nsec / 100);
1064 :
1065 15946 : return d;
1066 : }
1067 :
1068 : /*
1069 : * Functions supporting the full range of time_t and struct timespec values,
1070 : * including 0, -1 and all other negative values. These functions don't use 0 or
1071 : * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
1072 : * define UTIME_OMIT from utimensat(2).
1073 : */
1074 :
1075 : /**
1076 : * Check if it's a to be omitted timespec.
1077 : **/
1078 13513180 : bool is_omit_timespec(const struct timespec *ts)
1079 : {
1080 13513180 : return ts->tv_nsec == SAMBA_UTIME_OMIT;
1081 : }
1082 :
1083 : /**
1084 : * Return a to be omitted timespec.
1085 : **/
1086 8664190 : struct timespec make_omit_timespec(void)
1087 : {
1088 8664190 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1089 : }
1090 :
1091 : /**
1092 : * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
1093 : * and -1. Also dealing with SAMBA_UTIME_OMIT.
1094 : **/
1095 6263744 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
1096 : {
1097 6263744 : struct timespec ts = *_ts;
1098 9629 : uint64_t d;
1099 :
1100 6263744 : if (is_omit_timespec(_ts)) {
1101 1527472 : return NTTIME_OMIT;
1102 : }
1103 :
1104 : /* Ensure tv_nsec is less than 1 sec. */
1105 4733932 : while (ts.tv_nsec > 1000000000) {
1106 0 : if (ts.tv_sec > TIME_T_MAX) {
1107 0 : return NTTIME_MAX;
1108 : }
1109 0 : ts.tv_sec += 1;
1110 0 : ts.tv_nsec -= 1000000000;
1111 : }
1112 :
1113 4733932 : if (ts.tv_sec >= TIME_T_MAX) {
1114 0 : return NTTIME_MAX;
1115 : }
1116 4733932 : if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
1117 0 : return NTTIME_MIN;
1118 : }
1119 :
1120 4733932 : d = TIME_FIXUP_CONSTANT_INT;
1121 4733932 : d += ts.tv_sec;
1122 :
1123 4733932 : d *= 1000*1000*10;
1124 : /* d is now in 100ns units. */
1125 4733932 : d += (ts.tv_nsec / 100);
1126 :
1127 4733932 : return d;
1128 : }
1129 :
1130 : /**
1131 : * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
1132 : * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
1133 : *
1134 : * See also: is_omit_timespec().
1135 : **/
1136 2515634 : struct timespec nt_time_to_full_timespec(NTTIME nt)
1137 : {
1138 8507 : struct timespec ret;
1139 :
1140 2515634 : if (nt == NTTIME_OMIT) {
1141 88663 : return make_omit_timespec();
1142 : }
1143 2426971 : if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) {
1144 : /*
1145 : * This should be returned as SAMBA_UTIME_FREEZE or
1146 : * SAMBA_UTIME_THAW in the future.
1147 : */
1148 4161 : return make_omit_timespec();
1149 : }
1150 2422810 : if (nt > NTTIME_MAX) {
1151 2 : nt = NTTIME_MAX;
1152 : }
1153 :
1154 2422810 : ret = nt_time_to_unix_timespec_raw(nt);
1155 :
1156 2422810 : if (ret.tv_sec >= TIME_T_MAX) {
1157 0 : ret.tv_sec = TIME_T_MAX;
1158 0 : ret.tv_nsec = 0;
1159 0 : return ret;
1160 : }
1161 :
1162 2422810 : return ret;
1163 : }
1164 :
1165 : /**
1166 : * Note: this function uses the full time_t range as valid date values including
1167 : * (time_t)0 and -1. That means that struct timespec sentinel values (cf
1168 : * is_omit_timespec()) can't be converted to sentinel values in a time_t
1169 : * representation. Callers should therefore check the NTTIME value with
1170 : * null_nttime() before calling this function.
1171 : **/
1172 256401 : time_t full_timespec_to_time_t(const struct timespec *_ts)
1173 : {
1174 256401 : struct timespec ts = *_ts;
1175 :
1176 256401 : if (is_omit_timespec(_ts)) {
1177 : /*
1178 : * Unfortunately there's no sensible sentinel value in the
1179 : * time_t range that is not conflicting with a valid time value
1180 : * ((time_t)0 and -1 are valid time values). Bite the bullit and
1181 : * return 0.
1182 : */
1183 0 : return 0;
1184 : }
1185 :
1186 : /* Ensure tv_nsec is less than 1sec. */
1187 256401 : while (ts.tv_nsec > 1000000000) {
1188 0 : ts.tv_sec += 1;
1189 0 : ts.tv_nsec -= 1000000000;
1190 : }
1191 :
1192 : /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
1193 : increment if it's greater than 500 millionth of a second. */
1194 :
1195 256401 : if (ts.tv_nsec > 500000000) {
1196 7989 : return ts.tv_sec + 1;
1197 : }
1198 244484 : return ts.tv_sec;
1199 : }
1200 :
1201 : /**
1202 : * Like nt_time_to_unix() but supports negative time_t values.
1203 : *
1204 : * Note: this function uses the full time_t range as valid date values including
1205 : * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
1206 : * represent a "not-set" value, can't be converted to sentinel values in a
1207 : * time_t representation. Callers should therefore check the NTTIME value with
1208 : * null_nttime() before calling this function.
1209 : **/
1210 256401 : time_t nt_time_to_full_time_t(NTTIME nt)
1211 : {
1212 3982 : struct timespec ts;
1213 :
1214 256401 : ts = nt_time_to_full_timespec(nt);
1215 256401 : return full_timespec_to_time_t(&ts);
1216 : }
1217 :
1218 : /**
1219 : * Like time_t_to_unix_timespec() but supports negative time_t values.
1220 : *
1221 : * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
1222 : * can't be used as valid date values. The function supports values < -1 though.
1223 : **/
1224 32443 : struct timespec time_t_to_full_timespec(time_t t)
1225 : {
1226 32443 : if (null_time(t)) {
1227 32253 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1228 : }
1229 190 : return (struct timespec){.tv_sec = t};
1230 : }
1231 :
1232 : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1233 :
1234 : /* Old system - no ns timestamp. */
1235 : time_t get_atimensec(const struct stat *st)
1236 : {
1237 : return 0;
1238 : }
1239 :
1240 : time_t get_mtimensec(const struct stat *st)
1241 : {
1242 : return 0;
1243 : }
1244 :
1245 : time_t get_ctimensec(const struct stat *st)
1246 : {
1247 : return 0;
1248 : }
1249 :
1250 : /* Set does nothing with no ns timestamp. */
1251 : void set_atimensec(struct stat *st, time_t ns)
1252 : {
1253 : return;
1254 : }
1255 :
1256 : void set_mtimensec(struct stat *st, time_t ns)
1257 : {
1258 : return;
1259 : }
1260 :
1261 : void set_ctimensec(struct stat *st, time_t ns)
1262 : {
1263 : return;
1264 : }
1265 :
1266 : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1267 :
1268 : time_t get_atimensec(const struct stat *st)
1269 : {
1270 : return st->st_atimespec.tv_nsec;
1271 : }
1272 :
1273 : time_t get_mtimensec(const struct stat *st)
1274 : {
1275 : return st->st_mtimespec.tv_nsec;
1276 : }
1277 :
1278 : time_t get_ctimensec(const struct stat *st)
1279 : {
1280 : return st->st_ctimespec.tv_nsec;
1281 : }
1282 :
1283 : void set_atimensec(struct stat *st, time_t ns)
1284 : {
1285 : st->st_atimespec.tv_nsec = ns;
1286 : }
1287 :
1288 : void set_mtimensec(struct stat *st, time_t ns)
1289 : {
1290 : st->st_mtimespec.tv_nsec = ns;
1291 : }
1292 :
1293 : void set_ctimensec(struct stat *st, time_t ns)
1294 : {
1295 : st->st_ctimespec.tv_nsec = ns;
1296 : }
1297 :
1298 : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1299 :
1300 78441811 : time_t get_atimensec(const struct stat *st)
1301 : {
1302 78441811 : return st->st_atim.tv_nsec;
1303 : }
1304 :
1305 79235665 : time_t get_mtimensec(const struct stat *st)
1306 : {
1307 79235665 : return st->st_mtim.tv_nsec;
1308 : }
1309 :
1310 79247796 : time_t get_ctimensec(const struct stat *st)
1311 : {
1312 79247796 : return st->st_ctim.tv_nsec;
1313 : }
1314 :
1315 208 : void set_atimensec(struct stat *st, time_t ns)
1316 : {
1317 208 : st->st_atim.tv_nsec = ns;
1318 208 : }
1319 :
1320 208 : void set_mtimensec(struct stat *st, time_t ns)
1321 : {
1322 208 : st->st_mtim.tv_nsec = ns;
1323 208 : }
1324 208 : void set_ctimensec(struct stat *st, time_t ns)
1325 : {
1326 208 : st->st_ctim.tv_nsec = ns;
1327 208 : }
1328 :
1329 : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
1330 :
1331 : time_t get_atimensec(const struct stat *st)
1332 : {
1333 : return st->st_atimensec;
1334 : }
1335 :
1336 : time_t get_mtimensec(const struct stat *st)
1337 : {
1338 : return st->st_mtimensec;
1339 : }
1340 :
1341 : time_t get_ctimensec(const struct stat *st)
1342 : {
1343 : return st->st_ctimensec;
1344 : }
1345 :
1346 : void set_atimensec(struct stat *st, time_t ns)
1347 : {
1348 : st->st_atimensec = ns;
1349 : }
1350 :
1351 : void set_mtimensec(struct stat *st, time_t ns)
1352 : {
1353 : st->st_mtimensec = ns;
1354 : }
1355 :
1356 : void set_ctimensec(struct stat *st, time_t ns)
1357 : {
1358 : st->st_ctimensec = ns;
1359 : }
1360 :
1361 : #elif HAVE_STRUCT_STAT_ST_MTIME_N
1362 :
1363 : time_t get_atimensec(const struct stat *st)
1364 : {
1365 : return st->st_atime_n;
1366 : }
1367 :
1368 : time_t get_mtimensec(const struct stat *st)
1369 : {
1370 : return st->st_mtime_n;
1371 : }
1372 :
1373 : time_t get_ctimensec(const struct stat *st)
1374 : {
1375 : return st->st_ctime_n;
1376 : }
1377 :
1378 : void set_atimensec(struct stat *st, time_t ns)
1379 : {
1380 : st->st_atime_n = ns;
1381 : }
1382 :
1383 : void set_mtimensec(struct stat *st, time_t ns)
1384 : {
1385 : st->st_mtime_n = ns;
1386 : }
1387 :
1388 : void set_ctimensec(struct stat *st, time_t ns)
1389 : {
1390 : st->st_ctime_n = ns;
1391 : }
1392 :
1393 : #elif HAVE_STRUCT_STAT_ST_UMTIME
1394 :
1395 : /* Only usec timestamps available. Convert to/from nsec. */
1396 :
1397 : time_t get_atimensec(const struct stat *st)
1398 : {
1399 : return st->st_uatime * 1000;
1400 : }
1401 :
1402 : time_t get_mtimensec(const struct stat *st)
1403 : {
1404 : return st->st_umtime * 1000;
1405 : }
1406 :
1407 : time_t get_ctimensec(const struct stat *st)
1408 : {
1409 : return st->st_uctime * 1000;
1410 : }
1411 :
1412 : void set_atimensec(struct stat *st, time_t ns)
1413 : {
1414 : st->st_uatime = ns / 1000;
1415 : }
1416 :
1417 : void set_mtimensec(struct stat *st, time_t ns)
1418 : {
1419 : st->st_umtime = ns / 1000;
1420 : }
1421 :
1422 : void set_ctimensec(struct stat *st, time_t ns)
1423 : {
1424 : st->st_uctime = ns / 1000;
1425 : }
1426 :
1427 : #else
1428 : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1429 : #endif
1430 :
1431 77635822 : struct timespec get_atimespec(const struct stat *pst)
1432 : {
1433 270674 : struct timespec ret;
1434 :
1435 77635822 : ret.tv_sec = pst->st_atime;
1436 77635822 : ret.tv_nsec = get_atimensec(pst);
1437 77635822 : return ret;
1438 : }
1439 :
1440 78429672 : struct timespec get_mtimespec(const struct stat *pst)
1441 : {
1442 275323 : struct timespec ret;
1443 :
1444 78429672 : ret.tv_sec = pst->st_mtime;
1445 78429672 : ret.tv_nsec = get_mtimensec(pst);
1446 78429672 : return ret;
1447 : }
1448 :
1449 77635818 : struct timespec get_ctimespec(const struct stat *pst)
1450 : {
1451 270674 : struct timespec ret;
1452 :
1453 77635818 : ret.tv_sec = pst->st_mtime;
1454 77635818 : ret.tv_nsec = get_ctimensec(pst);
1455 77635818 : return ret;
1456 : }
1457 :
1458 : /****************************************************************************
1459 : Deal with nanoseconds overflow.
1460 : ****************************************************************************/
1461 :
1462 5651228 : void normalize_timespec(struct timespec *ts)
1463 : {
1464 155038 : lldiv_t dres;
1465 :
1466 : /* most likely case: nsec is valid */
1467 5651228 : if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
1468 5651228 : return;
1469 : }
1470 :
1471 21555 : dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
1472 :
1473 : /* if the operation would result in overflow, max out values and bail */
1474 21555 : if (dres.quot > 0) {
1475 21543 : if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
1476 1 : ts->tv_sec = LONG_MAX;
1477 1 : ts->tv_nsec = NSEC_PER_SEC - 1;
1478 1 : return;
1479 : }
1480 : } else {
1481 12 : if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
1482 1 : ts->tv_sec = LONG_MIN;
1483 1 : ts->tv_nsec = 0;
1484 1 : return;
1485 : }
1486 : }
1487 :
1488 21553 : ts->tv_nsec = dres.rem;
1489 21553 : ts->tv_sec += dres.quot;
1490 :
1491 : /* if the ns part was positive or a multiple of -1000000000, we're done */
1492 21553 : if (ts->tv_nsec > 0 || dres.rem == 0) {
1493 21535 : return;
1494 : }
1495 :
1496 9 : ts->tv_nsec += NSEC_PER_SEC;
1497 9 : --ts->tv_sec;
1498 : }
|