diff --git a/Cargo.lock b/Cargo.lock index 1d79b6f..da6a312 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,6 +880,7 @@ dependencies = [ "tempfile", "textwrap", "uu_ctrlaltdel", + "uu_dmesg", "uu_last", "uu_lscpu", "uu_lsmem", @@ -898,6 +899,17 @@ dependencies = [ "uucore", ] +[[package]] +name = "uu_dmesg" +version = "0.0.1" +dependencies = [ + "clap", + "regex", + "serde", + "serde_json", + "uucore", +] + [[package]] name = "uu_last" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index 22bf40d..88c5e32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,8 @@ feat_common_core = [ "ctrlaltdel", "rev", "setsid", - "last" + "last", + "dmesg" ] [workspace.dependencies] @@ -72,6 +73,7 @@ ctrlaltdel = { optional = true, version = "0.0.1", package = "uu_ctrlaltdel", pa rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" } setsid = { optional = true, version = "0.0.1", package = "uu_setsid", path ="src/uu/setsid" } last = { optional = true, version = "0.0.1", package = "uu_last", path = "src/uu/last" } +dmesg = { optional = true, version = "0.0.1", package = "uu_dmesg", path = "src/uu/dmesg" } [dev-dependencies] pretty_assertions = "1" diff --git a/src/uu/dmesg/Cargo.toml b/src/uu/dmesg/Cargo.toml new file mode 100644 index 0000000..96df1cc --- /dev/null +++ b/src/uu/dmesg/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "uu_dmesg" +version = "0.0.1" +edition = "2021" + +[lib] +path = "src/dmesg.rs" + +[[bin]] +name = "dmesg" +path = "src/main.rs" + +[dependencies] +clap = { workspace = true } +uucore = { workspace = true } +regex = { workspace = true } +serde_json = { workspace = true } +serde = { workspace = true } diff --git a/src/uu/dmesg/dmesg.md b/src/uu/dmesg/dmesg.md new file mode 100644 index 0000000..25b1522 --- /dev/null +++ b/src/uu/dmesg/dmesg.md @@ -0,0 +1,7 @@ +# dmesg + +``` +dmesg [options] +``` + +Display or control the kernel ring buffer. diff --git a/src/uu/dmesg/src/dmesg.rs b/src/uu/dmesg/src/dmesg.rs new file mode 100644 index 0000000..8fb64f7 --- /dev/null +++ b/src/uu/dmesg/src/dmesg.rs @@ -0,0 +1,153 @@ +// This file is part of the uutils util-linux package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +use clap::{crate_version, Arg, ArgAction, Command}; +use regex::Regex; +use std::fs; +use uucore::{ + error::{FromIo, UResult, USimpleError}, + format_usage, help_about, help_usage, +}; + +mod json; + +const ABOUT: &str = help_about!("dmesg.md"); +const USAGE: &str = help_usage!("dmesg.md"); + +#[uucore::main] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let mut dmesg = Dmesg::new(); + let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?; + if let Some(kmsg_file) = matches.get_one::(options::KMSG_FILE) { + dmesg.kmsg_file = kmsg_file; + } + if matches.get_flag(options::JSON) { + dmesg.output_format = OutputFormat::Json; + } + dmesg.parse()?.print(); + Ok(()) +} + +pub fn uu_app() -> Command { + Command::new(uucore::util_name()) + .override_usage(format_usage(USAGE)) + .about(ABOUT) + .version(crate_version!()) + .arg( + Arg::new(options::KMSG_FILE) + .short('K') + .long("kmsg-file") + .help("use the file in kmsg format") + .action(ArgAction::Set), + ) + .arg( + Arg::new(options::JSON) + .short('J') + .long("json") + .help("use JSON output format") + .action(ArgAction::SetTrue), + ) +} + +mod options { + pub const KMSG_FILE: &str = "kmsg-file"; + pub const JSON: &str = "json"; +} + +struct Dmesg<'a> { + kmsg_file: &'a str, + output_format: OutputFormat, + records: Option>, +} + +impl Dmesg<'_> { + fn new() -> Self { + Dmesg { + kmsg_file: "/dev/kmsg", + output_format: OutputFormat::Normal, + records: None, + } + } + + fn parse(mut self) -> UResult { + let mut records = vec![]; + let re = Self::record_regex(); + let lines = self.read_lines_from_kmsg_file()?; + for line in lines { + for (_, [pri_fac, seq, time, msg]) in re.captures_iter(&line).map(|c| c.extract()) { + records.push(Record::from_str_fields( + pri_fac, + seq, + time, + msg.to_string(), + )?); + } + } + self.records = Some(records); + Ok(self) + } + + fn record_regex() -> Regex { + let valid_number_pattern = "0|[1-9][0-9]*"; + let additional_fields_pattern = ",^[,;]*"; + let record_pattern = format!( + "(?m)^({0}),({0}),({0}),.(?:{1})*;(.*)$", + valid_number_pattern, additional_fields_pattern + ); + Regex::new(&record_pattern).expect("invalid regex.") + } + + fn read_lines_from_kmsg_file(&self) -> UResult> { + let kmsg_bytes = fs::read(self.kmsg_file) + .map_err_context(|| format!("cannot open {}", self.kmsg_file))?; + let lines = kmsg_bytes + .split(|&byte| byte == 0) + .map(|line| String::from_utf8_lossy(line).to_string()) + .collect(); + Ok(lines) + } + + fn print(&self) { + match self.output_format { + OutputFormat::Json => self.print_json(), + OutputFormat::Normal => unimplemented!(), + } + } + + fn print_json(&self) { + if let Some(records) = &self.records { + println!("{}", json::serialize_records(records)); + } + } +} + +enum OutputFormat { + Normal, + Json, +} + +struct Record { + priority_facility: u32, + _sequence: u64, + timestamp_us: u64, + message: String, +} + +impl Record { + fn from_str_fields(pri_fac: &str, seq: &str, time: &str, msg: String) -> UResult { + let pri_fac = str::parse(pri_fac); + let seq = str::parse(seq); + let time = str::parse(time); + match (pri_fac, seq, time) { + (Ok(pri_fac), Ok(seq), Ok(time)) => Ok(Record { + priority_facility: pri_fac, + _sequence: seq, + timestamp_us: time, + message: msg, + }), + _ => Err(USimpleError::new(1, "Failed to parse record field(s)")), + } + } +} diff --git a/src/uu/dmesg/src/json.rs b/src/uu/dmesg/src/json.rs new file mode 100644 index 0000000..672d515 --- /dev/null +++ b/src/uu/dmesg/src/json.rs @@ -0,0 +1,142 @@ +// This file is part of the uutils util-linux package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +use serde::Serialize; +use std::io; + +pub fn serialize_records(records: &Vec) -> String { + let json = Dmesg::from(records); + let formatter = DmesgFormatter::new(); + let mut buf = vec![]; + let mut serializer = serde_json::Serializer::with_formatter(&mut buf, formatter); + json.serialize(&mut serializer).unwrap(); + String::from_utf8_lossy(&buf).to_string() +} + +#[derive(serde::Serialize)] +struct Dmesg<'a> { + dmesg: Vec>, +} + +#[derive(serde::Serialize)] +struct Record<'a> { + pri: u32, + time: u64, + msg: &'a str, +} + +impl<'a> From<&'a Vec> for Dmesg<'a> { + fn from(value: &'a Vec) -> Self { + let mut dmesg_json = Dmesg { dmesg: vec![] }; + for record in value { + let record_json = Record { + pri: record.priority_facility, + time: record.timestamp_us, + msg: &record.message, + }; + dmesg_json.dmesg.push(record_json); + } + dmesg_json + } +} + +struct DmesgFormatter { + nesting_depth: i32, +} + +impl DmesgFormatter { + const SINGLE_INDENTATION: &[u8] = b" "; + + fn new() -> Self { + DmesgFormatter { nesting_depth: 0 } + } + + fn write_indentation(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + for _ in 0..self.nesting_depth { + writer.write_all(Self::SINGLE_INDENTATION)?; + } + Ok(()) + } +} + +impl serde_json::ser::Formatter for DmesgFormatter { + fn begin_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.nesting_depth += 1; + writer.write_all(b"{\n") + } + + fn end_object(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"\n")?; + self.nesting_depth -= 1; + self.write_indentation(writer)?; + writer.write_all(b"}") + } + + fn begin_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.nesting_depth += 1; + writer.write_all(b"[\n") + } + + fn end_array(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b"\n")?; + self.nesting_depth -= 1; + self.write_indentation(writer)?; + writer.write_all(b"]") + } + + fn begin_object_key(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + if !first { + writer.write_all(b",\n")?; + } + self.write_indentation(writer) + } + + fn begin_object_value(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + writer.write_all(b": ") + } + + fn begin_array_value(&mut self, writer: &mut W, first: bool) -> io::Result<()> + where + W: ?Sized + io::Write, + { + if first { + self.write_indentation(writer) + } else { + writer.write_all(b",") + } + } + + fn write_u64(&mut self, writer: &mut W, value: u64) -> io::Result<()> + where + W: ?Sized + io::Write, + { + // The only u64 field in Dmesg is time, which requires a specific format + let seconds = value / 1000000; + let sub_seconds = value % 1000000; + let repr = format!("{:>5}.{:0>6}", seconds, sub_seconds); + writer.write_all(repr.as_bytes()) + } +} diff --git a/src/uu/dmesg/src/main.rs b/src/uu/dmesg/src/main.rs new file mode 100644 index 0000000..902d5bf --- /dev/null +++ b/src/uu/dmesg/src/main.rs @@ -0,0 +1 @@ +uucore::bin!(uu_dmesg); diff --git a/tests/by-util/test_dmesg.rs b/tests/by-util/test_dmesg.rs new file mode 100644 index 0000000..08e398a --- /dev/null +++ b/tests/by-util/test_dmesg.rs @@ -0,0 +1,32 @@ +// This file is part of the uutils util-linux package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. +use crate::common::util::TestScenario; + +#[test] +fn test_invalid_arg() { + new_ucmd!().arg("--definitely-invalid").fails().code_is(1); +} + +#[test] +fn test_kmsg_nonexistent_file() { + new_ucmd!() + .arg("--kmsg-file") + .arg("definitely-nonexistent-file") + .fails() + .code_is(1) + .no_stdout() + .stderr_is("dmesg: cannot open definitely-nonexistent-file: No such file or directory\n"); +} + +#[test] +fn test_kmsg_json() { + new_ucmd!() + .arg("--kmsg-file") + .arg("kmsg.input") + .arg("--json") + .run() + .no_stderr() + .stdout_is_templated_fixture("test_kmsg_json.expected", &[("\r\n", "\n")]); +} diff --git a/tests/fixtures/dmesg/kmsg.input b/tests/fixtures/dmesg/kmsg.input new file mode 100644 index 0000000..a6468dc Binary files /dev/null and b/tests/fixtures/dmesg/kmsg.input differ diff --git a/tests/fixtures/dmesg/test_kmsg_json.expected b/tests/fixtures/dmesg/test_kmsg_json.expected new file mode 100644 index 0000000..fda2510 --- /dev/null +++ b/tests/fixtures/dmesg/test_kmsg_json.expected @@ -0,0 +1,645 @@ +{ + "dmesg": [ + { + "pri": 32, + "time": 0.000000, + "msg": "LOG_EMERG LOG_AUTH" + },{ + "pri": 80, + "time": 1000.000000, + "msg": "LOG_EMERG LOG_AUTHPRIV" + },{ + "pri": 72, + "time": 2000.000000, + "msg": "LOG_EMERG LOG_CRON" + },{ + "pri": 24, + "time": 3000.000000, + "msg": "LOG_EMERG LOG_DAEMON" + },{ + "pri": 88, + "time": 4000.000000, + "msg": "LOG_EMERG LOG_FTP" + },{ + "pri": 0, + "time": 5000.000000, + "msg": "LOG_EMERG LOG_KERN" + },{ + "pri": 128, + "time": 6000.000000, + "msg": "LOG_EMERG LOG_LOCAL0" + },{ + "pri": 136, + "time": 7000.000000, + "msg": "LOG_EMERG LOG_LOCAL1" + },{ + "pri": 144, + "time": 8000.000000, + "msg": "LOG_EMERG LOG_LOCAL2" + },{ + "pri": 152, + "time": 9000.000000, + "msg": "LOG_EMERG LOG_LOCAL3" + },{ + "pri": 160, + "time": 10000.000000, + "msg": "LOG_EMERG LOG_LOCAL4" + },{ + "pri": 168, + "time": 11000.000000, + "msg": "LOG_EMERG LOG_LOCAL5" + },{ + "pri": 176, + "time": 12000.000000, + "msg": "LOG_EMERG LOG_LOCAL6" + },{ + "pri": 184, + "time": 13000.000000, + "msg": "LOG_EMERG LOG_LOCAL7" + },{ + "pri": 48, + "time": 14000.000000, + "msg": "LOG_EMERG LOG_LPR" + },{ + "pri": 16, + "time": 15000.000000, + "msg": "LOG_EMERG LOG_MAIL" + },{ + "pri": 56, + "time": 16000.000000, + "msg": "LOG_EMERG LOG_NEWS" + },{ + "pri": 40, + "time": 17000.000000, + "msg": "LOG_EMERG LOG_SYSLOG" + },{ + "pri": 8, + "time": 18000.000000, + "msg": "LOG_EMERG LOG_USER" + },{ + "pri": 64, + "time": 19000.000000, + "msg": "LOG_EMERG LOG_UUCP" + },{ + "pri": 33, + "time": 20000.000000, + "msg": "LOG_ALERT LOG_AUTH" + },{ + "pri": 81, + "time": 21000.000000, + "msg": "LOG_ALERT LOG_AUTHPRIV" + },{ + "pri": 73, + "time": 22000.000000, + "msg": "LOG_ALERT LOG_CRON" + },{ + "pri": 25, + "time": 23000.000000, + "msg": "LOG_ALERT LOG_DAEMON" + },{ + "pri": 89, + "time": 24000.000000, + "msg": "LOG_ALERT LOG_FTP" + },{ + "pri": 1, + "time": 25000.000000, + "msg": "LOG_ALERT LOG_KERN" + },{ + "pri": 129, + "time": 26000.000000, + "msg": "LOG_ALERT LOG_LOCAL0" + },{ + "pri": 137, + "time": 27000.000000, + "msg": "LOG_ALERT LOG_LOCAL1" + },{ + "pri": 145, + "time": 28000.000000, + "msg": "LOG_ALERT LOG_LOCAL2" + },{ + "pri": 153, + "time": 29000.000000, + "msg": "LOG_ALERT LOG_LOCAL3" + },{ + "pri": 161, + "time": 30000.000000, + "msg": "LOG_ALERT LOG_LOCAL4" + },{ + "pri": 169, + "time": 31000.000000, + "msg": "LOG_ALERT LOG_LOCAL5" + },{ + "pri": 177, + "time": 32000.000000, + "msg": "LOG_ALERT LOG_LOCAL6" + },{ + "pri": 185, + "time": 33000.000000, + "msg": "LOG_ALERT LOG_LOCAL7" + },{ + "pri": 49, + "time": 34000.000000, + "msg": "LOG_ALERT LOG_LPR" + },{ + "pri": 17, + "time": 35000.000000, + "msg": "LOG_ALERT LOG_MAIL" + },{ + "pri": 57, + "time": 36000.000000, + "msg": "LOG_ALERT LOG_NEWS" + },{ + "pri": 41, + "time": 37000.000000, + "msg": "LOG_ALERT LOG_SYSLOG" + },{ + "pri": 9, + "time": 38000.000000, + "msg": "LOG_ALERT LOG_USER" + },{ + "pri": 65, + "time": 39000.000000, + "msg": "LOG_ALERT LOG_UUCP" + },{ + "pri": 34, + "time": 40000.000000, + "msg": "LOG_CRIT LOG_AUTH" + },{ + "pri": 82, + "time": 41000.000000, + "msg": "LOG_CRIT LOG_AUTHPRIV" + },{ + "pri": 74, + "time": 42000.000000, + "msg": "LOG_CRIT LOG_CRON" + },{ + "pri": 26, + "time": 43000.000000, + "msg": "LOG_CRIT LOG_DAEMON" + },{ + "pri": 90, + "time": 44000.000000, + "msg": "LOG_CRIT LOG_FTP" + },{ + "pri": 2, + "time": 45000.000000, + "msg": "LOG_CRIT LOG_KERN" + },{ + "pri": 130, + "time": 46000.000000, + "msg": "LOG_CRIT LOG_LOCAL0" + },{ + "pri": 138, + "time": 47000.000000, + "msg": "LOG_CRIT LOG_LOCAL1" + },{ + "pri": 146, + "time": 48000.000000, + "msg": "LOG_CRIT LOG_LOCAL2" + },{ + "pri": 154, + "time": 49000.000000, + "msg": "LOG_CRIT LOG_LOCAL3" + },{ + "pri": 162, + "time": 50000.000000, + "msg": "LOG_CRIT LOG_LOCAL4" + },{ + "pri": 170, + "time": 51000.000000, + "msg": "LOG_CRIT LOG_LOCAL5" + },{ + "pri": 178, + "time": 52000.000000, + "msg": "LOG_CRIT LOG_LOCAL6" + },{ + "pri": 186, + "time": 53000.000000, + "msg": "LOG_CRIT LOG_LOCAL7" + },{ + "pri": 50, + "time": 54000.000000, + "msg": "LOG_CRIT LOG_LPR" + },{ + "pri": 18, + "time": 55000.000000, + "msg": "LOG_CRIT LOG_MAIL" + },{ + "pri": 58, + "time": 56000.000000, + "msg": "LOG_CRIT LOG_NEWS" + },{ + "pri": 42, + "time": 57000.000000, + "msg": "LOG_CRIT LOG_SYSLOG" + },{ + "pri": 10, + "time": 58000.000000, + "msg": "LOG_CRIT LOG_USER" + },{ + "pri": 66, + "time": 59000.000000, + "msg": "LOG_CRIT LOG_UUCP" + },{ + "pri": 35, + "time": 60000.000000, + "msg": "LOG_ERR LOG_AUTH" + },{ + "pri": 83, + "time": 61000.000000, + "msg": "LOG_ERR LOG_AUTHPRIV" + },{ + "pri": 75, + "time": 62000.000000, + "msg": "LOG_ERR LOG_CRON" + },{ + "pri": 27, + "time": 63000.000000, + "msg": "LOG_ERR LOG_DAEMON" + },{ + "pri": 91, + "time": 64000.000000, + "msg": "LOG_ERR LOG_FTP" + },{ + "pri": 3, + "time": 65000.000000, + "msg": "LOG_ERR LOG_KERN" + },{ + "pri": 131, + "time": 66000.000000, + "msg": "LOG_ERR LOG_LOCAL0" + },{ + "pri": 139, + "time": 67000.000000, + "msg": "LOG_ERR LOG_LOCAL1" + },{ + "pri": 147, + "time": 68000.000000, + "msg": "LOG_ERR LOG_LOCAL2" + },{ + "pri": 155, + "time": 69000.000000, + "msg": "LOG_ERR LOG_LOCAL3" + },{ + "pri": 163, + "time": 70000.000000, + "msg": "LOG_ERR LOG_LOCAL4" + },{ + "pri": 171, + "time": 71000.000000, + "msg": "LOG_ERR LOG_LOCAL5" + },{ + "pri": 179, + "time": 72000.000000, + "msg": "LOG_ERR LOG_LOCAL6" + },{ + "pri": 187, + "time": 73000.000000, + "msg": "LOG_ERR LOG_LOCAL7" + },{ + "pri": 51, + "time": 74000.000000, + "msg": "LOG_ERR LOG_LPR" + },{ + "pri": 19, + "time": 75000.000000, + "msg": "LOG_ERR LOG_MAIL" + },{ + "pri": 59, + "time": 76000.000000, + "msg": "LOG_ERR LOG_NEWS" + },{ + "pri": 43, + "time": 77000.000000, + "msg": "LOG_ERR LOG_SYSLOG" + },{ + "pri": 11, + "time": 78000.000000, + "msg": "LOG_ERR LOG_USER" + },{ + "pri": 67, + "time": 79000.000000, + "msg": "LOG_ERR LOG_UUCP" + },{ + "pri": 36, + "time": 80000.000000, + "msg": "LOG_WARNING LOG_AUTH" + },{ + "pri": 84, + "time": 81000.000000, + "msg": "LOG_WARNING LOG_AUTHPRIV" + },{ + "pri": 76, + "time": 82000.000000, + "msg": "LOG_WARNING LOG_CRON" + },{ + "pri": 28, + "time": 83000.000000, + "msg": "LOG_WARNING LOG_DAEMON" + },{ + "pri": 92, + "time": 84000.000000, + "msg": "LOG_WARNING LOG_FTP" + },{ + "pri": 4, + "time": 85000.000000, + "msg": "LOG_WARNING LOG_KERN" + },{ + "pri": 132, + "time": 86000.000000, + "msg": "LOG_WARNING LOG_LOCAL0" + },{ + "pri": 140, + "time": 87000.000000, + "msg": "LOG_WARNING LOG_LOCAL1" + },{ + "pri": 148, + "time": 88000.000000, + "msg": "LOG_WARNING LOG_LOCAL2" + },{ + "pri": 156, + "time": 89000.000000, + "msg": "LOG_WARNING LOG_LOCAL3" + },{ + "pri": 164, + "time": 90000.000000, + "msg": "LOG_WARNING LOG_LOCAL4" + },{ + "pri": 172, + "time": 91000.000000, + "msg": "LOG_WARNING LOG_LOCAL5" + },{ + "pri": 180, + "time": 92000.000000, + "msg": "LOG_WARNING LOG_LOCAL6" + },{ + "pri": 188, + "time": 93000.000000, + "msg": "LOG_WARNING LOG_LOCAL7" + },{ + "pri": 52, + "time": 94000.000000, + "msg": "LOG_WARNING LOG_LPR" + },{ + "pri": 20, + "time": 95000.000000, + "msg": "LOG_WARNING LOG_MAIL" + },{ + "pri": 60, + "time": 96000.000000, + "msg": "LOG_WARNING LOG_NEWS" + },{ + "pri": 44, + "time": 97000.000000, + "msg": "LOG_WARNING LOG_SYSLOG" + },{ + "pri": 12, + "time": 98000.000000, + "msg": "LOG_WARNING LOG_USER" + },{ + "pri": 68, + "time": 99000.000000, + "msg": "LOG_WARNING LOG_UUCP" + },{ + "pri": 37, + "time": 100000.000000, + "msg": "LOG_NOTICE LOG_AUTH" + },{ + "pri": 85, + "time": 101000.000000, + "msg": "LOG_NOTICE LOG_AUTHPRIV" + },{ + "pri": 77, + "time": 102000.000000, + "msg": "LOG_NOTICE LOG_CRON" + },{ + "pri": 29, + "time": 103000.000000, + "msg": "LOG_NOTICE LOG_DAEMON" + },{ + "pri": 93, + "time": 104000.000000, + "msg": "LOG_NOTICE LOG_FTP" + },{ + "pri": 5, + "time": 105000.000000, + "msg": "LOG_NOTICE LOG_KERN" + },{ + "pri": 133, + "time": 106000.000000, + "msg": "LOG_NOTICE LOG_LOCAL0" + },{ + "pri": 141, + "time": 107000.000000, + "msg": "LOG_NOTICE LOG_LOCAL1" + },{ + "pri": 149, + "time": 108000.000000, + "msg": "LOG_NOTICE LOG_LOCAL2" + },{ + "pri": 157, + "time": 109000.000000, + "msg": "LOG_NOTICE LOG_LOCAL3" + },{ + "pri": 165, + "time": 110000.000000, + "msg": "LOG_NOTICE LOG_LOCAL4" + },{ + "pri": 173, + "time": 111000.000000, + "msg": "LOG_NOTICE LOG_LOCAL5" + },{ + "pri": 181, + "time": 112000.000000, + "msg": "LOG_NOTICE LOG_LOCAL6" + },{ + "pri": 189, + "time": 113000.000000, + "msg": "LOG_NOTICE LOG_LOCAL7" + },{ + "pri": 53, + "time": 114000.000000, + "msg": "LOG_NOTICE LOG_LPR" + },{ + "pri": 21, + "time": 115000.000000, + "msg": "LOG_NOTICE LOG_MAIL" + },{ + "pri": 61, + "time": 116000.000000, + "msg": "LOG_NOTICE LOG_NEWS" + },{ + "pri": 45, + "time": 117000.000000, + "msg": "LOG_NOTICE LOG_SYSLOG" + },{ + "pri": 13, + "time": 118000.000000, + "msg": "LOG_NOTICE LOG_USER" + },{ + "pri": 69, + "time": 119000.000000, + "msg": "LOG_NOTICE LOG_UUCP" + },{ + "pri": 38, + "time": 120000.000000, + "msg": "LOG_INFO LOG_AUTH" + },{ + "pri": 86, + "time": 121000.000000, + "msg": "LOG_INFO LOG_AUTHPRIV" + },{ + "pri": 78, + "time": 122000.000000, + "msg": "LOG_INFO LOG_CRON" + },{ + "pri": 30, + "time": 123000.000000, + "msg": "LOG_INFO LOG_DAEMON" + },{ + "pri": 94, + "time": 124000.000000, + "msg": "LOG_INFO LOG_FTP" + },{ + "pri": 6, + "time": 125000.000000, + "msg": "LOG_INFO LOG_KERN" + },{ + "pri": 134, + "time": 126000.000000, + "msg": "LOG_INFO LOG_LOCAL0" + },{ + "pri": 142, + "time": 127000.000000, + "msg": "LOG_INFO LOG_LOCAL1" + },{ + "pri": 150, + "time": 128000.000000, + "msg": "LOG_INFO LOG_LOCAL2" + },{ + "pri": 158, + "time": 129000.000000, + "msg": "LOG_INFO LOG_LOCAL3" + },{ + "pri": 166, + "time": 130000.000000, + "msg": "LOG_INFO LOG_LOCAL4" + },{ + "pri": 174, + "time": 131000.000000, + "msg": "LOG_INFO LOG_LOCAL5" + },{ + "pri": 182, + "time": 132000.000000, + "msg": "LOG_INFO LOG_LOCAL6" + },{ + "pri": 190, + "time": 133000.000000, + "msg": "LOG_INFO LOG_LOCAL7" + },{ + "pri": 54, + "time": 134000.000000, + "msg": "LOG_INFO LOG_LPR" + },{ + "pri": 22, + "time": 135000.000000, + "msg": "LOG_INFO LOG_MAIL" + },{ + "pri": 62, + "time": 136000.000000, + "msg": "LOG_INFO LOG_NEWS" + },{ + "pri": 46, + "time": 137000.000000, + "msg": "LOG_INFO LOG_SYSLOG" + },{ + "pri": 14, + "time": 138000.000000, + "msg": "LOG_INFO LOG_USER" + },{ + "pri": 70, + "time": 139000.000000, + "msg": "LOG_INFO LOG_UUCP" + },{ + "pri": 39, + "time": 140000.000000, + "msg": "LOG_DEBUG LOG_AUTH" + },{ + "pri": 87, + "time": 141000.000000, + "msg": "LOG_DEBUG LOG_AUTHPRIV" + },{ + "pri": 79, + "time": 142000.000000, + "msg": "LOG_DEBUG LOG_CRON" + },{ + "pri": 31, + "time": 143000.000000, + "msg": "LOG_DEBUG LOG_DAEMON" + },{ + "pri": 95, + "time": 144000.000000, + "msg": "LOG_DEBUG LOG_FTP" + },{ + "pri": 7, + "time": 145000.000000, + "msg": "LOG_DEBUG LOG_KERN" + },{ + "pri": 135, + "time": 146000.000000, + "msg": "LOG_DEBUG LOG_LOCAL0" + },{ + "pri": 143, + "time": 147000.000000, + "msg": "LOG_DEBUG LOG_LOCAL1" + },{ + "pri": 151, + "time": 148000.000000, + "msg": "LOG_DEBUG LOG_LOCAL2" + },{ + "pri": 159, + "time": 149000.000000, + "msg": "LOG_DEBUG LOG_LOCAL3" + },{ + "pri": 167, + "time": 150000.000000, + "msg": "LOG_DEBUG LOG_LOCAL4" + },{ + "pri": 175, + "time": 151000.000000, + "msg": "LOG_DEBUG LOG_LOCAL5" + },{ + "pri": 183, + "time": 152000.000000, + "msg": "LOG_DEBUG LOG_LOCAL6" + },{ + "pri": 191, + "time": 153000.000000, + "msg": "LOG_DEBUG LOG_LOCAL7" + },{ + "pri": 55, + "time": 154000.000000, + "msg": "LOG_DEBUG LOG_LPR" + },{ + "pri": 23, + "time": 155000.000000, + "msg": "LOG_DEBUG LOG_MAIL" + },{ + "pri": 63, + "time": 156000.000000, + "msg": "LOG_DEBUG LOG_NEWS" + },{ + "pri": 47, + "time": 157000.000000, + "msg": "LOG_DEBUG LOG_SYSLOG" + },{ + "pri": 15, + "time": 158000.000000, + "msg": "LOG_DEBUG LOG_USER" + },{ + "pri": 71, + "time": 159000.000000, + "msg": "LOG_DEBUG LOG_UUCP" + } + ] +} diff --git a/tests/tests.rs b/tests/tests.rs index 64cfc84..4532383 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -32,3 +32,7 @@ mod test_setsid; #[cfg(feature = "last")] #[path = "by-util/test_last.rs"] mod test_last; + +#[cfg(feature = "dmesg")] +#[path = "by-util/test_dmesg.rs"] +mod test_dmesg;