LCOV - code coverage report
Current view: top level - source3/lib - time.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 106 178 59.6 %
Date: 2023-11-21 12:31:41 Functions: 23 30 76.7 %

          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      305471 : 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      305471 :         if (t == 0x8000000000000000LL) {
      49           0 :                 return 0x80000000;
      50      305471 :         } else if (t == 0x7FFFFFFFFFFFFFFFLL) {
      51           0 :                 return 0x7FFFFFFF;
      52             :         }
      53             : #endif
      54      305471 :         return (uint32_t)t;
      55             : }
      56             : 
      57      555556 : 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      555556 :         if (u == 0x80000000) {
      62           0 :                 return (time_t)0x8000000000000000LL;
      63      555556 :         } else if (u == 0x7FFFFFFF) {
      64           0 :                 return (time_t)0x7FFFFFFFFFFFFFFFLL;
      65             :         }
      66             : #endif
      67      555488 :         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           0 :         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       11376 : int set_server_zone_offset(time_t t)
     118             : {
     119       11376 :         server_zone_offset = get_time_zone(t);
     120       11376 :         return server_zone_offset;
     121             : }
     122             : 
     123             : /***************************************************************************
     124             :  Server versions of the above functions.
     125             : ***************************************************************************/
     126             : 
     127       20743 : void srv_put_dos_date(char *buf,int offset,time_t unixdate)
     128             : {
     129       20743 :         push_dos_date((uint8_t *)buf, offset, unixdate, server_zone_offset);
     130       20743 : }
     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       20050 : void srv_put_dos_date3(char *buf,int offset,time_t unixdate)
     138             : {
     139       20050 :         push_dos_date3((uint8_t *)buf, offset, unixdate, server_zone_offset);
     140       20050 : }
     141             : 
     142     5706131 : void round_timespec(enum timestamp_set_resolution res, struct timespec *ts)
     143             : {
     144     5706131 :         if (is_omit_timespec(ts)) {
     145     1497665 :                 return;
     146             :         }
     147             : 
     148     4206131 :         switch (res) {
     149       65868 :                 case TIMESTAMP_SET_SECONDS:
     150       65868 :                         round_timespec_to_sec(ts);
     151       65868 :                         break;
     152           0 :                 case TIMESTAMP_SET_MSEC:
     153           0 :                         round_timespec_to_usec(ts);
     154           0 :                         break;
     155     4136405 :                 case TIMESTAMP_SET_NT_OR_BETTER:
     156             :                         /* No rounding needed. */
     157     4136405 :                         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           0 :         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     5661883 : void put_long_date_full_timespec(enum timestamp_set_resolution res,
     175             :                                  char *p,
     176             :                                  const struct timespec *_ts)
     177             : {
     178     5661883 :         struct timespec ts = *_ts;
     179        8213 :         NTTIME nt;
     180             : 
     181     5661883 :         round_timespec(res, &ts);
     182     5661883 :         nt = full_timespec_to_nt_time(&ts);
     183     5661883 :         SBVAL(p, 0, nt);
     184     5661883 : }
     185             : 
     186       11568 : struct timespec pull_long_date_full_timespec(const char *p)
     187             : {
     188       11568 :         NTTIME nt = BVAL(p, 0);
     189             : 
     190       11568 :         return nt_time_to_full_timespec(nt);
     191             : }
     192             : 
     193          92 : void put_long_date(char *p, time_t t)
     194             : {
     195           0 :         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         125 : time_t make_unix_date(const void *date_ptr, int zone_offset)
     213             : {
     214         125 :         return pull_dos_date(date_ptr, zone_offset);
     215             : }
     216             : 
     217             : /*******************************************************************
     218             :  Like make_unix_date() but the words are reversed.
     219             : ********************************************************************/
     220             : 
     221          39 : time_t make_unix_date2(const void *date_ptr, int zone_offset)
     222             : {
     223          39 :         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       33516 : time_t make_unix_date3(const void *date_ptr, int zone_offset)
     232             : {
     233       33516 :         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          24 : time_t srv_make_unix_date2(const void *date_ptr)
     242             : {
     243          24 :         return make_unix_date2(date_ptr, server_zone_offset);
     244             : }
     245             : 
     246       32427 : time_t srv_make_unix_date3(const void *date_ptr)
     247             : {
     248       32427 :         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      268908 : struct timespec interpret_long_date(NTTIME nt)
     258             : {
     259      268908 :         if (nt == (uint64_t)-1) {
     260           0 :                 struct timespec ret;
     261           0 :                 ret.tv_sec = (time_t)-1;
     262           0 :                 ret.tv_nsec = 0;
     263           0 :                 return ret;
     264             :         }
     265      268908 :         return nt_time_to_full_timespec(nt);
     266             : }
     267             : 
     268             : /*******************************************************************
     269             :  Re-read the smb serverzone value.
     270             : ******************************************************************/
     271             : 
     272             : static struct timeval start_time_hires;
     273             : 
     274         130 : void TimeInit(void)
     275             : {
     276         130 :         set_server_zone_offset(time(NULL));
     277             : 
     278         130 :         DEBUG(4,("TimeInit: Serverzone is %d\n", server_zone_offset));
     279             : 
     280             :         /* Save the start time of this process. */
     281         130 :         if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0) {
     282         130 :                 GetTimeOfDay(&start_time_hires);
     283             :         }
     284         130 : }
     285             : 
     286             : /**********************************************************************
     287             :  Return a timeval struct of the uptime of this process. As TimeInit is
     288             :  done before a daemon fork then this is the start time from the parent
     289             :  daemon start. JRA.
     290             : ***********************************************************************/
     291             : 
     292        3610 : void get_process_uptime(struct timeval *ret_time)
     293             : {
     294           0 :         struct timeval time_now_hires;
     295             : 
     296        3610 :         GetTimeOfDay(&time_now_hires);
     297        3610 :         ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
     298        3610 :         if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
     299           0 :                 ret_time->tv_sec -= 1;
     300           0 :                 ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
     301             :         } else {
     302        3610 :                 ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
     303             :         }
     304        3610 : }
     305             : 
     306             : /**
     307             :  * @brief Get the startup time of the server.
     308             :  *
     309             :  * @param[out] ret_time A pointer to a timveal structure to set the startup
     310             :  *                      time.
     311             :  */
     312         276 : void get_startup_time(struct timeval *ret_time)
     313             : {
     314         276 :         ret_time->tv_sec = start_time_hires.tv_sec;
     315         276 :         ret_time->tv_usec = start_time_hires.tv_usec;
     316         276 : }
     317             : 
     318             : 
     319             : /****************************************************************************
     320             :  Convert a NTTIME structure to a time_t.
     321             :  It's originally in "100ns units".
     322             : 
     323             :  This is an absolute version of the one above.
     324             :  By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
     325             :  if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
     326             : ****************************************************************************/
     327             : 
     328          11 : time_t nt_time_to_unix_abs(const NTTIME *nt)
     329             : {
     330           0 :         uint64_t d;
     331             : 
     332          11 :         if (*nt == 0) {
     333           0 :                 return (time_t)0;
     334             :         }
     335             : 
     336          11 :         if (*nt == (uint64_t)-1) {
     337           0 :                 return (time_t)-1;
     338             :         }
     339             : 
     340          11 :         if (*nt == NTTIME_INFINITY) {
     341           2 :                 return (time_t)-1;
     342             :         }
     343             : 
     344             :         /* reverse the time */
     345             :         /* it's a negative value, turn it to positive */
     346           9 :         d=~*nt;
     347             : 
     348           9 :         d += 1000*1000*10/2;
     349           9 :         d /= 1000*1000*10;
     350             : 
     351           9 :         if (!(TIME_T_MIN <= ((time_t)d) && ((time_t)d) <= TIME_T_MAX)) {
     352           0 :                 return (time_t)0;
     353             :         }
     354             : 
     355           9 :         return (time_t)d;
     356             : }
     357             : 
     358             : /****************************************************************************
     359             :  Convert a time_t to a NTTIME structure
     360             : 
     361             :  This is an absolute version of the one above.
     362             :  By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
     363             :  If the time_t was 5 seconds, the NTTIME is 5 seconds. JFM
     364             : ****************************************************************************/
     365             : 
     366          65 : void unix_to_nt_time_abs(NTTIME *nt, time_t t)
     367             : {
     368           0 :         double d;
     369             : 
     370          65 :         if (t==0) {
     371          12 :                 *nt = 0;
     372          12 :                 return;
     373             :         }
     374             : 
     375          53 :         if (t == TIME_T_MAX) {
     376          24 :                 *nt = 0x7fffffffffffffffLL;
     377          24 :                 return;
     378             :         }
     379             : 
     380          29 :         if (t == (time_t)-1) {
     381             :                 /* that's what NT uses for infinite */
     382           0 :                 *nt = NTTIME_INFINITY;
     383           0 :                 return;
     384             :         }
     385             : 
     386          29 :         d = (double)(t);
     387          29 :         d *= 1.0e7;
     388             : 
     389          29 :         *nt = (NTTIME)d;
     390             : 
     391             :         /* convert to a negative value */
     392          29 :         *nt=~*nt;
     393             : }
     394             : 
     395             : 
     396             : /****************************************************************************
     397             :  Utility function that always returns a const string even if localtime
     398             :  and asctime fail.
     399             : ****************************************************************************/
     400             : 
     401       36322 : const char *time_to_asc(const time_t t)
     402             : {
     403           0 :         const char *asct;
     404       36322 :         struct tm *lt = localtime(&t);
     405             : 
     406       36322 :         if (!lt) {
     407           0 :                 return "unknown time\n";
     408             :         }
     409             : 
     410       36322 :         asct = asctime(lt);
     411       36322 :         if (!asct) {
     412           0 :                 return "unknown time\n";
     413             :         }
     414       36322 :         return asct;
     415             : }
     416             : 
     417           0 : const char *display_time(NTTIME nttime)
     418             : {
     419           0 :         float high;
     420           0 :         float low;
     421           0 :         int sec;
     422           0 :         int days, hours, mins, secs;
     423             : 
     424           0 :         if (nttime==0)
     425           0 :                 return "Now";
     426             : 
     427           0 :         if (nttime==NTTIME_INFINITY)
     428           0 :                 return "Never";
     429             : 
     430           0 :         high = 65536;
     431           0 :         high = high/10000;
     432           0 :         high = high*65536;
     433           0 :         high = high/1000;
     434           0 :         high = high * (~(nttime >> 32));
     435             : 
     436           0 :         low = ~(nttime & 0xFFFFFFFF);
     437           0 :         low = low/(1000*1000*10);
     438             : 
     439           0 :         sec=(int)(high+low);
     440             : 
     441           0 :         days=sec/(60*60*24);
     442           0 :         hours=(sec - (days*60*60*24)) / (60*60);
     443           0 :         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
     444           0 :         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
     445             : 
     446           0 :         return talloc_asprintf(talloc_tos(), "%u days, %u hours, %u minutes, "
     447             :                                "%u seconds", days, hours, mins, secs);
     448             : }
     449             : 
     450           0 : bool nt_time_is_set(const NTTIME *nt)
     451             : {
     452           0 :         if (*nt == 0x7FFFFFFFFFFFFFFFLL) {
     453           0 :                 return false;
     454             :         }
     455             : 
     456           0 :         if (*nt == NTTIME_INFINITY) {
     457           0 :                 return false;
     458             :         }
     459             : 
     460           0 :         return true;
     461             : }

Generated by: LCOV version 1.14