xref: /linux/rust/kernel/seq_file.rs (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Seq file bindings.
4 //!
5 //! C header: [`include/linux/seq_file.h`](srctree/include/linux/seq_file.h)
6 
7 use crate::{bindings, c_str, types::NotThreadSafe, types::Opaque};
8 
9 /// A utility for generating the contents of a seq file.
10 #[repr(transparent)]
11 pub struct SeqFile {
12     inner: Opaque<bindings::seq_file>,
13     _not_send: NotThreadSafe,
14 }
15 
16 impl SeqFile {
17     /// Creates a new [`SeqFile`] from a raw pointer.
18     ///
19     /// # Safety
20     ///
21     /// The caller must ensure that for the duration of 'a the following is satisfied:
22     /// * The pointer points at a valid `struct seq_file`.
23     /// * The `struct seq_file` is not accessed from any other thread.
24     pub unsafe fn from_raw<'a>(ptr: *mut bindings::seq_file) -> &'a SeqFile {
25         // SAFETY: The caller ensures that the reference is valid for 'a. There's no way to trigger
26         // a data race by using the `&SeqFile` since this is the only thread accessing the seq_file.
27         //
28         // CAST: The layout of `struct seq_file` and `SeqFile` is compatible.
29         unsafe { &*ptr.cast() }
30     }
31 
32     /// Used by the [`seq_print`] macro.
33     pub fn call_printf(&self, args: core::fmt::Arguments<'_>) {
34         // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.
35         unsafe {
36             bindings::seq_printf(
37                 self.inner.get(),
38                 c_str!("%pA").as_char_ptr(),
39                 &args as *const _ as *const core::ffi::c_void,
40             );
41         }
42     }
43 }
44 
45 /// Write to a [`SeqFile`] with the ordinary Rust formatting syntax.
46 #[macro_export]
47 macro_rules! seq_print {
48     ($m:expr, $($arg:tt)+) => (
49         $m.call_printf(format_args!($($arg)+))
50     );
51 }
52 pub use seq_print;
53