LCOV - code coverage report
Current view: top level - lib/util - time.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 393 475 82.7 %
Date: 2021-09-23 10:06:22 Functions: 77 82 93.9 %

          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             :    Copyright (C) Andrew Bartlett                2011
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             :    
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "replace.h"
      25             : #include "system/time.h"
      26             : #include "byteorder.h"
      27             : #include "time_basic.h"
      28             : #include "lib/util/time.h" /* Avoid /usr/include/time.h */
      29             : #include <sys/stat.h>
      30             : #ifndef NO_CONFIG_H
      31             : #include "config.h"
      32             : #endif
      33             : 
      34             : /**
      35             :  * @file
      36             :  * @brief time handling functions
      37             :  */
      38             : 
      39             : #if (SIZEOF_LONG == 8)
      40             : #define TIME_FIXUP_CONSTANT_INT 11644473600L
      41             : #elif (SIZEOF_LONG_LONG == 8)
      42             : #define TIME_FIXUP_CONSTANT_INT 11644473600LL
      43             : #endif
      44             : 
      45             : 
      46             : #define NSEC_PER_SEC 1000000000
      47             : 
      48             : /**
      49             :  External access to time_t_min and time_t_max.
      50             : **/
      51      248836 : _PUBLIC_ time_t get_time_t_max(void)
      52             : {
      53      248836 :         return TIME_T_MAX;
      54             : }
      55             : 
      56             : /**
      57             : a wrapper to preferably get the monotonic time
      58             : **/
      59   711879846 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
      60             : {
      61             : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
      62             : #ifdef CLOCK_BOOTTIME
      63   711879846 :         if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
      64   711486279 :                 return;
      65             :         }
      66             : #endif
      67             : /* then try the  monotonic clock: */
      68             : #ifndef CUSTOM_CLOCK_MONOTONIC_IS_REALTIME
      69           0 :         if (clock_gettime(CUSTOM_CLOCK_MONOTONIC,tp) == 0) {
      70           0 :                 return;
      71             :         }
      72             : #endif
      73           0 :         clock_gettime(CLOCK_REALTIME,tp);
      74             : }
      75             : 
      76             : /**
      77             : a wrapper to preferably get the monotonic time in seconds
      78             : **/
      79        5857 : _PUBLIC_ time_t time_mono(time_t *t)
      80             : {
      81             :         struct timespec tp;
      82             : 
      83        5857 :         clock_gettime_mono(&tp);
      84        5857 :         if (t != NULL) {
      85           0 :                 *t = tp.tv_sec;
      86             :         }
      87        5857 :         return tp.tv_sec;
      88             : }
      89             : 
      90             : 
      91             : #define TIME_FIXUP_CONSTANT 11644473600LL
      92             : 
      93     3818365 : time_t convert_timespec_to_time_t(struct timespec ts)
      94             : {
      95             :         /* Ensure tv_nsec is less than 1sec. */
      96     3818365 :         normalize_timespec(&ts);
      97             : 
      98             :         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
      99             :            increment if it's greater than 500 millionth of a second. */
     100             : 
     101     3818365 :         if (ts.tv_nsec > 500000000) {
     102      890519 :                 return ts.tv_sec + 1;
     103             :         }
     104     2927846 :         return ts.tv_sec;
     105             : }
     106             : 
     107           0 : struct timespec convert_time_t_to_timespec(time_t t)
     108             : {
     109             :         struct timespec ts;
     110           0 :         ts.tv_sec = t;
     111           0 :         ts.tv_nsec = 0;
     112           0 :         return ts;
     113             : }
     114             : 
     115             : 
     116             : 
     117             : /**
     118             :  Interpret an 8 byte "filetime" structure to a time_t
     119             :  It's originally in "100ns units since jan 1st 1601"
     120             : 
     121             :  An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
     122             : 
     123             :         tv_sec = 0
     124             :         tv_nsec = 0;
     125             : 
     126             :  Returns GMT.
     127             : **/
     128     2164962 : time_t nt_time_to_unix(NTTIME nt)
     129             : {
     130     2164962 :         return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
     131             : }
     132             : 
     133             : 
     134             : /**
     135             : put a 8 byte filetime from a time_t
     136             : This takes GMT as input
     137             : **/
     138     6196753 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
     139             : {
     140             :         uint64_t t2; 
     141             : 
     142     6196753 :         if (t == (time_t)-1) {
     143           1 :                 *nt = (NTTIME)-1LL;
     144           1 :                 return;
     145             :         }       
     146             : 
     147     6196752 :         if (t == TIME_T_MAX || t == INT64_MAX) {
     148       52809 :                 *nt = 0x7fffffffffffffffLL;
     149       52809 :                 return;
     150             :         }
     151             : 
     152     6143943 :         if (t == 0) {
     153       19365 :                 *nt = 0;
     154       19365 :                 return;
     155             :         }               
     156             : 
     157     6124578 :         t2 = t;
     158     6124578 :         t2 += TIME_FIXUP_CONSTANT_INT;
     159     6124578 :         t2 *= 1000*1000*10;
     160             : 
     161     6124578 :         *nt = t2;
     162             : }
     163             : 
     164             : 
     165             : /**
     166             : check if it's a null unix time
     167             : **/
     168      897251 : _PUBLIC_ bool null_time(time_t t)
     169             : {
     170       81977 :         return t == 0 || 
     171      977744 :                 t == (time_t)0xFFFFFFFF || 
     172             :                 t == (time_t)-1;
     173             : }
     174             : 
     175             : 
     176             : /**
     177             : check if it's a null NTTIME
     178             : **/
     179     2279654 : _PUBLIC_ bool null_nttime(NTTIME t)
     180             : {
     181     2279654 :         return t == 0 || t == (NTTIME)-1;
     182             : }
     183             : 
     184             : /*******************************************************************
     185             :   create a 16 bit dos packed date
     186             : ********************************************************************/
     187      440683 : static uint16_t make_dos_date1(struct tm *t)
     188             : {
     189      440889 :         uint16_t ret=0;
     190      440889 :         ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
     191      440889 :         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
     192      440683 :         return ret;
     193             : }
     194             : 
     195             : /*******************************************************************
     196             :   create a 16 bit dos packed time
     197             : ********************************************************************/
     198      440683 : static uint16_t make_dos_time1(struct tm *t)
     199             : {
     200      440889 :         uint16_t ret=0;
     201      440889 :         ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
     202      440889 :         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
     203      440683 :         return ret;
     204             : }
     205             : 
     206             : /*******************************************************************
     207             :   create a 32 bit dos packed date/time from some parameters
     208             :   This takes a GMT time and returns a packed localtime structure
     209             : ********************************************************************/
     210      441025 : static uint32_t make_dos_date(time_t unixdate, int zone_offset)
     211             : {
     212             :         struct tm *t;
     213      441025 :         uint32_t ret=0;
     214             : 
     215      441025 :         if (unixdate == 0) {
     216         119 :                 return 0;
     217             :         }
     218             : 
     219      440889 :         unixdate -= zone_offset;
     220             : 
     221      440889 :         t = gmtime(&unixdate);
     222      440889 :         if (!t) {
     223           0 :                 return 0xFFFFFFFF;
     224             :         }
     225             : 
     226      441095 :         ret = make_dos_date1(t);
     227      441095 :         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
     228             : 
     229      440889 :         return ret;
     230             : }
     231             : 
     232             : /**
     233             : put a dos date into a buffer (time/date format)
     234             : This takes GMT time and puts local time in the buffer
     235             : **/
     236       33519 : _PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
     237             : {
     238       33519 :         uint32_t x = make_dos_date(unixdate, zone_offset);
     239       33519 :         SIVAL(buf,offset,x);
     240       33519 : }
     241             : 
     242             : /**
     243             : put a dos date into a buffer (date/time format)
     244             : This takes GMT time and puts local time in the buffer
     245             : **/
     246      407506 : _PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     247             : {
     248             :         uint32_t x;
     249      407506 :         x = make_dos_date(unixdate, zone_offset);
     250      407506 :         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
     251      407506 :         SIVAL(buf,offset,x);
     252      407506 : }
     253             : 
     254             : /**
     255             : put a dos 32 bit "unix like" date into a buffer. This routine takes
     256             : GMT and converts it to LOCAL time before putting it (most SMBs assume
     257             : localtime for this sort of date)
     258             : **/
     259      169301 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     260             : {
     261      169301 :         if (!null_time(unixdate)) {
     262       29187 :                 unixdate -= zone_offset;
     263             :         }
     264      169301 :         SIVAL(buf,offset,unixdate);
     265      169301 : }
     266             : 
     267             : /*******************************************************************
     268             :   interpret a 32 bit dos packed date/time to some parameters
     269             : ********************************************************************/
     270      440750 : void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
     271             : {
     272             :         uint32_t p0,p1,p2,p3;
     273             : 
     274      440750 :         p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
     275      440750 :         p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
     276             : 
     277      440750 :         *second = 2*(p0 & 0x1F);
     278      440750 :         *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
     279      440750 :         *hour = (p1>>3)&0xFF;
     280      440750 :         *day = (p2&0x1F);
     281      440750 :         *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
     282      440750 :         *year = ((p3>>1)&0xFF) + 80;
     283      440750 : }
     284             : 
     285             : /**
     286             :   create a unix date (int GMT) from a dos date (which is actually in
     287             :   localtime)
     288             : **/
     289      440805 : _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
     290             : {
     291      440805 :         uint32_t dos_date=0;
     292             :         struct tm t;
     293             :         time_t ret;
     294             : 
     295      440805 :         dos_date = IVAL(date_ptr,0);
     296             : 
     297      440805 :         if (dos_date == 0) return (time_t)0;
     298             :   
     299      440750 :         interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
     300             :                            &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
     301      440750 :         t.tm_isdst = -1;
     302             :   
     303      440750 :         ret = timegm(&t);
     304             : 
     305      440750 :         ret += zone_offset;
     306             : 
     307      440750 :         return ret;
     308             : }
     309             : 
     310             : /**
     311             : like make_unix_date() but the words are reversed
     312             : **/
     313      407379 : _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
     314             : {
     315             :         uint32_t x,x2;
     316             : 
     317      407379 :         x = IVAL(date_ptr,0);
     318      407379 :         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
     319      407379 :         SIVAL(&x,0,x2);
     320             : 
     321      407379 :         return pull_dos_date((const uint8_t *)&x, zone_offset);
     322             : }
     323             : 
     324             : /**
     325             :   create a unix GMT date from a dos date in 32 bit "unix like" format
     326             :   these generally arrive as localtimes, with corresponding DST
     327             : **/
     328      147567 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
     329             : {
     330      147567 :         time_t t = (time_t)IVAL(date_ptr,0);
     331             : 
     332      147567 :         if (t == (time_t)0xFFFFFFFF) {
     333        4056 :                 t = (time_t)-1;
     334             :         }
     335             : 
     336      147567 :         if (!null_time(t)) {
     337       27802 :                 t += zone_offset;
     338             :         }
     339      147567 :         return t;
     340             : }
     341             : 
     342             : /****************************************************************************
     343             :  Return the date and time as a string
     344             : ****************************************************************************/
     345             : 
     346          38 : char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
     347             : {
     348             :         struct timeval_buf tmp;
     349             :         char *result;
     350             : 
     351          38 :         result = talloc_strdup(ctx, timeval_str_buf(tp, false, hires, &tmp));
     352          38 :         if (result == NULL) {
     353           0 :                 return NULL;
     354             :         }
     355             : 
     356             :         /*
     357             :          * beautify the talloc_report output
     358             :          *
     359             :          * This is not just cosmetics. A C compiler might in theory make the
     360             :          * talloc_strdup call above a tail call with the tail call
     361             :          * optimization. This would render "tmp" invalid while talloc_strdup
     362             :          * tries to duplicate it. The talloc_set_name_const call below puts
     363             :          * the talloc_strdup call into non-tail position.
     364             :          */
     365          38 :         talloc_set_name_const(result, result);
     366          38 :         return result;
     367             : }
     368             : 
     369             : /****************************************************************************
     370             :  Return the date and time as a string
     371             : ****************************************************************************/
     372             : 
     373           0 : const char *timespec_string_buf(const struct timespec *tp,
     374             :                                 bool hires,
     375             :                                 struct timeval_buf *buf)
     376             : {
     377             :         time_t t;
     378           0 :         struct tm *tm = NULL;
     379             :         int len;
     380             : 
     381           0 :         if (is_omit_timespec(tp)) {
     382           0 :                 strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf));
     383           0 :                 return buf->buf;
     384             :         }
     385             : 
     386           0 :         t = (time_t)tp->tv_sec;
     387           0 :         tm = localtime(&t);
     388             : 
     389           0 :         if (tm == NULL) {
     390           0 :                 if (hires) {
     391           0 :                         len = snprintf(buf->buf, sizeof(buf->buf),
     392             :                                        "%ld.%09ld seconds since the Epoch",
     393           0 :                                        (long)tp->tv_sec, (long)tp->tv_nsec);
     394             :                 } else {
     395           0 :                         len = snprintf(buf->buf, sizeof(buf->buf),
     396             :                                        "%ld seconds since the Epoch", (long)t);
     397             :                 }
     398           0 :         } else if (!hires) {
     399           0 :                 len = snprintf(buf->buf, sizeof(buf->buf),
     400             :                                "%04d/%02d/%02d %02d:%02d:%02d",
     401           0 :                                1900 + tm->tm_year,
     402           0 :                                tm->tm_mon + 1,
     403             :                                tm->tm_mday,
     404             :                                tm->tm_hour,
     405             :                                tm->tm_min,
     406             :                                tm->tm_sec);
     407             :         } else {
     408           0 :                 len = snprintf(buf->buf, sizeof(buf->buf),
     409             :                                "%04d/%02d/%02d %02d:%02d:%02d.%09ld",
     410           0 :                                1900 + tm->tm_year,
     411           0 :                                tm->tm_mon + 1,
     412             :                                tm->tm_mday,
     413             :                                tm->tm_hour,
     414             :                                tm->tm_min,
     415             :                                tm->tm_sec,
     416           0 :                                (long)tp->tv_nsec);
     417             :         }
     418           0 :         if (len == -1) {
     419           0 :                 return "";
     420             :         }
     421             : 
     422           0 :         return buf->buf;
     423             : }
     424             : 
     425          38 : char *current_timestring(TALLOC_CTX *ctx, bool hires)
     426             : {
     427             :         struct timeval tv;
     428             : 
     429          38 :         GetTimeOfDay(&tv);
     430          38 :         return timeval_string(ctx, &tv, hires);
     431             : }
     432             : 
     433             : /*
     434             :  * Return date and time as a minimal string avoiding funny characters
     435             :  * that may cause trouble in file names. We only use digits and
     436             :  * underscore ... or a minus/hyphen if we got negative time.
     437             :  */
     438         165 : char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
     439             : {
     440             :         time_t t;
     441             :         struct tm *tm;
     442             : 
     443         165 :         t = (time_t)tp->tv_sec;
     444         165 :         tm = localtime(&t);
     445         165 :         if (!tm) {
     446           0 :                 if (hires) {
     447           0 :                         return talloc_asprintf(ctx, "%ld_%06ld",
     448           0 :                                                (long)tp->tv_sec,
     449           0 :                                                (long)tp->tv_usec);
     450             :                 } else {
     451           0 :                         return talloc_asprintf(ctx, "%ld", (long)t);
     452             :                 }
     453             :         } else {
     454         165 :                 if (hires) {
     455           3 :                         return talloc_asprintf(ctx,
     456             :                                                "%04d%02d%02d_%02d%02d%02d_%06ld",
     457           1 :                                                tm->tm_year+1900,
     458           1 :                                                tm->tm_mon+1,
     459             :                                                tm->tm_mday,
     460             :                                                tm->tm_hour,
     461             :                                                tm->tm_min,
     462             :                                                tm->tm_sec,
     463           1 :                                                (long)tp->tv_usec);
     464             :                 } else {
     465         448 :                         return talloc_asprintf(ctx,
     466             :                                                "%04d%02d%02d_%02d%02d%02d",
     467         164 :                                                tm->tm_year+1900,
     468         164 :                                                tm->tm_mon+1,
     469             :                                                tm->tm_mday,
     470             :                                                tm->tm_hour,
     471             :                                                tm->tm_min,
     472             :                                                tm->tm_sec);
     473             :                 }
     474             :         }
     475             : }
     476             : 
     477         163 : char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
     478             : {
     479             :         struct timeval tv;
     480             : 
     481         163 :         GetTimeOfDay(&tv);
     482         163 :         return minimal_timeval_string(ctx, &tv, hires);
     483             : }
     484             : 
     485             : /**
     486             : return a HTTP/1.0 time string
     487             : **/
     488         572 : _PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t)
     489             : {
     490             :         char *buf;
     491             :         char tempTime[60];
     492         572 :         struct tm *tm = localtime(&t);
     493             : 
     494         572 :         if (t == TIME_T_MAX) {
     495           7 :                 return talloc_strdup(mem_ctx, "never");
     496             :         }
     497             : 
     498         565 :         if (!tm) {
     499           0 :                 return talloc_asprintf(mem_ctx,"%ld seconds since the Epoch",(long)t);
     500             :         }
     501             : 
     502             : #ifndef HAVE_STRFTIME
     503             :         buf = talloc_strdup(mem_ctx, asctime(tm));
     504             :         if (buf[strlen(buf)-1] == '\n') {
     505             :                 buf[strlen(buf)-1] = 0;
     506             :         }
     507             : #else
     508         565 :         strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
     509         565 :         buf = talloc_strdup(mem_ctx, tempTime);
     510             : #endif /* !HAVE_STRFTIME */
     511             : 
     512         565 :         return buf;
     513             : }
     514             : 
     515             : /**
     516             :  Return the date and time as a string
     517             : **/
     518      299670 : _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t)
     519             : {
     520             :         char *TimeBuf;
     521             :         char tempTime[80];
     522             :         struct tm *tm;
     523             : 
     524      299670 :         tm = localtime(&t);
     525      299670 :         if (!tm) {
     526           0 :                 return talloc_asprintf(mem_ctx,
     527             :                                        "%ld seconds since the Epoch",
     528             :                                        (long)t);
     529             :         }
     530             : 
     531             : #ifdef HAVE_STRFTIME
     532             :         /* Some versions of gcc complain about using some special format
     533             :          * specifiers. This is a bug in gcc, not a bug in this code. See a
     534             :          * recent strftime() manual page for details. */
     535      299670 :         strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
     536      299670 :         TimeBuf = talloc_strdup(mem_ctx, tempTime);
     537             : #else
     538             :         TimeBuf = talloc_strdup(mem_ctx, asctime(tm));
     539             :         if (TimeBuf == NULL) {
     540             :                 return NULL;
     541             :         }
     542             :         if (TimeBuf[0] != '\0') {
     543             :                 size_t len = strlen(TimeBuf);
     544             :                 if (TimeBuf[len - 1] == '\n') {
     545             :                         TimeBuf[len - 1] = '\0';
     546             :                 }
     547             :         }
     548             : #endif
     549             : 
     550      299670 :         return TimeBuf;
     551             : }
     552             : 
     553             : /**
     554             :   return a talloced string representing a NTTIME for human consumption
     555             : */
     556      278602 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
     557             : {
     558             :         time_t t;
     559      278602 :         if (nt == 0) {
     560        6441 :                 return "NTTIME(0)";
     561             :         }
     562      270957 :         t = nt_time_to_full_time_t(nt);
     563      270957 :         return timestring(mem_ctx, t);
     564             : }
     565             : 
     566             : 
     567             : /**
     568             :   put a NTTIME into a packet
     569             : */
     570      405353 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
     571             : {
     572      405353 :         SBVAL(base, offset,   t);
     573      405353 : }
     574             : 
     575             : /**
     576             :   pull a NTTIME from a packet
     577             : */
     578        2196 : _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
     579             : {
     580        2196 :         NTTIME ret = BVAL(base, offset);
     581        2196 :         return ret;
     582             : }
     583             : 
     584             : /**
     585             :   return (tv1 - tv2) in microseconds
     586             : */
     587      295174 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
     588             : {
     589      295174 :         int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
     590      295174 :         return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
     591             : }
     592             : 
     593             : /**
     594             :   return (tp1 - tp2) in nanoseconds
     595             : */
     596   355723636 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
     597             : {
     598   355723636 :         int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
     599   355723636 :         return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
     600             : }
     601             : 
     602             : 
     603             : /**
     604             :   return a zero timeval
     605             : */
     606      121758 : _PUBLIC_ struct timeval timeval_zero(void)
     607             : {
     608             :         struct timeval tv;
     609      121758 :         tv.tv_sec = 0;
     610      121758 :         tv.tv_usec = 0;
     611      121758 :         return tv;
     612             : }
     613             : 
     614             : /**
     615             :   return true if a timeval is zero
     616             : */
     617      957005 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
     618             : {
     619      957005 :         return tv->tv_sec == 0 && tv->tv_usec == 0;
     620             : }
     621             : 
     622             : /**
     623             :   return a timeval for the current time
     624             : */
     625    10952484 : _PUBLIC_ struct timeval timeval_current(void)
     626             : {
     627             :         struct timeval tv;
     628    10952484 :         GetTimeOfDay(&tv);
     629    10952484 :         return tv;
     630             : }
     631             : 
     632             : /**
     633             :   return a timeval struct with the given elements
     634             : */
     635       82496 : _PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs)
     636             : {
     637             :         struct timeval tv;
     638       82496 :         tv.tv_sec = secs;
     639       82496 :         tv.tv_usec = usecs;
     640       82496 :         return tv;
     641             : }
     642             : 
     643             : 
     644             : /**
     645             :   return a timeval ofs microseconds after tv
     646             : */
     647     5313772 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
     648             :                            uint32_t secs, uint32_t usecs)
     649             : {
     650     5313772 :         struct timeval tv2 = *tv;
     651     5313772 :         const unsigned int million = 1000000;
     652     5313772 :         tv2.tv_sec += secs;
     653     5313772 :         tv2.tv_usec += usecs;
     654     5313772 :         tv2.tv_sec += tv2.tv_usec / million;
     655     5313772 :         tv2.tv_usec = tv2.tv_usec % million;
     656     5313772 :         return tv2;
     657             : }
     658             : 
     659             : /**
     660             :   return the sum of two timeval structures
     661             : */
     662      101282 : struct timeval timeval_sum(const struct timeval *tv1,
     663             :                            const struct timeval *tv2)
     664             : {
     665      101282 :         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
     666             : }
     667             : 
     668             : /**
     669             :   return a timeval secs/usecs into the future
     670             : */
     671     1640565 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
     672             : {
     673     1640565 :         struct timeval tv = timeval_current();
     674     1640565 :         return timeval_add(&tv, secs, usecs);
     675             : }
     676             : 
     677             : /**
     678             :   return a timeval milliseconds into the future
     679             : */
     680     3123747 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
     681             : {
     682     3123747 :         struct timeval tv = timeval_current();
     683     3123747 :         return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
     684             : }
     685             : 
     686             : /**
     687             :   return a timeval microseconds into the future
     688             : */
     689      412458 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
     690             : {
     691      412458 :         struct timeval tv = timeval_current();
     692      412458 :         return timeval_add(&tv, usecs / 1000000, usecs % 1000000);
     693             : }
     694             : 
     695             : /**
     696             :   compare two timeval structures. 
     697             :   Return -1 if tv1 < tv2
     698             :   Return 0 if tv1 == tv2
     699             :   Return 1 if tv1 > tv2
     700             : */
     701        8583 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
     702             : {
     703        8583 :         if (tv1->tv_sec  > tv2->tv_sec)  return 1;
     704        7557 :         if (tv1->tv_sec  < tv2->tv_sec)  return -1;
     705        7405 :         if (tv1->tv_usec > tv2->tv_usec) return 1;
     706        3828 :         if (tv1->tv_usec < tv2->tv_usec) return -1;
     707          11 :         return 0;
     708             : }
     709             : 
     710             : /**
     711             :   return true if a timer is in the past
     712             : */
     713      490331 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
     714             : {
     715      490331 :         struct timeval tv2 = timeval_current();
     716      490331 :         if (tv2.tv_sec > tv->tv_sec) return true;
     717      490260 :         if (tv2.tv_sec < tv->tv_sec) return false;
     718        3006 :         return (tv2.tv_usec >= tv->tv_usec);
     719             : }
     720             : 
     721             : /**
     722             :   return the number of seconds elapsed between two times
     723             : */
     724      244739 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
     725             : {
     726      489478 :         return (tv2->tv_sec - tv1->tv_sec) + 
     727      244739 :                (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
     728             : }
     729             : 
     730             : /**
     731             :   return the number of seconds elapsed since a given time
     732             : */
     733      244337 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
     734             : {
     735      244337 :         struct timeval tv2 = timeval_current();
     736      244337 :         return timeval_elapsed2(tv, &tv2);
     737             : }
     738             : /**
     739             :  *   return the number of seconds elapsed between two times
     740             :  **/
     741         533 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
     742             :                                 const struct timespec *ts2)
     743             : {
     744        1066 :         return (ts2->tv_sec - ts1->tv_sec) +
     745         533 :                (ts2->tv_nsec - ts1->tv_nsec)*1.0e-9;
     746             : }
     747             : 
     748             : /**
     749             :  *   return the number of seconds elapsed since a given time
     750             :  */
     751         162 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
     752             : {
     753         162 :         struct timespec ts2 = timespec_current();
     754         162 :         return timespec_elapsed2(ts, &ts2);
     755             : }
     756             : 
     757             : /**
     758             :   return the lesser of two timevals
     759             : */
     760        4062 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
     761             :                            const struct timeval *tv2)
     762             : {
     763        4062 :         if (tv1->tv_sec < tv2->tv_sec) return *tv1;
     764        3649 :         if (tv1->tv_sec > tv2->tv_sec) return *tv2;
     765        3555 :         if (tv1->tv_usec < tv2->tv_usec) return *tv1;
     766           0 :         return *tv2;
     767             : }
     768             : 
     769             : /**
     770             :   return the greater of two timevals
     771             : */
     772           0 : _PUBLIC_ struct timeval timeval_max(const struct timeval *tv1,
     773             :                            const struct timeval *tv2)
     774             : {
     775           0 :         if (tv1->tv_sec > tv2->tv_sec) return *tv1;
     776           0 :         if (tv1->tv_sec < tv2->tv_sec) return *tv2;
     777           0 :         if (tv1->tv_usec > tv2->tv_usec) return *tv1;
     778           0 :         return *tv2;
     779             : }
     780             : 
     781             : /**
     782             :   return the difference between two timevals as a timeval
     783             :   if tv1 comes after tv2, then return a zero timeval
     784             :   (this is *tv2 - *tv1)
     785             : */
     786         135 : _PUBLIC_ struct timeval timeval_until(const struct timeval *tv1,
     787             :                              const struct timeval *tv2)
     788             : {
     789             :         struct timeval t;
     790         135 :         if (timeval_compare(tv1, tv2) >= 0) {
     791           0 :                 return timeval_zero();
     792             :         }
     793         135 :         t.tv_sec = tv2->tv_sec - tv1->tv_sec;
     794         135 :         if (tv1->tv_usec > tv2->tv_usec) {
     795           0 :                 t.tv_sec--;
     796           0 :                 t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
     797             :         } else {
     798         135 :                 t.tv_usec = tv2->tv_usec - tv1->tv_usec;
     799             :         }
     800         135 :         return t;
     801             : }
     802             : 
     803             : 
     804             : /**
     805             :   convert a timeval to a NTTIME
     806             : */
     807     7565721 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
     808             : {
     809    15131442 :         return 10*(tv->tv_usec + 
     810     7565721 :                   ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
     811             : }
     812             : 
     813             : /**
     814             :   convert a NTTIME to a timeval
     815             : */
     816       61961 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
     817             : {
     818       61961 :         if (tv == NULL) return;
     819             : 
     820       61961 :         t += 10/2;
     821       61961 :         t /= 10;
     822       61961 :         t -= TIME_FIXUP_CONSTANT*1000*1000;
     823             : 
     824       61961 :         tv->tv_sec  = t / 1000000;
     825             : 
     826       61837 :         if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) {
     827           0 :                 tv->tv_sec  = 0;
     828           0 :                 tv->tv_usec = 0;
     829           0 :                 return;
     830             :         }
     831             :         
     832       61961 :         tv->tv_usec = t - tv->tv_sec*1000000;
     833             : }
     834             : 
     835             : /*******************************************************************
     836             : yield the difference between *A and *B, in seconds, ignoring leap seconds
     837             : ********************************************************************/
     838       14041 : static int tm_diff(struct tm *a, struct tm *b)
     839             : {
     840       14041 :         int ay = a->tm_year + (1900 - 1);
     841       14041 :         int by = b->tm_year + (1900 - 1);
     842       14041 :         int intervening_leap_days =
     843       14041 :                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
     844       14041 :         int years = ay - by;
     845       14041 :         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
     846       14041 :         int hours = 24*days + (a->tm_hour - b->tm_hour);
     847       14041 :         int minutes = 60*hours + (a->tm_min - b->tm_min);
     848       14041 :         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
     849             : 
     850       14041 :         return seconds;
     851             : }
     852             : 
     853             : 
     854             : /**
     855             :   return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
     856             :  */
     857       14041 : _PUBLIC_ int get_time_zone(time_t t)
     858             : {
     859       14041 :         struct tm *tm = gmtime(&t);
     860             :         struct tm tm_utc;
     861       14041 :         if (!tm)
     862           0 :                 return 0;
     863       14041 :         tm_utc = *tm;
     864       14041 :         tm = localtime(&t);
     865       14041 :         if (!tm)
     866           0 :                 return 0;
     867       14041 :         return tm_diff(&tm_utc,tm);
     868             : }
     869             : 
     870     3307071 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
     871             : {
     872             :         int64_t d;
     873             :         struct timespec ret;
     874             : 
     875     3307071 :         if (nt == 0 || nt == (int64_t)-1) {
     876        7409 :                 ret.tv_sec = 0;
     877        7409 :                 ret.tv_nsec = 0;
     878        7409 :                 return ret;
     879             :         }
     880             : 
     881     3299662 :         d = (int64_t)nt;
     882             :         /* d is now in 100ns units, since jan 1st 1601".
     883             :            Save off the ns fraction. */
     884             : 
     885             :         /*
     886             :          * Take the last seven decimal digits and multiply by 100.
     887             :          * to convert from 100ns units to 1ns units.
     888             :          */
     889     3299662 :         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
     890             : 
     891             :         /* Convert to seconds */
     892     3299662 :         d /= 1000*1000*10;
     893             : 
     894             :         /* Now adjust by 369 years to make the secs since 1970 */
     895     3299662 :         d -= TIME_FIXUP_CONSTANT_INT;
     896             : 
     897     3299662 :         if (d <= (int64_t)TIME_T_MIN) {
     898         398 :                 ret.tv_sec = TIME_T_MIN;
     899         398 :                 ret.tv_nsec = 0;
     900         398 :                 return ret;
     901             :         }
     902             : 
     903     3178472 :         if (d >= (int64_t)TIME_T_MAX) {
     904           0 :                 ret.tv_sec = TIME_T_MAX;
     905           0 :                 ret.tv_nsec = 0;
     906           0 :                 return ret;
     907             :         }
     908             : 
     909     3299264 :         ret.tv_sec = (time_t)d;
     910     3299264 :         return ret;
     911             : }
     912             : 
     913             : 
     914             : /**
     915             :   check if 2 NTTIMEs are equal.
     916             : */
     917          64 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
     918             : {
     919          64 :         return *t1 == *t2;
     920             : }
     921             : 
     922             : /**
     923             :  Check if it's a null timespec.
     924             : **/
     925             : 
     926   190999932 : bool null_timespec(struct timespec ts)
     927             : {
     928   380601018 :         return ts.tv_sec == 0 || 
     929   380601018 :                 ts.tv_sec == (time_t)0xFFFFFFFF || 
     930   189601086 :                 ts.tv_sec == (time_t)-1;
     931             : }
     932             : 
     933             : /****************************************************************************
     934             :  Convert a normalized timeval to a timespec.
     935             : ****************************************************************************/
     936             : 
     937           8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
     938             : {
     939             :         struct timespec ts;
     940           8 :         ts.tv_sec = tv.tv_sec;
     941           8 :         ts.tv_nsec = tv.tv_usec * 1000;
     942           8 :         return ts;
     943             : }
     944             : 
     945             : /****************************************************************************
     946             :  Convert a normalized timespec to a timeval.
     947             : ****************************************************************************/
     948             : 
     949           8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
     950             : {
     951             :         struct timeval tv;
     952           8 :         tv.tv_sec = ts.tv_sec;
     953           8 :         tv.tv_usec = ts.tv_nsec / 1000;
     954           8 :         return tv;
     955             : }
     956             : 
     957             : /****************************************************************************
     958             :  Return a timespec for the current time
     959             : ****************************************************************************/
     960             : 
     961      310109 : _PUBLIC_ struct timespec timespec_current(void)
     962             : {
     963             :         struct timespec ts;
     964      310109 :         clock_gettime(CLOCK_REALTIME, &ts);
     965      310109 :         return ts;
     966             : }
     967             : 
     968             : /****************************************************************************
     969             :  Return the lesser of two timespecs.
     970             : ****************************************************************************/
     971             : 
     972           0 : struct timespec timespec_min(const struct timespec *ts1,
     973             :                            const struct timespec *ts2)
     974             : {
     975           0 :         if (ts1->tv_sec < ts2->tv_sec) return *ts1;
     976           0 :         if (ts1->tv_sec > ts2->tv_sec) return *ts2;
     977           0 :         if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
     978           0 :         return *ts2;
     979             : }
     980             : 
     981             : /****************************************************************************
     982             :   compare two timespec structures. 
     983             :   Return -1 if ts1 < ts2
     984             :   Return 0 if ts1 == ts2
     985             :   Return 1 if ts1 > ts2
     986             : ****************************************************************************/
     987             : 
     988   192769564 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
     989             : {
     990   192769564 :         if (ts1->tv_sec  > ts2->tv_sec)  return 1;
     991   181074641 :         if (ts1->tv_sec  < ts2->tv_sec)  return -1;
     992   178538820 :         if (ts1->tv_nsec > ts2->tv_nsec) return 1;
     993   155543558 :         if (ts1->tv_nsec < ts2->tv_nsec) return -1;
     994   137305937 :         return 0;
     995             : }
     996             : 
     997             : /****************************************************************************
     998             :  Round up a timespec if nsec > 500000000, round down if lower,
     999             :  then zero nsec.
    1000             : ****************************************************************************/
    1001             : 
    1002          92 : void round_timespec_to_sec(struct timespec *ts)
    1003             : {
    1004          92 :         ts->tv_sec = convert_timespec_to_time_t(*ts);
    1005          92 :         ts->tv_nsec = 0;
    1006          92 : }
    1007             : 
    1008             : /****************************************************************************
    1009             :  Round a timespec to usec value.
    1010             : ****************************************************************************/
    1011             : 
    1012           0 : void round_timespec_to_usec(struct timespec *ts)
    1013             : {
    1014           0 :         struct timeval tv = convert_timespec_to_timeval(*ts);
    1015           0 :         *ts = convert_timeval_to_timespec(tv);
    1016           0 :         normalize_timespec(ts);
    1017           0 : }
    1018             : 
    1019             : /****************************************************************************
    1020             :  Round a timespec to NTTIME resolution.
    1021             : ****************************************************************************/
    1022             : 
    1023     1316328 : void round_timespec_to_nttime(struct timespec *ts)
    1024             : {
    1025     1316328 :         ts->tv_nsec = (ts->tv_nsec / 100) * 100;
    1026     1316328 : }
    1027             : 
    1028             : /****************************************************************************
    1029             :  Put a 8 byte filetime from a struct timespec. Uses GMT.
    1030             : ****************************************************************************/
    1031             : 
    1032       10222 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
    1033             : {
    1034             :         uint64_t d;
    1035             : 
    1036       10222 :         if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
    1037           0 :                 return 0;
    1038             :         }
    1039       10222 :         if (ts.tv_sec == TIME_T_MAX) {
    1040           0 :                 return 0x7fffffffffffffffLL;
    1041             :         }
    1042       10222 :         if (ts.tv_sec == (time_t)-1) {
    1043           0 :                 return (uint64_t)-1;
    1044             :         }
    1045             : 
    1046       10222 :         d = ts.tv_sec;
    1047       10222 :         d += TIME_FIXUP_CONSTANT_INT;
    1048       10222 :         d *= 1000*1000*10;
    1049             :         /* d is now in 100ns units. */
    1050       10222 :         d += (ts.tv_nsec / 100);
    1051             : 
    1052       10222 :         return d;
    1053             : }
    1054             : 
    1055             : /*
    1056             :  * Functions supporting the full range of time_t and struct timespec values,
    1057             :  * including 0, -1 and all other negative values. These functions don't use 0 or
    1058             :  * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
    1059             :  * define UTIME_OMIT from utimensat(2).
    1060             :  */
    1061             : 
    1062             : /**
    1063             :  * Check if it's a to be omitted timespec.
    1064             :  **/
    1065     9998028 : bool is_omit_timespec(const struct timespec *ts)
    1066             : {
    1067     9998028 :         return ts->tv_nsec == SAMBA_UTIME_OMIT;
    1068             : }
    1069             : 
    1070             : /**
    1071             :  * Return a to be omitted timespec.
    1072             :  **/
    1073    12593545 : struct timespec make_omit_timespec(void)
    1074             : {
    1075    12593545 :         return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1076             : }
    1077             : 
    1078             : /**
    1079             :  * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
    1080             :  * and -1. Also dealing with SAMBA_UTIME_OMIT.
    1081             :  **/
    1082     4810331 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
    1083             : {
    1084     4810331 :         struct timespec ts = *_ts;
    1085             :         uint64_t d;
    1086             : 
    1087     4810331 :         if (is_omit_timespec(_ts)) {
    1088     1500427 :                 return NTTIME_OMIT;
    1089             :         }
    1090             : 
    1091             :         /* Ensure tv_nsec is less than 1 sec. */
    1092     6148312 :         while (ts.tv_nsec > 1000000000) {
    1093           0 :                 if (ts.tv_sec > TIME_T_MAX) {
    1094           0 :                         return NTTIME_MAX;
    1095             :                 }
    1096           0 :                 ts.tv_sec += 1;
    1097           0 :                 ts.tv_nsec -= 1000000000;
    1098             :         }
    1099             : 
    1100     3307836 :         if (ts.tv_sec >= TIME_T_MAX) {
    1101           0 :                 return NTTIME_MAX;
    1102             :         }
    1103     3307836 :         if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
    1104           0 :                 return NTTIME_MIN;
    1105             :         }
    1106             : 
    1107     3307836 :         d = TIME_FIXUP_CONSTANT_INT;
    1108     3307836 :         d += ts.tv_sec;
    1109             : 
    1110     3307836 :         d *= 1000*1000*10;
    1111             :         /* d is now in 100ns units. */
    1112     3307836 :         d += (ts.tv_nsec / 100);
    1113             : 
    1114     3307836 :         return d;
    1115             : }
    1116             : 
    1117             : /**
    1118             :  * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
    1119             :  * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
    1120             :  *
    1121             :  * See also: is_omit_timespec().
    1122             :  **/
    1123     2060287 : struct timespec nt_time_to_full_timespec(NTTIME nt)
    1124             : {
    1125             :         int64_t d;
    1126             :         struct timespec ret;
    1127             : 
    1128     2060287 :         if (nt == NTTIME_OMIT) {
    1129       55627 :                 return make_omit_timespec();
    1130             :         }
    1131     2004660 :         if (nt == NTTIME_FREEZE) {
    1132             :                 /*
    1133             :                  * This should be returned as SAMBA_UTIME_FREEZE in the
    1134             :                  * future.
    1135             :                  */
    1136        4157 :                 return make_omit_timespec();
    1137             :         }
    1138     2000503 :         if (nt > NTTIME_MAX) {
    1139           8 :                 nt = NTTIME_MAX;
    1140             :         }
    1141             : 
    1142     2000503 :         d = (int64_t)nt;
    1143             :         /* d is now in 100ns units, since jan 1st 1601".
    1144             :            Save off the ns fraction. */
    1145             : 
    1146             :         /*
    1147             :          * Take the last seven decimal digits and multiply by 100.
    1148             :          * to convert from 100ns units to 1ns units.
    1149             :          */
    1150     2000503 :         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
    1151             : 
    1152             :         /* Convert to seconds */
    1153     2000503 :         d /= 1000*1000*10;
    1154             : 
    1155             :         /* Now adjust by 369 years to make the secs since 1970 */
    1156     2000503 :         d -= TIME_FIXUP_CONSTANT_INT;
    1157             : 
    1158     1993928 :         if (d >= (int64_t)TIME_T_MAX) {
    1159           0 :                 ret.tv_sec = TIME_T_MAX;
    1160           0 :                 ret.tv_nsec = 0;
    1161           0 :                 return ret;
    1162             :         }
    1163             : 
    1164     2000503 :         ret.tv_sec = (time_t)d;
    1165     2000503 :         return ret;
    1166             : }
    1167             : 
    1168             : /**
    1169             :  * Note: this function uses the full time_t range as valid date values including
    1170             :  * (time_t)0 and -1. That means that struct timespec sentinel values (cf
    1171             :  * is_omit_timespec()) can't be converted to sentinel values in a time_t
    1172             :  * representation. Callers should therefor check the NTTIME value with
    1173             :  * null_nttime() before calling this function.
    1174             :  **/
    1175      270957 : time_t full_timespec_to_time_t(const struct timespec *_ts)
    1176             : {
    1177      270957 :         struct timespec ts = *_ts;
    1178             : 
    1179      270957 :         if (is_omit_timespec(_ts)) {
    1180             :                 /*
    1181             :                  * Unfortunately there's no sensible sentinel value in the
    1182             :                  * time_t range that is not conflicting with a valid time value
    1183             :                  * ((time_t)0 and -1 are valid time values). Bite the bullit and
    1184             :                  * return 0.
    1185             :                  */
    1186           0 :                 return 0;
    1187             :         }
    1188             : 
    1189             :         /* Ensure tv_nsec is less than 1sec. */
    1190      534519 :         while (ts.tv_nsec > 1000000000) {
    1191           0 :                 ts.tv_sec += 1;
    1192           0 :                 ts.tv_nsec -= 1000000000;
    1193             :         }
    1194             : 
    1195             :         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
    1196             :            increment if it's greater than 500 millionth of a second. */
    1197             : 
    1198      270957 :         if (ts.tv_nsec > 500000000) {
    1199       17801 :                 return ts.tv_sec + 1;
    1200             :         }
    1201      249588 :         return ts.tv_sec;
    1202             : }
    1203             : 
    1204             : /**
    1205             :  * Like nt_time_to_unix() but supports negative time_t values.
    1206             :  *
    1207             :  * Note: this function uses the full time_t range as valid date values including
    1208             :  * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
    1209             :  * represent a "not-set" value, can't be converted to sentinel values in a
    1210             :  * time_t representation. Callers should therefor check the NTTIME value with
    1211             :  * null_nttime() before calling this function.
    1212             :  **/
    1213      270957 : time_t nt_time_to_full_time_t(NTTIME nt)
    1214             : {
    1215             :         struct timespec ts;
    1216             : 
    1217      270957 :         ts = nt_time_to_full_timespec(nt);
    1218      270957 :         return full_timespec_to_time_t(&ts);
    1219             : }
    1220             : 
    1221             : /**
    1222             :  * Like time_t_to_unix_timespec() but supports negative time_t values.
    1223             :  *
    1224             :  * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
    1225             :  * can't be used as valid date values. The function supports values < -1 though.
    1226             :  **/
    1227       32376 : struct timespec time_t_to_full_timespec(time_t t)
    1228             : {
    1229       32376 :         if (null_time(t)) {
    1230       32186 :                 return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1231             :         }
    1232         190 :         return (struct timespec){.tv_sec = t};
    1233             : }
    1234             : 
    1235             : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
    1236             : 
    1237             : /* Old system - no ns timestamp. */
    1238             : time_t get_atimensec(const struct stat *st)
    1239             : {
    1240             :         return 0;
    1241             : }
    1242             : 
    1243             : time_t get_mtimensec(const struct stat *st)
    1244             : {
    1245             :         return 0;
    1246             : }
    1247             : 
    1248             : time_t get_ctimensec(const struct stat *st)
    1249             : {
    1250             :         return 0;
    1251             : }
    1252             : 
    1253             : /* Set does nothing with no ns timestamp. */
    1254             : void set_atimensec(struct stat *st, time_t ns)
    1255             : {
    1256             :         return;
    1257             : }
    1258             : 
    1259             : void set_mtimensec(struct stat *st, time_t ns)
    1260             : {
    1261             :         return;
    1262             : }
    1263             : 
    1264             : void set_ctimensec(struct stat *st, time_t ns)
    1265             : {
    1266             :         return;
    1267             : }
    1268             : 
    1269             : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
    1270             : 
    1271             : time_t get_atimensec(const struct stat *st)
    1272             : {
    1273             :         return st->st_atimespec.tv_nsec;
    1274             : }
    1275             : 
    1276             : time_t get_mtimensec(const struct stat *st)
    1277             : {
    1278             :         return st->st_mtimespec.tv_nsec;
    1279             : }
    1280             : 
    1281             : time_t get_ctimensec(const struct stat *st)
    1282             : {
    1283             :         return st->st_ctimespec.tv_nsec;
    1284             : }
    1285             : 
    1286             : void set_atimensec(struct stat *st, time_t ns)
    1287             : {
    1288             :         st->st_atimespec.tv_nsec = ns;
    1289             : }
    1290             : 
    1291             : void set_mtimensec(struct stat *st, time_t ns)
    1292             : {
    1293             :         st->st_mtimespec.tv_nsec = ns;
    1294             : }
    1295             : 
    1296             : void set_ctimensec(struct stat *st, time_t ns)
    1297             : {
    1298             :         st->st_ctimespec.tv_nsec = ns;
    1299             : }
    1300             : 
    1301             : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
    1302             : 
    1303   191616360 : time_t get_atimensec(const struct stat *st)
    1304             : {
    1305   191616360 :         return st->st_atim.tv_nsec;
    1306             : }
    1307             : 
    1308   191616364 : time_t get_mtimensec(const struct stat *st)
    1309             : {
    1310   191616364 :         return st->st_mtim.tv_nsec;
    1311             : }
    1312             : 
    1313   192418268 : time_t get_ctimensec(const struct stat *st)
    1314             : {
    1315   192418268 :         return st->st_ctim.tv_nsec;
    1316             : }
    1317             : 
    1318         342 : void set_atimensec(struct stat *st, time_t ns)
    1319             : {
    1320         342 :         st->st_atim.tv_nsec = ns;
    1321         342 : }
    1322             : 
    1323         342 : void set_mtimensec(struct stat *st, time_t ns)
    1324             : {
    1325         342 :         st->st_mtim.tv_nsec = ns;
    1326         342 : }
    1327         342 : void set_ctimensec(struct stat *st, time_t ns)
    1328             : {
    1329         342 :         st->st_ctim.tv_nsec = ns;
    1330         342 : }
    1331             : 
    1332             : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
    1333             : 
    1334             : time_t get_atimensec(const struct stat *st)
    1335             : {
    1336             :         return st->st_atimensec;
    1337             : }
    1338             : 
    1339             : time_t get_mtimensec(const struct stat *st)
    1340             : {
    1341             :         return st->st_mtimensec;
    1342             : }
    1343             : 
    1344             : time_t get_ctimensec(const struct stat *st)
    1345             : {
    1346             :         return st->st_ctimensec;
    1347             : }
    1348             : 
    1349             : void set_atimensec(struct stat *st, time_t ns)
    1350             : {
    1351             :         st->st_atimensec = ns;
    1352             : }
    1353             : 
    1354             : void set_mtimensec(struct stat *st, time_t ns)
    1355             : {
    1356             :         st->st_mtimensec = ns;
    1357             : }
    1358             : 
    1359             : void set_ctimensec(struct stat *st, time_t ns)
    1360             : {
    1361             :         st->st_ctimensec = ns;
    1362             : }
    1363             : 
    1364             : #elif HAVE_STRUCT_STAT_ST_MTIME_N
    1365             : 
    1366             : time_t get_atimensec(const struct stat *st)
    1367             : {
    1368             :         return st->st_atime_n;
    1369             : }
    1370             : 
    1371             : time_t get_mtimensec(const struct stat *st)
    1372             : {
    1373             :         return st->st_mtime_n;
    1374             : }
    1375             : 
    1376             : time_t get_ctimensec(const struct stat *st)
    1377             : {
    1378             :         return st->st_ctime_n;
    1379             : }
    1380             : 
    1381             : void set_atimensec(struct stat *st, time_t ns)
    1382             : {
    1383             :         st->st_atime_n = ns;
    1384             : }
    1385             : 
    1386             : void set_mtimensec(struct stat *st, time_t ns)
    1387             : {
    1388             :         st->st_mtime_n = ns;
    1389             : }
    1390             : 
    1391             : void set_ctimensec(struct stat *st, time_t ns)
    1392             : {
    1393             :         st->st_ctime_n = ns;
    1394             : }
    1395             : 
    1396             : #elif HAVE_STRUCT_STAT_ST_UMTIME
    1397             : 
    1398             : /* Only usec timestamps available. Convert to/from nsec. */
    1399             : 
    1400             : time_t get_atimensec(const struct stat *st)
    1401             : {
    1402             :         return st->st_uatime * 1000;
    1403             : }
    1404             : 
    1405             : time_t get_mtimensec(const struct stat *st)
    1406             : {
    1407             :         return st->st_umtime * 1000;
    1408             : }
    1409             : 
    1410             : time_t get_ctimensec(const struct stat *st)
    1411             : {
    1412             :         return st->st_uctime * 1000;
    1413             : }
    1414             : 
    1415             : void set_atimensec(struct stat *st, time_t ns)
    1416             : {
    1417             :         st->st_uatime = ns / 1000;
    1418             : }
    1419             : 
    1420             : void set_mtimensec(struct stat *st, time_t ns)
    1421             : {
    1422             :         st->st_umtime = ns / 1000;
    1423             : }
    1424             : 
    1425             : void set_ctimensec(struct stat *st, time_t ns)
    1426             : {
    1427             :         st->st_uctime = ns / 1000;
    1428             : }
    1429             : 
    1430             : #else
    1431             : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
    1432             : #endif
    1433             : 
    1434   190814448 : struct timespec get_atimespec(const struct stat *pst)
    1435             : {
    1436             :         struct timespec ret;
    1437             : 
    1438   190814448 :         ret.tv_sec = pst->st_atime;
    1439   190814448 :         ret.tv_nsec = get_atimensec(pst);
    1440   190814448 :         return ret;
    1441             : }
    1442             : 
    1443   190814448 : struct timespec get_mtimespec(const struct stat *pst)
    1444             : {
    1445             :         struct timespec ret;
    1446             : 
    1447   190814448 :         ret.tv_sec = pst->st_mtime;
    1448   190814448 :         ret.tv_nsec = get_mtimensec(pst);
    1449   190814448 :         return ret;
    1450             : }
    1451             : 
    1452   190814444 : struct timespec get_ctimespec(const struct stat *pst)
    1453             : {
    1454             :         struct timespec ret;
    1455             : 
    1456   190814444 :         ret.tv_sec = pst->st_mtime;
    1457   190814444 :         ret.tv_nsec = get_ctimensec(pst);
    1458   190814444 :         return ret;
    1459             : }
    1460             : 
    1461             : /****************************************************************************
    1462             :  Deal with nanoseconds overflow.
    1463             : ****************************************************************************/
    1464             : 
    1465     3818391 : void normalize_timespec(struct timespec *ts)
    1466             : {
    1467             :         lldiv_t dres;
    1468             : 
    1469             :         /* most likely case: nsec is valid */
    1470     3818391 :         if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
    1471     7000515 :                 return;
    1472             :         }
    1473             : 
    1474       21104 :         dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
    1475             : 
    1476             :         /* if the operation would result in overflow, max out values and bail */
    1477       21104 :         if (dres.quot > 0) {
    1478       21092 :                 if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
    1479           1 :                         ts->tv_sec = LONG_MAX;
    1480           1 :                         ts->tv_nsec = NSEC_PER_SEC - 1;
    1481           1 :                         return;
    1482             :                 }
    1483             :         } else {
    1484          12 :                 if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
    1485           1 :                         ts->tv_sec = LONG_MIN;
    1486           1 :                         ts->tv_nsec = 0;
    1487           1 :                         return;
    1488             :                 }
    1489             :         }
    1490             : 
    1491       21102 :         ts->tv_nsec = dres.rem;
    1492       21102 :         ts->tv_sec += dres.quot;
    1493             : 
    1494             :         /* if the ns part was positive or a multiple of -1000000000, we're done */
    1495       21102 :         if (ts->tv_nsec > 0 || dres.rem == 0) {
    1496       21084 :                 return;
    1497             :         }
    1498             : 
    1499           9 :         ts->tv_nsec += NSEC_PER_SEC;
    1500           9 :         --ts->tv_sec;
    1501             : }

Generated by: LCOV version 1.13