chiark / gitweb /
use /run/udev/ if possible and fall back to /dev/.udev/
authorKay Sievers <kay.sievers@vrfy.org>
Wed, 23 Mar 2011 01:31:09 +0000 (02:31 +0100)
committerKay Sievers <kay.sievers@vrfy.org>
Wed, 23 Mar 2011 01:31:09 +0000 (02:31 +0100)
20 files changed:
NEWS
extras/collect/collect.c
extras/firmware/firmware.c
extras/rule_generator/rule_generator.functions
libudev/libudev-device-private.c
libudev/libudev-device.c
libudev/libudev-enumerate.c
libudev/libudev-private.h
libudev/libudev-queue-private.c
libudev/libudev-queue.c
libudev/libudev.c
test/udev-test.pl
udev/udev-node.c
udev/udev-rules.c
udev/udev-watch.c
udev/udev.xml
udev/udevadm-info.c
udev/udevadm.c
udev/udevadm.xml
udev/udevd.c

diff --git a/NEWS b/NEWS
index 8da1cd9..6382600 100644 (file)
--- 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.
index b567051..17b3df3 100644 (file)
@@ -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;
 }
index f7d21df..8199820 100644 (file)
@@ -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) {
index e2060a2..4bec27a 100644 (file)
@@ -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
index 7683f09..6d72d32 100644 (file)
@@ -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;
 }
index dd0224a..ccd4a70 100644 (file)
@@ -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;
        }
 
index d3dd5c9..6870bb6 100644 (file)
@@ -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)
index 0fe6f4a..bd31793 100644 (file)
@@ -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);
 
index 9b02daf..a714572 100644 (file)
@@ -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) {
index 6f743d2..75c5b24 100644 (file)
@@ -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;
index cd41870..d96934f 100644 (file)
@@ -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) {
index 6a0ea82..4103cf0 100755 (executable)
@@ -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;
index aaa2e32..ab4e932 100644 (file)
@@ -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) {
index 4a5b8de..221865c 100644 (file)
@@ -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");
 
index 47dca4c..0ec8bfd 100644 (file)
@@ -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);
index 452abc5..deb3429 100644 (file)
@@ -73,7 +73,7 @@
       <para>The udev rules are read from the files located in the
       default rules directory <filename>/lib/udev/rules.d/</filename>,
       the custom rules directory <filename>/etc/udev/rules.d/</filename>
-      and the temporary rules directory <filename>/var/run/udev/rules.d/</filename>.
+      and the temporary rules directory <filename>/run/udev/rules.d/</filename>.
       All rule files are sorted and processed in lexical order, regardless
       in which of these directories they live. Files in
       <filename>/etc/udev/rules.d/</filename> have precedence over files with
index 33d113c..9357f67 100644 (file)
@@ -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);
index 19b89ad..336d723 100644 (file)
@@ -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) {
index cefd776..be8f886 100644 (file)
           </listitem>
         </varlistentry>
         <varlistentry>
+          <term><option>--run</option></term>
+          <listitem>
+            <para>The udev runtime directory: <filename>/run/udev</filename>.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
           <term><option>--attribute-walk</option></term>
           <listitem>
             <para>Print all sysfs properties of the specified device that can be used
index 03cd2cb..ef82f72 100644 (file)
@@ -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);