~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/lib/time.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

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