extern crate errno;
extern crate libc;
#[cfg(target_os = "macos")]
use std::str;
#[cfg(target_os = "macos")]
use self::libc::c_void;
#[cfg(target_os = "linux")]
use std::fs::File;
#[cfg(target_os = "linux")]
use std::io::{BufRead, BufReader};
#[cfg(target_os = "linux")]
use std::sync::mpsc;
#[cfg(target_os = "linux")]
use std::sync::mpsc::Receiver;
#[cfg(target_os = "linux")]
use std::{thread, time};
#[cfg(target_os = "macos")]
use crate::osx_libproc_bindings::{MAXBSIZE as MAX_MSG_BSIZE, proc_kmsgbuf};
#[cfg(target_os = "macos")]
pub fn kmsgbuf() -> Result<String, String> {
let mut message_buffer: Vec<u8> = Vec::with_capacity(MAX_MSG_BSIZE as _);
let buffer_ptr = message_buffer.as_mut_ptr() as *mut c_void;
let ret: i32;
unsafe {
ret = proc_kmsgbuf(buffer_ptr, message_buffer.capacity() as u32);
if ret > 0 {
message_buffer.set_len(ret as usize - 1);
}
}
if !message_buffer.is_empty() {
let msg = str::from_utf8(&message_buffer)
.map_err(|_| "Could not convert kernel message buffer from utf8".to_string())?
.parse().map_err(|_| "Could not parse kernel message")?;
Ok(msg)
} else {
Err("Could not read kernel message buffer".to_string())
}
}
#[cfg(target_os = "linux")]
pub fn kmsgbuf() -> Result<String, String> {
let file = File::open("/dev/kmsg").map_err(|_| "Could not open /dev/kmsg file '{}'")?;
let kmsg_channel = spawn_kmsg_channel(file);
let duration = time::Duration::from_millis(1);
let mut buf = String::new();
while let Ok(line) = kmsg_channel.recv_timeout(duration) {
buf.push_str(&line)
}
Ok(buf)
}
#[cfg(target_os = "linux")]
fn spawn_kmsg_channel(file: File) -> Receiver<String> {
let mut reader = BufReader::new(file);
let (tx, rx) = mpsc::channel::<String>();
thread::spawn(move || loop {
let mut line = String::new();
match reader.read_line(&mut line) {
Ok(_) => {
if tx.send(line).is_err() { break; }
}
_ => break
}
});
rx
}
#[cfg(test)]
mod test {
use std::io;
use std::io::Write;
use crate::libproc::proc_pid::am_root;
use super::kmsgbuf;
#[test]
fn kmessage_buffer_test() {
if am_root() {
match kmsgbuf() {
Ok(_) => { },
Err(message) => panic!("{}", message)
}
} else {
writeln!(&mut io::stdout(), "test libproc::kmesg_buffer::kmessage_buffer_test ... skipped as it needs to be run as root").unwrap();
}
}
}