]>
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 | ||
912541b0 | 118 | free(udev_queue); |
20bbd54f | 119 | return NULL; |
64ccdf82 KS |
120 | } |
121 | ||
8d6bc73a KS |
122 | /** |
123 | * udev_queue_get_udev: | |
124 | * @udev_queue: udev queue context | |
125 | * | |
126 | * Retrieve the udev library context the queue context was created with. | |
127 | * | |
128 | * Returns: the udev library context. | |
129 | **/ | |
54cf0b7f | 130 | _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) |
64ccdf82 | 131 | { |
309f631d LP |
132 | if (udev_queue == NULL) { |
133 | errno = EINVAL; | |
912541b0 | 134 | return NULL; |
309f631d | 135 | } |
912541b0 | 136 | return udev_queue->udev; |
64ccdf82 KS |
137 | } |
138 | ||
8d6bc73a KS |
139 | /** |
140 | * udev_queue_get_kernel_seqnum: | |
141 | * @udev_queue: udev queue context | |
142 | * | |
9ea28c55 | 143 | * This function is deprecated. |
21dbe43a | 144 | * |
9ea28c55 | 145 | * Returns: 0. |
8d6bc73a | 146 | **/ |
54cf0b7f | 147 | _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) |
64ccdf82 | 148 | { |
912541b0 | 149 | return 0; |
f503f6b2 AJ |
150 | } |
151 | ||
8d6bc73a KS |
152 | /** |
153 | * udev_queue_get_udev_seqnum: | |
154 | * @udev_queue: udev queue context | |
155 | * | |
9ea28c55 | 156 | * This function is deprecated. |
21dbe43a | 157 | * |
9ea28c55 | 158 | * Returns: 0. |
8d6bc73a | 159 | **/ |
54cf0b7f | 160 | _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) |
f503f6b2 | 161 | { |
9ea28c55 | 162 | return 0; |
f503f6b2 AJ |
163 | } |
164 | ||
8d6bc73a KS |
165 | /** |
166 | * udev_queue_get_udev_is_active: | |
167 | * @udev_queue: udev queue context | |
168 | * | |
21dbe43a KS |
169 | * Check if udev is active on the system. |
170 | * | |
8d6bc73a KS |
171 | * Returns: a flag indicating if udev is active. |
172 | **/ | |
54cf0b7f | 173 | _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) |
f503f6b2 | 174 | { |
9ea28c55 | 175 | return access("/run/udev/control", F_OK) >= 0; |
11d5eec2 KS |
176 | } |
177 | ||
8d6bc73a KS |
178 | /** |
179 | * udev_queue_get_queue_is_empty: | |
180 | * @udev_queue: udev queue context | |
181 | * | |
21dbe43a KS |
182 | * Check if udev is currently processing any events. |
183 | * | |
8d6bc73a KS |
184 | * Returns: a flag indicating if udev is currently handling events. |
185 | **/ | |
54cf0b7f | 186 | _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) |
64ccdf82 | 187 | { |
45e60962 | 188 | return access("/run/udev/queue", F_OK) < 0; |
64ccdf82 KS |
189 | } |
190 | ||
8d6bc73a KS |
191 | /** |
192 | * udev_queue_get_seqnum_sequence_is_finished: | |
193 | * @udev_queue: udev queue context | |
194 | * @start: first event sequence number | |
195 | * @end: last event sequence number | |
196 | * | |
9ea28c55 KS |
197 | * This function is deprecated, it just returns the result of |
198 | * udev_queue_get_queue_is_empty(). | |
21dbe43a | 199 | * |
9ea28c55 | 200 | * Returns: a flag indicating if udev is currently handling events. |
8d6bc73a | 201 | **/ |
54cf0b7f | 202 | _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, |
912541b0 | 203 | unsigned long long int start, unsigned long long int end) |
64ccdf82 | 204 | { |
9ea28c55 | 205 | return udev_queue_get_queue_is_empty(udev_queue); |
f503f6b2 AJ |
206 | } |
207 | ||
8d6bc73a KS |
208 | /** |
209 | * udev_queue_get_seqnum_is_finished: | |
210 | * @udev_queue: udev queue context | |
211 | * @seqnum: sequence number | |
212 | * | |
9ea28c55 KS |
213 | * This function is deprecated, it just returns the result of |
214 | * udev_queue_get_queue_is_empty(). | |
21dbe43a | 215 | * |
9ea28c55 | 216 | * Returns: a flag indicating if udev is currently handling events. |
8d6bc73a | 217 | **/ |
54cf0b7f | 218 | _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) |
f503f6b2 | 219 | { |
9ea28c55 | 220 | return udev_queue_get_queue_is_empty(udev_queue); |
64ccdf82 KS |
221 | } |
222 | ||
8d6bc73a KS |
223 | /** |
224 | * udev_queue_get_queued_list_entry: | |
225 | * @udev_queue: udev queue context | |
226 | * | |
9ea28c55 | 227 | * This function is deprecated. |
21dbe43a | 228 | * |
9ea28c55 | 229 | * Returns: NULL. |
8d6bc73a | 230 | **/ |
54cf0b7f | 231 | _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) |
64ccdf82 | 232 | { |
309f631d | 233 | errno = ENODATA; |
9ea28c55 | 234 | return NULL; |
64ccdf82 | 235 | } |
14cb7336 KS |
236 | |
237 | /** | |
238 | * udev_queue_get_fd: | |
239 | * @udev_queue: udev queue context | |
240 | * | |
241 | * Returns: a file descriptor to watch for a queue to become empty. | |
242 | */ | |
243 | _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { | |
244 | int fd; | |
245 | int r; | |
246 | ||
247 | if (udev_queue->fd >= 0) | |
248 | return udev_queue->fd; | |
249 | ||
250 | fd = inotify_init1(IN_CLOEXEC); | |
251 | if (fd < 0) | |
252 | return -errno; | |
253 | ||
8a7a0c19 | 254 | r = inotify_add_watch(fd, "/run/udev" , IN_DELETE); |
14cb7336 KS |
255 | if (r < 0) { |
256 | r = -errno; | |
257 | close(fd); | |
258 | return r; | |
259 | } | |
260 | ||
261 | udev_queue->fd = fd; | |
262 | return fd; | |
263 | } | |
264 | ||
265 | /** | |
266 | * udev_queue_flush: | |
267 | * @udev_queue: udev queue context | |
268 | * | |
269 | * Returns: the result of clearing the watch for queue changes. | |
270 | */ | |
271 | _public_ int udev_queue_flush(struct udev_queue *udev_queue) { | |
272 | if (udev_queue->fd < 0) | |
273 | return -EINVAL; | |
274 | ||
275 | return flush_fd(udev_queue->fd); | |
276 | } |