r13350: Implement rpccli_samr_set_domain_info. Weird that it was not around :-)
[ira/wip.git] / source3 / lib / time.c
1 /* 
2    Unix SMB/CIFS implementation.
3    time handling functions
4    Copyright (C) Andrew Tridgell                1992-1998
5    Copyright (C) Stefan (metze) Metzmacher      2002   
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 /*
24   This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com>
25   in May 1996 
26   */
27
28 int extra_time_offset = 0;
29
30 #ifndef CHAR_BIT
31 #define CHAR_BIT 8
32 #endif
33
34 #ifndef TIME_T_MIN
35 #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
36                     : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
37 #endif
38 #ifndef TIME_T_MAX
39 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
40 #endif
41
42 void get_nttime_max(NTTIME *t)
43 {
44         /* FIXME: This is incorrect */
45         unix_to_nt_time(t, get_time_t_max());
46 }
47
48 /*******************************************************************
49  External access to time_t_min and time_t_max.
50 ********************************************************************/
51
52 time_t get_time_t_max(void)
53 {
54         return TIME_T_MAX;
55 }
56
57 /*******************************************************************
58  A gettimeofday wrapper.
59 ********************************************************************/
60
61 void GetTimeOfDay(struct timeval *tval)
62 {
63 #ifdef HAVE_GETTIMEOFDAY_TZ
64         gettimeofday(tval,NULL);
65 #else
66         gettimeofday(tval);
67 #endif
68 }
69
70 #define TM_YEAR_BASE 1900
71
72 /*******************************************************************
73  Yield the difference between *A and *B, in seconds, ignoring leap seconds.
74 ********************************************************************/
75
76 static int tm_diff(struct tm *a, struct tm *b)
77 {
78         int ay = a->tm_year + (TM_YEAR_BASE - 1);
79         int by = b->tm_year + (TM_YEAR_BASE - 1);
80         int intervening_leap_days = (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
81         int years = ay - by;
82         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
83         int hours = 24*days + (a->tm_hour - b->tm_hour);
84         int minutes = 60*hours + (a->tm_min - b->tm_min);
85         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
86
87         return seconds;
88 }
89
90 /*******************************************************************
91  Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
92 ******************************************************************/
93
94 int get_time_zone(time_t t)
95 {
96         struct tm *tm = gmtime(&t);
97         struct tm tm_utc;
98
99         if (!tm) {
100                 return 0;
101         }
102         tm_utc = *tm;
103         tm = localtime(&t);
104         if (!tm) {
105                 return 0;
106         }
107         return tm_diff(&tm_utc,tm) + 60*extra_time_offset;
108 }
109
110 /*******************************************************************
111  Accessor function for the server time zone offset.
112  set_server_zone_offset() must have been called first.
113 ******************************************************************/
114
115 static int server_zone_offset;
116
117 int get_server_zone_offset(void)
118 {
119         return server_zone_offset;
120 }
121
122 /*******************************************************************
123  Initialize the server time zone offset. Called when a client connects.
124 ******************************************************************/
125
126 int set_server_zone_offset(time_t t)
127 {
128         server_zone_offset = get_time_zone(t);
129         return server_zone_offset;
130 }
131
132 /*******************************************************************
133  Re-read the smb serverzone value.
134 ******************************************************************/
135
136 static struct timeval start_time_hires;
137
138 void TimeInit(void)
139 {
140         set_server_zone_offset(time(NULL));
141
142         DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
143
144         /* Save the start time of this process. */
145         if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
146                 GetTimeOfDay(&start_time_hires);
147         }
148 }
149
150 /**********************************************************************
151  Return a timeval struct of the uptime of this process. As TimeInit is
152  done before a daemon fork then this is the start time from the parent
153  daemon start. JRA.
154 ***********************************************************************/
155
156 void get_process_uptime(struct timeval *ret_time)
157 {
158         struct timeval time_now_hires;
159
160         GetTimeOfDay(&time_now_hires);
161         ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
162         ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
163         if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
164                 ret_time->tv_sec -= 1;
165                 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
166         } else {
167                 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
168         }
169 }
170
171 #if 0
172 /****************************************************************************
173  Return the UTC offset in seconds west of UTC, adjusted for extra time offset.
174 **************************************************************************/
175
176 int TimeDiff(time_t t)
177 {
178         return get_time_zone(t);
179 }
180 #endif
181
182 #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
183
184 /****************************************************************************
185  Interpret an 8 byte "filetime" structure to a time_t
186  It's originally in "100ns units since jan 1st 1601"
187
188  An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0.
189
190  Returns GMT.
191 ****************************************************************************/
192
193 time_t nt_time_to_unix(NTTIME *nt)
194 {
195         double d;
196         time_t ret;
197         /* The next two lines are a fix needed for the 
198                 broken SCO compiler. JRA. */
199         time_t l_time_min = TIME_T_MIN;
200         time_t l_time_max = TIME_T_MAX;
201
202         if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
203                 return(0);
204         }
205
206         d = ((double)nt->high)*4.0*(double)(1<<30);
207         d += (nt->low&0xFFF00000);
208         d *= 1.0e-7;
209  
210         /* now adjust by 369 years to make the secs since 1970 */
211         d -= TIME_FIXUP_CONSTANT;
212
213         if (d <= l_time_min) {
214                 return (l_time_min);
215         }
216
217         if (d >= l_time_max) {
218                 return (l_time_max);
219         }
220
221         ret = (time_t)(d+0.5);
222         return(ret);
223 }
224
225 /****************************************************************************
226  Convert a NTTIME structure to a time_t.
227  It's originally in "100ns units".
228
229  This is an absolute version of the one above.
230  By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
231  if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
232 ****************************************************************************/
233
234 time_t nt_time_to_unix_abs(const NTTIME *nt)
235 {
236         double d;
237         time_t ret;
238         /* The next two lines are a fix needed for the 
239            broken SCO compiler. JRA. */
240         time_t l_time_min = TIME_T_MIN;
241         time_t l_time_max = TIME_T_MAX;
242         NTTIME neg_nt;
243
244         if (nt->high == 0) {
245                 return(0);
246         }
247
248         if (nt->high==0x80000000 && nt->low==0) {
249                 return (time_t)-1;
250         }
251
252         /* reverse the time */
253         /* it's a negative value, turn it to positive */
254         neg_nt.high=~nt->high;
255         neg_nt.low=~nt->low;
256
257         d = ((double)neg_nt.high)*4.0*(double)(1<<30);
258         d += (neg_nt.low&0xFFF00000);
259         d *= 1.0e-7;
260   
261         if (!(l_time_min <= d && d <= l_time_max)) {
262                 return(0);
263         }
264
265         ret = (time_t)(d+0.5);
266
267         return(ret);
268 }
269
270 /****************************************************************************
271  Interprets an nt time into a unix time_t.
272  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
273  will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
274 ****************************************************************************/
275
276 time_t interpret_long_date(char *p)
277 {
278         NTTIME nt;
279         nt.low = IVAL(p,0);
280         nt.high = IVAL(p,4);
281         if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) {
282                 return (time_t)-1;
283         }
284         return nt_time_to_unix(&nt);
285 }
286
287 /****************************************************************************
288  Put a 8 byte filetime from a time_t. Uses GMT.
289 ****************************************************************************/
290
291 void unix_to_nt_time(NTTIME *nt, time_t t)
292 {
293         double d;
294
295         if (t==0) {
296                 nt->low = 0;
297                 nt->high = 0;
298                 return;
299         }
300         if (t == TIME_T_MAX) {
301                 nt->low = 0xffffffff;
302                 nt->high = 0x7fffffff;
303                 return;
304         }               
305         if (t == (time_t)-1) {
306                 nt->low = 0xffffffff;
307                 nt->high = 0xffffffff;
308                 return;
309         }               
310
311         d = (double)(t);
312         d += TIME_FIXUP_CONSTANT;
313         d *= 1.0e7;
314
315         nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
316         nt->low  = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
317 }
318
319 /****************************************************************************
320  Convert a time_t to a NTTIME structure
321
322  This is an absolute version of the one above.
323  By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
324  If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM
325 ****************************************************************************/
326
327 void unix_to_nt_time_abs(NTTIME *nt, time_t t)
328 {
329         double d;
330
331         if (t==0) {
332                 nt->low = 0;
333                 nt->high = 0;
334                 return;
335         }
336
337         if (t == TIME_T_MAX) {
338                 nt->low = 0xffffffff;
339                 nt->high = 0x7fffffff;
340                 return;
341         }
342                 
343         if (t == (time_t)-1) {
344                 /* that's what NT uses for infinite */
345                 nt->low = 0x0;
346                 nt->high = 0x80000000;
347                 return;
348         }               
349
350         d = (double)(t);
351         d *= 1.0e7;
352
353         nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
354         nt->low  = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
355
356         /* convert to a negative value */
357         nt->high=~nt->high;
358         nt->low=~nt->low;
359 }
360
361 /****************************************************************************
362  Take a Unix time and convert to an NTTIME structure and place in buffer 
363  pointed to by p.
364 ****************************************************************************/
365
366 void put_long_date(char *p, time_t t)
367 {
368         NTTIME nt;
369         unix_to_nt_time(&nt, t);
370         SIVAL(p, 0, nt.low);
371         SIVAL(p, 4, nt.high);
372 }
373
374 /****************************************************************************
375  Check if it's a null mtime.
376 ****************************************************************************/
377
378 BOOL null_mtime(time_t mtime)
379 {
380         if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
381                 return(True);
382         return(False);
383 }
384
385 /*******************************************************************
386  Create a 16 bit dos packed date.
387 ********************************************************************/
388
389 static uint16 make_dos_date1(struct tm *t)
390 {
391         uint16 ret=0;
392         ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
393         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
394         return(ret);
395 }
396
397 /*******************************************************************
398  Create a 16 bit dos packed time.
399 ********************************************************************/
400
401 static uint16 make_dos_time1(struct tm *t)
402 {
403         uint16 ret=0;
404         ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
405         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
406         return(ret);
407 }
408
409 /*******************************************************************
410  Create a 32 bit dos packed date/time from some parameters.
411  This takes a GMT time and returns a packed localtime structure.
412 ********************************************************************/
413
414 static uint32 make_dos_date(time_t unixdate, int zone_offset)
415 {
416         struct tm *t;
417         uint32 ret=0;
418
419         if (unixdate == 0) {
420                 return 0;
421         }
422
423         unixdate -= zone_offset;
424         t = gmtime(&unixdate);
425         if (!t) {
426                 return 0xFFFFFFFF;
427         }
428
429         ret = make_dos_date1(t);
430         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
431
432         return(ret);
433 }
434
435 /*******************************************************************
436  Put a dos date into a buffer (time/date format).
437  This takes GMT time and puts local time in the buffer.
438 ********************************************************************/
439
440 static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
441 {
442         uint32 x = make_dos_date(unixdate, zone_offset);
443         SIVAL(buf,offset,x);
444 }
445
446 /*******************************************************************
447  Put a dos date into a buffer (date/time format).
448  This takes GMT time and puts local time in the buffer.
449 ********************************************************************/
450
451 static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
452 {
453         uint32 x = make_dos_date(unixdate, zone_offset);
454         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
455         SIVAL(buf,offset,x);
456 }
457
458 /*******************************************************************
459  Put a dos 32 bit "unix like" date into a buffer. This routine takes
460  GMT and converts it to LOCAL time before putting it (most SMBs assume
461  localtime for this sort of date)
462 ********************************************************************/
463
464 static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
465 {
466         if (!null_mtime(unixdate)) {
467                 unixdate -= zone_offset;
468         }
469         SIVAL(buf,offset,unixdate);
470 }
471
472 /*******************************************************************
473  Interpret a 32 bit dos packed date/time to some parameters.
474 ********************************************************************/
475
476 static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
477 {
478         uint32 p0,p1,p2,p3;
479
480         p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
481         p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
482
483         *second = 2*(p0 & 0x1F);
484         *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
485         *hour = (p1>>3)&0xFF;
486         *day = (p2&0x1F);
487         *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
488         *year = ((p3>>1)&0xFF) + 80;
489 }
490
491 /*******************************************************************
492  Create a unix date (int GMT) from a dos date (which is actually in
493  localtime).
494 ********************************************************************/
495
496 static time_t make_unix_date(void *date_ptr, int zone_offset)
497 {
498         uint32 dos_date=0;
499         struct tm t;
500         time_t ret;
501
502         dos_date = IVAL(date_ptr,0);
503
504         if (dos_date == 0) {
505                 return 0;
506         }
507   
508         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
509                         &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
510         t.tm_isdst = -1;
511   
512         ret = timegm(&t);
513
514         ret += zone_offset;
515
516         return(ret);
517 }
518
519 /*******************************************************************
520  Like make_unix_date() but the words are reversed.
521 ********************************************************************/
522
523 static time_t make_unix_date2(void *date_ptr, int zone_offset)
524 {
525         uint32 x,x2;
526
527         x = IVAL(date_ptr,0);
528         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
529         SIVAL(&x,0,x2);
530
531         return(make_unix_date((void *)&x, zone_offset));
532 }
533
534 /*******************************************************************
535  Create a unix GMT date from a dos date in 32 bit "unix like" format
536  these generally arrive as localtimes, with corresponding DST.
537 ******************************************************************/
538
539 static time_t make_unix_date3(void *date_ptr, int zone_offset)
540 {
541         time_t t = (time_t)IVAL(date_ptr,0);
542         if (!null_mtime(t)) {
543                 t += zone_offset;
544         }
545         return(t);
546 }
547
548 /***************************************************************************
549  Server versions of the above functions.
550 ***************************************************************************/
551
552 void srv_put_dos_date(char *buf,int offset,time_t unixdate)
553 {
554         put_dos_date(buf, offset, unixdate, server_zone_offset);
555 }
556
557 void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
558 {
559         put_dos_date2(buf, offset, unixdate, server_zone_offset);
560 }
561
562 void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
563 {
564         put_dos_date3(buf, offset, unixdate, server_zone_offset);
565 }
566
567 time_t srv_make_unix_date(void *date_ptr)
568 {
569         return make_unix_date(date_ptr, server_zone_offset);
570 }
571
572 time_t srv_make_unix_date2(void *date_ptr)
573 {
574         return make_unix_date2(date_ptr, server_zone_offset);
575 }
576
577 time_t srv_make_unix_date3(void *date_ptr)
578 {
579         return make_unix_date3(date_ptr, server_zone_offset);
580 }
581
582 /***************************************************************************
583  Client versions of the above functions.
584 ***************************************************************************/
585
586 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
587 {
588         put_dos_date(buf, offset, unixdate, cli->serverzone);
589 }
590
591 void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
592 {
593         put_dos_date2(buf, offset, unixdate, cli->serverzone);
594 }
595
596 void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
597 {
598         put_dos_date3(buf, offset, unixdate, cli->serverzone);
599 }
600
601 time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr)
602 {
603         return make_unix_date(date_ptr, cli->serverzone);
604 }
605
606 time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr)
607 {
608         return make_unix_date2(date_ptr, cli->serverzone);
609 }
610
611 time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr)
612 {
613         return make_unix_date3(date_ptr, cli->serverzone);
614 }
615
616 /***************************************************************************
617  Return a HTTP/1.0 time string.
618 ***************************************************************************/
619
620 char *http_timestring(time_t t)
621 {
622         static fstring buf;
623         struct tm *tm = localtime(&t);
624
625         if (!tm)
626                 slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
627         else
628 #ifndef HAVE_STRFTIME
629                 fstrcpy(buf, asctime(tm));
630         if(buf[strlen(buf)-1] == '\n')
631                 buf[strlen(buf)-1] = 0;
632 #else /* !HAVE_STRFTIME */
633                 strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
634 #endif /* !HAVE_STRFTIME */
635         return buf;
636 }
637
638 /****************************************************************************
639  Return the date and time as a string
640 ****************************************************************************/
641
642 char *timestring(BOOL hires)
643 {
644         static fstring TimeBuf;
645         struct timeval tp;
646         time_t t;
647         struct tm *tm;
648
649         if (hires) {
650                 GetTimeOfDay(&tp);
651                 t = (time_t)tp.tv_sec;
652         } else {
653                 t = time(NULL);
654         }
655         tm = localtime(&t);
656         if (!tm) {
657                 if (hires) {
658                         slprintf(TimeBuf,
659                                  sizeof(TimeBuf)-1,
660                                  "%ld.%06ld seconds since the Epoch",
661                                  (long)tp.tv_sec, 
662                                  (long)tp.tv_usec);
663                 } else {
664                         slprintf(TimeBuf,
665                                  sizeof(TimeBuf)-1,
666                                  "%ld seconds since the Epoch",
667                                  (long)t);
668                 }
669         } else {
670 #ifdef HAVE_STRFTIME
671                 if (hires) {
672                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
673                         slprintf(TimeBuf+strlen(TimeBuf),
674                                  sizeof(TimeBuf)-1 - strlen(TimeBuf), 
675                                  ".%06ld", 
676                                  (long)tp.tv_usec);
677                 } else {
678                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
679                 }
680 #else
681                 if (hires) {
682                         slprintf(TimeBuf, 
683                                  sizeof(TimeBuf)-1, 
684                                  "%s.%06ld", 
685                                  asctime(tm), 
686                                  (long)tp.tv_usec);
687                 } else {
688                         fstrcpy(TimeBuf, asctime(tm));
689                 }
690 #endif
691         }
692         return(TimeBuf);
693 }
694
695 /****************************************************************************
696  Return the best approximation to a 'create time' under UNIX from a stat
697  structure.
698 ****************************************************************************/
699
700 time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
701 {
702         time_t ret, ret1;
703
704         if(S_ISDIR(st->st_mode) && fake_dirs) {
705                 return (time_t)315493200L;          /* 1/1/1980 */
706         }
707     
708         ret = MIN(st->st_ctime, st->st_mtime);
709         ret1 = MIN(ret, st->st_atime);
710
711         if(ret1 != (time_t)0) {
712                 return ret1;
713         }
714
715         /*
716          * One of ctime, mtime or atime was zero (probably atime).
717          * Just return MIN(ctime, mtime).
718          */
719         return ret;
720 }
721
722 /****************************************************************************
723  Initialise an NTTIME to -1, which means "unknown" or "don't expire".
724 ****************************************************************************/
725
726 void init_nt_time(NTTIME *nt)
727 {
728         nt->high = 0x7FFFFFFF;
729         nt->low = 0xFFFFFFFF;
730 }
731
732 BOOL nt_time_is_set(const NTTIME *nt)
733 {
734         if ((nt->high == 0x7FFFFFFF) && (nt->low == 0xFFFFFFFF)) {
735                 return False;
736         }
737
738         if ((nt->high == 0x80000000) && (nt->low == 0)) {
739                 return False;
740         }
741
742         return True;
743 }
744
745 /****************************************************************************
746  Check if NTTIME is 0.
747 ****************************************************************************/
748
749 BOOL nt_time_is_zero(const NTTIME *nt)
750 {
751         if(nt->high==0) {
752                 return True;
753         }
754         return False;
755 }
756
757 /****************************************************************************
758  Check if two NTTIMEs are the same.
759 ****************************************************************************/
760
761 BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
762 {
763         return (nt1->high == nt2->high && nt1->low == nt2->low);
764 }
765
766 /****************************************************************************
767  Return a timeval difference in usec.
768 ****************************************************************************/
769
770 SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *smallt)
771 {
772         SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec;
773         return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec);
774 }
775
776 /****************************************************************************
777  Return a timeval struct with the given elements.
778 ****************************************************************************/
779
780 struct timeval timeval_set(uint32_t secs, uint32_t usecs)
781 {
782         struct timeval tv;
783         tv.tv_sec = secs;
784         tv.tv_usec = usecs;
785         return tv;
786 }
787
788 /****************************************************************************
789  Return a zero timeval.
790 ****************************************************************************/
791
792 struct timeval timeval_zero(void)
793 {
794         return timeval_set(0,0);
795 }
796
797 /****************************************************************************
798  Return True if a timeval is zero.
799 ****************************************************************************/
800
801 BOOL timeval_is_zero(const struct timeval *tv)
802 {
803         return tv->tv_sec == 0 && tv->tv_usec == 0;
804 }
805
806 /****************************************************************************
807  Return a timeval for the current time.
808 ****************************************************************************/
809
810 struct timeval timeval_current(void)
811 {
812         struct timeval tv;
813         GetTimeOfDay(&tv);
814         return tv;
815 }
816
817 /****************************************************************************
818  Return a timeval ofs microseconds after tv.
819 ****************************************************************************/
820
821 struct timeval timeval_add(const struct timeval *tv,
822                            uint32_t secs, uint32_t usecs)
823 {
824         struct timeval tv2 = *tv;
825         tv2.tv_sec += secs;
826         tv2.tv_usec += usecs;
827         tv2.tv_sec += tv2.tv_usec / 1000000;
828         tv2.tv_usec = tv2.tv_usec % 1000000;
829         return tv2;
830 }
831
832 /****************************************************************************
833  Return the sum of two timeval structures.
834 ****************************************************************************/
835
836 struct timeval timeval_sum(const struct timeval *tv1,
837                            const struct timeval *tv2)
838 {
839         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
840 }
841
842 /****************************************************************************
843  Return a timeval secs/usecs into the future.
844 ****************************************************************************/
845
846 struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
847 {
848         struct timeval tv = timeval_current();
849         return timeval_add(&tv, secs, usecs);
850 }
851
852 /****************************************************************************
853  Compare two timeval structures. 
854  Return -1 if tv1 < tv2
855  Return 0 if tv1 == tv2
856  Return 1 if tv1 > tv2
857 ****************************************************************************/
858
859 int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
860 {
861         if (tv1->tv_sec  > tv2->tv_sec) {
862                 return 1;
863         }
864         if (tv1->tv_sec  < tv2->tv_sec) {
865                 return -1;
866         }
867         if (tv1->tv_usec > tv2->tv_usec) {
868                 return 1;
869         }
870         if (tv1->tv_usec < tv2->tv_usec) {
871                 return -1;
872         }
873         return 0;
874 }
875
876 /****************************************************************************
877  Return the difference between two timevals as a timeval.
878  If tv1 comes after tv2, then return a zero timeval
879  (this is *tv2 - *tv1).
880 ****************************************************************************/
881
882 struct timeval timeval_until(const struct timeval *tv1,
883                              const struct timeval *tv2)
884 {
885         struct timeval t;
886         if (timeval_compare(tv1, tv2) >= 0) {
887                 return timeval_zero();
888         }
889         t.tv_sec = tv2->tv_sec - tv1->tv_sec;
890         if (tv1->tv_usec > tv2->tv_usec) {
891                 t.tv_sec--;
892                 t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
893         } else {
894                 t.tv_usec = tv2->tv_usec - tv1->tv_usec;
895         }
896         return t;
897 }
898
899 /****************************************************************************
900  Return the lesser of two timevals.
901 ****************************************************************************/
902
903 struct timeval timeval_min(const struct timeval *tv1,
904                            const struct timeval *tv2)
905 {
906         if (tv1->tv_sec < tv2->tv_sec) {
907                 return *tv1;
908         }
909         if (tv1->tv_sec > tv2->tv_sec) {
910                 return *tv2;
911         }
912         if (tv1->tv_usec < tv2->tv_usec) {
913                 return *tv1;
914         }
915         return *tv2;
916 }
917
918 /****************************************************************************
919  Return the greater of two timevals.
920 ****************************************************************************/
921
922 struct timeval timeval_max(const struct timeval *tv1,
923                            const struct timeval *tv2)
924 {
925         if (tv1->tv_sec > tv2->tv_sec) {
926                 return *tv1;
927         }
928         if (tv1->tv_sec < tv2->tv_sec) {
929                 return *tv2;
930         }
931         if (tv1->tv_usec > tv2->tv_usec) {
932                 return *tv1;
933         }
934         return *tv2;
935 }
936
937 /****************************************************************************
938  Convert ASN.1 GeneralizedTime string to unix-time.
939  Returns 0 on failure; Currently ignores timezone. 
940 ****************************************************************************/
941
942 time_t generalized_to_unix_time(const char *str)
943
944         struct tm tm;
945
946         ZERO_STRUCT(tm);
947
948         if (sscanf(str, "%4d%2d%2d%2d%2d%2d", 
949                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
950                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
951                 return 0;
952         }
953         tm.tm_year -= 1900;
954         tm.tm_mon -= 1;
955
956         return timegm(&tm);
957 }