LCOV - code coverage report
Current view: top level - lib/util - time.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 438 516 84.9 %
Date: 2023-11-21 12:31:41 Functions: 78 83 94.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    time handling functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell                1992-2004
       6             :    Copyright (C) Stefan (metze) Metzmacher      2002
       7             :    Copyright (C) Jeremy Allison                 2007
       8             :    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      394008 : _PUBLIC_ time_t get_time_t_max(void)
      52             : {
      53      394008 :         return TIME_T_MAX;
      54             : }
      55             : 
      56             : /**
      57             : a wrapper to preferably get the monotonic time
      58             : **/
      59   428135929 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
      60             : {
      61             : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
      62             : #ifdef CLOCK_BOOTTIME
      63   428135929 :         if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
      64   427737820 :                 return;
      65             :         }
      66             : #endif
      67             : /* then try the  monotonic clock: */
      68             : #ifndef CUSTOM_CLOCK_MONOTONIC_IS_REALTIME
      69           2 :         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        6941 : _PUBLIC_ time_t time_mono(time_t *t)
      80             : {
      81           0 :         struct timespec tp;
      82             : 
      83        6941 :         clock_gettime_mono(&tp);
      84        6941 :         if (t != NULL) {
      85           0 :                 *t = tp.tv_sec;
      86             :         }
      87        6941 :         return tp.tv_sec;
      88             : }
      89             : 
      90             : 
      91             : #define TIME_FIXUP_CONSTANT 11644473600LL
      92             : 
      93     5651202 : time_t convert_timespec_to_time_t(struct timespec ts)
      94             : {
      95             :         /* Ensure tv_nsec is less than 1sec. */
      96     5651202 :         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     5651202 :         if (ts.tv_nsec > 500000000) {
     102     1472979 :                 return ts.tv_sec + 1;
     103             :         }
     104     4178223 :         return ts.tv_sec;
     105             : }
     106             : 
     107           0 : struct timespec convert_time_t_to_timespec(time_t t)
     108             : {
     109           0 :         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     2725819 : time_t nt_time_to_unix(NTTIME nt)
     129             : {
     130     2725819 :         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     7006011 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
     139             : {
     140      265057 :         uint64_t t2;
     141             : 
     142     7006011 :         if (t == (time_t)-1) {
     143           1 :                 *nt = (NTTIME)-1LL;
     144           1 :                 return;
     145             :         }
     146             : 
     147     7006010 :         if (t == TIME_T_MAX || t == INT64_MAX) {
     148       60652 :                 *nt = 0x7fffffffffffffffLL;
     149       60652 :                 return;
     150             :         }
     151             : 
     152     6945358 :         if (t == 0) {
     153       21748 :                 *nt = 0;
     154       21748 :                 return;
     155             :         }
     156             : 
     157     6923610 :         t2 = t;
     158     6923610 :         t2 += TIME_FIXUP_CONSTANT_INT;
     159     6923610 :         t2 *= 1000*1000*10;
     160             : 
     161     6923610 :         *nt = t2;
     162             : }
     163             : 
     164             : 
     165             : /**
     166             : check if it's a null unix time
     167             : **/
     168      913165 : _PUBLIC_ bool null_time(time_t t)
     169             : {
     170       85031 :         return t == 0 ||
     171      996706 :                 t == (time_t)0xFFFFFFFF ||
     172             :                 t == (time_t)-1;
     173             : }
     174             : 
     175             : 
     176             : /**
     177             : check if it's a null NTTIME
     178             : **/
     179     2498458 : _PUBLIC_ bool null_nttime(NTTIME t)
     180             : {
     181     2498458 :         return t == 0;
     182             : }
     183             : 
     184             : /*******************************************************************
     185             :   create a 16 bit dos packed date
     186             : ********************************************************************/
     187      440962 : static uint16_t make_dos_date1(struct tm *t)
     188             : {
     189      440962 :         uint16_t ret=0;
     190      440962 :         ret = (((unsigned int)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
     191      440962 :         ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
     192      440962 :         return ret;
     193             : }
     194             : 
     195             : /*******************************************************************
     196             :   create a 16 bit dos packed time
     197             : ********************************************************************/
     198      440962 : static uint16_t make_dos_time1(struct tm *t)
     199             : {
     200      440962 :         uint16_t ret=0;
     201      440962 :         ret = ((((unsigned int)t->tm_min >> 3)&0x7) | (((unsigned int)t->tm_hour) << 3));
     202      440962 :         ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
     203      440962 :         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      441090 : static uint32_t make_dos_date(time_t unixdate, int zone_offset)
     211             : {
     212         223 :         struct tm *t;
     213      441090 :         uint32_t ret=0;
     214             : 
     215      441090 :         if (unixdate == 0) {
     216         111 :                 return 0;
     217             :         }
     218             : 
     219      440962 :         unixdate -= zone_offset;
     220             : 
     221      440962 :         t = gmtime(&unixdate);
     222      440962 :         if (!t) {
     223           0 :                 return 0xFFFFFFFF;
     224             :         }
     225             : 
     226      440962 :         ret = make_dos_date1(t);
     227      440962 :         ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
     228             : 
     229      440962 :         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       33632 : _PUBLIC_ void push_dos_date(uint8_t *buf, int offset, time_t unixdate, int zone_offset)
     237             : {
     238       33632 :         uint32_t x = make_dos_date(unixdate, zone_offset);
     239       33632 :         SIVAL(buf,offset,x);
     240       33632 : }
     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      407458 : _PUBLIC_ void push_dos_date2(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     247             : {
     248         206 :         uint32_t x;
     249      407458 :         x = make_dos_date(unixdate, zone_offset);
     250      407458 :         x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
     251      407458 :         SIVAL(buf,offset,x);
     252      407458 : }
     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      169266 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     260             : {
     261      169266 :         if (!null_time(unixdate)) {
     262       29180 :                 unixdate -= zone_offset;
     263             :         }
     264      169266 :         SIVAL(buf,offset,unixdate);
     265      169266 : }
     266             : 
     267             : /*******************************************************************
     268             :   interpret a 32 bit dos packed date/time to some parameters
     269             : ********************************************************************/
     270      440823 : void interpret_dos_date(uint32_t date,int *year,int *month,int *day,int *hour,int *minute,int *second)
     271             : {
     272         195 :         uint32_t p0,p1,p2,p3;
     273             : 
     274      440823 :         p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
     275      440823 :         p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
     276             : 
     277      440823 :         *second = 2*(p0 & 0x1F);
     278      440823 :         *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
     279      440823 :         *hour = (p1>>3)&0xFF;
     280      440823 :         *day = (p2&0x1F);
     281      440823 :         *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
     282      440823 :         *year = ((p3>>1)&0xFF) + 80;
     283      440823 : }
     284             : 
     285             : /**
     286             :   create a unix date (int GMT) from a dos date (which is actually in
     287             :   localtime)
     288             : **/
     289      440894 : _PUBLIC_ time_t pull_dos_date(const uint8_t *date_ptr, int zone_offset)
     290             : {
     291      440894 :         uint32_t dos_date=0;
     292         195 :         struct tm t;
     293         195 :         time_t ret;
     294             : 
     295      440894 :         dos_date = IVAL(date_ptr,0);
     296             : 
     297      440894 :         if (dos_date == 0) return (time_t)0;
     298             : 
     299      440823 :         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      440823 :         t.tm_isdst = -1;
     302             : 
     303      440823 :         ret = timegm(&t);
     304             : 
     305      440823 :         ret += zone_offset;
     306             : 
     307      440823 :         return ret;
     308             : }
     309             : 
     310             : /**
     311             : like make_unix_date() but the words are reversed
     312             : **/
     313      407355 : _PUBLIC_ time_t pull_dos_date2(const uint8_t *date_ptr, int zone_offset)
     314             : {
     315         195 :         uint32_t x,x2;
     316             : 
     317      407355 :         x = IVAL(date_ptr,0);
     318      407355 :         x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
     319      407355 :         SIVAL(&x,0,x2);
     320             : 
     321      407355 :         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      147605 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
     329             : {
     330      147605 :         time_t t = (time_t)IVAL(date_ptr,0);
     331             : 
     332      147605 :         if (t == (time_t)0xFFFFFFFF) {
     333        4092 :                 t = (time_t)-1;
     334             :         }
     335             : 
     336      147605 :         if (!null_time(t)) {
     337       27796 :                 t += zone_offset;
     338             :         }
     339      147605 :         return t;
     340             : }
     341             : 
     342             : /****************************************************************************
     343             :  Return the date and time as a string
     344             : ****************************************************************************/
     345             : 
     346         218 : char *timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
     347             : {
     348          36 :         struct timeval_buf tmp;
     349          36 :         char *result;
     350             : 
     351         218 :         result = talloc_strdup(ctx, timeval_str_buf(tp, false, hires, &tmp));
     352         218 :         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         218 :         talloc_set_name_const(result, result);
     366         218 :         return result;
     367             : }
     368             : 
     369             : /****************************************************************************
     370             :  Return the date and time as a string
     371             : ****************************************************************************/
     372             : 
     373         173 : const char *timespec_string_buf(const struct timespec *tp,
     374             :                                 bool hires,
     375             :                                 struct timeval_buf *buf)
     376             : {
     377           1 :         time_t t;
     378         173 :         struct tm *tm = NULL;
     379           1 :         int len;
     380             : 
     381         173 :         if (is_omit_timespec(tp)) {
     382           0 :                 strlcpy(buf->buf, "SAMBA_UTIME_OMIT", sizeof(buf->buf));
     383           0 :                 return buf->buf;
     384             :         }
     385             : 
     386         173 :         t = (time_t)tp->tv_sec;
     387         173 :         tm = localtime(&t);
     388             : 
     389         173 :         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         173 :         } 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         173 :                 len = snprintf(buf->buf, sizeof(buf->buf),
     409             :                                "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
     410         173 :                                1900 + tm->tm_year,
     411         173 :                                tm->tm_mon + 1,
     412             :                                tm->tm_mday,
     413             :                                tm->tm_hour,
     414             :                                tm->tm_min,
     415             :                                tm->tm_sec,
     416         173 :                                (long)tp->tv_nsec);
     417             :         }
     418         173 :         if (len == -1) {
     419           0 :                 return "";
     420             :         }
     421             : 
     422         173 :         return buf->buf;
     423             : }
     424             : 
     425         218 : char *current_timestring(TALLOC_CTX *ctx, bool hires)
     426             : {
     427          36 :         struct timeval tv;
     428             : 
     429         218 :         GetTimeOfDay(&tv);
     430         218 :         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         166 : char *minimal_timeval_string(TALLOC_CTX *ctx, const struct timeval *tp, bool hires)
     439             : {
     440           2 :         time_t t;
     441           2 :         struct tm *tm;
     442             : 
     443         166 :         t = (time_t)tp->tv_sec;
     444         166 :         tm = localtime(&t);
     445         166 :         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         166 :                 if (hires) {
     455           1 :                         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         165 :                         return talloc_asprintf(ctx,
     466             :                                                "%04d%02d%02d_%02d%02d%02d",
     467         165 :                                                tm->tm_year+1900,
     468         165 :                                                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         164 : char *current_minimal_timestring(TALLOC_CTX *ctx, bool hires)
     478             : {
     479           0 :         struct timeval tv;
     480             : 
     481         164 :         GetTimeOfDay(&tv);
     482         164 :         return minimal_timeval_string(ctx, &tv, hires);
     483             : }
     484             : 
     485             : /**
     486             : return a HTTP/1.0 time string
     487             : **/
     488         549 : _PUBLIC_ char *http_timestring(TALLOC_CTX *mem_ctx, time_t t)
     489             : {
     490           2 :         char *buf;
     491           2 :         char tempTime[60];
     492         549 :         struct tm *tm = localtime(&t);
     493             : 
     494         549 :         if (t == TIME_T_MAX) {
     495           7 :                 return talloc_strdup(mem_ctx, "never");
     496             :         }
     497             : 
     498         542 :         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         542 :         strftime(tempTime, sizeof(tempTime)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
     509         542 :         buf = talloc_strdup(mem_ctx, tempTime);
     510             : #endif /* !HAVE_STRFTIME */
     511             : 
     512         542 :         return buf;
     513             : }
     514             : 
     515             : /**
     516             :  Return the date and time as a string
     517             : **/
     518      285653 : _PUBLIC_ char *timestring(TALLOC_CTX *mem_ctx, time_t t)
     519             : {
     520        4224 :         char *TimeBuf;
     521        4224 :         char tempTime[80];
     522        4224 :         struct tm *tm;
     523             : 
     524      285653 :         tm = localtime(&t);
     525      285653 :         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      285653 :         strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
     536      285653 :         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      285653 :         return TimeBuf;
     551             : }
     552             : 
     553             : /**
     554             :   return a talloced string representing a NTTIME for human consumption
     555             : */
     556      264753 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
     557             : {
     558        5318 :         time_t t;
     559      264753 :         if (nt == 0) {
     560        7016 :                 return "NTTIME(0)";
     561             :         }
     562      256401 :         t = nt_time_to_full_time_t(nt);
     563      256401 :         return timestring(mem_ctx, t);
     564             : }
     565             : 
     566             : 
     567             : /**
     568             :   put a NTTIME into a packet
     569             : */
     570      425428 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
     571             : {
     572      425428 :         SBVAL(base, offset,   t);
     573      425428 : }
     574             : 
     575             : /**
     576             :   pull a NTTIME from a packet
     577             : */
     578        2204 : _PUBLIC_ NTTIME pull_nttime(uint8_t *base, uint16_t offset)
     579             : {
     580        2204 :         NTTIME ret = BVAL(base, offset);
     581        2204 :         return ret;
     582             : }
     583             : 
     584             : /**
     585             :   return (tv1 - tv2) in microseconds
     586             : */
     587      394305 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
     588             : {
     589      394305 :         int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
     590      394305 :         return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
     591             : }
     592             : 
     593             : /**
     594             :   return (tp1 - tp2) in nanoseconds
     595             : */
     596   213738538 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
     597             : {
     598   213738538 :         int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
     599   213738538 :         return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
     600             : }
     601             : 
     602             : 
     603             : /**
     604             :   return a zero timeval
     605             : */
     606      139009 : _PUBLIC_ struct timeval timeval_zero(void)
     607             : {
     608        2476 :         struct timeval tv;
     609      139009 :         tv.tv_sec = 0;
     610      139009 :         tv.tv_usec = 0;
     611      139009 :         return tv;
     612             : }
     613             : 
     614             : /**
     615             :   return true if a timeval is zero
     616             : */
     617     1299145 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
     618             : {
     619     1299145 :         return tv->tv_sec == 0 && tv->tv_usec == 0;
     620             : }
     621             : 
     622             : /**
     623             :   return a timeval for the current time
     624             : */
     625    15457454 : _PUBLIC_ struct timeval timeval_current(void)
     626             : {
     627      703861 :         struct timeval tv;
     628    15457454 :         GetTimeOfDay(&tv);
     629    15457454 :         return tv;
     630             : }
     631             : 
     632             : /**
     633             :   return a timeval struct with the given elements
     634             : */
     635       93707 : _PUBLIC_ struct timeval timeval_set(uint32_t secs, uint32_t usecs)
     636             : {
     637        2526 :         struct timeval tv;
     638       93707 :         tv.tv_sec = secs;
     639       93707 :         tv.tv_usec = usecs;
     640       93707 :         return tv;
     641             : }
     642             : 
     643             : 
     644             : /**
     645             :   return a timeval ofs microseconds after tv
     646             : */
     647     8059550 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
     648             :                            uint32_t secs, uint32_t usecs)
     649             : {
     650     8059550 :         struct timeval tv2 = *tv;
     651     8059550 :         const unsigned int million = 1000000;
     652     8059550 :         tv2.tv_sec += secs;
     653     8059550 :         tv2.tv_usec += usecs;
     654     8059550 :         tv2.tv_sec += tv2.tv_usec / million;
     655     8059550 :         tv2.tv_usec = tv2.tv_usec % million;
     656     8059550 :         return tv2;
     657             : }
     658             : 
     659             : /**
     660             :   return the sum of two timeval structures
     661             : */
     662      111790 : struct timeval timeval_sum(const struct timeval *tv1,
     663             :                            const struct timeval *tv2)
     664             : {
     665      111790 :         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
     666             : }
     667             : 
     668             : /**
     669             :   return a timeval secs/usecs into the future
     670             : */
     671     2601044 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
     672             : {
     673     2601044 :         struct timeval tv = timeval_current();
     674     2601044 :         return timeval_add(&tv, secs, usecs);
     675             : }
     676             : 
     677             : /**
     678             :   return a timeval milliseconds into the future
     679             : */
     680     4490506 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
     681             : {
     682     4490506 :         struct timeval tv = timeval_current();
     683     4490506 :         return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
     684             : }
     685             : 
     686             : /**
     687             :   return a timeval microseconds into the future
     688             : */
     689      461635 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
     690             : {
     691      461635 :         struct timeval tv = timeval_current();
     692      461635 :         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        8704 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
     702             : {
     703        8704 :         if (tv1->tv_sec  > tv2->tv_sec)  return 1;
     704        7727 :         if (tv1->tv_sec  < tv2->tv_sec)  return -1;
     705        7580 :         if (tv1->tv_usec > tv2->tv_usec) return 1;
     706        3926 :         if (tv1->tv_usec < tv2->tv_usec) return -1;
     707          10 :         return 0;
     708             : }
     709             : 
     710             : /**
     711             :   return true if a timer is in the past
     712             : */
     713     1010951 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
     714             : {
     715     1010951 :         struct timeval tv2 = timeval_current();
     716     1010951 :         if (tv2.tv_sec > tv->tv_sec) return true;
     717     1010882 :         if (tv2.tv_sec < tv->tv_sec) return false;
     718        2989 :         return (tv2.tv_usec >= tv->tv_usec);
     719             : }
     720             : 
     721             : /**
     722             :   return the number of seconds elapsed between two times
     723             : */
     724      772653 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
     725             : {
     726      969478 :         return (tv2->tv_sec - tv1->tv_sec) +
     727      772653 :                (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      772206 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
     734             : {
     735      772206 :         struct timeval tv2 = timeval_current();
     736      772206 :         return timeval_elapsed2(tv, &tv2);
     737             : }
     738             : /**
     739             :  *   return the number of seconds elapsed between two times
     740             :  **/
     741         535 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
     742             :                                 const struct timespec *ts2)
     743             : {
     744        1063 :         return (ts2->tv_sec - ts1->tv_sec) +
     745         535 :                (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          12 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
     752             : {
     753          12 :         struct timespec ts2 = timespec_current();
     754          12 :         return timespec_elapsed2(ts, &ts2);
     755             : }
     756             : 
     757             : /**
     758             :   return the lesser of two timevals
     759             : */
     760        4152 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
     761             :                            const struct timeval *tv2)
     762             : {
     763        4152 :         if (tv1->tv_sec < tv2->tv_sec) return *tv1;
     764        3739 :         if (tv1->tv_sec > tv2->tv_sec) return *tv2;
     765        3649 :         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           0 :         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     7818769 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
     808             : {
     809    15560733 :         return 10*(tv->tv_usec +
     810     7818769 :                   ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
     811             : }
     812             : 
     813             : /**
     814             :   convert a NTTIME to a timeval
     815             : */
     816       74749 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
     817             : {
     818       74749 :         if (tv == NULL) return;
     819             : 
     820       74749 :         t += 10/2;
     821       74749 :         t /= 10;
     822       74749 :         t -= TIME_FIXUP_CONSTANT*1000*1000;
     823             : 
     824       74749 :         tv->tv_sec  = t / 1000000;
     825             : 
     826       74749 :         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       74749 :         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       15186 : static int tm_diff(struct tm *a, struct tm *b)
     839             : {
     840       15186 :         int ay = a->tm_year + (1900 - 1);
     841       15186 :         int by = b->tm_year + (1900 - 1);
     842       15186 :         int intervening_leap_days =
     843       15186 :                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
     844       15186 :         int years = ay - by;
     845       15186 :         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
     846       15186 :         int hours = 24*days + (a->tm_hour - b->tm_hour);
     847       15186 :         int minutes = 60*hours + (a->tm_min - b->tm_min);
     848       15186 :         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
     849             : 
     850       15186 :         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       15186 : _PUBLIC_ int get_time_zone(time_t t)
     858             : {
     859       15186 :         struct tm *tm = gmtime(&t);
     860         268 :         struct tm tm_utc;
     861       15186 :         if (!tm)
     862           0 :                 return 0;
     863       15186 :         tm_utc = *tm;
     864       15186 :         tm = localtime(&t);
     865       15186 :         if (!tm)
     866           0 :                 return 0;
     867       15186 :         return tm_diff(&tm_utc,tm);
     868             : }
     869             : 
     870             : /*
     871             :  * Raw convert an NTTIME to a unix timespec.
     872             :  */
     873             : 
     874     5152168 : struct timespec nt_time_to_unix_timespec_raw(
     875             :                         NTTIME nt)
     876             : {
     877      156266 :         int64_t d;
     878      156266 :         struct timespec ret;
     879             : 
     880     5152168 :         d = (int64_t)nt;
     881             :         /* d is now in 100ns units, since jan 1st 1601".
     882             :            Save off the ns fraction. */
     883             : 
     884             :         /*
     885             :          * Take the last seven decimal digits and multiply by 100.
     886             :          * to convert from 100ns units to 1ns units.
     887             :          */
     888     5152168 :         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
     889             : 
     890             :         /* Convert to seconds */
     891     5152168 :         d /= 1000*1000*10;
     892             : 
     893             :         /* Now adjust by 369 years to make the secs since 1970 */
     894     5152168 :         d -= TIME_FIXUP_CONSTANT_INT;
     895             : 
     896     5152168 :         ret.tv_sec = (time_t)d;
     897     5152168 :         return ret;
     898             : }
     899             : 
     900     2737279 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
     901             : {
     902      148754 :         struct timespec ret;
     903             : 
     904     2737279 :         if (nt == 0 || nt == (int64_t)-1) {
     905        7921 :                 ret.tv_sec = 0;
     906        7921 :                 ret.tv_nsec = 0;
     907        7921 :                 return ret;
     908             :         }
     909             : 
     910     2729358 :         ret = nt_time_to_unix_timespec_raw(nt);
     911             : 
     912     2729358 :         if (ret.tv_sec <= TIME_T_MIN) {
     913         383 :                 ret.tv_sec = TIME_T_MIN;
     914         383 :                 ret.tv_nsec = 0;
     915         383 :                 return ret;
     916             :         }
     917             : 
     918     2728975 :         if (ret.tv_sec >= TIME_T_MAX) {
     919           0 :                 ret.tv_sec = TIME_T_MAX;
     920           0 :                 ret.tv_nsec = 0;
     921           0 :                 return ret;
     922             :         }
     923     2728975 :         return ret;
     924             : }
     925             : 
     926             : 
     927             : /**
     928             :   check if 2 NTTIMEs are equal.
     929             : */
     930          72 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
     931             : {
     932          72 :         return *t1 == *t2;
     933             : }
     934             : 
     935             : /**
     936             :  Check if it's a null timespec.
     937             : **/
     938             : 
     939    77652638 : bool null_timespec(struct timespec ts)
     940             : {
     941   155033249 :         return ts.tv_sec == 0 ||
     942   155033249 :                 ts.tv_sec == (time_t)0xFFFFFFFF ||
     943    77380611 :                 ts.tv_sec == (time_t)-1;
     944             : }
     945             : 
     946             : /****************************************************************************
     947             :  Convert a normalized timeval to a timespec.
     948             : ****************************************************************************/
     949             : 
     950           8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
     951             : {
     952           0 :         struct timespec ts;
     953           8 :         ts.tv_sec = tv.tv_sec;
     954           8 :         ts.tv_nsec = tv.tv_usec * 1000;
     955           8 :         return ts;
     956             : }
     957             : 
     958             : /****************************************************************************
     959             :  Convert a normalized timespec to a timeval.
     960             : ****************************************************************************/
     961             : 
     962           8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
     963             : {
     964           0 :         struct timeval tv;
     965           8 :         tv.tv_sec = ts.tv_sec;
     966           8 :         tv.tv_usec = ts.tv_nsec / 1000;
     967           8 :         return tv;
     968             : }
     969             : 
     970             : /****************************************************************************
     971             :  Return a timespec for the current time
     972             : ****************************************************************************/
     973             : 
     974      325114 : _PUBLIC_ struct timespec timespec_current(void)
     975             : {
     976         983 :         struct timespec ts;
     977      325114 :         clock_gettime(CLOCK_REALTIME, &ts);
     978      325114 :         return ts;
     979             : }
     980             : 
     981             : /****************************************************************************
     982             :  Return the lesser of two timespecs.
     983             : ****************************************************************************/
     984             : 
     985           0 : struct timespec timespec_min(const struct timespec *ts1,
     986             :                            const struct timespec *ts2)
     987             : {
     988           0 :         if (ts1->tv_sec < ts2->tv_sec) return *ts1;
     989           0 :         if (ts1->tv_sec > ts2->tv_sec) return *ts2;
     990           0 :         if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
     991           0 :         return *ts2;
     992             : }
     993             : 
     994             : /****************************************************************************
     995             :   compare two timespec structures.
     996             :   Return -1 if ts1 < ts2
     997             :   Return 0 if ts1 == ts2
     998             :   Return 1 if ts1 > ts2
     999             : ****************************************************************************/
    1000             : 
    1001    79947033 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
    1002             : {
    1003    79947033 :         if (ts1->tv_sec  > ts2->tv_sec)  return 1;
    1004    77548090 :         if (ts1->tv_sec  < ts2->tv_sec)  return -1;
    1005    76448395 :         if (ts1->tv_nsec > ts2->tv_nsec) return 1;
    1006    67840617 :         if (ts1->tv_nsec < ts2->tv_nsec) return -1;
    1007    56521372 :         return 0;
    1008             : }
    1009             : 
    1010             : /****************************************************************************
    1011             :  Round up a timespec if nsec > 500000000, round down if lower,
    1012             :  then zero nsec.
    1013             : ****************************************************************************/
    1014             : 
    1015       65868 : void round_timespec_to_sec(struct timespec *ts)
    1016             : {
    1017       65868 :         ts->tv_sec = convert_timespec_to_time_t(*ts);
    1018       65868 :         ts->tv_nsec = 0;
    1019       65868 : }
    1020             : 
    1021             : /****************************************************************************
    1022             :  Round a timespec to usec value.
    1023             : ****************************************************************************/
    1024             : 
    1025           0 : void round_timespec_to_usec(struct timespec *ts)
    1026             : {
    1027           0 :         struct timeval tv = convert_timespec_to_timeval(*ts);
    1028           0 :         *ts = convert_timeval_to_timespec(tv);
    1029           0 :         normalize_timespec(ts);
    1030           0 : }
    1031             : 
    1032             : /****************************************************************************
    1033             :  Round a timespec to NTTIME resolution.
    1034             : ****************************************************************************/
    1035             : 
    1036           0 : void round_timespec_to_nttime(struct timespec *ts)
    1037             : {
    1038           0 :         ts->tv_nsec = (ts->tv_nsec / 100) * 100;
    1039           0 : }
    1040             : 
    1041             : /****************************************************************************
    1042             :  Put a 8 byte filetime from a struct timespec. Uses GMT.
    1043             : ****************************************************************************/
    1044             : 
    1045       15946 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
    1046             : {
    1047           0 :         uint64_t d;
    1048             : 
    1049       15946 :         if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
    1050           0 :                 return 0;
    1051             :         }
    1052       15946 :         if (ts.tv_sec == TIME_T_MAX) {
    1053           0 :                 return 0x7fffffffffffffffLL;
    1054             :         }
    1055       15946 :         if (ts.tv_sec == (time_t)-1) {
    1056           0 :                 return (uint64_t)-1;
    1057             :         }
    1058             : 
    1059       15946 :         d = ts.tv_sec;
    1060       15946 :         d += TIME_FIXUP_CONSTANT_INT;
    1061       15946 :         d *= 1000*1000*10;
    1062             :         /* d is now in 100ns units. */
    1063       15946 :         d += (ts.tv_nsec / 100);
    1064             : 
    1065       15946 :         return d;
    1066             : }
    1067             : 
    1068             : /*
    1069             :  * Functions supporting the full range of time_t and struct timespec values,
    1070             :  * including 0, -1 and all other negative values. These functions don't use 0 or
    1071             :  * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
    1072             :  * define UTIME_OMIT from utimensat(2).
    1073             :  */
    1074             : 
    1075             : /**
    1076             :  * Check if it's a to be omitted timespec.
    1077             :  **/
    1078    13513180 : bool is_omit_timespec(const struct timespec *ts)
    1079             : {
    1080    13513180 :         return ts->tv_nsec == SAMBA_UTIME_OMIT;
    1081             : }
    1082             : 
    1083             : /**
    1084             :  * Return a to be omitted timespec.
    1085             :  **/
    1086     8664190 : struct timespec make_omit_timespec(void)
    1087             : {
    1088     8664190 :         return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1089             : }
    1090             : 
    1091             : /**
    1092             :  * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
    1093             :  * and -1. Also dealing with SAMBA_UTIME_OMIT.
    1094             :  **/
    1095     6263744 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
    1096             : {
    1097     6263744 :         struct timespec ts = *_ts;
    1098        9629 :         uint64_t d;
    1099             : 
    1100     6263744 :         if (is_omit_timespec(_ts)) {
    1101     1527472 :                 return NTTIME_OMIT;
    1102             :         }
    1103             : 
    1104             :         /* Ensure tv_nsec is less than 1 sec. */
    1105     4733932 :         while (ts.tv_nsec > 1000000000) {
    1106           0 :                 if (ts.tv_sec > TIME_T_MAX) {
    1107           0 :                         return NTTIME_MAX;
    1108             :                 }
    1109           0 :                 ts.tv_sec += 1;
    1110           0 :                 ts.tv_nsec -= 1000000000;
    1111             :         }
    1112             : 
    1113     4733932 :         if (ts.tv_sec >= TIME_T_MAX) {
    1114           0 :                 return NTTIME_MAX;
    1115             :         }
    1116     4733932 :         if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
    1117           0 :                 return NTTIME_MIN;
    1118             :         }
    1119             : 
    1120     4733932 :         d = TIME_FIXUP_CONSTANT_INT;
    1121     4733932 :         d += ts.tv_sec;
    1122             : 
    1123     4733932 :         d *= 1000*1000*10;
    1124             :         /* d is now in 100ns units. */
    1125     4733932 :         d += (ts.tv_nsec / 100);
    1126             : 
    1127     4733932 :         return d;
    1128             : }
    1129             : 
    1130             : /**
    1131             :  * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
    1132             :  * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
    1133             :  *
    1134             :  * See also: is_omit_timespec().
    1135             :  **/
    1136     2515634 : struct timespec nt_time_to_full_timespec(NTTIME nt)
    1137             : {
    1138        8507 :         struct timespec ret;
    1139             : 
    1140     2515634 :         if (nt == NTTIME_OMIT) {
    1141       88663 :                 return make_omit_timespec();
    1142             :         }
    1143     2426971 :         if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) {
    1144             :                 /*
    1145             :                  * This should be returned as SAMBA_UTIME_FREEZE or
    1146             :                  * SAMBA_UTIME_THAW in the future.
    1147             :                  */
    1148        4161 :                 return make_omit_timespec();
    1149             :         }
    1150     2422810 :         if (nt > NTTIME_MAX) {
    1151           2 :                 nt = NTTIME_MAX;
    1152             :         }
    1153             : 
    1154     2422810 :         ret = nt_time_to_unix_timespec_raw(nt);
    1155             : 
    1156     2422810 :         if (ret.tv_sec >= TIME_T_MAX) {
    1157           0 :                 ret.tv_sec = TIME_T_MAX;
    1158           0 :                 ret.tv_nsec = 0;
    1159           0 :                 return ret;
    1160             :         }
    1161             : 
    1162     2422810 :         return ret;
    1163             : }
    1164             : 
    1165             : /**
    1166             :  * Note: this function uses the full time_t range as valid date values including
    1167             :  * (time_t)0 and -1. That means that struct timespec sentinel values (cf
    1168             :  * is_omit_timespec()) can't be converted to sentinel values in a time_t
    1169             :  * representation. Callers should therefore check the NTTIME value with
    1170             :  * null_nttime() before calling this function.
    1171             :  **/
    1172      256401 : time_t full_timespec_to_time_t(const struct timespec *_ts)
    1173             : {
    1174      256401 :         struct timespec ts = *_ts;
    1175             : 
    1176      256401 :         if (is_omit_timespec(_ts)) {
    1177             :                 /*
    1178             :                  * Unfortunately there's no sensible sentinel value in the
    1179             :                  * time_t range that is not conflicting with a valid time value
    1180             :                  * ((time_t)0 and -1 are valid time values). Bite the bullit and
    1181             :                  * return 0.
    1182             :                  */
    1183           0 :                 return 0;
    1184             :         }
    1185             : 
    1186             :         /* Ensure tv_nsec is less than 1sec. */
    1187      256401 :         while (ts.tv_nsec > 1000000000) {
    1188           0 :                 ts.tv_sec += 1;
    1189           0 :                 ts.tv_nsec -= 1000000000;
    1190             :         }
    1191             : 
    1192             :         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
    1193             :            increment if it's greater than 500 millionth of a second. */
    1194             : 
    1195      256401 :         if (ts.tv_nsec > 500000000) {
    1196        7989 :                 return ts.tv_sec + 1;
    1197             :         }
    1198      244484 :         return ts.tv_sec;
    1199             : }
    1200             : 
    1201             : /**
    1202             :  * Like nt_time_to_unix() but supports negative time_t values.
    1203             :  *
    1204             :  * Note: this function uses the full time_t range as valid date values including
    1205             :  * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
    1206             :  * represent a "not-set" value, can't be converted to sentinel values in a
    1207             :  * time_t representation. Callers should therefore check the NTTIME value with
    1208             :  * null_nttime() before calling this function.
    1209             :  **/
    1210      256401 : time_t nt_time_to_full_time_t(NTTIME nt)
    1211             : {
    1212        3982 :         struct timespec ts;
    1213             : 
    1214      256401 :         ts = nt_time_to_full_timespec(nt);
    1215      256401 :         return full_timespec_to_time_t(&ts);
    1216             : }
    1217             : 
    1218             : /**
    1219             :  * Like time_t_to_unix_timespec() but supports negative time_t values.
    1220             :  *
    1221             :  * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
    1222             :  * can't be used as valid date values. The function supports values < -1 though.
    1223             :  **/
    1224       32443 : struct timespec time_t_to_full_timespec(time_t t)
    1225             : {
    1226       32443 :         if (null_time(t)) {
    1227       32253 :                 return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1228             :         }
    1229         190 :         return (struct timespec){.tv_sec = t};
    1230             : }
    1231             : 
    1232             : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
    1233             : 
    1234             : /* Old system - no ns timestamp. */
    1235             : time_t get_atimensec(const struct stat *st)
    1236             : {
    1237             :         return 0;
    1238             : }
    1239             : 
    1240             : time_t get_mtimensec(const struct stat *st)
    1241             : {
    1242             :         return 0;
    1243             : }
    1244             : 
    1245             : time_t get_ctimensec(const struct stat *st)
    1246             : {
    1247             :         return 0;
    1248             : }
    1249             : 
    1250             : /* Set does nothing with no ns timestamp. */
    1251             : void set_atimensec(struct stat *st, time_t ns)
    1252             : {
    1253             :         return;
    1254             : }
    1255             : 
    1256             : void set_mtimensec(struct stat *st, time_t ns)
    1257             : {
    1258             :         return;
    1259             : }
    1260             : 
    1261             : void set_ctimensec(struct stat *st, time_t ns)
    1262             : {
    1263             :         return;
    1264             : }
    1265             : 
    1266             : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
    1267             : 
    1268             : time_t get_atimensec(const struct stat *st)
    1269             : {
    1270             :         return st->st_atimespec.tv_nsec;
    1271             : }
    1272             : 
    1273             : time_t get_mtimensec(const struct stat *st)
    1274             : {
    1275             :         return st->st_mtimespec.tv_nsec;
    1276             : }
    1277             : 
    1278             : time_t get_ctimensec(const struct stat *st)
    1279             : {
    1280             :         return st->st_ctimespec.tv_nsec;
    1281             : }
    1282             : 
    1283             : void set_atimensec(struct stat *st, time_t ns)
    1284             : {
    1285             :         st->st_atimespec.tv_nsec = ns;
    1286             : }
    1287             : 
    1288             : void set_mtimensec(struct stat *st, time_t ns)
    1289             : {
    1290             :         st->st_mtimespec.tv_nsec = ns;
    1291             : }
    1292             : 
    1293             : void set_ctimensec(struct stat *st, time_t ns)
    1294             : {
    1295             :         st->st_ctimespec.tv_nsec = ns;
    1296             : }
    1297             : 
    1298             : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
    1299             : 
    1300    78441811 : time_t get_atimensec(const struct stat *st)
    1301             : {
    1302    78441811 :         return st->st_atim.tv_nsec;
    1303             : }
    1304             : 
    1305    79235665 : time_t get_mtimensec(const struct stat *st)
    1306             : {
    1307    79235665 :         return st->st_mtim.tv_nsec;
    1308             : }
    1309             : 
    1310    79247796 : time_t get_ctimensec(const struct stat *st)
    1311             : {
    1312    79247796 :         return st->st_ctim.tv_nsec;
    1313             : }
    1314             : 
    1315         208 : void set_atimensec(struct stat *st, time_t ns)
    1316             : {
    1317         208 :         st->st_atim.tv_nsec = ns;
    1318         208 : }
    1319             : 
    1320         208 : void set_mtimensec(struct stat *st, time_t ns)
    1321             : {
    1322         208 :         st->st_mtim.tv_nsec = ns;
    1323         208 : }
    1324         208 : void set_ctimensec(struct stat *st, time_t ns)
    1325             : {
    1326         208 :         st->st_ctim.tv_nsec = ns;
    1327         208 : }
    1328             : 
    1329             : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
    1330             : 
    1331             : time_t get_atimensec(const struct stat *st)
    1332             : {
    1333             :         return st->st_atimensec;
    1334             : }
    1335             : 
    1336             : time_t get_mtimensec(const struct stat *st)
    1337             : {
    1338             :         return st->st_mtimensec;
    1339             : }
    1340             : 
    1341             : time_t get_ctimensec(const struct stat *st)
    1342             : {
    1343             :         return st->st_ctimensec;
    1344             : }
    1345             : 
    1346             : void set_atimensec(struct stat *st, time_t ns)
    1347             : {
    1348             :         st->st_atimensec = ns;
    1349             : }
    1350             : 
    1351             : void set_mtimensec(struct stat *st, time_t ns)
    1352             : {
    1353             :         st->st_mtimensec = ns;
    1354             : }
    1355             : 
    1356             : void set_ctimensec(struct stat *st, time_t ns)
    1357             : {
    1358             :         st->st_ctimensec = ns;
    1359             : }
    1360             : 
    1361             : #elif HAVE_STRUCT_STAT_ST_MTIME_N
    1362             : 
    1363             : time_t get_atimensec(const struct stat *st)
    1364             : {
    1365             :         return st->st_atime_n;
    1366             : }
    1367             : 
    1368             : time_t get_mtimensec(const struct stat *st)
    1369             : {
    1370             :         return st->st_mtime_n;
    1371             : }
    1372             : 
    1373             : time_t get_ctimensec(const struct stat *st)
    1374             : {
    1375             :         return st->st_ctime_n;
    1376             : }
    1377             : 
    1378             : void set_atimensec(struct stat *st, time_t ns)
    1379             : {
    1380             :         st->st_atime_n = ns;
    1381             : }
    1382             : 
    1383             : void set_mtimensec(struct stat *st, time_t ns)
    1384             : {
    1385             :         st->st_mtime_n = ns;
    1386             : }
    1387             : 
    1388             : void set_ctimensec(struct stat *st, time_t ns)
    1389             : {
    1390             :         st->st_ctime_n = ns;
    1391             : }
    1392             : 
    1393             : #elif HAVE_STRUCT_STAT_ST_UMTIME
    1394             : 
    1395             : /* Only usec timestamps available. Convert to/from nsec. */
    1396             : 
    1397             : time_t get_atimensec(const struct stat *st)
    1398             : {
    1399             :         return st->st_uatime * 1000;
    1400             : }
    1401             : 
    1402             : time_t get_mtimensec(const struct stat *st)
    1403             : {
    1404             :         return st->st_umtime * 1000;
    1405             : }
    1406             : 
    1407             : time_t get_ctimensec(const struct stat *st)
    1408             : {
    1409             :         return st->st_uctime * 1000;
    1410             : }
    1411             : 
    1412             : void set_atimensec(struct stat *st, time_t ns)
    1413             : {
    1414             :         st->st_uatime = ns / 1000;
    1415             : }
    1416             : 
    1417             : void set_mtimensec(struct stat *st, time_t ns)
    1418             : {
    1419             :         st->st_umtime = ns / 1000;
    1420             : }
    1421             : 
    1422             : void set_ctimensec(struct stat *st, time_t ns)
    1423             : {
    1424             :         st->st_uctime = ns / 1000;
    1425             : }
    1426             : 
    1427             : #else
    1428             : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
    1429             : #endif
    1430             : 
    1431    77635822 : struct timespec get_atimespec(const struct stat *pst)
    1432             : {
    1433      270674 :         struct timespec ret;
    1434             : 
    1435    77635822 :         ret.tv_sec = pst->st_atime;
    1436    77635822 :         ret.tv_nsec = get_atimensec(pst);
    1437    77635822 :         return ret;
    1438             : }
    1439             : 
    1440    78429672 : struct timespec get_mtimespec(const struct stat *pst)
    1441             : {
    1442      275323 :         struct timespec ret;
    1443             : 
    1444    78429672 :         ret.tv_sec = pst->st_mtime;
    1445    78429672 :         ret.tv_nsec = get_mtimensec(pst);
    1446    78429672 :         return ret;
    1447             : }
    1448             : 
    1449    77635818 : struct timespec get_ctimespec(const struct stat *pst)
    1450             : {
    1451      270674 :         struct timespec ret;
    1452             : 
    1453    77635818 :         ret.tv_sec = pst->st_mtime;
    1454    77635818 :         ret.tv_nsec = get_ctimensec(pst);
    1455    77635818 :         return ret;
    1456             : }
    1457             : 
    1458             : /****************************************************************************
    1459             :  Deal with nanoseconds overflow.
    1460             : ****************************************************************************/
    1461             : 
    1462     5651228 : void normalize_timespec(struct timespec *ts)
    1463             : {
    1464      155038 :         lldiv_t dres;
    1465             : 
    1466             :         /* most likely case: nsec is valid */
    1467     5651228 :         if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
    1468     5651228 :                 return;
    1469             :         }
    1470             : 
    1471       21555 :         dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
    1472             : 
    1473             :         /* if the operation would result in overflow, max out values and bail */
    1474       21555 :         if (dres.quot > 0) {
    1475       21543 :                 if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
    1476           1 :                         ts->tv_sec = LONG_MAX;
    1477           1 :                         ts->tv_nsec = NSEC_PER_SEC - 1;
    1478           1 :                         return;
    1479             :                 }
    1480             :         } else {
    1481          12 :                 if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
    1482           1 :                         ts->tv_sec = LONG_MIN;
    1483           1 :                         ts->tv_nsec = 0;
    1484           1 :                         return;
    1485             :                 }
    1486             :         }
    1487             : 
    1488       21553 :         ts->tv_nsec = dres.rem;
    1489       21553 :         ts->tv_sec += dres.quot;
    1490             : 
    1491             :         /* if the ns part was positive or a multiple of -1000000000, we're done */
    1492       21553 :         if (ts->tv_nsec > 0 || dres.rem == 0) {
    1493       21535 :                 return;
    1494             :         }
    1495             : 
    1496           9 :         ts->tv_nsec += NSEC_PER_SEC;
    1497           9 :         --ts->tv_sec;
    1498             : }

Generated by: LCOV version 1.14