root/lib/util/time.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_time_t_max
  2. GetTimeOfDay
  3. convert_timespec_to_time_t
  4. convert_time_t_to_timespec
  5. nt_time_to_unix
  6. unix_to_nt_time
  7. null_time
  8. null_nttime
  9. make_dos_date1
  10. make_dos_time1
  11. make_dos_date
  12. push_dos_date
  13. push_dos_date2
  14. push_dos_date3
  15. interpret_dos_date
  16. pull_dos_date
  17. pull_dos_date2
  18. pull_dos_date3
  19. http_timestring
  20. timestring
  21. nt_time_string
  22. push_nttime
  23. pull_nttime
  24. usec_time_diff
  25. timeval_zero
  26. timeval_is_zero
  27. timeval_current
  28. timeval_set
  29. timeval_add
  30. timeval_sum
  31. timeval_current_ofs
  32. timeval_compare
  33. timeval_expired
  34. timeval_elapsed2
  35. timeval_elapsed
  36. timeval_min
  37. timeval_max
  38. timeval_until
  39. timeval_to_nttime
  40. nttime_to_timeval
  41. tm_diff
  42. get_time_zone
  43. nt_time_to_unix_timespec
  44. nt_time_equal
  45. null_timespec

   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 
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "system/time.h"
  24 
  25 /**
  26  * @file
  27  * @brief time handling functions
  28  */
  29 
  30 #ifndef TIME_T_MIN
  31 /* we use 0 here, because (time_t)-1 means error */
  32 #define TIME_T_MIN 0
  33 #endif
  34 
  35 #if (SIZEOF_LONG == 8)
  36 #define TIME_FIXUP_CONSTANT_INT 11644473600L
  37 #elif (SIZEOF_LONG_LONG == 8)
  38 #define TIME_FIXUP_CONSTANT_INT 11644473600LL
  39 #endif
  40 
  41 
  42 
  43 /*
  44  * we use the INT32_MAX here as on 64 bit systems,
  45  * gmtime() fails with INT64_MAX
  46  */
  47 
  48 #ifndef TIME_T_MAX
  49 #define TIME_T_MAX MIN(INT32_MAX,_TYPE_MAXIMUM(time_t))
  50 #endif
  51 
  52 /**
  53  External access to time_t_min and time_t_max.
  54 **/
  55 _PUBLIC_ time_t get_time_t_max(void)
     /* [<][>][^][v][top][bottom][index][help] */
  56 {
  57         return TIME_T_MAX;
  58 }
  59 
  60 /**
  61 a gettimeofday wrapper
  62 **/
  63 _PUBLIC_ void GetTimeOfDay(struct timeval *tval)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65 #ifdef HAVE_GETTIMEOFDAY_TZ
  66         gettimeofday(tval,NULL);
  67 #else
  68         gettimeofday(tval);
  69 #endif
  70 }
  71 
  72 
  73 #define TIME_FIXUP_CONSTANT 11644473600LL
  74 
  75 time_t convert_timespec_to_time_t(struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
  76 {
  77         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
  78            increment if it's greater than 500 millionth of a second. */
  79         if (ts.tv_nsec > 500000000) {
  80                 return ts.tv_sec + 1;
  81         }
  82         return ts.tv_sec;
  83 }
  84 
  85 struct timespec convert_time_t_to_timespec(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
  86 {
  87         struct timespec ts;
  88         ts.tv_sec = t;
  89         ts.tv_nsec = 0;
  90         return ts;
  91 }
  92 
  93 
  94 
  95 /**
  96  Interpret an 8 byte "filetime" structure to a time_t
  97  It's originally in "100ns units since jan 1st 1601"
  98 
  99  An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
 100 
 101         tv_sec = 0
 102         tv_nsec = 0;
 103 
 104  Returns GMT.
 105 **/
 106 time_t nt_time_to_unix(NTTIME nt)
     /* [<][>][^][v][top][bottom][index][help] */
 107 {
 108         return convert_timespec_to_time_t(nt_time_to_unix_timespec(&nt));
 109 }
 110 
 111 
 112 /**
 113 put a 8 byte filetime from a time_t
 114 This takes GMT as input
 115 **/
 116 _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 117 {
 118         uint64_t t2; 
 119 
 120         if (t == (time_t)-1) {
 121                 *nt = (NTTIME)-1LL;
 122                 return;
 123         }       
 124 
 125         if (t == TIME_T_MAX) {
 126                 *nt = 0x7fffffffffffffffLL;
 127                 return;
 128         }
 129 
 130         if (t == 0) {
 131                 *nt = 0;
 132                 return;
 133         }               
 134 
 135         t2 = t;
 136         t2 += TIME_FIXUP_CONSTANT_INT;
 137         t2 *= 1000*1000*10;
 138 
 139         *nt = t2;
 140 }
 141 
 142 
 143 /**
 144 check if it's a null unix time
 145 **/
 146 _PUBLIC_ bool null_time(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         return t == 0 || 
 149                 t == (time_t)0xFFFFFFFF || 
 150                 t == (time_t)-1;
 151 }
 152 
 153 
 154 /**
 155 check if it's a null NTTIME
 156 **/
 157 _PUBLIC_ bool null_nttime(NTTIME t)
     /* [<][>][^][v][top][bottom][index][help] */
 158 {
 159         return t == 0 || t == (NTTIME)-1;
 160 }
 161 
 162 /*******************************************************************
 163   create a 16 bit dos packed date
 164 ********************************************************************/
 165 static uint16_t make_dos_date1(struct tm *t)
     /* [<][>][^][v][top][bottom][index][help] */
 166 {
 167         uint16_t ret=0;
 168         ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
 169         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
 170         return ret;
 171 }
 172 
 173 /*******************************************************************
 174   create a 16 bit dos packed time
 175 ********************************************************************/
 176 static uint16_t make_dos_time1(struct tm *t)
     /* [<][>][^][v][top][bottom][index][help] */
 177 {
 178         uint16_t ret=0;
 179         ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
 180         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
 181         return ret;
 182 }
 183 
 184 /*******************************************************************
 185   create a 32 bit dos packed date/time from some parameters
 186   This takes a GMT time and returns a packed localtime structure
 187 ********************************************************************/
 188 static uint32_t make_dos_date(time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 189 {
 190         struct tm *t;
 191         uint32_t ret=0;
 192 
 193         if (unixdate == 0) {
 194                 return 0;
 195         }
 196 
 197         unixdate -= zone_offset;
 198 
 199         t = gmtime(&unixdate);
 200         if (!t) {
 201                 return 0xFFFFFFFF;
 202         }
 203 
 204         ret = make_dos_date1(t);
 205         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
 206 
 207         return ret;
 208 }
 209 
 210 /**
 211 put a dos date into a buffer (time/date format)
 212 This takes GMT time and puts local time in the buffer
 213 **/
 214 _PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 215 {
 216         uint32_t x = make_dos_date(unixdate, zone_offset);
 217         SIVAL(buf,offset,x);
 218 }
 219 
 220 /**
 221 put a dos date into a buffer (date/time format)
 222 This takes GMT time and puts local time in the buffer
 223 **/
 224 _PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 225 {
 226         uint32_t x;
 227         x = make_dos_date(unixdate, zone_offset);
 228         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 229         SIVAL(buf,offset,x);
 230 }
 231 
 232 /**
 233 put a dos 32 bit "unix like" date into a buffer. This routine takes
 234 GMT and converts it to LOCAL time before putting it (most SMBs assume
 235 localtime for this sort of date)
 236 **/
 237 _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 238 {
 239         if (!null_time(unixdate)) {
 240                 unixdate -= zone_offset;
 241         }
 242         SIVAL(buf,offset,unixdate);
 243 }
 244 
 245 /*******************************************************************
 246   interpret a 32 bit dos packed date/time to some parameters
 247 ********************************************************************/
 248 void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
     /* [<][>][^][v][top][bottom][index][help] */
 249 {
 250         uint32_t p0,p1,p2,p3;
 251 
 252         p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
 253         p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
 254 
 255         *second = 2*(p0 & 0x1F);
 256         *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
 257         *hour = (p1>>3)&0xFF;
 258         *day = (p2&0x1F);
 259         *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
 260         *year = ((p3>>1)&0xFF) + 80;
 261 }
 262 
 263 /**
 264   create a unix date (int GMT) from a dos date (which is actually in
 265   localtime)
 266 **/
 267 _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 268 {
 269         uint32_t dos_date=0;
 270         struct tm t;
 271         time_t ret;
 272 
 273         dos_date = IVAL(date_ptr,0);
 274 
 275         if (dos_date == 0) return (time_t)0;
 276   
 277         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
 278                            &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
 279         t.tm_isdst = -1;
 280   
 281         ret = timegm(&t);
 282 
 283         ret += zone_offset;
 284 
 285         return ret;
 286 }
 287 
 288 /**
 289 like make_unix_date() but the words are reversed
 290 **/
 291 _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 292 {
 293         uint32_t x,x2;
 294 
 295         x = IVAL(date_ptr,0);
 296         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 297         SIVAL(&x,0,x2);
 298 
 299         return pull_dos_date((const uint8_t *)&x, zone_offset);
 300 }
 301 
 302 /**
 303   create a unix GMT date from a dos date in 32 bit "unix like" format
 304   these generally arrive as localtimes, with corresponding DST
 305 **/
 306 _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 307 {
 308         time_t t = (time_t)IVAL(date_ptr,0);
 309         if (!null_time(t)) {
 310                 t += zone_offset;
 311         }
 312         return t;
 313 }
 314 
 315 
 316 /**
 317 return a HTTP/1.0 time string
 318 **/
 319 _PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 320 {
 321         char *buf;
 322         char tempTime[60];
 323         struct tm *tm = localtime(&t);
 324 
 325         if (t == TIME_T_MAX) {
 326                 return talloc_strdup(mem_ctx, "never");
 327         }
 328 
 329         if (!tm) {
 330                 return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t);
 331         }
 332 
 333 #ifndef HAVE_STRFTIME
 334         buf = talloc_strdup(mem_ctx, asctime(tm));
 335         if (buf[strlen(buf)-1] == '\n') {
 336                 buf[strlen(buf)-1] = 0;
 337         }
 338 #else
 339         strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
 340         buf = talloc_strdup(mem_ctx, tempTime);
 341 #endif /* !HAVE_STRFTIME */
 342 
 343         return buf;
 344 }
 345 
 346 /**
 347  Return the date and time as a string
 348 **/
 349 _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 350 {
 351         char *TimeBuf;
 352         char tempTime[80];
 353         struct tm *tm;
 354 
 355         tm = localtime(&t);
 356         if (!tm) {
 357                 return talloc_asprintf(mem_ctx,
 358                                        "%ld seconds since the Epoch",
 359                                        (long)t);
 360         }
 361 
 362 #ifdef HAVE_STRFTIME
 363         /* some versions of gcc complain about using %c. This is a bug
 364            in the gcc warning, not a bug in this code. See a recent
 365            strftime() manual page for details.
 366          */
 367         strftime(tempTime,sizeof(tempTime)-1,"%c %Z",tm);
 368         TimeBuf = talloc_strdup(mem_ctx, tempTime);
 369 #else
 370         TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
 371 #endif
 372 
 373         return TimeBuf;
 374 }
 375 
 376 /**
 377   return a talloced string representing a NTTIME for human consumption
 378 */
 379 _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
     /* [<][>][^][v][top][bottom][index][help] */
 380 {
 381         time_t t;
 382         if (nt == 0) {
 383                 return "NTTIME(0)";
 384         }
 385         t = nt_time_to_unix(nt);
 386         return timestring(mem_ctx, t);
 387 }
 388 
 389 
 390 /**
 391   put a NTTIME into a packet
 392 */
 393 _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395         SBVAL(base, offset,   t);
 396 }
 397 
 398 /**
 399   pull a NTTIME from a packet
 400 */
 401 _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
     /* [<][>][^][v][top][bottom][index][help] */
 402 {
 403         NTTIME ret = BVAL(base, offset);
 404         return ret;
 405 }
 406 
 407 /**
 408   return (tv1 - tv2) in microseconds
 409 */
 410 _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
     /* [<][>][^][v][top][bottom][index][help] */
 411 {
 412         int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
 413         return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
 414 }
 415 
 416 
 417 /**
 418   return a zero timeval
 419 */
 420 _PUBLIC_ struct timeval timeval_zero(void)
     /* [<][>][^][v][top][bottom][index][help] */
 421 {
 422         struct timeval tv;
 423         tv.tv_sec = 0;
 424         tv.tv_usec = 0;
 425         return tv;
 426 }
 427 
 428 /**
 429   return true if a timeval is zero
 430 */
 431 _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
     /* [<][>][^][v][top][bottom][index][help] */
 432 {
 433         return tv->tv_sec == 0 && tv->tv_usec == 0;
 434 }
 435 
 436 /**
 437   return a timeval for the current time
 438 */
 439 _PUBLIC_ struct timeval timeval_current(void)
     /* [<][>][^][v][top][bottom][index][help] */
 440 {
 441         struct timeval tv;
 442         GetTimeOfDay(&tv);
 443         return tv;
 444 }
 445 
 446 /**
 447   return a timeval struct with the given elements
 448 */
 449 _PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs)
     /* [<][>][^][v][top][bottom][index][help] */
 450 {
 451         struct timeval tv;
 452         tv.tv_sec = secs;
 453         tv.tv_usec = usecs;
 454         return tv;
 455 }
 456 
 457 
 458 /**
 459   return a timeval ofs microseconds after tv
 460 */
 461 _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
     /* [<][>][^][v][top][bottom][index][help] */
 462                            uint32_t secs, uint32_t usecs)
 463 {
 464         struct timeval tv2 = *tv;
 465         const unsigned int million = 1000000;
 466         tv2.tv_sec += secs;
 467         tv2.tv_usec += usecs;
 468         tv2.tv_sec += tv2.tv_usec / million;
 469         tv2.tv_usec = tv2.tv_usec % million;
 470         return tv2;
 471 }
 472 
 473 /**
 474   return the sum of two timeval structures
 475 */
 476 struct timeval timeval_sum(const struct timeval *tv1,
     /* [<][>][^][v][top][bottom][index][help] */
 477                            const struct timeval *tv2)
 478 {
 479         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
 480 }
 481 
 482 /**
 483   return a timeval secs/usecs into the future
 484 */
 485 _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
     /* [<][>][^][v][top][bottom][index][help] */
 486 {
 487         struct timeval tv = timeval_current();
 488         return timeval_add(&tv, secs, usecs);
 489 }
 490 
 491 /**
 492   compare two timeval structures. 
 493   Return -1 if tv1 < tv2
 494   Return 0 if tv1 == tv2
 495   Return 1 if tv1 > tv2
 496 */
 497 _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
     /* [<][>][^][v][top][bottom][index][help] */
 498 {
 499         if (tv1->tv_sec  > tv2->tv_sec)  return 1;
 500         if (tv1->tv_sec  < tv2->tv_sec)  return -1;
 501         if (tv1->tv_usec > tv2->tv_usec) return 1;
 502         if (tv1->tv_usec < tv2->tv_usec) return -1;
 503         return 0;
 504 }
 505 
 506 /**
 507   return true if a timer is in the past
 508 */
 509 _PUBLIC_ bool timeval_expired(const struct timeval *tv)
     /* [<][>][^][v][top][bottom][index][help] */
 510 {
 511         struct timeval tv2 = timeval_current();
 512         if (tv2.tv_sec > tv->tv_sec) return true;
 513         if (tv2.tv_sec < tv->tv_sec) return false;
 514         return (tv2.tv_usec >= tv->tv_usec);
 515 }
 516 
 517 /**
 518   return the number of seconds elapsed between two times
 519 */
 520 _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
     /* [<][>][^][v][top][bottom][index][help] */
 521 {
 522         return (tv2->tv_sec - tv1->tv_sec) + 
 523                (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
 524 }
 525 
 526 /**
 527   return the number of seconds elapsed since a given time
 528 */
 529 _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
     /* [<][>][^][v][top][bottom][index][help] */
 530 {
 531         struct timeval tv2 = timeval_current();
 532         return timeval_elapsed2(tv, &tv2);
 533 }
 534 
 535 /**
 536   return the lesser of two timevals
 537 */
 538 _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
     /* [<][>][^][v][top][bottom][index][help] */
 539                            const struct timeval *tv2)
 540 {
 541         if (tv1->tv_sec < tv2->tv_sec) return *tv1;
 542         if (tv1->tv_sec > tv2->tv_sec) return *tv2;
 543         if (tv1->tv_usec < tv2->tv_usec) return *tv1;
 544         return *tv2;
 545 }
 546 
 547 /**
 548   return the greater of two timevals
 549 */
 550 _PUBLIC_ struct timeval timeval_max(const struct timeval *tv1,
     /* [<][>][^][v][top][bottom][index][help] */
 551                            const struct timeval *tv2)
 552 {
 553         if (tv1->tv_sec > tv2->tv_sec) return *tv1;
 554         if (tv1->tv_sec < tv2->tv_sec) return *tv2;
 555         if (tv1->tv_usec > tv2->tv_usec) return *tv1;
 556         return *tv2;
 557 }
 558 
 559 /**
 560   return the difference between two timevals as a timeval
 561   if tv1 comes after tv2, then return a zero timeval
 562   (this is *tv2 - *tv1)
 563 */
 564 _PUBLIC_ struct timeval timeval_until(const struct timeval *tv1,
     /* [<][>][^][v][top][bottom][index][help] */
 565                              const struct timeval *tv2)
 566 {
 567         struct timeval t;
 568         if (timeval_compare(tv1, tv2) >= 0) {
 569                 return timeval_zero();
 570         }
 571         t.tv_sec = tv2->tv_sec - tv1->tv_sec;
 572         if (tv1->tv_usec > tv2->tv_usec) {
 573                 t.tv_sec--;
 574                 t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
 575         } else {
 576                 t.tv_usec = tv2->tv_usec - tv1->tv_usec;
 577         }
 578         return t;
 579 }
 580 
 581 
 582 /**
 583   convert a timeval to a NTTIME
 584 */
 585 _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
     /* [<][>][^][v][top][bottom][index][help] */
 586 {
 587         return 10*(tv->tv_usec + 
 588                   ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
 589 }
 590 
 591 /**
 592   convert a NTTIME to a timeval
 593 */
 594 _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
     /* [<][>][^][v][top][bottom][index][help] */
 595 {
 596         if (tv == NULL) return;
 597 
 598         t += 10/2;
 599         t /= 10;
 600         t -= TIME_FIXUP_CONSTANT*1000*1000;
 601 
 602         tv->tv_sec  = t / 1000000;
 603 
 604         if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) {
 605                 tv->tv_sec  = 0;
 606                 tv->tv_usec = 0;
 607                 return;
 608         }
 609         
 610         tv->tv_usec = t - tv->tv_sec*1000000;
 611 }
 612 
 613 /*******************************************************************
 614 yield the difference between *A and *B, in seconds, ignoring leap seconds
 615 ********************************************************************/
 616 static int tm_diff(struct tm *a, struct tm *b)
     /* [<][>][^][v][top][bottom][index][help] */
 617 {
 618         int ay = a->tm_year + (1900 - 1);
 619         int by = b->tm_year + (1900 - 1);
 620         int intervening_leap_days =
 621                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
 622         int years = ay - by;
 623         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
 624         int hours = 24*days + (a->tm_hour - b->tm_hour);
 625         int minutes = 60*hours + (a->tm_min - b->tm_min);
 626         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
 627 
 628         return seconds;
 629 }
 630 
 631 
 632 int extra_time_offset=0;
 633 
 634 /**
 635   return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
 636  */
 637 _PUBLIC_ int get_time_zone(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 638 {
 639         struct tm *tm = gmtime(&t);
 640         struct tm tm_utc;
 641         if (!tm)
 642                 return 0;
 643         tm_utc = *tm;
 644         tm = localtime(&t);
 645         if (!tm)
 646                 return 0;
 647         return tm_diff(&tm_utc,tm)+60*extra_time_offset;
 648 }
 649 
 650 struct timespec nt_time_to_unix_timespec(NTTIME *nt)
     /* [<][>][^][v][top][bottom][index][help] */
 651 {
 652         int64_t d;
 653         struct timespec ret;
 654 
 655         if (*nt == 0 || *nt == (int64_t)-1) {
 656                 ret.tv_sec = 0;
 657                 ret.tv_nsec = 0;
 658                 return ret;
 659         }
 660 
 661         d = (int64_t)*nt;
 662         /* d is now in 100ns units, since jan 1st 1601".
 663            Save off the ns fraction. */
 664 
 665         /*
 666          * Take the last seven decimal digits and multiply by 100.
 667          * to convert from 100ns units to 1ns units.
 668          */
 669         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
 670 
 671         /* Convert to seconds */
 672         d /= 1000*1000*10;
 673 
 674         /* Now adjust by 369 years to make the secs since 1970 */
 675         d -= TIME_FIXUP_CONSTANT_INT;
 676 
 677         if (d <= (int64_t)TIME_T_MIN) {
 678                 ret.tv_sec = TIME_T_MIN;
 679                 ret.tv_nsec = 0;
 680                 return ret;
 681         }
 682 
 683         if (d >= (int64_t)TIME_T_MAX) {
 684                 ret.tv_sec = TIME_T_MAX;
 685                 ret.tv_nsec = 0;
 686                 return ret;
 687         }
 688 
 689         ret.tv_sec = (time_t)d;
 690         return ret;
 691 }
 692 
 693 
 694 /**
 695   check if 2 NTTIMEs are equal.
 696 */
 697 bool nt_time_equal(NTTIME *t1, NTTIME *t2)
     /* [<][>][^][v][top][bottom][index][help] */
 698 {
 699         return *t1 == *t2;
 700 }
 701 
 702 /**
 703  Check if it's a null timespec.
 704 **/
 705 
 706 bool null_timespec(struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 707 {
 708         return ts.tv_sec == 0 || 
 709                 ts.tv_sec == (time_t)0xFFFFFFFF || 
 710                 ts.tv_sec == (time_t)-1;
 711 }
 712 
 713 

/* [<][>][^][v][top][bottom][index][help] */