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

Generated by: LCOV version 1.14