#include <sys/time.h>
#include <sys/prctl.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <sys/signalfd.h>
#include <sys/select.h>
#include <sys/poll.h>
udev_monitor_enable_receiving(worker_monitor);
worker = calloc(1, sizeof(struct worker));
- if (worker == NULL)
+ if (worker == NULL) {
+ udev_monitor_unref(worker_monitor);
return;
+ }
/* worker + event reference */
worker->refcount = 2;
worker->udev = event->udev;
worker_new(event);
}
-static void event_queue_insert(struct udev_device *dev)
+static int event_queue_insert(struct udev_device *dev)
{
struct event *event;
event = calloc(1, sizeof(struct event));
if (event == NULL)
- return;
+ return -1;
event->udev = udev_device_get_udev(dev);
event->dev = dev;
/* run all events with a timeout set immediately */
if (udev_device_get_timeout(dev) > 0) {
event_run(event, true);
- return;
+ return 0;
}
+
+ return 0;
}
static void worker_kill(struct udev *udev, int retain)
unsigned int i;
for (i = 0; i < ARRAY_SIZE(stdlinks); i++) {
- udev_selinux_setfscreateconat(udev, dirfd(dir), stdlinks[i].link, S_IFLNK);
- if (symlinkat(stdlinks[i].target, dirfd(dir), stdlinks[i].link) < 0 && errno == EEXIST)
- utimensat(dirfd(dir), stdlinks[i].link, NULL, AT_SYMLINK_NOFOLLOW);
- udev_selinux_resetfscreatecon(udev);
+ struct stat sb;
+
+ if (stat(stdlinks[i].target, &sb) == 0) {
+ udev_selinux_setfscreateconat(udev, dirfd(dir), stdlinks[i].link, S_IFLNK);
+ if (symlinkat(stdlinks[i].target, dirfd(dir), stdlinks[i].link) < 0 && errno == EEXIST)
+ utimensat(dirfd(dir), stdlinks[i].link, NULL, AT_SYMLINK_NOFOLLOW);
+ udev_selinux_resetfscreatecon(udev);
+ }
}
}
return memsize;
}
+static int init_notify(const char *state)
+{
+ int fd = -1, r;
+ struct msghdr msghdr;
+ struct iovec iovec;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_un un;
+ } sockaddr;
+ const char *e;
+
+ if (!(e = getenv("NOTIFY_SOCKET"))) {
+ r = 0;
+ goto finish;
+ }
+
+ /* Must be an abstract socket, or an absolute path */
+ if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
+ r = -EINVAL;
+ goto finish;
+ }
+
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ memset(&sockaddr, 0, sizeof(sockaddr));
+ sockaddr.sa.sa_family = AF_UNIX;
+ strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
+
+ if (sockaddr.un.sun_path[0] == '@')
+ sockaddr.un.sun_path[0] = 0;
+
+ memset(&iovec, 0, sizeof(iovec));
+ iovec.iov_base = (char*) state;
+ iovec.iov_len = strlen(state);
+
+ memset(&msghdr, 0, sizeof(msghdr));
+ msghdr.msg_name = &sockaddr;
+ msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e);
+ if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
+ msghdr.msg_namelen = sizeof(struct sockaddr_un);
+ msghdr.msg_iov = &iovec;
+ msghdr.msg_iovlen = 1;
+
+ if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ r = 0;
+
+finish:
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
+
int main(int argc, char *argv[])
{
struct udev *udev;
for (;;) {
int option;
- option = getopt_long(argc, argv, "cdeDthV", options, NULL);
+ option = getopt_long(argc, argv, "c:deDthV", options, NULL);
if (option == -1)
break;
}
}
- if (getuid() != 0) {
- fprintf(stderr, "root privileges required\n");
- err(udev, "root privileges required\n");
- goto exit;
- }
-
/*
* read the kernel commandline, in case we need to get into debug mode
* udev.log-priority=<level> syslog priority
fclose(f);
}
- /* make sure std{in,out,err} fds are in a sane state */
+ if (getuid() != 0) {
+ fprintf(stderr, "root privileges required\n");
+ err(udev, "root privileges required\n");
+ goto exit;
+ }
+
+ /* set umask before creating any file/directory */
+ chdir("/");
+ umask(022);
+
+ /* before opening new files, make sure std{in,out,err} fds are in a sane state */
fd = open("/dev/null", O_RDWR);
if (fd < 0) {
fprintf(stderr, "cannot open /dev/null\n");
goto exit;
}
+ if (!debug) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ }
+ if (fd > STDERR_FILENO)
+ close(fd);
+
if (daemonize) {
pid_t pid;
rc = 0;
goto exit;
}
+ } else {
+ init_notify("READY=1");
}
- f = fopen("/dev/kmsg", "w");
- if (f != NULL) {
- fprintf(f, "<6>udev: starting version " VERSION "\n");
- fclose(f);
- }
-
- if (!debug) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- }
- if (fd > STDERR_FILENO)
- close(fd);
-
/* set scheduling priority for the main daemon process */
setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
- chdir("/");
- umask(022);
setsid();
- /* OOM_DISABLE == -17 */
- fd = open("/proc/self/oom_adj", O_RDWR);
+ f = fopen("/dev/kmsg", "w");
+ if (f != NULL) {
+ fprintf(f, "<6>udev[%u]: starting version " VERSION "\n", getpid());
+ fclose(f);
+ }
+
+ fd = open("/proc/self/oom_score_adj", O_RDWR);
if (fd < 0) {
- err(udev, "error disabling OOM: %m\n");
+ /* Fallback to old interface */
+ fd = open("/proc/self/oom_adj", O_RDWR);
+ if (fd < 0) {
+ err(udev, "error disabling OOM: %m\n");
+ } else {
+ /* OOM_DISABLE == -17 */
+ write(fd, "-17", 3);
+ close(fd);
+ }
} else {
- write(fd, "-17", 3);
+ write(fd, "-1000", 5);
close(fd);
}
dev = udev_monitor_receive_device(monitor);
if (dev != NULL)
- event_queue_insert(dev);
- else
- udev_device_unref(dev);
+ if (event_queue_insert(dev) < 0)
+ udev_device_unref(dev);
}
/* start new events */