1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
4 ***/
5
6 #include <errno.h>
7 #include <unistd.h>
8
9 #include "libudev.h"
10
11 #include "alloc-util.h"
12 #include "fd-util.h"
13 #include "io-util.h"
14 #include "udev-util.h"
15
16 /**
17 * SECTION:libudev-queue
18 * @short_description: access to currently active events
19 *
20 * This exports the current state of the udev processing queue.
21 */
22
23 /**
24 * udev_queue:
25 *
26 * Opaque object representing the current event queue in the udev daemon.
27 */
28 struct udev_queue {
29 struct udev *udev;
30 unsigned n_ref;
31 int fd;
32 };
33
34 /**
35 * udev_queue_new:
36 * @udev: udev library context
37 *
38 * The initial refcount is 1, and needs to be decremented to
39 * release the resources of the udev queue context.
40 *
41 * Returns: the udev queue context, or #NULL on error.
42 **/
udev_queue_new(struct udev * udev)43 _public_ struct udev_queue *udev_queue_new(struct udev *udev) {
44 struct udev_queue *udev_queue;
45
46 udev_queue = new(struct udev_queue, 1);
47 if (!udev_queue)
48 return_with_errno(NULL, ENOMEM);
49
50 *udev_queue = (struct udev_queue) {
51 .udev = udev,
52 .n_ref = 1,
53 .fd = -1,
54 };
55
56 return udev_queue;
57 }
58
udev_queue_free(struct udev_queue * udev_queue)59 static struct udev_queue *udev_queue_free(struct udev_queue *udev_queue) {
60 assert(udev_queue);
61
62 safe_close(udev_queue->fd);
63 return mfree(udev_queue);
64 }
65
66 /**
67 * udev_queue_ref:
68 * @udev_queue: udev queue context
69 *
70 * Take a reference of a udev queue context.
71 *
72 * Returns: the same udev queue context.
73 **/
74
75 /**
76 * udev_queue_unref:
77 * @udev_queue: udev queue context
78 *
79 * Drop a reference of a udev queue context. If the refcount reaches zero,
80 * the resources of the queue context will be released.
81 *
82 * Returns: #NULL
83 **/
84 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_queue, udev_queue, udev_queue_free);
85
86 /**
87 * udev_queue_get_udev:
88 * @udev_queue: udev queue context
89 *
90 * Retrieve the udev library context the queue context was created with.
91 *
92 * Returns: the udev library context.
93 **/
udev_queue_get_udev(struct udev_queue * udev_queue)94 _public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) {
95 assert_return_errno(udev_queue, NULL, EINVAL);
96
97 return udev_queue->udev;
98 }
99
100 /**
101 * udev_queue_get_kernel_seqnum:
102 * @udev_queue: udev queue context
103 *
104 * This function is deprecated.
105 *
106 * Returns: 0.
107 **/
udev_queue_get_kernel_seqnum(struct udev_queue * udev_queue)108 _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) {
109 return 0;
110 }
111
112 /**
113 * udev_queue_get_udev_seqnum:
114 * @udev_queue: udev queue context
115 *
116 * This function is deprecated.
117 *
118 * Returns: 0.
119 **/
udev_queue_get_udev_seqnum(struct udev_queue * udev_queue)120 _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) {
121 return 0;
122 }
123
124 /**
125 * udev_queue_get_udev_is_active:
126 * @udev_queue: udev queue context
127 *
128 * Check if udev is active on the system.
129 *
130 * Returns: a flag indicating if udev is active.
131 **/
udev_queue_get_udev_is_active(struct udev_queue * udev_queue)132 _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) {
133 return access("/run/udev/control", F_OK) >= 0;
134 }
135
136 /**
137 * udev_queue_get_queue_is_empty:
138 * @udev_queue: udev queue context
139 *
140 * Check if udev is currently processing any events.
141 *
142 * Returns: a flag indicating if udev is currently handling events.
143 **/
udev_queue_get_queue_is_empty(struct udev_queue * udev_queue)144 _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
145 return udev_queue_is_empty() > 0;
146 }
147
148 /**
149 * udev_queue_get_seqnum_sequence_is_finished:
150 * @udev_queue: udev queue context
151 * @start: first event sequence number
152 * @end: last event sequence number
153 *
154 * This function is deprecated, and equivalent to udev_queue_get_queue_is_empty().
155 *
156 * Returns: a flag indicating if udev is currently handling events.
157 **/
udev_queue_get_seqnum_sequence_is_finished(struct udev_queue * udev_queue,unsigned long long int start,unsigned long long int end)158 _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
159 unsigned long long int start, unsigned long long int end) {
160 return udev_queue_is_empty() > 0;
161 }
162
163 /**
164 * udev_queue_get_seqnum_is_finished:
165 * @udev_queue: udev queue context
166 * @seqnum: sequence number
167 *
168 * This function is deprecated, and equivalent to udev_queue_get_queue_is_empty().
169 *
170 * Returns: a flag indicating if udev is currently handling events.
171 **/
udev_queue_get_seqnum_is_finished(struct udev_queue * udev_queue,unsigned long long int seqnum)172 _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) {
173 return udev_queue_is_empty() > 0;
174 }
175
176 /**
177 * udev_queue_get_queued_list_entry:
178 * @udev_queue: udev queue context
179 *
180 * This function is deprecated.
181 *
182 * Returns: NULL.
183 **/
udev_queue_get_queued_list_entry(struct udev_queue * udev_queue)184 _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
185 return_with_errno(NULL, ENODATA);
186 }
187
188 /**
189 * udev_queue_get_fd:
190 * @udev_queue: udev queue context
191 *
192 * Returns: a file descriptor to watch for a queue to become empty.
193 */
udev_queue_get_fd(struct udev_queue * udev_queue)194 _public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
195 int r;
196
197 assert_return(udev_queue, -EINVAL);
198
199 if (udev_queue->fd >= 0)
200 return udev_queue->fd;
201
202 r = udev_queue_init();
203 if (r < 0)
204 return r;
205
206 return udev_queue->fd = r;
207 }
208
209 /**
210 * udev_queue_flush:
211 * @udev_queue: udev queue context
212 *
213 * Returns: the result of clearing the watch for queue changes.
214 */
udev_queue_flush(struct udev_queue * udev_queue)215 _public_ int udev_queue_flush(struct udev_queue *udev_queue) {
216 int r;
217
218 assert_return(udev_queue, -EINVAL);
219
220 if (udev_queue->fd < 0)
221 return -EINVAL;
222
223 r = flush_fd(udev_queue->fd);
224 if (r < 0)
225 return r;
226
227 return 0;
228 }
229