summaryrefslogtreecommitdiff
path: root/udev/udevd.c
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2010-05-20 17:09:04 +0200
committerKay Sievers <kay.sievers@vrfy.org>2010-05-20 17:09:04 +0200
commit761dfddcc027d0a4be881d779cc2f62edafbb2eb (patch)
tree25f934580900278ca36491c5f7ac9deeb017f1d5 /udev/udevd.c
parentf2291cd07f24d2e1b7c3295ea6570f64b935ba55 (diff)
create static nodes provided by kernel modules to allow module autoloading
Diffstat (limited to 'udev/udevd.c')
-rw-r--r--udev/udevd.c115
1 files changed, 97 insertions, 18 deletions
diff --git a/udev/udevd.c b/udev/udevd.c
index 1bde8f4a74..ab24885309 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -41,6 +41,7 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/inotify.h>
+#include <sys/utsname.h>
#include "udev.h"
@@ -745,6 +746,72 @@ static void handle_signal(struct udev *udev, int signo)
}
}
+static void static_dev_create_from_modules(struct udev *udev)
+{
+ struct utsname kernel;
+ char modules[UTIL_PATH_SIZE];
+ char buf[4096];
+ FILE *f;
+
+ uname(&kernel);
+ util_strscpyl(modules, sizeof(modules), "/lib/modules/", kernel.release, "/modules.devname", NULL);
+ f = fopen(modules, "r");
+ if (f == NULL)
+ return;
+
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ char *s;
+ const char *modname;
+ const char *devname;
+ const char *devno;
+ int maj, min;
+ char type;
+ mode_t mode;
+ char filename[UTIL_PATH_SIZE];
+
+ if (buf[0] == '#')
+ continue;
+
+ modname = buf;
+ s = strchr(modname, ' ');
+ if (s == NULL)
+ continue;
+ s[0] = '\0';
+
+ devname = &s[1];
+ s = strchr(devname, ' ');
+ if (s == NULL)
+ continue;
+ s[0] = '\0';
+
+ devno = &s[1];
+ s = strchr(devno, ' ');
+ if (s == NULL)
+ s = strchr(devno, '\n');
+ if (s != NULL)
+ s[0] = '\0';
+ if (sscanf(devno, "%c%u:%u", &type, &maj, &min) != 3)
+ continue;
+
+ if (type == 'c')
+ mode = 0600 | S_IFCHR;
+ else if (type == 'b')
+ mode = 0600 | S_IFBLK;
+ else
+ continue;
+
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/", devname, NULL);
+ util_create_path(udev, filename);
+ udev_selinux_setfscreatecon(udev, filename, mode);
+ info(udev, "mknod '%s' %c%u:%u\n", filename, type, maj, min);
+ if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST)
+ utimensat(AT_FDCWD, filename, NULL, 0);
+ udev_selinux_resetfscreatecon(udev);
+ }
+
+ fclose(f);
+}
+
static int copy_dir(struct udev *udev, DIR *dir_from, DIR *dir_to, int maxdepth)
{
struct dirent *dent;
@@ -808,7 +875,7 @@ static int copy_dir(struct udev *udev, DIR *dir_from, DIR *dir_to, int maxdepth)
return 0;
}
-static void prepare_dev(struct udev *udev)
+static void static_dev_create_links(struct udev *udev, DIR *dir)
{
struct stdlinks {
const char *link;
@@ -822,28 +889,38 @@ static void prepare_dev(struct udev *udev)
{ "stderr", "/proc/self/fd/2" },
};
unsigned int i;
- DIR *dir_from, *dir_to;
- dir_to = opendir(udev_get_dev_path(udev));
- if (dir_to == NULL)
- return;
-
- /* create standard symlinks to /proc */
for (i = 0; i < ARRAY_SIZE(stdlinks); i++) {
- udev_selinux_setfscreateconat(udev, dirfd(dir_to), stdlinks[i].link, S_IFLNK);
- if (symlinkat(stdlinks[i].target, dirfd(dir_to), stdlinks[i].link) < 0 && errno == EEXIST)
- utimensat(dirfd(dir_to), stdlinks[i].link, NULL, AT_SYMLINK_NOFOLLOW);
+ 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);
}
+}
+
+static void static_dev_create_from_devices(struct udev *udev, DIR *dir)
+{
+ DIR *dir_from;
- /* copy content from /lib/udev/devices to /dev */
dir_from = opendir(LIBEXECDIR "/devices");
- if (dir_from != NULL) {
- copy_dir(udev, dir_from, dir_to, 8);
- closedir(dir_from);
- }
+ if (dir_from == NULL)
+ return;
+ copy_dir(udev, dir_from, dir, 8);
+ closedir(dir_from);
+}
+
+static void static_dev_create(struct udev *udev)
+{
+ DIR *dir;
- closedir(dir_to);
+ dir = opendir(udev_get_dev_path(udev));
+ if (dir == NULL)
+ return;
+
+ static_dev_create_links(udev, dir);
+ static_dev_create_from_devices(udev, dir);
+
+ closedir(dir);
}
static int mem_size_mb(void)
@@ -959,8 +1036,6 @@ int main(int argc, char *argv[])
if (write(STDERR_FILENO, 0, 0) < 0)
dup2(fd, STDERR_FILENO);
- prepare_dev(udev);
-
/* init control socket, bind() ensures, that only one udevd instance is running */
udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
if (udev_ctrl == NULL) {
@@ -1118,6 +1193,10 @@ int main(int argc, char *argv[])
max_childs = strtoul(value, NULL, 10);
info(udev, "initialize max_childs to %u\n", max_childs);
+ static_dev_create(udev);
+ static_dev_create_from_modules(udev);
+ udev_rules_apply_static_dev_perms(rules);
+
udev_list_init(&event_list);
udev_list_init(&worker_list);