LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/roken - timeval.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 29 39 74.4 %
Date: 2024-04-13 12:30:31 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1999 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : /*
      35             :  * Timeval stuff
      36             :  */
      37             : 
      38             : #include <config.h>
      39             : 
      40             : #include "roken.h"
      41             : 
      42             : ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
      43      673874 : rk_time_add(time_t t, time_t delta)
      44             : {
      45      673874 :     if (delta == 0)
      46      192235 :         return t;
      47             : 
      48             : #ifdef TIME_T_SIGNED
      49             :     /* Signed overflow is UB in C */
      50             : #if SIZEOF_TIME_T == 4
      51             :     if (t >= 0 && delta > 0 && INT32_MAX - t < delta)
      52             :         /* Time left to hit INT32_MAX is less than what we want to add */
      53             :         return INT32_MAX;
      54             :     else if (t == INT32_MIN && delta < 0)
      55             :         /* Avoid computing -t when t == INT32_MIN! */
      56             :         return INT32_MIN;
      57             :     else if (t < 0 && delta < 0 && INT32_MIN + (-t) > delta)
      58             :         /* Time left to hit INT32_MIN is less than what we want to subtract */
      59             :         return INT32_MIN;
      60             :     else
      61             :         return t + delta;
      62             : #elif SIZEOF_TIME_T == 8
      63      473670 :     if (t >= 0 && delta > 0 && INT64_MAX - t < delta)
      64           0 :         return INT64_MAX;
      65      473670 :     else if (t == INT64_MIN && delta < 0)
      66             :         /* Avoid computing -t when t == INT64_MIN! */
      67           0 :         return INT64_MIN;
      68      473670 :     else if (t < 0 && delta < 0 && INT64_MIN + (-t) > delta)
      69           0 :         return INT64_MIN;
      70             :     else
      71      473670 :         return t + delta;
      72             : #else
      73             : #error "Unexpected sizeof(time_t)"
      74             : #endif
      75             : #else
      76             : 
      77             :     /* Unsigned overflow is defined in C */
      78             : #if SIZEOF_TIME_T == 4
      79             :     if (t + delta < t)
      80             :         return UINT32_MAX;
      81             : #elif SIZEOF_TIME_T == 8
      82             :     if (t + delta < t)
      83             :         return UINT64_MAX;
      84             : #else
      85             : #error "Unexpected sizeof(time_t)"
      86             : #endif
      87             :     return t + delta;
      88             : #endif
      89             : }
      90             : 
      91             : ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL
      92      403283 : rk_time_sub(time_t t, time_t delta)
      93             : {
      94      403283 :     if (delta == 0)
      95           0 :         return t;
      96             : #ifdef TIME_T_SIGNED
      97      403283 :     if (delta > 0)
      98      403283 :         return rk_time_add(t, -delta);
      99             : #if SIZEOF_TIME_T == 4
     100             :     if (delta == INT32_MIN) {
     101             :         if (t < 0) {
     102             :             t = t + INT32_MAX;
     103             :             return t + 1;
     104             :         }
     105             :         return INT32_MAX;
     106             :     }
     107             :     /* Safe to compute -delta, so use rk_time_add() to add -delta */
     108             :     return rk_time_add(t, -delta);
     109             : #elif SIZEOF_TIME_T == 8
     110           0 :     if (delta == INT64_MIN) {
     111           0 :         if (t < 0) {
     112           0 :             t = t + INT64_MAX;
     113           0 :             return t + 1;
     114             :         }
     115           0 :         return INT64_MAX;
     116             :     }
     117           0 :     return rk_time_add(t, -delta);
     118             : #else
     119             : #error "Unexpected sizeof(time_t)"
     120             : #endif
     121             : #else
     122             :     /* Both t and delta are non-negative. */
     123             :     if (delta > t)
     124             :         return 0;
     125             :     return t - delta;
     126             : #endif
     127             : }
     128             : 
     129             : /*
     130             :  * Make `t1' consistent.
     131             :  */
     132             : 
     133             : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
     134      486285 : timevalfix(struct timeval *t1)
     135             : {
     136      486285 :     if (t1->tv_usec < 0) {
     137        2295 :         t1->tv_sec = rk_time_sub(t1->tv_sec, 1);
     138        2295 :         t1->tv_usec = 1000000;
     139             :     }
     140      486285 :     if (t1->tv_usec >= 1000000) {
     141        2295 :         t1->tv_sec = rk_time_add(t1->tv_sec, 1);
     142        2295 :         t1->tv_usec -= 1000000;
     143             :     }
     144      486285 : }
     145             : 
     146             : /*
     147             :  * t1 += t2
     148             :  */
     149             : 
     150             : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
     151      201637 : timevaladd(struct timeval *t1, const struct timeval *t2)
     152             : {
     153      201637 :     t1->tv_sec   = rk_time_add(t1->tv_sec, t2->tv_sec);
     154      201637 :     t1->tv_usec += t2->tv_usec;
     155      201637 :     timevalfix(t1);
     156      201637 : }
     157             : 
     158             : /*
     159             :  * t1 -= t2
     160             :  */
     161             : 
     162             : ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
     163      284648 : timevalsub(struct timeval *t1, const struct timeval *t2)
     164             : {
     165      284648 :     t1->tv_sec   = rk_time_sub(t1->tv_sec, t2->tv_sec);
     166      284648 :     t1->tv_usec -= t2->tv_usec;
     167      284648 :     timevalfix(t1);
     168      284648 : }
     169             : 
     170             : #ifdef TEST
     171             : int
     172             : main(int argc, char **argv)
     173             : {
     174             :     time_t t, delta, r;
     175             :     int e = 0;
     176             : 
     177             :     if (argc == 0)
     178             :         return 0; /* Apparently POSIX and Linux allow this case */
     179             : 
     180             :     argc--;
     181             :     argv++;
     182             : 
     183             :     while (argc > 0) {
     184             :         int64_t n;
     185             :         time_t a;
     186             :         char *ends;
     187             : 
     188             :         if (argc < 3)
     189             :             errx(1, "Usage: [TIME +|- DELTA [== TIME]]");
     190             : 
     191             :         errno = 0;
     192             :         n = strtoll(argv[0], &ends, 0);
     193             :         if (errno)
     194             :             err(1, "Time value is invalid");
     195             :         if (*ends != '\0')
     196             :             errx(1, "Time value is invalid");
     197             :         t = n;
     198             : 
     199             :         n = strtoll(argv[2], &ends, 0);
     200             :         if (errno)
     201             :             err(1, "Delta value is invalid");
     202             :         if (*ends != '\0')
     203             :             errx(1, "Delta value is invalid");
     204             :         delta = n;
     205             : 
     206             :         if (argv[1][0] == '+' && argv[1][1] == '\0')
     207             :             r = rk_time_add(t, delta);
     208             :         else if (argv[1][0] == '-' && argv[1][1] == '\0')
     209             :             r = rk_time_sub(t, delta);
     210             :         else
     211             :             errx(1, "Operator must be a + or a - arithmetic operator");
     212             : 
     213             :         if (delta == 0 && r != t) {
     214             :             warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[0]);
     215             :             e = 1;
     216             :         }
     217             :         if (t == 0 && r != delta) {
     218             :             warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[2]);
     219             :             e = 1;
     220             :         }
     221             : 
     222             :         if (argc > 4 && strcmp(argv[3], "==") == 0) {
     223             :             n = strtoll(argv[4], &ends, 0);
     224             :             if (errno)
     225             :                 err(1, "Time value is invalid");
     226             :             if (*ends != '\0')
     227             :                 errx(1, "Time value is invalid");
     228             :             a = n;
     229             :             if (a != r) {
     230             :                 warnx("%s %s %s != %s!", argv[0], argv[1], argv[2], argv[4]);
     231             :                 e = 1;
     232             :             }
     233             :             argc -= 5;
     234             :             argv += 5;
     235             :         } else {
     236             : #ifdef TIME_T_SIGNED
     237             :             printf("%s %s %s == %lld\n", argv[0], argv[1], argv[2],
     238             :                    (long long)r);
     239             : #else
     240             :             printf("%s %s %s == %llu\n", argv[0], argv[1], argv[2],
     241             :                    (unsigned long long)r);
     242             : #endif
     243             :             argc -= 3;
     244             :             argv += 3;
     245             :         }
     246             :     }
     247             : 
     248             : #define CHECK(e) do { if (!(e)) errx(1, "Expression not true: " #e "!"); } while (0)
     249             : #ifdef TIME_T_SIGNED
     250             : #if SIZEOF_TIME_T == 4
     251             :     CHECK(rk_time_add(INT32_MIN, -1) == INT32_MIN);
     252             :     CHECK(rk_time_sub(INT32_MIN,  1) == INT32_MIN);
     253             :     CHECK(rk_time_sub(-1, INT32_MAX) == INT32_MIN);
     254             :     CHECK(rk_time_add(INT32_MAX,  0) == INT32_MAX);
     255             :     CHECK(rk_time_add(INT32_MAX,  1) == INT32_MAX);
     256             :     CHECK(rk_time_add(1,  INT32_MAX) == INT32_MAX);
     257             :     CHECK(rk_time_add(0,  INT32_MAX) == INT32_MAX);
     258             : #elif SIZEOF_TIME_T == 8
     259             :     CHECK(rk_time_add(INT64_MIN, -1) == INT64_MIN);
     260             :     CHECK(rk_time_sub(INT64_MIN,  1) == INT64_MIN);
     261             :     CHECK(rk_time_sub(-1, INT64_MAX) == INT64_MIN);
     262             :     CHECK(rk_time_add(INT64_MAX,  0) == INT64_MAX);
     263             :     CHECK(rk_time_add(INT64_MAX,  1) == INT64_MAX);
     264             :     CHECK(rk_time_add(1,  INT64_MAX) == INT64_MAX);
     265             :     CHECK(rk_time_add(0,  INT64_MAX) == INT64_MAX);
     266             : #endif
     267             :     CHECK(rk_time_add(0, -1) == -1);
     268             :     CHECK(rk_time_sub(0,  1) == -1);
     269             : #else
     270             : #if SIZEOF_TIME_T == 4
     271             :     CHECK(rk_time_add(UINT32_MAX, 0) == UINT32_MAX);
     272             :     CHECK(rk_time_add(UINT32_MAX, 1) == UINT32_MAX);
     273             :     CHECK(rk_time_add(1, UINT32_MAX) == UINT32_MAX);
     274             :     CHECK(rk_time_add(0, UINT32_MAX) == UINT32_MAX);
     275             : #elif SIZEOF_TIME_T == 8
     276             :     CHECK(rk_time_add(UINT64_MAX, 0) == UINT64_MAX);
     277             :     CHECK(rk_time_add(UINT64_MAX, 1) == UINT64_MAX);
     278             :     CHECK(rk_time_add(1, UINT64_MAX) == UINT64_MAX);
     279             :     CHECK(rk_time_add(0, UINT64_MAX) == UINT64_MAX);
     280             : #endif
     281             : #endif
     282             :     CHECK(rk_time_add(0, 1) == 1);
     283             :     CHECK(rk_time_add(1, 0) == 1);
     284             :     return e;
     285             : }
     286             : #endif

Generated by: LCOV version 1.14