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;