]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
dmesg: fix console-level off-by-one
authorBjørn Mork <bjorn@mork.no>
Mon, 1 Oct 2012 23:54:49 +0000 (01:54 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 2 Oct 2012 09:43:10 +0000 (11:43 +0200)
  commit f06ec64f dmesg; support level names (e.g. --console-level=alert)

introduced an off-by-one error.  The kernel will print messages with
a *higher* level than the console-level. The bug made it impossible to
set the level for debugging, like it is documented in e.g
Documentation/networking/netconsole.txt :

 nemi:/tmp# dmesg -n 8
 dmesg: unknown level '8'

And attempting to set the "emerg" level would result in an invalid 0 value:

 nemi:/tmp# dmesg -n emerg
 dmesg: klogctl failed: Invalid argument

Restoring the old behaviour for numeric levels, and mapping the level
names so that "dmesg -n debug" behaves as expected: logging everything
at level "debug" and higher.

[kzak@redhat.com: - add comment to parse_level()]

Signed-off-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/dmesg.c

index 0ee03eebaef4b8a8e732e354e298e7de6525598b..4c85f9fceaf28194c82d3817a4823ae785afaea8 100644 (file)
@@ -227,24 +227,36 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
 
 /*
  * LEVEL     ::= <number> | <name>
- *  <number> ::= number in range <0..N>, where N < ARRAY_SIZE(level_names)
+ *  <number> ::= @len is set:  number in range <0..N>, where N < ARRAY_SIZE(level_names)
+ *           ::= @len not set: number in range <1..N>, where N <= ARRAY_SIZE(level_names)
  *  <name>   ::= case-insensitive text
+ *
+ *  Note that @len argument is not set when parsing "-n <level>" command line
+ *  option. The console_level is intepreted as "log level less than the value".
+ *
+ *  For example "dmesg -n 8" or "dmesg -n debug" enables debug console log
+ *  level by klogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL, 8). The @str argument
+ *  has to be parsed to number in range <1..8>.
  */
 static int parse_level(const char *str, size_t len)
 {
+       int offset = 0;
+
        if (!str)
                return -1;
-       if (!len)
+       if (!len) {
                len = strlen(str);
+               offset = 1;
+       }
        errno = 0;
 
        if (isdigit(*str)) {
                char *end = NULL;
-               long x = strtol(str, &end, 10);
+               long x = strtol(str, &end, 10) - offset;
 
                if (!errno && end && end > str && (size_t) (end - str) == len &&
                    x >= 0 && (size_t) x < ARRAY_SIZE(level_names))
-                       return x;
+                       return x + offset;
        } else {
                size_t i;
 
@@ -252,7 +264,7 @@ static int parse_level(const char *str, size_t len)
                        const char *n = level_names[i].name;
 
                        if (strncasecmp(str, n, len) == 0 && *(n + len) == '\0')
-                               return i;
+                               return i + offset;
                }
        }