]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
88a6477e KS |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2008-2012 Kay Sievers <kay@vrfy.org> | |
6 | Copyright 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk> | |
7 | ||
8 | systemd is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU Lesser General Public License as published by | |
10 | the Free Software Foundation; either version 2.1 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | systemd is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | Lesser General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU Lesser General Public License | |
19 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
20 | ***/ | |
64ccdf82 | 21 | |
64ccdf82 | 22 | #include <errno.h> |
cf0fbc49 TA |
23 | #include <stddef.h> |
24 | #include <stdlib.h> | |
14cb7336 | 25 | #include <sys/inotify.h> |
cf0fbc49 | 26 | #include <unistd.h> |
64ccdf82 | 27 | |
b5efdb8a | 28 | #include "alloc-util.h" |
3ffd4af2 | 29 | #include "fd-util.h" |
c004493c | 30 | #include "io-util.h" |
64ccdf82 KS |
31 | #include "libudev-private.h" |
32 | ||
ce1d6d7f KS |
33 | /** |
34 | * SECTION:libudev-queue | |
35 | * @short_description: access to currently active events | |
36 | * | |
9ea28c55 | 37 | * This exports the current state of the udev processing queue. |
ce1d6d7f KS |
38 | */ |
39 | ||
40 | /** | |
41 | * udev_queue: | |
42 | * | |
43 | * Opaque object representing the current event queue in the udev daemon. | |
44 | */ | |
64ccdf82 | 45 | struct udev_queue { |
912541b0 KS |
46 | struct udev *udev; |
47 | int refcount; | |
14cb7336 | 48 | int fd; |
64ccdf82 KS |
49 | }; |
50 | ||
8d6bc73a KS |
51 | /** |
52 | * udev_queue_new: | |
53 | * @udev: udev library context | |
54 | * | |
55 | * The initial refcount is 1, and needs to be decremented to | |
56 | * release the resources of the udev queue context. | |
57 | * | |
58 | * Returns: the udev queue context, or #NULL on error. | |
59 | **/ | |
54cf0b7f | 60 | _public_ struct udev_queue *udev_queue_new(struct udev *udev) |
64ccdf82 | 61 | { |
912541b0 KS |
62 | struct udev_queue *udev_queue; |
63 | ||
309f631d LP |
64 | if (udev == NULL) { |
65 | errno = EINVAL; | |
912541b0 | 66 | return NULL; |
309f631d | 67 | } |
912541b0 | 68 | |
955d98c9 | 69 | udev_queue = new0(struct udev_queue, 1); |
309f631d LP |
70 | if (udev_queue == NULL) { |
71 | errno = ENOMEM; | |
912541b0 | 72 | return NULL; |
309f631d | 73 | } |
9ea28c55 | 74 | |
912541b0 KS |
75 | udev_queue->refcount = 1; |
76 | udev_queue->udev = udev; | |
14cb7336 | 77 | udev_queue->fd = -1; |
912541b0 | 78 | return udev_queue; |
64ccdf82 KS |
79 | } |
80 | ||
8d6bc73a KS |
81 | /** |
82 | * udev_queue_ref: | |
83 | * @udev_queue: udev queue context | |
84 | * | |
85 | * Take a reference of a udev queue context. | |
86 | * | |
87 | * Returns: the same udev queue context. | |
88 | **/ | |
54cf0b7f | 89 | _public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) |
64ccdf82 | 90 | { |
912541b0 KS |
91 | if (udev_queue == NULL) |
92 | return NULL; | |
9ea28c55 | 93 | |
912541b0 KS |
94 | udev_queue->refcount++; |
95 | return udev_queue; | |
64ccdf82 KS |
96 | } |
97 | ||
8d6bc73a KS |
98 | /** |
99 | * udev_queue_unref: | |
100 | * @udev_queue: udev queue context | |
101 | * | |
102 | * Drop a reference of a udev queue context. If the refcount reaches zero, | |
103 | * the resources of the queue context will be released. | |
c1959569 | 104 | * |
725d7e6c | 105 | * Returns: #NULL |
8d6bc73a | 106 | **/ |
20bbd54f | 107 | _public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) |
64ccdf82 | 108 | { |
912541b0 | 109 | if (udev_queue == NULL) |
20bbd54f | 110 | return NULL; |
9ea28c55 | 111 | |
912541b0 KS |
112 | udev_queue->refcount--; |
113 | if (udev_queue->refcount > 0) | |
725d7e6c | 114 | return NULL; |
9ea28c55 | 115 | |
14cb7336 KS |
116 | safe_close(udev_queue->fd); |
117 | ||
5fecf46d | 118 | return mfree(udev_queue); |
64ccdf82 KS |
119 | } |
120 | ||
8d6bc73a KS |
121 | /** |
122 | * udev_queue_get_udev: | |
123 | * @udev_queue: udev queue context | |
124 | * | |
125 | * Retrieve the udev library context the queue context was created with. | |
126 | * | |
127 | * Returns: the udev library context. | |
128 | **/ | |
54cf0b7f | 129 | _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) |
64ccdf82 | 130 | { |
309f631d LP |
131 | if (udev_queue == NULL) { |
132 | errno = EINVAL; | |
912541b0 | 133 | return NULL; |
309f631d | 134 | } |
912541b0 | 135 | return udev_queue->udev; |
64ccdf82 KS |
136 | } |
137 | ||
8d6bc73a KS |
138 | /** |
139 | * udev_queue_get_kernel_seqnum: | |
140 | * @udev_queue: udev queue context | |
141 | * | |
9ea28c55 | 142 | * This function is deprecated. |
21dbe43a | 143 | * |
9ea28c55 | 144 | * Returns: 0. |
8d6bc73a | 145 | **/ |
54cf0b7f | 146 | _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) |
64ccdf82 | 147 | { |
912541b0 | 148 | return 0; |
f503f6b2 AJ |
149 | } |
150 | ||
8d6bc73a KS |
151 | /** |
152 | * udev_queue_get_udev_seqnum: | |
153 | * @udev_queue: udev queue context | |
154 | * | |
9ea28c55 | 155 | * This function is deprecated. |
21dbe43a | 156 | * |
9ea28c55 | 157 | * Returns: 0. |
8d6bc73a | 158 | **/ |
54cf0b7f | 159 | _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) |
f503f6b2 | 160 | { |
9ea28c55 | 161 | return 0; |
f503f6b2 AJ |
162 | } |
163 | ||
8d6bc73a KS |
164 | /** |
165 | * udev_queue_get_udev_is_active: | |
166 | * @udev_queue: udev queue context | |
167 | * | |
21dbe43a KS |
168 | * Check if udev is active on the system. |
169 | * | |
8d6bc73a KS |
170 | * Returns: a flag indicating if udev is active. |
171 | **/ | |
54cf0b7f | 172 | _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) |
f503f6b2 | 173 | { |
9ea28c55 | 174 | return access("/run/udev/control", F_OK) >= 0; |
11d5eec2 KS |
175 | } |
176 | ||
8d6bc73a KS |
177 | /** |
178 | * udev_queue_get_queue_is_empty: | |
179 | * @udev_queue: udev queue context | |
180 | * | |
21dbe43a KS |
181 | * Check if udev is currently processing any events. |
182 | * | |
8d6bc73a KS |
183 | * Returns: a flag indicating if udev is currently handling events. |
184 | **/ | |
54cf0b7f | 185 | _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) |
64ccdf82 | 186 | { |
45e60962 | 187 | return access("/run/udev/queue", F_OK) < 0; |
64ccdf82 KS |
188 | } |
189 | ||
8d6bc73a KS |
190 | /** |
191 | * udev_queue_get_seqnum_sequence_is_finished: | |
192 | * @udev_queue: udev queue context | |
193 | * @start: first event sequence number | |
194 | * @end: last event sequence number | |
195 | * | |
9ea28c55 KS |
196 | * This function is deprecated, it just returns the result of |
197 | * udev_queue_get_queue_is_empty(). | |
21dbe43a | 198 | * |
9ea28c55 | 199 | * Returns: a flag indicating if udev is currently handling events. |
8d6bc73a | 200 | **/ |
54cf0b7f | 201 | _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, |
912541b0 | 202 | unsigned long long int start, unsigned long long int end) |
64ccdf82 | 203 | { |
9ea28c55 | 204 | return udev_queue_get_queue_is_empty(udev_queue); |
f503f6b2 AJ |
205 | } |
206 | ||
8d6bc73a KS |
207 | /** |
208 | * udev_queue_get_seqnum_is_finished: | |
209 | * @udev_queue: udev queue context | |
210 | * @seqnum: sequence number | |
211 | * | |
9ea28c55 KS |
212 | * This function is deprecated, it just returns the result of |
213 | * udev_queue_get_queue_is_empty(). | |
21dbe43a | 214 | * |
9ea28c55 | 215 | * Returns: a flag indicating if udev is currently handling events. |
8d6bc73a | 216 | **/ |
54cf0b7f | 217 | _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) |
f503f6b2 | 218 | { |
9ea28c55 | 219 | return udev_queue_get_queue_is_empty(udev_queue); |
64ccdf82 KS |
220 | } |
221 | ||
8d6bc73a KS |
222 | /** |
223 | * udev_queue_get_queued_list_entry: | |
224 | * @udev_queue: udev queue context | |
225 | * | |
9ea28c55 | 226 | * This function is deprecated. |
21dbe43a | 227 | * |
9ea28c55 | 228 | * Returns: NULL. |
8d6bc73a | 229 | **/ |
54cf0b7f | 230 | _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) |
64ccdf82 | 231 | { |
309f631d | 232 | errno = ENODATA; |
9ea28c55 | 233 | return NULL; |
64ccdf82 | 234 | } |
14cb7336 KS |
235 | |
236 | /** | |
237 | * udev_queue_get_fd: | |
238 | * @udev_queue: udev queue context | |
239 | * | |
240 | * Returns: a file descriptor to watch for a queue to become empty. | |
241 | */ | |
242 | _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { | |
243 | int fd; | |
244 | int r; | |
245 | ||
246 | if (udev_queue->fd >= 0) | |
247 | return udev_queue->fd; | |
248 | ||
249 | fd = inotify_init1(IN_CLOEXEC); | |
250 | if (fd < 0) | |
251 | return -errno; | |
252 | ||
8a7a0c19 | 253 | r = inotify_add_watch(fd, "/run/udev" , IN_DELETE); |
14cb7336 KS |
254 | if (r < 0) { |
255 | r = -errno; | |
256 | close(fd); | |
257 | return r; | |
258 | } | |
259 | ||
260 | udev_queue->fd = fd; | |
261 | return fd; | |
262 | } | |
263 | ||
264 | /** | |
265 | * udev_queue_flush: | |
266 | * @udev_queue: udev queue context | |
267 | * | |
268 | * Returns: the result of clearing the watch for queue changes. | |
269 | */ | |
270 | _public_ int udev_queue_flush(struct udev_queue *udev_queue) { | |
271 | if (udev_queue->fd < 0) | |
272 | return -EINVAL; | |
273 | ||
274 | return flush_fd(udev_queue->fd); | |
275 | } |