199ca880aSopenharmony_ci/*** 299ca880aSopenharmony_ci This file is part of systemd. 399ca880aSopenharmony_ci 499ca880aSopenharmony_ci Copyright 2008-2012 Kay Sievers <kay@vrfy.org> 599ca880aSopenharmony_ci Copyright 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk> 699ca880aSopenharmony_ci 799ca880aSopenharmony_ci systemd is free software; you can redistribute it and/or modify it 899ca880aSopenharmony_ci under the terms of the GNU Lesser General Public License as published by 999ca880aSopenharmony_ci the Free Software Foundation; either version 2.1 of the License, or 1099ca880aSopenharmony_ci (at your option) any later version. 1199ca880aSopenharmony_ci 1299ca880aSopenharmony_ci systemd is distributed in the hope that it will be useful, but 1399ca880aSopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1499ca880aSopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1599ca880aSopenharmony_ci Lesser General Public License for more details. 1699ca880aSopenharmony_ci 1799ca880aSopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1899ca880aSopenharmony_ci along with systemd; If not, see <http://www.gnu.org/licenses/>. 1999ca880aSopenharmony_ci***/ 2099ca880aSopenharmony_ci 2199ca880aSopenharmony_ci#include <stdio.h> 2299ca880aSopenharmony_ci#include <stdlib.h> 2399ca880aSopenharmony_ci#include <stddef.h> 2499ca880aSopenharmony_ci#include <unistd.h> 2599ca880aSopenharmony_ci#include <errno.h> 2699ca880aSopenharmony_ci#include <string.h> 2799ca880aSopenharmony_ci#include <limits.h> 2899ca880aSopenharmony_ci#include <sys/stat.h> 2999ca880aSopenharmony_ci#include <sys/inotify.h> 3099ca880aSopenharmony_ci 3199ca880aSopenharmony_ci#include "libudev.h" 3299ca880aSopenharmony_ci#include "libudev-private.h" 3399ca880aSopenharmony_ci 3499ca880aSopenharmony_ci/** 3599ca880aSopenharmony_ci * SECTION:libudev-queue 3699ca880aSopenharmony_ci * @short_description: access to currently active events 3799ca880aSopenharmony_ci * 3899ca880aSopenharmony_ci * This exports the current state of the udev processing queue. 3999ca880aSopenharmony_ci */ 4099ca880aSopenharmony_ci 4199ca880aSopenharmony_ci/** 4299ca880aSopenharmony_ci * udev_queue: 4399ca880aSopenharmony_ci * 4499ca880aSopenharmony_ci * Opaque object representing the current event queue in the udev daemon. 4599ca880aSopenharmony_ci */ 4699ca880aSopenharmony_cistruct udev_queue { 4799ca880aSopenharmony_ci struct udev *udev; 4899ca880aSopenharmony_ci int refcount; 4999ca880aSopenharmony_ci int fd; 5099ca880aSopenharmony_ci}; 5199ca880aSopenharmony_ci 5299ca880aSopenharmony_ci/** 5399ca880aSopenharmony_ci * udev_queue_new: 5499ca880aSopenharmony_ci * @udev: udev library context 5599ca880aSopenharmony_ci * 5699ca880aSopenharmony_ci * The initial refcount is 1, and needs to be decremented to 5799ca880aSopenharmony_ci * release the resources of the udev queue context. 5899ca880aSopenharmony_ci * 5999ca880aSopenharmony_ci * Returns: the udev queue context, or #NULL on error. 6099ca880aSopenharmony_ci **/ 6199ca880aSopenharmony_ci_public_ struct udev_queue *udev_queue_new(struct udev *udev) 6299ca880aSopenharmony_ci{ 6399ca880aSopenharmony_ci struct udev_queue *udev_queue; 6499ca880aSopenharmony_ci 6599ca880aSopenharmony_ci if (udev == NULL) 6699ca880aSopenharmony_ci return NULL; 6799ca880aSopenharmony_ci 6899ca880aSopenharmony_ci udev_queue = new0(struct udev_queue, 1); 6999ca880aSopenharmony_ci if (udev_queue == NULL) 7099ca880aSopenharmony_ci return NULL; 7199ca880aSopenharmony_ci 7299ca880aSopenharmony_ci udev_queue->refcount = 1; 7399ca880aSopenharmony_ci udev_queue->udev = udev; 7499ca880aSopenharmony_ci udev_queue->fd = -1; 7599ca880aSopenharmony_ci return udev_queue; 7699ca880aSopenharmony_ci} 7799ca880aSopenharmony_ci 7899ca880aSopenharmony_ci/** 7999ca880aSopenharmony_ci * udev_queue_ref: 8099ca880aSopenharmony_ci * @udev_queue: udev queue context 8199ca880aSopenharmony_ci * 8299ca880aSopenharmony_ci * Take a reference of a udev queue context. 8399ca880aSopenharmony_ci * 8499ca880aSopenharmony_ci * Returns: the same udev queue context. 8599ca880aSopenharmony_ci **/ 8699ca880aSopenharmony_ci_public_ struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue) 8799ca880aSopenharmony_ci{ 8899ca880aSopenharmony_ci if (udev_queue == NULL) 8999ca880aSopenharmony_ci return NULL; 9099ca880aSopenharmony_ci 9199ca880aSopenharmony_ci udev_queue->refcount++; 9299ca880aSopenharmony_ci return udev_queue; 9399ca880aSopenharmony_ci} 9499ca880aSopenharmony_ci 9599ca880aSopenharmony_ci/** 9699ca880aSopenharmony_ci * udev_queue_unref: 9799ca880aSopenharmony_ci * @udev_queue: udev queue context 9899ca880aSopenharmony_ci * 9999ca880aSopenharmony_ci * Drop a reference of a udev queue context. If the refcount reaches zero, 10099ca880aSopenharmony_ci * the resources of the queue context will be released. 10199ca880aSopenharmony_ci * 10299ca880aSopenharmony_ci * Returns: #NULL 10399ca880aSopenharmony_ci **/ 10499ca880aSopenharmony_ci_public_ struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue) 10599ca880aSopenharmony_ci{ 10699ca880aSopenharmony_ci if (udev_queue == NULL) 10799ca880aSopenharmony_ci return NULL; 10899ca880aSopenharmony_ci 10999ca880aSopenharmony_ci udev_queue->refcount--; 11099ca880aSopenharmony_ci if (udev_queue->refcount > 0) 11199ca880aSopenharmony_ci return NULL; 11299ca880aSopenharmony_ci 11399ca880aSopenharmony_ci safe_close(udev_queue->fd); 11499ca880aSopenharmony_ci 11599ca880aSopenharmony_ci free(udev_queue); 11699ca880aSopenharmony_ci return NULL; 11799ca880aSopenharmony_ci} 11899ca880aSopenharmony_ci 11999ca880aSopenharmony_ci/** 12099ca880aSopenharmony_ci * udev_queue_get_udev: 12199ca880aSopenharmony_ci * @udev_queue: udev queue context 12299ca880aSopenharmony_ci * 12399ca880aSopenharmony_ci * Retrieve the udev library context the queue context was created with. 12499ca880aSopenharmony_ci * 12599ca880aSopenharmony_ci * Returns: the udev library context. 12699ca880aSopenharmony_ci **/ 12799ca880aSopenharmony_ci_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) 12899ca880aSopenharmony_ci{ 12999ca880aSopenharmony_ci if (udev_queue == NULL) 13099ca880aSopenharmony_ci return NULL; 13199ca880aSopenharmony_ci return udev_queue->udev; 13299ca880aSopenharmony_ci} 13399ca880aSopenharmony_ci 13499ca880aSopenharmony_ci/** 13599ca880aSopenharmony_ci * udev_queue_get_kernel_seqnum: 13699ca880aSopenharmony_ci * @udev_queue: udev queue context 13799ca880aSopenharmony_ci * 13899ca880aSopenharmony_ci * This function is deprecated. 13999ca880aSopenharmony_ci * 14099ca880aSopenharmony_ci * Returns: 0. 14199ca880aSopenharmony_ci **/ 14299ca880aSopenharmony_ci_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) 14399ca880aSopenharmony_ci{ 14499ca880aSopenharmony_ci return 0; 14599ca880aSopenharmony_ci} 14699ca880aSopenharmony_ci 14799ca880aSopenharmony_ci/** 14899ca880aSopenharmony_ci * udev_queue_get_udev_seqnum: 14999ca880aSopenharmony_ci * @udev_queue: udev queue context 15099ca880aSopenharmony_ci * 15199ca880aSopenharmony_ci * This function is deprecated. 15299ca880aSopenharmony_ci * 15399ca880aSopenharmony_ci * Returns: 0. 15499ca880aSopenharmony_ci **/ 15599ca880aSopenharmony_ci_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) 15699ca880aSopenharmony_ci{ 15799ca880aSopenharmony_ci return 0; 15899ca880aSopenharmony_ci} 15999ca880aSopenharmony_ci 16099ca880aSopenharmony_ci/** 16199ca880aSopenharmony_ci * udev_queue_get_udev_is_active: 16299ca880aSopenharmony_ci * @udev_queue: udev queue context 16399ca880aSopenharmony_ci * 16499ca880aSopenharmony_ci * Check if udev is active on the system. 16599ca880aSopenharmony_ci * 16699ca880aSopenharmony_ci * Returns: a flag indicating if udev is active. 16799ca880aSopenharmony_ci **/ 16899ca880aSopenharmony_ci_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) 16999ca880aSopenharmony_ci{ 17099ca880aSopenharmony_ci return access(UDEV_ROOT_RUN "/udev/control", F_OK) >= 0; 17199ca880aSopenharmony_ci} 17299ca880aSopenharmony_ci 17399ca880aSopenharmony_ci/** 17499ca880aSopenharmony_ci * udev_queue_get_queue_is_empty: 17599ca880aSopenharmony_ci * @udev_queue: udev queue context 17699ca880aSopenharmony_ci * 17799ca880aSopenharmony_ci * Check if udev is currently processing any events. 17899ca880aSopenharmony_ci * 17999ca880aSopenharmony_ci * Returns: a flag indicating if udev is currently handling events. 18099ca880aSopenharmony_ci **/ 18199ca880aSopenharmony_ci_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) 18299ca880aSopenharmony_ci{ 18399ca880aSopenharmony_ci return access(UDEV_ROOT_RUN "/udev/queue", F_OK) < 0; 18499ca880aSopenharmony_ci} 18599ca880aSopenharmony_ci 18699ca880aSopenharmony_ci/** 18799ca880aSopenharmony_ci * udev_queue_get_seqnum_sequence_is_finished: 18899ca880aSopenharmony_ci * @udev_queue: udev queue context 18999ca880aSopenharmony_ci * @start: first event sequence number 19099ca880aSopenharmony_ci * @end: last event sequence number 19199ca880aSopenharmony_ci * 19299ca880aSopenharmony_ci * This function is deprecated, it just returns the result of 19399ca880aSopenharmony_ci * udev_queue_get_queue_is_empty(). 19499ca880aSopenharmony_ci * 19599ca880aSopenharmony_ci * Returns: a flag indicating if udev is currently handling events. 19699ca880aSopenharmony_ci **/ 19799ca880aSopenharmony_ci_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, 19899ca880aSopenharmony_ci unsigned long long int start, unsigned long long int end) 19999ca880aSopenharmony_ci{ 20099ca880aSopenharmony_ci return udev_queue_get_queue_is_empty(udev_queue); 20199ca880aSopenharmony_ci} 20299ca880aSopenharmony_ci 20399ca880aSopenharmony_ci/** 20499ca880aSopenharmony_ci * udev_queue_get_seqnum_is_finished: 20599ca880aSopenharmony_ci * @udev_queue: udev queue context 20699ca880aSopenharmony_ci * @seqnum: sequence number 20799ca880aSopenharmony_ci * 20899ca880aSopenharmony_ci * This function is deprecated, it just returns the result of 20999ca880aSopenharmony_ci * udev_queue_get_queue_is_empty(). 21099ca880aSopenharmony_ci * 21199ca880aSopenharmony_ci * Returns: a flag indicating if udev is currently handling events. 21299ca880aSopenharmony_ci **/ 21399ca880aSopenharmony_ci_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) 21499ca880aSopenharmony_ci{ 21599ca880aSopenharmony_ci return udev_queue_get_queue_is_empty(udev_queue); 21699ca880aSopenharmony_ci} 21799ca880aSopenharmony_ci 21899ca880aSopenharmony_ci/** 21999ca880aSopenharmony_ci * udev_queue_get_queued_list_entry: 22099ca880aSopenharmony_ci * @udev_queue: udev queue context 22199ca880aSopenharmony_ci * 22299ca880aSopenharmony_ci * This function is deprecated. 22399ca880aSopenharmony_ci * 22499ca880aSopenharmony_ci * Returns: NULL. 22599ca880aSopenharmony_ci **/ 22699ca880aSopenharmony_ci_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) 22799ca880aSopenharmony_ci{ 22899ca880aSopenharmony_ci return NULL; 22999ca880aSopenharmony_ci} 23099ca880aSopenharmony_ci 23199ca880aSopenharmony_ci/** 23299ca880aSopenharmony_ci * udev_queue_get_fd: 23399ca880aSopenharmony_ci * @udev_queue: udev queue context 23499ca880aSopenharmony_ci * 23599ca880aSopenharmony_ci * Returns: a file descriptor to watch for a queue to become empty. 23699ca880aSopenharmony_ci */ 23799ca880aSopenharmony_ci_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { 23899ca880aSopenharmony_ci int fd; 23999ca880aSopenharmony_ci int r; 24099ca880aSopenharmony_ci 24199ca880aSopenharmony_ci if (udev_queue->fd >= 0) 24299ca880aSopenharmony_ci return udev_queue->fd; 24399ca880aSopenharmony_ci 24499ca880aSopenharmony_ci fd = inotify_init1(IN_CLOEXEC); 24599ca880aSopenharmony_ci if (fd < 0) 24699ca880aSopenharmony_ci return -errno; 24799ca880aSopenharmony_ci 24899ca880aSopenharmony_ci r = inotify_add_watch(fd, UDEV_ROOT_RUN "/udev" , IN_DELETE); 24999ca880aSopenharmony_ci if (r < 0) { 25099ca880aSopenharmony_ci r = -errno; 25199ca880aSopenharmony_ci close(fd); 25299ca880aSopenharmony_ci return r; 25399ca880aSopenharmony_ci } 25499ca880aSopenharmony_ci 25599ca880aSopenharmony_ci udev_queue->fd = fd; 25699ca880aSopenharmony_ci return fd; 25799ca880aSopenharmony_ci} 25899ca880aSopenharmony_ci 25999ca880aSopenharmony_ci/** 26099ca880aSopenharmony_ci * udev_queue_flush: 26199ca880aSopenharmony_ci * @udev_queue: udev queue context 26299ca880aSopenharmony_ci * 26399ca880aSopenharmony_ci * Returns: the result of clearing the watch for queue changes. 26499ca880aSopenharmony_ci */ 26599ca880aSopenharmony_ci_public_ int udev_queue_flush(struct udev_queue *udev_queue) { 26699ca880aSopenharmony_ci if (udev_queue->fd < 0) 26799ca880aSopenharmony_ci return -EINVAL; 26899ca880aSopenharmony_ci 26999ca880aSopenharmony_ci return flush_fd(udev_queue->fd); 27099ca880aSopenharmony_ci} 271