udevd.c revision f503f6b22fa54d1a65156a51d8b3311190c73ae5
9262a519468491c80df2998eda238e2ac86a810dLennart Poettering/*
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers * Copyright (C) 2009 Canonical Ltd.
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers * Copyright (C) 2009 Scott James Remnant <scott@netsplit.com>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * This program is free software: you can redistribute it and/or modify
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * it under the terms of the GNU General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * the Free Software Foundation, either version 2 of the License, or
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * (at your option) any later version.
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * This program is distributed in the hope that it will be useful,
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * but WITHOUT ANY WARRANTY; without even the implied warranty of
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * GNU General Public License for more details.
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * You should have received a copy of the GNU General Public License
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * along with this program. If not, see <http://www.gnu.org/licenses/>.
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering */
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <stddef.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <signal.h>
38a60d7112d33ffd596b23e8df53d75a7c09e71bLennart Poettering#include <unistd.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <errno.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <stdio.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <stdlib.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <string.h>
78a825f216d39ee0295b00647b059d45467e1d02Kay Sievers#include <ctype.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <fcntl.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <time.h>
a80db8bd5f7f15859e8891aab9fc3694ce4cd0bdJavier Jardón#include <getopt.h>
a80db8bd5f7f15859e8891aab9fc3694ce4cd0bdJavier Jardón#include <dirent.h>
4db6d587c37c0357d20c79bf1a7c9afd4c7ced61Kay Sievers#include <sys/select.h>
907dd1953b7517534d646f5b2777780020c896e2Kay Sievers#include <sys/poll.h>
eb7bbee6cd182d5c4eb1e1180631c35158f59379Kay Sievers#include <sys/wait.h>
bbd9b8c2139a70005e4e83d198575e2a10fe1db2Lennart Poettering#include <sys/stat.h>
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers#include <sys/ioctl.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#ifdef HAVE_INOTIFY
22be093ffb403a1c474037939ca9b88b1ee39f77Lennart Poettering#include <sys/inotify.h>
d59d0a2b4b41a75eaf618b26b8f8bd1e17de7e2bcee#endif
d59d0a2b4b41a75eaf618b26b8f8bd1e17de7e2bcee
d59d0a2b4b41a75eaf618b26b8f8bd1e17de7e2bcee#include "udev.h"
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers#define UDEVD_PRIORITY -4
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers#define UDEV_PRIORITY -2
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera/* maximum limit of forked childs */
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera#define UDEVD_MAX_CHILDS 256
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocerastatic int debug;
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocerastatic void log_fn(struct udev *udev, int priority,
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering const char *file, int line, const char *fn,
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering const char *format, va_list args)
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering{
3ce4fad8f548db9edb19869ea540e3192d2123f4Kay Sievers if (debug) {
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering fprintf(stderr, "[%d] %s: ", (int) getpid(), fn);
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering vfprintf(stderr, format, args);
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering } else {
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering vsyslog(priority, format, args);
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering }
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering}
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sieversstatic void reap_sigchilds(void);
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek
92ec4495f76a7a2a6c31f5bb2a5240f78dcfe1d2Javier Jardónstatic int debug_trace;
80a5cbace45a6adbf2f9119edc5a4b10db493064Kay Sieversstatic struct udev_rules *rules;
92ec4495f76a7a2a6c31f5bb2a5240f78dcfe1d2Javier Jardónstatic struct udev_queue_export *udev_queue_export;
9e45e7d8f0d8d3f31d790f85694585d0d4b368b8Javier Jardónstatic struct udev_ctrl *udev_ctrl;
6e92b23f0d6dd398848376bbaf47e54a90ed3389Kay Sieversstatic struct udev_monitor *kernel_monitor;
92ec4495f76a7a2a6c31f5bb2a5240f78dcfe1d2Javier Jardónstatic volatile sig_atomic_t sigchilds_waiting;
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmekstatic volatile sig_atomic_t udev_exit;
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmekstatic volatile sig_atomic_t reload_config;
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmekstatic volatile sig_atomic_t signal_received;
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmekstatic volatile pid_t settle_pid;
6e92b23f0d6dd398848376bbaf47e54a90ed3389Kay Sieversstatic int run_exec_q;
0eaeca1f2373a323b98c86b47561d98e59c67b25Kay Sieversstatic int stop_exec_q;
6e92b23f0d6dd398848376bbaf47e54a90ed3389Kay Sieversstatic int max_childs;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sieversstatic int childs;
9a60da2834074d970ca063c210fe9d2f05c70532Thierry Redingstatic struct udev_list_node event_list;
9a60da2834074d970ca063c210fe9d2f05c70532Thierry Reding
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poetteringstatic struct udev_event *node_to_event(struct udev_list_node *node)
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl{
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl char *event;
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl
9a60da2834074d970ca063c210fe9d2f05c70532Thierry Reding event = (char *)node;
9c4fa6ed1069e98db5f01a5d1056b443a04cc7d9Lennart Poettering event -= offsetof(struct udev_event, node);
9c4fa6ed1069e98db5f01a5d1056b443a04cc7d9Lennart Poettering return (struct udev_event *)event;
9c4fa6ed1069e98db5f01a5d1056b443a04cc7d9Lennart Poettering}
9c4fa6ed1069e98db5f01a5d1056b443a04cc7d9Lennart Poettering
eb2e280f9c59b66965c9316eadc4c113a13ca744Lucas De Marchistatic void event_queue_delete(struct udev_event *event)
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering{
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering udev_list_node_remove(&event->node);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
27765dfc7a32d790badb29e6498b34edb0b60c33Lennart Poettering /* mark as failed, if "add" event returns non-zero */
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (event->exitstatus && strcmp(udev_device_get_action(event->dev), "add") == 0)
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering udev_queue_export_device_failed(udev_queue_export, event->dev);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering else
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering udev_queue_export_device_finished(udev_queue_export, event->dev);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering udev_device_unref(event->dev);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering udev_event_unref(event);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering}
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poetteringstatic void event_sig_handler(int signum)
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering{
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (signum == SIGALRM)
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering _exit(1);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering}
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poetteringstatic void event_fork(struct udev_event *event)
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering{
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering pid_t pid;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering struct sigaction act;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering int err;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering#if 0
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering /* single process, no forking, just for testing/profiling */
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering err = udev_event_execute_rules(event, rules);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (err == 0 && !event->ignore_device && udev_get_run(event->udev))
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering udev_event_execute_run(event);
8745297f9853c4a17bac69e1b7e652fe81bc1940Lennart Poettering info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err);
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt event_queue_delete(event);
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering return;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering#endif
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri if (debug_trace) {
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri event->trace = 1;
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri fprintf(stderr, "fork %s (%llu)\n",
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering udev_device_get_syspath(event->dev),
c1663b9daf5a43425e54bbe3daf6b10e64578f80Lennart Poettering udev_device_get_seqnum(event->dev));
c1663b9daf5a43425e54bbe3daf6b10e64578f80Lennart Poettering }
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering pid = fork();
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering switch (pid) {
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering case 0:
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering /* child */
9e7adc3ae1133fa08a468768a490812299fad030Lucas De Marchi udev_queue_export_unref(udev_queue_export);
9e7adc3ae1133fa08a468768a490812299fad030Lucas De Marchi udev_ctrl_unref(udev_ctrl);
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri logging_close();
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering logging_init("udevd-event");
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering /* set signal handlers */
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering memset(&act, 0x00, sizeof(act));
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering act.sa_handler = event_sig_handler;
afea26ad7d406d8b6c95d2642cb5a1d807b87546Lennart Poettering sigemptyset (&act.sa_mask);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl act.sa_flags = 0;
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl sigaction(SIGALRM, &act, NULL);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering /* reset to default */
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering act.sa_handler = SIG_DFL;
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl sigaction(SIGINT, &act, NULL);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl sigaction(SIGTERM, &act, NULL);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl sigaction(SIGCHLD, &act, NULL);
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering sigaction(SIGHUP, &act, NULL);
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering /* set timeout to prevent hanging processes */
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering alarm(UDEV_EVENT_TIMEOUT);
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering /* apply rules, create node, symlinks */
b237ef2cfac7ab0b33170809e8cb64628606207dTollef Fog Heen err = udev_event_execute_rules(event, rules);
a9b5b03212f9c854938483b8901e433c2ba6619bMichael Tremer
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering /* rules may change/disable the timeout */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (udev_device_get_event_timeout(event->dev) >= 0)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers alarm(udev_device_get_event_timeout(event->dev));
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
728beb28a713709f521d374c9f8f3da781969d26Tom Gundersen /* execute RUN= */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (err == 0 && !event->ignore_device && udev_get_run(event->udev))
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu udev_event_execute_run(event);
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu /* apply/restore inotify watch */
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu if (err == 0 && event->inotify_watch) {
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu udev_watch_begin(event->udev, event->dev);
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu udev_device_update_db(event->dev);
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu }
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu /* send processed event back to the kernel netlink socket */
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu udev_monitor_send_device(kernel_monitor, event->dev);
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err);
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu logging_close();
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (err != 0)
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering exit(1);
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering exit(0);
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering case -1:
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering err(event->udev, "fork of child failed: %m\n");
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering event_queue_delete(event);
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering break;
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering default:
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering /* get SIGCHLD in main loop */
56cf987fe74270bde4e16c7ec9e0414a9030723bDaniel J Walsh info(event->udev, "seq %llu forked, pid [%d], '%s' '%s', %ld seconds old\n",
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering udev_device_get_seqnum(event->dev),
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt pid,
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt udev_device_get_action(event->dev),
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt udev_device_get_subsystem(event->dev),
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt time(NULL) - event->queue_time);
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt event->pid = pid;
ed061a8dc2acd93c2eb569d2d983d5a77f7e5b77Michal Schmidt childs++;
56cf987fe74270bde4e16c7ec9e0414a9030723bDaniel J Walsh }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers}
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering
807e17f05e217b474af39503efb9503d81b12596Lennart Poetteringstatic void event_queue_insert(struct udev_event *event)
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering{
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering event->queue_time = time(NULL);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering udev_queue_export_device_queued(udev_queue_export, event->dev);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(event->dev),
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering udev_device_get_action(event->dev), udev_device_get_subsystem(event->dev));
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering udev_list_node_append(&event->node, &event_list);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering run_exec_q = 1;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering /* run all events with a timeout set immediately */
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering if (udev_device_get_timeout(event->dev) > 0) {
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering event_fork(event);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering}
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poetteringstatic int mem_size_mb(void)
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering{
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering FILE *f;
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering char buf[4096];
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering long int memsize = -1;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering f = fopen("/proc/meminfo", "r");
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering if (f == NULL)
812cce323db081634f37e4ec6d29f2b9328a3f52Lennart Poettering return -1;
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering while (fgets(buf, sizeof(buf), f) != NULL) {
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering long int value;
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (sscanf(buf, "MemTotal: %ld kB", &value) == 1) {
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering memsize = value / 1024;
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering break;
0213c3f8102bdc934c629d11a44ca0b408762287Lennart Poettering }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering fclose(f);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return memsize;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering}
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poetteringstatic int compare_devpath(const char *running, const char *waiting)
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering{
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering int i = 0;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering while (running[i] != '\0' && running[i] == waiting[i])
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering i++;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /* identical device event found */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (running[i] == '\0' && waiting[i] == '\0')
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return 1;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /* parent device event found */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (running[i] == '\0' && waiting[i] == '/')
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return 2;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /* child device event found */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (running[i] == '/' && waiting[i] == '\0')
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return 3;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /* no matching event */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering return 0;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering}
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
812cce323db081634f37e4ec6d29f2b9328a3f52Lennart Poettering/* lookup event for identical, parent, child device */
812cce323db081634f37e4ec6d29f2b9328a3f52Lennart Poetteringstatic int devpath_busy(struct udev_event *event)
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering{
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering struct udev_list_node *loop;
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /* check if queue contains events we depend on */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering udev_list_node_foreach(loop, &event_list) {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering struct udev_event *loop_event = node_to_event(loop);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers /* we already found a later event, earlier can not block us, no need to check again */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (udev_device_get_seqnum(loop_event->dev) < event->delaying_seqnum)
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering continue;
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /* event we checked earlier still exists, no need to check again */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (udev_device_get_seqnum(loop_event->dev) == event->delaying_seqnum)
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering return 2;
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /* found ourself, no later event can block us */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (udev_device_get_seqnum(loop_event->dev) >= udev_device_get_seqnum(event->dev))
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering break;
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /* check our old name */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (udev_device_get_devpath_old(event->dev) != NULL)
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (strcmp(udev_device_get_devpath(loop_event->dev), udev_device_get_devpath_old(event->dev)) == 0) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering return 3;
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering }
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /* check identical, parent, or child device event */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (compare_devpath(udev_device_get_devpath(loop_event->dev), udev_device_get_devpath(event->dev)) != 0) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering dbg(event->udev, "%llu, device event still pending %llu (%s)\n",
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_seqnum(event->dev),
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_seqnum(loop_event->dev),
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_devpath(loop_event->dev));
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering return 4;
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering }
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /* check for our major:minor number */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (major(udev_device_get_devnum(event->dev)) > 0 &&
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_devnum(loop_event->dev) == udev_device_get_devnum(event->dev) &&
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering strcmp(udev_device_get_subsystem(event->dev), udev_device_get_subsystem(loop_event->dev)) == 0) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering dbg(event->udev, "%llu, device event still pending %llu (%d:%d)\n",
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_seqnum(event->dev),
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering udev_device_get_seqnum(loop_event->dev),
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering major(udev_device_get_devnum(loop_event->dev)), minor(udev_device_get_devnum(loop_event->dev)));
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering return 5;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering return 0;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering}
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering/* serializes events for the identical and parent and child devices */
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poetteringstatic void event_queue_manager(struct udev *udev)
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering{
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering struct udev_list_node *loop;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering struct udev_list_node *tmp;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poetteringstart_over:
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (udev_list_is_empty(&event_list)) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (childs > 0) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering err(udev, "event list empty, but childs count is %i", childs);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering childs = 0;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering return;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering udev_list_node_foreach_safe(loop, tmp, &event_list) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering struct udev_event *loop_event = node_to_event(loop);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (childs >= max_childs) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering info(udev, "maximum number (%i) of childs reached\n", childs);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering break;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (loop_event->pid != 0)
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering continue;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering /* do not start event if parent or child event is still running */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (devpath_busy(loop_event) != 0) {
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering dbg(udev, "delay seq %llu (%s)\n",
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering udev_device_get_seqnum(loop_event->dev),
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering udev_device_get_devpath(loop_event->dev));
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering continue;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering }
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering event_fork(loop_event);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering dbg(udev, "moved seq %llu to running list\n", udev_device_get_seqnum(loop_event->dev));
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering /* retry if events finished in the meantime */
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering if (sigchilds_waiting) {
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering sigchilds_waiting = 0;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering reap_sigchilds();
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering goto start_over;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering }
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering }
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering}
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering/* receive the udevd message from userspace */
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poetteringstatic void handle_ctrl_msg(struct udev_ctrl *uctrl)
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering{
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering struct udev *udev = udev_ctrl_get_udev(uctrl);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering struct udev_ctrl_msg *ctrl_msg;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering const char *str;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering int i;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering ctrl_msg = udev_ctrl_receive_msg(uctrl);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering if (ctrl_msg == NULL)
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering return;
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering i = udev_ctrl_get_set_log_level(ctrl_msg);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering if (i >= 0) {
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering info(udev, "udevd message (SET_LOG_PRIORITY) received, log_priority=%i\n", i);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering udev_set_log_priority(udev, i);
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering }
4927fcae48de061393b3ce9c12d49f80d73fbf1dLennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) {
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering info(udev, "udevd message (STOP_EXEC_QUEUE) received\n");
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering stop_exec_q = 1;
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering }
880a599e262b9193219e612d827b35bb0c292daeTom Gundersen
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) {
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering info(udev, "udevd message (START_EXEC_QUEUE) received\n");
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering stop_exec_q = 0;
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering event_queue_manager(udev);
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering }
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering if (udev_ctrl_get_reload_rules(ctrl_msg) > 0) {
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering info(udev, "udevd message (RELOAD_RULES) received\n");
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering reload_config = 1;
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering }
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering str = udev_ctrl_get_set_env(ctrl_msg);
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering if (str != NULL) {
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering char *key;
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering key = strdup(str);
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering if (key != NULL) {
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering char *val;
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers val = strchr(key, '=');
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna if (val != NULL) {
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna val[0] = '\0';
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna val = &val[1];
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers if (val[0] == '\0') {
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna info(udev, "udevd message (ENV) received, unset '%s'\n", key);
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna udev_add_property(udev, key, NULL);
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna } else {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers info(udev, "udevd message (ENV) received, set '%s=%s'\n", key, val);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering udev_add_property(udev, key, val);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering }
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering } else {
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers err(udev, "wrong key format '%s'\n", key);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering }
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering free(key);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering i = udev_ctrl_get_set_max_childs(ctrl_msg);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering if (i >= 0) {
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers info(udev, "udevd message (SET_MAX_CHILDS) received, max_childs=%i\n", i);
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering max_childs = i;
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering }
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers settle_pid = udev_ctrl_get_settle(ctrl_msg);
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering if (settle_pid > 0) {
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering info(udev, "udevd message (SETTLE) received\n");
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering }
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers udev_ctrl_msg_unref(ctrl_msg);
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering}
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering/* read inotify messages */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sieversstatic int handle_inotify(struct udev *udev)
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering{
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering int nbytes, pos;
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering char *buf;
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers struct inotify_event *ev;
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering if ((ioctl(inotify_fd, FIONREAD, &nbytes) < 0) || (nbytes <= 0))
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering return 0;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers buf = malloc(nbytes);
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers if (buf == NULL) {
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers err(udev, "error getting buffer for inotify, disable watching\n");
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers close(inotify_fd);
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers inotify_fd = -1;
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers return 0;
4c80c73c2b804576b1de27e644c1da4dab2f9026Kay Sievers }
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers read(inotify_fd, buf, nbytes);
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna for (pos = 0; pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) {
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna struct udev_device *dev;
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna ev = (struct inotify_event *)(buf + pos);
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna if (ev->len) {
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna dbg(udev, "inotify event: %x for %s\n", ev->mask, ev->name);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers reload_config = 1;
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna continue;
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna }
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers dev = udev_watch_lookup(udev, ev->wd);
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna if (dev != NULL) {
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna dbg(udev, "inotify event: %x for %s\n", ev->mask, udev_device_get_devnode(dev));
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna if (ev->mask & IN_CLOSE_WRITE) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers char filename[UTIL_PATH_SIZE];
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna int fd;
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna info(udev, "device %s closed, synthesising 'change'\n", udev_device_get_devnode(dev));
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers util_strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL);
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna fd = open(filename, O_WRONLY);
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna if (fd < 0 || write(fd, "change", 6) < 0)
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna info(udev, "error writing uevent: %m\n");
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers close(fd);
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering }
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering if (ev->mask & IN_IGNORED)
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering udev_watch_end(udev, dev);
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering udev_device_unref(dev);
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering }
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers free (buf);
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers return 0;
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers}
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sieversstatic void sig_handler(int signum)
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers{
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers switch (signum) {
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers case SIGINT:
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers case SIGTERM:
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers udev_exit = 1;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers break;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers case SIGCHLD:
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers /* set flag, then write to pipe if needed */
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers sigchilds_waiting = 1;
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers break;
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers case SIGHUP:
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers reload_config = 1;
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers break;
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers }
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers
9a203affa6e1866f9b9b68501d10102d21c9d0daKay Sievers signal_received = 1;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers}
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sieversstatic void udev_done(int pid, int exitstatus)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers{
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers struct udev_list_node *loop;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers /* find event associated with pid and delete it */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers udev_list_node_foreach(loop, &event_list) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers struct udev_event *loop_event = node_to_event(loop);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (loop_event->pid == pid) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers info(loop_event->udev, "seq %llu cleanup, pid [%d], status %i, %ld seconds old\n",
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers udev_device_get_seqnum(loop_event->dev), loop_event->pid,
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers exitstatus, time(NULL) - loop_event->queue_time);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers loop_event->exitstatus = exitstatus;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (debug_trace)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers fprintf(stderr, "exit %s (%llu)\n",
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers udev_device_get_syspath(loop_event->dev),
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers udev_device_get_seqnum(loop_event->dev));
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers event_queue_delete(loop_event);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers childs--;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers /* there may be dependent events waiting */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers run_exec_q = 1;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers return;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers}
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sieversstatic void reap_sigchilds(void)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers{
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers pid_t pid;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers int status;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers while (1) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers pid = waitpid(-1, &status, WNOHANG);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (pid <= 0)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers break;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (WIFEXITED(status))
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers status = WEXITSTATUS(status);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers else if (WIFSIGNALED(status))
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers status = WTERMSIG(status) + 128;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers else
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers status = 0;
75db9a77605b33a1b9355eae957f26380441fce6Lennart Poettering udev_done(pid, status);
4c2b0e4e423fe73fafef10a5efa6fb778784cebcLennart Poettering }
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek}
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmekstatic void startup_log(struct udev *udev)
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek{
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek FILE *f;
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek char path[UTIL_PATH_SIZE];
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek struct stat statbuf;
75db9a77605b33a1b9355eae957f26380441fce6Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers f = fopen("/dev/kmsg", "w");
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (f != NULL)
8401e9f91d65c3d8d49cf0d2e35d03146354e957Auke Kok fprintf(f, "<6>udev: starting version " VERSION "\n");
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/class/mem/null", NULL);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering if (lstat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering const char *depr_str =
c87f7103fe38434f0b88df5c2b080c7b558feabfZbigniew Jędrzejewski-Szmek "udev: missing sysfs features; please update the kernel "
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering "or disable the kernel's CONFIG_SYSFS_DEPRECATED option; "
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering "udev may fail to work correctly";
3ce4fad8f548db9edb19869ea540e3192d2123f4Kay Sievers
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering if (f != NULL)
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering fprintf(f, "<3>%s\n", depr_str);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering err(udev, "%s\n", depr_str);
7d568925bda9797f611e36d1d00cd941701cb3c8Lennart Poettering sleep(3);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering }
34eff652cedec3cac34b92629ead5f140334b689Lennart Poettering
34eff652cedec3cac34b92629ead5f140334b689Lennart Poettering if (f != NULL)
f1dd0c3f9b4a257e81ff9c6a08070c702a0db45aLennart Poettering fclose(f);
34eff652cedec3cac34b92629ead5f140334b689Lennart Poettering}
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering
12e84679cc81cdf5f042540e54131a0ce37147adLennart Poetteringint main(int argc, char *argv[])
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering{
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering struct udev *udev;
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering int fd;
2c696a96a2bd63d2ff0d5595622124ef9270b172Lennart Poettering struct sigaction act;
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering const char *value;
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering int daemonize = 0;
3ce4fad8f548db9edb19869ea540e3192d2123f4Kay Sievers int resolve_names = 1;
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering static const struct option options[] = {
634826b51b074b2e6d9314031bdd9abdcf862b54Pavol Rusnak { "daemon", no_argument, NULL, 'd' },
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering { "debug-trace", no_argument, NULL, 't' },
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering { "debug", no_argument, NULL, 'D' },
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering { "help", no_argument, NULL, 'h' },
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering { "version", no_argument, NULL, 'V' },
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds { "resolve-names", required_argument, NULL, 'N' },
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering {}
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering };
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds int rc = 1;
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds udev = udev_new();
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering if (udev == NULL)
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds goto exit;
d7c114c00030309435fc56c77c8578a25d228ebeDave Reisner
4bf43a32a96465d2f9c244adea3e661075f208bfTom Gundersen logging_init("udevd");
4bf43a32a96465d2f9c244adea3e661075f208bfTom Gundersen udev_set_log_fn(udev, log_fn);
d7c114c00030309435fc56c77c8578a25d228ebeDave Reisner info(udev, "version %s\n", VERSION);
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering udev_selinux_init(udev);
d7c114c00030309435fc56c77c8578a25d228ebeDave Reisner
f2b4af1cd4112df6ce56f8fc1e677639935e3d0eFabian Henze while (1) {
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio int option;
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio
f2b4af1cd4112df6ce56f8fc1e677639935e3d0eFabian Henze option = getopt_long(argc, argv, "dDthV", options, NULL);
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering if (option == -1)
f2b4af1cd4112df6ce56f8fc1e677639935e3d0eFabian Henze break;
65c8976ab12f13fc339a16d108e620bf2fd703f4Malcolm Studd
65c8976ab12f13fc339a16d108e620bf2fd703f4Malcolm Studd switch (option) {
65c8976ab12f13fc339a16d108e620bf2fd703f4Malcolm Studd case 'd':
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering daemonize = 1;
65c8976ab12f13fc339a16d108e620bf2fd703f4Malcolm Studd break;
f5c88ec1330b61787441156de7d764a140774bd2Miklos Vajna case 't':
f5c88ec1330b61787441156de7d764a140774bd2Miklos Vajna debug_trace = 1;
f5c88ec1330b61787441156de7d764a140774bd2Miklos Vajna break;
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering case 'D':
f5c88ec1330b61787441156de7d764a140774bd2Miklos Vajna debug = 1;
a338bab5d0603a179befce062bc6fc8a6521a232Alexey Shabalin if (udev_get_log_priority(udev) < LOG_INFO)
a338bab5d0603a179befce062bc6fc8a6521a232Alexey Shabalin udev_set_log_priority(udev, LOG_INFO);
a338bab5d0603a179befce062bc6fc8a6521a232Alexey Shabalin break;
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering case 'N':
a338bab5d0603a179befce062bc6fc8a6521a232Alexey Shabalin if (strcmp (optarg, "early") == 0) {
1de4d79bf554946f486adf56ed765c5335816f15Andrey Borzenkov resolve_names = 1;
1de4d79bf554946f486adf56ed765c5335816f15Andrey Borzenkov } else if (strcmp (optarg, "late") == 0) {
1de4d79bf554946f486adf56ed765c5335816f15Andrey Borzenkov resolve_names = 0;
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering } else if (strcmp (optarg, "never") == 0) {
1de4d79bf554946f486adf56ed765c5335816f15Andrey Borzenkov resolve_names = -1;
1bd8b8184ee3bc7fc023d6d6dfb2ca99fb6612f3Koen Kooi } else {
1bd8b8184ee3bc7fc023d6d6dfb2ca99fb6612f3Koen Kooi fprintf(stderr, "resolve-names must be early, late or never\n");
1bd8b8184ee3bc7fc023d6d6dfb2ca99fb6612f3Koen Kooi err(udev, "resolve-names must be early, late or never\n");
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering goto exit;
1bd8b8184ee3bc7fc023d6d6dfb2ca99fb6612f3Koen Kooi }
6fdae8a6a40d6a3b5f77516abaee23b3eab002f6Dexter Morgan break;
6fdae8a6a40d6a3b5f77516abaee23b3eab002f6Dexter Morgan case 'h':
6fdae8a6a40d6a3b5f77516abaee23b3eab002f6Dexter Morgan printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] "
fbf5b12653e29674b1e85c73d446b13ac3a15b38Colin Guthrie "[--resolve-names=early|late|never] [--version]\n");
6fdae8a6a40d6a3b5f77516abaee23b3eab002f6Dexter Morgan goto exit;
bf024b022d9f53d2bb8d26107b4878cede3167b7Tollef Fog Heen case 'V':
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering printf("%s\n", VERSION);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering goto exit;
bf024b022d9f53d2bb8d26107b4878cede3167b7Tollef Fog Heen default:
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering goto exit;
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering }
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering }
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers if (getuid() != 0) {
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers fprintf(stderr, "root privileges required\n");
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers err(udev, "root privileges required\n");
be31376e6c9add0786f31a38eec2ecfdb73eb115Kay Sievers goto exit;
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen }
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen /* make sure std{in,out,err} fd's are in a sane state */
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen fd = open("/dev/null", O_RDWR);
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen if (fd < 0) {
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen fprintf(stderr, "cannot open /dev/null\n");
136337ff74f05be3d42a769d9f0cb99716c5c40fTollef Fog Heen err(udev, "cannot open /dev/null\n");
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering }
d64b723a9e275ee4c6ccb947e3fd6ed6b3e4c359Lennart Poettering if (write(STDOUT_FILENO, 0, 0) < 0)
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering dup2(fd, STDOUT_FILENO);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering if (write(STDERR_FILENO, 0, 0) < 0)
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio dup2(fd, STDERR_FILENO);
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio /* init control socket, bind() ensures, that only one udevd instance is running */
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio if (udev_ctrl == NULL) {
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio fprintf(stderr, "error initializing control socket");
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio err(udev, "error initializing udevd socket");
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio rc = 1;
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio goto exit;
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio }
bef2733fae665e880da6ea011b1f918e6900bb42Lennart Poettering
a05ea46dc788929bc8b13afb4208ca29cad68572Michael Biebl if (udev_ctrl_enable_receiving(udev_ctrl) < 0) {
bef2733fae665e880da6ea011b1f918e6900bb42Lennart Poettering fprintf(stderr, "error binding control socket, seems udevd is already running\n");
bef2733fae665e880da6ea011b1f918e6900bb42Lennart Poettering err(udev, "error binding control socket, seems udevd is already running\n");
bef2733fae665e880da6ea011b1f918e6900bb42Lennart Poettering rc = 1;
bef2733fae665e880da6ea011b1f918e6900bb42Lennart Poettering goto exit;
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering }
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel");
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds if (kernel_monitor == NULL || udev_monitor_enable_receiving(kernel_monitor) < 0) {
858dae181bb5461201ac1c04732d3ef4c67a0256Andrew Edmunds fprintf(stderr, "error initializing netlink socket\n");
d7c114c00030309435fc56c77c8578a25d228ebeDave Reisner err(udev, "error initializing netlink socket\n");
f2b4af1cd4112df6ce56f8fc1e677639935e3d0eFabian Henze rc = 3;
65c8976ab12f13fc339a16d108e620bf2fd703f4Malcolm Studd goto exit;
f5c88ec1330b61787441156de7d764a140774bd2Miklos Vajna }
a338bab5d0603a179befce062bc6fc8a6521a232Alexey Shabalin udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024);
1de4d79bf554946f486adf56ed765c5335816f15Andrey Borzenkov
1bd8b8184ee3bc7fc023d6d6dfb2ca99fb6612f3Koen Kooi rules = udev_rules_new(udev, resolve_names);
6fdae8a6a40d6a3b5f77516abaee23b3eab002f6Dexter Morgan if (rules == NULL) {
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering err(udev, "error reading rules\n");
cca4aeeead1985f503d175eb1fcad9ed66f2e25dLennart Poettering goto exit;
cd3f8b7ddb052ab5e4eab420968bae689db3899aJeff Mahoney }
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering udev_list_init(&event_list);
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering udev_queue_export = udev_queue_export_new(udev);
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering if (udev_queue_export == NULL) {
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering err(udev, "error creating queue file\n");
d122948d6fbaac4505cf14a08f1237daa89efdd0Lennart Poettering goto exit;
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering }
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering if (daemonize) {
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering pid_t pid;
d122948d6fbaac4505cf14a08f1237daa89efdd0Lennart Poettering
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering pid = fork();
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering switch (pid) {
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering case 0:
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering dbg(udev, "daemonized fork running\n");
d122948d6fbaac4505cf14a08f1237daa89efdd0Lennart Poettering break;
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering case -1:
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering err(udev, "fork of daemon failed: %m\n");
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering rc = 4;
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering goto exit;
d122948d6fbaac4505cf14a08f1237daa89efdd0Lennart Poettering default:
b8079ae19b41c9b61850c796dddc601b826850e0Kay Sievers dbg(udev, "child [%u] running, parent exits\n", pid);
b8079ae19b41c9b61850c796dddc601b826850e0Kay Sievers rc = 0;
39ad55a9aa99451f982628af6e14581092b2d2f6Kay Sievers goto exit;
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering }
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers }
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers /* redirect std{out,err} */
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers if (!debug && !debug_trace) {
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers dup2(fd, STDIN_FILENO);
9d3203b4765e64300ab8e8d6d3d1b9ed0c514d5eKay Sievers dup2(fd, STDOUT_FILENO);
b0cca7d886583a10b9342796b4619eca4d582cb2Michael Biebl dup2(fd, STDERR_FILENO);
9d3203b4765e64300ab8e8d6d3d1b9ed0c514d5eKay Sievers }
9d3203b4765e64300ab8e8d6d3d1b9ed0c514d5eKay Sievers if (fd > STDERR_FILENO)
9d3203b4765e64300ab8e8d6d3d1b9ed0c514d5eKay Sievers close(fd);
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny /* set scheduling priority for the daemon */
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny chdir("/");
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny umask(022);
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny setsid();
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny /* OOM_DISABLE == -17 */
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny fd = open("/proc/self/oom_adj", O_RDWR);
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering if (fd < 0)
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny err(udev, "error disabling OOM: %m\n");
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering else {
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering write(fd, "-17", 3);
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering close(fd);
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering }
d2d12cd1bfd90f3a13273d82331a7cbd36a93231Lennart Poettering
8c6db8336536916d0476ff8233e0abf40a2f6aabLennart Poettering startup_log(udev);
b8079ae19b41c9b61850c796dddc601b826850e0Kay Sievers
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers /* set signal handlers */
8c4a3079a7f358c179430d1aec59de8b670b5f6eLennart Poettering memset(&act, 0x00, sizeof(struct sigaction));
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers act.sa_handler = sig_handler;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers sigemptyset(&act.sa_mask);
bb061708d5aa83579f213bdfb67253f7027217c3Kay Sievers act.sa_flags = SA_RESTART;
bb061708d5aa83579f213bdfb67253f7027217c3Kay Sievers sigaction(SIGINT, &act, NULL);
bb061708d5aa83579f213bdfb67253f7027217c3Kay Sievers sigaction(SIGTERM, &act, NULL);
bb061708d5aa83579f213bdfb67253f7027217c3Kay Sievers sigaction(SIGCHLD, &act, NULL);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers sigaction(SIGHUP, &act, NULL);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
a45a909fbbe11ad8c75cda5639d875476ac65453Christian Ruppert /* watch rules directory */
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers udev_watch_init(udev);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering if (inotify_fd >= 0) {
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering if (udev_get_rules_path(udev) != NULL) {
2c696a96a2bd63d2ff0d5595622124ef9270b172Lennart Poettering inotify_add_watch(inotify_fd, udev_get_rules_path(udev),
07459bb6b92268beb2599f65cf195708d88c51ccFabiano Fidêncio IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering } else {
0571e0111d76cf96aa4069d9c7a6e24d97aa7e48Lennart Poettering char filename[UTIL_PATH_SIZE];
7f4e08056de0184b205a20632e62db73d299937eLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering inotify_add_watch(inotify_fd, UDEV_PREFIX "/lib/udev/rules.d",
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
1271623839b5bb4f0f383a8ad5500462dda0a94aLennart Poettering inotify_add_watch(inotify_fd, SYSCONFDIR "/udev/rules.d",
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
1271623839b5bb4f0f383a8ad5500462dda0a94aLennart Poettering
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering /* watch dynamic rules directory */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering inotify_add_watch(inotify_fd, filename,
f6a971bc0bf1252e9614919ccca0d53db5fc53d9Lennart Poettering IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
27669061f40766457db93d5cc3dfe00dce240806Miklos Vajna }
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering
e5e83e8362e946890ac991fc86a2c5869f9befdfLennart Poettering udev_watch_restore(udev);
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering }
4de856120f252e7aa19c923c10fbf23310d623aaLennart Poettering
2a018e83ded29c9719b2478a65ee6245c829c0f5Kay Sievers /* in trace mode run one event after the other */
b2e9fb99ab288e8817302851743ed1a3cddd384bMiklos Vajna if (debug_trace) {
f47cd184c0ff80e025428e9e385e61bda1ef3d69Miklos Vajna max_childs = 1;
4cd1eaa54507a65286413363216ad407fa7c6e50Miklos Vajna } else {
f5e04665ebf7124f3ea17dcf258793ed73a95fe1Lennart Poettering int memsize = mem_size_mb();
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (memsize > 0)
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers max_childs = 128 + (memsize / 4);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers else
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers max_childs = UDEVD_MAX_CHILDS;
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers /* possibly overwrite maximum limit of executed events */
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers value = getenv("UDEVD_MAX_CHILDS");
8c4a3079a7f358c179430d1aec59de8b670b5f6eLennart Poettering if (value)
b8079ae19b41c9b61850c796dddc601b826850e0Kay Sievers max_childs = strtoul(value, NULL, 10);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers info(udev, "initialize max_childs to %u\n", max_childs);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers while (!udev_exit) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers sigset_t blocked_mask, orig_mask;
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers struct pollfd pfd[4];
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers struct pollfd *ctrl_poll, *monitor_poll, *inotify_poll = NULL;
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering int nfds = 0;
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering int fdcount;
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering sigfillset(&blocked_mask);
2c6db6fb9b1a10184b086df0d23228c4c0205a49Lennart Poettering sigprocmask(SIG_SETMASK, &blocked_mask, &orig_mask);
bc9bdbbab45ea2c10fdd8ad7c517b5e4a358bdfbMichał Górny if (signal_received) {
5ee9f21e86bb6a06d3eb956546f85338e81395e6Lennart Poettering sigprocmask(SIG_SETMASK, &orig_mask, NULL);
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek goto handle_signals;
66be6554807773028a0111addb8e75c3cab11117Kay Sievers }
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering ctrl_poll = &pfd[nfds++];
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering ctrl_poll->fd = udev_ctrl_get_fd(udev_ctrl);
ae446765eb0605d2451bb4dd7c336672bcc7ab0cKay Sievers ctrl_poll->events = POLLIN;
monitor_poll = &pfd[nfds++];
monitor_poll->fd = udev_monitor_get_fd(kernel_monitor);
monitor_poll->events = POLLIN;
if (inotify_fd >= 0) {
inotify_poll = &pfd[nfds++];
inotify_poll->fd = inotify_fd;
inotify_poll->events = POLLIN;
}
fdcount = ppoll(pfd, nfds, NULL, &orig_mask);
sigprocmask(SIG_SETMASK, &orig_mask, NULL);
if (fdcount < 0) {
if (errno == EINTR)
goto handle_signals;
err(udev, "error in select: %m\n");
continue;
}
/* get control message */
if (ctrl_poll->revents & POLLIN)
handle_ctrl_msg(udev_ctrl);
/* get kernel uevent */
if (monitor_poll->revents & POLLIN) {
struct udev_device *dev;
dev = udev_monitor_receive_device(kernel_monitor);
if (dev != NULL) {
struct udev_event *event;
event = udev_event_new(dev);
if (event != NULL)
event_queue_insert(event);
else
udev_device_unref(dev);
}
}
/* rules directory inotify watch */
if (inotify_poll && (inotify_poll->revents & POLLIN))
handle_inotify(udev);
handle_signals:
signal_received = 0;
/* rules changed, set by inotify or a HUP signal */
if (reload_config) {
struct udev_rules *rules_new;
reload_config = 0;
rules_new = udev_rules_new(udev, resolve_names);
if (rules_new != NULL) {
udev_rules_unref(rules);
rules = rules_new;
}
}
if (sigchilds_waiting) {
sigchilds_waiting = 0;
reap_sigchilds();
}
if (run_exec_q) {
run_exec_q = 0;
if (!stop_exec_q)
event_queue_manager(udev);
}
if (settle_pid > 0) {
kill(settle_pid, SIGUSR1);
settle_pid = 0;
}
}
udev_queue_export_cleanup(udev_queue_export);
rc = 0;
exit:
udev_queue_export_unref(udev_queue_export);
udev_rules_unref(rules);
udev_ctrl_unref(udev_ctrl);
if (inotify_fd >= 0)
close(inotify_fd);
udev_monitor_unref(kernel_monitor);
udev_selinux_exit(udev);
udev_unref(udev);
logging_close();
return rc;
}