From 4ec9c3e79771aa95586390cecff4218cc8938160 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 23 Mar 2011 02:31:09 +0100 Subject: [PATCH 1/1] use /run/udev/ if possible and fall back to /dev/.udev/ --- NEWS | 25 ++-- extras/collect/collect.c | 19 ++- extras/firmware/firmware.c | 2 +- .../rule_generator/rule_generator.functions | 8 +- libudev/libudev-device-private.c | 6 +- libudev/libudev-device.c | 2 +- libudev/libudev-enumerate.c | 2 +- libudev/libudev-private.h | 3 + libudev/libudev-queue-private.c | 10 +- libudev/libudev-queue.c | 4 +- libudev/libudev.c | 120 +++++++++++++----- test/udev-test.pl | 1 + udev/udev-node.c | 2 +- udev/udev-rules.c | 2 +- udev/udev-watch.c | 10 +- udev/udev.xml | 2 +- udev/udevadm-info.c | 6 +- udev/udevadm.c | 2 + udev/udevadm.xml | 6 + udev/udevd.c | 32 ++++- 20 files changed, 186 insertions(+), 78 deletions(-) diff --git a/NEWS b/NEWS index 8da1cd9ed..63826003e 100644 --- a/NEWS +++ b/NEWS @@ -2,20 +2,27 @@ udev 167 ======== Bugfixes. -The udev runtime data moved from /dev/.udev/ to /dev/.run/udev/. -On systemd systems the tmpfs mountpoint /var/run/ will have a -permanent "early-boot alias" /dev/.run/, where udev and a couple -of other early-boot tools will put their runtime data. +The udev runtime data moved from /dev/.udev/ to /run/udev/. The +/run mountpoint is supposed to be a tmpfs mounted during early boot, +available and writable to for all tools at any time during bootup, +it replaces /var/run/, which should become a symlink some day. -On systemd systems with LVM used, packagers must make sure, that -the systemd and initramfs version match. The initramfs needs to -create the /dev/.run/ mountpoint for udev to store the data, so -that systemd will not overmount it, which would make the udev -data from initramfs invisible. +If /run does not exist, or is not writable, udev will fall back using +/dev/.udev/. + +On systemd systems with initramfs and LVM used, packagers must +make sure, that the systemd and initramfs versions match. The initramfs +needs to create the /run/ mountpoint for udev to store the data, and +mount this tmpfs to /run in the rootfs, so the that the udev database +is preserved for the udev version started in the rootfs. The command 'udevadm info --convert-db' is gone. The udev daemon itself, at startup, converts any old database version if necessary. +The fstab_import callout is no longer built or installed. Udev +should not be used to mount, does not watch changes to fstab, and +should not mirror fstab values in the udev database. + udev 166 ======== Bugfixes. diff --git a/extras/collect/collect.c b/extras/collect/collect.c index b5670516b..17b3df372 100644 --- a/extras/collect/collect.c +++ b/extras/collect/collect.c @@ -34,7 +34,6 @@ #include "libudev.h" #include "libudev-private.h" -#define TMPFILE "/dev/.run/udev/collect" #define BUFSIZE 16 #define UDEV_ALARM_TIMEOUT 180 @@ -338,6 +337,7 @@ static void everybody(void) int main(int argc, char **argv) { + struct udev *udev; static const struct option options[] = { { "add", no_argument, NULL, 'a' }, { "remove", no_argument, NULL, 'r' }, @@ -349,8 +349,15 @@ int main(int argc, char **argv) char *checkpoint, *us; int fd; int i; - int ret = 0; + int ret = EXIT_SUCCESS; int prune = 0; + char tmpdir[UTIL_PATH_SIZE]; + + udev = udev_new(); + if (udev == NULL) { + ret = EXIT_FAILURE; + goto exit; + } while (1) { int option; @@ -398,7 +405,8 @@ int main(int argc, char **argv) if (debug) fprintf(stderr, "Using checkpoint '%s'\n", checkpoint); - fd = prepare(TMPFILE, checkpoint); + util_strscpyl(tmpdir, sizeof(tmpdir), udev_get_run_path(udev), "/collect", NULL); + fd = prepare(tmpdir, checkpoint); if (fd < 0) { ret = 3; goto out; @@ -454,11 +462,12 @@ int main(int argc, char **argv) lockf(fd, F_ULOCK, 0); close(fd); - out: +out: if (debug) everybody(); if (ret >= 0) printf("COLLECT_%s=%d\n", checkpoint, ret); - exit: +exit: + udev_unref(udev); return ret; } diff --git a/extras/firmware/firmware.c b/extras/firmware/firmware.c index f7d21df6d..81998201b 100644 --- a/extras/firmware/firmware.c +++ b/extras/firmware/firmware.c @@ -147,7 +147,7 @@ int main(int argc, char **argv) } util_path_encode(firmware, fwencpath, sizeof(fwencpath)); - util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.run/udev/firmware-missing/", fwencpath, NULL); + util_strscpyl(misspath, sizeof(misspath), udev_get_run_path(udev), "/firmware-missing/", fwencpath, NULL); util_strscpyl(loadpath, sizeof(loadpath), udev_get_sys_path(udev), devpath, "/loading", NULL); if (fwfile == NULL) { diff --git a/extras/rule_generator/rule_generator.functions b/extras/rule_generator/rule_generator.functions index e2060a2ec..4bec27a1b 100644 --- a/extras/rule_generator/rule_generator.functions +++ b/extras/rule_generator/rule_generator.functions @@ -48,9 +48,10 @@ writeable() { # Create a lock file for the current rules file. lock_rules_file() { - [ -e /dev/.udev/ ] || return 0 + RUNDIR=$(udevadm info --run) + [ -e "$RUNDIR" ] || return 0 - RULES_LOCK="/dev/.udev/.lock-${RULES_FILE##*/}" + RULES_LOCK="$RUNDIR/.lock-${RULES_FILE##*/}" retry=30 while ! mkdir $RULES_LOCK 2> /dev/null; do @@ -71,7 +72,8 @@ unlock_rules_file() { # Choose the real rules file if it is writeable or a temporary file if not. # Both files should be checked later when looking for existing rules. choose_rules_file() { - local tmp_rules_file="/dev/.udev/tmp-rules--${RULES_FILE##*/}" + RUNDIR=$(udevadm info --run) + local tmp_rules_file="$RUNDIR/tmp-rules--${RULES_FILE##*/}" [ -e "$RULES_FILE" -o -e "$tmp_rules_file" ] || PRINT_HEADER=1 if writeable ${RULES_FILE%/*}; then diff --git a/libudev/libudev-device-private.c b/libudev/libudev-device-private.c index 7683f0985..6d72d328b 100644 --- a/libudev/libudev-device-private.c +++ b/libudev/libudev-device-private.c @@ -31,7 +31,7 @@ static void udev_device_tag(struct udev_device *dev, const char *tag, bool add) id = udev_device_get_id_filename(dev); if (id == NULL) return; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/tags/", tag, "/", id, NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/tags/", tag, "/", id, NULL); if (add) { int fd; @@ -115,7 +115,7 @@ int udev_device_update_db(struct udev_device *udev_device) return -1; has_info = device_has_info(udev_device); - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data/", id, NULL); /* do not store anything for otherwise empty devices */ if (!has_info && @@ -176,7 +176,7 @@ int udev_device_delete_db(struct udev_device *udev_device) id = udev_device_get_id_filename(udev_device); if (id == NULL) return -1; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data/", id, NULL); unlink(filename); return 0; } diff --git a/libudev/libudev-device.c b/libudev/libudev-device.c index dd0224ae4..ccd4a7067 100644 --- a/libudev/libudev-device.c +++ b/libudev/libudev-device.c @@ -254,7 +254,7 @@ int udev_device_read_db(struct udev_device *udev_device, const char *dbfile) id = udev_device_get_id_filename(udev_device); if (id == NULL) return -1; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.run/udev/db3/", id, NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_device->udev), "/data/", id, NULL); dbfile = filename; } diff --git a/libudev/libudev-enumerate.c b/libudev/libudev-enumerate.c index d3dd5c963..6870bb611 100644 --- a/libudev/libudev-enumerate.c +++ b/libudev/libudev-enumerate.c @@ -751,7 +751,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) struct dirent *dent; char path[UTIL_PATH_SIZE]; - util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.run/udev/tags/", + util_strscpyl(path, sizeof(path), udev_get_run_path(udev), "/tags/", udev_list_entry_get_name(list_entry), NULL); dir = opendir(path); if (dir == NULL) diff --git a/libudev/libudev-private.h b/libudev/libudev-private.h index 0fe6f4a6b..bd317933b 100644 --- a/libudev/libudev-private.h +++ b/libudev/libudev-private.h @@ -61,6 +61,9 @@ void udev_log(struct udev *udev, const char *format, ...) __attribute__((format(printf, 6, 7))); const char *udev_get_rules_path(struct udev *udev); +const char *udev_get_run_config_path(struct udev *udev); +const char *udev_get_run_path(struct udev *udev); +const char *udev_set_run_path(struct udev *udev, const char *path); struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value); struct udev_list_entry *udev_get_properties_list_entry(struct udev *udev); diff --git a/libudev/libudev-queue-private.c b/libudev/libudev-queue-private.c index 9b02daf0a..a71457236 100644 --- a/libudev/libudev-queue-private.c +++ b/libudev/libudev-queue-private.c @@ -103,10 +103,10 @@ void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export) { char filename[UTIL_PATH_SIZE]; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); unlink(filename); - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); unlink(filename); } @@ -221,7 +221,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) } /* create new queue file */ - util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL); + util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_run_path(udev_queue_export->udev), "/queue.tmp", NULL); new_queue_file = fopen(filename_tmp, "w+"); if (new_queue_file == NULL) goto error; @@ -255,7 +255,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) goto error; /* rename the new file on top of the old one */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue_export->udev), "/queue.bin", NULL); if (rename(filename_tmp, filename) != 0) goto error; @@ -401,7 +401,7 @@ static void update_failed(struct udev_queue_export *udev_queue_export, return; /* location of failed file */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/failed/", + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/failed/", udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL); switch (state) { diff --git a/libudev/libudev-queue.c b/libudev/libudev-queue.c index 6f743d206..75c5b2425 100644 --- a/libudev/libudev-queue.c +++ b/libudev/libudev-queue.c @@ -214,7 +214,7 @@ static FILE *open_queue_file(struct udev_queue *udev_queue, unsigned long long i char filename[UTIL_PATH_SIZE]; FILE *queue_file; - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.run/udev/queue.bin", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev_queue->udev), "/queue.bin", NULL); queue_file = fopen(filename, "re"); if (queue_file == NULL) return NULL; @@ -484,7 +484,7 @@ struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev if (udev_queue == NULL) return NULL; udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list); - util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.run/udev/failed", NULL); + util_strscpyl(path, sizeof(path), udev_get_run_path(udev_queue->udev), "/failed", NULL); dir = opendir(path); if (dir == NULL) return NULL; diff --git a/libudev/libudev.c b/libudev/libudev.c index cd418709f..d96934fba 100644 --- a/libudev/libudev.c +++ b/libudev/libudev.c @@ -43,6 +43,8 @@ struct udev { char *sys_path; char *dev_path; char *rules_path; + char *run_config_path; + char *run_path; struct udev_list_node properties_list; int log_priority; }; @@ -96,6 +98,14 @@ void udev_set_userdata(struct udev *udev, void *userdata) udev->userdata = userdata; } +static char *set_value(char **s, const char *v) +{ + free(*s); + *s = strdup(v); + util_remove_trailing_chars(*s, '/'); + return *s; +} + /** * udev_new: * @@ -111,7 +121,7 @@ struct udev *udev_new(void) { struct udev *udev; const char *env; - char *config_file; + char *config_file = NULL; FILE *f; udev = calloc(1, sizeof(struct udev)); @@ -121,31 +131,21 @@ struct udev *udev_new(void) udev->log_fn = log_stderr; udev->log_priority = LOG_ERR; udev_list_init(&udev->properties_list); - udev->dev_path = strdup("/dev"); - udev->sys_path = strdup("/sys"); - config_file = strdup(SYSCONFDIR "/udev/udev.conf"); - if (udev->dev_path == NULL || - udev->sys_path == NULL || - config_file == NULL) - goto err; - - /* settings by environment and config file */ - env = getenv("SYSFS_PATH"); - if (env != NULL) { - free(udev->sys_path); - udev->sys_path = strdup(env); - util_remove_trailing_chars(udev->sys_path, '/'); - udev_add_property(udev, "SYSFS_PATH", udev->sys_path); - } + /* custom config file */ env = getenv("UDEV_CONFIG_FILE"); if (env != NULL) { - free(config_file); - config_file = strdup(env); - util_remove_trailing_chars(config_file, '/'); + udev_add_property(udev, "UDEV_CONFIG_FILE", udev->dev_path); + if (set_value(&config_file, env) == NULL) + goto err; } + + /* default config file */ + if (config_file == NULL) + config_file = strdup(SYSCONFDIR "/udev/udev.conf"); if (config_file == NULL) goto err; + f = fopen(config_file, "re"); if (f != NULL) { char line[UTIL_LINE_SIZE]; @@ -214,40 +214,57 @@ struct udev *udev_new(void) continue; } if (strcmp(key, "udev_root") == 0) { - free(udev->dev_path); - udev->dev_path = strdup(val); - util_remove_trailing_chars(udev->dev_path, '/'); + set_value(&udev->dev_path, val); + continue; + } + if (strcmp(key, "udev_run") == 0) { + set_value(&udev->run_config_path, val); continue; } if (strcmp(key, "udev_rules") == 0) { - free(udev->rules_path); - udev->rules_path = strdup(val); - util_remove_trailing_chars(udev->rules_path, '/'); + set_value(&udev->rules_path, val); continue; } } fclose(f); } + /* environment overwrites config */ + env = getenv("UDEV_LOG"); + if (env != NULL) + udev_set_log_priority(udev, util_log_priority(env)); + env = getenv("UDEV_ROOT"); if (env != NULL) { - free(udev->dev_path); - udev->dev_path = strdup(env); - util_remove_trailing_chars(udev->dev_path, '/'); + set_value(&udev->dev_path, env); udev_add_property(udev, "UDEV_ROOT", udev->dev_path); } - env = getenv("UDEV_LOG"); - if (env != NULL) - udev_set_log_priority(udev, util_log_priority(env)); + env = getenv("SYSFS_PATH"); + if (env != NULL) { + set_value(&udev->sys_path, env); + udev_add_property(udev, "SYSFS_PATH", udev->sys_path); + } + + /* set defaults */ + if (udev->dev_path == NULL) + if (set_value(&udev->dev_path, "/dev") == NULL) + goto err; + + if (udev->sys_path == NULL) + if (set_value(&udev->sys_path, "/sys") == NULL) + goto err; + + if (udev->run_config_path == NULL) + if (set_value(&udev->run_config_path, "/run/udev") == NULL) + goto err; - if (udev->dev_path == NULL || udev->sys_path == NULL) - goto err; dbg(udev, "context %p created\n", udev); dbg(udev, "log_priority=%d\n", udev->log_priority); dbg(udev, "config_file='%s'\n", config_file); dbg(udev, "dev_path='%s'\n", udev->dev_path); dbg(udev, "sys_path='%s'\n", udev->sys_path); + dbg(udev, "run_path='%s'\n", udev->run_config_path); if (udev->rules_path != NULL) dbg(udev, "rules_path='%s'\n", udev->rules_path); free(config_file); @@ -294,6 +311,8 @@ void udev_unref(struct udev *udev) free(udev->dev_path); free(udev->sys_path); free(udev->rules_path); + free(udev->run_path); + free(udev->run_config_path); dbg(udev, "context %p released\n", udev); free(udev); } @@ -387,6 +406,39 @@ const char *udev_get_dev_path(struct udev *udev) return udev->dev_path; } +const char *udev_get_run_config_path(struct udev *udev) +{ + return udev->run_config_path; +} + +const char *udev_get_run_path(struct udev *udev) +{ + if (udev->run_path != NULL) + return udev->run_path; + + /* check if configured path exists */ + if (access(udev->run_config_path, F_OK) < 0) { + char filename[UTIL_PATH_SIZE]; + + /* fall back to /dev/.udev if that exists */ + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev", NULL); + if (access(filename, F_OK) >= 0) + if (set_value(&udev->run_path, filename) != NULL) + return udev->run_path; + } + + /* use default path */ + set_value(&udev->run_path, udev->run_config_path); + if (udev->run_path == NULL) + return udev->run_config_path; + return udev->run_path; +} + +const char *udev_set_run_path(struct udev *udev, const char *path) +{ + return set_value(&udev->run_path, path); +} + struct udev_list_entry *udev_add_property(struct udev *udev, const char *key, const char *value) { if (value == NULL) { diff --git a/test/udev-test.pl b/test/udev-test.pl index 6a0ea826f..4103cf0bf 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1732,6 +1732,7 @@ make_udev_root(); # create config file open CONF, ">$udev_conf" || die "unable to create config file: $udev_conf"; print CONF "udev_root=\"$udev_root\"\n"; +print CONF "udev_run=\"$udev_root/.udev\"\n"; print CONF "udev_rules=\"$PWD\"\n"; print CONF "udev_log=\"err\"\n"; close CONF; diff --git a/udev/udev-node.c b/udev/udev-node.c index aaa2e32e6..ab4e93228 100644 --- a/udev/udev-node.c +++ b/udev/udev-node.c @@ -292,7 +292,7 @@ static void link_update(struct udev_device *dev, const char *slink, bool add) dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev)); util_path_encode(&slink[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc)); - util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.run/udev/links/", name_enc, NULL); + util_strscpyl(dirname, sizeof(dirname), udev_get_run_path(udev), "/links/", name_enc, NULL); util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL); if (!add) { diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 4a5b8debc..221865c9d 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -1803,7 +1803,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules"); /* read dynamic/temporary rules */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/rules.d", NULL); udev_list_init(&sort_list); add_matching_files(udev, &sort_list, filename, ".rules"); diff --git a/udev/udev-watch.c b/udev/udev-watch.c index 47dca4c6e..0ec8bfd62 100644 --- a/udev/udev-watch.c +++ b/udev/udev-watch.c @@ -54,8 +54,8 @@ void udev_watch_restore(struct udev *udev) if (inotify_fd < 0) return; - util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.run/udev/watch.old", NULL); - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/watch", NULL); + util_strscpyl(oldname, sizeof(oldname), udev_get_run_path(udev), "/watch.old", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/watch", NULL); if (rename(filename, oldname) == 0) { DIR *dir; struct dirent *ent; @@ -118,7 +118,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) return; } - snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd); + snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); util_create_path(udev, filename); unlink(filename); symlink(udev_device_get_id_filename(dev), filename); @@ -141,7 +141,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev) info(udev, "removing watch on '%s'\n", udev_device_get_devnode(dev)); inotify_rm_watch(inotify_fd, wd); - snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd); + snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); unlink(filename); udev_device_set_watch_handle(dev, -1); @@ -158,7 +158,7 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd) if (inotify_fd < 0 || wd < 0) return NULL; - snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd); + snprintf(filename, sizeof(filename), "%s/watch/%d", udev_get_run_path(udev), wd); s = majmin; l = util_strpcpy(&s, sizeof(majmin), udev_get_sys_path(udev)); len = readlink(filename, s, l); diff --git a/udev/udev.xml b/udev/udev.xml index 452abc5c0..deb342969 100644 --- a/udev/udev.xml +++ b/udev/udev.xml @@ -73,7 +73,7 @@ The udev rules are read from the files located in the default rules directory /lib/udev/rules.d/, the custom rules directory /etc/udev/rules.d/ - and the temporary rules directory /var/run/udev/rules.d/. + and the temporary rules directory /run/udev/rules.d/. All rule files are sorted and processed in lexical order, regardless in which of these directories they live. Files in /etc/udev/rules.d/ have precedence over files with diff --git a/udev/udevadm-info.c b/udev/udevadm-info.c index 33d113c5b..9357f6720 100644 --- a/udev/udevadm-info.c +++ b/udev/udevadm-info.c @@ -218,6 +218,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) { "attribute-walk", no_argument, NULL, 'a' }, { "export-db", no_argument, NULL, 'e' }, { "root", no_argument, NULL, 'r' }, + { "run", no_argument, NULL, 'R' }, { "device-id-of-file", required_argument, NULL, 'd' }, { "export", no_argument, NULL, 'x' }, { "export-prefix", required_argument, NULL, 'P' }, @@ -247,7 +248,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) int option; struct stat statbuf; - option = getopt_long(argc, argv, "aed:n:p:q:rxP:Vh", options, NULL); + option = getopt_long(argc, argv, "aed:n:p:q:rxP:RVh", options, NULL); if (option == -1) break; @@ -331,6 +332,9 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) action = ACTION_ROOT; root = true; break; + case 'R': + printf("%s\n", udev_get_run_path(udev)); + goto exit; case 'd': action = ACTION_DEVICE_ID_FILE; util_strscpy(name, sizeof(name), optarg); diff --git a/udev/udevadm.c b/udev/udevadm.c index 19b89ad05..336d72370 100644 --- a/udev/udevadm.c +++ b/udev/udevadm.c @@ -171,6 +171,8 @@ int main(int argc, char *argv[]) } command = argv[optind]; + info(udev, "runtime dir '%s'\n", udev_get_run_path(udev)); + if (command != NULL) for (i = 0; cmds[i].cmd != NULL; i++) { if (strcmp(cmds[i].name, command) == 0) { diff --git a/udev/udevadm.xml b/udev/udevadm.xml index cefd7763a..be8f886fc 100644 --- a/udev/udevadm.xml +++ b/udev/udevadm.xml @@ -110,6 +110,12 @@ query returns the absolute path including the root directory. + + + + The udev runtime directory: /run/udev. + + diff --git a/udev/udevd.c b/udev/udevd.c index 03cd2cbce..ef82f72d0 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -979,13 +979,15 @@ static int convert_db(struct udev *udev) struct udev_list_entry *list_entry; /* current database */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/data", NULL); if (access(filename, F_OK) >= 0) return 0; /* make sure we do not get here again */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", NULL); util_create_path(udev, filename); + udev_selinux_setfscreatecon(udev, udev_get_run_path(udev), S_IFDIR|0755); + mkdir(filename, 0755); + udev_selinux_resetfscreatecon(udev); /* old database */ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db", NULL); @@ -1044,8 +1046,7 @@ static int convert_db(struct udev *udev) /* find old database with the encoded devpath name */ util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath)); - util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), - "/.udev/db/", devpath, NULL); + util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", devpath, NULL); if (lstat(from, &stats) == 0) { if (!have_db) { udev_device_read_db(device, from); @@ -1093,6 +1094,27 @@ int main(int argc, char *argv[]) info(udev, "version %s\n", VERSION); udev_selinux_init(udev); + /* make sure, that our runtime dir exists and is writable */ + if (utimensat(AT_FDCWD, udev_get_run_config_path(udev), NULL, 0) < 0) { + /* try to create our own subdirectory, do not create parent directories */ + udev_selinux_setfscreatecon(udev, udev_get_run_config_path(udev), S_IFDIR|0755); + mkdir(udev_get_run_config_path(udev), 0755); + udev_selinux_resetfscreatecon(udev); + + if (utimensat(AT_FDCWD, udev_get_run_config_path(udev), NULL, 0) >= 0) { + /* directory seems writable now */ + udev_set_run_path(udev, udev_get_run_config_path(udev)); + } else { + /* fall back to /dev/.udev */ + char filename[UTIL_PATH_SIZE]; + + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev", NULL); + if (udev_set_run_path(udev, filename) == NULL) + goto exit; + } + } + info(udev, "runtime dir '%s'\n", udev_get_run_path(udev)); + for (;;) { int option; @@ -1252,7 +1274,7 @@ int main(int argc, char *argv[]) IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); /* watch dynamic rules directory */ - util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_run_path(udev), "/rules.d", NULL); if (stat(filename, &statbuf) != 0) { util_create_path(udev, filename); udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755); -- 2.30.2