xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/android/syslog.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Implementation of the Syslog trait as a wrapper around Android's logging library, liblog.
6 
7 use std::ffi::CString;
8 use std::ffi::NulError;
9 use std::mem::size_of;
10 
11 use android_log_sys::__android_log_is_loggable;
12 use android_log_sys::__android_log_message;
13 use android_log_sys::__android_log_write_log_message;
14 use android_log_sys::log_id_t;
15 use android_log_sys::LogPriority;
16 
17 use crate::syslog::Error;
18 use crate::syslog::Facility;
19 use crate::syslog::Level;
20 use crate::syslog::Log;
21 use crate::syslog::Syslog;
22 use crate::RawDescriptor;
23 
24 pub struct PlatformSyslog {
25     proc_name: String,
26 }
27 
28 impl Syslog for PlatformSyslog {
new( proc_name: String, _facility: Facility, ) -> Result<(Option<Box<dyn Log + Send>>, Option<RawDescriptor>), Error>29     fn new(
30         proc_name: String,
31         _facility: Facility,
32     ) -> Result<(Option<Box<dyn Log + Send>>, Option<RawDescriptor>), Error> {
33         Ok((Some(Box::new(Self { proc_name })), None))
34     }
35 }
36 
37 impl Log for PlatformSyslog {
log(&self, record: &log::Record)38     fn log(&self, record: &log::Record) {
39         let priority = match record.level() {
40             Level::Error => LogPriority::ERROR,
41             Level::Warn => LogPriority::WARN,
42             Level::Info => LogPriority::INFO,
43             Level::Debug => LogPriority::VERBOSE,
44             Level::Trace => LogPriority::VERBOSE,
45         };
46         let message = std::fmt::format(*record.args());
47         let _ = android_log(
48             log_id_t::SYSTEM,
49             priority,
50             &self.proc_name,
51             record.file(),
52             record.line(),
53             &message,
54         );
55     }
56 
enabled(&self, _metadata: &log::Metadata) -> bool57     fn enabled(&self, _metadata: &log::Metadata) -> bool {
58         true
59     }
60 
flush(&self)61     fn flush(&self) {}
62 }
63 
64 /// Send a log message to the Android logger (logd, by default) if it is currently configured to be
65 /// loggable based on the priority and tag.
66 ///
67 /// # Arguments
68 /// * `priority` - The Android log priority. Used to determine whether the message is loggable.
69 /// * `tag` - A tag to indicate where the log comes from.
70 /// * `file` - The name of the file from where the message is being logged, if available.
71 /// * `line` - The line number from where the message is being logged, if available.
72 /// * `message` - The message to log.
android_log( buffer_id: log_id_t, priority: LogPriority, tag: &str, file: Option<&str>, line: Option<u32>, message: &str, ) -> Result<(), NulError>73 fn android_log(
74     buffer_id: log_id_t,
75     priority: LogPriority,
76     tag: &str,
77     file: Option<&str>,
78     line: Option<u32>,
79     message: &str,
80 ) -> Result<(), NulError> {
81     let tag = CString::new(tag)?;
82     let default_pri = LogPriority::VERBOSE;
83     // SAFETY: `tag` is guaranteed to be valid for duration of the call
84     if unsafe { __android_log_is_loggable(priority as i32, tag.as_ptr(), default_pri as i32) } != 0
85     {
86         let c_file_name = match file {
87             Some(file_name) => CString::new(file_name)?.as_ptr(),
88             None => std::ptr::null(),
89         };
90         let line = line.unwrap_or(0);
91         let message = CString::new(message)?;
92         let mut log_message = __android_log_message {
93             struct_size: size_of::<__android_log_message>(),
94             buffer_id: buffer_id as i32,
95             priority: priority as i32,
96             tag: tag.as_ptr(),
97             file: c_file_name,
98             line,
99             message: message.as_ptr(),
100         };
101         // SAFETY: `log_message` is guaranteed to be valid for duration of the call
102         unsafe { __android_log_write_log_message(&mut log_message) };
103     }
104     Ok(())
105 }
106