2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2012-11-12 17:50:33 +01:00
|
|
|
/***
|
2018-06-12 19:00:24 +02:00
|
|
|
Copyright © 2009 Alan Jenkins <alan-jenkins@tuffmail.co.uk>
|
2012-11-12 17:50:33 +01:00
|
|
|
***/
|
2008-10-01 09:34:07 +02:00
|
|
|
|
|
|
|
#include <errno.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
2014-06-27 17:42:44 +02:00
|
|
|
#include <sys/inotify.h>
|
2015-11-16 22:09:36 +01:00
|
|
|
#include <unistd.h>
|
2008-10-01 09:34:07 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2015-10-25 14:08:25 +01:00
|
|
|
#include "io-util.h"
|
2008-10-01 09:34:07 +02:00
|
|
|
#include "libudev-private.h"
|
|
|
|
|
2009-06-15 17:09:43 +02:00
|
|
|
/**
|
|
|
|
* SECTION:libudev-queue
|
|
|
|
* @short_description: access to currently active events
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This exports the current state of the udev processing queue.
|
2009-06-15 17:09:43 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* udev_queue:
|
|
|
|
*
|
|
|
|
* Opaque object representing the current event queue in the udev daemon.
|
|
|
|
*/
|
2008-10-01 09:34:07 +02:00
|
|
|
struct udev_queue {
|
2012-01-10 01:34:15 +01:00
|
|
|
struct udev *udev;
|
2018-08-28 06:07:48 +02:00
|
|
|
unsigned n_ref;
|
2014-06-27 17:42:44 +02:00
|
|
|
int fd;
|
2008-10-01 09:34:07 +02:00
|
|
|
};
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_new:
|
|
|
|
* @udev: udev library context
|
|
|
|
*
|
|
|
|
* The initial refcount is 1, and needs to be decremented to
|
|
|
|
* release the resources of the udev queue context.
|
|
|
|
*
|
|
|
|
* Returns: the udev queue context, or #NULL on error.
|
|
|
|
**/
|
2018-08-24 06:39:46 +02:00
|
|
|
_public_ struct udev_queue *udev_queue_new(struct udev *udev) {
|
2012-01-10 01:34:15 +01:00
|
|
|
struct udev_queue *udev_queue;
|
|
|
|
|
2018-08-24 06:39:46 +02:00
|
|
|
udev_queue = new(struct udev_queue, 1);
|
2017-09-09 22:31:09 +02:00
|
|
|
if (udev_queue == NULL) {
|
|
|
|
errno = ENOMEM;
|
2012-01-10 01:34:15 +01:00
|
|
|
return NULL;
|
2017-09-09 22:31:09 +02:00
|
|
|
}
|
2014-04-13 07:35:50 +02:00
|
|
|
|
2018-08-24 06:39:46 +02:00
|
|
|
*udev_queue = (struct udev_queue) {
|
|
|
|
.udev = udev,
|
|
|
|
.n_ref = 1,
|
|
|
|
.fd = -1,
|
|
|
|
};
|
|
|
|
|
2012-01-10 01:34:15 +01:00
|
|
|
return udev_queue;
|
2008-10-01 09:34:07 +02:00
|
|
|
}
|
|
|
|
|
2018-08-28 06:07:48 +02:00
|
|
|
static struct udev_queue *udev_queue_free(struct udev_queue *udev_queue) {
|
|
|
|
assert(udev_queue);
|
|
|
|
|
|
|
|
safe_close(udev_queue->fd);
|
|
|
|
return mfree(udev_queue);
|
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_ref:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
|
|
|
* Take a reference of a udev queue context.
|
|
|
|
*
|
|
|
|
* Returns: the same udev queue context.
|
|
|
|
**/
|
2008-10-01 09:34:07 +02:00
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_unref:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
|
|
|
* Drop a reference of a udev queue context. If the refcount reaches zero,
|
|
|
|
* the resources of the queue context will be released.
|
2012-05-15 23:44:28 +02:00
|
|
|
*
|
2013-11-19 01:15:31 +01:00
|
|
|
* Returns: #NULL
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2018-08-28 06:07:48 +02:00
|
|
|
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_queue, udev_queue, udev_queue_free);
|
2008-10-01 09:34:07 +02:00
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_udev:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
|
|
|
* Retrieve the udev library context the queue context was created with.
|
|
|
|
*
|
|
|
|
* Returns: the udev library context.
|
|
|
|
**/
|
2018-08-24 06:41:22 +02:00
|
|
|
_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) {
|
|
|
|
assert_return_errno(udev_queue, NULL, EINVAL);
|
|
|
|
|
2012-01-10 01:34:15 +01:00
|
|
|
return udev_queue->udev;
|
2008-10-01 09:34:07 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_kernel_seqnum:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This function is deprecated.
|
2012-04-20 03:25:36 +02:00
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* Returns: 0.
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) {
|
2012-01-10 01:34:15 +01:00
|
|
|
return 0;
|
2009-05-21 22:22:37 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_udev_seqnum:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This function is deprecated.
|
2012-04-20 03:25:36 +02:00
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* Returns: 0.
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) {
|
2014-04-13 07:35:50 +02:00
|
|
|
return 0;
|
2009-05-21 22:22:37 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_udev_is_active:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
2012-04-20 03:25:36 +02:00
|
|
|
* Check if udev is active on the system.
|
|
|
|
*
|
2009-06-15 20:28:28 +02:00
|
|
|
* Returns: a flag indicating if udev is active.
|
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) {
|
2014-04-13 07:35:50 +02:00
|
|
|
return access("/run/udev/control", F_OK) >= 0;
|
2008-11-06 19:41:58 +01:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_queue_is_empty:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
2012-04-20 03:25:36 +02:00
|
|
|
* Check if udev is currently processing any events.
|
|
|
|
*
|
2009-06-15 20:28:28 +02:00
|
|
|
* Returns: a flag indicating if udev is currently handling events.
|
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) {
|
2014-06-27 14:20:17 +02:00
|
|
|
return access("/run/udev/queue", F_OK) < 0;
|
2008-10-01 09:34:07 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_seqnum_sequence_is_finished:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
* @start: first event sequence number
|
|
|
|
* @end: last event sequence number
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This function is deprecated, it just returns the result of
|
|
|
|
* udev_queue_get_queue_is_empty().
|
2012-04-20 03:25:36 +02:00
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* Returns: a flag indicating if udev is currently handling events.
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2012-04-04 13:30:09 +02:00
|
|
|
_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue,
|
2018-08-24 06:43:59 +02:00
|
|
|
unsigned long long int start, unsigned long long int end) {
|
2014-04-13 07:35:50 +02:00
|
|
|
return udev_queue_get_queue_is_empty(udev_queue);
|
2009-05-21 22:22:37 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_seqnum_is_finished:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
* @seqnum: sequence number
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This function is deprecated, it just returns the result of
|
|
|
|
* udev_queue_get_queue_is_empty().
|
2012-04-20 03:25:36 +02:00
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* Returns: a flag indicating if udev is currently handling events.
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) {
|
2014-04-13 07:35:50 +02:00
|
|
|
return udev_queue_get_queue_is_empty(udev_queue);
|
2008-10-01 09:34:07 +02:00
|
|
|
}
|
|
|
|
|
2009-06-15 20:28:28 +02:00
|
|
|
/**
|
|
|
|
* udev_queue_get_queued_list_entry:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* This function is deprecated.
|
2012-04-20 03:25:36 +02:00
|
|
|
*
|
2014-04-13 07:35:50 +02:00
|
|
|
* Returns: NULL.
|
2009-06-15 20:28:28 +02:00
|
|
|
**/
|
2018-08-24 06:43:59 +02:00
|
|
|
_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) {
|
2017-09-09 22:31:09 +02:00
|
|
|
errno = ENODATA;
|
2014-04-13 07:35:50 +02:00
|
|
|
return NULL;
|
2008-10-01 09:34:07 +02:00
|
|
|
}
|
2014-06-27 17:42:44 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* udev_queue_get_fd:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
|
|
|
* Returns: a file descriptor to watch for a queue to become empty.
|
|
|
|
*/
|
|
|
|
_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) {
|
2018-08-24 06:42:18 +02:00
|
|
|
_cleanup_close_ int fd = -1;
|
|
|
|
|
|
|
|
assert_return(udev_queue, -EINVAL);
|
2014-06-27 17:42:44 +02:00
|
|
|
|
|
|
|
if (udev_queue->fd >= 0)
|
|
|
|
return udev_queue->fd;
|
|
|
|
|
|
|
|
fd = inotify_init1(IN_CLOEXEC);
|
|
|
|
if (fd < 0)
|
|
|
|
return -errno;
|
|
|
|
|
2018-08-24 06:42:18 +02:00
|
|
|
if (inotify_add_watch(fd, "/run/udev" , IN_DELETE) < 0)
|
|
|
|
return -errno;
|
2014-06-27 17:42:44 +02:00
|
|
|
|
2018-08-24 06:42:18 +02:00
|
|
|
udev_queue->fd = TAKE_FD(fd);
|
|
|
|
return udev_queue->fd;
|
2014-06-27 17:42:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* udev_queue_flush:
|
|
|
|
* @udev_queue: udev queue context
|
|
|
|
*
|
|
|
|
* Returns: the result of clearing the watch for queue changes.
|
|
|
|
*/
|
|
|
|
_public_ int udev_queue_flush(struct udev_queue *udev_queue) {
|
2017-12-12 23:21:09 +01:00
|
|
|
int r;
|
|
|
|
|
2018-08-24 06:41:22 +02:00
|
|
|
assert_return(udev_queue, -EINVAL);
|
2017-12-12 23:21:09 +01:00
|
|
|
|
2014-06-27 17:42:44 +02:00
|
|
|
if (udev_queue->fd < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-12-12 23:21:09 +01:00
|
|
|
r = flush_fd(udev_queue->fd);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return 0;
|
2014-06-27 17:42:44 +02:00
|
|
|
}
|