LCOV - code coverage report
Current view: top level - third_party/openssl/crypto - o_time.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 3 65 4.6 %
Date: 2015-10-10 Functions: 1 6 16.7 %

          Line data    Source code
       1             : /* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */
       2             : /*
       3             :  * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
       4             :  * 2001.
       5             :  */
       6             : /*
       7             :  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
       8             :  * 2008.
       9             :  */
      10             : /* ====================================================================
      11             :  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  *
      17             :  * 1. Redistributions of source code must retain the above copyright
      18             :  *    notice, this list of conditions and the following disclaimer.
      19             :  *
      20             :  * 2. Redistributions in binary form must reproduce the above copyright
      21             :  *    notice, this list of conditions and the following disclaimer in
      22             :  *    the documentation and/or other materials provided with the
      23             :  *    distribution.
      24             :  *
      25             :  * 3. All advertising materials mentioning features or use of this
      26             :  *    software must display the following acknowledgment:
      27             :  *    "This product includes software developed by the OpenSSL Project
      28             :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      29             :  *
      30             :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      31             :  *    endorse or promote products derived from this software without
      32             :  *    prior written permission. For written permission, please contact
      33             :  *    licensing@OpenSSL.org.
      34             :  *
      35             :  * 5. Products derived from this software may not be called "OpenSSL"
      36             :  *    nor may "OpenSSL" appear in their names without prior written
      37             :  *    permission of the OpenSSL Project.
      38             :  *
      39             :  * 6. Redistributions of any form whatsoever must retain the following
      40             :  *    acknowledgment:
      41             :  *    "This product includes software developed by the OpenSSL Project
      42             :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      43             :  *
      44             :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      45             :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      46             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      47             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      48             :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      49             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      50             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      51             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      52             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      53             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      54             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      55             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      56             :  * ====================================================================
      57             :  *
      58             :  * This product includes cryptographic software written by Eric Young
      59             :  * (eay@cryptsoft.com).  This product includes software written by Tim
      60             :  * Hudson (tjh@cryptsoft.com).
      61             :  *
      62             :  */
      63             : 
      64             : #include <openssl/e_os2.h>
      65             : #include <string.h>
      66             : #include "o_time.h"
      67             : 
      68             : #ifdef OPENSSL_SYS_VMS
      69             : # if __CRTL_VER >= 70000000 && \
      70             :      (defined _POSIX_C_SOURCE || !defined _ANSI_C_SOURCE)
      71             : #  define VMS_GMTIME_OK
      72             : # endif
      73             : # ifndef VMS_GMTIME_OK
      74             : #  include <libdtdef.h>
      75             : #  include <lib$routines.h>
      76             : #  include <lnmdef.h>
      77             : #  include <starlet.h>
      78             : #  include <descrip.h>
      79             : #  include <stdlib.h>
      80             : # endif                         /* ndef VMS_GMTIME_OK */
      81             : #endif
      82             : 
      83        1480 : struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result)
      84             : {
      85             :     struct tm *ts = NULL;
      86             : 
      87             : #if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_OS2) && (!defined(OPENSSL_SYS_VMS) || defined(gmtime_r)) && !defined(OPENSSL_SYS_MACOSX) && !defined(OPENSSL_SYS_SUNOS)
      88             :     /*
      89             :      * should return &data, but doesn't on some systems, so we don't even
      90             :      * look at the return value
      91             :      */
      92        1480 :     gmtime_r(timer, result);
      93             :     ts = result;
      94             : #elif !defined(OPENSSL_SYS_VMS) || defined(VMS_GMTIME_OK)
      95             :     ts = gmtime(timer);
      96             :     if (ts == NULL)
      97             :         return NULL;
      98             : 
      99             :     memcpy(result, ts, sizeof(struct tm));
     100             :     ts = result;
     101             : #endif
     102             : #if defined( OPENSSL_SYS_VMS) && !defined( VMS_GMTIME_OK)
     103             :     if (ts == NULL) {
     104             :         static $DESCRIPTOR(tabnam, "LNM$DCL_LOGICAL");
     105             :         static $DESCRIPTOR(lognam, "SYS$TIMEZONE_DIFFERENTIAL");
     106             :         char logvalue[256];
     107             :         unsigned int reslen = 0;
     108             :         struct {
     109             :             short buflen;
     110             :             short code;
     111             :             void *bufaddr;
     112             :             unsigned int *reslen;
     113             :         } itemlist[] = {
     114             :             {
     115             :                 0, LNM$_STRING, 0, 0
     116             :             },
     117             :             {
     118             :                 0, 0, 0, 0
     119             :             },
     120             :         };
     121             :         int status;
     122             :         time_t t;
     123             : 
     124             :         /* Get the value for SYS$TIMEZONE_DIFFERENTIAL */
     125             :         itemlist[0].buflen = sizeof(logvalue);
     126             :         itemlist[0].bufaddr = logvalue;
     127             :         itemlist[0].reslen = &reslen;
     128             :         status = sys$trnlnm(0, &tabnam, &lognam, 0, itemlist);
     129             :         if (!(status & 1))
     130             :             return NULL;
     131             :         logvalue[reslen] = '\0';
     132             : 
     133             :         t = *timer;
     134             : 
     135             : /* The following is extracted from the DEC C header time.h */
     136             :         /*
     137             :          **  Beginning in OpenVMS Version 7.0 mktime, time, ctime, strftime
     138             :          **  have two implementations.  One implementation is provided
     139             :          **  for compatibility and deals with time in terms of local time,
     140             :          **  the other __utc_* deals with time in terms of UTC.
     141             :          */
     142             :         /*
     143             :          * We use the same conditions as in said time.h to check if we should
     144             :          * assume that t contains local time (and should therefore be
     145             :          * adjusted) or UTC (and should therefore be left untouched).
     146             :          */
     147             : # if __CRTL_VER < 70000000 || defined _VMS_V6_SOURCE
     148             :         /* Get the numerical value of the equivalence string */
     149             :         status = atoi(logvalue);
     150             : 
     151             :         /* and use it to move time to GMT */
     152             :         t -= status;
     153             : # endif
     154             : 
     155             :         /* then convert the result to the time structure */
     156             : 
     157             :         /*
     158             :          * Since there was no gmtime_r() to do this stuff for us, we have to
     159             :          * do it the hard way.
     160             :          */
     161             :         {
     162             :             /*-
     163             :              * The VMS epoch is the astronomical Smithsonian date,
     164             :                if I remember correctly, which is November 17, 1858.
     165             :                Furthermore, time is measure in thenths of microseconds
     166             :                and stored in quadwords (64 bit integers).  unix_epoch
     167             :                below is January 1st 1970 expressed as a VMS time.  The
     168             :                following code was used to get this number:
     169             : 
     170             :                #include <stdio.h>
     171             :                #include <stdlib.h>
     172             :                #include <lib$routines.h>
     173             :                #include <starlet.h>
     174             : 
     175             :                main()
     176             :                {
     177             :                  unsigned long systime[2];
     178             :                  unsigned short epoch_values[7] =
     179             :                    { 1970, 1, 1, 0, 0, 0, 0 };
     180             : 
     181             :                  lib$cvt_vectim(epoch_values, systime);
     182             : 
     183             :                  printf("%u %u", systime[0], systime[1]);
     184             :                }
     185             :             */
     186             :             unsigned long unix_epoch[2] = { 1273708544, 8164711 };
     187             :             unsigned long deltatime[2];
     188             :             unsigned long systime[2];
     189             :             struct vms_vectime {
     190             :                 short year, month, day, hour, minute, second, centi_second;
     191             :             } time_values;
     192             :             long operation;
     193             : 
     194             :             /*
     195             :              * Turn the number of seconds since January 1st 1970 to an
     196             :              * internal delta time. Note that lib$cvt_to_internal_time() will
     197             :              * assume that t is signed, and will therefore break on 32-bit
     198             :              * systems some time in 2038.
     199             :              */
     200             :             operation = LIB$K_DELTA_SECONDS;
     201             :             status = lib$cvt_to_internal_time(&operation, &t, deltatime);
     202             : 
     203             :             /*
     204             :              * Add the delta time with the Unix epoch and we have the current
     205             :              * UTC time in internal format
     206             :              */
     207             :             status = lib$add_times(unix_epoch, deltatime, systime);
     208             : 
     209             :             /* Turn the internal time into a time vector */
     210             :             status = sys$numtim(&time_values, systime);
     211             : 
     212             :             /* Fill in the struct tm with the result */
     213             :             result->tm_sec = time_values.second;
     214             :             result->tm_min = time_values.minute;
     215             :             result->tm_hour = time_values.hour;
     216             :             result->tm_mday = time_values.day;
     217             :             result->tm_mon = time_values.month - 1;
     218             :             result->tm_year = time_values.year - 1900;
     219             : 
     220             :             operation = LIB$K_DAY_OF_WEEK;
     221             :             status = lib$cvt_from_internal_time(&operation,
     222             :                                                 &result->tm_wday, systime);
     223             :             result->tm_wday %= 7;
     224             : 
     225             :             operation = LIB$K_DAY_OF_YEAR;
     226             :             status = lib$cvt_from_internal_time(&operation,
     227             :                                                 &result->tm_yday, systime);
     228             :             result->tm_yday--;
     229             : 
     230             :             result->tm_isdst = 0; /* There's no way to know... */
     231             : 
     232             :             ts = result;
     233             :         }
     234             :     }
     235             : #endif
     236        1480 :     return ts;
     237             : }
     238             : 
     239             : /*
     240             :  * Take a tm structure and add an offset to it. This avoids any OS issues
     241             :  * with restricted date types and overflows which cause the year 2038
     242             :  * problem.
     243             :  */
     244             : 
     245             : #define SECS_PER_DAY (24 * 60 * 60)
     246             : 
     247             : static long date_to_julian(int y, int m, int d);
     248             : static void julian_to_date(long jd, int *y, int *m, int *d);
     249             : static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
     250             :                       long *pday, int *psec);
     251             : 
     252           0 : int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
     253             : {
     254             :     int time_sec, time_year, time_month, time_day;
     255             :     long time_jd;
     256             : 
     257             :     /* Convert time and offset into julian day and seconds */
     258           0 :     if (!julian_adj(tm, off_day, offset_sec, &time_jd, &time_sec))
     259             :         return 0;
     260             : 
     261             :     /* Convert Julian day back to date */
     262             : 
     263           0 :     julian_to_date(time_jd, &time_year, &time_month, &time_day);
     264             : 
     265           0 :     if (time_year < 1900 || time_year > 9999)
     266             :         return 0;
     267             : 
     268             :     /* Update tm structure */
     269             : 
     270           0 :     tm->tm_year = time_year - 1900;
     271           0 :     tm->tm_mon = time_month - 1;
     272           0 :     tm->tm_mday = time_day;
     273             : 
     274           0 :     tm->tm_hour = time_sec / 3600;
     275           0 :     tm->tm_min = (time_sec / 60) % 60;
     276           0 :     tm->tm_sec = time_sec % 60;
     277             : 
     278           0 :     return 1;
     279             : 
     280             : }
     281             : 
     282           0 : int OPENSSL_gmtime_diff(int *pday, int *psec,
     283             :                         const struct tm *from, const struct tm *to)
     284             : {
     285             :     int from_sec, to_sec, diff_sec;
     286             :     long from_jd, to_jd, diff_day;
     287           0 :     if (!julian_adj(from, 0, 0, &from_jd, &from_sec))
     288             :         return 0;
     289           0 :     if (!julian_adj(to, 0, 0, &to_jd, &to_sec))
     290             :         return 0;
     291           0 :     diff_day = to_jd - from_jd;
     292           0 :     diff_sec = to_sec - from_sec;
     293             :     /* Adjust differences so both positive or both negative */
     294           0 :     if (diff_day > 0 && diff_sec < 0) {
     295           0 :         diff_day--;
     296           0 :         diff_sec += SECS_PER_DAY;
     297             :     }
     298           0 :     if (diff_day < 0 && diff_sec > 0) {
     299           0 :         diff_day++;
     300           0 :         diff_sec -= SECS_PER_DAY;
     301             :     }
     302             : 
     303           0 :     if (pday)
     304           0 :         *pday = (int)diff_day;
     305           0 :     if (psec)
     306           0 :         *psec = diff_sec;
     307             : 
     308             :     return 1;
     309             : 
     310             : }
     311             : 
     312             : /* Convert tm structure and offset into julian day and seconds */
     313           0 : static int julian_adj(const struct tm *tm, int off_day, long offset_sec,
     314             :                       long *pday, int *psec)
     315             : {
     316             :     int offset_hms, offset_day;
     317             :     long time_jd;
     318             :     int time_year, time_month, time_day;
     319             :     /* split offset into days and day seconds */
     320           0 :     offset_day = offset_sec / SECS_PER_DAY;
     321             :     /* Avoid sign issues with % operator */
     322           0 :     offset_hms = offset_sec - (offset_day * SECS_PER_DAY);
     323           0 :     offset_day += off_day;
     324             :     /* Add current time seconds to offset */
     325           0 :     offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
     326             :     /* Adjust day seconds if overflow */
     327           0 :     if (offset_hms >= SECS_PER_DAY) {
     328           0 :         offset_day++;
     329           0 :         offset_hms -= SECS_PER_DAY;
     330           0 :     } else if (offset_hms < 0) {
     331           0 :         offset_day--;
     332           0 :         offset_hms += SECS_PER_DAY;
     333             :     }
     334             : 
     335             :     /*
     336             :      * Convert date of time structure into a Julian day number.
     337             :      */
     338             : 
     339           0 :     time_year = tm->tm_year + 1900;
     340           0 :     time_month = tm->tm_mon + 1;
     341           0 :     time_day = tm->tm_mday;
     342             : 
     343           0 :     time_jd = date_to_julian(time_year, time_month, time_day);
     344             : 
     345             :     /* Work out Julian day of new date */
     346           0 :     time_jd += offset_day;
     347             : 
     348           0 :     if (time_jd < 0)
     349             :         return 0;
     350             : 
     351           0 :     *pday = time_jd;
     352           0 :     *psec = offset_hms;
     353           0 :     return 1;
     354             : }
     355             : 
     356             : /*
     357             :  * Convert date to and from julian day Uses Fliegel & Van Flandern algorithm
     358             :  */
     359           0 : static long date_to_julian(int y, int m, int d)
     360             : {
     361           0 :     return (1461 * (y + 4800 + (m - 14) / 12)) / 4 +
     362           0 :         (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 -
     363           0 :         (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + d - 32075;
     364             : }
     365             : 
     366           0 : static void julian_to_date(long jd, int *y, int *m, int *d)
     367             : {
     368           0 :     long L = jd + 68569;
     369           0 :     long n = (4 * L) / 146097;
     370             :     long i, j;
     371             : 
     372           0 :     L = L - (146097 * n + 3) / 4;
     373           0 :     i = (4000 * (L + 1)) / 1461001;
     374           0 :     L = L - (1461 * i) / 4 + 31;
     375           0 :     j = (80 * L) / 2447;
     376           0 :     *d = L - (2447 * j) / 80;
     377           0 :     L = j / 11;
     378           0 :     *m = j + 2 - (12 * L);
     379           0 :     *y = 100 * (n - 49) + i + L;
     380           0 : }
     381             : 
     382             : #ifdef OPENSSL_TIME_TEST
     383             : 
     384             : # include <stdio.h>
     385             : 
     386             : /*
     387             :  * Time checking test code. Check times are identical for a wide range of
     388             :  * offsets. This should be run on a machine with 64 bit time_t or it will
     389             :  * trigger the very errors the routines fix.
     390             :  */
     391             : 
     392             : int main(int argc, char **argv)
     393             : {
     394             :     long offset;
     395             :     for (offset = 0; offset < 1000000; offset++) {
     396             :         check_time(offset);
     397             :         check_time(-offset);
     398             :         check_time(offset * 1000);
     399             :         check_time(-offset * 1000);
     400             :     }
     401             : }
     402             : 
     403             : int check_time(long offset)
     404             : {
     405             :     struct tm tm1, tm2, o1;
     406             :     int off_day, off_sec;
     407             :     long toffset;
     408             :     time_t t1, t2;
     409             :     time(&t1);
     410             :     t2 = t1 + offset;
     411             :     OPENSSL_gmtime(&t2, &tm2);
     412             :     OPENSSL_gmtime(&t1, &tm1);
     413             :     o1 = tm1;
     414             :     OPENSSL_gmtime_adj(&tm1, 0, offset);
     415             :     if ((tm1.tm_year != tm2.tm_year) ||
     416             :         (tm1.tm_mon != tm2.tm_mon) ||
     417             :         (tm1.tm_mday != tm2.tm_mday) ||
     418             :         (tm1.tm_hour != tm2.tm_hour) ||
     419             :         (tm1.tm_min != tm2.tm_min) || (tm1.tm_sec != tm2.tm_sec)) {
     420             :         fprintf(stderr, "TIME ERROR!!\n");
     421             :         fprintf(stderr, "Time1: %d/%d/%d, %d:%02d:%02d\n",
     422             :                 tm2.tm_mday, tm2.tm_mon + 1, tm2.tm_year + 1900,
     423             :                 tm2.tm_hour, tm2.tm_min, tm2.tm_sec);
     424             :         fprintf(stderr, "Time2: %d/%d/%d, %d:%02d:%02d\n",
     425             :                 tm1.tm_mday, tm1.tm_mon + 1, tm1.tm_year + 1900,
     426             :                 tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
     427             :         return 0;
     428             :     }
     429             :     OPENSSL_gmtime_diff(&o1, &tm1, &off_day, &off_sec);
     430             :     toffset = (long)off_day *SECS_PER_DAY + off_sec;
     431             :     if (offset != toffset) {
     432             :         fprintf(stderr, "TIME OFFSET ERROR!!\n");
     433             :         fprintf(stderr, "Expected %ld, Got %ld (%d:%d)\n",
     434             :                 offset, toffset, off_day, off_sec);
     435             :         return 0;
     436             :     }
     437             :     return 1;
     438             : }
     439             : 
     440             : #endif

Generated by: LCOV version 1.10