| | 462 | /** |
| | 463 | * Updates "hardware" RTC, so that time is correct during early boot. |
| | 464 | * |
| | 465 | */ |
| | 466 | static void vgsvcTimeSyncSaveToRTC() { |
| | 467 | #ifdef RT_OS_LINUX |
| | 468 | FILE *adjtime_f = NULL; |
| | 469 | char *adjtime_line = NULL; |
| | 470 | size_t adjtime_buffer_len = 0; |
| | 471 | ssize_t adjtime_line_len; |
| | 472 | struct tm * (*xtime) (const time_t *) = NULL; |
| | 473 | time_t now; |
| | 474 | struct tm *now_tm = NULL; |
| | 475 | int rtc_fd = -1; |
| | 476 | |
| | 477 | if (!(adjtime_f = fopen("/etc/adjtime", "re"))) |
| | 478 | { |
| | 479 | VGSvcError("vgsvcTimeSyncSaveToRTC: open(/etc/adjtime) failed, error=%d\n", errno); |
| | 480 | goto out; |
| | 481 | } |
| | 482 | |
| | 483 | getline(&adjtime_line, &adjtime_buffer_len, adjtime_f); |
| | 484 | getline(&adjtime_line, &adjtime_buffer_len, adjtime_f); |
| | 485 | if ((adjtime_line_len = getline(&adjtime_line, &adjtime_buffer_len, adjtime_f)) == -1) { |
| | 486 | VGSvcError("vgsvcTimeSyncSaveToRTC: could not read /etc/adjtime, assuming UTC is in use, error=%d\n", errno); |
| | 487 | xtime = &gmtime; |
| | 488 | } |
| | 489 | else |
| | 490 | { |
| | 491 | if (adjtime_line[adjtime_line_len-1] == '\n') |
| | 492 | adjtime_line[adjtime_line_len-1] = '\0'; |
| | 493 | |
| | 494 | if (strcmp(adjtime_line, "LOCAL") == 0) |
| | 495 | { |
| | 496 | VGSvcVerbose(3, "RTC using local time\n"); |
| | 497 | xtime = &localtime; |
| | 498 | } |
| | 499 | else if (strcmp(adjtime_line, "UTC") == 0) |
| | 500 | { |
| | 501 | VGSvcVerbose(3, "RTC using UTC\n"); |
| | 502 | xtime = &gmtime; |
| | 503 | } |
| | 504 | else |
| | 505 | { |
| | 506 | VGSvcError("vgsvcTimeSyncSaveToRTC: unknown time standard '%s', not setting RTC\n", adjtime_line); |
| | 507 | goto out; |
| | 508 | } |
| | 509 | } |
| | 510 | |
| | 511 | if ((now = time(NULL)) == (time_t)-1) |
| | 512 | { |
| | 513 | VGSvcError("vgsvcTimeSyncSaveToRTC: time() failed, error=%d\n", errno); |
| | 514 | goto out; |
| | 515 | } |
| | 516 | if (!(now_tm = (*xtime)(&now))) |
| | 517 | { |
| | 518 | VGSvcError("vgsvcTimeSyncSaveToRTC: {gm|local}time() failed\n"); |
| | 519 | goto out; |
| | 520 | } |
| | 521 | |
| | 522 | if ((rtc_fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC)) == -1) |
| | 523 | { |
| | 524 | VGSvcError("vgsvcTimeSyncSaveToRTC: open(/dev/rtc) failed, error=%d\n", errno); |
| | 525 | goto out; |
| | 526 | } |
| | 527 | |
| | 528 | if (ioctl(rtc_fd, RTC_SET_TIME, now_tm) == -1) |
| | 529 | { |
| | 530 | VGSvcError("vgsvcTimeSyncSaveToRTC: ioctl(RTC_SET_TIME) failed, errno=%d\n", errno); |
| | 531 | goto out; |
| | 532 | } |
| | 533 | |
| | 534 | VGSvcVerbose(3, "RTC updated\n"); |
| | 535 | |
| | 536 | out: |
| | 537 | close(rtc_fd); |
| | 538 | free(adjtime_line); |
| | 539 | if (adjtime_f) |
| | 540 | fclose(adjtime_f); |
| | 541 | return; |
| | 542 | #endif /* !RT_OS_LINUX */ |
| | 543 | } |
| | 544 | |