LCOV - code coverage report
Current view: top level - source3/lib - time.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 105 166 63.3 %
Date: 2021-09-23 10:06:22 Functions: 21 30 70.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    time handling functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell                1992-2004
       6             :    Copyright (C) Stefan (metze) Metzmacher      2002
       7             :    Copyright (C) Jeremy Allison                 2007
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : 
      25             : /**
      26             :  * @file
      27             :  * @brief time handling functions
      28             :  */
      29             : 
      30             : 
      31             : #define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
      32             : 
      33             : #if (SIZEOF_LONG == 8)
      34             : #define TIME_FIXUP_CONSTANT_INT 11644473600L
      35             : #elif (SIZEOF_LONG_LONG == 8)
      36             : #define TIME_FIXUP_CONSTANT_INT 11644473600LL
      37             : #endif
      38             : 
      39             : /**************************************************************
      40             :  Handle conversions between time_t and uint32, taking care to
      41             :  preserve the "special" values.
      42             : **************************************************************/
      43             : 
      44      171841 : uint32_t convert_time_t_to_uint32_t(time_t t)
      45             : {
      46             : #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
      47             :         /* time_t is 64-bit. */
      48      171841 :         if (t == 0x8000000000000000LL) {
      49           0 :                 return 0x80000000;
      50      171841 :         } else if (t == 0x7FFFFFFFFFFFFFFFLL) {
      51           0 :                 return 0x7FFFFFFF;
      52             :         }
      53             : #endif
      54      171841 :         return (uint32_t)t;
      55             : }
      56             : 
      57      287564 : time_t convert_uint32_t_to_time_t(uint32_t u)
      58             : {
      59             : #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8))
      60             :         /* time_t is 64-bit. */
      61      287564 :         if (u == 0x80000000) {
      62           0 :                 return (time_t)0x8000000000000000LL;
      63      287564 :         } else if (u == 0x7FFFFFFF) {
      64           0 :                 return (time_t)0x7FFFFFFFFFFFFFFFLL;
      65             :         }
      66             : #endif
      67      287496 :         return (time_t)u;
      68             : }
      69             : 
      70             : /****************************************************************************
      71             :  Check if NTTIME is 0.
      72             : ****************************************************************************/
      73             : 
      74           0 : bool nt_time_is_zero(const NTTIME *nt)
      75             : {
      76           0 :         return (*nt == 0);
      77             : }
      78             : 
      79             : /****************************************************************************
      80             :  Convert ASN.1 GeneralizedTime string to unix-time.
      81             :  Returns 0 on failure; Currently ignores timezone.
      82             : ****************************************************************************/
      83             : 
      84           0 : time_t generalized_to_unix_time(const char *str)
      85             : {
      86             :         struct tm tm;
      87             : 
      88           0 :         ZERO_STRUCT(tm);
      89             : 
      90           0 :         if (sscanf(str, "%4d%2d%2d%2d%2d%2d",
      91             :                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
      92             :                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
      93           0 :                 return 0;
      94             :         }
      95           0 :         tm.tm_year -= 1900;
      96           0 :         tm.tm_mon -= 1;
      97             : 
      98           0 :         return timegm(&tm);
      99             : }
     100             : 
     101             : /*******************************************************************
     102             :  Accessor function for the server time zone offset.
     103             :  set_server_zone_offset() must have been called first.
     104             : ******************************************************************/
     105             : 
     106             : static int server_zone_offset;
     107             : 
     108           0 : int get_server_zone_offset(void)
     109             : {
     110           0 :         return server_zone_offset;
     111             : }
     112             : 
     113             : /*******************************************************************
     114             :  Initialize the server time zone offset. Called when a client connects.
     115             : ******************************************************************/
     116             : 
     117        9967 : int set_server_zone_offset(time_t t)
     118             : {
     119        9967 :         server_zone_offset = get_time_zone(t);
     120        9967 :         return server_zone_offset;
     121             : }
     122             : 
     123             : /***************************************************************************
     124             :  Server versions of the above functions.
     125             : ***************************************************************************/
     126             : 
     127       20616 : void srv_put_dos_date(char *buf,int offset,time_t unixdate)
     128             : {
     129       20616 :         push_dos_date((uint8_t *)buf, offset, unixdate, server_zone_offset);
     130       20616 : }
     131             : 
     132      345232 : void srv_put_dos_date2(char *buf,int offset, time_t unixdate)
     133             : {
     134      345232 :         push_dos_date2((uint8_t *)buf, offset, unixdate, server_zone_offset);
     135      345232 : }
     136             : 
     137       20053 : void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
     138             : {
     139       20053 :         push_dos_date3((uint8_t *)buf, offset, unixdate, server_zone_offset);
     140       20053 : }
     141             : 
     142     4037283 : void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
     143             : {
     144     4037283 :         if (is_omit_timespec(ts)) {
     145     1482925 :                 return;
     146             :         }
     147             : 
     148     2552223 :         switch (res) {
     149          92 :                 case TIMESTAMP_SET_SECONDS:
     150          92 :                         round_timespec_to_sec(ts);
     151          92 :                         break;
     152           0 :                 case TIMESTAMP_SET_MSEC:
     153           0 :                         round_timespec_to_usec(ts);
     154           0 :                         break;
     155     2546606 :                 case TIMESTAMP_SET_NT_OR_BETTER:
     156             :                         /* No rounding needed. */
     157     2546606 :                         break;
     158             :         }
     159             : }
     160             : 
     161             : /****************************************************************************
     162             :  Take a Unix time and convert to an NTTIME structure and place in buffer
     163             :  pointed to by p, rounded to the correct resolution.
     164             : ****************************************************************************/
     165             : 
     166          92 : void put_long_date_timespec(enum timestamp_set_resolution res, char *p, struct timespec ts)
     167             : {
     168             :         NTTIME nt;
     169          92 :         round_timespec(res, &ts);
     170          92 :         nt = unix_timespec_to_nt_time(ts);
     171          92 :         SBVAL(p, 0, nt);
     172          92 : }
     173             : 
     174     3994791 : void put_long_date_full_timespec(enum timestamp_set_resolution res,
     175             :                                  char *p,
     176             :                                  const struct timespec *_ts)
     177             : {
     178     3994791 :         struct timespec ts = *_ts;
     179             :         NTTIME nt;
     180             : 
     181     3994791 :         round_timespec(res, &ts);
     182     3994791 :         nt = full_timespec_to_nt_time(&ts);
     183     3994791 :         SBVAL(p, 0, nt);
     184     3994791 : }
     185             : 
     186       11392 : struct timespec pull_long_date_full_timespec(const char *p)
     187             : {
     188       11392 :         NTTIME nt = BVAL(p, 0);
     189             : 
     190       11392 :         return nt_time_to_full_timespec(nt);
     191             : }
     192             : 
     193          92 : void put_long_date(char *p, time_t t)
     194             : {
     195             :         struct timespec ts;
     196          92 :         ts.tv_sec = t;
     197          92 :         ts.tv_nsec = 0;
     198          92 :         put_long_date_timespec(TIMESTAMP_SET_SECONDS, p, ts);
     199          92 : }
     200             : 
     201           0 : void dos_filetime_timespec(struct timespec *tsp)
     202             : {
     203           0 :         tsp->tv_sec &= ~1;
     204           0 :         tsp->tv_nsec = 0;
     205           0 : }
     206             : 
     207             : /*******************************************************************
     208             :  Create a unix date (int GMT) from a dos date (which is actually in
     209             :  localtime).
     210             : ********************************************************************/
     211             : 
     212           0 : time_t make_unix_date(const void *date_ptr, int zone_offset)
     213             : {
     214           0 :         return pull_dos_date(date_ptr, zone_offset);
     215             : }
     216             : 
     217             : /*******************************************************************
     218             :  Like make_unix_date() but the words are reversed.
     219             : ********************************************************************/
     220             : 
     221          15 : time_t make_unix_date2(const void *date_ptr, int zone_offset)
     222             : {
     223          15 :         return pull_dos_date2(date_ptr, zone_offset);
     224             : }
     225             : 
     226             : /*******************************************************************
     227             :  Create a unix GMT date from a dos date in 32 bit "unix like" format
     228             :  these generally arrive as localtimes, with corresponding DST.
     229             : ******************************************************************/
     230             : 
     231       33465 : time_t make_unix_date3(const void *date_ptr, int zone_offset)
     232             : {
     233       33465 :         return pull_dos_date3(date_ptr, zone_offset);
     234             : }
     235             : 
     236           0 : time_t srv_make_unix_date(const void *date_ptr)
     237             : {
     238           0 :         return make_unix_date(date_ptr, server_zone_offset);
     239             : }
     240             : 
     241           0 : time_t srv_make_unix_date2(const void *date_ptr)
     242             : {
     243           0 :         return make_unix_date2(date_ptr, server_zone_offset);
     244             : }
     245             : 
     246       32376 : time_t srv_make_unix_date3(const void *date_ptr)
     247             : {
     248       32376 :         return make_unix_date3(date_ptr, server_zone_offset);
     249             : }
     250             : 
     251             : /****************************************************************************
     252             :  Interprets an nt time into a unix struct timespec.
     253             :  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
     254             :  will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
     255             : ****************************************************************************/
     256             : 
     257      187257 : struct timespec interpret_long_date(const char *p)
     258             : {
     259             :         NTTIME nt;
     260      187257 :         nt = BVAL(p, 0);
     261      187257 :         if (nt == (uint64_t)-1) {
     262             :                 struct timespec ret;
     263           0 :                 ret.tv_sec = (time_t)-1;
     264           0 :                 ret.tv_nsec = 0;
     265           0 :                 return ret;
     266             :         }
     267      187257 :         return nt_time_to_full_timespec(nt);
     268             : }
     269             : 
     270             : /*******************************************************************
     271             :  Re-read the smb serverzone value.
     272             : ******************************************************************/
     273             : 
     274             : static struct timeval start_time_hires;
     275             : 
     276         213 : void TimeInit(void)
     277             : {
     278         213 :         set_server_zone_offset(time(NULL));
     279             : 
     280         213 :         DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
     281             : 
     282             :         /* Save the start time of this process. */
     283         213 :         if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
     284         213 :                 GetTimeOfDay(&start_time_hires);
     285             :         }
     286         213 : }
     287             : 
     288             : /**********************************************************************
     289             :  Return a timeval struct of the uptime of this process. As TimeInit is
     290             :  done before a daemon fork then this is the start time from the parent
     291             :  daemon start. JRA.
     292             : ***********************************************************************/
     293             : 
     294        3588 : void get_process_uptime(struct timeval *ret_time)
     295             : {
     296             :         struct timeval time_now_hires;
     297             : 
     298        3588 :         GetTimeOfDay(&time_now_hires);
     299        3588 :         ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
     300        3588 :         if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
     301        2081 :                 ret_time->tv_sec -= 1;
     302        2081 :                 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
     303             :         } else {
     304        1507 :                 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
     305             :         }
     306        3588 : }
     307             : 
     308             : /**
     309             :  * @brief Get the startup time of the server.
     310             :  *
     311             :  * @param[out] ret_time A pointer to a timveal structure to set the startup
     312             :  *                      time.
     313             :  */
     314         272 : void get_startup_time(struct timeval *ret_time)
     315             : {
     316         272 :         ret_time->tv_sec = start_time_hires.tv_sec;
     317         272 :         ret_time->tv_usec = start_time_hires.tv_usec;
     318         272 : }
     319             : 
     320             : 
     321             : /****************************************************************************
     322             :  Convert a NTTIME structure to a time_t.
     323             :  It's originally in "100ns units".
     324             : 
     325             :  This is an absolute version of the one above.
     326             :  By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
     327             :  if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
     328             : ****************************************************************************/
     329             : 
     330          89 : time_t nt_time_to_unix_abs(const NTTIME *nt)
     331             : {
     332             :         uint64_t d;
     333             : 
     334          89 :         if (*nt == 0) {
     335          24 :                 return (time_t)0;
     336             :         }
     337             : 
     338          65 :         if (*nt == (uint64_t)-1) {
     339           0 :                 return (time_t)-1;
     340             :         }
     341             : 
     342          65 :         if (*nt == NTTIME_INFINITY) {
     343           2 :                 return (time_t)-1;
     344             :         }
     345             : 
     346             :         /* reverse the time */
     347             :         /* it's a negative value, turn it to positive */
     348          63 :         d=~*nt;
     349             : 
     350          63 :         d += 1000*1000*10/2;
     351          63 :         d /= 1000*1000*10;
     352             : 
     353          63 :         if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
     354           0 :                 return (time_t)0;
     355             :         }
     356             : 
     357          63 :         return (time_t)d;
     358             : }
     359             : 
     360             : /****************************************************************************
     361             :  Convert a time_t to a NTTIME structure
     362             : 
     363             :  This is an absolute version of the one above.
     364             :  By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
     365             :  If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM
     366             : ****************************************************************************/
     367             : 
     368         236 : void unix_to_nt_time_abs(NTTIME *nt, time_t t)
     369             : {
     370             :         double d;
     371             : 
     372         236 :         if (t==0) {
     373          24 :                 *nt = 0;
     374          24 :                 return;
     375             :         }
     376             : 
     377         212 :         if (t == TIME_T_MAX) {
     378         114 :                 *nt = 0x7fffffffffffffffLL;
     379         114 :                 return;
     380             :         }
     381             : 
     382          98 :         if (t == (time_t)-1) {
     383             :                 /* that's what NT uses for infinite */
     384           0 :                 *nt = NTTIME_INFINITY;
     385           0 :                 return;
     386             :         }
     387             : 
     388          98 :         d = (double)(t);
     389          98 :         d *= 1.0e7;
     390             : 
     391          98 :         *nt = (NTTIME)d;
     392             : 
     393             :         /* convert to a negative value */
     394          98 :         *nt=~*nt;
     395             : }
     396             : 
     397             : 
     398             : /****************************************************************************
     399             :  Utility function that always returns a const string even if localtime
     400             :  and asctime fail.
     401             : ****************************************************************************/
     402             : 
     403       20084 : const char *time_to_asc(const time_t t)
     404             : {
     405             :         const char *asct;
     406       20084 :         struct tm *lt = localtime(&t);
     407             : 
     408       20084 :         if (!lt) {
     409           0 :                 return "unknown time";
     410             :         }
     411             : 
     412       20084 :         asct = asctime(lt);
     413       20084 :         if (!asct) {
     414           0 :                 return "unknown time";
     415             :         }
     416       20084 :         return asct;
     417             : }
     418             : 
     419           0 : const char *display_time(NTTIME nttime)
     420             : {
     421             :         float high;
     422             :         float low;
     423             :         int sec;
     424             :         int days, hours, mins, secs;
     425             : 
     426           0 :         if (nttime==0)
     427           0 :                 return "Now";
     428             : 
     429           0 :         if (nttime==NTTIME_INFINITY)
     430           0 :                 return "Never";
     431             : 
     432           0 :         high = 65536;
     433           0 :         high = high/10000;
     434           0 :         high = high*65536;
     435           0 :         high = high/1000;
     436           0 :         high = high * (~(nttime >> 32));
     437             : 
     438           0 :         low = ~(nttime & 0xFFFFFFFF);
     439           0 :         low = low/(1000*1000*10);
     440             : 
     441           0 :         sec=(int)(high+low);
     442             : 
     443           0 :         days=sec/(60*60*24);
     444           0 :         hours=(sec - (days*60*60*24)) / (60*60);
     445           0 :         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
     446           0 :         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
     447             : 
     448           0 :         return talloc_asprintf(talloc_tos(), "%u days, %u hours, %u minutes, "
     449             :                                "%u seconds", days, hours, mins, secs);
     450             : }
     451             : 
     452           0 : bool nt_time_is_set(const NTTIME *nt)
     453             : {
     454           0 :         if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
     455           0 :                 return false;
     456             :         }
     457             : 
     458           0 :         if (*nt == NTTIME_INFINITY) {
     459           0 :                 return false;
     460             :         }
     461             : 
     462           0 :         return true;
     463             : }

Generated by: LCOV version 1.13