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

Generated by: LCOV version 1.14