# libudev
# ------------------------------------------------------------------------------
LIBUDEV_CURRENT=11
-LIBUDEV_REVISION=0
+LIBUDEV_REVISION=1
LIBUDEV_AGE=11
SUBDIRS += libudev/docs
========
Bugfixes.
+The udev runtime data moved from /dev/.udev/ to /dev/.run/udev/.
+On new systems the tmpfs mountpoint /var/run/ will have an
+"early-boot alias" /dev/.run/ where udev and a couple of other
+early-boot tools will put their runtime data.
+On systems with LVM used, packagers must make sure, that the
+initramfs creates the /dev/.run/ mountpoint for udev to store
+the data, so that the real root will not overmount it, which
+would make it invisible.
+
+The command 'udevadm info --convert-db' is gone. The udev daemon
+itself, at startup, converts any old database version if necessary.
+
udev 166
========
Bugfixes.
#include "libudev.h"
#include "libudev-private.h"
-#define TMPFILE "/dev/.udev/collect"
+#define TMPFILE "/dev/.run/udev/collect"
#define BUFSIZE 16
#define UDEV_ALARM_TIMEOUT 180
}
util_path_encode(firmware, fwencpath, sizeof(fwencpath));
- util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.udev/firmware-missing/", fwencpath, NULL);
+ util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.run/udev/firmware-missing/", fwencpath, NULL);
util_strscpyl(loadpath, sizeof(loadpath), udev_get_sys_path(udev), devpath, "/loading", NULL);
if (fwfile == NULL) {
id = udev_device_get_id_filename(dev);
if (id == NULL)
return;
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/tags/", tag, "/", id, NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/tags/", tag, "/", id, NULL);
if (add) {
int fd;
return -1;
has_info = device_has_info(udev_device);
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
/* do not store anything for otherwise empty devices */
if (!has_info &&
id = udev_device_get_id_filename(udev_device);
if (id == NULL)
return -1;
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
unlink(filename);
return 0;
}
return udev_list_entry_get_value(list_entry);
}
-int udev_device_read_db(struct udev_device *udev_device)
+int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
{
- const char *id;
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
FILE *f;
- if (udev_device->db_loaded)
- return 0;
- udev_device->db_loaded = true;
+ /* providing a database file will always force-load it */
+ if (dbfile == NULL) {
+ const char *id;
- 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), "/.udev/db/", id, NULL);
- f = fopen(filename, "re");
+ if (udev_device->db_loaded)
+ return 0;
+ udev_device->db_loaded = true;
+
+ 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);
+ dbfile = filename;
+ }
+
+ f = fopen(dbfile, "re");
if (f == NULL) {
- info(udev_device->udev, "no db file to read %s: %m\n", filename);
+ info(udev_device->udev, "no db file to read %s: %m\n", dbfile);
return -1;
}
udev_device->is_initialized = true;
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
}
/* we might get called before we handled an event and have a db, use the kernel-provided name */
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
return udev_list_get_entry(&udev_device->devlinks_list);
}
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
}
if (!udev_device->devlinks_uptodate) {
char symlinks[UTIL_PATH_SIZE];
if (udev_device == NULL)
return 0;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
if (udev_device->usec_initialized == 0)
return 0;
now = usec_monotonic();
int udev_device_get_is_initialized(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
return udev_device->is_initialized;
}
struct udev_list_entry *list_entry;
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
list_entry = udev_device_get_tags_list_entry(udev_device);
list_entry = udev_list_entry_get_by_name(list_entry, tag);
if (list_entry != NULL)
int udev_device_get_event_timeout(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
return udev_device->event_timeout;
}
int udev_device_get_devlink_priority(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
return udev_device->devlink_priority;
}
int udev_device_get_watch_handle(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
- udev_device_read_db(udev_device);
+ udev_device_read_db(udev_device, NULL);
return udev_device->watch_handle;
}
struct dirent *dent;
char path[UTIL_PATH_SIZE];
- util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.udev/tags/",
+ util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.run/udev/tags/",
udev_list_entry_get_name(list_entry), NULL);
dir = opendir(path);
if (dir == NULL)
int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device);
char **udev_device_get_properties_envp(struct udev_device *udev_device);
ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf);
-int udev_device_read_db(struct udev_device *udev_device);
+int udev_device_read_db(struct udev_device *udev_device, const char *dbfile);
int udev_device_read_uevent_file(struct udev_device *udev_device);
int udev_device_set_action(struct udev_device *udev_device, const char *action);
int udev_device_set_driver(struct udev_device *udev_device, const char *driver);
{
char filename[UTIL_PATH_SIZE];
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
unlink(filename);
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
unlink(filename);
}
}
/* create new queue file */
- util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
+ util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
new_queue_file = fopen(filename_tmp, "w+");
if (new_queue_file == NULL)
goto error;
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), "/.udev/queue.bin", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
if (rename(filename_tmp, filename) != 0)
goto error;
return;
/* location of failed file */
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/failed/",
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/failed/",
udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
switch (state) {
char filename[UTIL_PATH_SIZE];
FILE *queue_file;
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/queue.bin", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.run/udev/queue.bin", NULL);
queue_file = fopen(filename, "re");
if (queue_file == NULL)
return NULL;
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), "/.udev/failed", NULL);
+ util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.run/udev/failed", NULL);
dir = opendir(path);
if (dir == NULL)
return NULL;
return -1;
if (strcmp(udev_device_get_action(dev), "remove") == 0) {
- udev_device_read_db(dev);
+ udev_device_read_db(dev, NULL);
udev_device_delete_db(dev);
udev_device_tag_index(dev, NULL, false);
} else {
event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
if (event->dev_db != NULL) {
- udev_device_read_db(event->dev_db);
+ udev_device_read_db(event->dev_db, NULL);
udev_device_set_info_loaded(event->dev_db);
/* disable watch during event processing */
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), "/.udev/links/", name_enc, NULL);
+ util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.run/udev/links/", name_enc, NULL);
util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
if (!add) {
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), "/.udev/rules.d", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
udev_list_init(&sort_list);
add_matching_files(udev, &sort_list, filename, ".rules");
if (inotify_fd < 0)
return;
- util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.udev/watch.old", NULL);
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/watch", NULL);
+ 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);
if (rename(filename, oldname) == 0) {
DIR *dir;
struct dirent *ent;
return;
}
- snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+ snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
util_create_path(udev, filename);
unlink(filename);
symlink(udev_device_get_id_filename(dev), filename);
info(udev, "removing watch on '%s'\n", udev_device_get_devnode(dev));
inotify_rm_watch(inotify_fd, wd);
- snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+ snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
unlink(filename);
udev_device_set_watch_handle(dev, -1);
if (inotify_fd < 0 || wd < 0)
return NULL;
- snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
+ snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
s = majmin;
l = util_strpcpy(&s, sizeof(majmin), udev_get_sys_path(udev));
len = readlink(filename, s, l);
<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>/dev/.udev/rules.d/</filename>.
+ and the temporary rules directory <filename>/var/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
return 0;
}
-static int convert_db(struct udev *udev)
-{
- struct udev_enumerate *udev_enumerate;
- struct udev_list_entry *list_entry;
-
- udev_enumerate = udev_enumerate_new(udev);
- if (udev_enumerate == NULL)
- return -1;
- udev_enumerate_scan_devices(udev_enumerate);
- udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
- struct udev_device *device;
-
- device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
- if (device != NULL) {
- const char *id;
- struct stat stats;
- char to[UTIL_PATH_SIZE];
- char devpath[UTIL_PATH_SIZE];
- char from[UTIL_PATH_SIZE];
-
- id = udev_device_get_id_filename(device);
- if (id == NULL) {
- udev_device_unref(device);
- continue;
- }
- util_strscpyl(to, sizeof(to), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
-
- /* find old database with $subsys:$sysname */
- util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
- "/.udev/db/", udev_device_get_subsystem(device), ":",
- udev_device_get_sysname(device), NULL);
- if (lstat(from, &stats) == 0) {
- if (lstat(to, &stats) == 0)
- unlink(from);
- else
- rename(from, to);
- }
-
- /* find old database with the encoded devpath */
- 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);
- if (lstat(from, &stats) == 0) {
- if (lstat(to, &stats) == 0)
- unlink(from);
- else
- rename(from, to);
- }
-
- /* read the old database, and write out a new one */
- udev_device_read_db(device);
- udev_device_update_db(device);
-
- udev_device_unref(device);
- }
- }
- udev_enumerate_unref(udev_enumerate);
- return 0;
-}
-
int udevadm_info(struct udev *udev, int argc, char *argv[])
{
struct udev_device *device = NULL;
{ "query", required_argument, NULL, 'q' },
{ "attribute-walk", no_argument, NULL, 'a' },
{ "export-db", no_argument, NULL, 'e' },
- { "convert-db", no_argument, NULL, 'C' },
{ "root", no_argument, NULL, 'r' },
{ "device-id-of-file", required_argument, NULL, 'd' },
{ "export", no_argument, NULL, 'x' },
case 'e':
export_devices(udev);
goto exit;
- case 'C':
- convert_db(udev);
- goto exit;
case 'x':
export = true;
break;
" --export export key/value pairs\n"
" --export-prefix export the key name with a prefix\n"
" --export-db export the content of the udev database\n"
- " --convert-db convert older version of database without a reboot\n"
" --help\n\n");
goto exit;
default:
<para>Export the content of the udev database.</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><option>--convert-db</option></term>
- <listitem>
- <para>Convert the database of an earlier udev version to the current format. This
- is only useful on udev version upgrades, where the content of the old database might
- be needed for the running system, and it is not sufficient for it, to be re-created
- with the next bootup.</para>
- </listitem>
- </varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem>
return memsize;
}
+static int convert_db(struct udev *udev)
+{
+ char filename[UTIL_PATH_SIZE];
+ FILE *f;
+ struct udev_enumerate *udev_enumerate;
+ struct udev_list_entry *list_entry;
+
+ /* current database */
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3", 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);
+
+ /* old database */
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db", NULL);
+ if (access(filename, F_OK) < 0)
+ return 0;
+
+ f = fopen("/dev/kmsg", "w");
+ if (f != NULL) {
+ fprintf(f, "<6>udev[%u]: converting old udev database\n", getpid());
+ fclose(f);
+ }
+
+ udev_enumerate = udev_enumerate_new(udev);
+ if (udev_enumerate == NULL)
+ return -1;
+ udev_enumerate_scan_devices(udev_enumerate);
+ udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
+ struct udev_device *device;
+
+ device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
+ if (device == NULL)
+ continue;
+
+ /* try to find the old database for devices without a current one */
+ if (udev_device_read_db(device, NULL) < 0) {
+ bool have_db;
+ const char *id;
+ struct stat stats;
+ char devpath[UTIL_PATH_SIZE];
+ char from[UTIL_PATH_SIZE];
+
+ have_db = false;
+
+ /* find database in old location */
+ id = udev_device_get_id_filename(device);
+ util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+ if (lstat(from, &stats) == 0) {
+ if (!have_db) {
+ udev_device_read_db(device, from);
+ have_db = true;
+ }
+ unlink(from);
+ }
+
+ /* find old database with $subsys:$sysname name */
+ util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
+ "/.udev/db/", udev_device_get_subsystem(device), ":",
+ udev_device_get_sysname(device), NULL);
+ if (lstat(from, &stats) == 0) {
+ if (!have_db) {
+ udev_device_read_db(device, from);
+ have_db = true;
+ }
+ unlink(from);
+ }
+
+ /* 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);
+ if (lstat(from, &stats) == 0) {
+ if (!have_db) {
+ udev_device_read_db(device, from);
+ have_db = true;
+ }
+ unlink(from);
+ }
+
+ /* write out new database */
+ if (have_db)
+ udev_device_update_db(device);
+ }
+ udev_device_unref(device);
+ }
+ udev_enumerate_unref(udev_enumerate);
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct udev *udev;
IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
/* watch dynamic rules directory */
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
+ util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
if (stat(filename, &statbuf) != 0) {
util_create_path(udev, filename);
udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
goto exit;
}
+ /* if needed, convert old database from earlier udev version */
+ convert_db(udev);
+
if (!debug) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);