]> git.ipfire.org Git - thirdparty/systemd.git/blame - udev/udevd.c
udevadm: settle - use timeout signal, instead of loop counter
[thirdparty/systemd.git] / udev / udevd.c
CommitLineData
7fafc032 1/*
55e9959b 2 * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
2f6cbd19 3 * Copyright (C) 2004 Chris Friesen <chris_friesen@sympatico.ca>
7fafc032 4 *
55e9959b
KS
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
7fafc032 9 *
55e9959b
KS
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
7fafc032 14 *
55e9959b
KS
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
7fafc032
KS
17 */
18
a695feae 19#include <stddef.h>
7fafc032
KS
20#include <signal.h>
21#include <unistd.h>
22#include <errno.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
085cce37 26#include <ctype.h>
085cce37 27#include <fcntl.h>
0b3dfb3d 28#include <time.h>
b52a01ee 29#include <getopt.h>
78230c0d 30#include <dirent.h>
138068d6 31#include <sys/select.h>
3210a72b 32#include <sys/poll.h>
138068d6 33#include <sys/wait.h>
dc117daa 34#include <sys/stat.h>
c895fd00 35#include <sys/ioctl.h>
01618658
KS
36#ifdef HAVE_INOTIFY
37#include <sys/inotify.h>
38#endif
7fafc032
KS
39
40#include "udev.h"
7fafc032 41
d59f11e1
KS
42#define UDEVD_PRIORITY -4
43#define UDEV_PRIORITY -2
44
45/* maximum limit of forked childs */
46#define UDEVD_MAX_CHILDS 256
d59f11e1 47
c70560fe 48static int debug;
9e8fe79b 49
7d563a17
KS
50static void log_fn(struct udev *udev, int priority,
51 const char *file, int line, const char *fn,
52 const char *format, va_list args)
53{
54 if (debug) {
55 fprintf(stderr, "[%d] %s: ", (int) getpid(), fn);
56 vfprintf(stderr, format, args);
57 } else {
58 vsyslog(priority, format, args);
59 }
60}
61
d1cc6562
OK
62static void reap_sigchilds(void);
63
7d563a17 64static int debug_trace;
d7ddce18 65static struct udev_rules *rules;
d59f11e1 66static struct udev_ctrl *udev_ctrl;
aa8734ff 67static struct udev_monitor *kernel_monitor;
5cab7caa 68static volatile int sigchilds_waiting;
63cc8f04 69static volatile int udev_exit;
c895fd00 70static volatile int reload_config;
3210a72b 71static volatile int signal_received;
f27125f9 72static int run_exec_q;
3b47c739 73static int stop_exec_q;
a15f42c4 74static int max_childs;
0bc74ea7
KS
75static int childs;
76static struct udev_list_node event_list;
a15f42c4 77
7a770250
KS
78enum event_state {
79 EVENT_QUEUED,
80 EVENT_FINISHED,
81 EVENT_FAILED,
82};
83
7e027927
KS
84static struct udev_event *node_to_event(struct udev_list_node *node)
85{
86 char *event;
87
88 event = (char *)node;
89 event -= offsetof(struct udev_event, node);
90 return (struct udev_event *)event;
91}
92
aa8734ff 93static void export_event_state(struct udev_event *event, enum event_state state)
7a770250 94{
17fcfb59
KS
95 char filename[UTIL_PATH_SIZE];
96 char filename_failed[UTIL_PATH_SIZE];
9c6ad9fb 97 size_t start;
7a770250 98
a2f2270e 99 /* location of queue file */
aa8734ff
KS
100 snprintf(filename, sizeof(filename), "%s/.udev/queue/%llu",
101 udev_get_dev_path(event->udev), udev_device_get_seqnum(event->dev));
7a770250 102
a2f2270e 103 /* location of failed file */
aa8734ff 104 util_strlcpy(filename_failed, udev_get_dev_path(event->udev), sizeof(filename_failed));
31c1f537
KS
105 util_strlcat(filename_failed, "/", sizeof(filename_failed));
106 start = util_strlcat(filename_failed, ".udev/failed/", sizeof(filename_failed));
aa8734ff 107 util_strlcat(filename_failed, udev_device_get_devpath(event->dev), sizeof(filename_failed));
ecc9ec57 108 util_path_encode(&filename_failed[start], sizeof(filename_failed) - start);
7a770250
KS
109
110 switch (state) {
111 case EVENT_QUEUED:
836dcf95 112 if(unlink(filename_failed) == 0)
54808d77
KS
113 util_delete_path(event->udev, filename_failed);
114 util_create_path(event->udev, filename);
aa8734ff
KS
115 udev_selinux_setfscreatecon(event->udev, filename, S_IFLNK);
116 symlink(udev_device_get_devpath(event->dev), filename);
117 udev_selinux_resetfscreatecon(event->udev);
ce398745 118 break;
7a770250 119 case EVENT_FINISHED:
aa8734ff 120 if (udev_device_get_devpath_old(event->dev) != NULL) {
a2f2270e 121 /* "move" event - rename failed file to current name, do not delete failed */
17fcfb59 122 char filename_failed_old[UTIL_PATH_SIZE];
a2f2270e 123
aa8734ff 124 util_strlcpy(filename_failed_old, udev_get_dev_path(event->udev), sizeof(filename_failed_old));
31c1f537
KS
125 util_strlcat(filename_failed_old, "/", sizeof(filename_failed_old));
126 start = util_strlcat(filename_failed_old, ".udev/failed/", sizeof(filename_failed_old));
aa8734ff 127 util_strlcat(filename_failed_old, udev_device_get_devpath_old(event->dev), sizeof(filename_failed_old));
ecc9ec57 128 util_path_encode(&filename_failed_old[start], sizeof(filename) - start);
a2f2270e
KS
129
130 if (rename(filename_failed_old, filename_failed) == 0)
aa8734ff
KS
131 info(event->udev, "renamed devpath, moved failed state of '%s' to %s'\n",
132 udev_device_get_devpath_old(event->dev), udev_device_get_devpath(event->dev));
a2f2270e 133 } else {
836dcf95 134 if (unlink(filename_failed) == 0)
54808d77 135 util_delete_path(event->udev, filename_failed);
a2f2270e 136 }
7a770250 137
ce398745 138 unlink(filename);
836dcf95
AJ
139
140 /* clean up possibly empty queue directory */
0bc74ea7 141 if (udev_list_is_empty(&event_list))
54808d77 142 util_delete_path(event->udev, filename);
ce398745
KS
143 break;
144 case EVENT_FAILED:
a2f2270e 145 /* move failed event to the failed directory */
54808d77 146 util_create_path(event->udev, filename_failed);
ce398745 147 rename(filename, filename_failed);
1b75f109 148
a2f2270e 149 /* clean up possibly empty queue directory */
0bc74ea7 150 if (udev_list_is_empty(&event_list))
54808d77 151 util_delete_path(event->udev, filename);
ce398745 152 break;
7a770250 153 }
ce398745
KS
154
155 return;
7a770250
KS
156}
157
aa8734ff 158static void event_queue_delete(struct udev_event *event)
fc465079 159{
7e027927 160 udev_list_node_remove(&event->node);
7a770250 161
a2f2270e 162 /* mark as failed, if "add" event returns non-zero */
aa8734ff
KS
163 if (event->exitstatus && strcmp(udev_device_get_action(event->dev), "add") == 0)
164 export_event_state(event, EVENT_FAILED);
7a770250 165 else
aa8734ff
KS
166 export_event_state(event, EVENT_FINISHED);
167
168 udev_device_unref(event->dev);
169 udev_event_unref(event);
170}
7a770250 171
aa8734ff
KS
172static void asmlinkage event_sig_handler(int signum)
173{
174 if (signum == SIGALRM)
175 exit(1);
fc465079
KS
176}
177
aa8734ff 178static void event_fork(struct udev_event *event)
7fafc032 179{
90c210eb 180 pid_t pid;
aa8734ff
KS
181 struct sigaction act;
182 int err;
90c210eb 183
0bc74ea7
KS
184 if (debug_trace) {
185 event->trace = 1;
27691aa3 186 fprintf(stderr, "fork %s (%llu)\n",
0bc74ea7
KS
187 udev_device_get_syspath(event->dev),
188 udev_device_get_seqnum(event->dev));
189 }
190
90c210eb
KS
191 pid = fork();
192 switch (pid) {
193 case 0:
33db4b8d 194 /* child */
aa8734ff 195 udev_monitor_unref(kernel_monitor);
d59f11e1 196 udev_ctrl_unref(udev_ctrl);
f602ccf0 197 logging_close();
c895fd00 198 logging_init("udevd-event");
085cce37 199 setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
b437ec95 200
aa8734ff
KS
201 /* set signal handlers */
202 memset(&act, 0x00, sizeof(act));
203 act.sa_handler = (void (*)(int)) event_sig_handler;
204 sigemptyset (&act.sa_mask);
205 act.sa_flags = 0;
206 sigaction(SIGALRM, &act, NULL);
207
208 /* reset to default */
209 act.sa_handler = SIG_DFL;
210 sigaction(SIGINT, &act, NULL);
211 sigaction(SIGTERM, &act, NULL);
212 sigaction(SIGCHLD, &act, NULL);
213 sigaction(SIGHUP, &act, NULL);
214
215 /* set timeout to prevent hanging processes */
216 alarm(UDEV_EVENT_TIMEOUT);
217
218 /* apply rules, create node, symlinks */
dcdcb8cc 219 err = udev_event_execute_rules(event, rules);
aa8734ff
KS
220
221 /* rules may change/disable the timeout */
222 if (udev_device_get_event_timeout(event->dev) >= 0)
223 alarm(udev_device_get_event_timeout(event->dev));
224
225 /* execute RUN= */
226 if (err == 0 && !event->ignore_device && udev_get_run(event->udev))
2d73813e 227 udev_event_execute_run(event);
0bc74ea7 228
5ae82640 229 /* apply/restore inotify watch */
3d3a0a70 230 if (err == 0 && event->inotify_watch) {
5ae82640 231 udev_watch_begin(event->udev, event->dev);
3d3a0a70
KS
232 udev_device_update_db(event->dev);
233 }
5ae82640 234
cb25a958 235 info(event->udev, "seq %llu exit with %i\n", udev_device_get_seqnum(event->dev), err);
c895fd00 236 logging_close();
aa8734ff 237 if (err != 0)
f4fc0136 238 exit(1);
c895fd00 239 exit(0);
90c210eb 240 case -1:
aa8734ff
KS
241 err(event->udev, "fork of child failed: %m\n");
242 event_queue_delete(event);
2f6cbd19 243 break;
90c210eb 244 default:
2f6cbd19 245 /* get SIGCHLD in main loop */
aa8734ff
KS
246 info(event->udev, "seq %llu forked, pid [%d], '%s' '%s', %ld seconds old\n",
247 udev_device_get_seqnum(event->dev),
248 pid,
249 udev_device_get_action(event->dev),
250 udev_device_get_subsystem(event->dev),
251 time(NULL) - event->queue_time);
252 event->pid = pid;
0bc74ea7 253 childs++;
90c210eb 254 }
7fafc032
KS
255}
256
aa8734ff 257static void event_queue_insert(struct udev_event *event)
fc465079 258{
17fcfb59 259 char filename[UTIL_PATH_SIZE];
7baada47
KS
260 int fd;
261
aa8734ff 262 event->queue_time = time(NULL);
7baada47 263
aa8734ff 264 export_event_state(event, EVENT_QUEUED);
cb25a958
KS
265 info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(event->dev),
266 udev_device_get_action(event->dev), udev_device_get_subsystem(event->dev));
0f624f16 267
aa8734ff 268 util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename));
31c1f537 269 util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename));
7baada47 270 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
90cd961e 271 if (fd >= 0) {
7baada47
KS
272 char str[32];
273 int len;
274
aa8734ff 275 len = sprintf(str, "%llu\n", udev_device_get_seqnum(event->dev));
7baada47
KS
276 write(fd, str, len);
277 close(fd);
278 }
fc465079 279
0bc74ea7
KS
280
281 udev_list_node_append(&event->node, &event_list);
282 run_exec_q = 1;
c7c00276 283
fc465079 284 /* run all events with a timeout set immediately */
aa8734ff 285 if (udev_device_get_timeout(event->dev) > 0) {
aa8734ff 286 event_fork(event);
fc465079
KS
287 return;
288 }
fc465079
KS
289}
290
f051e340
KS
291static int mem_size_mb(void)
292{
9f1f67b1
KS
293 FILE* f;
294 char buf[4096];
295 long int memsize = -1;
f051e340 296
9f1f67b1
KS
297 f = fopen("/proc/meminfo", "r");
298 if (f == NULL)
f051e340 299 return -1;
f051e340 300
9f1f67b1
KS
301 while (fgets(buf, sizeof(buf), f) != NULL) {
302 long int value;
f051e340 303
9f1f67b1
KS
304 if (sscanf(buf, "MemTotal: %ld kB", &value) == 1) {
305 memsize = value / 1024;
306 break;
307 }
308 }
f051e340 309
fdc9a0b5 310 fclose(f);
9f1f67b1 311 return memsize;
f051e340
KS
312}
313
7b6571a9
KS
314static int compare_devpath(const char *running, const char *waiting)
315{
e25fa4fa 316 int i = 0;
7b6571a9 317
0bc74ea7 318 while (running[i] != '\0' && running[i] == waiting[i])
e25fa4fa 319 i++;
7b6571a9 320
e25fa4fa
AJ
321 /* identical device event found */
322 if (running[i] == '\0' && waiting[i] == '\0')
323 return 1;
7b6571a9 324
e25fa4fa
AJ
325 /* parent device event found */
326 if (running[i] == '\0' && waiting[i] == '/')
327 return 2;
7b6571a9 328
e25fa4fa
AJ
329 /* child device event found */
330 if (running[i] == '/' && waiting[i] == '\0')
331 return 3;
7b6571a9 332
e25fa4fa 333 /* no matching event */
7b6571a9
KS
334 return 0;
335}
336
fc630eda 337/* lookup event for identical, parent, child, or physical device */
0bc74ea7 338static int devpath_busy(struct udev_event *event)
7fafc032 339{
7e027927 340 struct udev_list_node *loop;
7b6571a9 341
0bc74ea7
KS
342 if (event->delaying_seqnum > 0) {
343 }
344 /* check if queue contains events we depend on */
345 udev_list_node_foreach(loop, &event_list) {
7e027927
KS
346 struct udev_event *loop_event = node_to_event(loop);
347
0bc74ea7
KS
348 /* we already found a later event, earlier can not block us, no need to check again */
349 if (udev_device_get_seqnum(loop_event->dev) < event->delaying_seqnum)
350 continue;
351
352 /* event we checked earlier still exists, no need to check again */
353 if (udev_device_get_seqnum(loop_event->dev) == event->delaying_seqnum)
354 return 2;
355
356 /* found ourself, no later event can block us */
aa8734ff 357 if (udev_device_get_seqnum(loop_event->dev) >= udev_device_get_seqnum(event->dev))
fc630eda
KS
358 break;
359
a2f2270e 360 /* check our old name */
aa8734ff 361 if (udev_device_get_devpath_old(event->dev) != NULL)
0bc74ea7
KS
362 if (strcmp(udev_device_get_devpath(loop_event->dev), udev_device_get_devpath_old(event->dev)) == 0) {
363 event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
364 return 3;
365 }
a2f2270e 366
fc630eda 367 /* check identical, parent, or child device event */
aa8734ff
KS
368 if (compare_devpath(udev_device_get_devpath(loop_event->dev), udev_device_get_devpath(event->dev)) != 0) {
369 dbg(event->udev, "%llu, device event still pending %llu (%s)\n",
370 udev_device_get_seqnum(event->dev),
371 udev_device_get_seqnum(loop_event->dev),
372 udev_device_get_devpath(loop_event->dev));
0bc74ea7 373 event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
c3b145a3
MK
374 return 4;
375 }
376
c3b145a3 377 /* check for our major:minor number */
aa8734ff
KS
378 if (major(udev_device_get_devnum(event->dev)) > 0 &&
379 udev_device_get_devnum(loop_event->dev) == udev_device_get_devnum(event->dev) &&
380 strcmp(udev_device_get_subsystem(event->dev), udev_device_get_subsystem(loop_event->dev)) == 0) {
381 dbg(event->udev, "%llu, device event still pending %llu (%d:%d)\n",
382 udev_device_get_seqnum(event->dev),
383 udev_device_get_seqnum(loop_event->dev),
384 major(udev_device_get_devnum(loop_event->dev)), minor(udev_device_get_devnum(loop_event->dev)));
0bc74ea7
KS
385 event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
386 return 5;
c3b145a3
MK
387 }
388
fc630eda 389 /* check physical device event (special case of parent) */
aa8734ff
KS
390 if (udev_device_get_physdevpath(event->dev) != NULL &&
391 strcmp(udev_device_get_action(event->dev), "add") == 0)
392 if (compare_devpath(udev_device_get_devpath(loop_event->dev),
393 udev_device_get_physdevpath(event->dev)) != 0) {
394 dbg(event->udev, "%llu, physical device event still pending %llu (%s)\n",
395 udev_device_get_seqnum(event->dev),
396 udev_device_get_seqnum(loop_event->dev),
397 udev_device_get_devpath(loop_event->dev));
0bc74ea7
KS
398 event->delaying_seqnum = udev_device_get_seqnum(loop_event->dev);
399 return 6;
a15f42c4 400 }
80513ea3 401 }
a15f42c4 402 return 0;
7fafc032
KS
403}
404
fc630eda 405/* serializes events for the identical and parent and child devices */
aa8734ff 406static void event_queue_manager(struct udev *udev)
7fafc032 407{
7e027927
KS
408 struct udev_list_node *loop;
409 struct udev_list_node *tmp;
085cce37 410
d1cc6562 411start_over:
0bc74ea7
KS
412 if (udev_list_is_empty(&event_list)) {
413 if (childs > 0) {
414 err(udev, "event list empty, but childs count is %i", childs);
415 childs = 0;
416 }
8ab44e3f 417 return;
0bc74ea7 418 }
8ab44e3f 419
0bc74ea7 420 udev_list_node_foreach_safe(loop, tmp, &event_list) {
7e027927
KS
421 struct udev_event *loop_event = node_to_event(loop);
422
0bc74ea7
KS
423 if (childs >= max_childs) {
424 info(udev, "maximum number (%i) of childs reached\n", childs);
425 break;
426 }
427
428 if (loop_event->pid != 0)
429 continue;
430
431 /* do not start event if parent or child event is still running */
432 if (devpath_busy(loop_event) != 0) {
aa8734ff
KS
433 dbg(udev, "delay seq %llu (%s)\n",
434 udev_device_get_seqnum(loop_event->dev),
435 udev_device_get_devpath(loop_event->dev));
fc465079
KS
436 continue;
437 }
438
aa8734ff
KS
439 event_fork(loop_event);
440 dbg(udev, "moved seq %llu to running list\n", udev_device_get_seqnum(loop_event->dev));
d1cc6562
OK
441
442 /* retry if events finished in the meantime */
443 if (sigchilds_waiting) {
444 sigchilds_waiting = 0;
445 reap_sigchilds();
446 goto start_over;
447 }
e825b59b 448 }
88f4b648
KS
449}
450
3b47c739 451/* receive the udevd message from userspace */
d59f11e1 452static void handle_ctrl_msg(struct udev_ctrl *uctrl)
7fafc032 453{
d59f11e1
KS
454 struct udev *udev = udev_ctrl_get_udev(uctrl);
455 struct udev_ctrl_msg *ctrl_msg;
456 const char *str;
457 int i;
7b1cbec9 458
d59f11e1
KS
459 ctrl_msg = udev_ctrl_receive_msg(uctrl);
460 if (ctrl_msg == NULL)
b437ec95 461 return;
4a231017 462
d59f11e1
KS
463 i = udev_ctrl_get_set_log_level(ctrl_msg);
464 if (i >= 0) {
465 info(udev, "udevd message (SET_LOG_PRIORITY) received, log_priority=%i\n", i);
466 udev_set_log_priority(udev, i);
0028653c
KS
467 }
468
d59f11e1 469 if (udev_ctrl_get_stop_exec_queue(ctrl_msg) > 0) {
7d563a17 470 info(udev, "udevd message (STOP_EXEC_QUEUE) received\n");
3b47c739 471 stop_exec_q = 1;
d59f11e1
KS
472 }
473
474 if (udev_ctrl_get_start_exec_queue(ctrl_msg) > 0) {
7d563a17 475 info(udev, "udevd message (START_EXEC_QUEUE) received\n");
3b47c739 476 stop_exec_q = 0;
aa8734ff 477 event_queue_manager(udev);
d59f11e1
KS
478 }
479
480 if (udev_ctrl_get_reload_rules(ctrl_msg) > 0) {
7d563a17 481 info(udev, "udevd message (RELOAD_RULES) received\n");
c895fd00 482 reload_config = 1;
3b47c739 483 }
d59f11e1
KS
484
485 str = udev_ctrl_get_set_env(ctrl_msg);
486 if (str != NULL) {
aa8734ff
KS
487 char *key;
488
489 key = strdup(str);
490 if (key != NULL) {
491 char *val;
492
493 val = strchr(key, '=');
494 if (val != NULL) {
495 val[0] = '\0';
496 val = &val[1];
497 if (val[0] == '\0') {
498 info(udev, "udevd message (ENV) received, unset '%s'\n", key);
499 udev_add_property(udev, key, NULL);
500 } else {
501 info(udev, "udevd message (ENV) received, set '%s=%s'\n", key, val);
502 udev_add_property(udev, key, val);
503 }
d59f11e1 504 } else {
aa8734ff 505 err(udev, "wrong key format '%s'\n", key);
d59f11e1 506 }
aa8734ff 507 free(key);
d59f11e1 508 }
d59f11e1
KS
509 }
510
511 i = udev_ctrl_get_set_max_childs(ctrl_msg);
512 if (i >= 0) {
513 info(udev, "udevd message (SET_MAX_CHILDS) received, max_childs=%i\n", i);
514 max_childs = i;
515 }
d59f11e1 516 udev_ctrl_msg_unref(ctrl_msg);
88f4b648 517}
4a231017 518
bd284db1
SJR
519/* read inotify messages */
520static int handle_inotify(struct udev *udev)
521{
522 int nbytes, pos;
523 char *buf;
524 struct inotify_event *ev;
bd284db1
SJR
525
526 if ((ioctl(inotify_fd, FIONREAD, &nbytes) < 0) || (nbytes <= 0))
527 return 0;
528
529 buf = malloc(nbytes);
530 if (buf == NULL) {
531 err(udev, "error getting buffer for inotify, disable watching\n");
532 close(inotify_fd);
533 inotify_fd = -1;
534 return 0;
535 }
536
537 read(inotify_fd, buf, nbytes);
538
80be8c48 539 for (pos = 0; pos < nbytes; pos += sizeof(struct inotify_event) + ev->len) {
047f88bc 540 struct udev_device *dev;
bd284db1 541
80be8c48 542 ev = (struct inotify_event *)(buf + pos);
b8e96d67
SJR
543 if (ev->len) {
544 dbg(udev, "inotify event: %x for %s\n", ev->mask, ev->name);
545 reload_config = 1;
546 continue;
547 }
548
047f88bc
SJR
549 dev = udev_watch_lookup(udev, ev->wd);
550 if (dev != NULL) {
551 dbg(udev, "inotify event: %x for %s\n", ev->mask, udev_device_get_devnode(dev));
bd284db1
SJR
552 if (ev->mask & IN_CLOSE_WRITE) {
553 char filename[UTIL_PATH_SIZE];
554 int fd;
555
047f88bc
SJR
556 info(udev, "device %s closed, synthesising 'change'\n", udev_device_get_devnode(dev));
557 util_strlcpy(filename, udev_device_get_syspath(dev), sizeof(filename));
bd284db1
SJR
558 util_strlcat(filename, "/uevent", sizeof(filename));
559 fd = open(filename, O_WRONLY);
560 if (fd < 0 || write(fd, "change", 6) < 0)
561 info(udev, "error writing uevent: %m\n");
562 close(fd);
563 }
564 if (ev->mask & IN_IGNORED)
047f88bc
SJR
565 udev_watch_end(udev, dev);
566
567 udev_device_unref(dev);
bd284db1 568 }
b8e96d67 569
bd284db1
SJR
570 }
571
572 free (buf);
4aca304e 573 return 0;
bd284db1
SJR
574}
575
e5a5b54a 576static void asmlinkage sig_handler(int signum)
7fafc032 577{
53921bfa
KS
578 switch (signum) {
579 case SIGINT:
580 case SIGTERM:
63cc8f04 581 udev_exit = 1;
53921bfa 582 break;
2f6cbd19 583 case SIGCHLD:
f27125f9 584 /* set flag, then write to pipe if needed */
5cab7caa 585 sigchilds_waiting = 1;
2f6cbd19 586 break;
c895fd00
KS
587 case SIGHUP:
588 reload_config = 1;
589 break;
f27125f9 590 }
5a73b25f 591
3210a72b 592 signal_received = 1;
33db4b8d 593}
7fafc032 594
f4fc0136 595static void udev_done(int pid, int exitstatus)
2f6cbd19 596{
7e027927
KS
597 struct udev_list_node *loop;
598
aa8734ff 599 /* find event associated with pid and delete it */
0bc74ea7 600 udev_list_node_foreach(loop, &event_list) {
7e027927 601 struct udev_event *loop_event = node_to_event(loop);
2f6cbd19 602
7e027927
KS
603 if (loop_event->pid == pid) {
604 info(loop_event->udev, "seq %llu cleanup, pid [%d], status %i, %ld seconds old\n",
605 udev_device_get_seqnum(loop_event->dev), loop_event->pid,
606 exitstatus, time(NULL) - loop_event->queue_time);
607 loop_event->exitstatus = exitstatus;
0bc74ea7 608 if (debug_trace)
27691aa3 609 fprintf(stderr, "exit %s (%llu)\n",
0bc74ea7
KS
610 udev_device_get_syspath(loop_event->dev),
611 udev_device_get_seqnum(loop_event->dev));
7e027927 612 event_queue_delete(loop_event);
0bc74ea7 613 childs--;
3169e8d1 614
0bc74ea7 615 /* there may be dependent events waiting */
f27125f9 616 run_exec_q = 1;
2f6cbd19
KS
617 return;
618 }
619 }
620}
621
5cab7caa 622static void reap_sigchilds(void)
f27125f9 623{
40caaeec 624 pid_t pid;
f4fc0136 625 int status;
ce043f85 626
40caaeec 627 while (1) {
f4fc0136 628 pid = waitpid(-1, &status, WNOHANG);
40caaeec 629 if (pid <= 0)
f27125f9 630 break;
f4fc0136
KS
631 if (WIFEXITED(status))
632 status = WEXITSTATUS(status);
82de5983
KS
633 else if (WIFSIGNALED(status))
634 status = WTERMSIG(status) + 128;
f4fc0136
KS
635 else
636 status = 0;
637 udev_done(pid, status);
f27125f9 638 }
639}
640
78230c0d
KS
641static void cleanup_queue_dir(struct udev *udev)
642{
643 char dirname[UTIL_PATH_SIZE];
644 char filename[UTIL_PATH_SIZE];
645 DIR *dir;
646
647 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
648 util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename));
649 unlink(filename);
650
651 util_strlcpy(dirname, udev_get_dev_path(udev), sizeof(dirname));
652 util_strlcat(dirname, "/.udev/queue", sizeof(dirname));
653 dir = opendir(dirname);
654 if (dir != NULL) {
655 while (1) {
656 struct dirent *dent;
657
658 dent = readdir(dir);
659 if (dent == NULL || dent->d_name[0] == '\0')
660 break;
661 if (dent->d_name[0] == '.')
662 continue;
663 util_strlcpy(filename, dirname, sizeof(filename));
664 util_strlcat(filename, "/", sizeof(filename));
665 util_strlcat(filename, dent->d_name, sizeof(filename));
666 unlink(filename);
667 }
668 closedir(dir);
669 rmdir(dirname);
670 }
671}
672
7d563a17 673static void export_initial_seqnum(struct udev *udev)
90cd961e 674{
17fcfb59 675 char filename[UTIL_PATH_SIZE];
90cd961e
KS
676 int fd;
677 char seqnum[32];
678 ssize_t len = 0;
679
31c1f537
KS
680 util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename));
681 util_strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename));
90cd961e
KS
682 fd = open(filename, O_RDONLY);
683 if (fd >= 0) {
684 len = read(fd, seqnum, sizeof(seqnum)-1);
685 close(fd);
686 }
687 if (len <= 0) {
688 strcpy(seqnum, "0\n");
689 len = 3;
690 }
31c1f537
KS
691 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
692 util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename));
54808d77 693 util_create_path(udev, filename);
90cd961e
KS
694 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
695 if (fd >= 0) {
696 write(fd, seqnum, len);
697 close(fd);
698 }
699}
700
59345311 701int main(int argc, char *argv[])
c2cf4012 702{
7d563a17 703 struct udev *udev;
3904a758 704 int fd;
f8911dbb 705 struct sigaction act;
a15f42c4 706 const char *value;
561d4c5a 707 int daemonize = 0;
5f03ed8a 708 int resolve_names = 1;
b52a01ee 709 static const struct option options[] = {
033e9f8c
KS
710 { "daemon", no_argument, NULL, 'd' },
711 { "debug-trace", no_argument, NULL, 't' },
712 { "debug", no_argument, NULL, 'D' },
713 { "help", no_argument, NULL, 'h' },
714 { "version", no_argument, NULL, 'V' },
5f03ed8a 715 { "resolve-names", required_argument, NULL, 'N' },
b52a01ee
KS
716 {}
717 };
e3396a2d 718 int rc = 1;
53921bfa 719
7d563a17
KS
720 udev = udev_new();
721 if (udev == NULL)
722 goto exit;
723
7257cb18 724 logging_init("udevd");
7d563a17 725 udev_set_log_fn(udev, log_fn);
aa8734ff 726 info(udev, "version %s\n", VERSION);
c3b1fa66 727 udev_selinux_init(udev);
95a6f4c8 728
b52a01ee 729 while (1) {
7d563a17
KS
730 int option;
731
c70560fe 732 option = getopt_long(argc, argv, "dDthV", options, NULL);
b52a01ee
KS
733 if (option == -1)
734 break;
735
736 switch (option) {
737 case 'd':
561d4c5a 738 daemonize = 1;
b52a01ee 739 break;
c7c00276
KS
740 case 't':
741 debug_trace = 1;
742 break;
c70560fe
KS
743 case 'D':
744 debug = 1;
7d563a17
KS
745 if (udev_get_log_priority(udev) < LOG_INFO)
746 udev_set_log_priority(udev, LOG_INFO);
9e8fe79b 747 break;
5f03ed8a
SJR
748 case 'N':
749 if (strcmp (optarg, "early") == 0) {
750 resolve_names = 1;
9032f119
SJR
751 } else if (strcmp (optarg, "late") == 0) {
752 resolve_names = 0;
5f03ed8a
SJR
753 } else if (strcmp (optarg, "never") == 0) {
754 resolve_names = -1;
755 } else {
9032f119
SJR
756 fprintf(stderr, "resolve-names must be early, late or never\n");
757 err(udev, "resolve-names must be early, late or never\n");
5f03ed8a
SJR
758 goto exit;
759 }
760 break;
b52a01ee 761 case 'h':
6469c772
KS
762 printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] "
763 "[--resolve-names=early|late|never] [--version]\n");
841e168c
MS
764 goto exit;
765 case 'V':
01618658 766 printf("%s\n", VERSION);
e3396a2d 767 goto exit;
b52a01ee
KS
768 default:
769 goto exit;
561d4c5a 770 }
561d4c5a 771 }
40caaeec 772
fc89fe7e
KS
773 if (getuid() != 0) {
774 fprintf(stderr, "root privileges required\n");
7d563a17 775 err(udev, "root privileges required\n");
fc89fe7e
KS
776 goto exit;
777 }
778
5edec024
MS
779 /* make sure std{in,out,err} fd's are in a sane state */
780 fd = open("/dev/null", O_RDWR);
781 if (fd < 0) {
782 fprintf(stderr, "cannot open /dev/null\n");
7d563a17 783 err(udev, "cannot open /dev/null\n");
5edec024 784 }
5edec024
MS
785 if (write(STDOUT_FILENO, 0, 0) < 0)
786 dup2(fd, STDOUT_FILENO);
787 if (write(STDERR_FILENO, 0, 0) < 0)
788 dup2(fd, STDERR_FILENO);
789
d59f11e1
KS
790 /* init control socket, bind() ensures, that only one udevd instance is running */
791 udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
792 if (udev_ctrl == NULL) {
793 fprintf(stderr, "error initializing control socket");
794 err(udev, "error initializing udevd socket");
795 rc = 1;
796 goto exit;
797 }
798
799 if (udev_ctrl_enable_receiving(udev_ctrl) < 0) {
800 fprintf(stderr, "error binding control socket, seems udevd is already running\n");
801 err(udev, "error binding control socket, seems udevd is already running\n");
802 rc = 1;
833b3c68
KS
803 goto exit;
804 }
805
aa8734ff
KS
806 kernel_monitor = udev_monitor_new_from_netlink(udev);
807 if (kernel_monitor == NULL || udev_monitor_enable_receiving(kernel_monitor) < 0) {
e3396a2d 808 fprintf(stderr, "error initializing netlink socket\n");
7d563a17 809 err(udev, "error initializing netlink socket\n");
833b3c68
KS
810 rc = 3;
811 goto exit;
812 }
cb25a958 813 udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024);
833b3c68 814
5f03ed8a 815 rules = udev_rules_new(udev, resolve_names);
d7ddce18
KS
816 if (rules == NULL) {
817 err(udev, "error reading rules\n");
818 goto exit;
819 }
0bc74ea7 820 udev_list_init(&event_list);
78230c0d 821 cleanup_queue_dir(udev);
7d563a17 822 export_initial_seqnum(udev);
90cd961e 823
561d4c5a 824 if (daemonize) {
f15515b5
KS
825 pid_t pid;
826
827 pid = fork();
828 switch (pid) {
829 case 0:
7d563a17 830 dbg(udev, "daemonized fork running\n");
f15515b5
KS
831 break;
832 case -1:
659353f5 833 err(udev, "fork of daemon failed: %m\n");
833b3c68 834 rc = 4;
f15515b5
KS
835 goto exit;
836 default:
7d563a17 837 dbg(udev, "child [%u] running, parent exits\n", pid);
2f64aa40 838 rc = 0;
833b3c68 839 goto exit;
f15515b5
KS
840 }
841 }
842
d59f11e1 843 /* redirect std{out,err} */
0bc74ea7
KS
844 if (!debug && !debug_trace) {
845 dup2(fd, STDIN_FILENO);
5edec024 846 dup2(fd, STDOUT_FILENO);
d59f11e1
KS
847 dup2(fd, STDERR_FILENO);
848 }
5edec024
MS
849 if (fd > STDERR_FILENO)
850 close(fd);
e3396a2d 851
3904a758 852 /* set scheduling priority for the daemon */
085cce37
KS
853 setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
854
3904a758 855 chdir("/");
74adec7d 856 umask(022);
3bc7c84c 857 setsid();
3904a758
KS
858
859 /* OOM_DISABLE == -17 */
860 fd = open("/proc/self/oom_adj", O_RDWR);
861 if (fd < 0)
659353f5 862 err(udev, "error disabling OOM: %m\n");
3904a758
KS
863 else {
864 write(fd, "-17", 3);
865 close(fd);
866 }
867
798d7ab6
KS
868 fd = open("/dev/kmsg", O_WRONLY);
869 if (fd > 0) {
f13e4c36
KS
870 const char *ver_str = "<6>udev: starting version " VERSION "\n";
871 char path[UTIL_PATH_SIZE];
872 struct stat statbuf;
873
874 write(fd, ver_str, strlen(ver_str));
875 util_strlcpy(path, udev_get_sys_path(udev), sizeof(path));
876 util_strlcat(path, "/class/mem/null", sizeof(path));
877 if (lstat(path, &statbuf) == 0) {
878 if (S_ISDIR(statbuf.st_mode)) {
64be1437
KS
879 const char *depr_str =
880 "<6>udev: deprecated sysfs layout; update the kernel or "
881 "disable CONFIG_SYSFS_DEPRECATED; some udev features will "
882 "not work correctly\n";
f13e4c36
KS
883
884 write(fd, depr_str, strlen(depr_str));
885 }
886 }
798d7ab6
KS
887 close(fd);
888 }
889
f27125f9 890 /* set signal handlers */
0786e8e5 891 memset(&act, 0x00, sizeof(struct sigaction));
6b493a20 892 act.sa_handler = (void (*)(int)) sig_handler;
f27125f9 893 sigemptyset(&act.sa_mask);
5db88229 894 act.sa_flags = SA_RESTART;
f8911dbb
KS
895 sigaction(SIGINT, &act, NULL);
896 sigaction(SIGTERM, &act, NULL);
f8911dbb 897 sigaction(SIGCHLD, &act, NULL);
63cc8f04 898 sigaction(SIGHUP, &act, NULL);
7fafc032 899
c895fd00 900 /* watch rules directory */
bd284db1 901 udev_watch_init(udev);
254d6d3c 902 if (inotify_fd >= 0) {
7d563a17
KS
903 if (udev_get_rules_path(udev) != NULL) {
904 inotify_add_watch(inotify_fd, udev_get_rules_path(udev),
282988c4
KS
905 IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
906 } else {
0bc74ea7 907 char filename[UTIL_PATH_SIZE];
282988c4 908
01618658 909 inotify_add_watch(inotify_fd, UDEV_PREFIX "/lib/udev/rules.d",
282988c4 910 IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
01618658 911 inotify_add_watch(inotify_fd, SYSCONFDIR "/udev/rules.d",
282988c4
KS
912 IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
913
914 /* watch dynamic rules directory */
31c1f537
KS
915 util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename));
916 util_strlcat(filename, "/.udev/rules.d", sizeof(filename));
282988c4
KS
917 inotify_add_watch(inotify_fd, filename,
918 IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
919 }
bd284db1
SJR
920
921 udev_watch_restore(udev);
922 }
0028653c 923
0bc74ea7
KS
924 /* in trace mode run one event after the other */
925 if (debug_trace) {
926 max_childs = 1;
927 } else {
f051e340
KS
928 int memsize = mem_size_mb();
929 if (memsize > 0)
930 max_childs = 128 + (memsize / 4);
931 else
932 max_childs = UDEVD_MAX_CHILDS;
933 }
0bc74ea7
KS
934 /* possibly overwrite maximum limit of executed events */
935 value = getenv("UDEVD_MAX_CHILDS");
936 if (value)
937 max_childs = strtoul(value, NULL, 10);
7d563a17 938 info(udev, "initialize max_childs to %u\n", max_childs);
a15f42c4 939
63cc8f04 940 while (!udev_exit) {
3210a72b 941 sigset_t blocked_mask, orig_mask;
e9a77fd8 942 struct pollfd pfd[4];
3210a72b 943 struct pollfd *ctrl_poll, *monitor_poll, *inotify_poll = NULL;
e9a77fd8
KS
944 int nfds = 0;
945 int fdcount;
3210a72b
OK
946
947 sigfillset(&blocked_mask);
948 sigprocmask(SIG_SETMASK, &blocked_mask, &orig_mask);
949 if (signal_received) {
950 sigprocmask(SIG_SETMASK, &orig_mask, NULL);
951 goto handle_signals;
952 }
021a294c 953
e9a77fd8
KS
954 ctrl_poll = &pfd[nfds++];
955 ctrl_poll->fd = udev_ctrl_get_fd(udev_ctrl);
956 ctrl_poll->events = POLLIN;
957
958 monitor_poll = &pfd[nfds++];
959 monitor_poll->fd = udev_monitor_get_fd(kernel_monitor);
960 monitor_poll->events = POLLIN;
961
962 if (inotify_fd >= 0) {
963 inotify_poll = &pfd[nfds++];
964 inotify_poll->fd = inotify_fd;
965 inotify_poll->events = POLLIN;
966 }
3210a72b
OK
967
968 fdcount = ppoll(pfd, nfds, NULL, &orig_mask);
969 sigprocmask(SIG_SETMASK, &orig_mask, NULL);
40caaeec 970 if (fdcount < 0) {
3210a72b
OK
971 if (errno == EINTR)
972 goto handle_signals;
973 err(udev, "error in select: %m\n");
f27125f9 974 continue;
2f6cbd19 975 }
e5a2989e 976
b3518c16 977 /* get control message */
3210a72b 978 if (ctrl_poll->revents & POLLIN)
d59f11e1 979 handle_ctrl_msg(udev_ctrl);
88f4b648 980
aa8734ff 981 /* get kernel uevent */
3210a72b 982 if (monitor_poll->revents & POLLIN) {
aa8734ff
KS
983 struct udev_device *dev;
984
985 dev = udev_monitor_receive_device(kernel_monitor);
986 if (dev != NULL) {
987 struct udev_event *event;
988
989 event = udev_event_new(dev);
990 if (event != NULL)
991 event_queue_insert(event);
992 else
993 udev_device_unref(dev);
994 }
021a294c 995 }
e5a2989e 996
c895fd00 997 /* rules directory inotify watch */
bd284db1 998 if (inotify_poll && (inotify_poll->revents & POLLIN))
4aca304e 999 handle_inotify(udev);
c895fd00 1000
3210a72b
OK
1001handle_signals:
1002 signal_received = 0;
1003
e3396a2d 1004 /* rules changed, set by inotify or a HUP signal */
c895fd00 1005 if (reload_config) {
d7ddce18
KS
1006 struct udev_rules *rules_new;
1007
c895fd00 1008 reload_config = 0;
5f03ed8a 1009 rules_new = udev_rules_new(udev, resolve_names);
d7ddce18
KS
1010 if (rules_new != NULL) {
1011 udev_rules_unref(rules);
1012 rules = rules_new;
1013 }
c895fd00
KS
1014 }
1015
5cab7caa
KS
1016 if (sigchilds_waiting) {
1017 sigchilds_waiting = 0;
1018 reap_sigchilds();
f27125f9 1019 }
e5a2989e 1020
f27125f9 1021 if (run_exec_q) {
f27125f9 1022 run_exec_q = 0;
3b47c739 1023 if (!stop_exec_q)
aa8734ff 1024 event_queue_manager(udev);
53921bfa 1025 }
53921bfa 1026 }
c969f880 1027 cleanup_queue_dir(udev);
e3396a2d 1028 rc = 0;
53921bfa 1029exit:
d7ddce18 1030 udev_rules_unref(rules);
d59f11e1 1031 udev_ctrl_unref(udev_ctrl);
90cd961e 1032 if (inotify_fd >= 0)
c895fd00 1033 close(inotify_fd);
aa8734ff 1034 udev_monitor_unref(kernel_monitor);
c3b1fa66 1035 udev_selinux_exit(udev);
e598c573 1036 udev_unref(udev);
7257cb18 1037 logging_close();
833b3c68 1038 return rc;
7fafc032 1039}