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