LCOV - code coverage report
Current view: top level - lib/util - time.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 426 499 85.4 %
Date: 2024-05-31 13:13:24 Functions: 76 81 93.8 %

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

Generated by: LCOV version 1.14