From: Thomas Weißschuh Date: Mon, 11 Dec 2023 20:38:43 +0000 (+0100) Subject: dmesg: support reading kmsg format from file X-Git-Tag: v2.40-rc1~110^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=01c54718fc1634099972f6d2ffe6bce4175bb53a;p=thirdparty%2Futil-linux.git dmesg: support reading kmsg format from file Signed-off-by: Thomas Weißschuh --- diff --git a/sys-utils/dmesg.1.adoc b/sys-utils/dmesg.1.adoc index 6f4941ede0..156ee0896d 100644 --- a/sys-utils/dmesg.1.adoc +++ b/sys-utils/dmesg.1.adoc @@ -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. diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c index a80e1a8cbf..c16bcf7088 100644 --- a/sys-utils/dmesg.c +++ b/sys-utils/dmesg.c @@ -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 use the file instead of the kernel log buffer\n"), out); + fputs(_(" -K, --kmsg-file use the file in kmsg format\n"), out); fputs(_(" -f, --facility 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 index 0000000000..54b5e612d8 --- /dev/null +++ b/tests/expected/dmesg/kmsg-file @@ -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 index 0000000000..a90a91e5ea --- /dev/null +++ b/tests/ts/dmesg/kmsg-file @@ -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 index 0000000000..b000f4c951 Binary files /dev/null and b/tests/ts/dmesg/kmsg-input differ