summaryrefslogtreecommitdiffstats
path: root/sys-utils
diff options
context:
space:
mode:
Diffstat (limited to 'sys-utils')
-rw-r--r--sys-utils/Makemodule.am7
-rw-r--r--sys-utils/choom.11
-rw-r--r--sys-utils/choom.c2
-rw-r--r--sys-utils/dmesg.c26
-rw-r--r--sys-utils/fsfreeze.c2
-rw-r--r--sys-utils/fstrim.service.in2
-rw-r--r--sys-utils/hwclock-cmos.c47
-rw-r--r--sys-utils/hwclock.c2
-rw-r--r--sys-utils/ldattach.c2
-rw-r--r--sys-utils/losetup.c4
-rw-r--r--sys-utils/lscpu-dmi.c2
-rw-r--r--sys-utils/lscpu.15
-rw-r--r--sys-utils/lscpu.c56
-rw-r--r--sys-utils/lscpu.h9
-rw-r--r--sys-utils/lsipc.c2
-rw-r--r--sys-utils/mount.82
-rw-r--r--sys-utils/mountpoint.17
-rw-r--r--sys-utils/mountpoint.c19
-rw-r--r--sys-utils/wdctl.84
-rw-r--r--sys-utils/wdctl.c267
20 files changed, 312 insertions, 156 deletions
diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 7c118a6de..98e2cc29b 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -451,9 +451,12 @@ dist_man_MANS += \
PATHFILES += sys-utils/hwclock.8
hwclock_SOURCES = \
sys-utils/hwclock.c \
- sys-utils/hwclock.h \
- sys-utils/hwclock-cmos.c
+ sys-utils/hwclock.h
hwclock_LDADD = $(LDADD) libcommon.la -lm
+if USE_HWCLOCK_CMOS
+hwclock_SOURCES += \
+ sys-utils/hwclock-cmos.c
+endif
if LINUX
hwclock_SOURCES += \
sys-utils/hwclock-rtc.c \
diff --git a/sys-utils/choom.1 b/sys-utils/choom.1
index 2b844cbe2..def31d5f0 100644
--- a/sys-utils/choom.1
+++ b/sys-utils/choom.1
@@ -15,6 +15,7 @@ choom \- display and adjust OOM-killer score.
.B choom
.B \-n
.I number
+.B [\-\-]
.IR command\ [ argument ...]
.SH DESCRIPTION
diff --git a/sys-utils/choom.c b/sys-utils/choom.c
index 1096ab186..b3d3e4d91 100644
--- a/sys-utils/choom.c
+++ b/sys-utils/choom.c
@@ -37,7 +37,7 @@ static void __attribute__((__noreturn__)) usage(void)
fprintf(out,
_(" %1$s [options] -p pid\n"
" %1$s [options] -n number -p pid\n"
- " %1$s [options] -n number command [args...]]\n"),
+ " %1$s [options] -n number [--] command [args...]]\n"),
program_invocation_short_name);
fputs(USAGE_SEPARATOR, out);
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index f0b9b7137..9f2e5b804 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -637,25 +637,29 @@ static void safe_fwrite(const char *buf, size_t size, int indent, FILE *out)
if (len == (size_t)-1 || len == (size_t)-2) { /* invalid sequence */
memset(&s, 0, sizeof (s));
len = hex = 1;
- } else if (len > 1 && !iswprint(wc)) { /* non-printable multibyte */
- hex = 1;
- }
- i += len - 1;
-#else
- len = 1;
- if (!isprint((unsigned char) *p) &&
- !isspace((unsigned char) *p)) /* non-printable */
- hex = 1;
+ i += len - 1;
+ } else if (len > 1) {
+ if (!iswprint(wc) && !iswspace(wc)) /* non-printable multibyte */
+ hex = 1;
+ i += len - 1;
+ } else
#endif
+ {
+ len = 1;
+ if (!isprint((unsigned char) *p) &&
+ !isspace((unsigned char) *p)) /* non-printable */
+ hex = 1;
+ }
+
if (hex)
rc = fwrite_hex(p, len, out);
else if (*p == '\n' && *(p + 1) && indent) {
rc = fwrite(p, 1, len, out) != len;
if (fprintf(out, "%*s", indent, "") != indent)
rc |= 1;
- }
- else
+ } else
rc = fwrite(p, 1, len, out) != len;
+
if (rc != 0) {
if (errno != EPIPE)
err(EXIT_FAILURE, _("write failed"));
diff --git a/sys-utils/fsfreeze.c b/sys-utils/fsfreeze.c
index 4da1a6fa3..6035a1010 100644
--- a/sys-utils/fsfreeze.c
+++ b/sys-utils/fsfreeze.c
@@ -77,7 +77,7 @@ int main(int argc, char **argv)
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
while ((c = getopt_long(argc, argv, "hfuV", longopts, NULL)) != -1) {
diff --git a/sys-utils/fstrim.service.in b/sys-utils/fstrim.service.in
index 516023ed8..2a8dc1d3a 100644
--- a/sys-utils/fstrim.service.in
+++ b/sys-utils/fstrim.service.in
@@ -6,7 +6,7 @@ Documentation=man:fstrim(8)
Type=oneshot
ExecStart=@sbindir@/fstrim --fstab --verbose --quiet
ProtectSystem=strict
-ProtectHome=yes
+ProtectHome=read-only
PrivateDevices=no
PrivateNetwork=yes
PrivateUsers=no
diff --git a/sys-utils/hwclock-cmos.c b/sys-utils/hwclock-cmos.c
index a11f676b8..4d3e023d9 100644
--- a/sys-utils/hwclock-cmos.c
+++ b/sys-utils/hwclock-cmos.c
@@ -56,37 +56,13 @@
#include "pathnames.h"
/* for inb, outb */
-#if defined(__i386__) || defined(__x86_64__)
-# ifdef HAVE_SYS_IO_H
-# include <sys/io.h>
-# elif defined(HAVE_ASM_IO_H)
-# include <asm/io.h>
-# else
-# undef __i386__
-# undef __x86_64__
-# warning "disable cmos access - no sys/io.h or asm/io.h"
-static void outb(int a __attribute__((__unused__)),
- int b __attribute__((__unused__)))
-{
-}
-
-static int inb(int c __attribute__((__unused__)))
-{
- return 0;
-}
-# endif /* __i386__ __x86_64__ */
+#ifdef HAVE_SYS_IO_H
+# include <sys/io.h>
+#elif defined(HAVE_ASM_IO_H)
+# include <asm/io.h>
#else
-# warning "disable cmos access - not i386 or x86_64"
-static void outb(int a __attribute__((__unused__)),
- int b __attribute__((__unused__)))
-{
-}
-
-static int inb(int c __attribute__((__unused__)))
-{
- return 0;
-}
-#endif /* for inb, outb */
+# error "no sys/io.h or asm/io.h"
+#endif /* HAVE_SYS_IO_H, HAVE_ASM_IO_H */
#include "hwclock.h"
@@ -360,7 +336,6 @@ static int set_hardware_clock_cmos(const struct hwclock_control *ctl
return 0;
}
-#if defined(__i386__) || defined(__x86_64__)
# if defined(HAVE_IOPL)
static int i386_iopl(const int level)
{
@@ -373,12 +348,6 @@ static int i386_iopl(const int level __attribute__ ((__unused__)))
return ioperm(clock_ctl_addr, 2, 1);
}
# endif
-#else
-static int i386_iopl(const int level __attribute__ ((__unused__)))
-{
- return IOPL_NOT_IMPLEMENTED;
-}
-#endif
static int get_permissions_cmos(void)
{
@@ -412,9 +381,5 @@ static struct clock_ops cmos_interface = {
*/
struct clock_ops *probe_for_cmos_clock(void)
{
-#if defined(__i386__) || defined(__x86_64__)
return &cmos_interface;
-#else
- return NULL;
-#endif
}
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index a2c5cc2a4..c01a86826 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -925,8 +925,10 @@ static void determine_clock_access_method(const struct hwclock_control *ctl)
{
ur = NULL;
+#ifdef USE_HWCLOCK_CMOS
if (ctl->directisa)
ur = probe_for_cmos_clock();
+#endif
#ifdef __linux__
if (!ur)
ur = probe_for_rtc_clock(ctl);
diff --git a/sys-utils/ldattach.c b/sys-utils/ldattach.c
index 3019e5a9f..c2d2f8397 100644
--- a/sys-utils/ldattach.c
+++ b/sys-utils/ldattach.c
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
/* parse options */
if (argc == 0)
diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index f455b49c3..5e5ce9e28 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -434,7 +434,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(USAGE_SEPARATOR, out);
fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out);
fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out);
- fputs(_(" -b --sector-size <num> set the logical sector size to <num>\n"), out);
+ fputs(_(" -b, --sector-size <num> set the logical sector size to <num>\n"), out);
fputs(_(" -P, --partscan create a partitioned loop device\n"), out);
fputs(_(" -r, --read-only set up a read-only loop device\n"), out);
fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out);
@@ -667,7 +667,7 @@ int main(int argc, char **argv)
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
if (loopcxt_init(&lc, 0))
err(EXIT_FAILURE, _("failed to initialize loopcxt"));
diff --git a/sys-utils/lscpu-dmi.c b/sys-utils/lscpu-dmi.c
index 29bd2e4fc..82d8ed443 100644
--- a/sys-utils/lscpu-dmi.c
+++ b/sys-utils/lscpu-dmi.c
@@ -80,7 +80,7 @@ static void to_dmi_header(struct dmi_header *h, uint8_t *data)
{
h->type = data[0];
h->length = data[1];
- h->handle = WORD(data + 2);
+ memcpy(&h->handle, data + 2, sizeof(h->handle));
h->data = data;
}
diff --git a/sys-utils/lscpu.1 b/sys-utils/lscpu.1
index e82fa4320..cd509f72b 100644
--- a/sys-utils/lscpu.1
+++ b/sys-utils/lscpu.1
@@ -33,6 +33,11 @@ specified, \fBlscpu\fP prints the column but does not provide any data for it.
The default output formatting on terminal maybe optimized for better
readability. The output for non-terminals (e.g. pipes) is never affected by
this optimization and it is always in "Field: data\\n" format.
+.sp
+The cache sizes are reported as summary from all CPUs. The versions before
+v2.34 reported per-core sizes, but this output was confusing due to complicated
+CPUs topology and the way how caches are shared between CPUs. For more details
+about caches see \fB\-\-cache\fP.
.SS COLUMNS
Note that topology elements (core, socket, etc.) use a sequential unique ID
starting from zero, but CPU logical numbers follow the kernel where there is
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 0e775805e..4f1ab47e9 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -178,6 +178,11 @@ enum {
COL_CACHE_ONESIZE,
COL_CACHE_TYPE,
COL_CACHE_WAYS,
+ COL_CACHE_ALLOCPOL,
+ COL_CACHE_WRITEPOL,
+ COL_CACHE_PHYLINE,
+ COL_CACHE_SETS,
+ COL_CACHE_COHERENCYSIZE
};
@@ -215,7 +220,12 @@ static struct lscpu_coldesc coldescs_cache[] =
[COL_CACHE_NAME] = { "NAME", N_("cache name") },
[COL_CACHE_ONESIZE] = { "ONE-SIZE", N_("size of one cache"), SCOLS_FL_RIGHT },
[COL_CACHE_TYPE] = { "TYPE", N_("cache type") },
- [COL_CACHE_WAYS] = { "WAYS", N_("ways of associativity"), SCOLS_FL_RIGHT }
+ [COL_CACHE_WAYS] = { "WAYS", N_("ways of associativity"), SCOLS_FL_RIGHT },
+ [COL_CACHE_ALLOCPOL] = { "ALLOC-POLICY", N_("allocation policy") },
+ [COL_CACHE_WRITEPOL] = { "WRITE-POLICY", N_("write policy") },
+ [COL_CACHE_PHYLINE] = { "PHY-LINE", N_("number of physical cache line per cache t"), SCOLS_FL_RIGHT },
+ [COL_CACHE_SETS] = { "SETS", N_("number of sets in the cache; set lines has the same cache index"), SCOLS_FL_RIGHT },
+ [COL_CACHE_COHERENCYSIZE] = { "COHERENCY-SIZE", N_("minimum amount of data in bytes transferred from memory to cache"), SCOLS_FL_RIGHT }
};
@@ -1354,9 +1364,19 @@ read_cache(struct lscpu_desc *desc, int idx)
ca->name = xstrdup(buf);
- /* cache ways */
- ul_path_readf_s32(desc->syscpu, &ca->ways,
+ ul_path_readf_u32(desc->syscpu, &ca->ways_of_associativity,
"cpu%d/cache/index%d/ways_of_associativity", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->physical_line_partition,
+ "cpu%d/cache/index%d/physical_line_partition", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->number_of_sets,
+ "cpu%d/cache/index%d/number_of_sets", num, i);
+ ul_path_readf_u32(desc->syscpu, &ca->coherency_line_size,
+ "cpu%d/cache/index%d/coherency_line_size", num, i);
+
+ ul_path_readf_string(desc->syscpu, &ca->allocation_policy,
+ "cpu%d/cache/index%d/allocation_policy", num, i);
+ ul_path_readf_string(desc->syscpu, &ca->write_policy,
+ "cpu%d/cache/index%d/write_policy", num, i);
/* cache size */
if (ul_path_readf_buffer(desc->syscpu, buf, sizeof(buf),
@@ -1682,9 +1702,10 @@ print_caches_readable(struct lscpu_desc *desc, int cols[], int ncols,
break;
}
case COL_CACHE_WAYS:
- if (ca->ways)
- xasprintf(&data, "%d", ca->ways);
+ if (ca->ways_of_associativity)
+ xasprintf(&data, "%u", ca->ways_of_associativity);
break;
+
case COL_CACHE_TYPE:
if (ca->type)
data = xstrdup(ca->type);
@@ -1693,6 +1714,26 @@ print_caches_readable(struct lscpu_desc *desc, int cols[], int ncols,
if (ca->level)
xasprintf(&data, "%d", ca->level);
break;
+ case COL_CACHE_ALLOCPOL:
+ if (ca->allocation_policy)
+ data = xstrdup(ca->allocation_policy);
+ break;
+ case COL_CACHE_WRITEPOL:
+ if (ca->write_policy)
+ data = xstrdup(ca->write_policy);
+ break;
+ case COL_CACHE_PHYLINE:
+ if (ca->physical_line_partition)
+ xasprintf(&data, "%u", ca->physical_line_partition);
+ break;
+ case COL_CACHE_SETS:
+ if (ca->number_of_sets)
+ xasprintf(&data, "%u", ca->number_of_sets);
+ break;
+ case COL_CACHE_COHERENCYSIZE:
+ if (ca->coherency_line_size)
+ xasprintf(&data, "%u", ca->coherency_line_size);
+ break;
}
if (data && scols_line_refer_data(line, c, data))
@@ -2255,7 +2296,7 @@ int main(int argc, char *argv[])
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
while ((c = getopt_long(argc, argv, "aBbC::ce::hJp::s:xyV", longopts, NULL)) != -1) {
@@ -2414,6 +2455,9 @@ int main(int argc, char *argv[])
columns[ncolumns++] = COL_CACHE_WAYS;
columns[ncolumns++] = COL_CACHE_TYPE;
columns[ncolumns++] = COL_CACHE_LEVEL;
+ columns[ncolumns++] = COL_CACHE_SETS;
+ columns[ncolumns++] = COL_CACHE_PHYLINE;
+ columns[ncolumns++] = COL_CACHE_COHERENCYSIZE;
}
print_caches_readable(desc, columns, ncolumns, mod);
break;
diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
index 56c97e2e8..5bbdb348e 100644
--- a/sys-utils/lscpu.h
+++ b/sys-utils/lscpu.h
@@ -49,10 +49,17 @@ enum {
struct cpu_cache {
char *name;
char *type;
+ char *allocation_policy;
+ char *write_policy;
+
int level;
- int ways;
uint64_t size;
+ unsigned int ways_of_associativity;
+ unsigned int physical_line_partition;
+ unsigned int number_of_sets;
+ unsigned int coherency_line_size;
+
int nsharedmaps;
cpu_set_t **sharedmaps;
};
diff --git a/sys-utils/lsipc.c b/sys-utils/lsipc.c
index 5ba9cd7bf..5a1a3d7ac 100644
--- a/sys-utils/lsipc.c
+++ b/sys-utils/lsipc.c
@@ -1137,7 +1137,7 @@ int main(int argc, char *argv[])
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
ctl->time_mode = 0;
diff --git a/sys-utils/mount.8 b/sys-utils/mount.8
index b79b4ef5f..56d3520be 100644
--- a/sys-utils/mount.8
+++ b/sys-utils/mount.8
@@ -116,7 +116,7 @@ options to avoid ambivalent interpretation of the given argument. For example:
The same filesystem may be mounted more than once, and in some cases (e.g.
network filesystems) the same filesystem may be mounted on the same
mountpoint more times. The mount command does not implement any policy to
-control this behavior. All behavior is controlled bythe kernel and it is usually
+control this behavior. All behavior is controlled by the kernel and it is usually
specific to the filesystem driver. The exception is \fB\-\-all\fR, in this case
already mounted filesystems are ignored (see \fB\-\-all\fR below for more details).
diff --git a/sys-utils/mountpoint.1 b/sys-utils/mountpoint.1
index afc469ebc..6669b13eb 100644
--- a/sys-utils/mountpoint.1
+++ b/sys-utils/mountpoint.1
@@ -1,4 +1,4 @@
-.TH MOUNTPOINT 1 "July 2014" "util-linux" "User Commands"
+.TH MOUNTPOINT 1 "August 2019" "util-linux" "User Commands"
.SH NAME
mountpoint \- see if a directory or file is a mountpoint
.SH SYNOPSIS
@@ -28,6 +28,11 @@ directory.
.BR \-q , " \-\-quiet"
Be quiet - don't print anything.
.TP
+.B "\-\-nofollow"
+Do not follow symbolic link if it the last elemnt of the
+.I directory
+path.
+.TP
.BR \-x , " \-\-devno"
Show the major/minor numbers of the given blockdevice on standard output.
.TP
diff --git a/sys-utils/mountpoint.c b/sys-utils/mountpoint.c
index 985130cba..052440bd4 100644
--- a/sys-utils/mountpoint.c
+++ b/sys-utils/mountpoint.c
@@ -47,6 +47,7 @@ struct mountpoint_control {
unsigned int
dev_devno:1,
fs_devno:1,
+ nofollow:1,
quiet:1;
};
@@ -123,6 +124,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(USAGE_OPTIONS, out);
fputs(_(" -q, --quiet quiet mode - don't print anything\n"
+ " --nofollow do not follow symlink\n"
" -d, --fs-devno print maj:min device number of the filesystem\n"
" -x, --devno print maj:min device number of the block device\n"), out);
fputs(USAGE_SEPARATOR, out);
@@ -137,8 +139,13 @@ int main(int argc, char **argv)
int c;
struct mountpoint_control ctl = { NULL };
+ enum {
+ OPT_NOFOLLOW = CHAR_MAX + 1
+ };
+
static const struct option longopts[] = {
{ "quiet", no_argument, NULL, 'q' },
+ { "nofollow", no_argument, NULL, OPT_NOFOLLOW },
{ "fs-devno", no_argument, NULL, 'd' },
{ "devno", no_argument, NULL, 'x' },
{ "help", no_argument, NULL, 'h' },
@@ -159,6 +166,9 @@ int main(int argc, char **argv)
case 'q':
ctl.quiet = 1;
break;
+ case OPT_NOFOLLOW:
+ ctl.nofollow = 1;
+ break;
case 'd':
ctl.fs_devno = 1;
break;
@@ -179,17 +189,20 @@ int main(int argc, char **argv)
warnx(_("bad usage"));
errtryhelp(EXIT_FAILURE);
}
+ if (ctl.nofollow && ctl.dev_devno)
+ errx(EXIT_FAILURE, _("%s and %s are mutually exclusive"),
+ "--devno", "--nofollow");
ctl.path = argv[optind];
-
- if (stat(ctl.path, &ctl.st)) {
+ c = ctl.nofollow ? lstat(ctl.path, &ctl.st) : stat(ctl.path, &ctl.st);
+ if (c) {
if (!ctl.quiet)
err(EXIT_FAILURE, "%s", ctl.path);
return EXIT_FAILURE;
}
if (ctl.dev_devno)
return print_devno(&ctl) ? EXIT_FAILURE : EXIT_SUCCESS;
- if (dir_to_device(&ctl)) {
+ if ((ctl.nofollow && S_ISLNK(ctl.st.st_mode)) || dir_to_device(&ctl)) {
if (!ctl.quiet)
printf(_("%s is not a mountpoint\n"), ctl.path);
return EXIT_FAILURE;
diff --git a/sys-utils/wdctl.8 b/sys-utils/wdctl.8
index 7edf80866..efd8b5917 100644
--- a/sys-utils/wdctl.8
+++ b/sys-utils/wdctl.8
@@ -14,6 +14,10 @@ Show hardware watchdog status. The default device is
If more than one device is specified then the output is separated by
one blank line.
.PP
+If the device is already used or user has no permissions to read from the device than
+.B wdctl
+reads data from sysfs. In this case information about supported features (flags) might be missing.
+.PP
Note that the number of supported watchdog features is hardware specific.
.SH OPTIONS
.TP
diff --git a/sys-utils/wdctl.c b/sys-utils/wdctl.c
index 4574e10da..8de5d5a2d 100644
--- a/sys-utils/wdctl.c
+++ b/sys-utils/wdctl.c
@@ -21,10 +21,12 @@
#include <sys/ioctl.h>
#include <getopt.h>
#include <stdio.h>
-#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <linux/watchdog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <libsmartcols.h>
@@ -36,6 +38,7 @@
#include "pathnames.h"
#include "strutils.h"
#include "carefulputc.h"
+#include "path.h"
/*
* since 2.6.18
@@ -59,10 +62,6 @@
other external alarm not a reboot */
#endif
-/* basic output flags */
-static int no_headings;
-static int raw;
-
struct wdflag {
uint32_t flag;
const char *name;
@@ -108,8 +107,8 @@ static struct colinfo infos[] = {
static int columns[ARRAY_SIZE(infos) * 2];
static int ncolumns;
-struct wdinfo {
- char *device;
+struct wd_device {
+ const char *devpath;
int timeout;
int timeleft;
@@ -117,12 +116,23 @@ struct wdinfo {
uint32_t status;
uint32_t bstatus;
+ int nowayout;
struct watchdog_info ident;
unsigned int has_timeout : 1,
has_timeleft : 1,
- has_pretimeout : 1;
+ has_pretimeout : 1,
+ has_nowayout : 1;
+};
+
+struct wd_control {
+ unsigned int show_oneline : 1,
+ show_raw : 1,
+ hide_headings : 1,
+ hide_flags : 1,
+ hide_ident : 1,
+ hide_timeouts : 1;
};
/* converts flag name to flag bit */
@@ -165,10 +175,32 @@ static struct colinfo *get_column_info(unsigned num)
return &infos[ get_column_id(num) ];
}
+/* We preffer cdev /dev/watchdog0 as this device has node in
+ * /sys/class/watchdog/. The old miscdev /dev/watchdog is fallback for old
+ * systemds only.
+ */
+static const char *get_default_device(void)
+{
+ const char **p;
+ static const char *devs[] = {
+ "/dev/watchdog0",
+ "/dev/watchdog",
+ NULL
+ };
+
+ for (p = devs; *p; p++) {
+ if (access(*p, F_OK) == 0)
+ return *p;
+ }
+
+ return NULL;
+}
+
static void __attribute__((__noreturn__)) usage(void)
{
FILE *out = stdout;
size_t i;
+ const char *dflt = get_default_device();
fputs(USAGE_HEADER, out);
fprintf(out,
@@ -193,7 +225,10 @@ static void __attribute__((__noreturn__)) usage(void)
printf(USAGE_HELP_OPTIONS(24));
fputs(USAGE_SEPARATOR, out);
- fprintf(out, _("The default device is %s.\n"), _PATH_WATCHDOG_DEV);
+ if (dflt)
+ fprintf(out, _("The default device is %s.\n"), dflt);
+ else
+ fprintf(out, _("No default device is available.\n"));
fputs(USAGE_COLUMNS, out);
for (i = 0; i < ARRAY_SIZE(infos); i++)
@@ -204,7 +239,7 @@ static void __attribute__((__noreturn__)) usage(void)
exit(EXIT_SUCCESS);
}
-static void add_flag_line(struct libscols_table *table, struct wdinfo *wd, const struct wdflag *fl)
+static void add_flag_line(struct libscols_table *table, struct wd_device *wd, const struct wdflag *fl)
{
int i;
struct libscols_line *line;
@@ -232,7 +267,7 @@ static void add_flag_line(struct libscols_table *table, struct wdinfo *wd, const
str = wd->bstatus & fl->flag ? "1" : "0";
break;
case COL_DEVICE:
- str = wd->device;
+ str = wd->devpath;
break;
default:
break;
@@ -245,13 +280,17 @@ static void add_flag_line(struct libscols_table *table, struct wdinfo *wd, const
}
}
-static int show_flags(struct wdinfo *wd, uint32_t wanted)
+static int show_flags(struct wd_control *ctl, struct wd_device *wd, uint32_t wanted)
{
size_t i;
int rc = -1;
struct libscols_table *table;
uint32_t flags;
+ /* information about supported bits is probably missing in /sys */
+ if (!wd->ident.options)
+ return 0;
+
scols_init_debug(0);
/* create output table */
@@ -260,8 +299,8 @@ static int show_flags(struct wdinfo *wd, uint32_t wanted)
warn(_("failed to allocate output table"));
return -1;
}
- scols_table_enable_raw(table, raw);
- scols_table_enable_noheadings(table, no_headings);
+ scols_table_enable_raw(table, ctl->show_raw);
+ scols_table_enable_noheadings(table, ctl->hide_headings);
/* define columns */
for (i = 0; i < (size_t) ncolumns; i++) {
@@ -287,7 +326,7 @@ static int show_flags(struct wdinfo *wd, uint32_t wanted)
}
if (flags)
- warnx(_("%s: unknown flags 0x%x\n"), wd->device, flags);
+ warnx(_("%s: unknown flags 0x%x\n"), wd->devpath, flags);
scols_print_table(table);
rc = 0;
@@ -301,25 +340,25 @@ done:
*
* Don't use err() or exit() here!
*/
-static int set_watchdog(struct wdinfo *wd, int timeout)
+static int set_watchdog(struct wd_device *wd, int timeout)
{
int fd;
sigset_t sigs, oldsigs;
int rc = 0;
- assert(wd->device);
+ assert(wd->devpath);
sigemptyset(&oldsigs);
sigfillset(&sigs);
sigprocmask(SIG_BLOCK, &sigs, &oldsigs);
- fd = open(wd->device, O_WRONLY|O_CLOEXEC);
+ fd = open(wd->devpath, O_WRONLY|O_CLOEXEC);
if (fd < 0) {
if (errno == EBUSY)
warnx(_("%s: watchdog already in use, terminating."),
- wd->device);
- warn(_("cannot open %s"), wd->device);
+ wd->devpath);
+ warn(_("cannot open %s"), wd->devpath);
return -1;
}
@@ -331,7 +370,7 @@ static int set_watchdog(struct wdinfo *wd, int timeout)
if (write(fd, &v, 1) >= 0)
break;
if (errno != EINTR) {
- warn(_("%s: failed to disarm watchdog"), wd->device);
+ warn(_("%s: failed to disarm watchdog"), wd->devpath);
break;
}
/* Let's try hard, since if we don't get this right
@@ -340,7 +379,7 @@ static int set_watchdog(struct wdinfo *wd, int timeout)
if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) != 0) {
rc = errno;
- warn(_("cannot set timeout for %s"), wd->device);
+ warn(_("cannot set timeout for %s"), wd->devpath);
}
if (close(fd))
@@ -358,29 +397,24 @@ static int set_watchdog(struct wdinfo *wd, int timeout)
*
* Don't use err() or exit() here!
*/
-static int read_watchdog(struct wdinfo *wd)
+static int read_watchdog_from_device(struct wd_device *wd)
{
int fd;
sigset_t sigs, oldsigs;
- assert(wd->device);
+ assert(wd->devpath);
sigemptyset(&oldsigs);
sigfillset(&sigs);
sigprocmask(SIG_BLOCK, &sigs, &oldsigs);
- fd = open(wd->device, O_WRONLY|O_CLOEXEC);
+ fd = open(wd->devpath, O_WRONLY|O_CLOEXEC);
- if (fd < 0) {
- if (errno == EBUSY)
- warnx(_("%s: watchdog already in use, terminating."),
- wd->device);
- warn(_("cannot open %s"), wd->device);
- return -1;
- }
+ if (fd < 0)
+ return -errno;
if (ioctl(fd, WDIOC_GETSUPPORT, &wd->ident) < 0)
- warn(_("%s: failed to get information about watchdog"), wd->device);
+ warn(_("%s: failed to get information about watchdog"), wd->devpath);
else {
ioctl(fd, WDIOC_GETSTATUS, &wd->status);
ioctl(fd, WDIOC_GETBOOTSTATUS, &wd->bstatus);
@@ -401,7 +435,7 @@ static int read_watchdog(struct wdinfo *wd)
if (write(fd, &v, 1) >= 0)
break;
if (errno != EINTR) {
- warn(_("%s: failed to disarm watchdog"), wd->device);
+ warn(_("%s: failed to disarm watchdog"), wd->devpath);
break;
}
/* Let's try hard, since if we don't get this right
@@ -415,18 +449,88 @@ static int read_watchdog(struct wdinfo *wd)
return 0;
}
-static void print_oneline(struct wdinfo *wd, uint32_t wanted,
- int noident, int notimeouts, int noflags)
+/* Returns: <0 error, 0 success, 1 unssuported */
+static int read_watchdog_from_sysfs(struct wd_device *wd)
+{
+ struct path_cxt *sys;
+ struct stat st;
+ int rc;
+
+ rc = stat(wd->devpath, &st);
+ if (rc != 0)
+ return rc;
+
+ sys = ul_new_path(_PATH_SYS_DEVCHAR "/%u:%u",
+ major(st.st_rdev), minor(st.st_rdev));
+ if (!sys)
+ return -ENOMEM;
+
+ if (ul_path_get_dirfd(sys) < 0)
+ goto nosysfs; /* device not in /sys */
+
+ if (ul_path_access(sys, F_OK, "identity") != 0)
+ goto nosysfs; /* no info in /sys (old miscdev?) */
+
+ ul_path_read_buffer(sys, (char *) wd->ident.identity, sizeof(wd->ident.identity), "identity");
+
+ ul_path_scanf(sys, "status", "%x", &wd->status);
+ ul_path_read_u32(sys, &wd->bstatus, "bootstatus");
+
+ if (ul_path_read_s32(sys, &wd->nowayout, "nowayout") == 0)
+ wd->has_nowayout = 1;
+ if (ul_path_read_s32(sys, &wd->timeout, "timeout") == 0)
+ wd->has_timeout = 1;
+ if (ul_path_read_s32(sys, &wd->pretimeout, "pretimeout") == 0)
+ wd->has_pretimeout = 1;
+ if (ul_path_read_s32(sys, &wd->timeleft, "timeleft") == 0)
+ wd->has_timeleft = 1;
+
+ ul_unref_path(sys);
+ return 0;
+nosysfs:
+ ul_unref_path(sys);
+ return 1;
+}
+
+static int read_watchdog(struct wd_device *wd)
+{
+ int rc = read_watchdog_from_device(wd);
+
+ if (rc == -EBUSY || rc == -EACCES || rc == -EPERM)
+ rc = read_watchdog_from_sysfs(wd);
+
+ if (rc) {
+ warn(_("cannot read information about %s"), wd->devpath);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void show_timeouts(struct wd_device *wd)
+{
+ if (wd->has_timeout)
+ printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->timeout),
+ _("Timeout:"), wd->timeout);
+ if (wd->has_pretimeout)
+ printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->pretimeout),
+ _("Pre-timeout:"), wd->pretimeout);
+ if (wd->has_timeleft)
+ printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->timeleft),
+ _("Timeleft:"), wd->timeleft);
+}
+
+static void print_oneline(struct wd_control *ctl, struct wd_device *wd, uint32_t wanted)
{
- printf("%s:", wd->device);
+ printf("%s:", wd->devpath);
- if (!noident) {
+ if (!ctl->hide_ident) {
printf(" VERSION=\"%x\"", wd->ident.firmware_version);
printf(" IDENTITY=");
fputs_quoted((char *) wd->ident.identity, stdout);
}
- if (!notimeouts) {
+ if (!ctl->hide_timeouts) {
if (wd->has_timeout)
printf(" TIMEOUT=\"%i\"", wd->timeout);
if (wd->has_pretimeout)
@@ -435,7 +539,7 @@ static void print_oneline(struct wdinfo *wd, uint32_t wanted,
printf(" TIMELEFT=\"%i\"", wd->timeleft);
}
- if (!noflags) {
+ if (!ctl->hide_flags) {
size_t i;
uint32_t flags = wd->ident.options;
@@ -459,26 +563,38 @@ static void print_oneline(struct wdinfo *wd, uint32_t wanted,
fputc('\n', stdout);
}
-static void show_timeouts(struct wdinfo *wd)
+static void print_device(struct wd_control *ctl, struct wd_device *wd, uint32_t wanted)
{
- if (wd->has_timeout)
- printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->timeout),
- _("Timeout:"), wd->timeout);
- if (wd->has_pretimeout)
- printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->pretimeout),
- _("Pre-timeout:"), wd->pretimeout);
- if (wd->has_timeleft)
- printf(P_("%-14s %2i second\n", "%-14s %2i seconds\n", wd->timeleft),
- _("Timeleft:"), wd->timeleft);
+ /* NAME=value one line output */
+ if (ctl->show_oneline) {
+ print_oneline(ctl, wd, wanted);
+ return;
+ }
+
+ /* pretty output */
+ if (!ctl->hide_ident) {
+ printf("%-15s%s\n", _("Device:"), wd->devpath);
+ printf("%-15s%s [%s %x]\n",
+ _("Identity:"),
+ wd->ident.identity,
+ _("version"),
+ wd->ident.firmware_version);
+ }
+ if (!ctl->hide_timeouts)
+ show_timeouts(wd);
+
+ if (!ctl->hide_flags)
+ show_flags(ctl, wd, wanted);
}
int main(int argc, char *argv[])
{
- struct wdinfo wd;
+ struct wd_device wd;
+ struct wd_control ctl = { .hide_headings = 0 };
int c, res = EXIT_SUCCESS, count = 0;
- char noflags = 0, noident = 0, notimeouts = 0, oneline = 0;
uint32_t wanted = 0;
int timeout = 0;
+ const char *dflt_device = NULL;
static const struct option long_opts[] = {
{ "flags", required_argument, NULL, 'f' },
@@ -528,26 +644,26 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
break;
case 'F':
- noflags = 1;
+ ctl.hide_flags = 1;
break;
case 'I':
- noident = 1;
+ ctl.hide_ident = 1;
break;
case 'T':
- notimeouts = 1;
+ ctl.hide_timeouts = 1;
break;
case 'n':
- no_headings = 1;
+ ctl.hide_headings = 1;
break;
case 'r':
- raw = 1;
+ ctl.show_raw = 1;
break;
case 'O':
- oneline = 1;
+ ctl.show_oneline = 1;
break;
case 'x':
- noident = 1;
- notimeouts = 1;
+ ctl.hide_ident = 1;
+ ctl.hide_timeouts = 1;
break;
case 'h':
@@ -567,15 +683,18 @@ int main(int argc, char *argv[])
columns[ncolumns++] = COL_BSTATUS;
}
+ /* Device no specified, use default. */
+ if (optind == argc) {
+ dflt_device = get_default_device();
+ if (!dflt_device)
+ err(EXIT_FAILURE, _("No default device is available."));
+ }
+
do {
int rc;
memset(&wd, 0, sizeof(wd));
-
- if (optind == argc)
- wd.device = _PATH_WATCHDOG_DEV;
- else
- wd.device = argv[optind++];
+ wd.devpath = dflt_device ? dflt_device : argv[optind++];
if (count)
fputc('\n', stdout);
@@ -594,24 +713,8 @@ int main(int argc, char *argv[])
continue;
}
- if (oneline) {
- print_oneline(&wd, wanted, noident, notimeouts, noflags);
- continue;
- }
+ print_device(&ctl, &wd, wanted);
- /* pretty output */
- if (!noident) {
- printf("%-15s%s\n", _("Device:"), wd.device);
- printf("%-15s%s [%s %x]\n",
- _("Identity:"),
- wd.ident.identity,
- _("version"),
- wd.ident.firmware_version);
- }
- if (!notimeouts)
- show_timeouts(&wd);
- if (!noflags)
- show_flags(&wd, wanted);
} while (optind < argc);
return res;