chiark / gitweb /
util: open the first RTC that has hctosys=1 set
authorLennart Poettering <lennart@poettering.net>
Sat, 21 Jan 2012 02:15:54 +0000 (03:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 21 Jan 2012 02:15:54 +0000 (03:15 +0100)
TODO
src/util.c
src/util.h

diff --git a/TODO b/TODO
index 2c7e2b02f0b59ff2d8d7eab4efc10ffbf75fd10a..3b4d45fb7c9bfbf133390f976f79de1187448704 100644 (file)
--- a/TODO
+++ b/TODO
@@ -23,8 +23,6 @@ Features:
 
 * document the exit codes when services fail before they are exec()ed
 
-* use the rtc which has: /sys/class/rtc/*/hctosys == "1" as the system RTC
-
 * rework namespace support, don't use pivot_root, and mount things after creating the namespace, not before
 
 * systemctl journal command
index fbc37c4f0cdc05a452b7cf1a789d4e2b162e6dbd..de5feeb8d03eb4a2db31f929d167a5b99c29a63b 100644 (file)
@@ -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;
 
index 6acfcc83738cf40b479dc30a572a17b06d928244..114b24c3e7da00ab6cdb293e7928b53b002ba652 100644 (file)
@@ -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