From daf3d631501373c279d7f5a9d71f40a4c89242dc Mon Sep 17 00:00:00 2001 From: Yang Hau Date: Tue, 27 Aug 2024 20:05:13 +0800 Subject: [PATCH] dmesg: Add basic impl --- Cargo.lock | 35 ++++++++- Cargo.toml | 2 + src/uu/dmesg/Cargo.toml | 19 +++++ src/uu/dmesg/dmesg.md | 7 ++ src/uu/dmesg/src/dmesg.rs | 150 ++++++++++++++++++++++++++++++++++++++ src/uu/dmesg/src/main.rs | 1 + 6 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 src/uu/dmesg/Cargo.toml create mode 100644 src/uu/dmesg/dmesg.md create mode 100644 src/uu/dmesg/src/dmesg.rs create mode 100644 src/uu/dmesg/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index ead2c98..d4b0200 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clap" version = "4.5.16" @@ -297,7 +303,19 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.4.1", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "cfg_aliases 0.2.1", "libc", ] @@ -784,6 +802,7 @@ dependencies = [ "tempfile", "textwrap", "uu_ctrlaltdel", + "uu_dmesg", "uu_lscpu", "uu_lsmem", "uu_mountpoint", @@ -800,6 +819,18 @@ dependencies = [ "uucore", ] +[[package]] +name = "uu_dmesg" +version = "0.0.1" +dependencies = [ + "clap", + "nix 0.29.0", + "serde", + "serde_json", + "tabled", + "uucore", +] + [[package]] name = "uu_lscpu" version = "0.0.1" @@ -846,7 +877,7 @@ dependencies = [ "clap", "glob", "libc", - "nix", + "nix 0.28.0", "number_prefix", "once_cell", "os_display", diff --git a/Cargo.toml b/Cargo.toml index 984008e..50a0d68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ rand = { version = "0.8", features = ["small_rng"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.122" tabled = "0.16.0" +nix = "0.29.0" [dependencies] clap = { workspace = true } @@ -62,6 +63,7 @@ textwrap = { workspace = true } # lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" } lsmem = { optional = true, version = "0.0.1", package = "uu_lsmem", path = "src/uu/lsmem" } +dmesg = { optional = true, version = "0.0.1", package = "uu_dmesg", path = "src/uu/dmesg" } mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" } ctrlaltdel = { optional = true, version = "0.0.1", package = "uu_ctrlaltdel", path = "src/uu/ctrlaltdel" } rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" } diff --git a/src/uu/dmesg/Cargo.toml b/src/uu/dmesg/Cargo.toml new file mode 100644 index 0000000..06c2ab7 --- /dev/null +++ b/src/uu/dmesg/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "uu_dmesg" +version = "0.0.1" +edition = "2021" + +[lib] +path = "src/dmesg.rs" + +[[bin]] +name = "dmesg" +path = "src/main.rs" + +[dependencies] +uucore = { workspace = true } +clap = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tabled = { workspace = true } +nix = { workspace = true } diff --git a/src/uu/dmesg/dmesg.md b/src/uu/dmesg/dmesg.md new file mode 100644 index 0000000..dfa6244 --- /dev/null +++ b/src/uu/dmesg/dmesg.md @@ -0,0 +1,7 @@ +# dmesg + +``` +dmesg [OPTION]... +``` + +Print 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..bf6e32f --- /dev/null +++ b/src/uu/dmesg/src/dmesg.rs @@ -0,0 +1,150 @@ +// 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, Command}; +use clap::{Arg, ArgAction}; +use nix::errno::Errno; +// use nix::fcntl::SeekWhence; +// use nix::libc::{self, EPIPE}; +use std::fs::File; +use std::io::{self, BufRead, BufReader, BufWriter, ErrorKind}; +// use nix::unistd::lseek; +use std::borrow::Borrow; +// use std::fs::{File, OpenOptions}; +// use std::io::{self, BufWriter, Read, Seek, SeekFrom}; +use std::os::unix::fs::OpenOptionsExt; +use std::os::unix::io::{AsRawFd, RawFd}; +use uucore::{error::UResult, format_usage, help_about, help_usage}; + +const ABOUT: &str = help_about!("dmesg.md"); +const USAGE: &str = help_usage!("dmesg.md"); + +const FILE_KMSG: &str = "/dev/kmsg"; + +mod options { + pub const JSON: &str = "json"; +} + +struct DmesgControl { + // /* bit arrays -- see include/bitops.h */ + // char levels[ARRAY_SIZE(level_names) / NBBY + 1]; + // char facilities[ARRAY_SIZE(facility_names) / NBBY + 1]; + + // struct timeval lasttime; /* last printed timestamp */ + // struct tm lasttm; /* last localtime */ + // struct timeval boot_time; /* system boot time */ + // usec_t suspended_time; /* time spent in suspended state */ + + // int action; /* SYSLOG_ACTION_* */ + // int method; /* DMESG_METHOD_* */ + + // size_t bufsize; /* size of syslog buffer */ + kmsg: Option, // /dev/kmsg file descriptor + + kmsg_first_read: usize, /* initial read() return code */ + // /* + // * the kernel will give EINVAL if we do read() on /proc/kmsg with + // * length insufficient for the next message. messages may be up to + // * PRINTK_MESSAGE_MAX, which is defined as 2048, so we must be + // * able to buffer at least that much in one call + // */ + kmsg_buf: [u8; 2048], /* buffer to read kmsg data */ + + // usec_t since; /* filter records by time */ + // usec_t until; /* filter records by time */ + + // /* + // * For the --file option we mmap whole file. The unnecessary (already + // * printed) pages are always unmapped. The result is that we have in + // * memory only the currently used page(s). + // */ + // char *filename; + // char *mmap_buff; + // size_t pagesize; + // size_t ntime_fmts; + // unsigned int time_fmts[2 * __DMESG_TIMEFTM_COUNT]; /* time format */ + + // struct ul_jsonwrt jfmt; /* -J formatting */ + + // int indent; /* due to timestamps if newline */ + // size_t caller_id_size; /* PRINTK_CALLERID max field size */ +} + +struct Options { + follow: bool, // wait for new messages + end: bool, // seek to the of buffer + raw: bool, // raw mode + noesc: bool, // no escape + fltr_lev: bool, // filter out by levels[] + fltr_fac: bool, // filter out by facilities[] + decode: bool, // use "facility: level: " prefix + pager: bool, // pipe output into a pager + color: bool, // colorize messages + json: bool, // JSON output + force_prefix: bool, // force timestamp and decode prefix on each line +} + +fn set_line_buf() -> io::Result<()> { + let stdout = io::stdout(); + let handle = stdout.lock(); + let _writer = BufWriter::new(handle); + Ok(()) +} + +fn init_kmsg(ctl: &mut DmesgControl, opts: &Options) -> io::Result<()> { + match File::open(FILE_KMSG) { + Ok(fd) => { + ctl.kmsg = Some(fd); + } + Err(e) => { + ctl.kmsg = None; + return Err(e); + } + }; + + let mut reader = BufReader::new(ctl.kmsg.as_ref().unwrap()); + let mut line = String::new(); + match reader.read_line(&mut line) { + Ok(0) => println!("End of file or connection closed"), + Ok(_) => println!("Read line: {}", line), + Err(ref e) if e.kind() == ErrorKind::BrokenPipe => { + eprintln!("Error: Broken pipe (EPIPE) detected while reading"); + } + Err(e) => eprintln!("Unexpected error: {}", e), + } + + Ok(()) +} + +// fn read_kmsg_one(ctl: &mut DmesgControl) -> io::Result { +// let mut size: usize; + +// /* kmsg returns EPIPE if record was modified while reading */ +// loop { +// size = ctl.kmsg.borrow().read(&mut ctl.kmsg_buf)?; +// if size < 0 && Errno::last() == Errno::EPIPE { +// continue; +// } +// break; +// } + +// Ok(size) +// } + +#[uucore::main] +pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?; + let opt_json = matches.get_flag(options::JSON); + + Ok(()) +} + +pub fn uu_app() -> Command { + Command::new(uucore::util_name()) + .version(crate_version!()) + .about(ABOUT) + .override_usage(format_usage(USAGE)) + .infer_long_args(true) +} 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);