#include <unistd.h>
#include "monotonic.h"
+#include "strutils.h"
+#include "xalloc.h"
#include "nls.h"
#include "hwclock.h"
# define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
#endif
+#ifndef RTC_PARAM_GET
+struct rtc_param {
+ uint64_t param;
+ union {
+ uint64_t uvalue;
+ int64_t svalue;
+ uint64_t ptr;
+ };
+ uint32_t index;
+ uint32_t __pad;
+};
+
+# define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param)
+# define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param)
+
+# define RTC_PARAM_FEATURES 0
+# define RTC_PARAM_CORRECTION 1
+# define RTC_PARAM_BACKUP_SWITCH_MODE 2
+#endif /* RTC_PARAM_GET */
+
static const struct hwclock_param hwclock_params[] =
{
{ RTC_PARAM_FEATURES, "features", N_("supported features") },
/*
* Get the Hardware Clock parameter setting from the kernel.
*/
-int get_param_rtc(const struct hwclock_control *ctl, struct rtc_param *param)
+int get_param_rtc(const struct hwclock_control *ctl,
+ const char *name, uint64_t *id, uint64_t *value)
{
int rtc_fd;
+ struct rtc_param param = { .param = 0 };
/* handle name */
- if (resolve_rtc_param_alias(ctl->param_get_option, ¶m->param)) {
- char *end = NULL;
- int base;
-
- base = strncmp(ctl->param_get_option, "0x", 2) ? 10 : 16;
- errno = 0;
- param->param = strtoull(ctl->param_get_option, &end, base);
- if (errno || !end || *end) {
- warnx(_("could not convert parameter name to number"));
- return 1;
- }
+ if (resolve_rtc_param_alias(name, ¶m.param) != 0
+ && ul_strtou64(name, ¶m.param, 0) != 0) {
+ warnx(_("could not convert parameter name to number"));
+ return 1;
}
/* get parameter */
return 1;
}
- if (ioctl(rtc_fd, RTC_PARAM_GET, param) == -1) {
+ if (ioctl(rtc_fd, RTC_PARAM_GET, ¶m) == -1) {
warn(_("ioctl(%d, RTC_PARAM_GET, param) to %s failed"),
rtc_fd, rtc_dev_name);
return 1;
}
+ if (id)
+ *id = param.param;
+ if (*value)
+ *value = param.uvalue;
+
if (ctl->verbose)
printf(_("ioctl(%d, RTC_PARAM_GET, param) to %s succeeded.\n"),
rtc_fd, rtc_dev_name);
/*
* Set the Hardware Clock parameter in the kernel.
*/
-int set_param_rtc(const struct hwclock_control *ctl)
+int set_param_rtc(const struct hwclock_control *ctl, const char *opt0)
{
- char *tok = NULL, *end = NULL;
- int rtc_fd, base;
- struct rtc_param param;
-
- memset(¶m, 0, sizeof(param));
+ int rtc_fd, rc = 1;
+ struct rtc_param param = { .param = 0 };
+ char *tok, *opt = xstrdup(opt0);
/* handle name */
- tok = strtok(ctl->param_set_option, "=");
- if (resolve_rtc_param_alias(tok, ¶m.param)) {
- base = strncmp(tok, "0x", 2) ? 10 : 16;
-
- errno = 0;
- param.param = strtoull(tok, &end, base);
- if (errno || !end || *end) {
- warnx(_("could not convert parameter name to number"));
- return 1;
- }
+ tok = strtok(opt, "=");
+ if (resolve_rtc_param_alias(tok, ¶m.param) != 0
+ && ul_strtou64(tok, ¶m.param, 0) != 0) {
+ warnx(_("could not convert parameter name to number"));
+ goto done;
}
/* handle value */
tok = strtok(NULL, "=");
if (!tok) {
warnx(_("expected <param>=<value>"));
- return 1;
+ goto done;
}
-
- base = strncmp(tok, "0x", 2) ? 10 : 16;
- end = NULL;
- errno = 0;
- param.uvalue = strtoull(tok, &end, base);
- if (errno || !end || *end) {
+ if (ul_strtou64(tok, ¶m.uvalue, 0) != 0) {
warnx(_("could not convert parameter value to number"));
- return 1;
+ goto done;
}
/* set parameter */
if (ioctl(rtc_fd, RTC_PARAM_SET, ¶m) == -1) {
warn(_("ioctl(%d, RTC_PARAM_SET, param) to %s failed"),
rtc_fd, rtc_dev_name);
- return 1;
+ goto done;
}
if (ctl->verbose)
printf(_("ioctl(%d, RTC_PARAM_SET, param) to %s succeeded.\n"),
rtc_fd, rtc_dev_name);
- return 0;
+ rc = 0;
+done:
+ free(opt);
+ return rc;
}
manipulate_rtc_param(const struct hwclock_control *ctl)
{
if (ctl->param_get_option) {
- struct rtc_param param = {};
+ uint64_t id = 0, value = 0;
- if (get_param_rtc(ctl, ¶m)) {
- warnx(_("unable to read the RTC parameter 0x%jx."),
- (uintmax_t) param.param);
+ if (get_param_rtc(ctl, ctl->param_get_option, &id, &value)) {
+ warnx(_("unable to read the RTC parameter %s"),
+ ctl->param_get_option);
return 1;
}
printf(_("The RTC parameter 0x%jx is set to 0x%jx.\n"),
- (uintmax_t) param.param, (uintmax_t) param.uvalue);
+ (uintmax_t) id, (uintmax_t) value);
} else if (ctl->param_set_option) {
if (ctl->testing)
return 0;
- return set_param_rtc(ctl);
+ return set_param_rtc(ctl, ctl->param_set_option);
}
return 1;
extern int set_epoch_rtc(const struct hwclock_control *ctl);
#endif
-struct rtc_param {
- uint64_t param;
- union {
- uint64_t uvalue;
- int64_t svalue;
- uint64_t ptr;
- };
- uint32_t index;
- uint32_t __pad;
-};
-
-#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param)
-#define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param)
-
-#define RTC_PARAM_FEATURES 0
-#define RTC_PARAM_CORRECTION 1
-#define RTC_PARAM_BACKUP_SWITCH_MODE 2
-
struct hwclock_param {
int id;
const char *name;
};
extern const struct hwclock_param *get_hwclock_params(void);
-extern int get_param_rtc(const struct hwclock_control *ctl, struct rtc_param *param);
-extern int set_param_rtc(const struct hwclock_control *ctl);
+extern int get_param_rtc(const struct hwclock_control *ctl,
+ const char *name, uint64_t *id, uint64_t *value);
+extern int set_param_rtc(const struct hwclock_control *ctl, const char *name);
extern void __attribute__((__noreturn__))
hwclock_exit(const struct hwclock_control *ctl, int status);