+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
* Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
#include "fs-util.h"
#include "hashmap.h"
#include "io-util.h"
+#include "list.h"
#include "netlink-util.h"
#include "parse-util.h"
#include "proc-cmdline.h"
struct udev *udev;
sd_event *event;
Hashmap *workers;
- struct udev_list_node events;
+ LIST_HEAD(struct event, events);
const char *cgroup;
pid_t pid; /* the process that originally allocated the manager object */
};
struct event {
- struct udev_list_node node;
+ LIST_FIELDS(struct event, event);
Manager *manager;
struct udev *udev;
struct udev_device *dev;
sd_event_source *timeout;
};
-static inline struct event *node_to_event(struct udev_list_node *node) {
- return container_of(node, struct event, node);
-}
-
static void event_queue_cleanup(Manager *manager, enum event_state type);
enum worker_state {
struct worker {
Manager *manager;
- struct udev_list_node node;
int refcount;
pid_t pid;
struct udev_monitor *monitor;
if (!event)
return;
+ assert(event->manager);
- udev_list_node_remove(&event->node);
+ LIST_REMOVE(event, event->manager->events, event);
udev_device_unref(event->dev);
udev_device_unref(event->dev_kernel);
if (event->worker)
event->worker->event = NULL;
- assert(event->manager);
-
- if (udev_list_node_is_empty(&event->manager->events)) {
+ if (LIST_IS_EMPTY(event->manager->events)) {
/* only clean up the queue from the process that created it */
if (event->manager->pid == getpid_cached()) {
r = unlink("/run/udev/queue");
event->state = EVENT_QUEUED;
- if (udev_list_node_is_empty(&manager->events)) {
+ if (LIST_IS_EMPTY(manager->events)) {
r = touch("/run/udev/queue");
if (r < 0)
log_warning_errno(r, "could not touch /run/udev/queue: %m");
}
- udev_list_node_append(&event->node, &manager->events);
+ LIST_APPEND(event, manager->events, event);
return 0;
}
/* lookup event for identical, parent, child device */
static bool is_devpath_busy(Manager *manager, struct event *event) {
- struct udev_list_node *loop;
+ struct event *loop_event;
size_t common;
/* check if queue contains events we depend on */
- udev_list_node_foreach(loop, &manager->events) {
- struct event *loop_event = node_to_event(loop);
-
+ LIST_FOREACH(event, loop_event, manager->events) {
/* we already found a later event, earlier can not block us, no need to check again */
if (loop_event->seqnum < event->delaying_seqnum)
continue;
}
static void event_queue_start(Manager *manager) {
- struct udev_list_node *loop;
+ struct event *event;
usec_t usec;
assert(manager);
- if (udev_list_node_is_empty(&manager->events) ||
+ if (LIST_IS_EMPTY(manager->events) ||
manager->exit || manager->stop_exec_queue)
return;
return;
}
- udev_list_node_foreach(loop, &manager->events) {
- struct event *event = node_to_event(loop);
-
+ LIST_FOREACH(event,event,manager->events) {
if (event->state != EVENT_QUEUED)
continue;
}
static void event_queue_cleanup(Manager *manager, enum event_state match_type) {
- struct udev_list_node *loop, *tmp;
-
- udev_list_node_foreach_safe(loop, tmp, &manager->events) {
- struct event *event = node_to_event(loop);
+ struct event *event, *tmp;
+ LIST_FOREACH_SAFE(event, event, tmp, manager->events) {
if (match_type != EVENT_UNDEF && match_type != event->state)
continue;
assert(manager);
- if (udev_list_node_is_empty(&manager->events)) {
+ if (LIST_IS_EMPTY(manager->events)) {
/* no pending events */
if (!hashmap_isempty(manager->workers)) {
/* there are idle workers */
printf("%s [OPTIONS...]\n\n"
"Manages devices.\n\n"
" -h --help Print this message\n"
- " --version Print version of the program\n"
- " --daemon Detach and run in the background\n"
- " --debug Enable debug output\n"
- " --children-max=INT Set maximum number of workers\n"
- " --exec-delay=SECONDS Seconds to wait before executing RUN=\n"
- " --event-timeout=SECONDS Seconds to wait before terminating an event\n"
- " --resolve-names=early|late|never\n"
+ " -V --version Print version of the program\n"
+ " -d --daemon Detach and run in the background\n"
+ " -D --debug Enable debug output\n"
+ " -c --children-max=INT Set maximum number of workers\n"
+ " -e --exec-delay=SECONDS Seconds to wait before executing RUN=\n"
+ " -t --event-timeout=SECONDS Seconds to wait before terminating an event\n"
+ " -N --resolve-names=early|late|never\n"
" When to resolve users and groups\n"
, program_invocation_short_name);
}
if (!manager->rules)
return log_error_errno(ENOMEM, "error reading rules");
- udev_list_node_init(&manager->events);
+ LIST_HEAD_INIT(manager->events);
udev_list_init(manager->udev, &manager->properties, true);
manager->cgroup = cgroup;
log_set_max_level(LOG_DEBUG);
}
- if (getuid() != 0) {
- r = log_error_errno(EPERM, "root privileges required");
+ r = must_be_root();
+ if (r < 0)
goto exit;
- }
if (arg_children_max == 0) {
cpu_set_t cpu_set;
by PID1. otherwise we are not guaranteed to have a dedicated cgroup */
r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
if (r < 0) {
- if (r == -ENOENT || r == -ENOMEDIUM)
+ if (IN_SET(r, -ENOENT, -ENOMEDIUM))
log_debug_errno(r, "did not find dedicated cgroup: %m");
else
log_warning_errno(r, "failed to get cgroup: %m");