s3-time: fix build warnings after we moved to shared time functions.
[ira/wip.git] / source3 / lib / time.c
index c4aa7d01b3a7048c510fa914f482cf78df888ce7..dffc03b1cf7b0b31dc40703bb213aae9306aeb64 100644 (file)
  */
 
 
-#ifndef TIME_T_MIN
-#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \
-                   : ~ (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
-
 #define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
 
 #if (SIZEOF_LONG == 8)
 #define TIME_FIXUP_CONSTANT_INT 11644473600LL
 #endif
 
-/*******************************************************************
-  create a 16 bit dos packed date
-********************************************************************/
-static uint16_t make_dos_date1(struct tm *t)
-{
-       uint16_t ret=0;
-       ret = (((unsigned int)(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;
-}
-
-/*******************************************************************
-  create a 16 bit dos packed time
-********************************************************************/
-static uint16_t make_dos_time1(struct tm *t)
-{
-       uint16_t ret=0;
-       ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
-       ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
-       return ret;
-}
-
-/*******************************************************************
-  create a 32 bit dos packed date/time from some parameters
-  This takes a GMT time and returns a packed localtime structure
-********************************************************************/
-static uint32_t make_dos_date(time_t unixdate, int zone_offset)
-{
-       struct tm *t;
-       uint32_t ret=0;
-
-       if (unixdate == 0) {
-               return 0;
-       }
-
-       unixdate -= zone_offset;
-
-       t = gmtime(&unixdate);
-       if (!t) {
-               return 0xFFFFFFFF;
-       }
-
-       ret = make_dos_date1(t);
-       ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
-
-       return ret;
-}
 
 /**
   parse a nttime as a large integer in a string and return a NTTIME
@@ -105,7 +50,7 @@ NTTIME nttime_from_string(const char *s)
  preserve the "special" values.
 **************************************************************/
 
-uint32 convert_time_t_to_uint32(time_t t)
+uint32_t convert_time_t_to_uint32(time_t t)
 {
 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
        /* time_t is 64-bit. */
@@ -115,10 +60,10 @@ uint32 convert_time_t_to_uint32(time_t t)
                return 0x7FFFFFFF;
        }
 #endif
-       return (uint32)t;
+       return (uint32_t)t;
 }
 
-time_t convert_uint32_to_time_t(uint32 u)
+time_t convert_uint32_to_time_t(uint32_t u)
 {
 #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
        /* time_t is 64-bit. */
@@ -131,8 +76,6 @@ time_t convert_uint32_to_time_t(uint32 u)
        return (time_t)u;
 }
 
-int extra_time_offset=0;
-
 /****************************************************************************
  Check if NTTIME is 0.
 ****************************************************************************/
@@ -190,27 +133,21 @@ int set_server_zone_offset(time_t t)
  Return the date and time as a string
 ****************************************************************************/
 
-char *current_timestring(TALLOC_CTX *ctx, bool hires)
+char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
 {
        fstring TimeBuf;
-       struct timeval tp;
        time_t t;
        struct tm *tm;
 
-       if (hires) {
-               GetTimeOfDay(&tp);
-               t = (time_t)tp.tv_sec;
-       } else {
-               t = time(NULL);
-       }
+       t = (time_t)tp->tv_sec;
        tm = localtime(&t);
        if (!tm) {
                if (hires) {
                        slprintf(TimeBuf,
                                 sizeof(TimeBuf)-1,
                                 "%ld.%06ld seconds since the Epoch",
-                                (long)tp.tv_sec, 
-                                (long)tp.tv_usec);
+                                (long)tp->tv_sec,
+                                (long)tp->tv_usec);
                } else {
                        slprintf(TimeBuf,
                                 sizeof(TimeBuf)-1,
@@ -224,7 +161,7 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
                        slprintf(TimeBuf+strlen(TimeBuf),
                                 sizeof(TimeBuf)-1 - strlen(TimeBuf), 
                                 ".%06ld", 
-                                (long)tp.tv_usec);
+                                (long)tp->tv_usec);
                } else {
                        strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
                }
@@ -235,7 +172,7 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
                                 sizeof(TimeBuf)-1, 
                                 "%s.%06ld", 
                                 asct ? asct : "unknown", 
-                                (long)tp.tv_usec);
+                                (long)tp->tv_usec);
                } else {
                        const char *asct = asctime(tm);
                        fstrcpy(TimeBuf, asct ? asct : "unknown");
@@ -245,43 +182,14 @@ char *current_timestring(TALLOC_CTX *ctx, bool hires)
        return talloc_strdup(ctx, TimeBuf);
 }
 
-
-/*******************************************************************
- Put a dos date into a buffer (time/date format).
- This takes GMT time and puts local time in the buffer.
-********************************************************************/
-
-static void put_dos_date(char *buf,int offset,time_t unixdate, int zone_offset)
+char *current_timestring(TALLOC_CTX *ctx, bool hires)
 {
-       uint32 x = make_dos_date(unixdate, zone_offset);
-       SIVAL(buf,offset,x);
-}
-
-/*******************************************************************
- Put a dos date into a buffer (date/time format).
- This takes GMT time and puts local time in the buffer.
-********************************************************************/
+       struct timeval tv;
 
-static void put_dos_date2(char *buf,int offset,time_t unixdate, int zone_offset)
-{
-       uint32 x = make_dos_date(unixdate, zone_offset);
-       x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
-       SIVAL(buf,offset,x);
+       GetTimeOfDay(&tv);
+       return timeval_string(ctx, &tv, hires);
 }
 
-/*******************************************************************
- 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)
-********************************************************************/
-
-static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
-{
-       if (!null_mtime(unixdate)) {
-               unixdate -= zone_offset;
-       }
-       SIVAL(buf,offset,unixdate);
-}
 
 
 /***************************************************************************
@@ -290,27 +198,43 @@ static void put_dos_date3(char *buf,int offset,time_t unixdate, int zone_offset)
 
 void srv_put_dos_date(char *buf,int offset,time_t unixdate)
 {
-       put_dos_date(buf, offset, unixdate, server_zone_offset);
+       push_dos_date((uint8_t *)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);
+       push_dos_date2((uint8_t *)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);
+       push_dos_date3((uint8_t *)buf, offset, unixdate, server_zone_offset);
+}
+
+void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
+{
+       switch (res) {
+               case TIMESTAMP_SET_SECONDS:
+                       round_timespec_to_sec(ts);
+                       break;
+               case TIMESTAMP_SET_MSEC:
+                       round_timespec_to_usec(ts);
+                       break;
+               case TIMESTAMP_SET_NT_OR_BETTER:
+                       /* No rounding needed. */
+                       break;
+        }
 }
 
 /****************************************************************************
  Take a Unix time and convert to an NTTIME structure and place in buffer 
- pointed to by p.
+ pointed to by p, rounded to the correct resolution.
 ****************************************************************************/
 
-void put_long_date_timespec(char *p, struct timespec ts)
+void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct timespec ts)
 {
        NTTIME nt;
+       round_timespec(res, &ts);
        unix_timespec_to_nt_time(&nt, ts);
        SIVAL(p, 0, nt & 0xFFFFFFFF);
        SIVAL(p, 4, nt >> 32);
@@ -321,192 +245,7 @@ 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);
-}
-
-/****************************************************************************
- Return the best approximation to a 'create time' under UNIX from a stat
- structure.
-****************************************************************************/
-
-static time_t calc_create_time(const SMB_STRUCT_STAT *st)
-{
-       time_t ret, ret1;
-
-       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;
-}
-
-/****************************************************************************
- Return the 'create time' from a stat struct if it exists (birthtime) or else
- use the best approximation.
-****************************************************************************/
-
-struct timespec get_create_timespec(const SMB_STRUCT_STAT *pst,bool fake_dirs)
-{
-       struct timespec ret;
-
-       if(S_ISDIR(pst->st_mode) && fake_dirs) {
-               ret.tv_sec = 315493200L;          /* 1/1/1980 */
-               ret.tv_nsec = 0;
-               return ret;
-       }
-
-#if defined(HAVE_STAT_ST_BIRTHTIMESPEC)
-       ret = pst->st_birthtimespec;
-#elif defined(HAVE_STAT_ST_BIRTHTIMENSEC)
-       ret.tv_sec = pst->st_birthtime;
-       ret.tv_nsec = pst->st_birthtimenspec;
-#elif defined(HAVE_STAT_ST_BIRTHTIME)
-       ret.tv_sec = pst->st_birthtime;
-       ret.tv_nsec = 0;
-#else
-       ret.tv_sec = calc_create_time(pst);
-       ret.tv_nsec = 0;
-#endif
-
-       /* Deal with systems that don't initialize birthtime correctly.
-        * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>.
-        */
-       if (null_timespec(ret)) {
-               ret.tv_sec = calc_create_time(pst);
-               ret.tv_nsec = 0;
-       }
-       return ret;
-}
-
-/****************************************************************************
- Get/Set all the possible time fields from a stat struct as a timespec.
-****************************************************************************/
-
-struct timespec get_atimespec(const 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
-}
-
-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
-}
-
-struct timespec get_mtimespec(const 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
-}
-
-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
-}
-
-struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst)
-{
-#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
-       struct timespec ret;
-
-       /* Old system - no ns timestamp. */
-       ret.tv_sec = pst->st_ctime;
-       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
-}
-
-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_ctim = 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
+       put_long_date_timespec(TIMESTAMP_SET_SECONDS, p, ts);
 }
 
 void dos_filetime_timespec(struct timespec *tsp)
@@ -522,7 +261,7 @@ void dos_filetime_timespec(struct timespec *tsp)
 
 static time_t make_unix_date(const void *date_ptr, int zone_offset)
 {
-       uint32 dos_date=0;
+       uint32_t dos_date=0;
        struct tm t;
        time_t ret;
 
@@ -547,9 +286,9 @@ static time_t make_unix_date(const void *date_ptr, int zone_offset)
  Like make_unix_date() but the words are reversed.
 ********************************************************************/
 
-static time_t make_unix_date2(const void *date_ptr, int zone_offset)
+time_t make_unix_date2(const void *date_ptr, int zone_offset)
 {
-       uint32 x,x2;
+       uint32_t x,x2;
 
        x = IVAL(date_ptr,0);
        x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
@@ -563,10 +302,10 @@ static time_t make_unix_date2(const void *date_ptr, int zone_offset)
  these generally arrive as localtimes, with corresponding DST.
 ******************************************************************/
 
-static time_t make_unix_date3(const void *date_ptr, int zone_offset)
+time_t make_unix_date3(const void *date_ptr, int zone_offset)
 {
        time_t t = (time_t)IVAL(date_ptr,0);
-       if (!null_mtime(t)) {
+       if (!null_time(t)) {
                t += zone_offset;
        }
        return(t);
@@ -654,6 +393,27 @@ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
        return 0;
 }
 
+/****************************************************************************
+ Round up a timespec if nsec > 500000000, round down if lower,
+ then zero nsec.
+****************************************************************************/
+
+void round_timespec_to_sec(struct timespec *ts)
+{
+       ts->tv_sec = convert_timespec_to_time_t(*ts);
+       ts->tv_nsec = 0;
+}
+
+/****************************************************************************
+ Round a timespec to usec value.
+****************************************************************************/
+
+void round_timespec_to_usec(struct timespec *ts)
+{
+       struct timeval tv = convert_timespec_to_timeval(*ts);
+       *ts = convert_timeval_to_timespec(tv);
+}
+
 /****************************************************************************
  Interprets an nt time into a unix struct timespec.
  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
@@ -679,17 +439,17 @@ struct timespec interpret_long_date(const char *p)
 
 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate)
 {
-       put_dos_date(buf, offset, unixdate, cli->serverzone);
+       push_dos_date((uint8_t *)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);
+       push_dos_date2((uint8_t *)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);
+       push_dos_date3((uint8_t *)buf, offset, unixdate, cli->serverzone);
 }
 
 time_t cli_make_unix_date(struct cli_state *cli, const void *date_ptr)
@@ -707,14 +467,6 @@ time_t cli_make_unix_date3(struct cli_state *cli, const void *date_ptr)
        return make_unix_date3(date_ptr, cli->serverzone);
 }
 
-/****************************************************************************
- Check if two NTTIMEs are the same.
-****************************************************************************/
-
-bool nt_time_equals(const NTTIME *nt1, const NTTIME *nt2)
-{
-       return (*nt1 == *nt2);
-}
 
 /*******************************************************************
  Re-read the smb serverzone value.
@@ -765,13 +517,13 @@ void get_process_uptime(struct timeval *ret_time)
 
 time_t nt_time_to_unix_abs(const NTTIME *nt)
 {
-       uint64 d;
+       uint64_t d;
 
        if (*nt == 0) {
                return (time_t)0;
        }
 
-       if (*nt == (uint64)-1) {
+       if (*nt == (uint64_t)-1) {
                return (time_t)-1;
        }
 
@@ -806,7 +558,7 @@ time_t uint64s_nt_time_to_unix_abs(const uint64_t *src)
 
 void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
 {
-       uint64 d;
+       uint64_t d;
 
        if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
                *nt = 0;
@@ -817,7 +569,7 @@ void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
                return;
        }               
        if (ts.tv_sec == (time_t)-1) {
-               *nt = (uint64)-1;
+               *nt = (uint64_t)-1;
                return;
        }               
 
@@ -830,6 +582,33 @@ void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
        *nt = d;
 }
 
+#if 0
+void nt_time_to_unix_timespec(struct timespec *ts, NTTIME t)
+{
+       if (ts == NULL) {
+               return;
+       }
+
+       /* t starts in 100 nsec units since 1601-01-01. */
+
+       t *= 100;
+       /* t is now in nsec units since 1601-01-01. */
+
+       t -= TIME_FIXUP_CONSTANT*1000*1000*100;
+       /* t is now in nsec units since the UNIX epoch 1970-01-01. */
+
+       ts->tv_sec  = t / 1000000000LL;
+
+       if (TIME_T_MIN > ts->tv_sec || ts->tv_sec > TIME_T_MAX) {
+               ts->tv_sec  = 0;
+               ts->tv_nsec = 0;
+               return;
+       }
+
+       ts->tv_nsec = t - ts->tv_sec*1000000000LL;
+}
+#endif
+
 /****************************************************************************
  Convert a time_t to a NTTIME structure
 
@@ -868,17 +647,6 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
 }
 
 
-/****************************************************************************
- Check if it's a null mtime.
-****************************************************************************/
-
-bool null_mtime(time_t mtime)
-{
-       if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
-               return(True);
-       return(False);
-}
-
 /****************************************************************************
  Utility function that always returns a const string even if localtime
  and asctime fail.
@@ -936,12 +704,12 @@ const char *display_time(NTTIME nttime)
 bool nt_time_is_set(const NTTIME *nt)
 {
        if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
-               return False;
+               return false;
        }
 
        if (*nt == NTTIME_INFINITY) {
-               return False;
+               return false;
        }
 
-       return True;
+       return true;
 }