]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
dmesg: support reading kmsg format from file
authorThomas Weißschuh <thomas@t-8ch.de>
Mon, 11 Dec 2023 20:38:43 +0000 (21:38 +0100)
committerThomas Weißschuh <thomas@t-8ch.de>
Mon, 11 Dec 2023 23:06:38 +0000 (00:06 +0100)
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
sys-utils/dmesg.1.adoc
sys-utils/dmesg.c
tests/expected/dmesg/kmsg-file [new file with mode: 0644]
tests/ts/dmesg/kmsg-file [new file with mode: 0755]
tests/ts/dmesg/kmsg-input [new file with mode: 0644]

index 6f4941ede0ed921846a479ae6022a8c29f6aa270..156ee0896debd73ae9b6608d6c86809d6c450513 100644 (file)
@@ -57,7 +57,7 @@ Enable printing messages to the console.
 Display the local time and the delta in human-readable format. Be aware that conversion to the local time could be inaccurate (see *-T* for more details).
 
 *-F*, *--file* _file_::
-Read the syslog messages from the given _file_. Note that *-F* does not support messages in kmsg format. The old syslog format is supported only.
+Read the syslog messages from the given _file_. Note that *-F* does not support messages in kmsg format. See *-K* instead.
 
 *-f*, *--facility* _list_::
 Restrict output to the given (comma-separated) _list_ of facilities. For example:
@@ -72,6 +72,9 @@ Enable human-readable output. See also *--color*, *--reltime* and *--nopager*.
 *-J*, *--json*::
 Use JSON output format. The time output format is in "sec.usec" format only, log priority level is not decoded by default (use *--decode* to split into facility and priority), the other options to control the output format or time format are silently ignored.
 
+*-K*, *--kmsg-file* _file_::
+Read the /dev/kmsg messages from the given _file_. Different record as expected to be separated by a NULL byte.
+
 *-k*, *--kernel*::
 Print kernel messages.
 
index a80e1a8cbf8e3cc0e75460fb0c849e350a043b05..c16bcf70884c299f9d3c3f0c209fe145f967a1c1 100644 (file)
@@ -245,6 +245,7 @@ struct dmesg_record {
        } while (0)
 
 static int process_kmsg(struct dmesg_control *ctl);
+static int process_kmsg_file(struct dmesg_control *ctl, char **buf);
 
 static int set_level_color(int log_level, const char *mesg, size_t mesgsz)
 {
@@ -296,6 +297,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" -D, --console-off           disable printing messages to console\n"), out);
        fputs(_(" -E, --console-on            enable printing messages to console\n"), out);
        fputs(_(" -F, --file <file>           use the file instead of the kernel log buffer\n"), out);
+       fputs(_(" -K, --kmsg-file <file>      use the file in kmsg format\n"), out);
        fputs(_(" -f, --facility <list>       restrict output to defined facilities\n"), out);
        fputs(_(" -H, --human                 human readable output\n"), out);
        fputs(_(" -J, --json                  use JSON output format\n"), out);
@@ -612,10 +614,13 @@ static ssize_t process_buffer(struct dmesg_control *ctl, char **buf)
                n = read_syslog_buffer(ctl, buf);
                break;
        case DMESG_METHOD_KMSG:
-               /*
-                * Since kernel 3.5.0
-                */
-               n = process_kmsg(ctl);
+               if (ctl->filename)
+                       n = process_kmsg_file(ctl, buf);
+               else
+                       /*
+                        * Since kernel 3.5.0
+                        */
+                       n = process_kmsg(ctl);
                break;
        default:
                abort();        /* impossible method -> drop core */
@@ -1339,6 +1344,40 @@ static int process_kmsg(struct dmesg_control *ctl)
        return 0;
 }
 
+static int process_kmsg_file(struct dmesg_control *ctl, char **buf)
+{
+       char str[sizeof(ctl->kmsg_buf)];
+       struct dmesg_record rec;
+       ssize_t sz;
+       size_t len;
+
+       if (ctl->method != DMESG_METHOD_KMSG || !ctl->filename)
+               return -1;
+
+       sz = mmap_file_buffer(ctl, buf);
+       if (sz == -1)
+               return -1;
+
+       while (sz > 0) {
+               len = strnlen(ctl->mmap_buff, sz);
+               if (len > sizeof(str))
+                       errx(EXIT_FAILURE, _("record too large"));
+
+               memcpy(str, ctl->mmap_buff, len);
+
+               if (parse_kmsg_record(ctl, &rec, str, len) == 0)
+                       print_record(ctl, &rec);
+
+               if (len < (size_t)sz)
+                       len++;
+
+               sz -= len;
+               ctl->mmap_buff += len;
+       }
+
+       return 0;
+}
+
 static int which_time_format(const char *s)
 {
        if (!strcmp(s, "notime"))
@@ -1420,6 +1459,7 @@ int main(int argc, char *argv[])
                { "help",          no_argument,       NULL, 'h' },
                { "json",          no_argument,       NULL, 'J' },
                { "kernel",        no_argument,       NULL, 'k' },
+               { "kmsg-file",     required_argument, NULL, 'K' },
                { "level",         required_argument, NULL, 'l' },
                { "since",         required_argument, NULL, OPT_SINCE },
                { "syslog",        no_argument,       NULL, 'S' },
@@ -1441,6 +1481,7 @@ int main(int argc, char *argv[])
 
        static const ul_excl_t excl[] = {       /* rows and cols in ASCII order */
                { 'C','D','E','c','n','r' },    /* clear,off,on,read-clear,level,raw*/
+               { 'F','K' },                    /* file, kmsg-file */
                { 'H','r' },                    /* human, raw */
                { 'L','r' },                    /* color, raw */
                { 'S','w' },                    /* syslog,follow */
@@ -1458,7 +1499,7 @@ int main(int argc, char *argv[])
        textdomain(PACKAGE);
        close_stdout_atexit();
 
-       while ((c = getopt_long(argc, argv, "CcDdEeF:f:HhJkL::l:n:iPprSs:TtuVWwx",
+       while ((c = getopt_long(argc, argv, "CcDdEeF:f:HhJK:kL::l:n:iPprSs:TtuVWwx",
                                longopts, NULL)) != -1) {
 
                err_exclusive_options(c, longopts, excl, excl_st);
@@ -1486,6 +1527,10 @@ int main(int argc, char *argv[])
                        ctl.filename = optarg;
                        ctl.method = DMESG_METHOD_MMAP;
                        break;
+               case 'K':
+                       ctl.filename = optarg;
+                       ctl.method = DMESG_METHOD_KMSG;
+                       break;
                case 'f':
                        ctl.fltr_fac = 1;
                        if (string_to_bitarray(optarg,
@@ -1637,7 +1682,7 @@ int main(int argc, char *argv[])
        switch (ctl.action) {
        case SYSLOG_ACTION_READ_ALL:
        case SYSLOG_ACTION_READ_CLEAR:
-               if (ctl.method == DMESG_METHOD_KMSG && init_kmsg(&ctl) != 0)
+               if (ctl.method == DMESG_METHOD_KMSG && !ctl.filename && init_kmsg(&ctl) != 0)
                        ctl.method = DMESG_METHOD_SYSLOG;
 
                if (ctl.raw
diff --git a/tests/expected/dmesg/kmsg-file b/tests/expected/dmesg/kmsg-file
new file mode 100644 (file)
index 0000000..54b5e61
--- /dev/null
@@ -0,0 +1,93 @@
+{
+   "dmesg": [
+      {
+         "pri": 5,
+         "time":     0.000000,
+         "msg": "Linux version 6.6.4-arch1-1 (linux@archlinux) (gcc (GCC) 13.2.1 20230801, GNU ld (GNU Binutils) 2.41.0) #1 SMP PREEMPT_DYNAMIC Mon, 04 Dec 2023 00:29:19 +0000"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "Command line: initrd=\\ucode.img initrd=\\initramfs-linux.img rw cryptdevice=/dev/nvme0n1p3:system:discard root=/dev/mapper/system"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-provided physical RAM map:"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x000000000009f000-0x00000000000bffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000000100000-0x0000000009afffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000009b00000-0x0000000009dfffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000009e00000-0x0000000009efffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000009f00000-0x0000000009f3bfff] ACPI NVS"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000009f3c000-0x000000004235ffff] usable"
+      },{
+         "pri": 6,
+         "time":     0.000000,
+         "msg": "BIOS-e820: [mem 0x0000000042360000-0x000000004455ffff] reserved"
+      },{
+         "pri": 6,
+         "time":     0.367657,
+         "msg": "ACPI: \\_SB_.PCI0.GP19.NHI1.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.368615,
+         "msg": "ACPI: \\_SB_.PCI0.GP19.XHC4.PWRS: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376316,
+         "msg": "ACPI: \\_SB_.PRWL: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.376343,
+         "msg": "ACPI: \\_SB_.PRWB: New power resource"
+      },{
+         "pri": 6,
+         "time":     0.377373,
+         "msg": "ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])"
+      },{
+         "pri": 6,
+         "time":     0.377378,
+         "msg": "acpi PNP0A08:00: _OSC: OS supports [ExtendedConfig ASPM ClockPM Segments MSI EDR HPX-Type3]"
+      },{
+         "pri": 6,
+         "time":     0.377569,
+         "msg": "acpi PNP0A08:00: _OSC: platform does not support [SHPCHotplug AER]"
+      },{
+         "pri": 6,
+         "time":     0.377933,
+         "msg": "acpi PNP0A08:00: _OSC: OS now controls [PCIeHotplug PME PCIeCapability LTR DPC]"
+      },{
+         "pri": 6,
+         "time":     0.378458,
+         "msg": "PCI host bridge to bus 0000:00"
+      },{
+         "pri": 6,
+         "time":     0.378459,
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]"
+      },{
+         "pri": 6,
+         "time":     0.378461,
+         "msg": "pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]"
+      }
+   ]
+}
diff --git a/tests/ts/dmesg/kmsg-file b/tests/ts/dmesg/kmsg-file
new file mode 100755 (executable)
index 0000000..a90a91e
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="kmsg-file"
+
+. "$TS_TOPDIR"/functions.sh
+ts_init "$*"
+
+ts_check_test_command "$TS_HELPER_DMESG"
+
+export TZ="GMT"
+export DMESG_TEST_BOOTIME="1234567890.123456"
+
+$TS_HELPER_DMESG -J -K $TS_SELF/kmsg-input >> $TS_OUTPUT 2>/dev/null
+
+ts_finalize
diff --git a/tests/ts/dmesg/kmsg-input b/tests/ts/dmesg/kmsg-input
new file mode 100644 (file)
index 0000000..b000f4c
Binary files /dev/null and b/tests/ts/dmesg/kmsg-input differ