1 1.5 christos /* $NetBSD: check_y2k.c,v 1.5 2020/05/25 20:47:25 christos Exp $ */ 2 1.1 kardel 3 1.1 kardel /* check_y2k.c -- test ntp code constructs for Y2K correctness Y2KFixes [*/ 4 1.1 kardel 5 1.1 kardel /* 6 1.1 kardel Code invoked by `make check`. Not part of ntpd and not to be 7 1.1 kardel installed. 8 1.1 kardel 9 1.1 kardel On any code I even wonder about, I've cut and pasted the code 10 1.1 kardel here and ran it as a test case just to be sure. 11 1.1 kardel 12 1.1 kardel For code not in "ntpd" proper, we have tried to call most 13 1.1 kardel repaired functions from herein to properly test them 14 1.1 kardel (something never done before!). This has found several bugs, 15 1.1 kardel not normal Y2K bugs, that will strike in Y2K so repair them 16 1.1 kardel we did. 17 1.1 kardel 18 1.1 kardel Program exits with 0 on success, 1 on Y2K failure (stdout messages). 19 1.1 kardel Exit of 2 indicates internal logic bug detected OR failure of 20 1.1 kardel what should be our correct formulas. 21 1.1 kardel 22 1.1 kardel While "make check" should only check logic for source within that 23 1.1 kardel specific directory, this check goes outside the scope of the local 24 1.1 kardel directory. It's not a perfect world (besides, there is a lot of 25 1.1 kardel interdependence here, and it really needs to be tested in 26 1.1 kardel a controled order). 27 1.1 kardel */ 28 1.1 kardel 29 1.1 kardel /* { definitions lifted from ntpd.c to allow us to complie with 30 1.1 kardel "#include ntp.h". I have not taken the time to reduce the clutter. */ 31 1.1 kardel 32 1.1 kardel #ifdef HAVE_CONFIG_H 33 1.1 kardel # include <config.h> 34 1.1 kardel #endif 35 1.1 kardel 36 1.1 kardel #include "ntpd.h" 37 1.1 kardel 38 1.1 kardel #ifdef HAVE_UNISTD_H 39 1.1 kardel # include <unistd.h> 40 1.1 kardel #endif 41 1.1 kardel #ifdef HAVE_SYS_STAT_H 42 1.1 kardel # include <sys/stat.h> 43 1.1 kardel #endif 44 1.1 kardel #include <stdio.h> 45 1.1 kardel #include <errno.h> 46 1.1 kardel #ifndef SYS_WINNT 47 1.1 kardel # if !defined(VMS) /*wjm*/ 48 1.1 kardel # include <sys/param.h> 49 1.1 kardel # endif /* VMS */ 50 1.1 kardel # if HAVE_SYS_SIGNAL_H 51 1.1 kardel # include <sys/signal.h> 52 1.1 kardel # endif /* HAVE_SYS_SIGNAL_H */ 53 1.1 kardel # include <sys/signal.h> 54 1.1 kardel # ifdef HAVE_SYS_IOCTL_H 55 1.1 kardel # include <sys/ioctl.h> 56 1.1 kardel # endif /* HAVE_SYS_IOCTL_H */ 57 1.1 kardel # if !defined(VMS) /*wjm*/ 58 1.1 kardel # include <sys/resource.h> 59 1.1 kardel # endif /* VMS */ 60 1.1 kardel #else 61 1.1 kardel # include <signal.h> 62 1.1 kardel # include <process.h> 63 1.1 kardel # include <io.h> 64 1.1 kardel # include "../libntp/log.h" 65 1.1 kardel #endif /* SYS_WINNT */ 66 1.1 kardel #if defined(HAVE_RTPRIO) 67 1.1 kardel # ifdef HAVE_SYS_RESOURCE_H 68 1.1 kardel # include <sys/resource.h> 69 1.1 kardel # endif 70 1.1 kardel # ifdef HAVE_SYS_LOCK_H 71 1.1 kardel # include <sys/lock.h> 72 1.1 kardel # endif 73 1.1 kardel # include <sys/rtprio.h> 74 1.1 kardel #else 75 1.1 kardel # ifdef HAVE_PLOCK 76 1.1 kardel # ifdef HAVE_SYS_LOCK_H 77 1.1 kardel # include <sys/lock.h> 78 1.1 kardel # endif 79 1.1 kardel # endif 80 1.1 kardel #endif 81 1.1 kardel #if defined(HAVE_SCHED_SETSCHEDULER) 82 1.1 kardel # ifdef HAVE_SCHED_H 83 1.1 kardel # include <sched.h> 84 1.1 kardel # else 85 1.1 kardel # ifdef HAVE_SYS_SCHED_H 86 1.1 kardel # include <sys/sched.h> 87 1.1 kardel # endif 88 1.1 kardel # endif 89 1.1 kardel #endif 90 1.1 kardel #if defined(HAVE_SYS_MMAN_H) 91 1.1 kardel # include <sys/mman.h> 92 1.1 kardel #endif 93 1.1 kardel 94 1.1 kardel #ifdef HAVE_TERMIOS_H 95 1.1 kardel # include <termios.h> 96 1.1 kardel #endif 97 1.1 kardel 98 1.1 kardel #ifdef SYS_DOMAINOS 99 1.1 kardel # include <apollo/base.h> 100 1.1 kardel #endif /* SYS_DOMAINOS */ 101 1.1 kardel 102 1.1 kardel /* } end definitions lifted from ntpd.c */ 103 1.1 kardel 104 1.1 kardel #include "ntp_calendar.h" 105 1.1 kardel #include "parse.h" 106 1.1 kardel 107 1.1 kardel #define GoodLeap(Year) (((Year)%4 || (!((Year)%100) && (Year)%400)) ? 0 : 13 ) 108 1.1 kardel 109 1.1 kardel char const *progname = "check_y2k"; 110 1.1 kardel 111 1.1 kardel long 112 1.1 kardel Days ( int Year ) /* return number of days since year "0" */ 113 1.1 kardel { 114 1.1 kardel long Return; 115 1.1 kardel /* this is a known to be good algorithm */ 116 1.1 kardel Return = Year * 365; /* first aproximation to the value */ 117 1.1 kardel if ( Year >= 1 ) 118 1.1 kardel { /* see notes in libparse/parse.c if you want a PROPER 119 1.1 kardel * **generic algorithm. */ 120 1.1 kardel Return += (Year+3) / 4; /* add in (too many) leap days */ 121 1.1 kardel Return -= (Year-1) / 100; /* reduce by (too many) centurys */ 122 1.1 kardel Return += (Year-1) / 400; /* get final answer */ 123 1.1 kardel } 124 1.1 kardel 125 1.1 kardel return Return; 126 1.1 kardel } 127 1.1 kardel 128 1.1 kardel static int year0 = 1900; /* sarting year for NTP time */ 129 1.1 kardel static int yearend; /* ending year we test for NTP time. 130 1.1 kardel * 32-bit systems: through 2036, the 131 1.1 kardel **year in which NTP time overflows. 132 1.1 kardel * 64-bit systems: a reasonable upper 133 1.1 kardel **limit (well, maybe somewhat beyond 134 1.1 kardel **reasonable, but well before the 135 1.1 kardel **max time, by which time the earth 136 1.1 kardel **will be dead.) */ 137 1.1 kardel static time_t Time; 138 1.1 kardel static struct tm LocalTime; 139 1.1 kardel 140 1.1 kardel #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \ 141 1.1 kardel Warnings++; else Fatals++ 142 1.1 kardel 143 1.1 kardel int 144 1.1 kardel main( void ) 145 1.1 kardel { 146 1.1 kardel int Fatals; 147 1.1 kardel int Warnings; 148 1.1 kardel int year; 149 1.1 kardel 150 1.1 kardel Time = time( (time_t *)NULL ) 151 1.1 kardel #ifdef TESTTIMEOFFSET 152 1.1 kardel + test_time_offset 153 1.1 kardel #endif 154 1.1 kardel ; 155 1.1 kardel LocalTime = *localtime( &Time ); 156 1.1 kardel 157 1.1 kardel year = ( sizeof( u_long ) > 4 ) /* save max span using year as temp */ 158 1.1 kardel ? ( 400 * 3 ) /* three greater gregorian cycles */ 159 1.1 kardel : ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/ 160 1.1 kardel /* NOTE: will automacially expand test years on 161 1.1 kardel * 64 bit machines.... this may cause some of the 162 1.1 kardel * existing ntp logic to fail for years beyond 163 1.1 kardel * 2036 (the current 32-bit limit). If all checks 164 1.1 kardel * fail ONLY beyond year 2036 you may ignore such 165 1.1 kardel * errors, at least for a decade or so. */ 166 1.1 kardel yearend = year0 + year; 167 1.1 kardel 168 1.1 kardel puts( " internal self check" ); 169 1.1 kardel { /* verify our own logic used to verify repairs */ 170 1.1 kardel unsigned long days; 171 1.1 kardel 172 1.1 kardel if ( year0 >= yearend ) 173 1.1 kardel { 174 1.1 kardel fprintf( stdout, "year0=%d NOT LESS THAN yearend=%d (span=%d)\n", 175 1.1 kardel (int)year0, (int)yearend, (int)year ); 176 1.1 kardel exit(2); 177 1.1 kardel } 178 1.1 kardel 179 1.1 kardel { 180 1.1 kardel int save_year; 181 1.1 kardel 182 1.1 kardel save_year = LocalTime.tm_year; /* save current year */ 183 1.1 kardel 184 1.1 kardel year = 1980; 185 1.1 kardel LocalTime.tm_year = year - 1900; 186 1.1 kardel Fatals = Warnings = 0; 187 1.1 kardel Error(year); /* should increment Fatals */ 188 1.1 kardel if ( Fatals == 0 ) 189 1.1 kardel { 190 1.1 kardel fprintf( stdout, 191 1.1 kardel "%4d: %s(%d): FATAL DID NOT INCREMENT (Fatals=%d Warnings=%d)\n", 192 1.1 kardel (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings ); 193 1.1 kardel exit(2); 194 1.1 kardel } 195 1.1 kardel 196 1.1 kardel year = 2100; /* test year > limit but CURRENT year < limit */ 197 1.1 kardel Fatals = Warnings = 0; 198 1.1 kardel Error(year); /* should increment Fatals */ 199 1.1 kardel if ( Warnings == 0 ) 200 1.1 kardel { 201 1.1 kardel fprintf( stdout, 202 1.1 kardel "%4d: %s(%d): WARNING DID NOT INCREMENT (Fatals=%d Warnings=%d)\n", 203 1.1 kardel (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings ); 204 1.1 kardel exit(2); 205 1.1 kardel } 206 1.1 kardel Fatals = Warnings = 0; 207 1.1 kardel LocalTime.tm_year = year - 1900; /* everything > limit */ 208 1.1 kardel Error(1980); /* should increment Fatals */ 209 1.1 kardel if ( Fatals == 0 ) 210 1.1 kardel { 211 1.1 kardel fprintf( stdout, 212 1.1 kardel "%4d: %s(%d): FATALS DID NOT INCREMENT (Fatals=%d Warnings=%d)\n", 213 1.1 kardel (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings ); 214 1.1 kardel exit(2); 215 1.1 kardel } 216 1.1 kardel 217 1.1 kardel LocalTime.tm_year = save_year; 218 1.1 kardel } 219 1.1 kardel 220 1.1 kardel days = 365+1; /* days in year 0 + 1 more day */ 221 1.1 kardel for ( year = 1; year <= 2500; year++ ) 222 1.1 kardel { 223 1.1 kardel long Test; 224 1.1 kardel Test = Days( year ); 225 1.1 kardel if ( days != Test ) 226 1.1 kardel { 227 1.1 kardel fprintf( stdout, "%04d: Days() DAY COUNT ERROR: s/b=%ld was=%ld\n", 228 1.1 kardel year, (long)days, (long)Test ); 229 1.1 kardel exit(2); /* would throw off many other tests */ 230 1.1 kardel } 231 1.1 kardel 232 1.1 kardel Test = julian0(year); /* compare with julian0() macro */ 233 1.1 kardel if ( days != Test ) 234 1.1 kardel { 235 1.1 kardel fprintf( stdout, "%04d: julian0() DAY COUNT ERROR: s/b=%ld was=%ld\n", 236 1.1 kardel year, (long)days, (long)Test ); 237 1.1 kardel exit(2); /* would throw off many other tests */ 238 1.1 kardel } 239 1.1 kardel 240 1.1 kardel days += 365; 241 1.1 kardel if ( isleap_4(year) ) days++; 242 1.1 kardel } 243 1.1 kardel 244 1.1 kardel if ( isleap_4(1999) ) 245 1.1 kardel { 246 1.1 kardel fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" ); 247 1.1 kardel exit(2); 248 1.1 kardel } 249 1.1 kardel if ( !isleap_4(2000) ) 250 1.1 kardel { 251 1.1 kardel fprintf( stdout, "isleap_4(2000) REPORTED FALSE\n" ); 252 1.1 kardel exit(2); 253 1.1 kardel } 254 1.1 kardel if ( isleap_4(2001) ) 255 1.1 kardel { 256 1.1 kardel fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" ); 257 1.1 kardel exit(2); 258 1.1 kardel } 259 1.1 kardel 260 1.1 kardel if ( !isleap_tm(2000-1900) ) 261 1.1 kardel { 262 1.1 kardel fprintf( stdout, "isleap_tm(100) REPORTED FALSE\n" ); 263 1.1 kardel exit(2); 264 1.1 kardel } 265 1.1 kardel } 266 1.1 kardel 267 1.1 kardel Fatals = Warnings = 0; 268 1.1 kardel 269 1.1 kardel puts( " include/ntp.h" ); 270 1.1 kardel { /* test our new isleap_*() #define "functions" */ 271 1.1 kardel 272 1.1 kardel for ( year = 1400; year <= 2200; year++ ) 273 1.1 kardel { 274 1.1 kardel int LeapSw; 275 1.1 kardel int IsLeapSw; 276 1.1 kardel 277 1.1 kardel LeapSw = GoodLeap(year); 278 1.1 kardel IsLeapSw = isleap_4(year); 279 1.1 kardel 280 1.1 kardel if ( !!LeapSw != !!IsLeapSw ) 281 1.1 kardel { 282 1.1 kardel Error(year); 283 1.1 kardel fprintf( stdout, 284 1.1 kardel " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw ); 285 1.1 kardel break; 286 1.1 kardel } 287 1.1 kardel 288 1.1 kardel IsLeapSw = isleap_tm(year-1900); 289 1.1 kardel 290 1.1 kardel if ( !!LeapSw != !!IsLeapSw ) 291 1.1 kardel { 292 1.1 kardel Error(year); 293 1.1 kardel fprintf( stdout, 294 1.1 kardel " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw ); 295 1.1 kardel break; 296 1.1 kardel } 297 1.1 kardel } 298 1.1 kardel } 299 1.1 kardel 300 1.1 kardel puts( " include/ntp_calendar.h" ); 301 1.1 kardel { /* I belive this is good, but just to be sure... */ 302 1.1 kardel 303 1.1 kardel /* we are testing this #define */ 304 1.1 kardel #define is_leapyear(y) (y%4 == 0 && !(y%100 == 0 && !(y%400 == 0))) 305 1.1 kardel 306 1.1 kardel for ( year = 1400; year <= 2200; year++ ) 307 1.1 kardel { 308 1.1 kardel int LeapSw; 309 1.1 kardel 310 1.1 kardel LeapSw = GoodLeap(year); 311 1.1 kardel 312 1.1 kardel if ( !(!LeapSw) != !(!is_leapyear(year)) ) 313 1.1 kardel { 314 1.1 kardel Error(year); 315 1.1 kardel fprintf( stdout, 316 1.1 kardel " %4d %2d *** ERROR\n", year, LeapSw ); 317 1.1 kardel break; 318 1.1 kardel } 319 1.1 kardel } 320 1.1 kardel } 321 1.1 kardel 322 1.1 kardel 323 1.1 kardel puts( " libparse/parse.c" ); 324 1.1 kardel { 325 1.1 kardel long Days1970; /* days from 1900 to 1970 */ 326 1.1 kardel 327 1.1 kardel struct ParseTime /* womp up a test structure to all cut/paste code */ 328 1.1 kardel { 329 1.1 kardel int year; 330 1.1 kardel } Clock_Time, *clock_time; 331 1.1 kardel 332 1.1 kardel clock_time = &Clock_Time; 333 1.1 kardel 334 1.1 kardel /* first test this #define */ 335 1.1 kardel #define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366)) 336 1.1 kardel 337 1.1 kardel for ( year = 1400; year <= 2200; year++ ) 338 1.1 kardel { 339 1.1 kardel int LeapSw; 340 1.1 kardel int DayCnt; 341 1.1 kardel 342 1.1 kardel LeapSw = GoodLeap(year); 343 1.1 kardel DayCnt = (int)days_per_year(year); 344 1.1 kardel 345 1.1 kardel if ( ( LeapSw ? 366 : 365 ) != DayCnt ) 346 1.1 kardel { 347 1.1 kardel Error(year); 348 1.1 kardel fprintf( stdout, 349 1.1 kardel " days_per_year() %4d %2d %3d *** ERROR\n", 350 1.1 kardel year, LeapSw, DayCnt ); 351 1.1 kardel break; 352 1.1 kardel } 353 1.1 kardel } 354 1.1 kardel 355 1.1 kardel /* test (what is now julian0) calculations */ 356 1.1 kardel 357 1.1 kardel Days1970 = Days( 1970 ); /* get days since 1970 using a known good */ 358 1.1 kardel 359 1.1 kardel for ( year = 1970; year < yearend; year++ ) 360 1.1 kardel { 361 1.1 kardel unsigned long t; 362 1.1 kardel long DaysYear ; 363 1.1 kardel 364 1.1 kardel clock_time->year = year; 365 1.1 kardel 366 1.1 kardel /* here is the code we are testing, cut and pasted out of the source */ 367 1.1 kardel #if 0 /* old BUGGY code that has Y2K (and many other) failures */ 368 1.1 kardel /* ghealton: this logic FAILED with great frequency when run 369 1.1 kardel * over a period of time, including for year 2000. True, it 370 1.1 kardel * had more successes than failures, but that's not really good 371 1.1 kardel * enough for critical time distribution software. 372 1.1 kardel * It is so awful I wonder if it has had a history of failure 373 1.1 kardel * and fixes? */ 374 1.1 kardel t = (clock_time->year - 1970) * 365; 375 1.1 kardel t += (clock_time->year >> 2) - (1970 >> 2); 376 1.1 kardel t -= clock_time->year / 100 - 1970 / 100; 377 1.1 kardel t += clock_time->year / 400 - 1970 / 400; 378 1.1 kardel 379 1.1 kardel /* (immediate feare of rounding errors on integer 380 1.1 kardel * **divisions proved well founded) */ 381 1.1 kardel 382 1.1 kardel #else 383 1.1 kardel /* my replacement, based on Days() above */ 384 1.1 kardel t = julian0(year) - julian0(1970); 385 1.1 kardel #endif 386 1.1 kardel 387 1.1 kardel /* compare result in t against trusted calculations */ 388 1.1 kardel DaysYear = Days( year ); /* get days to this year */ 389 1.1 kardel if ( t != DaysYear - Days1970 ) 390 1.1 kardel { 391 1.1 kardel Error(year); 392 1.1 kardel fprintf( stdout, 393 1.1 kardel " %4d 1970=%-8ld %4d=%-8ld %-3ld t=%-8ld *** ERROR ***\n", 394 1.1 kardel year, (long)Days1970, 395 1.1 kardel year, 396 1.1 kardel (long)DaysYear, 397 1.1 kardel (long)(DaysYear - Days1970), 398 1.1 kardel (long)t ); 399 1.1 kardel } 400 1.1 kardel } 401 1.1 kardel 402 1.1 kardel #if 1 /* { */ 403 1.1 kardel { 404 1.1 kardel debug = 1; /* enable debugging */ 405 1.1 kardel for ( year = 1970; year < yearend; year++ ) 406 1.1 kardel { /* (limited by theory unix 2038 related bug lives by, but 407 1.1 kardel * ends in yearend) */ 408 1.1 kardel clocktime_t ct; 409 1.1 kardel time_t Observed; 410 1.1 kardel time_t Expected; 411 1.1 kardel u_long Flag; 412 1.1 kardel unsigned long t; 413 1.1 kardel 414 1.1 kardel ct.day = 1; 415 1.1 kardel ct.month = 1; 416 1.1 kardel ct.year = year; 417 1.1 kardel ct.hour = ct.minute = ct.second = ct.usecond = 0; 418 1.1 kardel ct.utcoffset = 0; 419 1.1 kardel ct.utctime = 0; 420 1.1 kardel ct.flags = 0; 421 1.1 kardel 422 1.1 kardel Flag = 0; 423 1.1 kardel Observed = parse_to_unixtime( &ct, &Flag ); 424 1.1 kardel if ( ct.year != year ) 425 1.1 kardel { 426 1.1 kardel fprintf( stdout, 427 1.1 kardel "%04d: parse_to_unixtime(,%d) CORRUPTED ct.year: was %d\n", 428 1.1 kardel (int)year, (int)Flag, (int)ct.year ); 429 1.1 kardel Error(year); 430 1.1 kardel break; 431 1.1 kardel } 432 1.1 kardel t = julian0(year) - julian0(1970); /* Julian day from 1970 */ 433 1.1 kardel Expected = t * 24 * 60 * 60; 434 1.1 kardel if ( Observed != Expected || Flag ) 435 1.1 kardel { /* time difference */ 436 1.1 kardel fprintf( stdout, 437 1.1 kardel "%04d: parse_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu (%ld)\n", 438 1.1 kardel year, (int)Flag, 439 1.1 kardel (unsigned long)Observed, (unsigned long)Expected, 440 1.1 kardel ((long)Observed - (long)Expected) ); 441 1.1 kardel Error(year); 442 1.1 kardel break; 443 1.1 kardel } 444 1.1 kardel 445 1.1 kardel if ( year >= YEAR_PIVOT+1900 ) 446 1.1 kardel { 447 1.1 kardel /* check year % 100 code we put into parse_to_unixtime() */ 448 1.1 kardel ct.utctime = 0; 449 1.1 kardel ct.year = year % 100; 450 1.1 kardel Flag = 0; 451 1.1 kardel 452 1.1 kardel Observed = parse_to_unixtime( &ct, &Flag ); 453 1.1 kardel 454 1.1 kardel if ( Observed != Expected || Flag ) 455 1.1 kardel { /* time difference */ 456 1.1 kardel fprintf( stdout, 457 1.1 kardel "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n", 458 1.1 kardel year, (int)ct.year, (int)Flag, 459 1.1 kardel (unsigned long)Observed, (unsigned long)Expected, 460 1.1 kardel ((long)Observed - (long)Expected) ); 461 1.1 kardel Error(year); 462 1.1 kardel break; 463 1.1 kardel } 464 1.1 kardel 465 1.1 kardel /* check year - 1900 code we put into parse_to_unixtime() */ 466 1.1 kardel ct.utctime = 0; 467 1.1 kardel ct.year = year - 1900; 468 1.1 kardel Flag = 0; 469 1.1 kardel 470 1.1 kardel Observed = parse_to_unixtime( &ct, &Flag ); 471 1.1 kardel 472 1.1 kardel if ( Observed != Expected || Flag ) 473 1.1 kardel { /* time difference */ 474 1.1 kardel fprintf( stdout, 475 1.1 kardel "%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n", 476 1.1 kardel year, (int)ct.year, (int)Flag, 477 1.1 kardel (unsigned long)Observed, (unsigned long)Expected, 478 1.1 kardel ((long)Observed - (long)Expected) ); 479 1.1 kardel Error(year); 480 1.1 kardel break; 481 1.1 kardel } 482 1.1 kardel 483 1.1 kardel 484 1.1 kardel } 485 1.1 kardel } 486 1.1 kardel #endif /* } */ 487 1.1 kardel } 488 1.1 kardel } 489 1.1 kardel 490 1.1 kardel puts( " libntp/caljulian.c" ); 491 1.1 kardel { /* test caljulian() */ 492 1.1 kardel struct calendar ot; 493 1.1 kardel u_long ntp_time; /* NTP time */ 494 1.1 kardel 495 1.1 kardel year = year0; /* calculate the basic year */ 496 1.1 kardel printf( " starting year %04d\n", (int)year0 ); 497 1.1 kardel printf( " ending year %04d\n", (int)yearend ); 498 1.1 kardel 499 1.1 kardel 500 1.1 kardel ntp_time = julian0( year0 ); /* NTP starts in 1900-01-01 */ 501 1.1 kardel #if DAY_NTP_STARTS == 693596 502 1.1 kardel ntp_time -= 365; /* BIAS required for successful test */ 503 1.1 kardel #endif 504 1.1 kardel if ( DAY_NTP_STARTS != ntp_time ) 505 1.1 kardel { 506 1.1 kardel Error(year); 507 1.1 kardel fprintf( stdout, 508 1.1 kardel "%04d: DAY_NTP_STARTS (%ld) NOT TRUE VALUE OF %ld (%ld)\n", 509 1.1 kardel (int)year0, 510 1.1 kardel (long)DAY_NTP_STARTS, (long)ntp_time, 511 1.1 kardel (long)DAY_NTP_STARTS - (long)ntp_time ); 512 1.1 kardel } 513 1.1 kardel 514 1.1 kardel for ( ; year < yearend; year++ ) 515 1.1 kardel { 516 1.1 kardel 517 1.1 kardel /* 01-01 for the current year */ 518 1.1 kardel ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */ 519 1.1 kardel ntp_time *= 24 * 60 * 60; /* convert into seconds */ 520 1.1 kardel caljulian( ntp_time, &ot ); /* convert January 1 */ 521 1.1 kardel if ( ot.year != year 522 1.1 kardel || ot.month != 1 523 1.1 kardel || ot.monthday != 1 ) 524 1.1 kardel { 525 1.1 kardel Error(year); 526 1.1 kardel fprintf( stdout, "%lu: EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n", 527 1.1 kardel (unsigned long)ntp_time, 528 1.1 kardel year, 529 1.1 kardel (int)ot.year, (int)ot.month, (int)ot.monthday ); 530 1.1 kardel break; 531 1.1 kardel } 532 1.1 kardel 533 1.1 kardel ntp_time += (31 + 28-1) * ( 24 * 60 * 60 ); /* advance to 02-28 */ 534 1.1 kardel caljulian( ntp_time, &ot ); /* convert Feb 28 */ 535 1.1 kardel if ( ot.year != year 536 1.1 kardel || ot.month != 2 537 1.1 kardel || ot.monthday != 28 ) 538 1.1 kardel { 539 1.1 kardel Error(year); 540 1.1 kardel fprintf( stdout, "%lu: EXPECTED %04d-02-28: FOUND %04d-%02d-%02d\n", 541 1.1 kardel (unsigned long)ntp_time, 542 1.1 kardel year, 543 1.1 kardel (int)ot.year, (int)ot.month, (int)ot.monthday ); 544 1.1 kardel break; 545 1.1 kardel } 546 1.1 kardel 547 1.1 kardel { 548 1.1 kardel int m; /* expected month */ 549 1.1 kardel int d; /* expected day */ 550 1.1 kardel 551 1.1 kardel m = isleap_4(year) ? 2 : 3; 552 1.1 kardel d = isleap_4(year) ? 29 : 1; 553 1.1 kardel 554 1.1 kardel ntp_time += ( 24 * 60 * 60 ); /* advance to the next day */ 555 1.1 kardel caljulian( ntp_time, &ot ); /* convert this day */ 556 1.1 kardel if ( ot.year != year 557 1.1 kardel || ot.month != m 558 1.1 kardel || ot.monthday != d ) 559 1.1 kardel { 560 1.1 kardel Error(year); 561 1.1 kardel fprintf( stdout, "%lu: EXPECTED %04d-%02d-%02d: FOUND %04d-%02d-%02d\n", 562 1.1 kardel (unsigned long)ntp_time, 563 1.1 kardel year, m, d, 564 1.1 kardel (int)ot.year, (int)ot.month, (int)ot.monthday ); 565 1.1 kardel break; 566 1.1 kardel } 567 1.1 kardel 568 1.1 kardel } 569 1.1 kardel } 570 1.1 kardel } 571 1.1 kardel 572 1.1 kardel puts( " libntp/caltontp.c" ); 573 1.1 kardel { /* test caltontp() */ 574 1.1 kardel struct calendar ot; 575 1.1 kardel u_long ntp_time; /* NTP time */ 576 1.1 kardel 577 1.1 kardel year = year0; /* calculate the basic year */ 578 1.1 kardel printf( " starting year %04d\n", (int)year0 ); 579 1.1 kardel printf( " ending year %04d\n", (int)yearend ); 580 1.1 kardel 581 1.1 kardel 582 1.1 kardel for ( ; year < yearend; year++ ) 583 1.1 kardel { 584 1.1 kardel u_long ObservedNtp; 585 1.1 kardel 586 1.1 kardel /* 01-01 for the current year */ 587 1.1 kardel ot.year = year; 588 1.1 kardel ot.month = ot.monthday = 1; /* unused, but set anyway JIC */ 589 1.1 kardel ot.yearday = 1; /* this is the magic value used by caltontp() */ 590 1.1 kardel ot.hour = ot.minute = ot.second = 0; 591 1.1 kardel 592 1.1 kardel ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */ 593 1.1 kardel ntp_time *= 24 * 60 * 60; /* convert into seconds */ 594 1.1 kardel ObservedNtp = caltontp( &ot ); 595 1.1 kardel if ( ntp_time != ObservedNtp ) 596 1.1 kardel { 597 1.1 kardel Error(year); 598 1.1 kardel fprintf( stdout, "%d: EXPECTED %lu: FOUND %lu (%ld)\n", 599 1.1 kardel (int)year, 600 1.1 kardel (unsigned long)ntp_time, (unsigned long)ObservedNtp , 601 1.1 kardel (long)ntp_time - (long)ObservedNtp ); 602 1.1 kardel 603 1.1 kardel break; 604 1.1 kardel } 605 1.1 kardel 606 1.1 kardel /* now call caljulian as a type of failsafe supercheck */ 607 1.1 kardel caljulian( ObservedNtp, &ot ); /* convert January 1 */ 608 1.1 kardel if ( ot.year != year 609 1.1 kardel || ot.month != 1 610 1.1 kardel || ot.monthday != 1 ) 611 1.1 kardel { 612 1.1 kardel Error(year); 613 1.1 kardel fprintf( stdout, "%lu: caljulian FAILSAFE EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n", 614 1.1 kardel (unsigned long)ObservedNtp, 615 1.1 kardel year, 616 1.1 kardel (int)ot.year, (int)ot.month, (int)ot.monthday ); 617 1.1 kardel break; 618 1.1 kardel } 619 1.1 kardel } 620 1.1 kardel } 621 1.1 kardel 622 1.1 kardel if ( Warnings > 0 ) 623 1.1 kardel fprintf( stdout, "%d WARNINGS\n", Warnings ); 624 1.1 kardel if ( Fatals > 0 ) 625 1.1 kardel fprintf( stdout, "%d FATAL ERRORS\n", Fatals ); 626 1.1 kardel return Fatals ? 1 : 0; 627 1.1 kardel } 628 1.1 kardel /* Y2KFixes ] */ 629