| 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 | |