+ } else {
+ sd_notify(1, "READY=1");
+ }
+
+ fd_inotify = udev_watch_init(udev);
+ if (fd_inotify < 0) {
+ fprintf(stderr, "error initializing inotify\n");
+ err(udev, "error initializing inotify\n");
+ rc = 4;
+ goto exit;
+ }
+
+ if (udev_get_rules_path(udev) != NULL) {
+ inotify_add_watch(fd_inotify, udev_get_rules_path(udev),
+ IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
+ } else {
+ char filename[UTIL_PATH_SIZE];
+ struct stat statbuf;
+
+ inotify_add_watch(fd_inotify, LIBEXECDIR "/rules.d",
+ IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
+ inotify_add_watch(fd_inotify, SYSCONFDIR "/udev/rules.d",
+ IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
+
+ /* watch dynamic rules directory */
+ util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/rules.d", NULL);
+ if (stat(filename, &statbuf) != 0) {
+ util_create_path(udev, filename);
+ mkdir(filename, 0755);
+ }
+ inotify_add_watch(fd_inotify, filename,
+ IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
+ }
+ udev_watch_restore(udev);
+
+ /* block and listen to all signals on signalfd */
+ sigfillset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, &orig_sigmask);
+ fd_signal = signalfd(-1, &mask, SFD_CLOEXEC);
+ if (fd_signal < 0) {
+ fprintf(stderr, "error getting signalfd\n");
+ err(udev, "error getting signalfd\n");
+ rc = 5;
+ goto exit;
+ }
+
+ /* unnamed socket from workers to the main daemon */
+ if (socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, worker_watch) < 0) {
+ fprintf(stderr, "error getting socketpair\n");
+ err(udev, "error getting socketpair\n");
+ rc = 6;
+ goto exit;
+ }
+ fd_worker = worker_watch[READ_END];
+
+ rules = udev_rules_new(udev, resolve_names);
+ if (rules == NULL) {
+ err(udev, "error reading rules\n");
+ goto exit;
+ }
+
+ udev_queue_export = udev_queue_export_new(udev);
+ if (udev_queue_export == NULL) {
+ err(udev, "error creating queue file\n");
+ goto exit;
+ }
+
+ memset(&ep_ctrl, 0, sizeof(struct epoll_event));
+ ep_ctrl.events = EPOLLIN;
+ ep_ctrl.data.fd = fd_ctrl;
+ memset(&ep_inotify, 0, sizeof(struct epoll_event));
+ ep_inotify.events = EPOLLIN;
+ ep_inotify.data.fd = fd_inotify;
+ memset(&ep_signal, 0, sizeof(struct epoll_event));
+ ep_signal.events = EPOLLIN;
+ ep_signal.data.fd = fd_signal;
+ memset(&ep_netlink, 0, sizeof(struct epoll_event));
+ ep_netlink.events = EPOLLIN;
+ ep_netlink.data.fd = fd_netlink;
+ memset(&ep_worker, 0, sizeof(struct epoll_event));
+ ep_worker.events = EPOLLIN;
+ ep_worker.data.fd = fd_worker;
+ fd_ep = epoll_create1(EPOLL_CLOEXEC);
+ if (fd_ep < 0) {
+ err(udev, "error creating epoll fd: %m\n");
+ goto exit;
+ }
+ if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_ctrl, &ep_ctrl) < 0 ||
+ epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_inotify, &ep_inotify) < 0 ||
+ epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_signal, &ep_signal) < 0 ||
+ epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_netlink, &ep_netlink) < 0 ||
+ epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_worker, &ep_worker) < 0) {
+ err(udev, "fail to add fds to epoll: %m\n");
+ goto exit;