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

Generated by: LCOV version 1.14