diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/util.c | 69 | ||||
-rw-r--r-- | src/util.h | 2 |
2 files changed, 69 insertions, 2 deletions
diff --git a/src/util.c b/src/util.c index fbc37c4f0c..de5feeb8d0 100644 --- a/src/util.c +++ b/src/util.c @@ -5155,13 +5155,78 @@ int hwclock_reset_localtime_delta(void) { return 0; } +int rtc_open(int flags) { + int fd; + DIR *d; + + /* We open the first RTC which has hctosys=1 set. If we don't + * find any we just take the first one */ + + d = opendir("/sys/class/rtc"); + if (!d) + goto fallback; + + for (;;) { + char *p, *v; + struct dirent buf, *de; + int r; + + r = readdir_r(d, &buf, &de); + if (r != 0) + goto fallback; + + if (!de) + goto fallback; + + if (ignore_file(de->d_name)) + continue; + + p = join("/sys/class/rtc/", de->d_name, "/hctosys", NULL); + if (!p) { + closedir(d); + return -ENOMEM; + } + + r = read_one_line_file(p, &v); + free(p); + + if (r < 0) + continue; + + r = parse_boolean(v); + free(v); + + if (r <= 0) + continue; + + p = strappend("/dev/", de->d_name); + fd = open(p, flags); + free(p); + + if (fd >= 0) { + closedir(d); + return fd; + } + } + +fallback: + if (d) + closedir(d); + + fd = open("/dev/rtc0", flags); + if (fd < 0) + return -errno; + + return fd; +} + int hwclock_get_time(struct tm *tm) { int fd; int err = 0; assert(tm); - fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC); + fd = rtc_open(O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; @@ -5185,7 +5250,7 @@ int hwclock_set_time(const struct tm *tm) { assert(tm); - fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC); + fd = rtc_open(O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; diff --git a/src/util.h b/src/util.h index 6acfcc8373..114b24c3e7 100644 --- a/src/util.h +++ b/src/util.h @@ -529,4 +529,6 @@ int fd_wait_for_event(int fd, int event); void* memdup(const void *p, size_t l); +int rtc_open(int flags); + #endif |