@@ -2,15 +2,10 @@ extern crate errno;
22extern crate libc;
33
44#[ cfg( target_os = "macos" ) ]
5- use std:: fmt;
6- #[ cfg( target_os = "macos" ) ]
7- use std:: { mem, ptr} ;
8-
9- #[ cfg( target_os = "macos" ) ]
10- use crate :: libproc:: helpers;
5+ use std:: str;
116
127#[ cfg( target_os = "macos" ) ]
13- use self :: libc:: c_int;
8+ use self :: libc:: { c_int, c_void } ;
149
1510#[ cfg( target_os = "linux" ) ]
1611use std:: fs:: File ;
@@ -23,101 +18,45 @@ use std::sync::mpsc::Receiver;
2318#[ cfg( target_os = "linux" ) ]
2419use std:: { thread, time} ;
2520
26-
2721// See https://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/sys/msgbuf.h
2822#[ cfg( target_os = "macos" ) ]
29- const MAX_MSG_BSIZE : c_int = 1024 * 1024 ;
30- #[ cfg( target_os = "macos" ) ]
31- const MSG_MAGIC : c_int = 0x063_061 ;
32-
33- // See /usr/include/sys/msgbuf.h on your Mac.
34- #[ cfg( target_os = "macos" ) ]
35- #[ repr( C ) ]
36- struct MessageBuffer {
37- pub msg_magic : c_int ,
38- pub msg_size : c_int ,
39- pub msg_bufx : c_int ,
40- // write pointer
41- pub msg_bufr : c_int ,
42- // read pointer
43- pub msg_bufc : * mut u8 , // buffer
44- }
45-
46- #[ cfg( target_os = "macos" ) ]
47- impl Default for MessageBuffer {
48- fn default ( ) -> MessageBuffer {
49- MessageBuffer {
50- msg_magic : 0 ,
51- msg_size : 0 ,
52- msg_bufx : 0 ,
53- msg_bufr : 0 ,
54- msg_bufc : ptr:: null_mut ( ) as * mut u8 ,
55- }
56- }
57- }
58-
59- #[ cfg( target_os = "macos" ) ]
60- impl fmt:: Debug for MessageBuffer {
61- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
62- write ! ( f, "MessageBuffer {{ magic: 0x{:x}, size: {}, bufx: {}}}" , self . msg_magic, self . msg_size, self . msg_bufx)
63- }
64- }
23+ const MAX_MSG_BSIZE : usize = 1024 * 1024 ;
6524
6625// this extern block links to the libproc library
6726// Original signatures of functions can be found at http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
6827#[ cfg( target_os = "macos" ) ]
6928#[ link( name = "proc" , kind = "dylib" ) ]
7029extern {
71- fn proc_kmsgbuf ( buffer : * mut MessageBuffer , buffersize : u32 ) -> c_int ;
30+ fn proc_kmsgbuf ( buffer : * mut c_void , buffersize : u32 ) -> c_int ;
7231}
7332
7433/// Get the contents of the kernel message buffer
7534///
7635/// Entries are in the format:
7736/// faclev,seqnum,timestamp[optional, ...];message\n
7837/// TAGNAME=value (0 or more Tags)
79- // See http://opensource.apple.com//source/system_cmds/system_cmds-336.6/dmesg.tproj/dmesg.c
38+ // See http://opensource.apple.com//source/system_cmds/system_cmds-336.6/dmesg.tproj/dmesg.c// See http://opensource.apple.com//source/system_cmds/system_cmds-336.6/dmesg.tproj/dmesg.c
8039#[ cfg( target_os = "macos" ) ]
8140pub fn kmsgbuf ( ) -> Result < String , String > {
82- let mut message_buffer: MessageBuffer = Default :: default ( ) ;
41+ let mut message_buffer: Vec < u8 > = Vec :: with_capacity ( MAX_MSG_BSIZE ) ;
42+ let buffer_ptr = message_buffer. as_mut_ptr ( ) as * mut c_void ;
8343 let ret: i32 ;
8444
8545 unsafe {
86- ret = proc_kmsgbuf ( & mut message_buffer, mem:: size_of :: < MessageBuffer > ( ) as u32 ) ;
46+ ret = proc_kmsgbuf ( buffer_ptr, message_buffer. capacity ( ) as u32 ) ;
47+ if ret > 0 {
48+ message_buffer. set_len ( ret as usize - 1 ) ;
49+ }
8750 }
8851
89- if ret <= 0 {
90- Err ( helpers:: get_errno_with_message ( ret) )
91- } else if message_buffer. msg_magic != MSG_MAGIC {
92- println ! ( "Message buffer: {:?}" , message_buffer) ;
93- Err ( format ! ( "The magic number 0x{:x} is incorrect" , message_buffer. msg_magic) )
94- } else {
95- // Avoid starting beyond the end of the buffer
96- if message_buffer. msg_bufx >= MAX_MSG_BSIZE {
97- message_buffer. msg_bufx = 0 ;
98- }
99- let mut output: Vec < u8 > = Vec :: new ( ) ;
100-
101- // The message buffer is circular; start at the read pointer, and go to the write pointer - 1.
102- unsafe {
103- let mut ch: u8 ;
104- let mut p: * mut u8 = message_buffer. msg_bufc . offset ( message_buffer. msg_bufx as isize ) ;
105- let ep: * mut u8 = message_buffer. msg_bufc . offset ( ( message_buffer. msg_bufx - 1 ) as isize ) ;
106-
107- while p != ep {
108- // If at the end, then loop around to the start
109- // TODO should use actual size (from struct element) - not the max size??
110- if p == message_buffer. msg_bufc . offset ( MAX_MSG_BSIZE as isize ) {
111- p = message_buffer. msg_bufc ;
112- }
113-
114- ch = * p;
115- output. push ( ch) ;
116- p = p. offset ( 1 ) ;
117- }
52+ if !message_buffer. is_empty ( ) {
53+ let msg = str:: from_utf8 ( & message_buffer)
54+ . map_err ( |_| "Could not convert kernel message buffer from utf8" . to_string ( ) ) ?
55+ . parse ( ) . unwrap ( ) ;
11856
119- Ok ( String :: from_utf8 ( output) . map_err ( |_| "Could not convert to UTF-8" ) ?)
120- }
57+ Ok ( msg)
58+ } else {
59+ Err ( "Could not read kernel message buffer" . to_string ( ) )
12160 }
12261}
12362
@@ -132,7 +71,7 @@ pub fn kmsgbuf() -> Result<String, String> {
13271 let duration = time:: Duration :: from_millis ( 1 ) ;
13372 let mut buf = String :: new ( ) ;
13473 while let Ok ( line) = kmsg_channel. recv_timeout ( duration) {
135- buf. push_str ( & line)
74+ buf. push_str ( & line)
13675 }
13776
13877 Ok ( buf)
@@ -148,8 +87,8 @@ fn spawn_kmsg_channel(file: File) -> Receiver<String> {
14887 let mut line = String :: new ( ) ;
14988 match reader. read_line ( & mut line) {
15089 Ok ( _) => {
151- if tx. send ( line) . is_err ( ) { break }
152- } ,
90+ if tx. send ( line) . is_err ( ) { break ; }
91+ }
15392 _ => break
15493 }
15594 } ) ;
@@ -167,14 +106,10 @@ mod test {
167106 use super :: kmsgbuf;
168107
169108 #[ test]
170- #[ ignore]
171- // TODO fix on macos: an error message is returned - https://github.com/andrewdavidmackenzie/libproc-rs/issues/39
172- // Message buffer: MessageBuffer { magic: 0x3a657461, size: 1986947360, bufx: 1684630625}
173- // thread 'libproc::kmesg_buffer::test::kmessagebuffer_test' panicked at 'The magic number 0x3a657461 is incorrect', src/libproc/kmesg_buffer.rs:194:33
174109 fn kmessagebuffer_test ( ) {
175110 if am_root ( ) {
176111 match kmsgbuf ( ) {
177- Ok ( buffer ) => println ! ( "Buffer: {:?}" , buffer ) ,
112+ Ok ( _ ) => { } ,
178113 Err ( message) => panic ! ( message)
179114 }
180115 } else {
0 commit comments