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