summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--libudev/libudev-device-private.c29
-rw-r--r--libudev/libudev-device.c51
-rw-r--r--libudev/libudev-private.h1
-rw-r--r--udev/udev-event.c3
-rw-r--r--udev/udev-node.c6
-rw-r--r--udev/udev-watch.c6
-rw-r--r--udev/udevadm-info.c61
-rw-r--r--udev/udevadm.xml9
9 files changed, 142 insertions, 26 deletions
diff --git a/Makefile.am b/Makefile.am
index 891440cf73..9fe4a3ac51 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,7 @@ DISTCHECK_HOOKS =
# libudev
# ------------------------------------------------------------------------------
LIBUDEV_CURRENT=9
-LIBUDEV_REVISION=3
+LIBUDEV_REVISION=4
LIBUDEV_AGE=9
SUBDIRS += libudev/docs
diff --git a/libudev/libudev-device-private.c b/libudev/libudev-device-private.c
index a4b2fb0169..63f947e16b 100644
--- a/libudev/libudev-device-private.c
+++ b/libudev/libudev-device-private.c
@@ -24,23 +24,18 @@
static void udev_device_tag(struct udev_device *dev, const char *tag, bool add)
{
+ const char *id;
struct udev *udev = udev_device_get_udev(dev);
char filename[UTIL_PATH_SIZE];
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/tags/", tag, "/",
- udev_device_get_subsystem(dev), ":", udev_device_get_sysname(dev), 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);
if (add) {
util_create_path(udev, filename);
symlink(udev_device_get_devpath(dev), filename);
- /* possibly cleanup old entries after a device renaming */
- if (udev_device_get_sysname_old(dev) != NULL) {
- char filename_old[UTIL_PATH_SIZE];
-
- util_strscpyl(filename_old, sizeof(filename_old), udev_get_dev_path(udev), "/.udev/tags/", tag, "/",
- udev_device_get_subsystem(dev), ":", udev_device_get_sysname_old(dev), NULL);
- unlink(filename_old);
- }
} else {
unlink(filename);
}
@@ -79,6 +74,7 @@ int udev_device_tag_index(struct udev_device *dev, struct udev_device *dev_old,
int udev_device_update_db(struct udev_device *udev_device)
{
+ const char *id;
struct udev *udev = udev_device_get_udev(udev_device);
char filename[UTIL_PATH_SIZE];
char filename_tmp[UTIL_PATH_SIZE];
@@ -90,8 +86,10 @@ int udev_device_update_db(struct udev_device *udev_device)
struct udev_list_entry *list_entry;
int ret;
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/",
- udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
+ 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_tmp, sizeof(filename_tmp), filename, ".tmp", NULL);
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device))
@@ -169,11 +167,14 @@ out:
int udev_device_delete_db(struct udev_device *udev_device)
{
+ const char *id;
struct udev *udev = udev_device_get_udev(udev_device);
char filename[UTIL_PATH_SIZE];
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/",
- udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
+ 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);
unlink(filename);
return 0;
}
diff --git a/libudev/libudev-device.c b/libudev/libudev-device.c
index 9b5d79ff4b..d87b0c6c8a 100644
--- a/libudev/libudev-device.c
+++ b/libudev/libudev-device.c
@@ -54,6 +54,7 @@ struct udev_device {
char *devpath_old;
char *sysname_old;
char *knodename;
+ char *id_filename;
char **envp;
char *monitor_buf;
size_t monitor_buf_len;
@@ -230,6 +231,7 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons
int udev_device_read_db(struct udev_device *udev_device)
{
+ const char *id;
struct stat stats;
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
@@ -238,8 +240,10 @@ int udev_device_read_db(struct udev_device *udev_device)
if (udev_device->db_loaded)
return 0;
- util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.udev/db/",
- udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
+ 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);
if (lstat(filename, &stats) != 0) {
dbg(udev_device->udev, "no db file to read %s: %m\n", filename);
@@ -799,6 +803,7 @@ void udev_device_unref(struct udev_device *udev_device)
free(udev_device->devpath_old);
free(udev_device->sysname_old);
free(udev_device->knodename);
+ free(udev_device->id_filename);
free(udev_device->envp);
free(udev_device->monitor_buf);
dbg(udev_device->udev, "udev_device: %p released\n", udev_device);
@@ -1287,6 +1292,40 @@ int udev_device_add_devlink(struct udev_device *udev_device, const char *devlink
return 0;
}
+const char *udev_device_get_id_filename(struct udev_device *udev_device)
+{
+ if (udev_device->id_filename == NULL) {
+ if (udev_device_get_subsystem(udev_device) == NULL)
+ return NULL;
+
+ if (major(udev_device_get_devnum(udev_device)) > 0) {
+ /* use dev_t -- b259:131072, c254:0 */
+ if (asprintf(&udev_device->id_filename, "%c%u:%u",
+ strcmp(udev_device_get_subsystem(udev_device), "block") == 0 ? 'b' : 'c',
+ major(udev_device_get_devnum(udev_device)),
+ minor(udev_device_get_devnum(udev_device))) < 0)
+ udev_device->id_filename = NULL;
+ } else if (strcmp(udev_device_get_subsystem(udev_device), "net") == 0) {
+ /* use netdev ifindex -- n3 */
+ if (asprintf(&udev_device->id_filename, "n%u", udev_device_get_ifindex(udev_device)) < 0)
+ udev_device->id_filename = NULL;
+ } else {
+ /*
+ * use $subsys:$syname -- pci:0000:00:1f.2
+ * sysname() has '!' translated, get it from devpath
+ */
+ const char *sysname;
+ sysname = strrchr(udev_device->devpath, '/');
+ if (sysname == NULL)
+ return NULL;
+ sysname = &sysname[1];
+ if (asprintf(&udev_device->id_filename, "+%s:%s", udev_device_get_subsystem(udev_device), sysname) < 0)
+ udev_device->id_filename = NULL;
+ }
+ }
+ return udev_device->id_filename;
+}
+
int udev_device_add_tag(struct udev_device *udev_device, const char *tag)
{
if (strchr(tag, ':') != NULL || strchr(tag, ' ') != NULL)
@@ -1500,7 +1539,11 @@ int udev_device_get_event_timeout(struct udev_device *udev_device)
int udev_device_set_event_timeout(struct udev_device *udev_device, int event_timeout)
{
+ char num[32];
+
udev_device->event_timeout = event_timeout;
+ snprintf(num, sizeof(num), "%u", event_timeout);
+ udev_device_add_property(udev_device, "TIMEOUT", num);
return 0;
}
@@ -1560,6 +1603,10 @@ int udev_device_get_ifindex(struct udev_device *udev_device)
int udev_device_set_ifindex(struct udev_device *udev_device, int ifindex)
{
+ char num[32];
+
udev_device->ifindex = ifindex;
+ snprintf(num, sizeof(num), "%u", ifindex);
+ udev_device_add_property(udev_device, "IFINDEX", num);
return 0;
}
diff --git a/libudev/libudev-private.h b/libudev/libudev-private.h
index c9ed46211c..d09a9a52a8 100644
--- a/libudev/libudev-private.h
+++ b/libudev/libudev-private.h
@@ -85,6 +85,7 @@ const char *udev_device_get_devpath_old(struct udev_device *udev_device);
const char *udev_device_get_sysname_old(struct udev_device *udev_device);
int udev_device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old);
const char *udev_device_get_knodename(struct udev_device *udev_device);
+const char *udev_device_get_id_filename(struct udev_device *udev_device);
int udev_device_add_tag(struct udev_device *udev_device, const char *tag);
void udev_device_cleanup_tags_list(struct udev_device *udev_device);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
diff --git a/udev/udev-event.c b/udev/udev-event.c
index 064873531b..f41f06b16a 100644
--- a/udev/udev-event.c
+++ b/udev/udev-event.c
@@ -535,6 +535,9 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
struct udev_device *dev = event->dev;
int err = 0;
+ if (udev_device_get_subsystem(dev) == NULL)
+ return -1;
+
if (strcmp(udev_device_get_action(dev), "remove") == 0) {
udev_device_read_db(dev);
udev_device_delete_db(dev);
diff --git a/udev/udev-node.c b/udev/udev-node.c
index c8113f10b0..92634427f9 100644
--- a/udev/udev-node.c
+++ b/udev/udev-node.c
@@ -298,10 +298,8 @@ 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));
- snprintf(dirname, sizeof(dirname), "%s/.udev/links/%s", udev_get_dev_path(udev), name_enc);
- snprintf(filename, sizeof(filename), "%s/%c%u:%u", dirname,
- strcmp(udev_device_get_subsystem(dev), "block") == 0 ? 'b' : 'c',
- major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
+ util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.udev/links/", name_enc, NULL);
+ util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
if (!add) {
dbg(udev, "removing index: '%s'\n", filename);
diff --git a/udev/udev-watch.c b/udev/udev-watch.c
index 5fa60101c4..9e1b8d8553 100644
--- a/udev/udev-watch.c
+++ b/udev/udev-watch.c
@@ -109,7 +109,6 @@ unlink:
void udev_watch_begin(struct udev *udev, struct udev_device *dev)
{
char filename[UTIL_PATH_SIZE];
- char majmin[UTIL_PATH_SIZE];
int wd;
if (inotify_fd < 0)
@@ -123,13 +122,10 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev)
return;
}
- snprintf(majmin, sizeof(majmin), "%c%i:%i",
- strcmp(udev_device_get_subsystem(dev), "block") == 0 ? 'b' : 'c',
- major(udev_device_get_devnum(dev)), minor(udev_device_get_devnum(dev)));
snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
util_create_path(udev, filename);
unlink(filename);
- symlink(majmin, filename);
+ symlink(udev_device_get_id_filename(dev), filename);
udev_device_set_watch_handle(dev, wd);
}
diff --git a/udev/udevadm-info.c b/udev/udevadm-info.c
index b3b31ebafe..7206f4fcf6 100644
--- a/udev/udevadm-info.c
+++ b/udev/udevadm-info.c
@@ -195,6 +195,60 @@ static int export_devices(struct udev *udev)
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 statbuf;
+ 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)
+ goto next;
+ util_strscpyl(to, sizeof(to), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
+
+ /* do not overwrite a new database file */
+ if (lstat(to, &statbuf) == 0)
+ goto next;
+
+ /* 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, &statbuf) == 0) {
+ rename(from, to);
+ goto next;
+ }
+
+ /* 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, &statbuf) == 0) {
+ rename(from, to);
+ goto next;
+ }
+next:
+ 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;
@@ -212,6 +266,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
{ "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' },
@@ -336,6 +391,9 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
case 'e':
export_devices(udev);
goto exit;
+ case 'C':
+ convert_db(udev);
+ goto exit;
case 'x':
export = true;
break;
@@ -359,7 +417,10 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
" --attribute-walk print all key matches while walking along the chain\n"
" of parent devices\n"
" --device-id-of-file=<file> print major:minor of device containing this file\n"
+ " --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:
diff --git a/udev/udevadm.xml b/udev/udevadm.xml
index cefd7763af..00f299fb73 100644
--- a/udev/udevadm.xml
+++ b/udev/udevadm.xml
@@ -144,6 +144,15 @@
</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>
<para>Print version.</para>