Merge branch 'v3-devel' of ssh://jra@git.samba.org/data/git/samba into v3-devel
[metze/samba/wip.git] / source3 / lib / time.c
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
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 /**
26  * @file
27  * @brief time handling functions
28  */
29
30
31 #ifndef TIME_T_MIN
32 #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
33                     : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
34 #endif
35 #ifndef TIME_T_MAX
36 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
37 #endif
38
39 #define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
40
41 /***************************************************************************
42  External access to time_t_min and time_t_max.
43 ****************************************************************************/
44
45 time_t get_time_t_max(void)
46 {
47         return TIME_T_MAX;
48 }
49
50 /***************************************************************************
51  A gettimeofday wrapper.
52 ****************************************************************************/
53
54 void GetTimeOfDay(struct timeval *tval)
55 {
56 #ifdef HAVE_GETTIMEOFDAY_TZ
57         gettimeofday(tval,NULL);
58 #else
59         gettimeofday(tval);
60 #endif
61 }
62
63 #if (SIZEOF_LONG == 8)
64 #define TIME_FIXUP_CONSTANT_INT 11644473600L
65 #elif (SIZEOF_LONG_LONG == 8)
66 #define TIME_FIXUP_CONSTANT_INT 11644473600LL
67 #endif
68
69 /****************************************************************************
70  Interpret an 8 byte "filetime" structure to a time_t
71  It's originally in "100ns units since jan 1st 1601"
72
73  An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
74
75         tv_sec = 0
76         tv_nsec = 0;
77
78  Returns GMT.
79 ****************************************************************************/
80
81 time_t nt_time_to_unix(NTTIME nt)
82 {
83         return convert_timespec_to_time_t(nt_time_to_unix_timespec(&nt));
84 }
85
86 /****************************************************************************
87  Put a 8 byte filetime from a time_t. Uses GMT.
88 ****************************************************************************/
89
90 void unix_to_nt_time(NTTIME *nt, time_t t)
91 {
92         uint64_t t2; 
93
94         if (t == (time_t)-1) {
95                 *nt = (NTTIME)-1LL;
96                 return;
97         }       
98
99         if (t == TIME_T_MAX) {
100                 *nt = 0x7fffffffffffffffLL;
101                 return;
102         }
103
104         if (t == 0) {
105                 *nt = 0;
106                 return;
107         }               
108
109         t2 = t;
110         t2 += TIME_FIXUP_CONSTANT_INT;
111         t2 *= 1000*1000*10;
112
113         *nt = t2;
114 }
115
116 /****************************************************************************
117  Check if it's a null unix time.
118 ****************************************************************************/
119
120 bool null_time(time_t t)
121 {
122         return t == 0 || 
123                 t == (time_t)0xFFFFFFFF || 
124                 t == (time_t)-1;
125 }
126
127 /****************************************************************************
128  Check if it's a null NTTIME.
129 ****************************************************************************/
130
131 bool null_nttime(NTTIME t)
132 {
133         return t == 0 || t == (NTTIME)-1;
134 }
135
136 /****************************************************************************
137  Check if it's a null timespec.
138 ****************************************************************************/
139
140 bool null_timespec(struct timespec ts)
141 {
142         return ts.tv_sec == 0 || 
143                 ts.tv_sec == (time_t)0xFFFFFFFF || 
144                 ts.tv_sec == (time_t)-1;
145 }
146
147 /*******************************************************************
148   create a 16 bit dos packed date
149 ********************************************************************/
150 static uint16_t make_dos_date1(struct tm *t)
151 {
152         uint16_t ret=0;
153         ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
154         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
155         return ret;
156 }
157
158 /*******************************************************************
159   create a 16 bit dos packed time
160 ********************************************************************/
161 static uint16_t make_dos_time1(struct tm *t)
162 {
163         uint16_t ret=0;
164         ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
165         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
166         return ret;
167 }
168
169 /*******************************************************************
170   create a 32 bit dos packed date/time from some parameters
171   This takes a GMT time and returns a packed localtime structure
172 ********************************************************************/
173 static uint32_t make_dos_date(time_t unixdate, int zone_offset)
174 {
175         struct tm *t;
176         uint32_t ret=0;
177
178         if (unixdate == 0) {
179                 return 0;
180         }
181
182         unixdate -= zone_offset;
183
184         t = gmtime(&unixdate);
185         if (!t) {
186                 return 0xFFFFFFFF;
187         }
188
189         ret = make_dos_date1(t);
190         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
191
192         return ret;
193 }
194
195 /**
196 put a dos date into a buffer (time/date format)
197 This takes GMT time and puts local time in the buffer
198 **/
199 void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
200 {
201         uint32_t x = make_dos_date(unixdate, zone_offset);
202         SIVAL(buf,offset,x);
203 }
204
205 /**
206 put a dos date into a buffer (date/time format)
207 This takes GMT time and puts local time in the buffer
208 **/
209 void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
210 {
211         uint32_t x;
212         x = make_dos_date(unixdate, zone_offset);
213         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
214         SIVAL(buf,offset,x);
215 }
216
217 /**
218 put a dos 32 bit "unix like" date into a buffer. This routine takes
219 GMT and converts it to LOCAL time before putting it (most SMBs assume
220 localtime for this sort of date)
221 **/
222 void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
223 {
224         if (!null_time(unixdate)) {
225                 unixdate -= zone_offset;
226         }
227         SIVAL(buf,offset,unixdate);
228 }
229
230 /*******************************************************************
231   interpret a 32 bit dos packed date/time to some parameters
232 ********************************************************************/
233 static void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
234 {
235         uint32_t p0,p1,p2,p3;
236
237         p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
238         p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
239
240         *second = 2*(p0 & 0x1F);
241         *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
242         *hour = (p1>>3)&0xFF;
243         *day = (p2&0x1F);
244         *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
245         *year = ((p3>>1)&0xFF) + 80;
246 }
247
248 /**
249   create a unix date (int GMT) from a dos date (which is actually in
250   localtime)
251 **/
252 time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
253 {
254         uint32_t dos_date=0;
255         struct tm t;
256         time_t ret;
257
258         dos_date = IVAL(date_ptr,0);
259
260         if (dos_date == 0) return (time_t)0;
261   
262         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
263                            &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
264         t.tm_isdst = -1;
265   
266         ret = timegm(&t);
267
268         ret += zone_offset;
269
270         return ret;
271 }
272
273 /**
274 like make_unix_date() but the words are reversed
275 **/
276 time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
277 {
278         uint32_t x,x2;
279
280         x = IVAL(date_ptr,0);
281         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
282         SIVAL(&x,0,x2);
283
284         return pull_dos_date((const uint8_t *)&x, zone_offset);
285 }
286
287 /**
288   create a unix GMT date from a dos date in 32 bit "unix like" format
289   these generally arrive as localtimes, with corresponding DST
290 **/
291 time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
292 {
293         time_t t = (time_t)IVAL(date_ptr,0);
294         if (!null_time(t)) {
295                 t += zone_offset;
296         }
297         return t;
298 }
299
300 /***************************************************************************
301  Return a HTTP/1.0 time string.
302 ***************************************************************************/
303
304 char *http_timestring(time_t t)
305 {
306         fstring buf;
307         struct tm *tm = localtime(&t);
308
309         if (t == TIME_T_MAX) {
310                 fstrcpy(buf, "never");
311         } else if (!tm) {
312                 fstr_sprintf(buf, "%ld seconds since the Epoch", (long)t);
313         } else {
314 #ifndef HAVE_STRFTIME
315                 const char *asct = asctime(tm);
316                 fstrcpy(buf, asct ? asct : "unknown");
317         }
318         if(buf[strlen(buf)-1] == '\n') {
319                 buf[strlen(buf)-1] = 0;
320 #else /* !HAVE_STRFTIME */
321                 strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
322 #endif /* !HAVE_STRFTIME */
323         }
324         return talloc_strdup(talloc_tos(), buf);
325 }
326
327
328 /**
329  Return the date and time as a string
330 **/
331 char *timestring(TALLOC_CTX *mem_ctx, time_t t)
332 {
333         char *TimeBuf;
334         char tempTime[80];
335         struct tm *tm;
336
337         tm = localtime(&t);
338         if (!tm) {
339                 return talloc_asprintf(mem_ctx,
340                                        "%ld seconds since the Epoch",
341                                        (long)t);
342         }
343
344 #ifdef HAVE_STRFTIME
345         /* some versions of gcc complain about using %c. This is a bug
346            in the gcc warning, not a bug in this code. See a recent
347            strftime() manual page for details.
348          */
349         strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm);
350         TimeBuf = talloc_strdup(mem_ctx, tempTime);
351 #else
352         TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
353 #endif
354
355         return TimeBuf;
356 }
357
358 /**
359   return a talloced string representing a NTTIME for human consumption
360 */
361 const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
362 {
363         time_t t;
364         if (nt == 0) {
365                 return "NTTIME(0)";
366         }
367         t = nt_time_to_unix(nt);
368         return timestring(mem_ctx, t);
369 }
370
371
372 /**
373   parse a nttime as a large integer in a string and return a NTTIME
374 */
375 NTTIME nttime_from_string(const char *s)
376 {
377         return strtoull(s, NULL, 0);
378 }
379
380 /**
381   return (tv1 - tv2) in microseconds
382 */
383 int64_t usec_time_diff(struct timeval *tv1, struct timeval *tv2)
384 {
385         int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
386         return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
387 }
388
389
390 /**
391   return a zero timeval
392 */
393 struct timeval timeval_zero(void)
394 {
395         struct timeval tv;
396         tv.tv_sec = 0;
397         tv.tv_usec = 0;
398         return tv;
399 }
400
401 /**
402   return True if a timeval is zero
403 */
404 bool timeval_is_zero(const struct timeval *tv)
405 {
406         return tv->tv_sec == 0 && tv->tv_usec == 0;
407 }
408
409 /**
410   return a timeval for the current time
411 */
412 struct timeval timeval_current(void)
413 {
414         struct timeval tv;
415         GetTimeOfDay(&tv);
416         return tv;
417 }
418
419 /**
420   return a timeval struct with the given elements
421 */
422 struct timeval timeval_set(uint32_t secs, uint32_t usecs)
423 {
424         struct timeval tv;
425         tv.tv_sec = secs;
426         tv.tv_usec = usecs;
427         return tv;
428 }
429
430
431 /**
432   return a timeval ofs microseconds after tv
433 */
434 struct timeval timeval_add(const struct timeval *tv,
435                            uint32_t secs, uint32_t usecs)
436 {
437         struct timeval tv2 = *tv;
438         const unsigned int million = 1000000;
439         tv2.tv_sec += secs;
440         tv2.tv_usec += usecs;
441         tv2.tv_sec += tv2.tv_usec / million;
442         tv2.tv_usec = tv2.tv_usec % million;
443         return tv2;
444 }
445
446 /**
447   return the sum of two timeval structures
448 */
449 struct timeval timeval_sum(const struct timeval *tv1,
450                            const struct timeval *tv2)
451 {
452         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
453 }
454
455 /**
456   return a timeval secs/usecs into the future
457 */
458 struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
459 {
460         struct timeval tv = timeval_current();
461         return timeval_add(&tv, secs, usecs);
462 }
463
464 /**
465   compare two timeval structures. 
466   Return -1 if tv1 < tv2
467   Return 0 if tv1 == tv2
468   Return 1 if tv1 > tv2
469 */
470 int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
471 {
472         if (tv1->tv_sec  > tv2->tv_sec)  return 1;
473         if (tv1->tv_sec  < tv2->tv_sec)  return -1;
474         if (tv1->tv_usec > tv2->tv_usec) return 1;
475         if (tv1->tv_usec < tv2->tv_usec) return -1;
476         return 0;
477 }
478
479 /**
480   return True if a timer is in the past
481 */
482 bool timeval_expired(const struct timeval *tv)
483 {
484         struct timeval tv2 = timeval_current();
485         if (tv2.tv_sec > tv->tv_sec) return True;
486         if (tv2.tv_sec < tv->tv_sec) return False;
487         return (tv2.tv_usec >= tv->tv_usec);
488 }
489
490 /**
491   return the number of seconds elapsed between two times
492 */
493 double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
494 {
495         return (tv2->tv_sec - tv1->tv_sec) + 
496                (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
497 }
498
499 /**
500   return the number of seconds elapsed since a given time
501 */
502 double timeval_elapsed(const struct timeval *tv)
503 {
504         struct timeval tv2 = timeval_current();
505         return timeval_elapsed2(tv, &tv2);
506 }
507
508 /**
509   return the lesser of two timevals
510 */
511 struct timeval timeval_min(const struct timeval *tv1,
512                            const struct timeval *tv2)
513 {
514         if (tv1->tv_sec < tv2->tv_sec) return *tv1;
515         if (tv1->tv_sec > tv2->tv_sec) return *tv2;
516         if (tv1->tv_usec < tv2->tv_usec) return *tv1;
517         return *tv2;
518 }
519
520 /**
521   return the greater of two timevals
522 */
523 struct timeval timeval_max(const struct timeval *tv1,
524                            const struct timeval *tv2)
525 {
526         if (tv1->tv_sec > tv2->tv_sec) return *tv1;
527         if (tv1->tv_sec < tv2->tv_sec) return *tv2;
528         if (tv1->tv_usec > tv2->tv_usec) return *tv1;
529         return *tv2;
530 }
531
532 /**
533   return the difference between two timevals as a timeval
534   if tv1 comes after tv2, then return a zero timeval
535   (this is *tv2 - *tv1)
536 */
537 struct timeval timeval_until(const struct timeval *tv1,
538                              const struct timeval *tv2)
539 {
540         struct timeval t;
541         if (timeval_compare(tv1, tv2) >= 0) {
542                 return timeval_zero();
543         }
544         t.tv_sec = tv2->tv_sec - tv1->tv_sec;
545         if (tv1->tv_usec > tv2->tv_usec) {
546                 t.tv_sec--;
547                 t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
548         } else {
549                 t.tv_usec = tv2->tv_usec - tv1->tv_usec;
550         }
551         return t;
552 }
553
554
555 /**
556   convert a timeval to a NTTIME
557 */
558 NTTIME timeval_to_nttime(const struct timeval *tv)
559 {
560         return 10*(tv->tv_usec + 
561                   ((TIME_FIXUP_CONSTANT_INT + (uint64_t)tv->tv_sec) * 1000000));
562 }
563
564 /**************************************************************
565  Handle conversions between time_t and uint32, taking care to
566  preserve the "special" values.
567 **************************************************************/
568
569 uint32 convert_time_t_to_uint32(time_t t)
570 {
571 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
572         /* time_t is 64-bit. */
573         if (t == 0x8000000000000000LL) {
574                 return 0x80000000;
575         } else if (t == 0x7FFFFFFFFFFFFFFFLL) {
576                 return 0x7FFFFFFF;
577         }
578 #endif
579         return (uint32)t;
580 }
581
582 time_t convert_uint32_to_time_t(uint32 u)
583 {
584 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
585         /* time_t is 64-bit. */
586         if (u == 0x80000000) {
587                 return (time_t)0x8000000000000000LL;
588         } else if (u == 0x7FFFFFFF) {
589                 return (time_t)0x7FFFFFFFFFFFFFFFLL;
590         }
591 #endif
592         return (time_t)u;
593 }
594
595 /*******************************************************************
596  Yield the difference between *A and *B, in seconds, ignoring leap seconds.
597 ********************************************************************/
598
599 static int tm_diff(struct tm *a, struct tm *b)
600 {
601         int ay = a->tm_year + (1900 - 1);
602         int by = b->tm_year + (1900 - 1);
603         int intervening_leap_days =
604                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
605         int years = ay - by;
606         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
607         int hours = 24*days + (a->tm_hour - b->tm_hour);
608         int minutes = 60*hours + (a->tm_min - b->tm_min);
609         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
610
611         return seconds;
612 }
613
614 int extra_time_offset=0;
615
616 /*******************************************************************
617  Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
618 ********************************************************************/
619
620 int get_time_zone(time_t t)
621 {
622         struct tm *tm = gmtime(&t);
623         struct tm tm_utc;
624         if (!tm)
625                 return 0;
626         tm_utc = *tm;
627         tm = localtime(&t);
628         if (!tm)
629                 return 0;
630         return tm_diff(&tm_utc,tm)+60*extra_time_offset;
631 }
632
633 /****************************************************************************
634  Check if NTTIME is 0.
635 ****************************************************************************/
636
637 bool nt_time_is_zero(const NTTIME *nt)
638 {
639         return (*nt == 0);
640 }
641
642 /****************************************************************************
643  Convert ASN.1 GeneralizedTime string to unix-time.
644  Returns 0 on failure; Currently ignores timezone. 
645 ****************************************************************************/
646
647 time_t generalized_to_unix_time(const char *str)
648
649         struct tm tm;
650
651         ZERO_STRUCT(tm);
652
653         if (sscanf(str, "%4d%2d%2d%2d%2d%2d", 
654                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
655                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
656                 return 0;
657         }
658         tm.tm_year -= 1900;
659         tm.tm_mon -= 1;
660
661         return timegm(&tm);
662 }
663
664 /*******************************************************************
665  Accessor function for the server time zone offset.
666  set_server_zone_offset() must have been called first.
667 ******************************************************************/
668
669 static int server_zone_offset;
670
671 int get_server_zone_offset(void)
672 {
673         return server_zone_offset;
674 }
675
676 /*******************************************************************
677  Initialize the server time zone offset. Called when a client connects.
678 ******************************************************************/
679
680 int set_server_zone_offset(time_t t)
681 {
682         server_zone_offset = get_time_zone(t);
683         return server_zone_offset;
684 }
685
686 /****************************************************************************
687  Return the date and time as a string
688 ****************************************************************************/
689
690 char *current_timestring(TALLOC_CTX *ctx, bool hires)
691 {
692         fstring TimeBuf;
693         struct timeval tp;
694         time_t t;
695         struct tm *tm;
696
697         if (hires) {
698                 GetTimeOfDay(&tp);
699                 t = (time_t)tp.tv_sec;
700         } else {
701                 t = time(NULL);
702         }
703         tm = localtime(&t);
704         if (!tm) {
705                 if (hires) {
706                         slprintf(TimeBuf,
707                                  sizeof(TimeBuf)-1,
708                                  "%ld.%06ld seconds since the Epoch",
709                                  (long)tp.tv_sec, 
710                                  (long)tp.tv_usec);
711                 } else {
712                         slprintf(TimeBuf,
713                                  sizeof(TimeBuf)-1,
714                                  "%ld seconds since the Epoch",
715                                  (long)t);
716                 }
717         } else {
718 #ifdef HAVE_STRFTIME
719                 if (hires) {
720                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
721                         slprintf(TimeBuf+strlen(TimeBuf),
722                                  sizeof(TimeBuf)-1 - strlen(TimeBuf), 
723                                  ".%06ld", 
724                                  (long)tp.tv_usec);
725                 } else {
726                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
727                 }
728 #else
729                 if (hires) {
730                         const char *asct = asctime(tm);
731                         slprintf(TimeBuf, 
732                                  sizeof(TimeBuf)-1, 
733                                  "%s.%06ld", 
734                                  asct ? asct : "unknown", 
735                                  (long)tp.tv_usec);
736                 } else {
737                         const char *asct = asctime(tm);
738                         fstrcpy(TimeBuf, asct ? asct : "unknown");
739                 }
740 #endif
741         }
742         return talloc_strdup(ctx, TimeBuf);
743 }
744
745
746 /*******************************************************************
747  Put a dos date into a buffer (time/date format).
748  This takes GMT time and puts local time in the buffer.
749 ********************************************************************/
750
751 static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
752 {
753         uint32 x = make_dos_date(unixdate, zone_offset);
754         SIVAL(buf,offset,x);
755 }
756
757 /*******************************************************************
758  Put a dos date into a buffer (date/time format).
759  This takes GMT time and puts local time in the buffer.
760 ********************************************************************/
761
762 static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
763 {
764         uint32 x = make_dos_date(unixdate, zone_offset);
765         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
766         SIVAL(buf,offset,x);
767 }
768
769 /*******************************************************************
770  Put a dos 32 bit "unix like" date into a buffer. This routine takes
771  GMT and converts it to LOCAL time before putting it (most SMBs assume
772  localtime for this sort of date)
773 ********************************************************************/
774
775 static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
776 {
777         if (!null_mtime(unixdate)) {
778                 unixdate -= zone_offset;
779         }
780         SIVAL(buf,offset,unixdate);
781 }
782
783
784 /***************************************************************************
785  Server versions of the above functions.
786 ***************************************************************************/
787
788 void srv_put_dos_date(char *buf,int offset,time_t unixdate)
789 {
790         put_dos_date(buf, offset, unixdate, server_zone_offset);
791 }
792
793 void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
794 {
795         put_dos_date2(buf, offset, unixdate, server_zone_offset);
796 }
797
798 void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
799 {
800         put_dos_date3(buf, offset, unixdate, server_zone_offset);
801 }
802
803 /****************************************************************************
804  Take a Unix time and convert to an NTTIME structure and place in buffer 
805  pointed to by p.
806 ****************************************************************************/
807
808 void put_long_date_timespec(char *p, struct timespec ts)
809 {
810         NTTIME nt;
811         unix_timespec_to_nt_time(&nt, ts);
812         SIVAL(p, 0, nt & 0xFFFFFFFF);
813         SIVAL(p, 4, nt >> 32);
814 }
815
816 void put_long_date(char *p, time_t t)
817 {
818         struct timespec ts;
819         ts.tv_sec = t;
820         ts.tv_nsec = 0;
821         put_long_date_timespec(p, ts);
822 }
823
824 /****************************************************************************
825  Return the best approximation to a 'create time' under UNIX from a stat
826  structure.
827 ****************************************************************************/
828
829 static time_t calc_create_time(const SMB_STRUCT_STAT *st)
830 {
831         time_t ret, ret1;
832
833         ret = MIN(st->st_ctime, st->st_mtime);
834         ret1 = MIN(ret, st->st_atime);
835
836         if(ret1 != (time_t)0) {
837                 return ret1;
838         }
839
840         /*
841          * One of ctime, mtime or atime was zero (probably atime).
842          * Just return MIN(ctime, mtime).
843          */
844         return ret;
845 }
846
847 /****************************************************************************
848  Return the 'create time' from a stat struct if it exists (birthtime) or else
849  use the best approximation.
850 ****************************************************************************/
851
852 struct timespec get_create_timespec(const SMB_STRUCT_STAT *pst,bool fake_dirs)
853 {
854         struct timespec ret;
855
856         if(S_ISDIR(pst->st_mode) && fake_dirs) {
857                 ret.tv_sec = 315493200L;          /* 1/1/1980 */
858                 ret.tv_nsec = 0;
859                 return ret;
860         }
861
862 #if defined(HAVE_STAT_ST_BIRTHTIMESPEC)
863         ret = pst->st_birthtimespec;
864 #elif defined(HAVE_STAT_ST_BIRTHTIMENSEC)
865         ret.tv_sec = pst->st_birthtime;
866         ret.tv_nsec = pst->st_birthtimenspec;
867 #elif defined(HAVE_STAT_ST_BIRTHTIME)
868         ret.tv_sec = pst->st_birthtime;
869         ret.tv_nsec = 0;
870 #else
871         ret.tv_sec = calc_create_time(pst);
872         ret.tv_nsec = 0;
873 #endif
874
875         /* Deal with systems that don't initialize birthtime correctly.
876          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
877          */
878         if (null_timespec(ret)) {
879                 ret.tv_sec = calc_create_time(pst);
880                 ret.tv_nsec = 0;
881         }
882         return ret;
883 }
884
885 /****************************************************************************
886  Get/Set all the possible time fields from a stat struct as a timespec.
887 ****************************************************************************/
888
889 struct timespec get_atimespec(const SMB_STRUCT_STAT *pst)
890 {
891 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
892         struct timespec ret;
893
894         /* Old system - no ns timestamp. */
895         ret.tv_sec = pst->st_atime;
896         ret.tv_nsec = 0;
897         return ret;
898 #else
899 #if defined(HAVE_STAT_ST_ATIM)
900         return pst->st_atim;
901 #elif defined(HAVE_STAT_ST_ATIMENSEC)
902         struct timespec ret;
903         ret.tv_sec = pst->st_atime;
904         ret.tv_nsec = pst->st_atimensec;
905         return ret;
906 #else
907 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
908 #endif
909 #endif
910 }
911
912 void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
913 {
914 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
915         /* Old system - no ns timestamp. */
916         pst->st_atime = ts.tv_sec;
917 #else
918 #if defined(HAVE_STAT_ST_ATIM)
919         pst->st_atim = ts;
920 #elif defined(HAVE_STAT_ST_ATIMENSEC)
921         pst->st_atime = ts.tv_sec;
922         pst->st_atimensec = ts.tv_nsec
923 #else
924 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
925 #endif
926 #endif
927 }
928
929 struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst)
930 {
931 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
932         struct timespec ret;
933
934         /* Old system - no ns timestamp. */
935         ret.tv_sec = pst->st_mtime;
936         ret.tv_nsec = 0;
937         return ret;
938 #else
939 #if defined(HAVE_STAT_ST_MTIM)
940         return pst->st_mtim;
941 #elif defined(HAVE_STAT_ST_MTIMENSEC)
942         struct timespec ret;
943         ret.tv_sec = pst->st_mtime;
944         ret.tv_nsec = pst->st_mtimensec;
945         return ret;
946 #else
947 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
948 #endif
949 #endif
950 }
951
952 void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
953 {
954 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
955         /* Old system - no ns timestamp. */
956         pst->st_mtime = ts.tv_sec;
957 #else
958 #if defined(HAVE_STAT_ST_MTIM)
959         pst->st_mtim = ts;
960 #elif defined(HAVE_STAT_ST_MTIMENSEC)
961         pst->st_mtime = ts.tv_sec;
962         pst->st_mtimensec = ts.tv_nsec
963 #else
964 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
965 #endif
966 #endif
967 }
968
969 struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst)
970 {
971 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
972         struct timespec ret;
973
974         /* Old system - no ns timestamp. */
975         ret.tv_sec = pst->st_ctime;
976         ret.tv_nsec = 0;
977         return ret;
978 #else
979 #if defined(HAVE_STAT_ST_CTIM)
980         return pst->st_ctim;
981 #elif defined(HAVE_STAT_ST_CTIMENSEC)
982         struct timespec ret;
983         ret.tv_sec = pst->st_ctime;
984         ret.tv_nsec = pst->st_ctimensec;
985         return ret;
986 #else
987 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
988 #endif
989 #endif
990 }
991
992 void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
993 {
994 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
995         /* Old system - no ns timestamp. */
996         pst->st_ctime = ts.tv_sec;
997 #else
998 #if defined(HAVE_STAT_ST_CTIM)
999         pst->st_ctim = ts;
1000 #elif defined(HAVE_STAT_ST_CTIMENSEC)
1001         pst->st_ctime = ts.tv_sec;
1002         pst->st_ctimensec = ts.tv_nsec
1003 #else
1004 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
1005 #endif
1006 #endif
1007 }
1008
1009 void dos_filetime_timespec(struct timespec *tsp)
1010 {
1011         tsp->tv_sec &= ~1;
1012         tsp->tv_nsec = 0;
1013 }
1014
1015 /*******************************************************************
1016  Create a unix date (int GMT) from a dos date (which is actually in
1017  localtime).
1018 ********************************************************************/
1019
1020 static time_t make_unix_date(const void *date_ptr, int zone_offset)
1021 {
1022         uint32 dos_date=0;
1023         struct tm t;
1024         time_t ret;
1025
1026         dos_date = IVAL(date_ptr,0);
1027
1028         if (dos_date == 0) {
1029                 return 0;
1030         }
1031   
1032         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
1033                         &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
1034         t.tm_isdst = -1;
1035   
1036         ret = timegm(&t);
1037
1038         ret += zone_offset;
1039
1040         return(ret);
1041 }
1042
1043 /*******************************************************************
1044  Like make_unix_date() but the words are reversed.
1045 ********************************************************************/
1046
1047 static time_t make_unix_date2(const void *date_ptr, int zone_offset)
1048 {
1049         uint32 x,x2;
1050
1051         x = IVAL(date_ptr,0);
1052         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
1053         SIVAL(&x,0,x2);
1054
1055         return(make_unix_date((const void *)&x, zone_offset));
1056 }
1057
1058 /*******************************************************************
1059  Create a unix GMT date from a dos date in 32 bit "unix like" format
1060  these generally arrive as localtimes, with corresponding DST.
1061 ******************************************************************/
1062
1063 static time_t make_unix_date3(const void *date_ptr, int zone_offset)
1064 {
1065         time_t t = (time_t)IVAL(date_ptr,0);
1066         if (!null_mtime(t)) {
1067                 t += zone_offset;
1068         }
1069         return(t);
1070 }
1071
1072 time_t srv_make_unix_date(const void *date_ptr)
1073 {
1074         return make_unix_date(date_ptr, server_zone_offset);
1075 }
1076
1077 time_t srv_make_unix_date2(const void *date_ptr)
1078 {
1079         return make_unix_date2(date_ptr, server_zone_offset);
1080 }
1081
1082 time_t srv_make_unix_date3(const void *date_ptr)
1083 {
1084         return make_unix_date3(date_ptr, server_zone_offset);
1085 }
1086
1087 time_t convert_timespec_to_time_t(struct timespec ts)
1088 {
1089         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
1090            increment if it's greater than 500 millionth of a second. */
1091         if (ts.tv_nsec > 500000000) {
1092                 return ts.tv_sec + 1;
1093         }
1094         return ts.tv_sec;
1095 }
1096
1097 struct timespec convert_time_t_to_timespec(time_t t)
1098 {
1099         struct timespec ts;
1100         ts.tv_sec = t;
1101         ts.tv_nsec = 0;
1102         return ts;
1103 }
1104
1105 /****************************************************************************
1106  Convert a normalized timeval to a timespec.
1107 ****************************************************************************/
1108
1109 struct timespec convert_timeval_to_timespec(const struct timeval tv)
1110 {
1111         struct timespec ts;
1112         ts.tv_sec = tv.tv_sec;
1113         ts.tv_nsec = tv.tv_usec * 1000;
1114         return ts;
1115 }
1116
1117 /****************************************************************************
1118  Convert a normalized timespec to a timeval.
1119 ****************************************************************************/
1120
1121 struct timeval convert_timespec_to_timeval(const struct timespec ts)
1122 {
1123         struct timeval tv;
1124         tv.tv_sec = ts.tv_sec;
1125         tv.tv_usec = ts.tv_nsec / 1000;
1126         return tv;
1127 }
1128
1129 /****************************************************************************
1130  Return a timespec for the current time
1131 ****************************************************************************/
1132
1133 struct timespec timespec_current(void)
1134 {
1135         struct timeval tv;
1136         struct timespec ts;
1137         GetTimeOfDay(&tv);
1138         ts.tv_sec = tv.tv_sec;
1139         ts.tv_nsec = tv.tv_usec * 1000;
1140         return ts;
1141 }
1142
1143 /****************************************************************************
1144  Return the lesser of two timespecs.
1145 ****************************************************************************/
1146
1147 struct timespec timespec_min(const struct timespec *ts1,
1148                            const struct timespec *ts2)
1149 {
1150         if (ts1->tv_sec < ts2->tv_sec) return *ts1;
1151         if (ts1->tv_sec > ts2->tv_sec) return *ts2;
1152         if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
1153         return *ts2;
1154 }
1155
1156 /****************************************************************************
1157   compare two timespec structures. 
1158   Return -1 if ts1 < ts2
1159   Return 0 if ts1 == ts2
1160   Return 1 if ts1 > ts2
1161 ****************************************************************************/
1162
1163 int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
1164 {
1165         if (ts1->tv_sec  > ts2->tv_sec)  return 1;
1166         if (ts1->tv_sec  < ts2->tv_sec)  return -1;
1167         if (ts1->tv_nsec > ts2->tv_nsec) return 1;
1168         if (ts1->tv_nsec < ts2->tv_nsec) return -1;
1169         return 0;
1170 }
1171
1172 /****************************************************************************
1173  Interprets an nt time into a unix struct timespec.
1174  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
1175  will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
1176 ****************************************************************************/
1177
1178 struct timespec interpret_long_date(const char *p)
1179 {
1180         NTTIME nt;
1181         nt = IVAL(p,0) + ((uint64_t)IVAL(p,4) << 32);
1182         if (nt == (uint64_t)-1) {
1183                 struct timespec ret;
1184                 ret.tv_sec = (time_t)-1;
1185                 ret.tv_nsec = 0;
1186                 return ret;
1187         }
1188         return nt_time_to_unix_timespec(&nt);
1189 }
1190
1191 /***************************************************************************
1192  Client versions of the above functions.
1193 ***************************************************************************/
1194
1195 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
1196 {
1197         put_dos_date(buf, offset, unixdate, cli->serverzone);
1198 }
1199
1200 void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
1201 {
1202         put_dos_date2(buf, offset, unixdate, cli->serverzone);
1203 }
1204
1205 void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
1206 {
1207         put_dos_date3(buf, offset, unixdate, cli->serverzone);
1208 }
1209
1210 time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr)
1211 {
1212         return make_unix_date(date_ptr, cli->serverzone);
1213 }
1214
1215 time_t cli_make_unix_date2(struct cli_state *cli, const void *date_ptr)
1216 {
1217         return make_unix_date2(date_ptr, cli->serverzone);
1218 }
1219
1220 time_t cli_make_unix_date3(struct cli_state *cli, const void *date_ptr)
1221 {
1222         return make_unix_date3(date_ptr, cli->serverzone);
1223 }
1224
1225 /* Large integer version. */
1226 struct timespec nt_time_to_unix_timespec(NTTIME *nt)
1227 {
1228         int64 d;
1229         struct timespec ret;
1230
1231         if (*nt == 0 || *nt == (int64)-1) {
1232                 ret.tv_sec = 0;
1233                 ret.tv_nsec = 0;
1234                 return ret;
1235         }
1236
1237         d = (int64)*nt;
1238         /* d is now in 100ns units, since jan 1st 1601".
1239            Save off the ns fraction. */
1240
1241         /*
1242          * Take the last seven decimal digits and multiply by 100.
1243          * to convert from 100ns units to 1ns units.
1244          */
1245         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
1246
1247         /* Convert to seconds */
1248         d /= 1000*1000*10;
1249
1250         /* Now adjust by 369 years to make the secs since 1970 */
1251         d -= TIME_FIXUP_CONSTANT_INT;
1252
1253         if (d <= (int64)TIME_T_MIN) {
1254                 ret.tv_sec = TIME_T_MIN;
1255                 ret.tv_nsec = 0;
1256                 return ret;
1257         }
1258
1259         if (d >= (int64)TIME_T_MAX) {
1260                 ret.tv_sec = TIME_T_MAX;
1261                 ret.tv_nsec = 0;
1262                 return ret;
1263         }
1264
1265         ret.tv_sec = (time_t)d;
1266         return ret;
1267 }
1268 /****************************************************************************
1269  Check if two NTTIMEs are the same.
1270 ****************************************************************************/
1271
1272 bool nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
1273 {
1274         return (*nt1 == *nt2);
1275 }
1276
1277 /*******************************************************************
1278  Re-read the smb serverzone value.
1279 ******************************************************************/
1280
1281 static struct timeval start_time_hires;
1282
1283 void TimeInit(void)
1284 {
1285         set_server_zone_offset(time(NULL));
1286
1287         DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
1288
1289         /* Save the start time of this process. */
1290         if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
1291                 GetTimeOfDay(&start_time_hires);
1292         }
1293 }
1294
1295 /**********************************************************************
1296  Return a timeval struct of the uptime of this process. As TimeInit is
1297  done before a daemon fork then this is the start time from the parent
1298  daemon start. JRA.
1299 ***********************************************************************/
1300
1301 void get_process_uptime(struct timeval *ret_time)
1302 {
1303         struct timeval time_now_hires;
1304
1305         GetTimeOfDay(&time_now_hires);
1306         ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
1307         if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
1308                 ret_time->tv_sec -= 1;
1309                 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
1310         } else {
1311                 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
1312         }
1313 }
1314
1315 /****************************************************************************
1316  Convert a NTTIME structure to a time_t.
1317  It's originally in "100ns units".
1318
1319  This is an absolute version of the one above.
1320  By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
1321  if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
1322 ****************************************************************************/
1323
1324 time_t nt_time_to_unix_abs(const NTTIME *nt)
1325 {
1326         uint64 d;
1327
1328         if (*nt == 0) {
1329                 return (time_t)0;
1330         }
1331
1332         if (*nt == (uint64)-1) {
1333                 return (time_t)-1;
1334         }
1335
1336         if (*nt == NTTIME_INFINITY) {
1337                 return (time_t)-1;
1338         }
1339
1340         /* reverse the time */
1341         /* it's a negative value, turn it to positive */
1342         d=~*nt;
1343
1344         d += 1000*1000*10/2;
1345         d /= 1000*1000*10;
1346
1347         if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
1348                 return (time_t)0;
1349         }
1350
1351         return (time_t)d;
1352 }
1353
1354 time_t uint64s_nt_time_to_unix_abs(const uint64_t *src)
1355 {
1356         NTTIME nttime;
1357         nttime = *src;
1358         return nt_time_to_unix_abs(&nttime);
1359 }
1360
1361 /****************************************************************************
1362  Put a 8 byte filetime from a struct timespec. Uses GMT.
1363 ****************************************************************************/
1364
1365 void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
1366 {
1367         uint64 d;
1368
1369         if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
1370                 *nt = 0;
1371                 return;
1372         }
1373         if (ts.tv_sec == TIME_T_MAX) {
1374                 *nt = 0x7fffffffffffffffLL;
1375                 return;
1376         }               
1377         if (ts.tv_sec == (time_t)-1) {
1378                 *nt = (uint64)-1;
1379                 return;
1380         }               
1381
1382         d = ts.tv_sec;
1383         d += TIME_FIXUP_CONSTANT_INT;
1384         d *= 1000*1000*10;
1385         /* d is now in 100ns units. */
1386         d += (ts.tv_nsec / 100);
1387
1388         *nt = d;
1389 }
1390
1391 /****************************************************************************
1392  Convert a time_t to a NTTIME structure
1393
1394  This is an absolute version of the one above.
1395  By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
1396  If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM
1397 ****************************************************************************/
1398
1399 void unix_to_nt_time_abs(NTTIME *nt, time_t t)
1400 {
1401         double d;
1402
1403         if (t==0) {
1404                 *nt = 0;
1405                 return;
1406         }
1407
1408         if (t == TIME_T_MAX) {
1409                 *nt = 0x7fffffffffffffffLL;
1410                 return;
1411         }
1412                 
1413         if (t == (time_t)-1) {
1414                 /* that's what NT uses for infinite */
1415                 *nt = NTTIME_INFINITY;
1416                 return;
1417         }               
1418
1419         d = (double)(t);
1420         d *= 1.0e7;
1421
1422         *nt = (NTTIME)d;
1423
1424         /* convert to a negative value */
1425         *nt=~*nt;
1426 }
1427
1428
1429 /****************************************************************************
1430  Check if it's a null mtime.
1431 ****************************************************************************/
1432
1433 bool null_mtime(time_t mtime)
1434 {
1435         if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
1436                 return(True);
1437         return(False);
1438 }
1439
1440 /****************************************************************************
1441  Utility function that always returns a const string even if localtime
1442  and asctime fail.
1443 ****************************************************************************/
1444
1445 const char *time_to_asc(const time_t t)
1446 {
1447         const char *asct;
1448         struct tm *lt = localtime(&t);
1449
1450         if (!lt) {
1451                 return "unknown time";
1452         }
1453
1454         asct = asctime(lt);
1455         if (!asct) {
1456                 return "unknown time";
1457         }
1458         return asct;
1459 }
1460
1461 const char *display_time(NTTIME nttime)
1462 {
1463         float high;
1464         float low;
1465         int sec;
1466         int days, hours, mins, secs;
1467
1468         if (nttime==0)
1469                 return "Now";
1470
1471         if (nttime==NTTIME_INFINITY)
1472                 return "Never";
1473
1474         high = 65536;   
1475         high = high/10000;
1476         high = high*65536;
1477         high = high/1000;
1478         high = high * (~(nttime >> 32));
1479
1480         low = ~(nttime & 0xFFFFFFFF);
1481         low = low/(1000*1000*10);
1482
1483         sec=(int)(high+low);
1484
1485         days=sec/(60*60*24);
1486         hours=(sec - (days*60*60*24)) / (60*60);
1487         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
1488         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
1489
1490         return talloc_asprintf(talloc_tos(), "%u days, %u hours, %u minutes, "
1491                                "%u seconds", days, hours, mins, secs);
1492 }
1493
1494 bool nt_time_is_set(const NTTIME *nt)
1495 {
1496         if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
1497                 return False;
1498         }
1499
1500         if (*nt == NTTIME_INFINITY) {
1501                 return False;
1502         }
1503
1504         return True;
1505 }