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