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 398463 : _PUBLIC_ time_t get_time_t_max(void)
48 : {
49 398463 : return TIME_T_MAX;
50 : }
51 :
52 : /**
53 : a wrapper to preferably get the monotonic time
54 : **/
55 429924834 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
56 : {
57 : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
58 : #ifdef CLOCK_BOOTTIME
59 429924834 : if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
60 429526798 : 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 6583 : _PUBLIC_ time_t time_mono(time_t *t)
76 : {
77 0 : struct timespec tp;
78 :
79 6583 : clock_gettime_mono(&tp);
80 6583 : if (t != NULL) {
81 0 : *t = tp.tv_sec;
82 : }
83 6583 : return tp.tv_sec;
84 : }
85 :
86 :
87 : #define TIME_FIXUP_CONSTANT 11644473600LL
88 :
89 3238756 : time_t convert_timespec_to_time_t(struct timespec ts)
90 : {
91 : /* Ensure tv_nsec is less than 1sec. */
92 3238756 : 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 3238756 : if (ts.tv_nsec > 500000000) {
98 300901 : return ts.tv_sec + 1;
99 : }
100 2937855 : 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 2748817 : time_t nt_time_to_unix(NTTIME nt)
125 : {
126 2748817 : 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 7015749 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
135 : {
136 265081 : uint64_t t2;
137 :
138 7015749 : if (t == (time_t)-1) {
139 1 : *nt = UINT64_MAX;
140 1 : return;
141 : }
142 :
143 7015748 : if (t == TIME_T_MAX || t == INT64_MAX) {
144 61651 : *nt = 0x7fffffffffffffffLL;
145 61651 : return;
146 : }
147 :
148 6954097 : if (t == 0) {
149 22081 : *nt = 0;
150 22081 : return;
151 : }
152 :
153 6932016 : t2 = t;
154 6932016 : t2 += TIME_FIXUP_CONSTANT_INT;
155 6932016 : t2 *= 1000*1000*10;
156 :
157 6932016 : *nt = t2;
158 : }
159 :
160 :
161 : /**
162 : check if it's a null unix time
163 : **/
164 914645 : _PUBLIC_ bool null_time(time_t t)
165 : {
166 86127 : return t == 0 ||
167 999282 : t == (time_t)0xFFFFFFFF ||
168 : t == (time_t)-1;
169 : }
170 :
171 :
172 : /**
173 : check if it's a null NTTIME
174 : **/
175 2503287 : _PUBLIC_ bool null_nttime(NTTIME t)
176 : {
177 2503287 : 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 169293 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
256 : {
257 169293 : if (!null_time(unixdate)) {
258 29190 : unixdate -= zone_offset;
259 : }
260 169293 : SIVAL(buf,offset,unixdate);
261 169293 : }
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 147792 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
325 : {
326 147792 : time_t t = (time_t)IVAL(date_ptr,0);
327 :
328 147792 : if (t == (time_t)0xFFFFFFFF) {
329 4256 : t = (time_t)-1;
330 : }
331 :
332 147792 : if (!null_time(t)) {
333 27806 : t += zone_offset;
334 : }
335 147792 : 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 288359 : _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 288359 : tm = localtime(&t);
513 288359 : 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 288359 : strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
524 288359 : 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 288359 : return TimeBuf;
539 : }
540 :
541 : /**
542 : return a talloced string representing a NTTIME for human consumption
543 : */
544 267397 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
545 : {
546 5318 : time_t t;
547 267397 : if (nt == 0) {
548 6950 : return "NTTIME(0)";
549 : }
550 259111 : t = nt_time_to_full_time_t(nt);
551 259111 : return timestring(mem_ctx, t);
552 : }
553 :
554 :
555 : /**
556 : put a NTTIME into a packet
557 : */
558 425234 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
559 : {
560 425234 : SBVAL(base, offset, t);
561 425234 : }
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 395706 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
576 : {
577 395706 : int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
578 395706 : return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
579 : }
580 :
581 : /**
582 : return (tp1 - tp2) in nanoseconds
583 : */
584 214630144 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
585 : {
586 214630144 : int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
587 214630144 : return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
588 : }
589 :
590 :
591 : /**
592 : return a zero timeval
593 : */
594 130878 : _PUBLIC_ struct timeval timeval_zero(void)
595 : {
596 2476 : struct timeval tv;
597 130878 : tv.tv_sec = 0;
598 130878 : tv.tv_usec = 0;
599 130878 : return tv;
600 : }
601 :
602 : /**
603 : return true if a timeval is zero
604 : */
605 1335987 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
606 : {
607 1335987 : return tv->tv_sec == 0 && tv->tv_usec == 0;
608 : }
609 :
610 : /**
611 : return a timeval for the current time
612 : */
613 15708887 : _PUBLIC_ struct timeval timeval_current(void)
614 : {
615 722162 : struct timeval tv;
616 15708887 : GetTimeOfDay(&tv);
617 15708887 : return tv;
618 : }
619 :
620 : /**
621 : return a timeval ofs microseconds after tv
622 : */
623 8177352 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
624 : uint32_t secs, uint32_t usecs)
625 : {
626 8177352 : struct timeval tv2 = *tv;
627 8177352 : const unsigned int million = 1000000;
628 8177352 : tv2.tv_sec += secs;
629 8177352 : tv2.tv_usec += usecs;
630 8177352 : tv2.tv_sec += tv2.tv_usec / million;
631 8177352 : tv2.tv_usec = tv2.tv_usec % million;
632 8177352 : return tv2;
633 : }
634 :
635 : /**
636 : return the sum of two timeval structures
637 : */
638 112741 : struct timeval timeval_sum(const struct timeval *tv1,
639 : const struct timeval *tv2)
640 : {
641 112741 : return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
642 : }
643 :
644 : /**
645 : return a timeval secs/usecs into the future
646 : */
647 2679069 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
648 : {
649 2679069 : struct timeval tv = timeval_current();
650 2679069 : return timeval_add(&tv, secs, usecs);
651 : }
652 :
653 : /**
654 : return a timeval milliseconds into the future
655 : */
656 4508584 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
657 : {
658 4508584 : struct timeval tv = timeval_current();
659 4508584 : return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
660 : }
661 :
662 : /**
663 : return a timeval microseconds into the future
664 : */
665 465750 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
666 : {
667 465750 : struct timeval tv = timeval_current();
668 465750 : return timeval_add(&tv, usecs / 1000000, usecs % 1000000);
669 : }
670 :
671 : /**
672 : compare two timeval structures.
673 : Return -1 if tv1 < tv2
674 : Return 0 if tv1 == tv2
675 : Return 1 if tv1 > tv2
676 : */
677 8211 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
678 : {
679 8211 : if (tv1->tv_sec > tv2->tv_sec) return 1;
680 7263 : if (tv1->tv_sec < tv2->tv_sec) return -1;
681 7254 : if (tv1->tv_usec > tv2->tv_usec) return 1;
682 3748 : if (tv1->tv_usec < tv2->tv_usec) return -1;
683 6 : return 0;
684 : }
685 :
686 : /**
687 : return true if a timer is in the past
688 : */
689 1045572 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
690 : {
691 1045572 : struct timeval tv2 = timeval_current();
692 1045572 : if (tv2.tv_sec > tv->tv_sec) return true;
693 1045502 : if (tv2.tv_sec < tv->tv_sec) return false;
694 2989 : return (tv2.tv_usec >= tv->tv_usec);
695 : }
696 :
697 : /**
698 : return the number of seconds elapsed between two times
699 : */
700 828417 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
701 : {
702 1066157 : return (tv2->tv_sec - tv1->tv_sec) +
703 828417 : (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
704 : }
705 :
706 : /**
707 : return the number of seconds elapsed since a given time
708 : */
709 827970 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
710 : {
711 827970 : struct timeval tv2 = timeval_current();
712 827970 : return timeval_elapsed2(tv, &tv2);
713 : }
714 : /**
715 : * return the number of seconds elapsed between two times
716 : **/
717 630 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
718 : const struct timespec *ts2)
719 : {
720 1253 : return (ts2->tv_sec - ts1->tv_sec) +
721 630 : (ts2->tv_nsec - ts1->tv_nsec)*1.0e-9;
722 : }
723 :
724 : /**
725 : * return the number of seconds elapsed since a given time
726 : */
727 106 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
728 : {
729 106 : struct timespec ts2 = timespec_current();
730 106 : return timespec_elapsed2(ts, &ts2);
731 : }
732 :
733 : /**
734 : return the lesser of two timevals
735 : */
736 3975 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
737 : const struct timeval *tv2)
738 : {
739 3975 : if (tv1->tv_sec < tv2->tv_sec) return *tv1;
740 3572 : if (tv1->tv_sec > tv2->tv_sec) return *tv2;
741 3482 : if (tv1->tv_usec < tv2->tv_usec) return *tv1;
742 0 : return *tv2;
743 : }
744 :
745 : /**
746 : return the greater of two timevals
747 : */
748 0 : _PUBLIC_ struct timeval timeval_max(const struct timeval *tv1,
749 : const struct timeval *tv2)
750 : {
751 0 : if (tv1->tv_sec > tv2->tv_sec) return *tv1;
752 0 : if (tv1->tv_sec < tv2->tv_sec) return *tv2;
753 0 : if (tv1->tv_usec > tv2->tv_usec) return *tv1;
754 0 : return *tv2;
755 : }
756 :
757 : /**
758 : convert a timeval to a NTTIME
759 : */
760 7874952 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
761 : {
762 15675187 : return 10*(tv->tv_usec +
763 7874952 : ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
764 : }
765 :
766 : /**
767 : convert a NTTIME to a timeval
768 : */
769 75179 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
770 : {
771 75179 : if (tv == NULL) return;
772 :
773 75179 : t += 10/2;
774 75179 : t /= 10;
775 75179 : t -= TIME_FIXUP_CONSTANT*1000*1000;
776 :
777 75179 : tv->tv_sec = t / 1000000;
778 :
779 75179 : if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) {
780 0 : tv->tv_sec = 0;
781 0 : tv->tv_usec = 0;
782 0 : return;
783 : }
784 :
785 75179 : tv->tv_usec = t - tv->tv_sec*1000000;
786 : }
787 :
788 : /*******************************************************************
789 : yield the difference between *A and *B, in seconds, ignoring leap seconds
790 : ********************************************************************/
791 15508 : static int tm_diff(struct tm *a, struct tm *b)
792 : {
793 15508 : int ay = a->tm_year + (1900 - 1);
794 15508 : int by = b->tm_year + (1900 - 1);
795 15508 : int intervening_leap_days =
796 15508 : (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
797 15508 : int years = ay - by;
798 15508 : int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
799 15508 : int hours = 24*days + (a->tm_hour - b->tm_hour);
800 15508 : int minutes = 60*hours + (a->tm_min - b->tm_min);
801 15508 : int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
802 :
803 15508 : return seconds;
804 : }
805 :
806 :
807 : /**
808 : return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
809 : */
810 15508 : _PUBLIC_ int get_time_zone(time_t t)
811 : {
812 15508 : struct tm *tm = gmtime(&t);
813 268 : struct tm tm_utc;
814 15508 : if (!tm)
815 0 : return 0;
816 15508 : tm_utc = *tm;
817 15508 : tm = localtime(&t);
818 15508 : if (!tm)
819 0 : return 0;
820 15508 : return tm_diff(&tm_utc,tm);
821 : }
822 :
823 : /*
824 : * Raw convert an NTTIME to a unix timespec.
825 : */
826 :
827 5190233 : struct timespec nt_time_to_unix_timespec_raw(
828 : NTTIME nt)
829 : {
830 156268 : int64_t d;
831 156268 : struct timespec ret;
832 :
833 5190233 : d = (int64_t)nt;
834 : /* d is now in 100ns units, since jan 1st 1601".
835 : Save off the ns fraction. */
836 :
837 : /*
838 : * Take the last seven decimal digits and multiply by 100.
839 : * to convert from 100ns units to 1ns units.
840 : */
841 5190233 : ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
842 :
843 : /* Convert to seconds */
844 5190233 : d /= 1000*1000*10;
845 :
846 : /* Now adjust by 369 years to make the secs since 1970 */
847 5190233 : d -= TIME_FIXUP_CONSTANT_INT;
848 :
849 5190233 : ret.tv_sec = (time_t)d;
850 5190233 : return ret;
851 : }
852 :
853 2760271 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
854 : {
855 148756 : struct timespec ret;
856 :
857 2760271 : if (nt == 0 || nt == UINT64_MAX) {
858 7922 : ret.tv_sec = 0;
859 7922 : ret.tv_nsec = 0;
860 7922 : return ret;
861 : }
862 :
863 2752349 : ret = nt_time_to_unix_timespec_raw(nt);
864 :
865 2752349 : if (ret.tv_sec <= TIME_T_MIN) {
866 383 : ret.tv_sec = TIME_T_MIN;
867 383 : ret.tv_nsec = 0;
868 383 : return ret;
869 : }
870 :
871 2751966 : if (ret.tv_sec >= TIME_T_MAX) {
872 0 : ret.tv_sec = TIME_T_MAX;
873 0 : ret.tv_nsec = 0;
874 0 : return ret;
875 : }
876 2751966 : return ret;
877 : }
878 :
879 :
880 : /**
881 : check if 2 NTTIMEs are equal.
882 : */
883 72 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
884 : {
885 72 : return *t1 == *t2;
886 : }
887 :
888 : /**
889 : Check if it's a null timespec.
890 : **/
891 :
892 79084251 : bool null_timespec(struct timespec ts)
893 : {
894 157895963 : return ts.tv_sec == 0 ||
895 157895963 : ts.tv_sec == (time_t)0xFFFFFFFF ||
896 78811712 : ts.tv_sec == (time_t)-1;
897 : }
898 :
899 : /****************************************************************************
900 : Convert a normalized timeval to a timespec.
901 : ****************************************************************************/
902 :
903 8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
904 : {
905 0 : struct timespec ts;
906 8 : ts.tv_sec = tv.tv_sec;
907 8 : ts.tv_nsec = tv.tv_usec * 1000;
908 8 : return ts;
909 : }
910 :
911 : /****************************************************************************
912 : Convert a normalized timespec to a timeval.
913 : ****************************************************************************/
914 :
915 8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
916 : {
917 0 : struct timeval tv;
918 8 : tv.tv_sec = ts.tv_sec;
919 8 : tv.tv_usec = ts.tv_nsec / 1000;
920 8 : return tv;
921 : }
922 :
923 : /****************************************************************************
924 : Return a timespec for the current time
925 : ****************************************************************************/
926 :
927 325257 : _PUBLIC_ struct timespec timespec_current(void)
928 : {
929 983 : struct timespec ts;
930 325257 : clock_gettime(CLOCK_REALTIME, &ts);
931 325257 : return ts;
932 : }
933 :
934 : /****************************************************************************
935 : Return the lesser of two timespecs.
936 : ****************************************************************************/
937 :
938 0 : struct timespec timespec_min(const struct timespec *ts1,
939 : const struct timespec *ts2)
940 : {
941 0 : if (ts1->tv_sec < ts2->tv_sec) return *ts1;
942 0 : if (ts1->tv_sec > ts2->tv_sec) return *ts2;
943 0 : if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
944 0 : return *ts2;
945 : }
946 :
947 : /****************************************************************************
948 : compare two timespec structures.
949 : Return -1 if ts1 < ts2
950 : Return 0 if ts1 == ts2
951 : Return 1 if ts1 > ts2
952 : ****************************************************************************/
953 :
954 81395251 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
955 : {
956 81395251 : if (ts1->tv_sec > ts2->tv_sec) return 1;
957 78803078 : if (ts1->tv_sec < ts2->tv_sec) return -1;
958 77498238 : if (ts1->tv_nsec > ts2->tv_nsec) return 1;
959 69360186 : if (ts1->tv_nsec < ts2->tv_nsec) return -1;
960 58353300 : return 0;
961 : }
962 :
963 : /****************************************************************************
964 : Round up a timespec if nsec > 500000000, round down if lower,
965 : then zero nsec.
966 : ****************************************************************************/
967 :
968 66128 : void round_timespec_to_sec(struct timespec *ts)
969 : {
970 66128 : ts->tv_sec = convert_timespec_to_time_t(*ts);
971 66128 : ts->tv_nsec = 0;
972 66128 : }
973 :
974 : /****************************************************************************
975 : Round a timespec to usec value.
976 : ****************************************************************************/
977 :
978 0 : void round_timespec_to_usec(struct timespec *ts)
979 : {
980 0 : struct timeval tv = convert_timespec_to_timeval(*ts);
981 0 : *ts = convert_timeval_to_timespec(tv);
982 0 : normalize_timespec(ts);
983 0 : }
984 :
985 : /****************************************************************************
986 : Round a timespec to NTTIME resolution.
987 : ****************************************************************************/
988 :
989 0 : void round_timespec_to_nttime(struct timespec *ts)
990 : {
991 0 : ts->tv_nsec = (ts->tv_nsec / 100) * 100;
992 0 : }
993 :
994 : /****************************************************************************
995 : Put a 8 byte filetime from a struct timespec. Uses GMT.
996 : ****************************************************************************/
997 :
998 18130 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
999 : {
1000 0 : uint64_t d;
1001 :
1002 18130 : if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
1003 0 : return 0;
1004 : }
1005 18130 : if (ts.tv_sec == TIME_T_MAX) {
1006 0 : return 0x7fffffffffffffffLL;
1007 : }
1008 18130 : if (ts.tv_sec == (time_t)-1) {
1009 0 : return UINT64_MAX;
1010 : }
1011 :
1012 18130 : d = ts.tv_sec;
1013 18130 : d += TIME_FIXUP_CONSTANT_INT;
1014 18130 : d *= 1000*1000*10;
1015 : /* d is now in 100ns units. */
1016 18130 : d += (ts.tv_nsec / 100);
1017 :
1018 18130 : return d;
1019 : }
1020 :
1021 : /*
1022 : * Functions supporting the full range of time_t and struct timespec values,
1023 : * including 0, -1 and all other negative values. These functions don't use 0 or
1024 : * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
1025 : * define UTIME_OMIT from utimensat(2).
1026 : */
1027 :
1028 : /**
1029 : * Check if it's a to be omitted timespec.
1030 : **/
1031 13631534 : bool is_omit_timespec(const struct timespec *ts)
1032 : {
1033 13631534 : return ts->tv_nsec == SAMBA_UTIME_OMIT;
1034 : }
1035 :
1036 : /**
1037 : * Return a to be omitted timespec.
1038 : **/
1039 8688694 : struct timespec make_omit_timespec(void)
1040 : {
1041 8688694 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1042 : }
1043 :
1044 : /**
1045 : * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
1046 : * and -1. Also dealing with SAMBA_UTIME_OMIT.
1047 : **/
1048 6298243 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
1049 : {
1050 6298243 : struct timespec ts = *_ts;
1051 9649 : uint64_t d;
1052 :
1053 6298243 : if (is_omit_timespec(_ts)) {
1054 1538629 : return NTTIME_OMIT;
1055 : }
1056 :
1057 : /* Ensure tv_nsec is less than 1 sec. */
1058 4757254 : while (ts.tv_nsec > 1000000000) {
1059 0 : if (ts.tv_sec > TIME_T_MAX) {
1060 0 : return NTTIME_MAX;
1061 : }
1062 0 : ts.tv_sec += 1;
1063 0 : ts.tv_nsec -= 1000000000;
1064 : }
1065 :
1066 4757254 : if (ts.tv_sec >= TIME_T_MAX) {
1067 0 : return NTTIME_MAX;
1068 : }
1069 4757254 : if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
1070 0 : return NTTIME_MIN;
1071 : }
1072 :
1073 4757254 : d = TIME_FIXUP_CONSTANT_INT;
1074 4757254 : d += ts.tv_sec;
1075 :
1076 4757254 : d *= 1000*1000*10;
1077 : /* d is now in 100ns units. */
1078 4757254 : d += (ts.tv_nsec / 100);
1079 :
1080 4757254 : return d;
1081 : }
1082 :
1083 : /**
1084 : * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
1085 : * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
1086 : *
1087 : * See also: is_omit_timespec().
1088 : **/
1089 2532668 : struct timespec nt_time_to_full_timespec(NTTIME nt)
1090 : {
1091 8507 : struct timespec ret;
1092 :
1093 2532668 : if (nt == NTTIME_OMIT) {
1094 90625 : return make_omit_timespec();
1095 : }
1096 2442043 : if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) {
1097 : /*
1098 : * This should be returned as SAMBA_UTIME_FREEZE or
1099 : * SAMBA_UTIME_THAW in the future.
1100 : */
1101 4159 : return make_omit_timespec();
1102 : }
1103 2437884 : if (nt > NTTIME_MAX) {
1104 2 : nt = NTTIME_MAX;
1105 : }
1106 :
1107 2437884 : ret = nt_time_to_unix_timespec_raw(nt);
1108 :
1109 2437884 : if (ret.tv_sec >= TIME_T_MAX) {
1110 0 : ret.tv_sec = TIME_T_MAX;
1111 0 : ret.tv_nsec = 0;
1112 0 : return ret;
1113 : }
1114 :
1115 2437884 : return ret;
1116 : }
1117 :
1118 : /**
1119 : * Note: this function uses the full time_t range as valid date values including
1120 : * (time_t)0 and -1. That means that struct timespec sentinel values (cf
1121 : * is_omit_timespec()) can't be converted to sentinel values in a time_t
1122 : * representation. Callers should therefore check the NTTIME value with
1123 : * null_nttime() before calling this function.
1124 : **/
1125 259111 : time_t full_timespec_to_time_t(const struct timespec *_ts)
1126 : {
1127 259111 : struct timespec ts = *_ts;
1128 :
1129 259111 : if (is_omit_timespec(_ts)) {
1130 : /*
1131 : * Unfortunately there's no sensible sentinel value in the
1132 : * time_t range that is not conflicting with a valid time value
1133 : * ((time_t)0 and -1 are valid time values). Bite the bullit and
1134 : * return 0.
1135 : */
1136 0 : return 0;
1137 : }
1138 :
1139 : /* Ensure tv_nsec is less than 1sec. */
1140 259111 : while (ts.tv_nsec > 1000000000) {
1141 0 : ts.tv_sec += 1;
1142 0 : ts.tv_nsec -= 1000000000;
1143 : }
1144 :
1145 : /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
1146 : increment if it's greater than 500 millionth of a second. */
1147 :
1148 259111 : if (ts.tv_nsec > 500000000) {
1149 17932 : return ts.tv_sec + 1;
1150 : }
1151 237879 : return ts.tv_sec;
1152 : }
1153 :
1154 : /**
1155 : * Like nt_time_to_unix() but supports negative time_t values.
1156 : *
1157 : * Note: this function uses the full time_t range as valid date values including
1158 : * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
1159 : * represent a "not-set" value, can't be converted to sentinel values in a
1160 : * time_t representation. Callers should therefore check the NTTIME value with
1161 : * null_nttime() before calling this function.
1162 : **/
1163 259111 : time_t nt_time_to_full_time_t(NTTIME nt)
1164 : {
1165 3982 : struct timespec ts;
1166 :
1167 259111 : ts = nt_time_to_full_timespec(nt);
1168 259111 : return full_timespec_to_time_t(&ts);
1169 : }
1170 :
1171 : /**
1172 : * Like time_t_to_unix_timespec() but supports negative time_t values.
1173 : *
1174 : * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
1175 : * can't be used as valid date values. The function supports values < -1 though.
1176 : **/
1177 32606 : struct timespec time_t_to_full_timespec(time_t t)
1178 : {
1179 32606 : if (null_time(t)) {
1180 32416 : return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
1181 : }
1182 190 : return (struct timespec){.tv_sec = t};
1183 : }
1184 :
1185 : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1186 :
1187 : /* Old system - no ns timestamp. */
1188 : time_t get_atimensec(const struct stat *st)
1189 : {
1190 : return 0;
1191 : }
1192 :
1193 : time_t get_mtimensec(const struct stat *st)
1194 : {
1195 : return 0;
1196 : }
1197 :
1198 : time_t get_ctimensec(const struct stat *st)
1199 : {
1200 : return 0;
1201 : }
1202 :
1203 : /* Set does nothing with no ns timestamp. */
1204 : void set_atimensec(struct stat *st, time_t ns)
1205 : {
1206 : return;
1207 : }
1208 :
1209 : void set_mtimensec(struct stat *st, time_t ns)
1210 : {
1211 : return;
1212 : }
1213 :
1214 : void set_ctimensec(struct stat *st, time_t ns)
1215 : {
1216 : return;
1217 : }
1218 :
1219 : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
1220 :
1221 : time_t get_atimensec(const struct stat *st)
1222 : {
1223 : return st->st_atimespec.tv_nsec;
1224 : }
1225 :
1226 : time_t get_mtimensec(const struct stat *st)
1227 : {
1228 : return st->st_mtimespec.tv_nsec;
1229 : }
1230 :
1231 : time_t get_ctimensec(const struct stat *st)
1232 : {
1233 : return st->st_ctimespec.tv_nsec;
1234 : }
1235 :
1236 : void set_atimensec(struct stat *st, time_t ns)
1237 : {
1238 : st->st_atimespec.tv_nsec = ns;
1239 : }
1240 :
1241 : void set_mtimensec(struct stat *st, time_t ns)
1242 : {
1243 : st->st_mtimespec.tv_nsec = ns;
1244 : }
1245 :
1246 : void set_ctimensec(struct stat *st, time_t ns)
1247 : {
1248 : st->st_ctimespec.tv_nsec = ns;
1249 : }
1250 :
1251 : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1252 :
1253 79868083 : time_t get_atimensec(const struct stat *st)
1254 : {
1255 79868083 : return st->st_atim.tv_nsec;
1256 : }
1257 :
1258 80674985 : time_t get_mtimensec(const struct stat *st)
1259 : {
1260 80674985 : return st->st_mtim.tv_nsec;
1261 : }
1262 :
1263 80674610 : time_t get_ctimensec(const struct stat *st)
1264 : {
1265 80674610 : return st->st_ctim.tv_nsec;
1266 : }
1267 :
1268 215 : void set_atimensec(struct stat *st, time_t ns)
1269 : {
1270 215 : st->st_atim.tv_nsec = ns;
1271 215 : }
1272 :
1273 215 : void set_mtimensec(struct stat *st, time_t ns)
1274 : {
1275 215 : st->st_mtim.tv_nsec = ns;
1276 215 : }
1277 215 : void set_ctimensec(struct stat *st, time_t ns)
1278 : {
1279 215 : st->st_ctim.tv_nsec = ns;
1280 215 : }
1281 :
1282 : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
1283 :
1284 : time_t get_atimensec(const struct stat *st)
1285 : {
1286 : return st->st_atimensec;
1287 : }
1288 :
1289 : time_t get_mtimensec(const struct stat *st)
1290 : {
1291 : return st->st_mtimensec;
1292 : }
1293 :
1294 : time_t get_ctimensec(const struct stat *st)
1295 : {
1296 : return st->st_ctimensec;
1297 : }
1298 :
1299 : void set_atimensec(struct stat *st, time_t ns)
1300 : {
1301 : st->st_atimensec = ns;
1302 : }
1303 :
1304 : void set_mtimensec(struct stat *st, time_t ns)
1305 : {
1306 : st->st_mtimensec = ns;
1307 : }
1308 :
1309 : void set_ctimensec(struct stat *st, time_t ns)
1310 : {
1311 : st->st_ctimensec = ns;
1312 : }
1313 :
1314 : #elif HAVE_STRUCT_STAT_ST_MTIME_N
1315 :
1316 : time_t get_atimensec(const struct stat *st)
1317 : {
1318 : return st->st_atime_n;
1319 : }
1320 :
1321 : time_t get_mtimensec(const struct stat *st)
1322 : {
1323 : return st->st_mtime_n;
1324 : }
1325 :
1326 : time_t get_ctimensec(const struct stat *st)
1327 : {
1328 : return st->st_ctime_n;
1329 : }
1330 :
1331 : void set_atimensec(struct stat *st, time_t ns)
1332 : {
1333 : st->st_atime_n = ns;
1334 : }
1335 :
1336 : void set_mtimensec(struct stat *st, time_t ns)
1337 : {
1338 : st->st_mtime_n = ns;
1339 : }
1340 :
1341 : void set_ctimensec(struct stat *st, time_t ns)
1342 : {
1343 : st->st_ctime_n = ns;
1344 : }
1345 :
1346 : #elif HAVE_STRUCT_STAT_ST_UMTIME
1347 :
1348 : /* Only usec timestamps available. Convert to/from nsec. */
1349 :
1350 : time_t get_atimensec(const struct stat *st)
1351 : {
1352 : return st->st_uatime * 1000;
1353 : }
1354 :
1355 : time_t get_mtimensec(const struct stat *st)
1356 : {
1357 : return st->st_umtime * 1000;
1358 : }
1359 :
1360 : time_t get_ctimensec(const struct stat *st)
1361 : {
1362 : return st->st_uctime * 1000;
1363 : }
1364 :
1365 : void set_atimensec(struct stat *st, time_t ns)
1366 : {
1367 : st->st_uatime = ns / 1000;
1368 : }
1369 :
1370 : void set_mtimensec(struct stat *st, time_t ns)
1371 : {
1372 : st->st_umtime = ns / 1000;
1373 : }
1374 :
1375 : void set_ctimensec(struct stat *st, time_t ns)
1376 : {
1377 : st->st_uctime = ns / 1000;
1378 : }
1379 :
1380 : #else
1381 : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1382 : #endif
1383 :
1384 79061552 : struct timespec get_atimespec(const struct stat *pst)
1385 : {
1386 271098 : struct timespec ret;
1387 :
1388 79061552 : ret.tv_sec = pst->st_atime;
1389 79061552 : ret.tv_nsec = get_atimensec(pst);
1390 79061552 : return ret;
1391 : }
1392 :
1393 79868450 : struct timespec get_mtimespec(const struct stat *pst)
1394 : {
1395 275748 : struct timespec ret;
1396 :
1397 79868450 : ret.tv_sec = pst->st_mtime;
1398 79868450 : ret.tv_nsec = get_mtimensec(pst);
1399 79868450 : return ret;
1400 : }
1401 :
1402 79061548 : struct timespec get_ctimespec(const struct stat *pst)
1403 : {
1404 271098 : struct timespec ret;
1405 :
1406 79061548 : ret.tv_sec = pst->st_ctime;
1407 79061548 : ret.tv_nsec = get_ctimensec(pst);
1408 79061548 : return ret;
1409 : }
1410 :
1411 : /****************************************************************************
1412 : Deal with nanoseconds overflow.
1413 : ****************************************************************************/
1414 :
1415 3238782 : void normalize_timespec(struct timespec *ts)
1416 : {
1417 151578 : lldiv_t dres;
1418 :
1419 : /* most likely case: nsec is valid */
1420 3238782 : if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
1421 3238782 : return;
1422 : }
1423 :
1424 21552 : dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
1425 :
1426 : /* if the operation would result in overflow, max out values and bail */
1427 21552 : if (dres.quot > 0) {
1428 21540 : if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
1429 1 : ts->tv_sec = LONG_MAX;
1430 1 : ts->tv_nsec = NSEC_PER_SEC - 1;
1431 1 : return;
1432 : }
1433 : } else {
1434 12 : if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
1435 1 : ts->tv_sec = LONG_MIN;
1436 1 : ts->tv_nsec = 0;
1437 1 : return;
1438 : }
1439 : }
1440 :
1441 21550 : ts->tv_nsec = dres.rem;
1442 21550 : ts->tv_sec += dres.quot;
1443 :
1444 : /* if the ns part was positive or a multiple of -1000000000, we're done */
1445 21550 : if (ts->tv_nsec > 0 || dres.rem == 0) {
1446 21532 : return;
1447 : }
1448 :
1449 9 : ts->tv_nsec += NSEC_PER_SEC;
1450 9 : --ts->tv_sec;
1451 : }
|