OLD | NEW |
1 /* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */ | 1 /* crypto/o_time.c -*- mode:C; c-file-style: "eay" -*- */ |
2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL | 2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL |
3 * project 2001. | 3 * project 2001. |
4 */ | 4 */ |
| 5 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
| 6 * project 2008. |
| 7 */ |
5 /* ==================================================================== | 8 /* ==================================================================== |
6 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. | 9 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. |
7 * | 10 * |
8 * Redistribution and use in source and binary forms, with or without | 11 * Redistribution and use in source and binary forms, with or without |
9 * modification, are permitted provided that the following conditions | 12 * modification, are permitted provided that the following conditions |
10 * are met: | 13 * are met: |
11 * | 14 * |
12 * 1. Redistributions of source code must retain the above copyright | 15 * 1. Redistributions of source code must retain the above copyright |
13 * notice, this list of conditions and the following disclaimer. | 16 * notice, this list of conditions and the following disclaimer. |
14 * | 17 * |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 * (eay@cryptsoft.com). This product includes software written by Tim | 57 * (eay@cryptsoft.com). This product includes software written by Tim |
55 * Hudson (tjh@cryptsoft.com). | 58 * Hudson (tjh@cryptsoft.com). |
56 * | 59 * |
57 */ | 60 */ |
58 | 61 |
59 #include <openssl/e_os2.h> | 62 #include <openssl/e_os2.h> |
60 #include <string.h> | 63 #include <string.h> |
61 #include "o_time.h" | 64 #include "o_time.h" |
62 | 65 |
63 #ifdef OPENSSL_SYS_VMS | 66 #ifdef OPENSSL_SYS_VMS |
64 # include <libdtdef.h> | 67 # if __CRTL_VER >= 70000000 && \ |
65 # include <lib$routines.h> | 68 (defined _POSIX_C_SOURCE || !defined _ANSI_C_SOURCE) |
66 # include <lnmdef.h> | 69 # define VMS_GMTIME_OK |
67 # include <starlet.h> | 70 # endif |
68 # include <descrip.h> | 71 # ifndef VMS_GMTIME_OK |
69 # include <stdlib.h> | 72 # include <libdtdef.h> |
| 73 # include <lib$routines.h> |
| 74 # include <lnmdef.h> |
| 75 # include <starlet.h> |
| 76 # include <descrip.h> |
| 77 # include <stdlib.h> |
| 78 # endif /* ndef VMS_GMTIME_OK */ |
70 #endif | 79 #endif |
71 | 80 |
72 struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) | 81 struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result) |
73 { | 82 { |
74 struct tm *ts = NULL; | 83 struct tm *ts = NULL; |
75 | 84 |
76 #if defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_
SYS_OS2) && !defined(__CYGWIN32__) && (!defined(OPENSSL_SYS_VMS) || defined(gmti
me_r)) && !defined(OPENSSL_SYS_MACOSX) && !defined(OPENSSL_SYS_SUNOS) | 85 #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) |
77 /* should return &data, but doesn't on some systems, | 86 /* should return &data, but doesn't on some systems, |
78 so we don't even look at the return value */ | 87 so we don't even look at the return value */ |
79 gmtime_r(timer,result); | 88 gmtime_r(timer,result); |
80 ts = result; | 89 ts = result; |
81 #elif !defined(OPENSSL_SYS_VMS) | 90 #elif !defined(OPENSSL_SYS_VMS) || defined(VMS_GMTIME_OK) |
82 ts = gmtime(timer); | 91 ts = gmtime(timer); |
83 if (ts == NULL) | 92 if (ts == NULL) |
84 return NULL; | 93 return NULL; |
85 | 94 |
86 memcpy(result, ts, sizeof(struct tm)); | 95 memcpy(result, ts, sizeof(struct tm)); |
87 ts = result; | 96 ts = result; |
88 #endif | 97 #endif |
89 #ifdef OPENSSL_SYS_VMS | 98 #if defined( OPENSSL_SYS_VMS) && !defined( VMS_GMTIME_OK) |
90 if (ts == NULL) | 99 if (ts == NULL) |
91 { | 100 { |
92 static $DESCRIPTOR(tabnam,"LNM$DCL_LOGICAL"); | 101 static $DESCRIPTOR(tabnam,"LNM$DCL_LOGICAL"); |
93 static $DESCRIPTOR(lognam,"SYS$TIMEZONE_DIFFERENTIAL"); | 102 static $DESCRIPTOR(lognam,"SYS$TIMEZONE_DIFFERENTIAL"); |
94 char logvalue[256]; | 103 char logvalue[256]; |
95 unsigned int reslen = 0; | 104 unsigned int reslen = 0; |
96 struct { | 105 struct { |
97 short buflen; | 106 short buflen; |
98 short code; | 107 short code; |
99 void *bufaddr; | 108 void *bufaddr; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 &result->tm_yday, systime); | 216 &result->tm_yday, systime); |
208 result->tm_yday--; | 217 result->tm_yday--; |
209 | 218 |
210 result->tm_isdst = 0; /* There's no way to know... */ | 219 result->tm_isdst = 0; /* There's no way to know... */ |
211 | 220 |
212 ts = result; | 221 ts = result; |
213 } | 222 } |
214 } | 223 } |
215 #endif | 224 #endif |
216 return ts; | 225 return ts; |
217 » }» | 226 » } |
| 227 |
| 228 /* Take a tm structure and add an offset to it. This avoids any OS issues |
| 229 * with restricted date types and overflows which cause the year 2038 |
| 230 * problem. |
| 231 */ |
| 232 |
| 233 #define SECS_PER_DAY (24 * 60 * 60) |
| 234 |
| 235 static long date_to_julian(int y, int m, int d); |
| 236 static void julian_to_date(long jd, int *y, int *m, int *d); |
| 237 |
| 238 int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) |
| 239 » { |
| 240 » int offset_hms, offset_day; |
| 241 » long time_jd; |
| 242 » int time_year, time_month, time_day; |
| 243 » /* split offset into days and day seconds */ |
| 244 » offset_day = offset_sec / SECS_PER_DAY; |
| 245 » /* Avoid sign issues with % operator */ |
| 246 » offset_hms = offset_sec - (offset_day * SECS_PER_DAY); |
| 247 » offset_day += off_day; |
| 248 » /* Add current time seconds to offset */ |
| 249 » offset_hms += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; |
| 250 » /* Adjust day seconds if overflow */ |
| 251 » if (offset_hms >= SECS_PER_DAY) |
| 252 » » { |
| 253 » » offset_day++; |
| 254 » » offset_hms -= SECS_PER_DAY; |
| 255 » » } |
| 256 » else if (offset_hms < 0) |
| 257 » » { |
| 258 » » offset_day--; |
| 259 » » offset_hms += SECS_PER_DAY; |
| 260 » » } |
| 261 |
| 262 » /* Convert date of time structure into a Julian day number. |
| 263 » */ |
| 264 |
| 265 » time_year = tm->tm_year + 1900; |
| 266 » time_month = tm->tm_mon + 1; |
| 267 » time_day = tm->tm_mday; |
| 268 |
| 269 » time_jd = date_to_julian(time_year, time_month, time_day); |
| 270 |
| 271 » /* Work out Julian day of new date */ |
| 272 » time_jd += offset_day; |
| 273 |
| 274 » if (time_jd < 0) |
| 275 » » return 0; |
| 276 |
| 277 » /* Convert Julian day back to date */ |
| 278 |
| 279 » julian_to_date(time_jd, &time_year, &time_month, &time_day); |
| 280 |
| 281 » if (time_year < 1900 || time_year > 9999) |
| 282 » » return 0; |
| 283 |
| 284 » /* Update tm structure */ |
| 285 |
| 286 » tm->tm_year = time_year - 1900; |
| 287 » tm->tm_mon = time_month - 1; |
| 288 » tm->tm_mday = time_day; |
| 289 |
| 290 » tm->tm_hour = offset_hms / 3600; |
| 291 » tm->tm_min = (offset_hms / 60) % 60; |
| 292 » tm->tm_sec = offset_hms % 60; |
| 293 |
| 294 » return 1; |
| 295 » » |
| 296 } |
| 297 |
| 298 /* Convert date to and from julian day |
| 299 * Uses Fliegel & Van Flandern algorithm |
| 300 */ |
| 301 static long date_to_julian(int y, int m, int d) |
| 302 { |
| 303 » return (1461 * (y + 4800 + (m - 14) / 12)) / 4 + |
| 304 » » (367 * (m - 2 - 12 * ((m - 14) / 12))) / 12 - |
| 305 » » (3 * ((y + 4900 + (m - 14) / 12) / 100)) / 4 + |
| 306 » » d - 32075; |
| 307 } |
| 308 |
| 309 static void julian_to_date(long jd, int *y, int *m, int *d) |
| 310 » { |
| 311 » long L = jd + 68569; |
| 312 » long n = (4 * L) / 146097; |
| 313 » long i, j; |
| 314 |
| 315 » L = L - (146097 * n + 3) / 4; |
| 316 » i = (4000 * (L + 1)) / 1461001; |
| 317 » L = L - (1461 * i) / 4 + 31; |
| 318 » j = (80 * L) / 2447; |
| 319 » *d = L - (2447 * j) / 80; |
| 320 » L = j / 11; |
| 321 » *m = j + 2 - (12 * L); |
| 322 » *y = 100 * (n - 49) + i + L; |
| 323 » } |
| 324 |
| 325 #ifdef OPENSSL_TIME_TEST |
| 326 |
| 327 #include <stdio.h> |
| 328 |
| 329 /* Time checking test code. Check times are identical for a wide range of |
| 330 * offsets. This should be run on a machine with 64 bit time_t or it will |
| 331 * trigger the very errors the routines fix. |
| 332 */ |
| 333 |
| 334 int main(int argc, char **argv) |
| 335 » { |
| 336 » long offset; |
| 337 » for (offset = 0; offset < 1000000; offset++) |
| 338 » » { |
| 339 » » check_time(offset); |
| 340 » » check_time(-offset); |
| 341 » » check_time(offset * 1000); |
| 342 » » check_time(-offset * 1000); |
| 343 » » } |
| 344 » } |
| 345 |
| 346 int check_time(long offset) |
| 347 » { |
| 348 » struct tm tm1, tm2; |
| 349 » time_t t1, t2; |
| 350 » time(&t1); |
| 351 » t2 = t1 + offset; |
| 352 » OPENSSL_gmtime(&t2, &tm2); |
| 353 » OPENSSL_gmtime(&t1, &tm1); |
| 354 » OPENSSL_gmtime_adj(&tm1, 0, offset); |
| 355 » if ((tm1.tm_year == tm2.tm_year) && |
| 356 » (tm1.tm_mon == tm2.tm_mon) && |
| 357 » (tm1.tm_mday == tm2.tm_mday) && |
| 358 » (tm1.tm_hour == tm2.tm_hour) && |
| 359 » (tm1.tm_min == tm2.tm_min) && |
| 360 » (tm1.tm_sec == tm2.tm_sec)) |
| 361 » » return 1; |
| 362 » fprintf(stderr, "TIME ERROR!!\n"); |
| 363 » fprintf(stderr, "Time1: %d/%d/%d, %d:%02d:%02d\n", |
| 364 » » » tm2.tm_mday, tm2.tm_mon + 1, tm2.tm_year + 1900, |
| 365 » » » tm2.tm_hour, tm2.tm_min, tm2.tm_sec); |
| 366 » fprintf(stderr, "Time2: %d/%d/%d, %d:%02d:%02d\n", |
| 367 » » » tm1.tm_mday, tm1.tm_mon + 1, tm1.tm_year + 1900, |
| 368 » » » tm1.tm_hour, tm1.tm_min, tm1.tm_sec); |
| 369 » return 0; |
| 370 » } |
| 371 |
| 372 #endif |
OLD | NEW |