Apparently some RTC drivers return EINVAL in that case when we try to
read it. Handle that reasonably gracefully.
Fixes: #31854
if (fd < 0)
return -errno;
- /* This leaves the timezone fields of struct tm
- * uninitialized! */
+ /* This leaves the timezone fields of struct tm uninitialized! */
if (ioctl(fd, RTC_RD_TIME, tm) < 0)
- return -errno;
+ /* Some drivers return -EINVAL in case the time could not be kept, i.e. power loss
+ * happened. Let's turn that into a clearly recognizable error */
+ return errno == EINVAL ? -ENODATA : -errno;
/* We don't know daylight saving, so we reset this in order not
* to confuse mktime(). */
log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp.");
else if (r == -ENOENT)
log_debug("/dev/rtc not found.");
+ else if (r == -ENODATA)
+ log_debug("/dev/rtc has no valid time, power loss probably occurred?");
else if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m");
else