1 | //! |
2 | //! libudev Bindings for Rust |
3 | //! |
4 | |
5 | #![warn (missing_docs)] |
6 | |
7 | extern crate io_lifetimes; |
8 | extern crate libc; |
9 | pub extern crate libudev_sys as ffi; |
10 | #[cfg (feature = "mio06" )] |
11 | pub extern crate mio06 as mio; |
12 | #[cfg (feature = "mio07" )] |
13 | pub extern crate mio07 as mio; |
14 | #[cfg (feature = "mio08" )] |
15 | pub extern crate mio08 as mio; |
16 | #[cfg (feature = "mio10" )] |
17 | pub extern crate mio10 as mio; |
18 | |
19 | pub use device::{Attributes, Device, DeviceType, Properties}; |
20 | pub use enumerator::{Devices, Enumerator}; |
21 | #[cfg (feature = "hwdb" )] |
22 | pub use hwdb::Hwdb; |
23 | pub use list::{Entry, List}; |
24 | pub use monitor::{ |
25 | Builder as MonitorBuilder, Event, EventType, Socket as MonitorSocket, |
26 | SocketIter as MonitorSocketIter, |
27 | }; |
28 | pub use udev::Udev; |
29 | |
30 | macro_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 |
43 | pub 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. |
57 | pub 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 |
75 | pub 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. |
88 | pub 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 |
106 | macro_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 | |
113 | macro_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 | |
120 | macro_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 | |
140 | macro_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 | |
150 | macro_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 | |
186 | macro_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 | |
199 | mod device; |
200 | mod enumerator; |
201 | #[cfg (feature = "hwdb" )] |
202 | mod hwdb; |
203 | mod list; |
204 | mod monitor; |
205 | mod udev; |
206 | mod util; |
207 | |