1#![cfg(target_os = "linux")]
32
33pub use udev::{
34 Attribute, Attributes, Device, Enumerator, Event, EventType, Properties,
35 Property,
36};
37
38mod util;
39
40use std::ffi::OsStr;
41use std::io;
42use std::os::unix::io::{AsRawFd, RawFd};
43
44use mio::event::Source;
45use mio::unix::SourceFd;
46use mio::{Interest, Registry, Token};
47
48pub struct MonitorBuilder {
55 builder: udev::MonitorBuilder,
56}
57
58impl MonitorBuilder {
59 #[inline(always)]
61 pub fn new() -> io::Result<Self> {
62 Ok(MonitorBuilder {
63 builder: udev::MonitorBuilder::new()?,
64 })
65 }
66
67 #[inline(always)]
68 fn map(builder: udev::MonitorBuilder) -> Self {
69 MonitorBuilder { builder }
70 }
71
72 #[inline(always)]
74 pub fn match_subsystem<T>(self, subsystem: T) -> io::Result<Self>
75 where
76 T: AsRef<OsStr>,
77 {
78 self.builder.match_subsystem::<T>(subsystem).map(Self::map)
79 }
80
81 #[inline(always)]
84 pub fn match_subsystem_devtype<T, U>(
85 self,
86 subsystem: T,
87 devtype: U,
88 ) -> io::Result<Self>
89 where
90 T: AsRef<OsStr>,
91 U: AsRef<OsStr>,
92 {
93 self.builder
94 .match_subsystem_devtype::<T, U>(subsystem, devtype)
95 .map(Self::map)
96 }
97
98 #[inline(always)]
100 pub fn match_tag<T>(self, tag: T) -> io::Result<Self>
101 where
102 T: AsRef<OsStr>,
103 {
104 self.builder.match_tag::<T>(tag).map(Self::map)
105 }
106
107 #[inline(always)]
109 pub fn clear_filters(self) -> io::Result<Self> {
110 self.builder.clear_filters().map(Self::map)
111 }
112
113 pub fn listen(self) -> io::Result<MonitorSocket> {
117 MonitorSocket::new(self.builder.listen()?)
118 }
119}
120
121pub struct MonitorSocket {
124 monitor: udev::MonitorSocket,
125}
126
127impl MonitorSocket {
128 fn new(monitor: udev::MonitorSocket) -> io::Result<MonitorSocket> {
129 use crate::util::cvt;
130 use libc::{
131 fcntl, FD_CLOEXEC, F_GETFD, F_GETFL, F_SETFD, F_SETFL, O_NONBLOCK,
132 };
133
134 let fd = monitor.as_raw_fd();
135
136 let r = unsafe { cvt(fcntl(fd, F_GETFD))? };
138
139 if (r & FD_CLOEXEC) != FD_CLOEXEC {
140 unsafe { cvt(fcntl(fd, F_SETFD, r | FD_CLOEXEC))? };
141 }
142
143 let r = unsafe { cvt(fcntl(fd, F_GETFL))? };
146
147 if (r & O_NONBLOCK) != O_NONBLOCK {
148 unsafe { cvt(fcntl(fd, F_SETFL, r | O_NONBLOCK))? };
149 }
150
151 Ok(MonitorSocket { monitor })
152 }
153
154 #[inline(always)]
155 fn fd(&self) -> RawFd {
156 self.monitor.as_raw_fd()
157 }
158}
159
160impl AsRawFd for MonitorSocket {
161 fn as_raw_fd(&self) -> RawFd {
162 self.fd()
163 }
164}
165
166impl Source for MonitorSocket {
167 fn register(
168 &mut self,
169 registry: &Registry,
170 token: Token,
171 interest: Interest,
172 ) -> io::Result<()> {
173 SourceFd(&self.fd()).register(registry, token, interest)
174 }
175
176 fn reregister(
177 &mut self,
178 registry: &Registry,
179 token: Token,
180 interest: Interest,
181 ) -> io::Result<()> {
182 SourceFd(&self.fd()).reregister(registry, token, interest)
183 }
184
185 fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
186 SourceFd(&self.fd()).deregister(registry)
187 }
188}
189
190impl Iterator for MonitorSocket {
191 type Item = Event;
192
193 fn next(&mut self) -> Option<Self::Item> {
194 self.monitor.next()
195 }
196}