1996-05-31 19:13:29 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-31 19:13:29 +04:00
time handling functions
2002-09-26 22:58:34 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Stefan ( metze ) Metzmacher 2002
1996-05-31 19:13:29 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
/*
This stuff was largely rewritten by Paul Eggert < eggert @ twinsun . com >
in May 1996
*/
int extra_time_offset = 0 ;
# ifndef CHAR_BIT
# define CHAR_BIT 8
# endif
# ifndef TIME_T_MIN
1997-03-07 20:22:27 +03:00
# define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
1996-05-31 19:13:29 +04:00
: ~ ( time_t ) 0 < < ( sizeof ( time_t ) * CHAR_BIT - 1 ) )
# endif
# ifndef TIME_T_MAX
# define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
# endif
2001-10-02 10:57:18 +04:00
/*******************************************************************
External access to time_t_min and time_t_max .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-31 19:13:29 +04:00
2001-10-02 10:57:18 +04:00
time_t get_time_t_max ( void )
{
return TIME_T_MAX ;
}
1996-05-31 19:13:29 +04:00
/*******************************************************************
2005-02-11 22:31:48 +03:00
A gettimeofday wrapper .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1996-05-31 19:13:29 +04:00
void GetTimeOfDay ( struct timeval * tval )
{
1998-07-29 07:08:05 +04:00
# ifdef HAVE_GETTIMEOFDAY_TZ
gettimeofday ( tval , NULL ) ;
1996-05-31 19:13:29 +04:00
# else
1998-07-29 07:08:05 +04:00
gettimeofday ( tval ) ;
1996-05-31 19:13:29 +04:00
# endif
}
# define TM_YEAR_BASE 1900
/*******************************************************************
2005-02-11 22:31:48 +03:00
Yield the difference between * A and * B , in seconds , ignoring leap seconds .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1996-05-31 19:13:29 +04:00
static int tm_diff ( struct tm * a , struct tm * b )
{
2005-02-11 22:31:48 +03:00
int ay = a - > tm_year + ( TM_YEAR_BASE - 1 ) ;
int by = b - > tm_year + ( TM_YEAR_BASE - 1 ) ;
int intervening_leap_days = ( ay / 4 - by / 4 ) - ( ay / 100 - by / 100 ) + ( ay / 400 - by / 400 ) ;
int years = ay - by ;
int days = 365 * years + intervening_leap_days + ( a - > tm_yday - b - > tm_yday ) ;
int hours = 24 * days + ( a - > tm_hour - b - > tm_hour ) ;
int minutes = 60 * hours + ( a - > tm_min - b - > tm_min ) ;
int seconds = 60 * minutes + ( a - > tm_sec - b - > tm_sec ) ;
1997-11-21 07:57:37 +03:00
2005-02-11 22:31:48 +03:00
return seconds ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Return the UTC offset in seconds west of UTC , or 0 if it cannot be determined .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-11-05 07:21:55 +03:00
int get_time_zone ( time_t t )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
struct tm * tm = gmtime ( & t ) ;
struct tm tm_utc ;
2005-11-05 07:21:55 +03:00
if ( ! tm ) {
2005-02-11 22:31:48 +03:00
return 0 ;
2005-11-05 07:21:55 +03:00
}
2005-02-11 22:31:48 +03:00
tm_utc = * tm ;
tm = localtime ( & t ) ;
2005-11-05 07:21:55 +03:00
if ( ! tm ) {
2005-02-11 22:31:48 +03:00
return 0 ;
2005-11-05 07:21:55 +03:00
}
2005-11-06 04:55:09 +03:00
return tm_diff ( & tm_utc , tm ) + 60 * extra_time_offset ;
1996-05-31 19:13:29 +04:00
}
2005-02-11 22:31:48 +03:00
/*******************************************************************
2005-11-05 07:21:55 +03:00
Accessor function for the server time zone offset .
set_server_zone_offset ( ) must have been called first .
2005-02-11 22:31:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-23 03:52:29 +03:00
2005-11-05 07:21:55 +03:00
static int server_zone_offset ;
1997-12-03 06:46:43 +03:00
2005-11-05 07:21:55 +03:00
int get_server_zone_offset ( void )
{
return server_zone_offset ;
}
2001-11-23 03:52:29 +03:00
2005-11-05 07:21:55 +03:00
/*******************************************************************
Initialize the server time zone offset . Called when a client connects .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-23 03:52:29 +03:00
2005-11-05 07:21:55 +03:00
int set_server_zone_offset ( time_t t )
{
server_zone_offset = get_time_zone ( t ) ;
return server_zone_offset ;
1996-05-31 19:13:29 +04:00
}
2005-02-11 22:31:48 +03:00
/*******************************************************************
Re - read the smb serverzone value .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-23 03:52:29 +03:00
2002-01-12 00:52:46 +03:00
static struct timeval start_time_hires ;
2001-11-23 03:52:29 +03:00
void TimeInit ( void )
{
2005-11-05 07:21:55 +03:00
set_server_zone_offset ( time ( NULL ) ) ;
DEBUG ( 4 , ( " TimeInit: Serverzone is %d \n " , server_zone_offset ) ) ;
2002-01-12 00:52:46 +03:00
/* Save the start time of this process. */
2005-11-05 07:21:55 +03:00
if ( start_time_hires . tv_sec = = 0 & & start_time_hires . tv_usec = = 0 ) {
2002-01-12 02:33:12 +03:00
GetTimeOfDay ( & start_time_hires ) ;
2005-11-05 07:21:55 +03:00
}
2002-01-12 00:52:46 +03:00
}
/**********************************************************************
Return a timeval struct of the uptime of this process . As TimeInit is
done before a daemon fork then this is the start time from the parent
daemon start . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void get_process_uptime ( struct timeval * ret_time )
{
struct timeval time_now_hires ;
GetTimeOfDay ( & time_now_hires ) ;
ret_time - > tv_sec = time_now_hires . tv_sec - start_time_hires . tv_sec ;
if ( time_now_hires . tv_usec < start_time_hires . tv_usec ) {
ret_time - > tv_sec - = 1 ;
ret_time - > tv_usec = 1000000 + ( time_now_hires . tv_usec - start_time_hires . tv_usec ) ;
2005-02-11 22:31:48 +03:00
} else {
2005-11-05 07:21:55 +03:00
ret_time - > tv_usec = time_now_hires . tv_usec - start_time_hires . tv_usec ;
2005-02-11 22:31:48 +03:00
}
1996-05-31 19:13:29 +04:00
}
2005-11-05 07:21:55 +03:00
#if 0
1996-05-31 19:13:29 +04:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Return the UTC offset in seconds west of UTC , adjusted for extra time offset .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-31 19:13:29 +04:00
int TimeDiff ( time_t t )
{
2005-11-05 07:21:55 +03:00
return get_time_zone ( t ) ;
1996-05-31 19:13:29 +04:00
}
2005-11-05 07:21:55 +03:00
# endif
1996-05-31 19:13:29 +04:00
2006-08-24 20:44:00 +04:00
time_t convert_timespec_to_time_t ( struct timespec ts )
{
/* 1 ns == 1,000,000,000 - one thousand millionths of a second.
increment if it ' s greater than 500 millionth of a second . */
if ( ts . tv_nsec > 500000000 ) {
return ts . tv_sec + 1 ;
}
return ts . tv_sec ;
}
struct timespec convert_time_t_to_timespec ( time_t t )
{
struct timespec ts ;
ts . tv_sec = t ;
ts . tv_nsec = 0 ;
return ts ;
}
2006-08-25 00:51:57 +04:00
# ifdef uint64
# if (SIZEOF_LONG == 8)
# define TIME_FIXUP_CONSTANT_INT 11644473600L
# elif (SIZEOF_LONG_LONG == 8)
# define TIME_FIXUP_CONSTANT_INT 11644473600LL
# endif
1996-05-31 19:13:29 +04:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Interpret an 8 byte " filetime " structure to a time_t
It ' s originally in " 100ns units since jan 1st 1601 "
1996-05-31 19:13:29 +04:00
2006-08-24 20:44:00 +04:00
An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
tv_sec = 0
tv_nsec = 0 ;
2005-02-11 23:00:30 +03:00
2005-11-05 07:21:55 +03:00
Returns GMT .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2006-08-25 00:51:57 +04:00
/* Large integer version. */
static struct timespec nt_time_to_unix_timespec ( NTTIME * nt )
{
uint64 d ;
struct timespec ret ;
if ( ( nt - > high = = 0 & & nt - > low = = 0 ) | |
( nt - > high = = 0xffffffff & & nt - > low = = 0xffffffff ) ) {
ret . tv_sec = 0 ;
ret . tv_nsec = 0 ;
return ret ;
}
d = ( ( ( uint64 ) nt - > high ) < < 32 ) + ( ( uint64 ) nt - > low ) ;
/* d is now in 100ns units, since jan 1st 1601".
Save off the ns fraction . */
ret . tv_nsec = ( long ) ( ( d % 100 ) * 100 ) ;
/* Convert to seconds */
d / = 1000 * 1000 * 10 ;
/* Now adjust by 369 years to make the secs since 1970 */
d - = TIME_FIXUP_CONSTANT_INT ;
2006-08-25 01:37:10 +04:00
if ( ( ( time_t ) d ) < = TIME_T_MIN ) {
2006-08-25 00:51:57 +04:00
ret . tv_sec = TIME_T_MIN ;
ret . tv_nsec = 0 ;
return ret ;
}
2006-08-25 01:37:10 +04:00
if ( ( ( time_t ) d ) > = TIME_T_MAX ) {
2006-08-25 00:51:57 +04:00
ret . tv_sec = TIME_T_MAX ;
ret . tv_nsec = 0 ;
return ret ;
}
ret . tv_sec = ( time_t ) d ;
return ret ;
}
/****************************************************************************
Convert a NTTIME structure to a time_t .
It ' s originally in " 100ns units " .
This is an absolute version of the one above .
By absolute I mean , it doesn ' t adjust from 1 / 1 / 1601 to 1 / 1 / 1970
if the NTTIME was 5 seconds , the time_t is 5 seconds . JFM
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
time_t nt_time_to_unix_abs ( const NTTIME * nt )
{
uint64 d ;
NTTIME neg_nt ;
if ( nt - > high = = 0 ) {
return ( time_t ) 0 ;
}
if ( nt - > high = = 0x80000000 & & nt - > low = = 0 ) {
return ( time_t ) - 1 ;
}
/* reverse the time */
/* it's a negative value, turn it to positive */
neg_nt . high = ~ nt - > high ;
neg_nt . low = ~ nt - > low ;
d = ( ( ( uint64 ) neg_nt . high ) < < 32 ) + ( ( uint64 ) neg_nt . low ) ;
d + = 1000 * 1000 * 10 / 2 ;
d / = 1000 * 1000 * 10 ;
2006-08-25 01:37:10 +04:00
if ( ! ( TIME_T_MIN < = ( ( time_t ) d ) & & ( ( time_t ) d ) < = TIME_T_MAX ) ) {
2006-08-25 00:51:57 +04:00
return ( time_t ) 0 ;
}
return ( time_t ) d ;
}
/****************************************************************************
Put a 8 byte filetime from a struct timespec . Uses GMT .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void unix_timespec_to_nt_time ( NTTIME * nt , struct timespec ts )
{
uint64 d ;
if ( ts . tv_sec = = 0 & & ts . tv_nsec = = 0 ) {
nt - > low = 0 ;
nt - > high = 0 ;
return ;
}
if ( ts . tv_sec = = TIME_T_MAX ) {
nt - > low = 0xffffffff ;
nt - > high = 0x7fffffff ;
return ;
}
if ( ts . tv_sec = = ( time_t ) - 1 ) {
nt - > low = 0xffffffff ;
nt - > high = 0xffffffff ;
return ;
}
d = ts . tv_sec ;
d + = TIME_FIXUP_CONSTANT_INT ;
d = ts . tv_sec * 1000 * 1000 * 10 ;
/* d is now in 100ns units. */
d + = ( ts . tv_nsec / 100 ) ;
nt - > high = ( uint32 ) ( d / 1000 * 1000 * 10 ) ;
nt - > low = ( uint32 ) ( d % 1000 * 1000 * 10 ) ;
}
# else
/* No 64-bit datatype. Use double float. */
# define TIME_FIXUP_CONSTANT_DOUBLE (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
/* Floating point double versions. */
2006-08-24 20:44:00 +04:00
static struct timespec nt_time_to_unix_timespec ( NTTIME * nt )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
double d ;
2006-08-24 20:44:00 +04:00
struct timespec ret ;
1998-07-01 01:19:40 +04:00
2006-08-24 20:44:00 +04:00
if ( ( nt - > high = = 0 & & nt - > low = = 0 ) | |
( nt - > high = = 0xffffffff & & nt - > low = = 0xffffffff ) ) {
ret . tv_sec = 0 ;
ret . tv_nsec = 0 ;
return ret ;
2005-11-05 07:21:55 +03:00
}
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
d = ( ( double ) nt - > high ) * 4.0 * ( double ) ( 1 < < 30 ) ;
d + = ( nt - > low & 0xFFF00000 ) ;
d * = 1.0e-7 ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
/* now adjust by 369 years to make the secs since 1970 */
2006-08-25 00:51:57 +04:00
d - = TIME_FIXUP_CONSTANT_DOUBLE ;
1996-05-31 19:13:29 +04:00
2006-08-25 00:51:57 +04:00
if ( d < = TIME_T_MIN ) {
ret . tv_sec = TIME_T_MIN ;
2006-08-24 20:44:00 +04:00
ret . tv_nsec = 0 ;
return ret ;
2005-11-05 07:21:55 +03:00
}
2003-10-13 00:48:56 +04:00
2006-08-25 00:51:57 +04:00
if ( d > = TIME_T_MAX ) {
ret . tv_sec = TIME_T_MAX ;
2006-08-24 20:44:00 +04:00
ret . tv_nsec = 0 ;
return ret ;
2005-11-05 07:21:55 +03:00
}
1996-05-31 19:13:29 +04:00
2006-08-24 20:44:00 +04:00
ret . tv_sec = ( time_t ) d ;
ret . tv_nsec = ( long ) ( ( d - ( double ) ret . tv_sec ) * 1.0e9 ) ;
return ret ;
}
2001-12-03 20:14:23 +03:00
/****************************************************************************
2002-12-10 03:46:52 +03:00
Convert a NTTIME structure to a time_t .
It ' s originally in " 100ns units " .
2001-12-03 20:14:23 +03:00
2002-12-10 03:46:52 +03:00
This is an absolute version of the one above .
By absolute I mean , it doesn ' t adjust from 1 / 1 / 1601 to 1 / 1 / 1970
if the NTTIME was 5 seconds , the time_t is 5 seconds . JFM
2001-12-03 20:14:23 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-12-10 03:46:52 +03:00
2006-08-24 05:34:33 +04:00
time_t nt_time_to_unix_abs ( const NTTIME * nt )
2001-12-03 20:14:23 +03:00
{
double d ;
2006-08-24 05:34:33 +04:00
time_t ret ;
2006-02-05 00:44:57 +03:00
NTTIME neg_nt ;
2001-12-03 20:14:23 +03:00
2005-11-05 07:21:55 +03:00
if ( nt - > high = = 0 ) {
2006-08-24 20:44:00 +04:00
return ( time_t ) 0 ;
2005-11-05 07:21:55 +03:00
}
2001-12-03 20:14:23 +03:00
2005-11-05 07:21:55 +03:00
if ( nt - > high = = 0x80000000 & & nt - > low = = 0 ) {
2006-08-24 05:34:33 +04:00
return ( time_t ) - 1 ;
2005-11-05 07:21:55 +03:00
}
2001-12-03 20:14:23 +03:00
/* reverse the time */
/* it's a negative value, turn it to positive */
2006-02-05 00:44:57 +03:00
neg_nt . high = ~ nt - > high ;
neg_nt . low = ~ nt - > low ;
2001-12-03 20:14:23 +03:00
2006-02-05 00:44:57 +03:00
d = ( ( double ) neg_nt . high ) * 4.0 * ( double ) ( 1 < < 30 ) ;
d + = ( neg_nt . low & 0xFFF00000 ) ;
2001-12-03 20:14:23 +03:00
d * = 1.0e-7 ;
2006-08-25 00:51:57 +04:00
if ( ! ( TIME_T_MIN < = d & & d < = TIME_T_MAX ) ) {
2006-08-24 20:44:00 +04:00
return ( time_t ) 0 ;
2005-11-05 07:21:55 +03:00
}
2001-12-03 20:14:23 +03:00
2006-08-24 05:34:33 +04:00
ret = ( time_t ) ( d + 0.5 ) ;
2006-08-24 20:44:00 +04:00
return ret ;
2001-12-03 20:14:23 +03:00
}
1996-05-31 19:13:29 +04:00
/****************************************************************************
2006-08-24 20:44:00 +04:00
Put a 8 byte filetime from a struct timespec . Uses GMT .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2006-08-24 20:44:00 +04:00
void unix_timespec_to_nt_time ( NTTIME * nt , struct timespec ts )
1996-05-31 19:13:29 +04:00
{
1998-11-10 22:05:00 +03:00
double d ;
1996-05-31 19:13:29 +04:00
2006-08-24 20:44:00 +04:00
if ( ts . tv_sec = = 0 & & ts . tv_nsec = = 0 ) {
1999-12-13 16:27:58 +03:00
nt - > low = 0 ;
nt - > high = 0 ;
return ;
}
2006-08-24 20:44:00 +04:00
if ( ts . tv_sec = = TIME_T_MAX ) {
2001-10-02 10:57:18 +04:00
nt - > low = 0xffffffff ;
nt - > high = 0x7fffffff ;
return ;
}
2006-08-24 20:44:00 +04:00
if ( ts . tv_sec = = ( time_t ) - 1 ) {
2000-11-21 08:55:16 +03:00
nt - > low = 0xffffffff ;
nt - > high = 0xffffffff ;
return ;
}
1999-12-13 16:27:58 +03:00
2006-08-24 20:44:00 +04:00
d = ( double ) ( ts . tv_sec ) ;
2006-08-25 00:51:57 +04:00
d + = TIME_FIXUP_CONSTANT_DOUBLE ;
1998-11-10 22:05:00 +03:00
d * = 1.0e7 ;
2006-08-24 20:44:00 +04:00
d + = ( ( double ) ts . tv_nsec / 100.0 ) ;
1996-05-31 19:13:29 +04:00
1998-11-10 22:05:00 +03:00
nt - > high = ( uint32 ) ( d * ( 1.0 / ( 4.0 * ( double ) ( 1 < < 30 ) ) ) ) ;
nt - > low = ( uint32 ) ( d - ( ( double ) nt - > high ) * 4.0 * ( double ) ( 1 < < 30 ) ) ;
}
2006-08-25 00:51:57 +04:00
# endif
time_t nt_time_to_unix ( NTTIME * nt )
{
return convert_timespec_to_time_t ( nt_time_to_unix_timespec ( nt ) ) ;
}
/****************************************************************************
Interprets an nt time into a unix struct timespec .
Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
will be returned as ( time_t ) - 1 , whereas nt_time_to_unix returns 0 in this case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct timespec interpret_long_date ( char * p )
{
NTTIME nt ;
nt . low = IVAL ( p , 0 ) ;
nt . high = IVAL ( p , 4 ) ;
if ( nt . low = = 0xFFFFFFFF & & nt . high = = 0xFFFFFFFF ) {
struct timespec ret ;
ret . tv_sec = ( time_t ) - 1 ;
ret . tv_nsec = 0 ;
return ret ;
}
return nt_time_to_unix_timespec ( & nt ) ;
}
1996-05-31 19:13:29 +04:00
2006-08-24 20:44:00 +04:00
/****************************************************************************
Put a 8 byte filetime from a time_t . Uses GMT .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void unix_to_nt_time ( NTTIME * nt , time_t t )
{
struct timespec ts ;
ts . tv_sec = t ;
ts . tv_nsec = 0 ;
unix_timespec_to_nt_time ( nt , ts ) ;
}
2001-12-03 20:14:23 +03:00
/****************************************************************************
2002-12-10 03:46:52 +03:00
Convert a time_t to a NTTIME structure
2001-12-03 20:14:23 +03:00
2002-12-10 03:46:52 +03:00
This is an absolute version of the one above .
By absolute I mean , it doesn ' t adjust from 1 / 1 / 1970 to 1 / 1 / 1601
If the nttime_t was 5 seconds , the NTTIME is 5 seconds . JFM
2001-12-03 20:14:23 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-12-10 03:46:52 +03:00
2001-12-03 20:14:23 +03:00
void unix_to_nt_time_abs ( NTTIME * nt , time_t t )
{
double d ;
if ( t = = 0 ) {
nt - > low = 0 ;
nt - > high = 0 ;
return ;
}
if ( t = = TIME_T_MAX ) {
nt - > low = 0xffffffff ;
nt - > high = 0x7fffffff ;
return ;
}
2005-08-03 00:44:30 +04:00
if ( t = = ( time_t ) - 1 ) {
2001-12-03 20:14:23 +03:00
/* that's what NT uses for infinite */
nt - > low = 0x0 ;
nt - > high = 0x80000000 ;
return ;
}
d = ( double ) ( t ) ;
d * = 1.0e7 ;
nt - > high = ( uint32 ) ( d * ( 1.0 / ( 4.0 * ( double ) ( 1 < < 30 ) ) ) ) ;
nt - > low = ( uint32 ) ( d - ( ( double ) nt - > high ) * 4.0 * ( double ) ( 1 < < 30 ) ) ;
/* convert to a negative value */
nt - > high = ~ nt - > high ;
nt - > low = ~ nt - > low ;
}
1998-11-10 22:05:00 +03:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Take a Unix time and convert to an NTTIME structure and place in buffer
pointed to by p .
1998-11-10 22:05:00 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2006-08-24 20:44:00 +04:00
void put_long_date_timespec ( char * p , struct timespec ts )
1998-11-10 22:05:00 +03:00
{
NTTIME nt ;
2006-08-24 20:44:00 +04:00
unix_timespec_to_nt_time ( & nt , ts ) ;
1998-11-10 22:05:00 +03:00
SIVAL ( p , 0 , nt . low ) ;
SIVAL ( p , 4 , nt . high ) ;
1996-05-31 19:13:29 +04:00
}
2006-08-24 20:44:00 +04:00
void put_long_date ( char * p , time_t t )
{
struct timespec ts ;
ts . tv_sec = t ;
ts . tv_nsec = 0 ;
put_long_date_timespec ( p , ts ) ;
}
1996-05-31 19:13:29 +04:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Check if it ' s a null mtime .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1997-10-20 22:52:04 +04:00
BOOL null_mtime ( time_t mtime )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
if ( mtime = = 0 | | mtime = = ( time_t ) 0xFFFFFFFF | | mtime = = ( time_t ) - 1 )
return ( True ) ;
return ( False ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Create a 16 bit dos packed date .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1998-10-06 07:20:43 +04:00
static uint16 make_dos_date1 ( struct tm * t )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
uint16 ret = 0 ;
ret = ( ( ( unsigned ) ( t - > tm_mon + 1 ) ) > > 3 ) | ( ( t - > tm_year - 80 ) < < 1 ) ;
ret = ( ( ret & 0xFF ) < < 8 ) | ( t - > tm_mday | ( ( ( t - > tm_mon + 1 ) & 0x7 ) < < 5 ) ) ;
return ( ret ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Create a 16 bit dos packed time .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1998-10-06 07:20:43 +04:00
static uint16 make_dos_time1 ( struct tm * t )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
uint16 ret = 0 ;
ret = ( ( ( ( unsigned ) t - > tm_min > > 3 ) & 0x7 ) | ( ( ( unsigned ) t - > tm_hour ) < < 3 ) ) ;
ret = ( ( ret & 0xFF ) < < 8 ) | ( ( t - > tm_sec / 2 ) | ( ( t - > tm_min & 0x7 ) < < 5 ) ) ;
return ( ret ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Create a 32 bit dos packed date / time from some parameters .
This takes a GMT time and returns a packed localtime structure .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static uint32 make_dos_date ( time_t unixdate , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
struct tm * t ;
uint32 ret = 0 ;
1996-05-31 19:13:29 +04:00
2005-11-05 07:21:55 +03:00
if ( unixdate = = 0 ) {
return 0 ;
}
unixdate - = zone_offset ;
t = gmtime ( & unixdate ) ;
if ( ! t ) {
2005-02-11 22:31:48 +03:00
return 0xFFFFFFFF ;
2005-11-05 07:21:55 +03:00
}
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
ret = make_dos_date1 ( t ) ;
ret = ( ( ret & 0xFFFF ) < < 16 ) | make_dos_time1 ( t ) ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
return ( ret ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Put a dos date into a buffer ( time / date format ) .
This takes GMT time and puts local time in the buffer .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static void put_dos_date ( char * buf , int offset , time_t unixdate , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-11-05 07:21:55 +03:00
uint32 x = make_dos_date ( unixdate , zone_offset ) ;
2005-02-11 22:31:48 +03:00
SIVAL ( buf , offset , x ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Put a dos date into a buffer ( date / time format ) .
This takes GMT time and puts local time in the buffer .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static void put_dos_date2 ( char * buf , int offset , time_t unixdate , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-11-05 07:21:55 +03:00
uint32 x = make_dos_date ( unixdate , zone_offset ) ;
2005-02-11 22:31:48 +03:00
x = ( ( x & 0xFFFF ) < < 16 ) | ( ( x & 0xFFFF0000 ) > > 16 ) ;
SIVAL ( buf , offset , x ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Put a dos 32 bit " unix like " date into a buffer . This routine takes
GMT and converts it to LOCAL time before putting it ( most SMBs assume
localtime for this sort of date )
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static void put_dos_date3 ( char * buf , int offset , time_t unixdate , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-11-05 07:21:55 +03:00
if ( ! null_mtime ( unixdate ) ) {
unixdate - = zone_offset ;
}
2005-02-11 22:31:48 +03:00
SIVAL ( buf , offset , unixdate ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Interpret a 32 bit dos packed date / time to some parameters .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
1996-05-31 19:13:29 +04:00
static void interpret_dos_date ( uint32 date , int * year , int * month , int * day , int * hour , int * minute , int * second )
{
2005-02-11 22:31:48 +03:00
uint32 p0 , p1 , p2 , p3 ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
p0 = date & 0xFF ; p1 = ( ( date & 0xFF00 ) > > 8 ) & 0xFF ;
p2 = ( ( date & 0xFF0000 ) > > 16 ) & 0xFF ; p3 = ( ( date & 0xFF000000 ) > > 24 ) & 0xFF ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
* second = 2 * ( p0 & 0x1F ) ;
* minute = ( ( p0 > > 5 ) & 0xFF ) + ( ( p1 & 0x7 ) < < 3 ) ;
* hour = ( p1 > > 3 ) & 0xFF ;
* day = ( p2 & 0x1F ) ;
* month = ( ( p2 > > 5 ) & 0xFF ) + ( ( p3 & 0x1 ) < < 3 ) - 1 ;
* year = ( ( p3 > > 1 ) & 0xFF ) + 80 ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Create a unix date ( int GMT ) from a dos date ( which is actually in
localtime ) .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static time_t make_unix_date ( void * date_ptr , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
uint32 dos_date = 0 ;
struct tm t ;
time_t ret ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
dos_date = IVAL ( date_ptr , 0 ) ;
1996-05-31 19:13:29 +04:00
2005-11-05 07:21:55 +03:00
if ( dos_date = = 0 ) {
return 0 ;
}
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
interpret_dos_date ( dos_date , & t . tm_year , & t . tm_mon ,
& t . tm_mday , & t . tm_hour , & t . tm_min , & t . tm_sec ) ;
t . tm_isdst = - 1 ;
1996-05-31 19:13:29 +04:00
2005-11-05 07:21:55 +03:00
ret = timegm ( & t ) ;
ret + = zone_offset ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
return ( ret ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Like make_unix_date ( ) but the words are reversed .
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2005-11-05 07:21:55 +03:00
static time_t make_unix_date2 ( void * date_ptr , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
uint32 x , x2 ;
1996-05-31 19:13:29 +04:00
2005-02-11 22:31:48 +03:00
x = IVAL ( date_ptr , 0 ) ;
x2 = ( ( x & 0xFFFF ) < < 16 ) | ( ( x & 0xFFFF0000 ) > > 16 ) ;
SIVAL ( & x , 0 , x2 ) ;
1996-05-31 19:13:29 +04:00
2005-11-05 07:21:55 +03:00
return ( make_unix_date ( ( void * ) & x , zone_offset ) ) ;
1996-05-31 19:13:29 +04:00
}
/*******************************************************************
2005-02-11 22:31:48 +03:00
Create a unix GMT date from a dos date in 32 bit " unix like " format
these generally arrive as localtimes , with corresponding DST .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-11-05 07:21:55 +03:00
static time_t make_unix_date3 ( void * date_ptr , int zone_offset )
1996-05-31 19:13:29 +04:00
{
2005-02-11 22:31:48 +03:00
time_t t = ( time_t ) IVAL ( date_ptr , 0 ) ;
2005-11-05 07:21:55 +03:00
if ( ! null_mtime ( t ) ) {
t + = zone_offset ;
}
2005-02-11 22:31:48 +03:00
return ( t ) ;
1996-05-31 19:13:29 +04:00
}
2005-11-05 07:21:55 +03:00
/***************************************************************************
Server versions of the above functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void srv_put_dos_date ( char * buf , int offset , time_t unixdate )
{
put_dos_date ( buf , offset , unixdate , server_zone_offset ) ;
}
void srv_put_dos_date2 ( char * buf , int offset , time_t unixdate )
{
put_dos_date2 ( buf , offset , unixdate , server_zone_offset ) ;
}
void srv_put_dos_date3 ( char * buf , int offset , time_t unixdate )
{
put_dos_date3 ( buf , offset , unixdate , server_zone_offset ) ;
}
time_t srv_make_unix_date ( void * date_ptr )
{
return make_unix_date ( date_ptr , server_zone_offset ) ;
}
time_t srv_make_unix_date2 ( void * date_ptr )
{
return make_unix_date2 ( date_ptr , server_zone_offset ) ;
}
time_t srv_make_unix_date3 ( void * date_ptr )
{
return make_unix_date3 ( date_ptr , server_zone_offset ) ;
}
/***************************************************************************
Client versions of the above functions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void cli_put_dos_date ( struct cli_state * cli , char * buf , int offset , time_t unixdate )
{
put_dos_date ( buf , offset , unixdate , cli - > serverzone ) ;
}
void cli_put_dos_date2 ( struct cli_state * cli , char * buf , int offset , time_t unixdate )
{
put_dos_date2 ( buf , offset , unixdate , cli - > serverzone ) ;
}
void cli_put_dos_date3 ( struct cli_state * cli , char * buf , int offset , time_t unixdate )
{
put_dos_date3 ( buf , offset , unixdate , cli - > serverzone ) ;
}
time_t cli_make_unix_date ( struct cli_state * cli , void * date_ptr )
{
return make_unix_date ( date_ptr , cli - > serverzone ) ;
}
time_t cli_make_unix_date2 ( struct cli_state * cli , void * date_ptr )
{
return make_unix_date2 ( date_ptr , cli - > serverzone ) ;
}
time_t cli_make_unix_date3 ( struct cli_state * cli , void * date_ptr )
{
return make_unix_date3 ( date_ptr , cli - > serverzone ) ;
}
1998-03-10 07:56:58 +03:00
/***************************************************************************
2005-02-11 22:31:48 +03:00
Return a HTTP / 1.0 time string .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-03-10 07:56:58 +03:00
char * http_timestring ( time_t t )
{
2005-02-11 22:31:48 +03:00
static fstring buf ;
2005-11-05 07:21:55 +03:00
struct tm * tm = localtime ( & t ) ;
1998-03-10 07:56:58 +03:00
2006-06-15 01:36:49 +04:00
if ( ! tm ) {
2005-02-11 22:31:48 +03:00
slprintf ( buf , sizeof ( buf ) - 1 , " %ld seconds since the Epoch " , ( long ) t ) ;
2006-06-15 01:36:49 +04:00
} else {
1998-07-29 07:08:05 +04:00
# ifndef HAVE_STRFTIME
2006-06-15 01:36:49 +04:00
const char * asct = asctime ( tm ) ;
fstrcpy ( buf , asct ? asct : " unknown " ) ;
}
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' ) {
2005-02-11 22:31:48 +03:00
buf [ strlen ( buf ) - 1 ] = 0 ;
1998-07-29 07:08:05 +04:00
# else /* !HAVE_STRFTIME */
2005-02-11 22:31:48 +03:00
strftime ( buf , sizeof ( buf ) - 1 , " %a, %d %b %Y %H:%M:%S %Z " , tm ) ;
1998-07-29 07:08:05 +04:00
# endif /* !HAVE_STRFTIME */
2006-06-15 01:36:49 +04:00
}
2005-02-11 22:31:48 +03:00
return buf ;
1998-03-10 07:56:58 +03:00
}
1996-05-31 19:13:29 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Return the date and time as a string
1996-05-31 19:13:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2006-07-11 22:01:26 +04:00
char * current_timestring ( BOOL hires )
1996-05-31 19:13:29 +04:00
{
1998-07-29 07:08:05 +04:00
static fstring TimeBuf ;
1999-12-13 16:27:58 +03:00
struct timeval tp ;
time_t t ;
struct tm * tm ;
1998-07-29 07:08:05 +04:00
1999-12-13 16:27:58 +03:00
if ( hires ) {
GetTimeOfDay ( & tp ) ;
t = ( time_t ) tp . tv_sec ;
} else {
t = time ( NULL ) ;
}
2005-11-05 07:21:55 +03:00
tm = localtime ( & t ) ;
1998-07-29 07:08:05 +04:00
if ( ! tm ) {
1999-12-13 16:27:58 +03:00
if ( hires ) {
slprintf ( TimeBuf ,
sizeof ( TimeBuf ) - 1 ,
" %ld.%06ld seconds since the Epoch " ,
( long ) tp . tv_sec ,
( long ) tp . tv_usec ) ;
} else {
slprintf ( TimeBuf ,
sizeof ( TimeBuf ) - 1 ,
" %ld seconds since the Epoch " ,
( long ) t ) ;
}
1998-07-29 07:08:05 +04:00
} else {
# ifdef HAVE_STRFTIME
1999-12-13 16:27:58 +03:00
if ( hires ) {
strftime ( TimeBuf , sizeof ( TimeBuf ) - 1 , " %Y/%m/%d %H:%M:%S " , tm ) ;
slprintf ( TimeBuf + strlen ( TimeBuf ) ,
sizeof ( TimeBuf ) - 1 - strlen ( TimeBuf ) ,
" .%06ld " ,
( long ) tp . tv_usec ) ;
} else {
2003-11-04 23:09:44 +03:00
strftime ( TimeBuf , sizeof ( TimeBuf ) - 1 , " %Y/%m/%d %H:%M:%S " , tm ) ;
1999-12-13 16:27:58 +03:00
}
1996-05-31 19:13:29 +04:00
# else
2000-03-22 22:03:12 +03:00
if ( hires ) {
2006-06-15 01:36:49 +04:00
const char * asct = asctime ( tm ) ;
1999-12-13 16:27:58 +03:00
slprintf ( TimeBuf ,
sizeof ( TimeBuf ) - 1 ,
" %s.%06ld " ,
2006-06-15 01:36:49 +04:00
asct ? asct : " unknown " ,
1999-12-13 16:27:58 +03:00
( long ) tp . tv_usec ) ;
} else {
2006-06-15 01:36:49 +04:00
const char * asct = asctime ( tm ) ;
fstrcpy ( TimeBuf , asct ? asct : " unknown " ) ;
1999-12-13 16:27:58 +03:00
}
1996-05-31 19:13:29 +04:00
# endif
1998-07-29 07:08:05 +04:00
}
return ( TimeBuf ) ;
1996-05-31 19:13:29 +04:00
}
1998-01-24 11:49:21 +03:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Return the best approximation to a ' create time ' under UNIX from a stat
structure .
1998-01-24 11:49:21 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-02 00:11:54 +04:00
time_t get_create_time ( SMB_STRUCT_STAT * st , BOOL fake_dirs )
1998-01-24 11:49:21 +03:00
{
2005-02-11 22:31:48 +03:00
time_t ret , ret1 ;
1998-03-16 23:59:47 +03:00
2005-11-05 07:21:55 +03:00
if ( S_ISDIR ( st - > st_mode ) & & fake_dirs ) {
2005-02-11 22:31:48 +03:00
return ( time_t ) 315493200L ; /* 1/1/1980 */
2005-11-05 07:21:55 +03:00
}
1998-03-16 23:59:47 +03:00
2005-02-11 22:31:48 +03:00
ret = MIN ( st - > st_ctime , st - > st_mtime ) ;
ret1 = MIN ( ret , st - > st_atime ) ;
1998-01-24 11:49:21 +03:00
2005-11-05 07:21:55 +03:00
if ( ret1 ! = ( time_t ) 0 ) {
2005-02-11 22:31:48 +03:00
return ret1 ;
2005-11-05 07:21:55 +03:00
}
1998-01-24 11:49:21 +03:00
2005-02-11 22:31:48 +03:00
/*
* One of ctime , mtime or atime was zero ( probably atime ) .
* Just return MIN ( ctime , mtime ) .
*/
return ret ;
1998-01-24 11:49:21 +03:00
}
1998-09-26 02:20:05 +04:00
2006-08-24 20:44:00 +04:00
struct timespec get_create_timespec ( SMB_STRUCT_STAT * st , BOOL fake_dirs )
{
struct timespec ts ;
ts . tv_sec = get_create_time ( st , fake_dirs ) ;
ts . tv_nsec = 0 ;
return ts ;
}
2001-08-28 10:02:18 +04:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Initialise an NTTIME to - 1 , which means " unknown " or " don't expire " .
2001-08-28 10:02:18 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void init_nt_time ( NTTIME * nt )
{
nt - > high = 0x7FFFFFFF ;
nt - > low = 0xFFFFFFFF ;
}
2002-09-26 22:58:34 +04:00
2006-02-05 00:44:57 +03:00
BOOL nt_time_is_set ( const NTTIME * nt )
{
if ( ( nt - > high = = 0x7FFFFFFF ) & & ( nt - > low = = 0xFFFFFFFF ) ) {
return False ;
}
if ( ( nt - > high = = 0x80000000 ) & & ( nt - > low = = 0 ) ) {
return False ;
}
return True ;
}
2002-09-26 22:58:34 +04:00
/****************************************************************************
2005-02-11 22:31:48 +03:00
Check if NTTIME is 0.
2002-09-26 22:58:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-02-11 22:31:48 +03:00
2006-02-05 00:44:57 +03:00
BOOL nt_time_is_zero ( const NTTIME * nt )
2002-09-26 22:58:34 +04:00
{
2005-11-05 07:21:55 +03:00
if ( nt - > high = = 0 ) {
2002-09-26 22:58:34 +04:00
return True ;
2005-11-05 07:21:55 +03:00
}
2002-09-26 22:58:34 +04:00
return False ;
}
2004-06-08 20:14:31 +04:00
2005-09-30 21:13:37 +04:00
/****************************************************************************
Check if two NTTIMEs are the same .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-02-05 00:44:57 +03:00
BOOL nt_time_equals ( const NTTIME * nt1 , const NTTIME * nt2 )
2005-09-30 21:13:37 +04:00
{
return ( nt1 - > high = = nt2 - > high & & nt1 - > low = = nt2 - > low ) ;
}
2005-02-11 22:31:48 +03:00
/****************************************************************************
Return a timeval difference in usec .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-05-31 17:46:45 +04:00
SMB_BIG_INT usec_time_diff ( const struct timeval * larget , const struct timeval * smallt )
2004-06-08 20:14:31 +04:00
{
SMB_BIG_INT sec_diff = larget - > tv_sec - smallt - > tv_sec ;
return ( sec_diff * 1000000 ) + ( SMB_BIG_INT ) ( larget - > tv_usec - smallt - > tv_usec ) ;
}
2005-03-24 02:26:33 +03:00
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return a timeval struct with the given elements .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_set ( uint32_t secs , uint32_t usecs )
{
struct timeval tv ;
tv . tv_sec = secs ;
tv . tv_usec = usecs ;
return tv ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return a zero timeval .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_zero ( void )
{
return timeval_set ( 0 , 0 ) ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return True if a timeval is zero .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
BOOL timeval_is_zero ( const struct timeval * tv )
{
return tv - > tv_sec = = 0 & & tv - > tv_usec = = 0 ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return a timeval for the current time .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_current ( void )
{
struct timeval tv ;
GetTimeOfDay ( & tv ) ;
return tv ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return a timeval ofs microseconds after tv .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_add ( const struct timeval * tv ,
uint32_t secs , uint32_t usecs )
{
struct timeval tv2 = * tv ;
tv2 . tv_sec + = secs ;
tv2 . tv_usec + = usecs ;
tv2 . tv_sec + = tv2 . tv_usec / 1000000 ;
tv2 . tv_usec = tv2 . tv_usec % 1000000 ;
return tv2 ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return the sum of two timeval structures .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_sum ( const struct timeval * tv1 ,
const struct timeval * tv2 )
{
return timeval_add ( tv1 , tv2 - > tv_sec , tv2 - > tv_usec ) ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return a timeval secs / usecs into the future .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_current_ofs ( uint32_t secs , uint32_t usecs )
{
struct timeval tv = timeval_current ( ) ;
return timeval_add ( & tv , secs , usecs ) ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Compare two timeval structures .
Return - 1 if tv1 < tv2
Return 0 if tv1 = = tv2
Return 1 if tv1 > tv2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
int timeval_compare ( const struct timeval * tv1 , const struct timeval * tv2 )
{
2005-11-05 07:21:55 +03:00
if ( tv1 - > tv_sec > tv2 - > tv_sec ) {
return 1 ;
}
if ( tv1 - > tv_sec < tv2 - > tv_sec ) {
return - 1 ;
}
if ( tv1 - > tv_usec > tv2 - > tv_usec ) {
return 1 ;
}
if ( tv1 - > tv_usec < tv2 - > tv_usec ) {
return - 1 ;
}
2005-09-30 21:13:37 +04:00
return 0 ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return the difference between two timevals as a timeval .
If tv1 comes after tv2 , then return a zero timeval
( this is * tv2 - * tv1 ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_until ( const struct timeval * tv1 ,
const struct timeval * tv2 )
{
struct timeval t ;
if ( timeval_compare ( tv1 , tv2 ) > = 0 ) {
return timeval_zero ( ) ;
}
t . tv_sec = tv2 - > tv_sec - tv1 - > tv_sec ;
if ( tv1 - > tv_usec > tv2 - > tv_usec ) {
t . tv_sec - - ;
t . tv_usec = 1000000 - ( tv1 - > tv_usec - tv2 - > tv_usec ) ;
} else {
t . tv_usec = tv2 - > tv_usec - tv1 - > tv_usec ;
}
return t ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return the lesser of two timevals .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_min ( const struct timeval * tv1 ,
const struct timeval * tv2 )
{
2005-11-05 07:21:55 +03:00
if ( tv1 - > tv_sec < tv2 - > tv_sec ) {
return * tv1 ;
}
if ( tv1 - > tv_sec > tv2 - > tv_sec ) {
return * tv2 ;
}
if ( tv1 - > tv_usec < tv2 - > tv_usec ) {
return * tv1 ;
}
2005-09-30 21:13:37 +04:00
return * tv2 ;
}
2005-11-05 07:21:55 +03:00
/****************************************************************************
Return the greater of two timevals .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-09-30 21:13:37 +04:00
struct timeval timeval_max ( const struct timeval * tv1 ,
const struct timeval * tv2 )
{
2005-11-05 07:21:55 +03:00
if ( tv1 - > tv_sec > tv2 - > tv_sec ) {
return * tv1 ;
}
if ( tv1 - > tv_sec < tv2 - > tv_sec ) {
return * tv2 ;
}
if ( tv1 - > tv_usec > tv2 - > tv_usec ) {
return * tv1 ;
}
2005-09-30 21:13:37 +04:00
return * tv2 ;
}
2005-03-24 02:26:33 +03:00
/****************************************************************************
2005-11-05 07:21:55 +03:00
Convert ASN .1 GeneralizedTime string to unix - time .
Returns 0 on failure ; Currently ignores timezone .
2005-03-24 02:26:33 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-11-05 07:21:55 +03:00
2005-03-24 02:26:33 +03:00
time_t generalized_to_unix_time ( const char * str )
{
struct tm tm ;
ZERO_STRUCT ( tm ) ;
if ( sscanf ( str , " %4d%2d%2d%2d%2d%2d " ,
& tm . tm_year , & tm . tm_mon , & tm . tm_mday ,
& tm . tm_hour , & tm . tm_min , & tm . tm_sec ) ! = 6 ) {
return 0 ;
}
tm . tm_year - = 1900 ;
tm . tm_mon - = 1 ;
return timegm ( & tm ) ;
}
2006-02-10 04:43:33 +03:00
/****************************************************************************
2006-08-24 20:44:00 +04:00
Get / Set all the possible time fields from a stat struct as a timespec .
2006-02-10 04:43:33 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct timespec get_atimespec ( SMB_STRUCT_STAT * pst )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret ;
/* Old system - no ns timestamp. */
ret . tv_sec = pst - > st_atime ;
ret . tv_nsec = 0 ;
return ret ;
# else
# if defined(HAVE_STAT_ST_ATIM)
return pst - > st_atim ;
# elif defined(HAVE_STAT_ST_ATIMENSEC)
struct timespec ret ;
ret . tv_sec = pst - > st_atime ;
ret . tv_nsec = pst - > st_atimensec ;
return ret ;
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-08-24 20:44:00 +04:00
void set_atimespec ( SMB_STRUCT_STAT * pst , struct timespec ts )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
/* Old system - no ns timestamp. */
pst - > st_atime = ts . tv_sec ;
# else
# if defined(HAVE_STAT_ST_ATIM)
pst - > st_atim = ts ;
# elif defined(HAVE_STAT_ST_ATIMENSEC)
pst - > st_atime = ts . tv_sec ;
pst - > st_atimensec = ts . tv_nsec
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-02-10 04:43:33 +03:00
struct timespec get_mtimespec ( SMB_STRUCT_STAT * pst )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret ;
/* Old system - no ns timestamp. */
ret . tv_sec = pst - > st_mtime ;
ret . tv_nsec = 0 ;
return ret ;
# else
# if defined(HAVE_STAT_ST_MTIM)
return pst - > st_mtim ;
# elif defined(HAVE_STAT_ST_MTIMENSEC)
struct timespec ret ;
ret . tv_sec = pst - > st_mtime ;
ret . tv_nsec = pst - > st_mtimensec ;
return ret ;
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-08-24 20:44:00 +04:00
void set_mtimespec ( SMB_STRUCT_STAT * pst , struct timespec ts )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
/* Old system - no ns timestamp. */
pst - > st_mtime = ts . tv_sec ;
# else
# if defined(HAVE_STAT_ST_MTIM)
pst - > st_mtim = ts ;
# elif defined(HAVE_STAT_ST_MTIMENSEC)
pst - > st_mtime = ts . tv_sec ;
pst - > st_mtimensec = ts . tv_nsec
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-02-10 04:43:33 +03:00
struct timespec get_ctimespec ( SMB_STRUCT_STAT * pst )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
struct timespec ret ;
/* Old system - no ns timestamp. */
2006-02-10 08:13:37 +03:00
ret . tv_sec = pst - > st_ctime ;
2006-02-10 04:43:33 +03:00
ret . tv_nsec = 0 ;
return ret ;
# else
# if defined(HAVE_STAT_ST_CTIM)
return pst - > st_ctim ;
# elif defined(HAVE_STAT_ST_CTIMENSEC)
struct timespec ret ;
ret . tv_sec = pst - > st_ctime ;
ret . tv_nsec = pst - > st_ctimensec ;
return ret ;
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-08-24 20:44:00 +04:00
void set_ctimespec ( SMB_STRUCT_STAT * pst , struct timespec ts )
{
# if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
/* Old system - no ns timestamp. */
pst - > st_ctime = ts . tv_sec ;
# else
# if defined(HAVE_STAT_ST_CTIM)
pst - > st_atim = ts ;
# elif defined(HAVE_STAT_ST_CTIMENSEC)
pst - > st_ctime = ts . tv_sec ;
pst - > st_ctimensec = ts . tv_nsec
# else
# error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
# endif
# endif
}
2006-02-10 04:43:33 +03:00
#if 0
/****************************************************************************
Return the best approximation to a ' create time ' under UNIX from a stat
structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct timespec get_create_timespec ( SMB_STRUCT_STAT * st , BOOL fake_dirs )
{
time_t ret , ret1 ;
if ( S_ISDIR ( st - > st_mode ) & & fake_dirs ) {
return ( time_t ) 315493200L ; /* 1/1/1980 */
}
ret = MIN ( st - > st_ctime , st - > st_mtime ) ;
ret1 = MIN ( ret , st - > st_atime ) ;
if ( ret1 ! = ( time_t ) 0 ) {
return ret1 ;
}
/*
* One of ctime , mtime or atime was zero ( probably atime ) .
* Just return MIN ( ctime , mtime ) .
*/
return ret ;
}
# endif
2006-06-15 01:36:49 +04:00
2006-08-24 20:44:00 +04:00
void dos_filetime_timespec ( struct timespec * tsp )
{
tsp - > tv_sec & = ~ 1 ;
tsp - > tv_nsec = 0 ;
}
2006-07-11 22:01:26 +04:00
/**
Return the date and time as a string
* */
char * timestring ( TALLOC_CTX * mem_ctx , time_t t )
{
char * TimeBuf ;
char tempTime [ 80 ] ;
struct tm * tm ;
tm = localtime ( & t ) ;
if ( ! tm ) {
return talloc_asprintf ( mem_ctx ,
" %ld seconds since the Epoch " ,
( long ) t ) ;
}
# ifdef HAVE_STRFTIME
/* some versions of gcc complain about using %c. This is a bug
in the gcc warning , not a bug in this code . See a recent
strftime ( ) manual page for details .
*/
strftime ( tempTime , sizeof ( tempTime ) - 1 , " %c %Z " , tm ) ;
TimeBuf = talloc_strdup ( mem_ctx , tempTime ) ;
# else
TimeBuf = talloc_strdup ( mem_ctx , asctime ( tm ) ) ;
# endif
return TimeBuf ;
}
/**
return a talloced string representing a NTTIME for human consumption
*/
const char * nt_time_string ( TALLOC_CTX * mem_ctx , NTTIME nt )
{
time_t t ;
if ( nt . low = = 0 & & nt . high = = 0 ) {
return " NTTIME(0) " ;
}
t = nt_time_to_unix ( & nt ) ;
return timestring ( mem_ctx , t ) ;
}
2006-06-15 01:36:49 +04:00
/****************************************************************************
Utility function that always returns a const string even if localtime
and asctime fail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char * time_to_asc ( const time_t * t )
{
const char * asct ;
struct tm * lt = localtime ( t ) ;
if ( ! lt ) {
return " unknown time " ;
}
asct = asctime ( lt ) ;
if ( ! asct ) {
return " unknown time " ;
}
return asct ;
}