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