]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
hwclock: skip RTC_PARAM_SET for --param-set with unchanged value
authorBastian Krause <bst@pengutronix.de>
Fri, 24 Oct 2025 15:32:20 +0000 (17:32 +0200)
committerBastian Krause <bst@pengutronix.de>
Thu, 30 Oct 2025 11:05:11 +0000 (12:05 +0100)
Parameters set with `hwclock --param-set` tend to be persisted in the
RTC's EEPROM. Writing the same value over and over again can wear out
the EEPROM (e.g. on each boot).
So read the current value first. Only if the parameter is changed,
actually write the new value.

This allows for easier integrations, especially since there is no
machine-readable way of retrieving the current value via hwclock.

Signed-off-by: Bastian Krause <bst@pengutronix.de>
sys-utils/hwclock-rtc.c

index f8af5545dc5cbc9b091961fdaebece0acff554dd..318e692e97c95062cc98136833529ec695978e69 100644 (file)
@@ -498,6 +498,7 @@ int get_param_rtc(const struct hwclock_control *ctl,
 int set_param_rtc(const struct hwclock_control *ctl, const char *opt0)
 {
        int rtc_fd, rc = 1;
+       struct rtc_param current_param = { .index = ctl->param_idx };
        struct rtc_param param = { .index = ctl->param_idx };
        char *tok, *opt = xstrdup(opt0);
 
@@ -520,13 +521,25 @@ int set_param_rtc(const struct hwclock_control *ctl, const char *opt0)
                goto done;
        }
 
-       /* set parameter */
        rtc_fd = open_rtc(ctl);
        if (rtc_fd < 0) {
                warnx(_("cannot open %s"), rtc_dev_name);
                goto done;
        }
 
+       /* get parameter and compare with value */
+       current_param.param = param.param;
+       if (!ioctl(rtc_fd, RTC_PARAM_GET, &current_param)
+               && current_param.uvalue == param.uvalue) {
+               /* value to be written matches current value, skip write */
+               if (ctl->verbose)
+                       printf(_("skipping ioctl(%d, RTC_PARAM_GET, param) to %s: value unchanged\n"),
+                                  rtc_fd, rtc_dev_name);
+               rc = 0;
+               goto done;
+       }
+
+       /* set parameter */
        if (ioctl(rtc_fd, RTC_PARAM_SET, &param) == -1) {
                warn(_("ioctl(%d, RTC_PARAM_SET, param) to %s failed"),
                     rtc_fd, rtc_dev_name);