summaryrefslogtreecommitdiffstats
path: root/sys-utils/wdctl.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sys-utils/wdctl.c70
1 files changed, 49 insertions, 21 deletions
diff --git a/sys-utils/wdctl.c b/sys-utils/wdctl.c
index 2a656b8..8611924 100644
--- a/sys-utils/wdctl.c
+++ b/sys-utils/wdctl.c
@@ -87,16 +87,16 @@ static const struct wdflag wdflags[] = {
/* column names */
struct colinfo {
- const char *name; /* header */
- double whint; /* width hint (N < 1 is in percent of termwidth) */
- int flags; /* SCOLS_FL_* */
- const char *help;
+ const char * const name; /* header */
+ double whint; /* width hint (N < 1 is in percent of termwidth) */
+ int flags; /* SCOLS_FL_* */
+ const char *help;
};
enum { COL_FLAG, COL_DESC, COL_STATUS, COL_BSTATUS, COL_DEVICE };
/* columns descriptions */
-static struct colinfo infos[] = {
+static const struct colinfo infos[] = {
[COL_FLAG] = { "FLAG", 14, 0, N_("flag name") },
[COL_DESC] = { "DESCRIPTION", 0.1, SCOLS_FL_TRUNC, N_("flag description") },
[COL_STATUS] = { "STATUS", 1, SCOLS_FL_RIGHT, N_("flag status") },
@@ -125,7 +125,12 @@ struct wd_device {
struct watchdog_info ident;
- unsigned int has_timeout : 1,
+ unsigned int has_identity : 1,
+ has_fw_version : 1,
+ has_options : 1,
+ has_status : 1,
+ has_bootstatus : 1,
+ has_timeout : 1,
has_timeleft : 1,
has_pretimeout : 1,
has_nowayout : 1,
@@ -188,7 +193,7 @@ static int get_column_id(int num)
return columns[num];
}
-static struct colinfo *get_column_info(unsigned num)
+static const struct colinfo *get_column_info(unsigned num)
{
return &infos[ get_column_id(num) ];
}
@@ -242,7 +247,7 @@ static void __attribute__((__noreturn__)) usage(void)
" -x, --flags-only print only flags table (same as -I -T)\n"), out);
fputs(USAGE_SEPARATOR, out);
- printf(USAGE_HELP_OPTIONS(24));
+ fprintf(out, USAGE_HELP_OPTIONS(24));
fputs(USAGE_SEPARATOR, out);
if (dflt)
@@ -254,7 +259,7 @@ static void __attribute__((__noreturn__)) usage(void)
for (i = 0; i < ARRAY_SIZE(infos); i++)
fprintf(out, " %13s %s\n", infos[i].name, _(infos[i].help));
- printf(USAGE_MAN_TAIL("wdctl(8)"));
+ fprintf(out, USAGE_MAN_TAIL("wdctl(8)"));
exit(EXIT_SUCCESS);
}
@@ -354,7 +359,7 @@ static int show_flags(struct wd_control *ctl, struct wd_device *wd, uint32_t wan
/* define columns */
for (i = 0; i < (size_t) ncolumns; i++) {
- struct colinfo *col = get_column_info(i);
+ const struct colinfo *col = get_column_info(i);
if (!scols_table_new_column(table, col->name, col->whint, col->flags)) {
warnx(_("failed to allocate output column"));
@@ -401,7 +406,7 @@ static int set_watchdog(struct wd_control *ctl, struct wd_device *wd)
assert(wd->devpath);
assert(ctl);
- if (!ctl->set_timeout && !ctl->set_timeout)
+ if (!ctl->set_timeout && !ctl->set_pretimeout)
goto sysfs_only;
sigemptyset(&oldsigs);
@@ -549,13 +554,16 @@ static int read_watchdog_from_sysfs(struct wd_device *wd)
if (!sys)
return 1;
- ul_path_read_buffer(sys, (char *) wd->ident.identity, sizeof(wd->ident.identity), "identity");
- ul_path_read_u32(sys, &wd->ident.firmware_version, "fw_version");
- ul_path_scanf(sys, "options", "%x", &wd->ident.options);
-
- ul_path_scanf(sys, "status", "%x", &wd->status);
- ul_path_read_u32(sys, &wd->bstatus, "bootstatus");
-
+ if (ul_path_read_buffer(sys, (char *) wd->ident.identity, sizeof(wd->ident.identity), "identity") >= 0)
+ wd->has_identity = 1;
+ if (ul_path_read_u32(sys, &wd->ident.firmware_version, "fw_version") == 0)
+ wd->has_fw_version = 1;
+ if (ul_path_scanf(sys, "options", "%x", &wd->ident.options) == 1)
+ wd->has_options = 1;
+ if (ul_path_scanf(sys, "status", "%x", &wd->status) == 1)
+ wd->has_status = 1;
+ if (ul_path_read_u32(sys, &wd->bstatus, "bootstatus") == 0)
+ wd->has_bootstatus = 1;
if (ul_path_read_s32(sys, &wd->nowayout, "nowayout") == 0)
wd->has_nowayout = 1;
if (ul_path_read_s32(sys, &wd->timeout, "timeout") == 0)
@@ -598,12 +606,32 @@ static int read_governors(struct wd_device *wd)
return 0;
}
+static bool should_read_from_device(struct wd_device *wd)
+{
+ if (!wd->has_nowayout)
+ return false;
+
+ if (wd->nowayout)
+ return false;
+
+ return !wd->has_identity ||
+ !wd->has_fw_version ||
+ !wd->has_options ||
+ !wd->has_status ||
+ !wd->has_bootstatus ||
+ !wd->has_timeout ||
+ !wd->has_timeleft;
+ // pretimeout attribute may be hidden in sysfs
+}
+
static int read_watchdog(struct wd_device *wd)
{
- int rc = read_watchdog_from_device(wd);
+ int rc;
+
+ rc = read_watchdog_from_sysfs(wd);
- if (rc == -EBUSY || rc == -EACCES || rc == -EPERM)
- rc = read_watchdog_from_sysfs(wd);
+ if (rc && should_read_from_device(wd))
+ rc = read_watchdog_from_device(wd);
if (rc) {
warn(_("cannot read information about %s"), wd->devpath);