root/source3/lib/time.c

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

DEFINITIONS

This source file includes following definitions.
  1. make_dos_date1
  2. make_dos_time1
  3. make_dos_date
  4. nttime_from_string
  5. convert_time_t_to_uint32
  6. convert_uint32_to_time_t
  7. nt_time_is_zero
  8. generalized_to_unix_time
  9. get_server_zone_offset
  10. set_server_zone_offset
  11. current_timestring
  12. put_dos_date
  13. put_dos_date2
  14. put_dos_date3
  15. srv_put_dos_date
  16. srv_put_dos_date2
  17. srv_put_dos_date3
  18. round_timespec
  19. put_long_date_timespec
  20. put_long_date
  21. calc_create_time
  22. get_create_timespec
  23. get_atimespec
  24. set_atimespec
  25. get_mtimespec
  26. set_mtimespec
  27. get_ctimespec
  28. set_ctimespec
  29. dos_filetime_timespec
  30. make_unix_date
  31. make_unix_date2
  32. make_unix_date3
  33. srv_make_unix_date
  34. srv_make_unix_date2
  35. srv_make_unix_date3
  36. convert_timeval_to_timespec
  37. convert_timespec_to_timeval
  38. timespec_current
  39. timespec_min
  40. timespec_compare
  41. round_timespec_to_sec
  42. round_timespec_to_usec
  43. interpret_long_date
  44. cli_put_dos_date
  45. cli_put_dos_date2
  46. cli_put_dos_date3
  47. cli_make_unix_date
  48. cli_make_unix_date2
  49. cli_make_unix_date3
  50. nt_time_equals
  51. TimeInit
  52. get_process_uptime
  53. nt_time_to_unix_abs
  54. uint64s_nt_time_to_unix_abs
  55. unix_timespec_to_nt_time
  56. unix_to_nt_time_abs
  57. null_mtime
  58. time_to_asc
  59. display_time
  60. nt_time_is_set

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    time handling functions
   4 
   5    Copyright (C) Andrew Tridgell                1992-2004
   6    Copyright (C) Stefan (metze) Metzmacher      2002   
   7    Copyright (C) Jeremy Allison                 2007
   8 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 
  25 /**
  26  * @file
  27  * @brief time handling functions
  28  */
  29 
  30 
  31 #ifndef TIME_T_MIN
  32 #define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
  33                     : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1))
  34 #endif
  35 #ifndef TIME_T_MAX
  36 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
  37 #endif
  38 
  39 #define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
  40 
  41 #if (SIZEOF_LONG == 8)
  42 #define TIME_FIXUP_CONSTANT_INT 11644473600L
  43 #elif (SIZEOF_LONG_LONG == 8)
  44 #define TIME_FIXUP_CONSTANT_INT 11644473600LL
  45 #endif
  46 
  47 /*******************************************************************
  48   create a 16 bit dos packed date
  49 ********************************************************************/
  50 static uint16_t make_dos_date1(struct tm *t)
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52         uint16_t ret=0;
  53         ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
  54         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
  55         return ret;
  56 }
  57 
  58 /*******************************************************************
  59   create a 16 bit dos packed time
  60 ********************************************************************/
  61 static uint16_t make_dos_time1(struct tm *t)
     /* [<][>][^][v][top][bottom][index][help] */
  62 {
  63         uint16_t ret=0;
  64         ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
  65         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
  66         return ret;
  67 }
  68 
  69 /*******************************************************************
  70   create a 32 bit dos packed date/time from some parameters
  71   This takes a GMT time and returns a packed localtime structure
  72 ********************************************************************/
  73 static uint32_t make_dos_date(time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         struct tm *t;
  76         uint32_t ret=0;
  77 
  78         if (unixdate == 0) {
  79                 return 0;
  80         }
  81 
  82         unixdate -= zone_offset;
  83 
  84         t = gmtime(&unixdate);
  85         if (!t) {
  86                 return 0xFFFFFFFF;
  87         }
  88 
  89         ret = make_dos_date1(t);
  90         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
  91 
  92         return ret;
  93 }
  94 
  95 /**
  96   parse a nttime as a large integer in a string and return a NTTIME
  97 */
  98 NTTIME nttime_from_string(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         return strtoull(s, NULL, 0);
 101 }
 102 
 103 /**************************************************************
 104  Handle conversions between time_t and uint32, taking care to
 105  preserve the "special" values.
 106 **************************************************************/
 107 
 108 uint32_t convert_time_t_to_uint32(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 109 {
 110 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
 111         /* time_t is 64-bit. */
 112         if (t == 0x8000000000000000LL) {
 113                 return 0x80000000;
 114         } else if (t == 0x7FFFFFFFFFFFFFFFLL) {
 115                 return 0x7FFFFFFF;
 116         }
 117 #endif
 118         return (uint32_t)t;
 119 }
 120 
 121 time_t convert_uint32_to_time_t(uint32_t u)
     /* [<][>][^][v][top][bottom][index][help] */
 122 {
 123 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
 124         /* time_t is 64-bit. */
 125         if (u == 0x80000000) {
 126                 return (time_t)0x8000000000000000LL;
 127         } else if (u == 0x7FFFFFFF) {
 128                 return (time_t)0x7FFFFFFFFFFFFFFFLL;
 129         }
 130 #endif
 131         return (time_t)u;
 132 }
 133 
 134 /****************************************************************************
 135  Check if NTTIME is 0.
 136 ****************************************************************************/
 137 
 138 bool nt_time_is_zero(const NTTIME *nt)
     /* [<][>][^][v][top][bottom][index][help] */
 139 {
 140         return (*nt == 0);
 141 }
 142 
 143 /****************************************************************************
 144  Convert ASN.1 GeneralizedTime string to unix-time.
 145  Returns 0 on failure; Currently ignores timezone. 
 146 ****************************************************************************/
 147 
 148 time_t generalized_to_unix_time(const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
 149 { 
 150         struct tm tm;
 151 
 152         ZERO_STRUCT(tm);
 153 
 154         if (sscanf(str, "%4d%2d%2d%2d%2d%2d", 
 155                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
 156                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
 157                 return 0;
 158         }
 159         tm.tm_year -= 1900;
 160         tm.tm_mon -= 1;
 161 
 162         return timegm(&tm);
 163 }
 164 
 165 /*******************************************************************
 166  Accessor function for the server time zone offset.
 167  set_server_zone_offset() must have been called first.
 168 ******************************************************************/
 169 
 170 static int server_zone_offset;
 171 
 172 int get_server_zone_offset(void)
     /* [<][>][^][v][top][bottom][index][help] */
 173 {
 174         return server_zone_offset;
 175 }
 176 
 177 /*******************************************************************
 178  Initialize the server time zone offset. Called when a client connects.
 179 ******************************************************************/
 180 
 181 int set_server_zone_offset(time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 182 {
 183         server_zone_offset = get_time_zone(t);
 184         return server_zone_offset;
 185 }
 186 
 187 /****************************************************************************
 188  Return the date and time as a string
 189 ****************************************************************************/
 190 
 191 char *current_timestring(TALLOC_CTX *ctx, bool hires)
     /* [<][>][^][v][top][bottom][index][help] */
 192 {
 193         fstring TimeBuf;
 194         struct timeval tp;
 195         time_t t;
 196         struct tm *tm;
 197 
 198         if (hires) {
 199                 GetTimeOfDay(&tp);
 200                 t = (time_t)tp.tv_sec;
 201         } else {
 202                 t = time(NULL);
 203         }
 204         tm = localtime(&t);
 205         if (!tm) {
 206                 if (hires) {
 207                         slprintf(TimeBuf,
 208                                  sizeof(TimeBuf)-1,
 209                                  "%ld.%06ld seconds since the Epoch",
 210                                  (long)tp.tv_sec, 
 211                                  (long)tp.tv_usec);
 212                 } else {
 213                         slprintf(TimeBuf,
 214                                  sizeof(TimeBuf)-1,
 215                                  "%ld seconds since the Epoch",
 216                                  (long)t);
 217                 }
 218         } else {
 219 #ifdef HAVE_STRFTIME
 220                 if (hires) {
 221                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
 222                         slprintf(TimeBuf+strlen(TimeBuf),
 223                                  sizeof(TimeBuf)-1 - strlen(TimeBuf), 
 224                                  ".%06ld", 
 225                                  (long)tp.tv_usec);
 226                 } else {
 227                         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
 228                 }
 229 #else
 230                 if (hires) {
 231                         const char *asct = asctime(tm);
 232                         slprintf(TimeBuf, 
 233                                  sizeof(TimeBuf)-1, 
 234                                  "%s.%06ld", 
 235                                  asct ? asct : "unknown", 
 236                                  (long)tp.tv_usec);
 237                 } else {
 238                         const char *asct = asctime(tm);
 239                         fstrcpy(TimeBuf, asct ? asct : "unknown");
 240                 }
 241 #endif
 242         }
 243         return talloc_strdup(ctx, TimeBuf);
 244 }
 245 
 246 
 247 /*******************************************************************
 248  Put a dos date into a buffer (time/date format).
 249  This takes GMT time and puts local time in the buffer.
 250 ********************************************************************/
 251 
 252 static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 253 {
 254         uint32_t x = make_dos_date(unixdate, zone_offset);
 255         SIVAL(buf,offset,x);
 256 }
 257 
 258 /*******************************************************************
 259  Put a dos date into a buffer (date/time format).
 260  This takes GMT time and puts local time in the buffer.
 261 ********************************************************************/
 262 
 263 static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 264 {
 265         uint32_t x = make_dos_date(unixdate, zone_offset);
 266         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 267         SIVAL(buf,offset,x);
 268 }
 269 
 270 /*******************************************************************
 271  Put a dos 32 bit "unix like" date into a buffer. This routine takes
 272  GMT and converts it to LOCAL time before putting it (most SMBs assume
 273  localtime for this sort of date)
 274 ********************************************************************/
 275 
 276 static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 277 {
 278         if (!null_mtime(unixdate)) {
 279                 unixdate -= zone_offset;
 280         }
 281         SIVAL(buf,offset,unixdate);
 282 }
 283 
 284 
 285 /***************************************************************************
 286  Server versions of the above functions.
 287 ***************************************************************************/
 288 
 289 void srv_put_dos_date(char *buf,int offset,time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 290 {
 291         put_dos_date(buf, offset, unixdate, server_zone_offset);
 292 }
 293 
 294 void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 295 {
 296         put_dos_date2(buf, offset, unixdate, server_zone_offset);
 297 }
 298 
 299 void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 300 {
 301         put_dos_date3(buf, offset, unixdate, server_zone_offset);
 302 }
 303 
 304 void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
     /* [<][>][^][v][top][bottom][index][help] */
 305 {
 306         switch (res) {
 307                 case TIMESTAMP_SET_SECONDS:
 308                         round_timespec_to_sec(ts);
 309                         break;
 310                 case TIMESTAMP_SET_MSEC:
 311                         round_timespec_to_usec(ts);
 312                         break;
 313                 case TIMESTAMP_SET_NT_OR_BETTER:
 314                         /* No rounding needed. */
 315                         break;
 316         }
 317 }
 318 
 319 /****************************************************************************
 320  Take a Unix time and convert to an NTTIME structure and place in buffer 
 321  pointed to by p.
 322 ****************************************************************************/
 323 
 324 void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 325 {
 326         NTTIME nt;
 327         round_timespec(res, &ts);
 328         unix_timespec_to_nt_time(&nt, ts);
 329         SIVAL(p, 0, nt & 0xFFFFFFFF);
 330         SIVAL(p, 4, nt >> 32);
 331 }
 332 
 333 void put_long_date(char *p, time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 334 {
 335         struct timespec ts;
 336         ts.tv_sec = t;
 337         ts.tv_nsec = 0;
 338         put_long_date_timespec(TIMESTAMP_SET_SECONDS, p, ts);
 339 }
 340 
 341 /****************************************************************************
 342  Return the best approximation to a 'create time' under UNIX from a stat
 343  structure.
 344 ****************************************************************************/
 345 
 346 static time_t calc_create_time(const SMB_STRUCT_STAT *st)
     /* [<][>][^][v][top][bottom][index][help] */
 347 {
 348         time_t ret, ret1;
 349 
 350         ret = MIN(st->st_ctime, st->st_mtime);
 351         ret1 = MIN(ret, st->st_atime);
 352 
 353         if(ret1 != (time_t)0) {
 354                 return ret1;
 355         }
 356 
 357         /*
 358          * One of ctime, mtime or atime was zero (probably atime).
 359          * Just return MIN(ctime, mtime).
 360          */
 361         return ret;
 362 }
 363 
 364 /****************************************************************************
 365  Return the 'create time' from a stat struct if it exists (birthtime) or else
 366  use the best approximation.
 367 ****************************************************************************/
 368 
 369 struct timespec get_create_timespec(const SMB_STRUCT_STAT *pst,bool fake_dirs)
     /* [<][>][^][v][top][bottom][index][help] */
 370 {
 371         struct timespec ret;
 372 
 373         if(S_ISDIR(pst->st_mode) && fake_dirs) {
 374                 ret.tv_sec = 315493200L;          /* 1/1/1980 */
 375                 ret.tv_nsec = 0;
 376                 return ret;
 377         }
 378 
 379 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
 380         ret = pst->st_birthtimespec;
 381 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
 382         ret.tv_sec = pst->st_birthtime;
 383         ret.tv_nsec = pst->st_birthtimenspec;
 384 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
 385         ret.tv_sec = pst->st_birthtime;
 386         ret.tv_nsec = 0;
 387 #else
 388         ret.tv_sec = calc_create_time(pst);
 389         ret.tv_nsec = 0;
 390 #endif
 391 
 392         /* Deal with systems that don't initialize birthtime correctly.
 393          * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
 394          */
 395         if (null_timespec(ret)) {
 396                 ret.tv_sec = calc_create_time(pst);
 397                 ret.tv_nsec = 0;
 398         }
 399         return ret;
 400 }
 401 
 402 /****************************************************************************
 403  Get/Set all the possible time fields from a stat struct as a timespec.
 404 ****************************************************************************/
 405 
 406 struct timespec get_atimespec(const SMB_STRUCT_STAT *pst)
     /* [<][>][^][v][top][bottom][index][help] */
 407 {
 408 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 409         struct timespec ret;
 410 
 411         /* Old system - no ns timestamp. */
 412         ret.tv_sec = pst->st_atime;
 413         ret.tv_nsec = 0;
 414         return ret;
 415 #else
 416 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 417         return pst->st_atim;
 418 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 419         struct timespec ret;
 420         ret.tv_sec = pst->st_atime;
 421         ret.tv_nsec = pst->st_atimensec;
 422         return ret;
 423 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 424         struct timespec ret;
 425         ret.tv_sec = pst->st_atime;
 426         ret.tv_nsec = pst->st_atime_n;
 427         return ret;
 428 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 429         struct timespec ret;
 430         ret.tv_sec = pst->st_atime;
 431         ret.tv_nsec = pst->st_uatime * 1000;
 432         return ret;
 433 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 434         return pst->st_atimespec;
 435 #else
 436 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 437 #endif
 438 #endif
 439 }
 440 
 441 void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 442 {
 443 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 444         /* Old system - no ns timestamp. */
 445         pst->st_atime = ts.tv_sec;
 446 #else
 447 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 448         pst->st_atim = ts;
 449 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 450         pst->st_atime = ts.tv_sec;
 451         pst->st_atimensec = ts.tv_nsec;
 452 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 453         pst->st_atime = ts.tv_sec;
 454         pst->st_atime_n = ts.tv_nsec;
 455 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 456         pst->st_atime = ts.tv_sec;
 457         pst->st_uatime = ts.tv_nsec / 1000;
 458 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 459         pst->st_atimespec = ts;
 460 #else
 461 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 462 #endif
 463 #endif
 464 }
 465 
 466 struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst)
     /* [<][>][^][v][top][bottom][index][help] */
 467 {
 468 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 469         struct timespec ret;
 470 
 471         /* Old system - no ns timestamp. */
 472         ret.tv_sec = pst->st_mtime;
 473         ret.tv_nsec = 0;
 474         return ret;
 475 #else
 476 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 477         return pst->st_mtim;
 478 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 479         struct timespec ret;
 480         ret.tv_sec = pst->st_mtime;
 481         ret.tv_nsec = pst->st_mtimensec;
 482         return ret;
 483 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 484         struct timespec ret;
 485         ret.tv_sec = pst->st_mtime;
 486         ret.tv_nsec = pst->st_mtime_n;
 487         return ret;
 488 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 489         struct timespec ret;
 490         ret.tv_sec = pst->st_mtime;
 491         ret.tv_nsec = pst->st_umtime * 1000;
 492         return ret;
 493 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 494         return pst->st_mtimespec;
 495 #else
 496 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 497 #endif
 498 #endif
 499 }
 500 
 501 void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 502 {
 503 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 504         /* Old system - no ns timestamp. */
 505         pst->st_mtime = ts.tv_sec;
 506 #else
 507 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 508         pst->st_mtim = ts;
 509 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 510         pst->st_mtime = ts.tv_sec;
 511         pst->st_mtimensec = ts.tv_nsec;
 512 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 513         pst->st_mtime = ts.tv_sec;
 514         pst->st_mtime_n = ts.tv_nsec;
 515 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 516         pst->st_mtime = ts.tv_sec;
 517         pst->st_umtime = ts.tv_nsec / 1000;
 518 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 519         pst->st_mtimespec = ts;
 520 #else
 521 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 522 #endif
 523 #endif
 524 }
 525 
 526 struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst)
     /* [<][>][^][v][top][bottom][index][help] */
 527 {
 528 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 529         struct timespec ret;
 530 
 531         /* Old system - no ns timestamp. */
 532         ret.tv_sec = pst->st_ctime;
 533         ret.tv_nsec = 0;
 534         return ret;
 535 #else
 536 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 537         return pst->st_ctim;
 538 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 539         struct timespec ret;
 540         ret.tv_sec = pst->st_ctime;
 541         ret.tv_nsec = pst->st_ctimensec;
 542         return ret;
 543 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 544         struct timespec ret;
 545         ret.tv_sec = pst->st_ctime;
 546         ret.tv_nsec = pst->st_ctime_n;
 547         return ret;
 548 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 549         struct timespec ret;
 550         ret.tv_sec = pst->st_ctime;
 551         ret.tv_nsec = pst->st_uctime * 1000;
 552         return ret;
 553 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 554         return pst->st_ctimespec;
 555 #else
 556 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 557 #endif
 558 #endif
 559 }
 560 
 561 void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 562 {
 563 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
 564         /* Old system - no ns timestamp. */
 565         pst->st_ctime = ts.tv_sec;
 566 #else
 567 #if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
 568         pst->st_ctim = ts;
 569 #elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
 570         pst->st_ctime = ts.tv_sec;
 571         pst->st_ctimensec = ts.tv_nsec;
 572 #elif defined(HAVE_STRUCT_STAT_ST_MTIME_N)
 573         pst->st_ctime = ts.tv_sec;
 574         pst->st_ctime_n = ts.tv_nsec;
 575 #elif defined(HAVE_STRUCT_STAT_ST_UMTIME)
 576         pst->st_ctime = ts.tv_sec;
 577         pst->st_uctime = ts.tv_nsec / 1000;
 578 #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
 579         pst->st_ctimespec = ts;
 580 #else
 581 #error  CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT 
 582 #endif
 583 #endif
 584 }
 585 
 586 void dos_filetime_timespec(struct timespec *tsp)
     /* [<][>][^][v][top][bottom][index][help] */
 587 {
 588         tsp->tv_sec &= ~1;
 589         tsp->tv_nsec = 0;
 590 }
 591 
 592 /*******************************************************************
 593  Create a unix date (int GMT) from a dos date (which is actually in
 594  localtime).
 595 ********************************************************************/
 596 
 597 static time_t make_unix_date(const void *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 598 {
 599         uint32_t dos_date=0;
 600         struct tm t;
 601         time_t ret;
 602 
 603         dos_date = IVAL(date_ptr,0);
 604 
 605         if (dos_date == 0) {
 606                 return 0;
 607         }
 608   
 609         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
 610                         &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
 611         t.tm_isdst = -1;
 612   
 613         ret = timegm(&t);
 614 
 615         ret += zone_offset;
 616 
 617         return(ret);
 618 }
 619 
 620 /*******************************************************************
 621  Like make_unix_date() but the words are reversed.
 622 ********************************************************************/
 623 
 624 static time_t make_unix_date2(const void *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 625 {
 626         uint32_t x,x2;
 627 
 628         x = IVAL(date_ptr,0);
 629         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 630         SIVAL(&x,0,x2);
 631 
 632         return(make_unix_date((const void *)&x, zone_offset));
 633 }
 634 
 635 /*******************************************************************
 636  Create a unix GMT date from a dos date in 32 bit "unix like" format
 637  these generally arrive as localtimes, with corresponding DST.
 638 ******************************************************************/
 639 
 640 static time_t make_unix_date3(const void *date_ptr, int zone_offset)
     /* [<][>][^][v][top][bottom][index][help] */
 641 {
 642         time_t t = (time_t)IVAL(date_ptr,0);
 643         if (!null_mtime(t)) {
 644                 t += zone_offset;
 645         }
 646         return(t);
 647 }
 648 
 649 time_t srv_make_unix_date(const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 650 {
 651         return make_unix_date(date_ptr, server_zone_offset);
 652 }
 653 
 654 time_t srv_make_unix_date2(const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 655 {
 656         return make_unix_date2(date_ptr, server_zone_offset);
 657 }
 658 
 659 time_t srv_make_unix_date3(const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 660 {
 661         return make_unix_date3(date_ptr, server_zone_offset);
 662 }
 663 
 664 /****************************************************************************
 665  Convert a normalized timeval to a timespec.
 666 ****************************************************************************/
 667 
 668 struct timespec convert_timeval_to_timespec(const struct timeval tv)
     /* [<][>][^][v][top][bottom][index][help] */
 669 {
 670         struct timespec ts;
 671         ts.tv_sec = tv.tv_sec;
 672         ts.tv_nsec = tv.tv_usec * 1000;
 673         return ts;
 674 }
 675 
 676 /****************************************************************************
 677  Convert a normalized timespec to a timeval.
 678 ****************************************************************************/
 679 
 680 struct timeval convert_timespec_to_timeval(const struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 681 {
 682         struct timeval tv;
 683         tv.tv_sec = ts.tv_sec;
 684         tv.tv_usec = ts.tv_nsec / 1000;
 685         return tv;
 686 }
 687 
 688 /****************************************************************************
 689  Return a timespec for the current time
 690 ****************************************************************************/
 691 
 692 struct timespec timespec_current(void)
     /* [<][>][^][v][top][bottom][index][help] */
 693 {
 694         struct timeval tv;
 695         struct timespec ts;
 696         GetTimeOfDay(&tv);
 697         ts.tv_sec = tv.tv_sec;
 698         ts.tv_nsec = tv.tv_usec * 1000;
 699         return ts;
 700 }
 701 
 702 /****************************************************************************
 703  Return the lesser of two timespecs.
 704 ****************************************************************************/
 705 
 706 struct timespec timespec_min(const struct timespec *ts1,
     /* [<][>][^][v][top][bottom][index][help] */
 707                            const struct timespec *ts2)
 708 {
 709         if (ts1->tv_sec < ts2->tv_sec) return *ts1;
 710         if (ts1->tv_sec > ts2->tv_sec) return *ts2;
 711         if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
 712         return *ts2;
 713 }
 714 
 715 /****************************************************************************
 716   compare two timespec structures. 
 717   Return -1 if ts1 < ts2
 718   Return 0 if ts1 == ts2
 719   Return 1 if ts1 > ts2
 720 ****************************************************************************/
 721 
 722 int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
     /* [<][>][^][v][top][bottom][index][help] */
 723 {
 724         if (ts1->tv_sec  > ts2->tv_sec)  return 1;
 725         if (ts1->tv_sec  < ts2->tv_sec)  return -1;
 726         if (ts1->tv_nsec > ts2->tv_nsec) return 1;
 727         if (ts1->tv_nsec < ts2->tv_nsec) return -1;
 728         return 0;
 729 }
 730 
 731 /****************************************************************************
 732  Round up a timespec if nsec > 500000000, round down if lower,
 733  then zero nsec.
 734 ****************************************************************************/
 735 
 736 void round_timespec_to_sec(struct timespec *ts)
     /* [<][>][^][v][top][bottom][index][help] */
 737 {
 738         ts->tv_sec = convert_timespec_to_time_t(*ts);
 739         ts->tv_nsec = 0;
 740 }
 741 
 742 /****************************************************************************
 743  Round a timespec to usec value.
 744 ****************************************************************************/
 745 
 746 void round_timespec_to_usec(struct timespec *ts)
     /* [<][>][^][v][top][bottom][index][help] */
 747 {
 748         struct timeval tv = convert_timespec_to_timeval(*ts);
 749         *ts = convert_timeval_to_timespec(tv);
 750 }
 751 
 752 /****************************************************************************
 753  Interprets an nt time into a unix struct timespec.
 754  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
 755  will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
 756 ****************************************************************************/
 757 
 758 struct timespec interpret_long_date(const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
 759 {
 760         NTTIME nt;
 761         nt = IVAL(p,0) + ((uint64_t)IVAL(p,4) << 32);
 762         if (nt == (uint64_t)-1) {
 763                 struct timespec ret;
 764                 ret.tv_sec = (time_t)-1;
 765                 ret.tv_nsec = 0;
 766                 return ret;
 767         }
 768         return nt_time_to_unix_timespec(&nt);
 769 }
 770 
 771 /***************************************************************************
 772  Client versions of the above functions.
 773 ***************************************************************************/
 774 
 775 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 776 {
 777         put_dos_date(buf, offset, unixdate, cli->serverzone);
 778 }
 779 
 780 void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 781 {
 782         put_dos_date2(buf, offset, unixdate, cli->serverzone);
 783 }
 784 
 785 void cli_put_dos_date3(struct cli_state *cli, char *buf, int offset, time_t unixdate)
     /* [<][>][^][v][top][bottom][index][help] */
 786 {
 787         put_dos_date3(buf, offset, unixdate, cli->serverzone);
 788 }
 789 
 790 time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 791 {
 792         return make_unix_date(date_ptr, cli->serverzone);
 793 }
 794 
 795 time_t cli_make_unix_date2(struct cli_state *cli, const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 796 {
 797         return make_unix_date2(date_ptr, cli->serverzone);
 798 }
 799 
 800 time_t cli_make_unix_date3(struct cli_state *cli, const void *date_ptr)
     /* [<][>][^][v][top][bottom][index][help] */
 801 {
 802         return make_unix_date3(date_ptr, cli->serverzone);
 803 }
 804 
 805 /****************************************************************************
 806  Check if two NTTIMEs are the same.
 807 ****************************************************************************/
 808 
 809 bool nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
     /* [<][>][^][v][top][bottom][index][help] */
 810 {
 811         return (*nt1 == *nt2);
 812 }
 813 
 814 /*******************************************************************
 815  Re-read the smb serverzone value.
 816 ******************************************************************/
 817 
 818 static struct timeval start_time_hires;
 819 
 820 void TimeInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 821 {
 822         set_server_zone_offset(time(NULL));
 823 
 824         DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
 825 
 826         /* Save the start time of this process. */
 827         if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
 828                 GetTimeOfDay(&start_time_hires);
 829         }
 830 }
 831 
 832 /**********************************************************************
 833  Return a timeval struct of the uptime of this process. As TimeInit is
 834  done before a daemon fork then this is the start time from the parent
 835  daemon start. JRA.
 836 ***********************************************************************/
 837 
 838 void get_process_uptime(struct timeval *ret_time)
     /* [<][>][^][v][top][bottom][index][help] */
 839 {
 840         struct timeval time_now_hires;
 841 
 842         GetTimeOfDay(&time_now_hires);
 843         ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
 844         if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
 845                 ret_time->tv_sec -= 1;
 846                 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
 847         } else {
 848                 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
 849         }
 850 }
 851 
 852 /****************************************************************************
 853  Convert a NTTIME structure to a time_t.
 854  It's originally in "100ns units".
 855 
 856  This is an absolute version of the one above.
 857  By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
 858  if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
 859 ****************************************************************************/
 860 
 861 time_t nt_time_to_unix_abs(const NTTIME *nt)
     /* [<][>][^][v][top][bottom][index][help] */
 862 {
 863         uint64_t d;
 864 
 865         if (*nt == 0) {
 866                 return (time_t)0;
 867         }
 868 
 869         if (*nt == (uint64_t)-1) {
 870                 return (time_t)-1;
 871         }
 872 
 873         if (*nt == NTTIME_INFINITY) {
 874                 return (time_t)-1;
 875         }
 876 
 877         /* reverse the time */
 878         /* it's a negative value, turn it to positive */
 879         d=~*nt;
 880 
 881         d += 1000*1000*10/2;
 882         d /= 1000*1000*10;
 883 
 884         if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
 885                 return (time_t)0;
 886         }
 887 
 888         return (time_t)d;
 889 }
 890 
 891 time_t uint64s_nt_time_to_unix_abs(const uint64_t *src)
     /* [<][>][^][v][top][bottom][index][help] */
 892 {
 893         NTTIME nttime;
 894         nttime = *src;
 895         return nt_time_to_unix_abs(&nttime);
 896 }
 897 
 898 /****************************************************************************
 899  Put a 8 byte filetime from a struct timespec. Uses GMT.
 900 ****************************************************************************/
 901 
 902 void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
     /* [<][>][^][v][top][bottom][index][help] */
 903 {
 904         uint64_t d;
 905 
 906         if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
 907                 *nt = 0;
 908                 return;
 909         }
 910         if (ts.tv_sec == TIME_T_MAX) {
 911                 *nt = 0x7fffffffffffffffLL;
 912                 return;
 913         }               
 914         if (ts.tv_sec == (time_t)-1) {
 915                 *nt = (uint64_t)-1;
 916                 return;
 917         }               
 918 
 919         d = ts.tv_sec;
 920         d += TIME_FIXUP_CONSTANT_INT;
 921         d *= 1000*1000*10;
 922         /* d is now in 100ns units. */
 923         d += (ts.tv_nsec / 100);
 924 
 925         *nt = d;
 926 }
 927 
 928 /****************************************************************************
 929  Convert a time_t to a NTTIME structure
 930 
 931  This is an absolute version of the one above.
 932  By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
 933  If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM
 934 ****************************************************************************/
 935 
 936 void unix_to_nt_time_abs(NTTIME *nt, time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 937 {
 938         double d;
 939 
 940         if (t==0) {
 941                 *nt = 0;
 942                 return;
 943         }
 944 
 945         if (t == TIME_T_MAX) {
 946                 *nt = 0x7fffffffffffffffLL;
 947                 return;
 948         }
 949                 
 950         if (t == (time_t)-1) {
 951                 /* that's what NT uses for infinite */
 952                 *nt = NTTIME_INFINITY;
 953                 return;
 954         }               
 955 
 956         d = (double)(t);
 957         d *= 1.0e7;
 958 
 959         *nt = (NTTIME)d;
 960 
 961         /* convert to a negative value */
 962         *nt=~*nt;
 963 }
 964 
 965 
 966 /****************************************************************************
 967  Check if it's a null mtime.
 968 ****************************************************************************/
 969 
 970 bool null_mtime(time_t mtime)
     /* [<][>][^][v][top][bottom][index][help] */
 971 {
 972         if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
 973                 return true;
 974         return false;
 975 }
 976 
 977 /****************************************************************************
 978  Utility function that always returns a const string even if localtime
 979  and asctime fail.
 980 ****************************************************************************/
 981 
 982 const char *time_to_asc(const time_t t)
     /* [<][>][^][v][top][bottom][index][help] */
 983 {
 984         const char *asct;
 985         struct tm *lt = localtime(&t);
 986 
 987         if (!lt) {
 988                 return "unknown time";
 989         }
 990 
 991         asct = asctime(lt);
 992         if (!asct) {
 993                 return "unknown time";
 994         }
 995         return asct;
 996 }
 997 
 998 const char *display_time(NTTIME nttime)
     /* [<][>][^][v][top][bottom][index][help] */
 999 {
1000         float high;
1001         float low;
1002         int sec;
1003         int days, hours, mins, secs;
1004 
1005         if (nttime==0)
1006                 return "Now";
1007 
1008         if (nttime==NTTIME_INFINITY)
1009                 return "Never";
1010 
1011         high = 65536;   
1012         high = high/10000;
1013         high = high*65536;
1014         high = high/1000;
1015         high = high * (~(nttime >> 32));
1016 
1017         low = ~(nttime & 0xFFFFFFFF);
1018         low = low/(1000*1000*10);
1019 
1020         sec=(int)(high+low);
1021 
1022         days=sec/(60*60*24);
1023         hours=(sec - (days*60*60*24)) / (60*60);
1024         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
1025         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
1026 
1027         return talloc_asprintf(talloc_tos(), "%u days, %u hours, %u minutes, "
1028                                "%u seconds", days, hours, mins, secs);
1029 }
1030 
1031 bool nt_time_is_set(const NTTIME *nt)
     /* [<][>][^][v][top][bottom][index][help] */
1032 {
1033         if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
1034                 return false;
1035         }
1036 
1037         if (*nt == NTTIME_INFINITY) {
1038                 return false;
1039         }
1040 
1041         return true;
1042 }

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