r17818: Fixup uint64 time calc. NT time is a 64 bit number,
[Samba/nascimento.git] / source3 / lib / time.c
blobb4477d693ac30d23b4f8960abac451ef8d8926f6
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.
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.
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.
21 #include "includes.h"
24 This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com>
25 in May 1996
28 int extra_time_offset = 0;
30 #ifndef CHAR_BIT
31 #define CHAR_BIT 8
32 #endif
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
42 /*******************************************************************
43 External access to time_t_min and time_t_max.
44 ********************************************************************/
46 time_t get_time_t_max(void)
48 return TIME_T_MAX;
51 /*******************************************************************
52 A gettimeofday wrapper.
53 ********************************************************************/
55 void GetTimeOfDay(struct timeval *tval)
57 #ifdef HAVE_GETTIMEOFDAY_TZ
58 gettimeofday(tval,NULL);
59 #else
60 gettimeofday(tval);
61 #endif
64 #define TM_YEAR_BASE 1900
66 /*******************************************************************
67 Yield the difference between *A and *B, in seconds, ignoring leap seconds.
68 ********************************************************************/
70 static int tm_diff(struct tm *a, struct tm *b)
72 int ay = a->tm_year + (TM_YEAR_BASE - 1);
73 int by = b->tm_year + (TM_YEAR_BASE - 1);
74 int intervening_leap_days = (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
75 int years = ay - by;
76 int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
77 int hours = 24*days + (a->tm_hour - b->tm_hour);
78 int minutes = 60*hours + (a->tm_min - b->tm_min);
79 int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
81 return seconds;
84 /*******************************************************************
85 Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
86 ******************************************************************/
88 int get_time_zone(time_t t)
90 struct tm *tm = gmtime(&t);
91 struct tm tm_utc;
93 if (!tm) {
94 return 0;
96 tm_utc = *tm;
97 tm = localtime(&t);
98 if (!tm) {
99 return 0;
101 return tm_diff(&tm_utc,tm) + 60*extra_time_offset;
104 /*******************************************************************
105 Accessor function for the server time zone offset.
106 set_server_zone_offset() must have been called first.
107 ******************************************************************/
109 static int server_zone_offset;
111 int get_server_zone_offset(void)
113 return server_zone_offset;
116 /*******************************************************************
117 Initialize the server time zone offset. Called when a client connects.
118 ******************************************************************/
120 int set_server_zone_offset(time_t t)
122 server_zone_offset = get_time_zone(t);
123 return server_zone_offset;
126 /*******************************************************************
127 Re-read the smb serverzone value.
128 ******************************************************************/
130 static struct timeval start_time_hires;
132 void TimeInit(void)
134 set_server_zone_offset(time(NULL));
136 DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
138 /* Save the start time of this process. */
139 if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
140 GetTimeOfDay(&start_time_hires);
144 /**********************************************************************
145 Return a timeval struct of the uptime of this process. As TimeInit is
146 done before a daemon fork then this is the start time from the parent
147 daemon start. JRA.
148 ***********************************************************************/
150 void get_process_uptime(struct timeval *ret_time)
152 struct timeval time_now_hires;
154 GetTimeOfDay(&time_now_hires);
155 ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
156 if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
157 ret_time->tv_sec -= 1;
158 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
159 } else {
160 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
164 #if 0
165 /****************************************************************************
166 Return the UTC offset in seconds west of UTC, adjusted for extra time offset.
167 **************************************************************************/
169 int TimeDiff(time_t t)
171 return get_time_zone(t);
173 #endif
175 time_t convert_timespec_to_time_t(struct timespec ts)
177 /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
178 increment if it's greater than 500 millionth of a second. */
179 if (ts.tv_nsec > 500000000) {
180 return ts.tv_sec + 1;
182 return ts.tv_sec;
185 struct timespec convert_time_t_to_timespec(time_t t)
187 struct timespec ts;
188 ts.tv_sec = t;
189 ts.tv_nsec = 0;
190 return ts;
193 #ifdef uint64
195 #if (SIZEOF_LONG == 8)
196 #define TIME_FIXUP_CONSTANT_INT 11644473600L
197 #elif (SIZEOF_LONG_LONG == 8)
198 #define TIME_FIXUP_CONSTANT_INT 11644473600LL
199 #endif
201 /****************************************************************************
202 Interpret an 8 byte "filetime" structure to a time_t
203 It's originally in "100ns units since jan 1st 1601"
205 An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
207 tv_sec = 0
208 tv_nsec = 0;
210 Returns GMT.
211 ****************************************************************************/
213 /* Large integer version. */
214 static struct timespec nt_time_to_unix_timespec(NTTIME *nt)
216 uint64 d;
217 struct timespec ret;
219 if ((nt->high == 0 && nt->low == 0 )||
220 (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
221 ret.tv_sec = 0;
222 ret.tv_nsec = 0;
223 return ret;
226 d = (((uint64)nt->high) << 32 ) + ((uint64)nt->low);
227 /* d is now in 100ns units, since jan 1st 1601".
228 Save off the ns fraction. */
230 ret.tv_nsec = (long) ((d % 100) * 100);
232 /* Convert to seconds */
233 d /= 1000*1000*10;
235 /* Now adjust by 369 years to make the secs since 1970 */
236 d -= TIME_FIXUP_CONSTANT_INT;
238 if (((time_t)d) <= TIME_T_MIN) {
239 ret.tv_sec = TIME_T_MIN;
240 ret.tv_nsec = 0;
241 return ret;
244 if (((time_t)d) >= TIME_T_MAX) {
245 ret.tv_sec = TIME_T_MAX;
246 ret.tv_nsec = 0;
247 return ret;
250 ret.tv_sec = (time_t)d;
251 return ret;
254 /****************************************************************************
255 Convert a NTTIME structure to a time_t.
256 It's originally in "100ns units".
258 This is an absolute version of the one above.
259 By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
260 if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
261 ****************************************************************************/
263 time_t nt_time_to_unix_abs(const NTTIME *nt)
265 uint64 d;
266 NTTIME neg_nt;
268 if (nt->high == 0) {
269 return (time_t)0;
272 if (nt->high==0x80000000 && nt->low==0) {
273 return (time_t)-1;
276 /* reverse the time */
277 /* it's a negative value, turn it to positive */
278 neg_nt.high=~nt->high;
279 neg_nt.low=~nt->low;
281 d = (((uint64)neg_nt.high) << 32 ) + ((uint64)neg_nt.low);
283 d += 1000*1000*10/2;
284 d /= 1000*1000*10;
286 if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
287 return (time_t)0;
290 return (time_t)d;
293 /****************************************************************************
294 Put a 8 byte filetime from a struct timespec. Uses GMT.
295 ****************************************************************************/
297 void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
299 uint64 d;
301 if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
302 nt->low = 0;
303 nt->high = 0;
304 return;
306 if (ts.tv_sec == TIME_T_MAX) {
307 nt->low = 0xffffffff;
308 nt->high = 0x7fffffff;
309 return;
311 if (ts.tv_sec == (time_t)-1) {
312 nt->low = 0xffffffff;
313 nt->high = 0xffffffff;
314 return;
317 d = ts.tv_sec;
318 d += TIME_FIXUP_CONSTANT_INT;
319 d *= 1000*1000*10;
320 /* d is now in 100ns units. */
321 d += (ts.tv_nsec / 100);
323 nt->low = (uint32)(d & 0xFFFFFFFF);
324 nt->high = (uint32)(d >> 32 );
327 #else
329 /* No 64-bit datatype. Use double float. */
330 #define TIME_FIXUP_CONSTANT_DOUBLE (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
332 /* Floating point double versions. */
333 static struct timespec nt_time_to_unix_timespec(NTTIME *nt)
335 double d;
336 struct timespec ret;
338 if ((nt->high == 0 && nt->low == 0 )||
339 (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
340 ret.tv_sec = 0;
341 ret.tv_nsec = 0;
342 return ret;
345 d = ((double)nt->high)*4.0*(double)(1<<30);
346 d += (nt->low&0xFFF00000);
347 d *= 1.0e-7;
349 /* now adjust by 369 years to make the secs since 1970 */
350 d -= TIME_FIXUP_CONSTANT_DOUBLE;
352 if (d <= TIME_T_MIN) {
353 ret.tv_sec = TIME_T_MIN;
354 ret.tv_nsec = 0;
355 return ret;
358 if (d >= TIME_T_MAX) {
359 ret.tv_sec = TIME_T_MAX;
360 ret.tv_nsec = 0;
361 return ret;
364 ret.tv_sec = (time_t)d;
365 ret.tv_nsec = (long) ((d - (double)ret.tv_sec)*1.0e9);
366 return ret;
369 /****************************************************************************
370 Convert a NTTIME structure to a time_t.
371 It's originally in "100ns units".
373 This is an absolute version of the one above.
374 By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
375 if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
376 ****************************************************************************/
378 time_t nt_time_to_unix_abs(const NTTIME *nt)
380 double d;
381 time_t ret;
382 NTTIME neg_nt;
384 if (nt->high == 0) {
385 return (time_t)0;
388 if (nt->high==0x80000000 && nt->low==0) {
389 return (time_t)-1;
392 /* reverse the time */
393 /* it's a negative value, turn it to positive */
394 neg_nt.high=~nt->high;
395 neg_nt.low=~nt->low;
397 d = ((double)neg_nt.high)*4.0*(double)(1<<30);
398 d += (neg_nt.low&0xFFF00000);
399 d *= 1.0e-7;
401 if (!(TIME_T_MIN <= d && d <= TIME_T_MAX)) {
402 return (time_t)0;
405 ret = (time_t)(d+0.5);
406 return ret;
409 /****************************************************************************
410 Put a 8 byte filetime from a struct timespec. Uses GMT.
411 ****************************************************************************/
413 void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
415 double d;
417 if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
418 nt->low = 0;
419 nt->high = 0;
420 return;
422 if (ts.tv_sec == TIME_T_MAX) {
423 nt->low = 0xffffffff;
424 nt->high = 0x7fffffff;
425 return;
427 if (ts.tv_sec == (time_t)-1) {
428 nt->low = 0xffffffff;
429 nt->high = 0xffffffff;
430 return;
433 d = (double)(ts.tv_sec);
434 d += TIME_FIXUP_CONSTANT_DOUBLE;
435 d *= 1.0e7;
436 d += ((double)ts.tv_nsec / 100.0);
438 nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
439 nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
441 #endif
443 time_t nt_time_to_unix(NTTIME *nt)
445 return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
448 /****************************************************************************
449 Interprets an nt time into a unix struct timespec.
450 Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
451 will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
452 ****************************************************************************/
454 struct timespec interpret_long_date(char *p)
456 NTTIME nt;
457 nt.low = IVAL(p,0);
458 nt.high = IVAL(p,4);
459 if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) {
460 struct timespec ret;
461 ret.tv_sec = (time_t)-1;
462 ret.tv_nsec = 0;
463 return ret;
465 return nt_time_to_unix_timespec(&nt);
468 /****************************************************************************
469 Put a 8 byte filetime from a time_t. Uses GMT.
470 ****************************************************************************/
472 void unix_to_nt_time(NTTIME *nt, time_t t)
474 struct timespec ts;
475 ts.tv_sec = t;
476 ts.tv_nsec = 0;
477 unix_timespec_to_nt_time(nt, ts);
480 /****************************************************************************
481 Convert a time_t to a NTTIME structure
483 This is an absolute version of the one above.
484 By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
485 If the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM
486 ****************************************************************************/
488 void unix_to_nt_time_abs(NTTIME *nt, time_t t)
490 double d;
492 if (t==0) {
493 nt->low = 0;
494 nt->high = 0;
495 return;
498 if (t == TIME_T_MAX) {
499 nt->low = 0xffffffff;
500 nt->high = 0x7fffffff;
501 return;
504 if (t == (time_t)-1) {
505 /* that's what NT uses for infinite */
506 nt->low = 0x0;
507 nt->high = 0x80000000;
508 return;
511 d = (double)(t);
512 d *= 1.0e7;
514 nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
515 nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
517 /* convert to a negative value */
518 nt->high=~nt->high;
519 nt->low=~nt->low;
522 /****************************************************************************
523 Take a Unix time and convert to an NTTIME structure and place in buffer
524 pointed to by p.
525 ****************************************************************************/
527 void put_long_date_timespec(char *p, struct timespec ts)
529 NTTIME nt;
530 unix_timespec_to_nt_time(&nt, ts);
531 SIVAL(p, 0, nt.low);
532 SIVAL(p, 4, nt.high);
535 void put_long_date(char *p, time_t t)
537 struct timespec ts;
538 ts.tv_sec = t;
539 ts.tv_nsec = 0;
540 put_long_date_timespec(p, ts);
543 /****************************************************************************
544 Check if it's a null mtime.
545 ****************************************************************************/
547 BOOL null_mtime(time_t mtime)
549 if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
550 return(True);
551 return(False);
554 /*******************************************************************
555 Create a 16 bit dos packed date.
556 ********************************************************************/
558 static uint16 make_dos_date1(struct tm *t)
560 uint16 ret=0;
561 ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
562 ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
563 return(ret);
566 /*******************************************************************
567 Create a 16 bit dos packed time.
568 ********************************************************************/
570 static uint16 make_dos_time1(struct tm *t)
572 uint16 ret=0;
573 ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
574 ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
575 return(ret);
578 /*******************************************************************
579 Create a 32 bit dos packed date/time from some parameters.
580 This takes a GMT time and returns a packed localtime structure.
581 ********************************************************************/
583 static uint32 make_dos_date(time_t unixdate, int zone_offset)
585 struct tm *t;
586 uint32 ret=0;
588 if (unixdate == 0) {
589 return 0;
592 unixdate -= zone_offset;
593 t = gmtime(&unixdate);
594 if (!t) {
595 return 0xFFFFFFFF;
598 ret = make_dos_date1(t);
599 ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
601 return(ret);
604 /*******************************************************************
605 Put a dos date into a buffer (time/date format).
606 This takes GMT time and puts local time in the buffer.
607 ********************************************************************/
609 static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
611 uint32 x = make_dos_date(unixdate, zone_offset);
612 SIVAL(buf,offset,x);
615 /*******************************************************************
616 Put a dos date into a buffer (date/time format).
617 This takes GMT time and puts local time in the buffer.
618 ********************************************************************/
620 static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
622 uint32 x = make_dos_date(unixdate, zone_offset);
623 x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
624 SIVAL(buf,offset,x);
627 /*******************************************************************
628 Put a dos 32 bit "unix like" date into a buffer. This routine takes
629 GMT and converts it to LOCAL time before putting it (most SMBs assume
630 localtime for this sort of date)
631 ********************************************************************/
633 static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
635 if (!null_mtime(unixdate)) {
636 unixdate -= zone_offset;
638 SIVAL(buf,offset,unixdate);
641 /*******************************************************************
642 Interpret a 32 bit dos packed date/time to some parameters.
643 ********************************************************************/
645 static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
647 uint32 p0,p1,p2,p3;
649 p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
650 p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
652 *second = 2*(p0 & 0x1F);
653 *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
654 *hour = (p1>>3)&0xFF;
655 *day = (p2&0x1F);
656 *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
657 *year = ((p3>>1)&0xFF) + 80;
660 /*******************************************************************
661 Create a unix date (int GMT) from a dos date (which is actually in
662 localtime).
663 ********************************************************************/
665 static time_t make_unix_date(void *date_ptr, int zone_offset)
667 uint32 dos_date=0;
668 struct tm t;
669 time_t ret;
671 dos_date = IVAL(date_ptr,0);
673 if (dos_date == 0) {
674 return 0;
677 interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
678 &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
679 t.tm_isdst = -1;
681 ret = timegm(&t);
683 ret += zone_offset;
685 return(ret);
688 /*******************************************************************
689 Like make_unix_date() but the words are reversed.
690 ********************************************************************/
692 static time_t make_unix_date2(void *date_ptr, int zone_offset)
694 uint32 x,x2;
696 x = IVAL(date_ptr,0);
697 x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
698 SIVAL(&x,0,x2);
700 return(make_unix_date((void *)&x, zone_offset));
703 /*******************************************************************
704 Create a unix GMT date from a dos date in 32 bit "unix like" format
705 these generally arrive as localtimes, with corresponding DST.
706 ******************************************************************/
708 static time_t make_unix_date3(void *date_ptr, int zone_offset)
710 time_t t = (time_t)IVAL(date_ptr,0);
711 if (!null_mtime(t)) {
712 t += zone_offset;
714 return(t);
717 /***************************************************************************
718 Server versions of the above functions.
719 ***************************************************************************/
721 void srv_put_dos_date(char *buf,int offset,time_t unixdate)
723 put_dos_date(buf, offset, unixdate, server_zone_offset);
726 void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
728 put_dos_date2(buf, offset, unixdate, server_zone_offset);
731 void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
733 put_dos_date3(buf, offset, unixdate, server_zone_offset);
736 time_t srv_make_unix_date(void *date_ptr)
738 return make_unix_date(date_ptr, server_zone_offset);
741 time_t srv_make_unix_date2(void *date_ptr)
743 return make_unix_date2(date_ptr, server_zone_offset);
746 time_t srv_make_unix_date3(void *date_ptr)
748 return make_unix_date3(date_ptr, server_zone_offset);
751 /***************************************************************************
752 Client versions of the above functions.
753 ***************************************************************************/
755 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
757 put_dos_date(buf, offset, unixdate, cli->serverzone);
760 void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
762 put_dos_date2(buf, offset, unixdate, cli->serverzone);
765 void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
767 put_dos_date3(buf, offset, unixdate, cli->serverzone);
770 time_t cli_make_unix_date(struct cli_state *cli, void *date_ptr)
772 return make_unix_date(date_ptr, cli->serverzone);
775 time_t cli_make_unix_date2(struct cli_state *cli, void *date_ptr)
777 return make_unix_date2(date_ptr, cli->serverzone);
780 time_t cli_make_unix_date3(struct cli_state *cli, void *date_ptr)
782 return make_unix_date3(date_ptr, cli->serverzone);
785 /***************************************************************************
786 Return a HTTP/1.0 time string.
787 ***************************************************************************/
789 char *http_timestring(time_t t)
791 static fstring buf;
792 struct tm *tm = localtime(&t);
794 if (!tm) {
795 slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
796 } else {
797 #ifndef HAVE_STRFTIME
798 const char *asct = asctime(tm);
799 fstrcpy(buf, asct ? asct : "unknown");
801 if(buf[strlen(buf)-1] == '\n') {
802 buf[strlen(buf)-1] = 0;
803 #else /* !HAVE_STRFTIME */
804 strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
805 #endif /* !HAVE_STRFTIME */
807 return buf;
810 /****************************************************************************
811 Return the date and time as a string
812 ****************************************************************************/
814 char *current_timestring(BOOL hires)
816 static fstring TimeBuf;
817 struct timeval tp;
818 time_t t;
819 struct tm *tm;
821 if (hires) {
822 GetTimeOfDay(&tp);
823 t = (time_t)tp.tv_sec;
824 } else {
825 t = time(NULL);
827 tm = localtime(&t);
828 if (!tm) {
829 if (hires) {
830 slprintf(TimeBuf,
831 sizeof(TimeBuf)-1,
832 "%ld.%06ld seconds since the Epoch",
833 (long)tp.tv_sec,
834 (long)tp.tv_usec);
835 } else {
836 slprintf(TimeBuf,
837 sizeof(TimeBuf)-1,
838 "%ld seconds since the Epoch",
839 (long)t);
841 } else {
842 #ifdef HAVE_STRFTIME
843 if (hires) {
844 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
845 slprintf(TimeBuf+strlen(TimeBuf),
846 sizeof(TimeBuf)-1 - strlen(TimeBuf),
847 ".%06ld",
848 (long)tp.tv_usec);
849 } else {
850 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
852 #else
853 if (hires) {
854 const char *asct = asctime(tm);
855 slprintf(TimeBuf,
856 sizeof(TimeBuf)-1,
857 "%s.%06ld",
858 asct ? asct : "unknown",
859 (long)tp.tv_usec);
860 } else {
861 const char *asct = asctime(tm);
862 fstrcpy(TimeBuf, asct ? asct : "unknown");
864 #endif
866 return(TimeBuf);
869 /****************************************************************************
870 Return the best approximation to a 'create time' under UNIX from a stat
871 structure.
872 ****************************************************************************/
874 time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
876 time_t ret, ret1;
878 if(S_ISDIR(st->st_mode) && fake_dirs) {
879 return (time_t)315493200L; /* 1/1/1980 */
882 ret = MIN(st->st_ctime, st->st_mtime);
883 ret1 = MIN(ret, st->st_atime);
885 if(ret1 != (time_t)0) {
886 return ret1;
890 * One of ctime, mtime or atime was zero (probably atime).
891 * Just return MIN(ctime, mtime).
893 return ret;
896 struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
898 struct timespec ts;
899 ts.tv_sec = get_create_time(st, fake_dirs);
900 ts.tv_nsec = 0;
901 return ts;
904 /****************************************************************************
905 Initialise an NTTIME to -1, which means "unknown" or "don't expire".
906 ****************************************************************************/
908 void init_nt_time(NTTIME *nt)
910 nt->high = 0x7FFFFFFF;
911 nt->low = 0xFFFFFFFF;
914 BOOL nt_time_is_set(const NTTIME *nt)
916 if ((nt->high == 0x7FFFFFFF) && (nt->low == 0xFFFFFFFF)) {
917 return False;
920 if ((nt->high == 0x80000000) && (nt->low == 0)) {
921 return False;
924 return True;
927 /****************************************************************************
928 Check if NTTIME is 0.
929 ****************************************************************************/
931 BOOL nt_time_is_zero(const NTTIME *nt)
933 if(nt->high==0) {
934 return True;
936 return False;
939 /****************************************************************************
940 Check if two NTTIMEs are the same.
941 ****************************************************************************/
943 BOOL nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
945 return (nt1->high == nt2->high && nt1->low == nt2->low);
948 /****************************************************************************
949 Return a timeval difference in usec.
950 ****************************************************************************/
952 SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *smallt)
954 SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec;
955 return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec);
958 /****************************************************************************
959 Return a timeval struct with the given elements.
960 ****************************************************************************/
962 struct timeval timeval_set(uint32_t secs, uint32_t usecs)
964 struct timeval tv;
965 tv.tv_sec = secs;
966 tv.tv_usec = usecs;
967 return tv;
970 /****************************************************************************
971 Return a zero timeval.
972 ****************************************************************************/
974 struct timeval timeval_zero(void)
976 return timeval_set(0,0);
979 /****************************************************************************
980 Return True if a timeval is zero.
981 ****************************************************************************/
983 BOOL timeval_is_zero(const struct timeval *tv)
985 return tv->tv_sec == 0 && tv->tv_usec == 0;
988 /****************************************************************************
989 Return a timeval for the current time.
990 ****************************************************************************/
992 struct timeval timeval_current(void)
994 struct timeval tv;
995 GetTimeOfDay(&tv);
996 return tv;
999 /****************************************************************************
1000 Return a timeval ofs microseconds after tv.
1001 ****************************************************************************/
1003 struct timeval timeval_add(const struct timeval *tv,
1004 uint32_t secs, uint32_t usecs)
1006 struct timeval tv2 = *tv;
1007 tv2.tv_sec += secs;
1008 tv2.tv_usec += usecs;
1009 tv2.tv_sec += tv2.tv_usec / 1000000;
1010 tv2.tv_usec = tv2.tv_usec % 1000000;
1011 return tv2;
1014 /****************************************************************************
1015 Return the sum of two timeval structures.
1016 ****************************************************************************/
1018 struct timeval timeval_sum(const struct timeval *tv1,
1019 const struct timeval *tv2)
1021 return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
1024 /****************************************************************************
1025 Return a timeval secs/usecs into the future.
1026 ****************************************************************************/
1028 struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
1030 struct timeval tv = timeval_current();
1031 return timeval_add(&tv, secs, usecs);
1034 /****************************************************************************
1035 Compare two timeval structures.
1036 Return -1 if tv1 < tv2
1037 Return 0 if tv1 == tv2
1038 Return 1 if tv1 > tv2
1039 ****************************************************************************/
1041 int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
1043 if (tv1->tv_sec > tv2->tv_sec) {
1044 return 1;
1046 if (tv1->tv_sec < tv2->tv_sec) {
1047 return -1;
1049 if (tv1->tv_usec > tv2->tv_usec) {
1050 return 1;
1052 if (tv1->tv_usec < tv2->tv_usec) {
1053 return -1;
1055 return 0;
1058 /****************************************************************************
1059 Return the difference between two timevals as a timeval.
1060 If tv1 comes after tv2, then return a zero timeval
1061 (this is *tv2 - *tv1).
1062 ****************************************************************************/
1064 struct timeval timeval_until(const struct timeval *tv1,
1065 const struct timeval *tv2)
1067 struct timeval t;
1068 if (timeval_compare(tv1, tv2) >= 0) {
1069 return timeval_zero();
1071 t.tv_sec = tv2->tv_sec - tv1->tv_sec;
1072 if (tv1->tv_usec > tv2->tv_usec) {
1073 t.tv_sec--;
1074 t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
1075 } else {
1076 t.tv_usec = tv2->tv_usec - tv1->tv_usec;
1078 return t;
1081 /****************************************************************************
1082 Return the lesser of two timevals.
1083 ****************************************************************************/
1085 struct timeval timeval_min(const struct timeval *tv1,
1086 const struct timeval *tv2)
1088 if (tv1->tv_sec < tv2->tv_sec) {
1089 return *tv1;
1091 if (tv1->tv_sec > tv2->tv_sec) {
1092 return *tv2;
1094 if (tv1->tv_usec < tv2->tv_usec) {
1095 return *tv1;
1097 return *tv2;
1100 /****************************************************************************
1101 Return the greater of two timevals.
1102 ****************************************************************************/
1104 struct timeval timeval_max(const struct timeval *tv1,
1105 const struct timeval *tv2)
1107 if (tv1->tv_sec > tv2->tv_sec) {
1108 return *tv1;
1110 if (tv1->tv_sec < tv2->tv_sec) {
1111 return *tv2;
1113 if (tv1->tv_usec > tv2->tv_usec) {
1114 return *tv1;
1116 return *tv2;
1119 /****************************************************************************
1120 Convert ASN.1 GeneralizedTime string to unix-time.
1121 Returns 0 on failure; Currently ignores timezone.
1122 ****************************************************************************/
1124 time_t generalized_to_unix_time(const char *str)
1126 struct tm tm;
1128 ZERO_STRUCT(tm);
1130 if (sscanf(str, "%4d%2d%2d%2d%2d%2d",
1131 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1132 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1133 return 0;
1135 tm.tm_year -= 1900;
1136 tm.tm_mon -= 1;
1138 return timegm(&tm);
1141 /****************************************************************************
1142 Get/Set all the possible time fields from a stat struct as a timespec.
1143 ****************************************************************************/
1145 struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
1147 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1148 struct timespec ret;
1150 /* Old system - no ns timestamp. */
1151 ret.tv_sec = pst->st_atime;
1152 ret.tv_nsec = 0;
1153 return ret;
1154 #else
1155 #if defined(HAVE_STAT_ST_ATIM)
1156 return pst->st_atim;
1157 #elif defined(HAVE_STAT_ST_ATIMENSEC)
1158 struct timespec ret;
1159 ret.tv_sec = pst->st_atime;
1160 ret.tv_nsec = pst->st_atimensec;
1161 return ret;
1162 #else
1163 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1164 #endif
1165 #endif
1168 void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
1170 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1171 /* Old system - no ns timestamp. */
1172 pst->st_atime = ts.tv_sec;
1173 #else
1174 #if defined(HAVE_STAT_ST_ATIM)
1175 pst->st_atim = ts;
1176 #elif defined(HAVE_STAT_ST_ATIMENSEC)
1177 pst->st_atime = ts.tv_sec;
1178 pst->st_atimensec = ts.tv_nsec
1179 #else
1180 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1181 #endif
1182 #endif
1185 struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
1187 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1188 struct timespec ret;
1190 /* Old system - no ns timestamp. */
1191 ret.tv_sec = pst->st_mtime;
1192 ret.tv_nsec = 0;
1193 return ret;
1194 #else
1195 #if defined(HAVE_STAT_ST_MTIM)
1196 return pst->st_mtim;
1197 #elif defined(HAVE_STAT_ST_MTIMENSEC)
1198 struct timespec ret;
1199 ret.tv_sec = pst->st_mtime;
1200 ret.tv_nsec = pst->st_mtimensec;
1201 return ret;
1202 #else
1203 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1204 #endif
1205 #endif
1208 void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
1210 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1211 /* Old system - no ns timestamp. */
1212 pst->st_mtime = ts.tv_sec;
1213 #else
1214 #if defined(HAVE_STAT_ST_MTIM)
1215 pst->st_mtim = ts;
1216 #elif defined(HAVE_STAT_ST_MTIMENSEC)
1217 pst->st_mtime = ts.tv_sec;
1218 pst->st_mtimensec = ts.tv_nsec
1219 #else
1220 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1221 #endif
1222 #endif
1225 struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
1227 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1228 struct timespec ret;
1230 /* Old system - no ns timestamp. */
1231 ret.tv_sec = pst->st_ctime;
1232 ret.tv_nsec = 0;
1233 return ret;
1234 #else
1235 #if defined(HAVE_STAT_ST_CTIM)
1236 return pst->st_ctim;
1237 #elif defined(HAVE_STAT_ST_CTIMENSEC)
1238 struct timespec ret;
1239 ret.tv_sec = pst->st_ctime;
1240 ret.tv_nsec = pst->st_ctimensec;
1241 return ret;
1242 #else
1243 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1244 #endif
1245 #endif
1248 void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
1250 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
1251 /* Old system - no ns timestamp. */
1252 pst->st_ctime = ts.tv_sec;
1253 #else
1254 #if defined(HAVE_STAT_ST_CTIM)
1255 pst->st_atim = ts;
1256 #elif defined(HAVE_STAT_ST_CTIMENSEC)
1257 pst->st_ctime = ts.tv_sec;
1258 pst->st_ctimensec = ts.tv_nsec
1259 #else
1260 #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
1261 #endif
1262 #endif
1265 #if 0
1266 /****************************************************************************
1267 Return the best approximation to a 'create time' under UNIX from a stat
1268 structure.
1269 ****************************************************************************/
1271 struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
1273 time_t ret, ret1;
1275 if(S_ISDIR(st->st_mode) && fake_dirs) {
1276 return (time_t)315493200L; /* 1/1/1980 */
1279 ret = MIN(st->st_ctime, st->st_mtime);
1280 ret1 = MIN(ret, st->st_atime);
1282 if(ret1 != (time_t)0) {
1283 return ret1;
1287 * One of ctime, mtime or atime was zero (probably atime).
1288 * Just return MIN(ctime, mtime).
1290 return ret;
1292 #endif
1294 void dos_filetime_timespec(struct timespec *tsp)
1296 tsp->tv_sec &= ~1;
1297 tsp->tv_nsec = 0;
1301 Return the date and time as a string
1303 char *timestring(TALLOC_CTX *mem_ctx, time_t t)
1305 char *TimeBuf;
1306 char tempTime[80];
1307 struct tm *tm;
1309 tm = localtime(&t);
1310 if (!tm) {
1311 return talloc_asprintf(mem_ctx,
1312 "%ld seconds since the Epoch",
1313 (long)t);
1316 #ifdef HAVE_STRFTIME
1317 /* some versions of gcc complain about using %c. This is a bug
1318 in the gcc warning, not a bug in this code. See a recent
1319 strftime() manual page for details.
1321 strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm);
1322 TimeBuf = talloc_strdup(mem_ctx, tempTime);
1323 #else
1324 TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
1325 #endif
1327 return TimeBuf;
1332 return a talloced string representing a NTTIME for human consumption
1334 const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
1336 time_t t;
1337 if (nt.low == 0 && nt.high == 0) {
1338 return "NTTIME(0)";
1340 t = nt_time_to_unix(&nt);
1341 return timestring(mem_ctx, t);
1344 /****************************************************************************
1345 Utility function that always returns a const string even if localtime
1346 and asctime fail.
1347 ****************************************************************************/
1349 const char *time_to_asc(const time_t *t)
1351 const char *asct;
1352 struct tm *lt = localtime(t);
1354 if (!lt) {
1355 return "unknown time";
1358 asct = asctime(lt);
1359 if (!asct) {
1360 return "unknown time";
1362 return asct;