Coverage Report

Created: 2026-02-14 07:07

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