LCOV - code coverage report
Current view: top level - lib/util - time.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 426 501 85.0 %
Date: 2024-04-21 15:09:00 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      398463 : _PUBLIC_ time_t get_time_t_max(void)
      48             : {
      49      398463 :         return TIME_T_MAX;
      50             : }
      51             : 
      52             : /**
      53             : a wrapper to preferably get the monotonic time
      54             : **/
      55   429924834 : _PUBLIC_ void clock_gettime_mono(struct timespec *tp)
      56             : {
      57             : /* prefer a suspend aware monotonic CLOCK_BOOTTIME: */
      58             : #ifdef CLOCK_BOOTTIME
      59   429924834 :         if (clock_gettime(CLOCK_BOOTTIME,tp) == 0) {
      60   429526798 :                 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        6583 : _PUBLIC_ time_t time_mono(time_t *t)
      76             : {
      77           0 :         struct timespec tp;
      78             : 
      79        6583 :         clock_gettime_mono(&tp);
      80        6583 :         if (t != NULL) {
      81           0 :                 *t = tp.tv_sec;
      82             :         }
      83        6583 :         return tp.tv_sec;
      84             : }
      85             : 
      86             : 
      87             : #define TIME_FIXUP_CONSTANT 11644473600LL
      88             : 
      89     3238756 : time_t convert_timespec_to_time_t(struct timespec ts)
      90             : {
      91             :         /* Ensure tv_nsec is less than 1sec. */
      92     3238756 :         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     3238756 :         if (ts.tv_nsec > 500000000) {
      98      300901 :                 return ts.tv_sec + 1;
      99             :         }
     100     2937855 :         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     2748817 : time_t nt_time_to_unix(NTTIME nt)
     125             : {
     126     2748817 :         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     7015749 : _PUBLIC_ void unix_to_nt_time(NTTIME *nt, time_t t)
     135             : {
     136      265081 :         uint64_t t2;
     137             : 
     138     7015749 :         if (t == (time_t)-1) {
     139           1 :                 *nt = UINT64_MAX;
     140           1 :                 return;
     141             :         }
     142             : 
     143     7015748 :         if (t == TIME_T_MAX || t == INT64_MAX) {
     144       61651 :                 *nt = 0x7fffffffffffffffLL;
     145       61651 :                 return;
     146             :         }
     147             : 
     148     6954097 :         if (t == 0) {
     149       22081 :                 *nt = 0;
     150       22081 :                 return;
     151             :         }
     152             : 
     153     6932016 :         t2 = t;
     154     6932016 :         t2 += TIME_FIXUP_CONSTANT_INT;
     155     6932016 :         t2 *= 1000*1000*10;
     156             : 
     157     6932016 :         *nt = t2;
     158             : }
     159             : 
     160             : 
     161             : /**
     162             : check if it's a null unix time
     163             : **/
     164      914645 : _PUBLIC_ bool null_time(time_t t)
     165             : {
     166       86127 :         return t == 0 ||
     167      999282 :                 t == (time_t)0xFFFFFFFF ||
     168             :                 t == (time_t)-1;
     169             : }
     170             : 
     171             : 
     172             : /**
     173             : check if it's a null NTTIME
     174             : **/
     175     2503287 : _PUBLIC_ bool null_nttime(NTTIME t)
     176             : {
     177     2503287 :         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      169293 : _PUBLIC_ void push_dos_date3(uint8_t *buf,int offset,time_t unixdate, int zone_offset)
     256             : {
     257      169293 :         if (!null_time(unixdate)) {
     258       29190 :                 unixdate -= zone_offset;
     259             :         }
     260      169293 :         SIVAL(buf,offset,unixdate);
     261      169293 : }
     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      147792 : _PUBLIC_ time_t pull_dos_date3(const uint8_t *date_ptr, int zone_offset)
     325             : {
     326      147792 :         time_t t = (time_t)IVAL(date_ptr,0);
     327             : 
     328      147792 :         if (t == (time_t)0xFFFFFFFF) {
     329        4256 :                 t = (time_t)-1;
     330             :         }
     331             : 
     332      147792 :         if (!null_time(t)) {
     333       27806 :                 t += zone_offset;
     334             :         }
     335      147792 :         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      288359 : _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      288359 :         tm = localtime(&t);
     513      288359 :         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      288359 :         strftime(tempTime,sizeof(tempTime)-1,"%a %b %e %X %Y %Z",tm);
     524      288359 :         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      288359 :         return TimeBuf;
     539             : }
     540             : 
     541             : /**
     542             :   return a talloced string representing a NTTIME for human consumption
     543             : */
     544      267397 : _PUBLIC_ const char *nt_time_string(TALLOC_CTX *mem_ctx, NTTIME nt)
     545             : {
     546        5318 :         time_t t;
     547      267397 :         if (nt == 0) {
     548        6950 :                 return "NTTIME(0)";
     549             :         }
     550      259111 :         t = nt_time_to_full_time_t(nt);
     551      259111 :         return timestring(mem_ctx, t);
     552             : }
     553             : 
     554             : 
     555             : /**
     556             :   put a NTTIME into a packet
     557             : */
     558      425234 : _PUBLIC_ void push_nttime(uint8_t *base, uint16_t offset, NTTIME t)
     559             : {
     560      425234 :         SBVAL(base, offset,   t);
     561      425234 : }
     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      395706 : _PUBLIC_ int64_t usec_time_diff(const struct timeval *tv1, const struct timeval *tv2)
     576             : {
     577      395706 :         int64_t sec_diff = tv1->tv_sec - tv2->tv_sec;
     578      395706 :         return (sec_diff * 1000000) + (int64_t)(tv1->tv_usec - tv2->tv_usec);
     579             : }
     580             : 
     581             : /**
     582             :   return (tp1 - tp2) in nanoseconds
     583             : */
     584   214630144 : _PUBLIC_ int64_t nsec_time_diff(const struct timespec *tp1, const struct timespec *tp2)
     585             : {
     586   214630144 :         int64_t sec_diff = tp1->tv_sec - tp2->tv_sec;
     587   214630144 :         return (sec_diff * 1000000000) + (int64_t)(tp1->tv_nsec - tp2->tv_nsec);
     588             : }
     589             : 
     590             : 
     591             : /**
     592             :   return a zero timeval
     593             : */
     594      130878 : _PUBLIC_ struct timeval timeval_zero(void)
     595             : {
     596        2476 :         struct timeval tv;
     597      130878 :         tv.tv_sec = 0;
     598      130878 :         tv.tv_usec = 0;
     599      130878 :         return tv;
     600             : }
     601             : 
     602             : /**
     603             :   return true if a timeval is zero
     604             : */
     605     1335987 : _PUBLIC_ bool timeval_is_zero(const struct timeval *tv)
     606             : {
     607     1335987 :         return tv->tv_sec == 0 && tv->tv_usec == 0;
     608             : }
     609             : 
     610             : /**
     611             :   return a timeval for the current time
     612             : */
     613    15708887 : _PUBLIC_ struct timeval timeval_current(void)
     614             : {
     615      722162 :         struct timeval tv;
     616    15708887 :         GetTimeOfDay(&tv);
     617    15708887 :         return tv;
     618             : }
     619             : 
     620             : /**
     621             :   return a timeval ofs microseconds after tv
     622             : */
     623     8177352 : _PUBLIC_ struct timeval timeval_add(const struct timeval *tv,
     624             :                            uint32_t secs, uint32_t usecs)
     625             : {
     626     8177352 :         struct timeval tv2 = *tv;
     627     8177352 :         const unsigned int million = 1000000;
     628     8177352 :         tv2.tv_sec += secs;
     629     8177352 :         tv2.tv_usec += usecs;
     630     8177352 :         tv2.tv_sec += tv2.tv_usec / million;
     631     8177352 :         tv2.tv_usec = tv2.tv_usec % million;
     632     8177352 :         return tv2;
     633             : }
     634             : 
     635             : /**
     636             :   return the sum of two timeval structures
     637             : */
     638      112741 : struct timeval timeval_sum(const struct timeval *tv1,
     639             :                            const struct timeval *tv2)
     640             : {
     641      112741 :         return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
     642             : }
     643             : 
     644             : /**
     645             :   return a timeval secs/usecs into the future
     646             : */
     647     2679069 : _PUBLIC_ struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
     648             : {
     649     2679069 :         struct timeval tv = timeval_current();
     650     2679069 :         return timeval_add(&tv, secs, usecs);
     651             : }
     652             : 
     653             : /**
     654             :   return a timeval milliseconds into the future
     655             : */
     656     4508584 : _PUBLIC_ struct timeval timeval_current_ofs_msec(uint32_t msecs)
     657             : {
     658     4508584 :         struct timeval tv = timeval_current();
     659     4508584 :         return timeval_add(&tv, msecs / 1000, (msecs % 1000) * 1000);
     660             : }
     661             : 
     662             : /**
     663             :   return a timeval microseconds into the future
     664             : */
     665      465750 : _PUBLIC_ struct timeval timeval_current_ofs_usec(uint32_t usecs)
     666             : {
     667      465750 :         struct timeval tv = timeval_current();
     668      465750 :         return timeval_add(&tv, usecs / 1000000, usecs % 1000000);
     669             : }
     670             : 
     671             : /**
     672             :   compare two timeval structures.
     673             :   Return -1 if tv1 < tv2
     674             :   Return 0 if tv1 == tv2
     675             :   Return 1 if tv1 > tv2
     676             : */
     677        8211 : _PUBLIC_ int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
     678             : {
     679        8211 :         if (tv1->tv_sec  > tv2->tv_sec)  return 1;
     680        7263 :         if (tv1->tv_sec  < tv2->tv_sec)  return -1;
     681        7254 :         if (tv1->tv_usec > tv2->tv_usec) return 1;
     682        3748 :         if (tv1->tv_usec < tv2->tv_usec) return -1;
     683           6 :         return 0;
     684             : }
     685             : 
     686             : /**
     687             :   return true if a timer is in the past
     688             : */
     689     1045572 : _PUBLIC_ bool timeval_expired(const struct timeval *tv)
     690             : {
     691     1045572 :         struct timeval tv2 = timeval_current();
     692     1045572 :         if (tv2.tv_sec > tv->tv_sec) return true;
     693     1045502 :         if (tv2.tv_sec < tv->tv_sec) return false;
     694        2989 :         return (tv2.tv_usec >= tv->tv_usec);
     695             : }
     696             : 
     697             : /**
     698             :   return the number of seconds elapsed between two times
     699             : */
     700      828417 : _PUBLIC_ double timeval_elapsed2(const struct timeval *tv1, const struct timeval *tv2)
     701             : {
     702     1066157 :         return (tv2->tv_sec - tv1->tv_sec) +
     703      828417 :                (tv2->tv_usec - tv1->tv_usec)*1.0e-6;
     704             : }
     705             : 
     706             : /**
     707             :   return the number of seconds elapsed since a given time
     708             : */
     709      827970 : _PUBLIC_ double timeval_elapsed(const struct timeval *tv)
     710             : {
     711      827970 :         struct timeval tv2 = timeval_current();
     712      827970 :         return timeval_elapsed2(tv, &tv2);
     713             : }
     714             : /**
     715             :  *   return the number of seconds elapsed between two times
     716             :  **/
     717         630 : _PUBLIC_ double timespec_elapsed2(const struct timespec *ts1,
     718             :                                 const struct timespec *ts2)
     719             : {
     720        1253 :         return (ts2->tv_sec - ts1->tv_sec) +
     721         630 :                (ts2->tv_nsec - ts1->tv_nsec)*1.0e-9;
     722             : }
     723             : 
     724             : /**
     725             :  *   return the number of seconds elapsed since a given time
     726             :  */
     727         106 : _PUBLIC_ double timespec_elapsed(const struct timespec *ts)
     728             : {
     729         106 :         struct timespec ts2 = timespec_current();
     730         106 :         return timespec_elapsed2(ts, &ts2);
     731             : }
     732             : 
     733             : /**
     734             :   return the lesser of two timevals
     735             : */
     736        3975 : _PUBLIC_ struct timeval timeval_min(const struct timeval *tv1,
     737             :                            const struct timeval *tv2)
     738             : {
     739        3975 :         if (tv1->tv_sec < tv2->tv_sec) return *tv1;
     740        3572 :         if (tv1->tv_sec > tv2->tv_sec) return *tv2;
     741        3482 :         if (tv1->tv_usec < tv2->tv_usec) return *tv1;
     742           0 :         return *tv2;
     743             : }
     744             : 
     745             : /**
     746             :   return the greater of two timevals
     747             : */
     748           0 : _PUBLIC_ struct timeval timeval_max(const struct timeval *tv1,
     749             :                            const struct timeval *tv2)
     750             : {
     751           0 :         if (tv1->tv_sec > tv2->tv_sec) return *tv1;
     752           0 :         if (tv1->tv_sec < tv2->tv_sec) return *tv2;
     753           0 :         if (tv1->tv_usec > tv2->tv_usec) return *tv1;
     754           0 :         return *tv2;
     755             : }
     756             : 
     757             : /**
     758             :   convert a timeval to a NTTIME
     759             : */
     760     7874952 : _PUBLIC_ NTTIME timeval_to_nttime(const struct timeval *tv)
     761             : {
     762    15675187 :         return 10*(tv->tv_usec +
     763     7874952 :                   ((TIME_FIXUP_CONSTANT + (uint64_t)tv->tv_sec) * 1000000));
     764             : }
     765             : 
     766             : /**
     767             :   convert a NTTIME to a timeval
     768             : */
     769       75179 : _PUBLIC_ void nttime_to_timeval(struct timeval *tv, NTTIME t)
     770             : {
     771       75179 :         if (tv == NULL) return;
     772             : 
     773       75179 :         t += 10/2;
     774       75179 :         t /= 10;
     775       75179 :         t -= TIME_FIXUP_CONSTANT*1000*1000;
     776             : 
     777       75179 :         tv->tv_sec  = t / 1000000;
     778             : 
     779       75179 :         if (TIME_T_MIN > tv->tv_sec || tv->tv_sec > TIME_T_MAX) {
     780           0 :                 tv->tv_sec  = 0;
     781           0 :                 tv->tv_usec = 0;
     782           0 :                 return;
     783             :         }
     784             : 
     785       75179 :         tv->tv_usec = t - tv->tv_sec*1000000;
     786             : }
     787             : 
     788             : /*******************************************************************
     789             : yield the difference between *A and *B, in seconds, ignoring leap seconds
     790             : ********************************************************************/
     791       15508 : static int tm_diff(struct tm *a, struct tm *b)
     792             : {
     793       15508 :         int ay = a->tm_year + (1900 - 1);
     794       15508 :         int by = b->tm_year + (1900 - 1);
     795       15508 :         int intervening_leap_days =
     796       15508 :                 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
     797       15508 :         int years = ay - by;
     798       15508 :         int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
     799       15508 :         int hours = 24*days + (a->tm_hour - b->tm_hour);
     800       15508 :         int minutes = 60*hours + (a->tm_min - b->tm_min);
     801       15508 :         int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
     802             : 
     803       15508 :         return seconds;
     804             : }
     805             : 
     806             : 
     807             : /**
     808             :   return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
     809             :  */
     810       15508 : _PUBLIC_ int get_time_zone(time_t t)
     811             : {
     812       15508 :         struct tm *tm = gmtime(&t);
     813         268 :         struct tm tm_utc;
     814       15508 :         if (!tm)
     815           0 :                 return 0;
     816       15508 :         tm_utc = *tm;
     817       15508 :         tm = localtime(&t);
     818       15508 :         if (!tm)
     819           0 :                 return 0;
     820       15508 :         return tm_diff(&tm_utc,tm);
     821             : }
     822             : 
     823             : /*
     824             :  * Raw convert an NTTIME to a unix timespec.
     825             :  */
     826             : 
     827     5190233 : struct timespec nt_time_to_unix_timespec_raw(
     828             :                         NTTIME nt)
     829             : {
     830      156268 :         int64_t d;
     831      156268 :         struct timespec ret;
     832             : 
     833     5190233 :         d = (int64_t)nt;
     834             :         /* d is now in 100ns units, since jan 1st 1601".
     835             :            Save off the ns fraction. */
     836             : 
     837             :         /*
     838             :          * Take the last seven decimal digits and multiply by 100.
     839             :          * to convert from 100ns units to 1ns units.
     840             :          */
     841     5190233 :         ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
     842             : 
     843             :         /* Convert to seconds */
     844     5190233 :         d /= 1000*1000*10;
     845             : 
     846             :         /* Now adjust by 369 years to make the secs since 1970 */
     847     5190233 :         d -= TIME_FIXUP_CONSTANT_INT;
     848             : 
     849     5190233 :         ret.tv_sec = (time_t)d;
     850     5190233 :         return ret;
     851             : }
     852             : 
     853     2760271 : struct timespec nt_time_to_unix_timespec(NTTIME nt)
     854             : {
     855      148756 :         struct timespec ret;
     856             : 
     857     2760271 :         if (nt == 0 || nt == UINT64_MAX) {
     858        7922 :                 ret.tv_sec = 0;
     859        7922 :                 ret.tv_nsec = 0;
     860        7922 :                 return ret;
     861             :         }
     862             : 
     863     2752349 :         ret = nt_time_to_unix_timespec_raw(nt);
     864             : 
     865     2752349 :         if (ret.tv_sec <= TIME_T_MIN) {
     866         383 :                 ret.tv_sec = TIME_T_MIN;
     867         383 :                 ret.tv_nsec = 0;
     868         383 :                 return ret;
     869             :         }
     870             : 
     871     2751966 :         if (ret.tv_sec >= TIME_T_MAX) {
     872           0 :                 ret.tv_sec = TIME_T_MAX;
     873           0 :                 ret.tv_nsec = 0;
     874           0 :                 return ret;
     875             :         }
     876     2751966 :         return ret;
     877             : }
     878             : 
     879             : 
     880             : /**
     881             :   check if 2 NTTIMEs are equal.
     882             : */
     883          72 : bool nt_time_equal(NTTIME *t1, NTTIME *t2)
     884             : {
     885          72 :         return *t1 == *t2;
     886             : }
     887             : 
     888             : /**
     889             :  Check if it's a null timespec.
     890             : **/
     891             : 
     892    79084251 : bool null_timespec(struct timespec ts)
     893             : {
     894   157895963 :         return ts.tv_sec == 0 ||
     895   157895963 :                 ts.tv_sec == (time_t)0xFFFFFFFF ||
     896    78811712 :                 ts.tv_sec == (time_t)-1;
     897             : }
     898             : 
     899             : /****************************************************************************
     900             :  Convert a normalized timeval to a timespec.
     901             : ****************************************************************************/
     902             : 
     903           8 : struct timespec convert_timeval_to_timespec(const struct timeval tv)
     904             : {
     905           0 :         struct timespec ts;
     906           8 :         ts.tv_sec = tv.tv_sec;
     907           8 :         ts.tv_nsec = tv.tv_usec * 1000;
     908           8 :         return ts;
     909             : }
     910             : 
     911             : /****************************************************************************
     912             :  Convert a normalized timespec to a timeval.
     913             : ****************************************************************************/
     914             : 
     915           8 : struct timeval convert_timespec_to_timeval(const struct timespec ts)
     916             : {
     917           0 :         struct timeval tv;
     918           8 :         tv.tv_sec = ts.tv_sec;
     919           8 :         tv.tv_usec = ts.tv_nsec / 1000;
     920           8 :         return tv;
     921             : }
     922             : 
     923             : /****************************************************************************
     924             :  Return a timespec for the current time
     925             : ****************************************************************************/
     926             : 
     927      325257 : _PUBLIC_ struct timespec timespec_current(void)
     928             : {
     929         983 :         struct timespec ts;
     930      325257 :         clock_gettime(CLOCK_REALTIME, &ts);
     931      325257 :         return ts;
     932             : }
     933             : 
     934             : /****************************************************************************
     935             :  Return the lesser of two timespecs.
     936             : ****************************************************************************/
     937             : 
     938           0 : struct timespec timespec_min(const struct timespec *ts1,
     939             :                            const struct timespec *ts2)
     940             : {
     941           0 :         if (ts1->tv_sec < ts2->tv_sec) return *ts1;
     942           0 :         if (ts1->tv_sec > ts2->tv_sec) return *ts2;
     943           0 :         if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
     944           0 :         return *ts2;
     945             : }
     946             : 
     947             : /****************************************************************************
     948             :   compare two timespec structures.
     949             :   Return -1 if ts1 < ts2
     950             :   Return 0 if ts1 == ts2
     951             :   Return 1 if ts1 > ts2
     952             : ****************************************************************************/
     953             : 
     954    81395251 : _PUBLIC_ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
     955             : {
     956    81395251 :         if (ts1->tv_sec  > ts2->tv_sec)  return 1;
     957    78803078 :         if (ts1->tv_sec  < ts2->tv_sec)  return -1;
     958    77498238 :         if (ts1->tv_nsec > ts2->tv_nsec) return 1;
     959    69360186 :         if (ts1->tv_nsec < ts2->tv_nsec) return -1;
     960    58353300 :         return 0;
     961             : }
     962             : 
     963             : /****************************************************************************
     964             :  Round up a timespec if nsec > 500000000, round down if lower,
     965             :  then zero nsec.
     966             : ****************************************************************************/
     967             : 
     968       66128 : void round_timespec_to_sec(struct timespec *ts)
     969             : {
     970       66128 :         ts->tv_sec = convert_timespec_to_time_t(*ts);
     971       66128 :         ts->tv_nsec = 0;
     972       66128 : }
     973             : 
     974             : /****************************************************************************
     975             :  Round a timespec to usec value.
     976             : ****************************************************************************/
     977             : 
     978           0 : void round_timespec_to_usec(struct timespec *ts)
     979             : {
     980           0 :         struct timeval tv = convert_timespec_to_timeval(*ts);
     981           0 :         *ts = convert_timeval_to_timespec(tv);
     982           0 :         normalize_timespec(ts);
     983           0 : }
     984             : 
     985             : /****************************************************************************
     986             :  Round a timespec to NTTIME resolution.
     987             : ****************************************************************************/
     988             : 
     989           0 : void round_timespec_to_nttime(struct timespec *ts)
     990             : {
     991           0 :         ts->tv_nsec = (ts->tv_nsec / 100) * 100;
     992           0 : }
     993             : 
     994             : /****************************************************************************
     995             :  Put a 8 byte filetime from a struct timespec. Uses GMT.
     996             : ****************************************************************************/
     997             : 
     998       18130 : _PUBLIC_ NTTIME unix_timespec_to_nt_time(struct timespec ts)
     999             : {
    1000           0 :         uint64_t d;
    1001             : 
    1002       18130 :         if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
    1003           0 :                 return 0;
    1004             :         }
    1005       18130 :         if (ts.tv_sec == TIME_T_MAX) {
    1006           0 :                 return 0x7fffffffffffffffLL;
    1007             :         }
    1008       18130 :         if (ts.tv_sec == (time_t)-1) {
    1009           0 :                 return UINT64_MAX;
    1010             :         }
    1011             : 
    1012       18130 :         d = ts.tv_sec;
    1013       18130 :         d += TIME_FIXUP_CONSTANT_INT;
    1014       18130 :         d *= 1000*1000*10;
    1015             :         /* d is now in 100ns units. */
    1016       18130 :         d += (ts.tv_nsec / 100);
    1017             : 
    1018       18130 :         return d;
    1019             : }
    1020             : 
    1021             : /*
    1022             :  * Functions supporting the full range of time_t and struct timespec values,
    1023             :  * including 0, -1 and all other negative values. These functions don't use 0 or
    1024             :  * -1 values as sentinel to denote "unset" variables, but use the POSIX 2008
    1025             :  * define UTIME_OMIT from utimensat(2).
    1026             :  */
    1027             : 
    1028             : /**
    1029             :  * Check if it's a to be omitted timespec.
    1030             :  **/
    1031    13631534 : bool is_omit_timespec(const struct timespec *ts)
    1032             : {
    1033    13631534 :         return ts->tv_nsec == SAMBA_UTIME_OMIT;
    1034             : }
    1035             : 
    1036             : /**
    1037             :  * Return a to be omitted timespec.
    1038             :  **/
    1039     8688694 : struct timespec make_omit_timespec(void)
    1040             : {
    1041     8688694 :         return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1042             : }
    1043             : 
    1044             : /**
    1045             :  * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
    1046             :  * and -1. Also dealing with SAMBA_UTIME_OMIT.
    1047             :  **/
    1048     6298243 : NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
    1049             : {
    1050     6298243 :         struct timespec ts = *_ts;
    1051        9649 :         uint64_t d;
    1052             : 
    1053     6298243 :         if (is_omit_timespec(_ts)) {
    1054     1538629 :                 return NTTIME_OMIT;
    1055             :         }
    1056             : 
    1057             :         /* Ensure tv_nsec is less than 1 sec. */
    1058     4757254 :         while (ts.tv_nsec > 1000000000) {
    1059           0 :                 if (ts.tv_sec > TIME_T_MAX) {
    1060           0 :                         return NTTIME_MAX;
    1061             :                 }
    1062           0 :                 ts.tv_sec += 1;
    1063           0 :                 ts.tv_nsec -= 1000000000;
    1064             :         }
    1065             : 
    1066     4757254 :         if (ts.tv_sec >= TIME_T_MAX) {
    1067           0 :                 return NTTIME_MAX;
    1068             :         }
    1069     4757254 :         if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
    1070           0 :                 return NTTIME_MIN;
    1071             :         }
    1072             : 
    1073     4757254 :         d = TIME_FIXUP_CONSTANT_INT;
    1074     4757254 :         d += ts.tv_sec;
    1075             : 
    1076     4757254 :         d *= 1000*1000*10;
    1077             :         /* d is now in 100ns units. */
    1078     4757254 :         d += (ts.tv_nsec / 100);
    1079             : 
    1080     4757254 :         return d;
    1081             : }
    1082             : 
    1083             : /**
    1084             :  * Like nt_time_to_unix_timespec() but allowing negative tv_sec values and
    1085             :  * returning NTTIME=0 and -1 as struct timespec {.tv_nsec = SAMBA_UTIME_OMIT}.
    1086             :  *
    1087             :  * See also: is_omit_timespec().
    1088             :  **/
    1089     2532668 : struct timespec nt_time_to_full_timespec(NTTIME nt)
    1090             : {
    1091        8507 :         struct timespec ret;
    1092             : 
    1093     2532668 :         if (nt == NTTIME_OMIT) {
    1094       90625 :                 return make_omit_timespec();
    1095             :         }
    1096     2442043 :         if (nt == NTTIME_FREEZE || nt == NTTIME_THAW) {
    1097             :                 /*
    1098             :                  * This should be returned as SAMBA_UTIME_FREEZE or
    1099             :                  * SAMBA_UTIME_THAW in the future.
    1100             :                  */
    1101        4159 :                 return make_omit_timespec();
    1102             :         }
    1103     2437884 :         if (nt > NTTIME_MAX) {
    1104           2 :                 nt = NTTIME_MAX;
    1105             :         }
    1106             : 
    1107     2437884 :         ret = nt_time_to_unix_timespec_raw(nt);
    1108             : 
    1109     2437884 :         if (ret.tv_sec >= TIME_T_MAX) {
    1110           0 :                 ret.tv_sec = TIME_T_MAX;
    1111           0 :                 ret.tv_nsec = 0;
    1112           0 :                 return ret;
    1113             :         }
    1114             : 
    1115     2437884 :         return ret;
    1116             : }
    1117             : 
    1118             : /**
    1119             :  * Note: this function uses the full time_t range as valid date values including
    1120             :  * (time_t)0 and -1. That means that struct timespec sentinel values (cf
    1121             :  * is_omit_timespec()) can't be converted to sentinel values in a time_t
    1122             :  * representation. Callers should therefore check the NTTIME value with
    1123             :  * null_nttime() before calling this function.
    1124             :  **/
    1125      259111 : time_t full_timespec_to_time_t(const struct timespec *_ts)
    1126             : {
    1127      259111 :         struct timespec ts = *_ts;
    1128             : 
    1129      259111 :         if (is_omit_timespec(_ts)) {
    1130             :                 /*
    1131             :                  * Unfortunately there's no sensible sentinel value in the
    1132             :                  * time_t range that is not conflicting with a valid time value
    1133             :                  * ((time_t)0 and -1 are valid time values). Bite the bullit and
    1134             :                  * return 0.
    1135             :                  */
    1136           0 :                 return 0;
    1137             :         }
    1138             : 
    1139             :         /* Ensure tv_nsec is less than 1sec. */
    1140      259111 :         while (ts.tv_nsec > 1000000000) {
    1141           0 :                 ts.tv_sec += 1;
    1142           0 :                 ts.tv_nsec -= 1000000000;
    1143             :         }
    1144             : 
    1145             :         /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
    1146             :            increment if it's greater than 500 millionth of a second. */
    1147             : 
    1148      259111 :         if (ts.tv_nsec > 500000000) {
    1149       17932 :                 return ts.tv_sec + 1;
    1150             :         }
    1151      237879 :         return ts.tv_sec;
    1152             : }
    1153             : 
    1154             : /**
    1155             :  * Like nt_time_to_unix() but supports negative time_t values.
    1156             :  *
    1157             :  * Note: this function uses the full time_t range as valid date values including
    1158             :  * (time_t)0 and -1. That means that NTTIME sentinel values of 0 and -1 which
    1159             :  * represent a "not-set" value, can't be converted to sentinel values in a
    1160             :  * time_t representation. Callers should therefore check the NTTIME value with
    1161             :  * null_nttime() before calling this function.
    1162             :  **/
    1163      259111 : time_t nt_time_to_full_time_t(NTTIME nt)
    1164             : {
    1165        3982 :         struct timespec ts;
    1166             : 
    1167      259111 :         ts = nt_time_to_full_timespec(nt);
    1168      259111 :         return full_timespec_to_time_t(&ts);
    1169             : }
    1170             : 
    1171             : /**
    1172             :  * Like time_t_to_unix_timespec() but supports negative time_t values.
    1173             :  *
    1174             :  * This version converts (time_t)0 and -1 to an is_omit_timespec(), so 0 and -1
    1175             :  * can't be used as valid date values. The function supports values < -1 though.
    1176             :  **/
    1177       32606 : struct timespec time_t_to_full_timespec(time_t t)
    1178             : {
    1179       32606 :         if (null_time(t)) {
    1180       32416 :                 return (struct timespec){.tv_nsec = SAMBA_UTIME_OMIT};
    1181             :         }
    1182         190 :         return (struct timespec){.tv_sec = t};
    1183             : }
    1184             : 
    1185             : #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
    1186             : 
    1187             : /* Old system - no ns timestamp. */
    1188             : time_t get_atimensec(const struct stat *st)
    1189             : {
    1190             :         return 0;
    1191             : }
    1192             : 
    1193             : time_t get_mtimensec(const struct stat *st)
    1194             : {
    1195             :         return 0;
    1196             : }
    1197             : 
    1198             : time_t get_ctimensec(const struct stat *st)
    1199             : {
    1200             :         return 0;
    1201             : }
    1202             : 
    1203             : /* Set does nothing with no ns timestamp. */
    1204             : void set_atimensec(struct stat *st, time_t ns)
    1205             : {
    1206             :         return;
    1207             : }
    1208             : 
    1209             : void set_mtimensec(struct stat *st, time_t ns)
    1210             : {
    1211             :         return;
    1212             : }
    1213             : 
    1214             : void set_ctimensec(struct stat *st, time_t ns)
    1215             : {
    1216             :         return;
    1217             : }
    1218             : 
    1219             : #elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
    1220             : 
    1221             : time_t get_atimensec(const struct stat *st)
    1222             : {
    1223             :         return st->st_atimespec.tv_nsec;
    1224             : }
    1225             : 
    1226             : time_t get_mtimensec(const struct stat *st)
    1227             : {
    1228             :         return st->st_mtimespec.tv_nsec;
    1229             : }
    1230             : 
    1231             : time_t get_ctimensec(const struct stat *st)
    1232             : {
    1233             :         return st->st_ctimespec.tv_nsec;
    1234             : }
    1235             : 
    1236             : void set_atimensec(struct stat *st, time_t ns)
    1237             : {
    1238             :         st->st_atimespec.tv_nsec = ns;
    1239             : }
    1240             : 
    1241             : void set_mtimensec(struct stat *st, time_t ns)
    1242             : {
    1243             :         st->st_mtimespec.tv_nsec = ns;
    1244             : }
    1245             : 
    1246             : void set_ctimensec(struct stat *st, time_t ns)
    1247             : {
    1248             :         st->st_ctimespec.tv_nsec = ns;
    1249             : }
    1250             : 
    1251             : #elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
    1252             : 
    1253    79868083 : time_t get_atimensec(const struct stat *st)
    1254             : {
    1255    79868083 :         return st->st_atim.tv_nsec;
    1256             : }
    1257             : 
    1258    80674985 : time_t get_mtimensec(const struct stat *st)
    1259             : {
    1260    80674985 :         return st->st_mtim.tv_nsec;
    1261             : }
    1262             : 
    1263    80674610 : time_t get_ctimensec(const struct stat *st)
    1264             : {
    1265    80674610 :         return st->st_ctim.tv_nsec;
    1266             : }
    1267             : 
    1268         215 : void set_atimensec(struct stat *st, time_t ns)
    1269             : {
    1270         215 :         st->st_atim.tv_nsec = ns;
    1271         215 : }
    1272             : 
    1273         215 : void set_mtimensec(struct stat *st, time_t ns)
    1274             : {
    1275         215 :         st->st_mtim.tv_nsec = ns;
    1276         215 : }
    1277         215 : void set_ctimensec(struct stat *st, time_t ns)
    1278             : {
    1279         215 :         st->st_ctim.tv_nsec = ns;
    1280         215 : }
    1281             : 
    1282             : #elif HAVE_STRUCT_STAT_ST_MTIMENSEC
    1283             : 
    1284             : time_t get_atimensec(const struct stat *st)
    1285             : {
    1286             :         return st->st_atimensec;
    1287             : }
    1288             : 
    1289             : time_t get_mtimensec(const struct stat *st)
    1290             : {
    1291             :         return st->st_mtimensec;
    1292             : }
    1293             : 
    1294             : time_t get_ctimensec(const struct stat *st)
    1295             : {
    1296             :         return st->st_ctimensec;
    1297             : }
    1298             : 
    1299             : void set_atimensec(struct stat *st, time_t ns)
    1300             : {
    1301             :         st->st_atimensec = ns;
    1302             : }
    1303             : 
    1304             : void set_mtimensec(struct stat *st, time_t ns)
    1305             : {
    1306             :         st->st_mtimensec = ns;
    1307             : }
    1308             : 
    1309             : void set_ctimensec(struct stat *st, time_t ns)
    1310             : {
    1311             :         st->st_ctimensec = ns;
    1312             : }
    1313             : 
    1314             : #elif HAVE_STRUCT_STAT_ST_MTIME_N
    1315             : 
    1316             : time_t get_atimensec(const struct stat *st)
    1317             : {
    1318             :         return st->st_atime_n;
    1319             : }
    1320             : 
    1321             : time_t get_mtimensec(const struct stat *st)
    1322             : {
    1323             :         return st->st_mtime_n;
    1324             : }
    1325             : 
    1326             : time_t get_ctimensec(const struct stat *st)
    1327             : {
    1328             :         return st->st_ctime_n;
    1329             : }
    1330             : 
    1331             : void set_atimensec(struct stat *st, time_t ns)
    1332             : {
    1333             :         st->st_atime_n = ns;
    1334             : }
    1335             : 
    1336             : void set_mtimensec(struct stat *st, time_t ns)
    1337             : {
    1338             :         st->st_mtime_n = ns;
    1339             : }
    1340             : 
    1341             : void set_ctimensec(struct stat *st, time_t ns)
    1342             : {
    1343             :         st->st_ctime_n = ns;
    1344             : }
    1345             : 
    1346             : #elif HAVE_STRUCT_STAT_ST_UMTIME
    1347             : 
    1348             : /* Only usec timestamps available. Convert to/from nsec. */
    1349             : 
    1350             : time_t get_atimensec(const struct stat *st)
    1351             : {
    1352             :         return st->st_uatime * 1000;
    1353             : }
    1354             : 
    1355             : time_t get_mtimensec(const struct stat *st)
    1356             : {
    1357             :         return st->st_umtime * 1000;
    1358             : }
    1359             : 
    1360             : time_t get_ctimensec(const struct stat *st)
    1361             : {
    1362             :         return st->st_uctime * 1000;
    1363             : }
    1364             : 
    1365             : void set_atimensec(struct stat *st, time_t ns)
    1366             : {
    1367             :         st->st_uatime = ns / 1000;
    1368             : }
    1369             : 
    1370             : void set_mtimensec(struct stat *st, time_t ns)
    1371             : {
    1372             :         st->st_umtime = ns / 1000;
    1373             : }
    1374             : 
    1375             : void set_ctimensec(struct stat *st, time_t ns)
    1376             : {
    1377             :         st->st_uctime = ns / 1000;
    1378             : }
    1379             : 
    1380             : #else
    1381             : #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
    1382             : #endif
    1383             : 
    1384    79061552 : struct timespec get_atimespec(const struct stat *pst)
    1385             : {
    1386      271098 :         struct timespec ret;
    1387             : 
    1388    79061552 :         ret.tv_sec = pst->st_atime;
    1389    79061552 :         ret.tv_nsec = get_atimensec(pst);
    1390    79061552 :         return ret;
    1391             : }
    1392             : 
    1393    79868450 : struct timespec get_mtimespec(const struct stat *pst)
    1394             : {
    1395      275748 :         struct timespec ret;
    1396             : 
    1397    79868450 :         ret.tv_sec = pst->st_mtime;
    1398    79868450 :         ret.tv_nsec = get_mtimensec(pst);
    1399    79868450 :         return ret;
    1400             : }
    1401             : 
    1402    79061548 : struct timespec get_ctimespec(const struct stat *pst)
    1403             : {
    1404      271098 :         struct timespec ret;
    1405             : 
    1406    79061548 :         ret.tv_sec = pst->st_ctime;
    1407    79061548 :         ret.tv_nsec = get_ctimensec(pst);
    1408    79061548 :         return ret;
    1409             : }
    1410             : 
    1411             : /****************************************************************************
    1412             :  Deal with nanoseconds overflow.
    1413             : ****************************************************************************/
    1414             : 
    1415     3238782 : void normalize_timespec(struct timespec *ts)
    1416             : {
    1417      151578 :         lldiv_t dres;
    1418             : 
    1419             :         /* most likely case: nsec is valid */
    1420     3238782 :         if ((unsigned long)ts->tv_nsec < NSEC_PER_SEC) {
    1421     3238782 :                 return;
    1422             :         }
    1423             : 
    1424       21552 :         dres = lldiv(ts->tv_nsec, NSEC_PER_SEC);
    1425             : 
    1426             :         /* if the operation would result in overflow, max out values and bail */
    1427       21552 :         if (dres.quot > 0) {
    1428       21540 :                 if ((int64_t)LONG_MAX - dres.quot < ts->tv_sec) {
    1429           1 :                         ts->tv_sec = LONG_MAX;
    1430           1 :                         ts->tv_nsec = NSEC_PER_SEC - 1;
    1431           1 :                         return;
    1432             :                 }
    1433             :         } else {
    1434          12 :                 if ((int64_t)LONG_MIN - dres.quot > ts->tv_sec) {
    1435           1 :                         ts->tv_sec = LONG_MIN;
    1436           1 :                         ts->tv_nsec = 0;
    1437           1 :                         return;
    1438             :                 }
    1439             :         }
    1440             : 
    1441       21550 :         ts->tv_nsec = dres.rem;
    1442       21550 :         ts->tv_sec += dres.quot;
    1443             : 
    1444             :         /* if the ns part was positive or a multiple of -1000000000, we're done */
    1445       21550 :         if (ts->tv_nsec > 0 || dres.rem == 0) {
    1446       21532 :                 return;
    1447             :         }
    1448             : 
    1449           9 :         ts->tv_nsec += NSEC_PER_SEC;
    1450           9 :         --ts->tv_sec;
    1451             : }

Generated by: LCOV version 1.14