udev/
lib.rs

1//!
2//! libudev Bindings for Rust
3//!
4
5#![warn(missing_docs)]
6
7extern crate io_lifetimes;
8extern crate libc;
9pub extern crate libudev_sys as ffi;
10#[cfg(feature = "mio06")]
11pub extern crate mio06 as mio;
12#[cfg(feature = "mio07")]
13pub extern crate mio07 as mio;
14#[cfg(feature = "mio08")]
15pub extern crate mio08 as mio;
16#[cfg(feature = "mio10")]
17pub extern crate mio10 as mio;
18
19pub use device::{Attributes, Device, DeviceType, Properties};
20pub use enumerator::{Devices, Enumerator};
21#[cfg(feature = "hwdb")]
22pub use hwdb::Hwdb;
23pub use list::{Entry, List};
24pub use monitor::{
25    Builder as MonitorBuilder, Event, EventType, Socket as MonitorSocket,
26    SocketIter as MonitorSocketIter,
27};
28pub use udev::Udev;
29
30macro_rules! try_alloc {
31    ($exp:expr) => {{
32        let ptr = $exp;
33
34        if ptr.is_null() {
35            return Err(std::io::Error::last_os_error());
36        }
37
38        ptr
39    }};
40}
41
42/// Receive the underlying raw pointer
43pub trait AsRaw<T: 'static> {
44    /// Get a reference of the underlying struct.
45    ///
46    /// The reference count will not be increased.
47    fn as_raw(&self) -> *mut T;
48
49    /// Convert the object into the underlying pointer.
50    ///
51    /// You are responsible for freeing the object.
52    fn into_raw(self) -> *mut T;
53}
54
55/// Receive the underlying raw pointer for types with an associated `udev` struct which must
56/// outlive them.
57pub trait AsRawWithContext<T: 'static> {
58    /// Get a reference of the underlying struct.
59    ///
60    /// The reference count will not be increased.
61    fn as_raw(&self) -> *mut T;
62
63    /// The `udev` context with which this struct was created.  This must live at least as long as
64    /// the struct itself or undefined behavior will result.
65    fn udev(&self) -> &Udev;
66
67    /// Convert the object into the raw `udev` pointer and the underlying pointer for this object.
68    ///
69    /// You are responsible for freeing both.  You're also responsible for ensuring that the `udev`
70    /// pointer is not freed until after this object's pointer is freed.
71    fn into_raw_with_context(self) -> (*mut ffi::udev, *mut T);
72}
73
74/// Convert from a raw pointer
75pub trait FromRaw<T: 'static> {
76    /// Create an object from a given raw pointer.
77    ///
78    /// The reference count will not be increased, be sure not to free this pointer.
79    ///
80    /// ## Safety
81    ///
82    /// The pointer has to be a valid reference to the expected underlying udev-struct or undefined
83    /// behaviour might occur.
84    unsafe fn from_raw(ptr: *mut T) -> Self;
85}
86
87/// Convert from a raw pointer for types which must be associated with a `Udev` context object.
88pub trait FromRawWithContext<T: 'static> {
89    /// Create an object from a given raw pointer and `udev` context pointer.
90    ///
91    /// The reference count will not be increased, be sure not to free this pointer.
92    ///
93    /// ## Safety
94    ///
95    /// The `udev` pointer must correspond to the `udev` pointer used when `ptr` was created.  If
96    /// not memory corruption and undefined behavior will result.
97    ///
98    /// Both the `udev` and `ptr` pointers must be a valid reference to the expected underlying udev-struct or undefined
99    /// behaviour might occur.  Do NOT attempt to free either pointer; `udev_unref` and the
100    /// corresponding `*_unref` function for `ptr` will be called automatically when this type is
101    /// dropped.
102    unsafe fn from_raw_with_context(udev: *mut ffi::udev, ptr: *mut T) -> Self;
103}
104
105/// Convert from a raw pointer and the matching context
106macro_rules! as_ffi {
107    ($struct_:ident, $field:ident, $type_:ty, $ref:path) => {
108        as_raw!($struct_, $field, $type_, $ref);
109        from_raw!($struct_, $field, $type_);
110    };
111}
112
113macro_rules! as_ffi_with_context {
114    ($struct_:ident, $field:ident, $type_:ty, $ref:path) => {
115        as_raw_with_context!($struct_, $field, $type_, $ref);
116        from_raw_with_context!($struct_, $field, $type_);
117    };
118}
119
120macro_rules! as_raw {
121    ($struct_:ident, $field:ident, $type_:ty, $ref:path) => {
122        impl $crate::AsRaw<$type_> for $struct_ {
123            fn as_raw(&self) -> *mut $type_ {
124                self.$field
125            }
126
127            fn into_raw(self) -> *mut $type_ {
128                // Note that all `AsRaw` implementations also implement `Drop` which calls the
129                // `_unref` function that correponds to $type_.  We can't prevent this from
130                // happening, so we have to add a reference here to ensure the returned pointer
131                // remains allocated for the caller.
132                unsafe { $ref(self.$field) };
133
134                self.$field
135            }
136        }
137    };
138}
139
140macro_rules! from_raw {
141    ($struct_:ident, $field:ident, $type_:ty) => {
142        impl $crate::FromRaw<$type_> for $struct_ {
143            unsafe fn from_raw(t: *mut $type_) -> Self {
144                Self { $field: t }
145            }
146        }
147    };
148}
149
150macro_rules! as_raw_with_context {
151    ($struct_:ident, $field:ident, $type_:ty, $ref:path) => {
152        impl $crate::AsRawWithContext<$type_> for $struct_ {
153            fn as_raw(&self) -> *mut $type_ {
154                self.$field
155            }
156
157            fn udev(&self) -> &Udev {
158                &self.udev
159            }
160
161            fn into_raw_with_context(self) -> (*mut ffi::udev, *mut $type_) {
162                // We can't call `self.udev.into_raw()` here, because that will consume
163                // `self.udev`, which is not possible because every type that implements
164                // `AsRawWithContext` also implements `Drop`.  Of course we know that it would be
165                // safe here to just skip the `drop()` on `Udev` and "leak" the `udev` pointer back
166                // to the caller, but the Rust compiler doesn't know that.
167                //
168                // So instead we have to add a new reference to the `udev` pointer before we return
169                // it, because as soon as we leave the scope of this function the `Udev` struct
170                // will be dropped which will call `udev_unref` on it.  If there's only once
171                // reference left that will free the pointer and we'll end up returning a dangling
172                // pointer to the caller.
173                //
174                // For much the same reason, we do the same with the pointer of type $type
175                let udev = self.udev.as_raw();
176                unsafe { ffi::udev_ref(udev) };
177
178                unsafe { $ref(self.$field) };
179
180                (udev, self.$field)
181            }
182        }
183    };
184}
185
186macro_rules! from_raw_with_context {
187    ($struct_:ident, $field:ident, $type_:ty) => {
188        impl $crate::FromRawWithContext<$type_> for $struct_ {
189            unsafe fn from_raw_with_context(udev: *mut ffi::udev, t: *mut $type_) -> Self {
190                Self {
191                    udev: Udev::from_raw(udev),
192                    $field: t,
193                }
194            }
195        }
196    };
197}
198
199mod device;
200mod enumerator;
201#[cfg(feature = "hwdb")]
202mod hwdb;
203mod list;
204mod monitor;
205mod udev;
206mod util;