/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- make_dos_date1
- make_dos_time1
- make_dos_date
- nttime_from_string
- convert_time_t_to_uint32
- convert_uint32_to_time_t
- nt_time_is_zero
- generalized_to_unix_time
- get_server_zone_offset
- set_server_zone_offset
- current_timestring
- put_dos_date
- put_dos_date2
- put_dos_date3
- srv_put_dos_date
- srv_put_dos_date2
- srv_put_dos_date3
- round_timespec
- put_long_date_timespec
- put_long_date
- calc_create_time
- get_create_timespec
- get_atimespec
- set_atimespec
- get_mtimespec
- set_mtimespec
- get_ctimespec
- set_ctimespec
- dos_filetime_timespec
- make_unix_date
- make_unix_date2
- make_unix_date3
- srv_make_unix_date
- srv_make_unix_date2
- srv_make_unix_date3
- convert_timeval_to_timespec
- convert_timespec_to_timeval
- timespec_current
- timespec_min
- timespec_compare
- round_timespec_to_sec
- round_timespec_to_usec
- interpret_long_date
- cli_put_dos_date
- cli_put_dos_date2
- cli_put_dos_date3
- cli_make_unix_date
- cli_make_unix_date2
- cli_make_unix_date3
- nt_time_equals
- TimeInit
- get_process_uptime
- nt_time_to_unix_abs
- uint64s_nt_time_to_unix_abs
- unix_timespec_to_nt_time
- unix_to_nt_time_abs
- null_mtime
- time_to_asc
- display_time
- 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 }