1109998Smarkm/* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */ 2296465Sdelphij/* 3296465Sdelphij * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project 4296465Sdelphij * 2001. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <openssl/e_os2.h> 61109998Smarkm#include <string.h> 62109998Smarkm#include "o_time.h" 63109998Smarkm 64109998Smarkm#ifdef OPENSSL_SYS_VMS 65109998Smarkm# include <libdtdef.h> 66109998Smarkm# include <lib$routines.h> 67109998Smarkm# include <lnmdef.h> 68109998Smarkm# include <starlet.h> 69109998Smarkm# include <descrip.h> 70109998Smarkm# include <stdlib.h> 71109998Smarkm#endif 72109998Smarkm 73109998Smarkmstruct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) 74296465Sdelphij{ 75296465Sdelphij struct tm *ts = NULL; 76109998Smarkm 77120631Snectar#if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_OS2) && !defined(__CYGWIN32__) && (!defined(OPENSSL_SYS_VMS) || defined(gmtime_r)) && !defined(OPENSSL_SYS_MACOSX) && !defined(OPENSSL_SYS_SUNOS) 78296465Sdelphij /* 79296465Sdelphij * should return &data, but doesn't on some systems, so we don't even 80296465Sdelphij * look at the return value 81296465Sdelphij */ 82296465Sdelphij gmtime_r(timer, result); 83296465Sdelphij ts = result; 84109998Smarkm#elif !defined(OPENSSL_SYS_VMS) 85296465Sdelphij ts = gmtime(timer); 86296465Sdelphij if (ts == NULL) 87296465Sdelphij return NULL; 88120631Snectar 89296465Sdelphij memcpy(result, ts, sizeof(struct tm)); 90296465Sdelphij ts = result; 91109998Smarkm#endif 92109998Smarkm#ifdef OPENSSL_SYS_VMS 93296465Sdelphij if (ts == NULL) { 94296465Sdelphij static $DESCRIPTOR(tabnam, "LNM$DCL_LOGICAL"); 95296465Sdelphij static $DESCRIPTOR(lognam, "SYS$TIMEZONE_DIFFERENTIAL"); 96296465Sdelphij char logvalue[256]; 97296465Sdelphij unsigned int reslen = 0; 98296465Sdelphij struct { 99296465Sdelphij short buflen; 100296465Sdelphij short code; 101296465Sdelphij void *bufaddr; 102296465Sdelphij unsigned int *reslen; 103296465Sdelphij } itemlist[] = { 104296465Sdelphij { 105296465Sdelphij 0, LNM$_STRING, 0, 0 106296465Sdelphij }, 107296465Sdelphij { 108296465Sdelphij 0, 0, 0, 0 109296465Sdelphij }, 110296465Sdelphij }; 111296465Sdelphij int status; 112296465Sdelphij time_t t; 113109998Smarkm 114296465Sdelphij /* Get the value for SYS$TIMEZONE_DIFFERENTIAL */ 115296465Sdelphij itemlist[0].buflen = sizeof(logvalue); 116296465Sdelphij itemlist[0].bufaddr = logvalue; 117296465Sdelphij itemlist[0].reslen = &reslen; 118296465Sdelphij status = sys$trnlnm(0, &tabnam, &lognam, 0, itemlist); 119296465Sdelphij if (!(status & 1)) 120296465Sdelphij return NULL; 121296465Sdelphij logvalue[reslen] = '\0'; 122109998Smarkm 123296465Sdelphij t = *timer; 124142425Snectar 125142425Snectar/* The following is extracted from the DEC C header time.h */ 126296465Sdelphij /* 127296465Sdelphij ** Beginning in OpenVMS Version 7.0 mktime, time, ctime, strftime 128296465Sdelphij ** have two implementations. One implementation is provided 129296465Sdelphij ** for compatibility and deals with time in terms of local time, 130296465Sdelphij ** the other __utc_* deals with time in terms of UTC. 131296465Sdelphij */ 132296465Sdelphij /* 133296465Sdelphij * We use the same conditions as in said time.h to check if we should 134296465Sdelphij * assume that t contains local time (and should therefore be 135296465Sdelphij * adjusted) or UTC (and should therefore be left untouched). 136296465Sdelphij */ 137296465Sdelphij# if __CRTL_VER < 70000000 || defined _VMS_V6_SOURCE 138296465Sdelphij /* Get the numerical value of the equivalence string */ 139296465Sdelphij status = atoi(logvalue); 140109998Smarkm 141296465Sdelphij /* and use it to move time to GMT */ 142296465Sdelphij t -= status; 143296465Sdelphij# endif 144109998Smarkm 145296465Sdelphij /* then convert the result to the time structure */ 146142425Snectar 147296465Sdelphij /* 148296465Sdelphij * Since there was no gmtime_r() to do this stuff for us, we have to 149296465Sdelphij * do it the hard way. 150296465Sdelphij */ 151296465Sdelphij { 152296465Sdelphij /*- 153296465Sdelphij * The VMS epoch is the astronomical Smithsonian date, 154296465Sdelphij if I remember correctly, which is November 17, 1858. 155296465Sdelphij Furthermore, time is measure in thenths of microseconds 156296465Sdelphij and stored in quadwords (64 bit integers). unix_epoch 157296465Sdelphij below is January 1st 1970 expressed as a VMS time. The 158296465Sdelphij following code was used to get this number: 159109998Smarkm 160296465Sdelphij #include <stdio.h> 161296465Sdelphij #include <stdlib.h> 162296465Sdelphij #include <lib$routines.h> 163296465Sdelphij #include <starlet.h> 164109998Smarkm 165296465Sdelphij main() 166296465Sdelphij { 167296465Sdelphij unsigned long systime[2]; 168296465Sdelphij unsigned short epoch_values[7] = 169296465Sdelphij { 1970, 1, 1, 0, 0, 0, 0 }; 170109998Smarkm 171296465Sdelphij lib$cvt_vectim(epoch_values, systime); 172109998Smarkm 173296465Sdelphij printf("%u %u", systime[0], systime[1]); 174296465Sdelphij } 175296465Sdelphij */ 176296465Sdelphij unsigned long unix_epoch[2] = { 1273708544, 8164711 }; 177296465Sdelphij unsigned long deltatime[2]; 178296465Sdelphij unsigned long systime[2]; 179296465Sdelphij struct vms_vectime { 180296465Sdelphij short year, month, day, hour, minute, second, centi_second; 181296465Sdelphij } time_values; 182296465Sdelphij long operation; 183109998Smarkm 184296465Sdelphij /* 185296465Sdelphij * Turn the number of seconds since January 1st 1970 to an 186296465Sdelphij * internal delta time. Note that lib$cvt_to_internal_time() will 187296465Sdelphij * assume that t is signed, and will therefore break on 32-bit 188296465Sdelphij * systems some time in 2038. 189296465Sdelphij */ 190296465Sdelphij operation = LIB$K_DELTA_SECONDS; 191296465Sdelphij status = lib$cvt_to_internal_time(&operation, &t, deltatime); 192109998Smarkm 193296465Sdelphij /* 194296465Sdelphij * Add the delta time with the Unix epoch and we have the current 195296465Sdelphij * UTC time in internal format 196296465Sdelphij */ 197296465Sdelphij status = lib$add_times(unix_epoch, deltatime, systime); 198109998Smarkm 199296465Sdelphij /* Turn the internal time into a time vector */ 200296465Sdelphij status = sys$numtim(&time_values, systime); 201109998Smarkm 202296465Sdelphij /* Fill in the struct tm with the result */ 203296465Sdelphij result->tm_sec = time_values.second; 204296465Sdelphij result->tm_min = time_values.minute; 205296465Sdelphij result->tm_hour = time_values.hour; 206296465Sdelphij result->tm_mday = time_values.day; 207296465Sdelphij result->tm_mon = time_values.month - 1; 208296465Sdelphij result->tm_year = time_values.year - 1900; 209109998Smarkm 210296465Sdelphij operation = LIB$K_DAY_OF_WEEK; 211296465Sdelphij status = lib$cvt_from_internal_time(&operation, 212296465Sdelphij &result->tm_wday, systime); 213296465Sdelphij result->tm_wday %= 7; 214109998Smarkm 215296465Sdelphij operation = LIB$K_DAY_OF_YEAR; 216296465Sdelphij status = lib$cvt_from_internal_time(&operation, 217296465Sdelphij &result->tm_yday, systime); 218296465Sdelphij result->tm_yday--; 219109998Smarkm 220296465Sdelphij result->tm_isdst = 0; /* There's no way to know... */ 221109998Smarkm 222296465Sdelphij ts = result; 223296465Sdelphij } 224296465Sdelphij } 225109998Smarkm#endif 226296465Sdelphij return ts; 227296465Sdelphij} 228