dlogutil/lib.rs
1use dlog::{BufferId, Priority};
2use dlog_sys::{log_id_t, log_priority};
3use dlogutil_sys::*;
4use libc::timespec;
5use std::ffi::CStr;
6use std::io::{Error, ErrorKind, Result};
7use std::ptr::{null, null_mut};
8use std::time::Duration;
9
10/// Enumeration for timestamp-based log sorting orderings.
11///
12/// For more detailed information on the timestamp documentation,
13/// refer to the C library documentation.
14#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
15pub enum SortingOrder {
16 /// Monotonic timestamp applied by the sender.
17 SentMono,
18 /// Real-time timestamp applied by the sender.
19 SentReal,
20 /// Monotonic timestamp applied by the receiver.
21 RecvMono,
22 /// Real-time timestamp applied by the receiver.
23 RecvReal,
24 /// The default timestamp of the buffer. See [`buffer_get_default_ts_type`].
25 Default,
26}
27
28impl From<dlogutil_sorting_order> for SortingOrder {
29 fn from(c_enum: dlogutil_sorting_order) -> Self {
30 match c_enum {
31 dlogutil_sorting_order::DLOGUTIL_SORT_SENT_MONO => SortingOrder::SentMono,
32 dlogutil_sorting_order::DLOGUTIL_SORT_SENT_REAL => SortingOrder::SentReal,
33 dlogutil_sorting_order::DLOGUTIL_SORT_RECV_MONO => SortingOrder::RecvMono,
34 dlogutil_sorting_order::DLOGUTIL_SORT_RECV_REAL => SortingOrder::RecvReal,
35 dlogutil_sorting_order::DLOGUTIL_SORT_DEFAULT => SortingOrder::Default,
36 }
37 }
38}
39
40impl From<SortingOrder> for dlogutil_sorting_order {
41 fn from(rust_enum: SortingOrder) -> Self {
42 match rust_enum {
43 SortingOrder::SentMono => dlogutil_sorting_order::DLOGUTIL_SORT_SENT_MONO,
44 SortingOrder::SentReal => dlogutil_sorting_order::DLOGUTIL_SORT_SENT_REAL,
45 SortingOrder::RecvMono => dlogutil_sorting_order::DLOGUTIL_SORT_RECV_MONO,
46 SortingOrder::RecvReal => dlogutil_sorting_order::DLOGUTIL_SORT_RECV_REAL,
47 SortingOrder::Default => dlogutil_sorting_order::DLOGUTIL_SORT_DEFAULT,
48 }
49 }
50}
51
52/// A struct containing libdlogutil initialisation configuration.
53pub struct DlogutilConfig {
54 config: *mut dlogutil_config,
55}
56
57// SAFETY: it is ok to use the this object from different threads if only one thread
58// is using the memory at the time.
59unsafe impl Send for DlogutilConfig {}
60
61// SAFETY: the operations that do not modify the memory at all are ok to be used from
62// different threads at once, and those who do are marked as &mut.
63unsafe impl Sync for DlogutilConfig {}
64
65/// A struct containing the state of a log handling request.
66pub struct DlogutilState {
67 state: *mut dlogutil_state,
68}
69
70// SAFETY: it is ok to use the this object from different threads if only one thread
71// is using the memory at the time.
72unsafe impl Send for DlogutilState {}
73
74// SAFETY: the operations that do not modify the memory at all are ok to be used from
75// different threads at once, and those who do are marked as &mut.
76unsafe impl Sync for DlogutilState {}
77
78/// A struct containing the metadata and contents for a single dlog entry.
79pub struct DlogutilEntry {
80 entry: *mut dlogutil_entry,
81}
82
83// SAFETY: it is ok to use the this object from different threads if only one thread
84// is using the memory at the time.
85unsafe impl Send for DlogutilEntry {}
86
87// SAFETY: the operations that do not modify the memory at all are ok to be used from
88// different threads at once, and those who do are marked as &mut.
89unsafe impl Sync for DlogutilEntry {}
90
91impl Drop for DlogutilConfig {
92 fn drop(&mut self) {
93 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
94 // Since the function takes &mut, no other references can exist.
95 unsafe {
96 dlogutil_config_destroy(self.config);
97 }
98 }
99}
100
101impl Drop for DlogutilState {
102 fn drop(&mut self) {
103 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
104 // Since the function takes &mut, no other references can exist.
105 unsafe {
106 dlogutil_state_destroy(self.state);
107 }
108 }
109}
110
111impl Drop for DlogutilEntry {
112 fn drop(&mut self) {
113 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
114 // Since the function takes &mut, no other references can exist.
115 unsafe {
116 dlogutil_entry_destroy(self.entry);
117 }
118 }
119}
120
121impl DlogutilConfig {
122 /// Creates a new [`DlogutilConfig`] struct to be filled with configuration.
123 ///
124 /// Useful for dumping the logs of a specific thread in a multithreaded process.
125 ///
126 /// # Returns
127 ///
128 /// * `Ok(Self)` - A handle to the config struct.
129 /// * `Err(std::io::Error)` - An error.
130 ///
131 /// # Errors
132 ///
133 /// * [`std::io::ErrorKind::OutOfMemory`] - Out of memory.
134 pub fn create() -> Result<Self> {
135 // SAFETY: the function is safe by itself. It returns either a valid pointer,
136 // in which case we return Ok, or NULL, in which case we return Err, which
137 // means that if Self is created, the inner pointer is guaranteed to be correct.
138 let config = unsafe { dlogutil_config_create() };
139 if config.is_null() {
140 return Err(Error::from(ErrorKind::OutOfMemory));
141 }
142 Ok(DlogutilConfig { config })
143 }
144
145 /// Enables retrieving only those logs that are logged by the thread with
146 /// the given TID.
147 ///
148 /// Useful for dumping the logs of a specific thread in a multithreaded process.
149 ///
150 /// # Errors
151 ///
152 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
153 /// * [`std::io::ErrorKind::OutOfMemory`] - Out of memory.
154 pub fn filter_tid(&mut self, tid: i32) -> Result<()> {
155 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
156 // Since the function takes &mut, no other references can exist.
157 match unsafe { dlogutil_config_filter_tid(self.config, tid) } {
158 0 => Ok(()),
159 e => Err(Error::from_raw_os_error(-e)),
160 }
161 }
162
163 /// Enables retrieving only those logs that are logged by the process with
164 /// the given PID.
165 ///
166 /// Useful for dumping the logs of a specific process.
167 ///
168 /// # Errors
169 ///
170 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
171 /// * [`std::io::ErrorKind::OutOfMemory`] - Out of memory.
172 pub fn filter_pid(&mut self, pid: i32) -> Result<()> {
173 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
174 // Since the function takes &mut, no other references can exist.
175 match unsafe { dlogutil_config_filter_pid(self.config, pid) } {
176 0 => Ok(()),
177 e => Err(Error::from_raw_os_error(-e)),
178 }
179 }
180
181 /// Enables retrieving only those logs that match a given filter.
182 ///
183 /// # Arguments
184 ///
185 /// * `query` - The filter query. For syntax, see dlogutil's --help.
186 ///
187 /// # Errors
188 ///
189 /// * [`std::io::ErrorKind::InvalidInput`] - Invalid syntax of the filterspec.
190 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
191 /// * [`std::io::ErrorKind::OutOfMemory`] - Out of memory.
192 pub fn filter_filterspec(&mut self, query: &str) -> Result<()> {
193 let query = format!("{}\0", query);
194 let query_c =
195 CStr::from_bytes_with_nul(query.as_bytes()).map_err(|_| ErrorKind::InvalidInput)?;
196 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
197 // The string is defined in a verified way above.
198 // Since the function takes &mut, no other references can exist.
199 match unsafe { dlogutil_config_filter_filterspec(self.config, query_c.as_ptr()) } {
200 0 => Ok(()),
201 e => Err(Error::from_raw_os_error(-e)),
202 }
203 }
204
205 /// Disables log sorting for given log retrieval request.
206 ///
207 /// Logs are still received in some order that is usually largely sorted,
208 /// but if sorting is disabled logutil-side there may be cases where a log
209 /// with a later timestamp is in front of a log with an earlier one.
210 /// The use case here is performance, since the failure case above is rare.
211 ///
212 /// # Errors
213 ///
214 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
215 pub fn sorting_disable(&mut self) -> Result<()> {
216 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
217 // Since the function takes &mut, no other references can exist.
218 match unsafe { dlogutil_config_sorting_disable(self.config) } {
219 0 => Ok(()),
220 e => Err(Error::from_raw_os_error(-e)),
221 }
222 }
223
224 /// Enables log sorting for given log retrieval request.
225 ///
226 /// This is the default and generally makes sure that logs are in order,
227 /// but has a modest performance cost.
228 ///
229 /// # Errors
230 ///
231 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
232 pub fn sorting_enable(&mut self) -> Result<()> {
233 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
234 // Since the function takes &mut, no other references can exist.
235 match unsafe { dlogutil_config_sorting_enable(self.config) } {
236 0 => Ok(()),
237 e => Err(Error::from_raw_os_error(-e)),
238 }
239 }
240
241 /// Enables sorting, choosing the sort buffer size manually.
242 ///
243 /// The count parameter influences the quality of sorting, but also memory usage.
244 /// This version is a somewhat lower level version of [`sorting_enable`].
245 /// For more information on sorting quality, refer to the C library documentation.
246 ///
247 /// [`sorting_enable`]: DlogutilConfig::sorting_enable
248 ///
249 /// # Arguments
250 ///
251 /// * `entry_count` - How many logs to keep at a given time. At least 1.
252 ///
253 /// # Errors
254 ///
255 /// * [`std::io::ErrorKind::InvalidInput`] - Zero size.
256 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
257 pub fn sorting_enable_with_size(&mut self, entry_count: u32) -> Result<()> {
258 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
259 // Since the function takes &mut, no other references can exist.
260 match unsafe { dlogutil_config_sorting_enable_with_size(self.config, entry_count) } {
261 0 => Ok(()),
262 e => Err(Error::from_raw_os_error(-e)),
263 }
264 }
265
266 /// Chooses a timestamp type by which returned logs are sorted by.
267 ///
268 /// If the chosen timestamp is missing in the logs, currently they will not
269 /// be sorted at all. This should, however, still become a reasonable order,
270 /// since logs are usually stored sorted by one of timestamps. If only some
271 /// logs are missing the chosen timestamp, ordering of the logs is undefined.
272 /// See [`buffer_get_default_ts_type`] for the default.
273 ///
274 /// # Errors
275 ///
276 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
277 pub fn order_set(&mut self, sort_by: SortingOrder) -> Result<()> {
278 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
279 // Since the function takes &mut, no other references can exist.
280 match unsafe { dlogutil_config_order_set(self.config, sort_by.into()) } {
281 0 => Ok(()),
282 e => Err(Error::from_raw_os_error(-e)),
283 }
284 }
285
286 /// Adds a buffer whence logs will be taken to a request.
287 ///
288 /// # Errors
289 ///
290 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
291 pub fn buffer_add(&mut self, buf: BufferId) -> Result<()> {
292 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
293 // Since the function takes &mut, no other references can exist.
294 match unsafe { dlogutil_config_buffer_add(self.config, buf.into()) } {
295 0 => Ok(()),
296 e => Err(Error::from_raw_os_error(-e)),
297 }
298 }
299
300 /// Set log retrieval mode to retrieving all the logs since the start of
301 /// the system without an end.
302 ///
303 /// This is similar to `dlogutil` in a default mode.
304 ///
305 /// # Errors
306 ///
307 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
308 pub fn mode_set_continuous(&mut self) -> Result<()> {
309 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
310 // Since the function takes &mut, no other references can exist.
311 match unsafe { dlogutil_config_mode_set_continuous(self.config) } {
312 0 => Ok(()),
313 e => Err(Error::from_raw_os_error(-e)),
314 }
315 }
316
317 /// Set log retrieval mode to retrieving all the logs since the call
318 /// without an end.
319 ///
320 /// This is similar to `dlogutil -m`.
321 ///
322 /// # Errors
323 ///
324 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
325 pub fn mode_set_monitor(&mut self) -> Result<()> {
326 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
327 // Since the function takes &mut, no other references can exist.
328 match unsafe { dlogutil_config_mode_set_monitor(self.config) } {
329 0 => Ok(()),
330 e => Err(Error::from_raw_os_error(-e)),
331 }
332 }
333
334 /// Set log retrieval mode to dumping all the logs since the start of the
335 /// system until the call (possibly a specified amount of the most recent
336 /// of them instead).
337 ///
338 /// This is similar to `dlogutil -d`. After dumping all the logs,
339 /// [`get_log`] will signal this by returning `TIZEN_ERROR_NO_DATA`.
340 ///
341 /// [`get_log`]: DlogutilState::get_log
342 ///
343 /// # Arguments
344 ///
345 /// * `entry_count` - Number of logs to be returned. It can be
346 /// `DLOGUTIL_MAX_DUMP_SIZE`, in which case all the logs will be dumped.
347 ///
348 /// # Errors
349 ///
350 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
351 pub fn mode_set_dump(&mut self, entry_count: u32) -> Result<()> {
352 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
353 // Since the function takes &mut, no other references can exist.
354 match unsafe { dlogutil_config_mode_set_dump(self.config, entry_count) } {
355 0 => Ok(()),
356 e => Err(Error::from_raw_os_error(-e)),
357 }
358 }
359
360 /// Set log retrieval mode to dumping compressed historical logs.
361 ///
362 /// This is similar to `cat /var/log/dlog/xyz`. After dumping all the logs,
363 /// [`get_log`] will signal this by returning `TIZEN_ERROR_NO_DATA`.
364 ///
365 /// [`get_log`]: DlogutilState::get_log
366 ///
367 /// # Arguments
368 ///
369 /// * `compress_buffer` - The name of the compression storage entry.
370 ///
371 /// # Errors
372 ///
373 /// * [`std::io::ErrorKind::OutOfMemory`] - Not enough memory. Parameters left unchanged.
374 /// * [`std::io::ErrorKind::InvalidInput`] - The pointer was NULL.
375 pub fn mode_set_compressed_memory_dump(&mut self, compress_buffer: &str) -> Result<()> {
376 let compress_buffer = format!("{}\0", compress_buffer);
377 let compress_buffer_c = CStr::from_bytes_with_nul(compress_buffer.as_bytes())
378 .map_err(|_| ErrorKind::InvalidInput)?;
379 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
380 // The string is defined in a verified way above.
381 // Since the function takes &mut, no other references can exist.
382 match unsafe {
383 dlogutil_config_mode_set_compressed_memory_dump(self.config, compress_buffer_c.as_ptr())
384 } {
385 0 => Ok(()),
386 e => Err(Error::from_raw_os_error(-e)),
387 }
388 }
389}
390
391impl DlogutilState {
392 /// Finalizes the config into a state struct by connecting to buffers.
393 ///
394 /// An application having platform privilege level can read platform log
395 /// data by declaring <http://tizen.org/privilege/log>.
396 ///
397 /// # Returns
398 ///
399 /// * `Ok(Self)` - A handle to the state struct.
400 /// * `Err(std::io::Error)` - An error.
401 ///
402 /// # Errors
403 ///
404 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
405 /// * [`std::io::ErrorKind::InvalidInput`] - No buffers selected.
406 /// * [`std::io::ErrorKind::Uncategorized`] - Unsupported buffer set (KMSG + non-KMSG).
407 /// * [`std::io::ErrorKind::Uncategorized`] - Unsupported backend (zero-copy).
408 /// * [`std::io::ErrorKind::Uncategorized`] - No buffers were opened (incl. due to null backend).
409 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't read config file.
410 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't contact log backend.
411 /// * [`std::io::ErrorKind::OutOfMemory`] - There's not enough memory.
412 pub fn create(config: DlogutilConfig) -> Result<Self> {
413 let mut state = DlogutilState { state: null_mut() };
414 // SAFETY: the config pointer is guaranteed to be correct by the way it's created.
415 // Otherwise, the function is safe by itself. It returns either a valid pointer,
416 // in which case we return Ok, or NULL, in which case we return Err, which
417 // means that if Self is created, the inner pointer is guaranteed to be correct.
418 match unsafe { dlogutil_config_connect(config.config, &mut state.state) } {
419 0 => Ok(state),
420 e => Err(Error::from_raw_os_error(-e)),
421 }
422 }
423
424 /// Retrieves a single log according to a dump request.
425 ///
426 /// Returns a returned log as a [`DlogutilEntry`] struct.
427 ///
428 /// If the calling process doesn't have `CAP_SYSLOG` and is not in the
429 /// log group, you will only get some of the logs.
430 /// Also, you must set the mode (`DlogutilConfig::mode_set_*`).
431 ///
432 /// [`DlogutilEntry`]: DlogutilEntry
433 ///
434 /// # Arguments
435 ///
436 /// * `timeout` - How many miliseconds to wait for the log.
437 /// The actual runtime of the call can obviously be slightly longer than
438 /// this argument. 0 means don't wait, None means wait indefinitely.
439 ///
440 /// # Returns
441 ///
442 /// * `Ok(DlogutilEntry)` - A returned log.
443 /// * `Err(std::io::Error)` - An error.
444 ///
445 /// # Errors
446 ///
447 /// * [`std::io::ErrorKind::Uncategorized`] - Timeout exceeded.
448 /// * [`std::io::ErrorKind::Uncategorized`] - In dump mode, no more logs remaining.
449 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
450 /// * [`std::io::ErrorKind::InvalidInput`] - State not in log-getting mode.
451 /// * [`std::io::ErrorKind::OutOfMemory`] - There's not enough memory.
452 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't fulfill request.
453 pub fn get_log(&mut self, timeout: Option<Duration>) -> Result<DlogutilEntry> {
454 let mut entry_out = DlogutilEntry { entry: null_mut() };
455 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
456 // The C function passes the ownership of the entry to the pointer iff the
457 // return value is nonzero, which is exactly the case in which we return
458 // the struct in an Ok. Since the function takes &mut, no other references can exist.
459 match unsafe {
460 dlogutil_get_log(
461 self.state,
462 timeout.map_or(-1, |t| t.as_millis() as i32),
463 &mut entry_out.entry,
464 )
465 } {
466 0 => Ok(entry_out),
467 e => Err(Error::from_raw_os_error(-e)),
468 }
469 }
470
471 /// Irreversibly clears a log buffer from any logs inside.
472 ///
473 /// Either `CAP_SYSLOG` or being in the log group is required.
474 /// Also, you can't use one of the log-getting modes
475 /// (`DlogutilConfig::mode_set_*`).
476 ///
477 /// # Errors
478 ///
479 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
480 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't fulfill request.
481 pub fn buffer_clear(&mut self, buffer: BufferId) -> Result<()> {
482 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
483 // Since the function takes &mut, no other references can exist.
484 match unsafe { dlogutil_buffer_clear(self.state, buffer.into()) } {
485 0 => Ok(()),
486 e => Err(Error::from_raw_os_error(-e)),
487 }
488 }
489
490 /// Gets the data storage capacity of a log buffer in bytes.
491 ///
492 /// Either `CAP_SYSLOG` or being in the log group is required.
493 /// Also, you can't use one of the log-getting modes
494 /// (`DlogutilConfig::mode_set_*`).
495 ///
496 /// # Returns
497 ///
498 /// * `Ok(u32)` - The buffer's maximum capacity in bytes.
499 /// * `Err(std::io::Error)` - An error.
500 ///
501 /// # Errors
502 ///
503 /// * [`std::io::ErrorKind::InvalidInput`] - State in log-getting mode.
504 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
505 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't fulfill request.
506 pub fn buffer_get_capacity(&mut self, buffer: BufferId) -> Result<u32> {
507 let mut capacity = 0;
508 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
509 // Note that it is not correct for this function to take a shared reference, as in case of
510 // the pipe backend, the function will write to a pipe and expect to read an answer
511 // immediately.
512 match unsafe { dlogutil_buffer_get_capacity(self.state, buffer.into(), &mut capacity) } {
513 0 => Ok(capacity),
514 e => Err(Error::from_raw_os_error(-e)),
515 }
516 }
517
518 /// Gets the storage data usage of a log buffer in bytes.
519 ///
520 /// Either `CAP_SYSLOG` or being in the log group is required.
521 /// Also, you can't use one of the log-getting modes
522 /// (`DlogutilConfig::mode_set_*`).
523 ///
524 /// # Returns
525 ///
526 /// * `Ok(u32)` - Buffer's current usage in bytes.
527 /// * `Err(std::io::Error)` - An error.
528 ///
529 /// # Errors
530 ///
531 /// * [`std::io::ErrorKind::InvalidInput`] - State in log-getting mode.
532 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
533 /// * [`std::io::ErrorKind::Uncategorized`] - Couldn't fulfill request.
534 pub fn buffer_get_usage(&mut self, buffer: BufferId) -> Result<u32> {
535 let mut usage = 0;
536 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
537 // Note that it is not correct for this function to take a shared reference, as in case of
538 // the pipe backend, the function will write to a pipe and expect to read an answer
539 // immediately.
540 match unsafe { dlogutil_buffer_get_usage(self.state, buffer.into(), &mut usage) } {
541 0 => Ok(usage),
542 e => Err(Error::from_raw_os_error(-e)),
543 }
544 }
545
546 /// Gets the buffer aliasing (same storage) information.
547 ///
548 /// Sometimes, multiple buffers will be backed by a single log storage
549 /// (for example, by the same kernel device). In such cases, the storage
550 /// will only be opened once.
551 /// This function allows you to see whether this is the case.
552 ///
553 /// # Returns
554 ///
555 /// * `Ok(BufferId)` - Buffer aliasing information.
556 /// * `Err(std::io::Error)` - An error.
557 ///
558 /// # Errors
559 ///
560 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
561 pub fn buffer_get_alias(&self, buffer: BufferId) -> Result<BufferId> {
562 let mut real_buffer = log_id_t::LOG_ID_MAIN;
563 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
564 // This method only reads from the memory of the object, so it is ok for it to take
565 // a shared reference.
566 match unsafe { dlogutil_buffer_get_alias(self.state, buffer.into(), &mut real_buffer) } {
567 0 => Ok(real_buffer.into()),
568 e => Err(Error::from_raw_os_error(-e)),
569 }
570 }
571}
572
573impl DlogutilEntry {
574 /// Retrieves the timestamp of given type from the log entry.
575 ///
576 /// The information about timestamp availability can be retrieved using the
577 /// [`buffer_check_ts_type_available`] function.
578 ///
579 /// # Returns
580 ///
581 /// * `Ok(Duration)` - Timestamp of the entry as a [`Duration`] struct.
582 /// * `Err(std::io::Error)` - An error.
583 ///
584 /// [`Duration`]: std::time::Duration
585 ///
586 /// # Errors
587 ///
588 /// * [`std::io::ErrorKind::InvalidInput`] - Invalid value of order.
589 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
590 /// * [`std::io::ErrorKind::Uncategorized`] - The timestamp is missing.
591 pub fn get_timestamp(&self, stamp_type: SortingOrder) -> Result<Duration> {
592 let mut ts = timespec {
593 tv_sec: 0,
594 tv_nsec: 0,
595 };
596 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
597 // This method only reads from the memory of the object, so it is ok for it to take
598 // a shared reference.
599 match unsafe { dlogutil_entry_get_timestamp(self.entry, stamp_type.into(), &mut ts) } {
600 0 => Ok(Duration::new(ts.tv_sec as u64, ts.tv_nsec as u32)),
601 e => Err(Error::from_raw_os_error(-e)),
602 }
603 }
604
605 /// Retrieves the TID (thread identificator) of the log sender.
606 ///
607 /// If [`LogIdKmsg`] is used as the buffer, this function will always return
608 /// `TIZEN_ERROR_NO_DATA`.
609 /// This is because the KMSG buffer contains no TID information.
610 ///
611 /// [`LogIdKmsg`]: BufferId::LogIdKmsg
612 ///
613 /// # Returns
614 ///
615 /// * `Ok(i32)` - TID of the log sender.
616 /// * `Err(std::io::Error)` - An error.
617 ///
618 /// # Errors
619 ///
620 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
621 /// * [`std::io::ErrorKind::Uncategorized`] - TID is missing or not applicable.
622 pub fn get_tid(&self) -> Result<i32> {
623 let mut tid = 0;
624 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
625 // This method only reads from the memory of the object, so it is ok for it to take
626 // a shared reference.
627 match unsafe { dlogutil_entry_get_tid(self.entry, &mut tid) } {
628 0 => Ok(tid),
629 e => Err(Error::from_raw_os_error(-e)),
630 }
631 }
632
633 /// Retrieves the PID (process identificator) of the log sender.
634 ///
635 /// If [`LogIdKmsg`] is used as the buffer, this function will always return
636 /// `TIZEN_ERROR_NO_DATA`.
637 /// This is because the KMSG buffer contains no PID information.
638 ///
639 /// [`LogIdKmsg`]: BufferId::LogIdKmsg
640 ///
641 /// # Returns
642 ///
643 /// * `Ok(i32)` - PID of the log sender.
644 /// * `Err(std::io::Error)` - An error.
645 ///
646 /// # Errors
647 ///
648 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
649 /// * [`std::io::ErrorKind::Uncategorized`] - PID is missing or not applicable.
650 pub fn get_pid(&self) -> Result<i32> {
651 let mut pid = 0;
652 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
653 // This method only reads from the memory of the object, so it is ok for it to take
654 // a shared reference.
655 match unsafe { dlogutil_entry_get_pid(self.entry, &mut pid) } {
656 0 => Ok(pid),
657 e => Err(Error::from_raw_os_error(-e)),
658 }
659 }
660
661 /// Retrieves the priority level metadata of the log entry.
662 ///
663 /// # Returns
664 ///
665 /// * `Ok(Priority)` - Log priority.
666 /// * `Err(std::io::Error)` - An error.
667 ///
668 /// # Errors
669 ///
670 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
671 /// * [`std::io::ErrorKind::Uncategorized`] - The priority is missing.
672 pub fn get_priority(&self) -> Result<Priority> {
673 let mut prio = log_priority::DLOG_UNKNOWN;
674 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
675 // This method only reads from the memory of the object, so it is ok for it to take
676 // a shared reference.
677 match unsafe { dlogutil_entry_get_priority(self.entry, &mut prio) } {
678 0 => Ok(prio.into()),
679 e => Err(Error::from_raw_os_error(-e)),
680 }
681 }
682
683 /// Retrieves the tag (arbitrary label) of the log entry.
684 ///
685 /// In some rare cases the entry may be malformed and the tag
686 /// may turn out to be unavailable.
687 ///
688 /// In such cases, an empty string may be returned instead.
689 ///
690 /// # Returns
691 ///
692 /// * `Ok(&str)` - Log tag.
693 /// * `Err(std::io::Error)` - An error.
694 ///
695 /// # Errors
696 ///
697 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
698 /// * [`std::io::ErrorKind::Uncategorized`] - The tag is missing.
699 pub fn get_tag(&self) -> Result<&str> {
700 let mut tag_ptr = null();
701 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
702 // The function returns either NULL, in which case we return Err,
703 // or a string with same lifetime as self.entry, in which case we can safely
704 // call CStr::from_ptr and return it in an Ok.
705 // This method only reads from the memory of the object, so it is ok for it to take
706 // a shared reference.
707 unsafe {
708 match dlogutil_entry_get_tag(self.entry, &mut tag_ptr) {
709 0 => Ok(CStr::from_ptr(tag_ptr).to_str().unwrap()),
710 e => Err(Error::from_raw_os_error(-e)),
711 }
712 }
713 }
714
715 /// Retrieves the message (without any metadata) of the log entry.
716 ///
717 /// In some rare cases the entry may be malformed and the message
718 /// may turn out to be unavailable.
719 ///
720 /// In such cases, an empty string may be returned instead.
721 ///
722 /// # Returns
723 ///
724 /// * `Ok(&str)` - Log message.
725 /// * `Err(std::io::Error)` - An error.
726 ///
727 /// # Errors
728 ///
729 /// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
730 /// * [`std::io::ErrorKind::Uncategorized`] - The message is missing.
731 pub fn get_message(&self) -> Result<&str> {
732 let mut msg_ptr = null();
733 // SAFETY: the pointer is guaranteed to be correct by the way it's created.
734 // The function returns either NULL, in which case we return Err,
735 // or a string with same lifetime as self.entry, in which case we can safely
736 // call CStr::from_ptr and return it in an Ok.
737 // This method only reads from the memory of the object, so it is ok for it to take
738 // a shared reference.
739 unsafe {
740 match dlogutil_entry_get_message(self.entry, &mut msg_ptr) {
741 0 => Ok(CStr::from_ptr(msg_ptr).to_str().unwrap()),
742 e => Err(Error::from_raw_os_error(-e)),
743 }
744 }
745 }
746}
747
748/// Gets the human-readable, constant name of a buffer.
749///
750/// # Returns
751///
752/// * `Ok(&str)` - The name of the passed buffer.
753/// * `Err(std::io::Error)` - An error.
754///
755/// # Errors
756///
757/// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
758pub fn buffer_get_name(buffer: BufferId) -> Result<&'static str> {
759 let mut name_ptr = null();
760 // SAFETY: the function is safe by itself provided the target is a valid pointer.
761 // The function returns either NULL, in which case we return Err,
762 // or a string with static lifetime, in which case we can safely call
763 // CStr::from_ptr and return it in an Ok.
764 unsafe {
765 match dlogutil_buffer_get_name(buffer.into(), &mut name_ptr) {
766 0 => Ok(CStr::from_ptr(name_ptr).to_str().unwrap()),
767 e => Err(Error::from_raw_os_error(-e)),
768 }
769 }
770}
771
772/// Gets the default sorting timestamp type of a buffer.
773///
774/// This is the timestamp type that will be used for sorting by default.
775/// We assume that it is always available and the input is sorted by it.
776///
777/// # Returns
778///
779/// * `Ok(SortingOrder)` - The default timestamp type of the passed buffer.
780/// * `Err(std::io::Error)` - An error.
781///
782/// # Errors
783///
784/// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
785/// * [`std::io::ErrorKind::Uncategorized`] - Couldn't read config file.
786pub fn buffer_get_default_ts_type(buffer: BufferId) -> Result<SortingOrder> {
787 let mut typ = dlogutil_sorting_order::DLOGUTIL_SORT_SENT_MONO;
788 // SAFETY: the function is safe by itself provided the target is a valid pointer.
789 match unsafe { dlogutil_buffer_get_default_ts_type(buffer.into(), &mut typ) } {
790 0 => Ok(typ.into()),
791 e => Err(Error::from_raw_os_error(-e)),
792 }
793}
794
795/// Checks if a buffer contains timestamps of a given type.
796///
797/// If false is returned, the timestamp may still be available in some of the logs.
798/// However, if true is returned, the timestamp will always be available.
799/// You can check the timestamp availability per log using the [`get_timestamp`]
800/// function.
801///
802/// [`get_timestamp`]: DlogutilEntry::get_timestamp
803///
804/// # Returns
805///
806/// * `Ok(bool)` - Whether the given timestamp type is guaranteed to be available.
807/// * `Err(std::io::Error)` - An error.
808///
809/// # Errors
810///
811/// * [`std::io::ErrorKind::InvalidInput`] - More than one buffer.
812/// * [`std::io::ErrorKind::InvalidInput`] - One of the pointers was NULL.
813/// * [`std::io::ErrorKind::Uncategorized`] - Couldn't read config file.
814pub fn buffer_check_ts_type_available(buffer: BufferId, stamp_type: SortingOrder) -> Result<bool> {
815 let mut available = false;
816 // SAFETY: the function is safe by itself provided the target is a valid pointer.
817 match unsafe {
818 dlogutil_buffer_check_ts_type_available(buffer.into(), stamp_type.into(), &mut available)
819 } {
820 0 => Ok(available),
821 e => Err(Error::from_raw_os_error(-e)),
822 }
823}