summaryrefslogtreecommitdiff
path: root/libudev
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2010-12-10 01:13:35 +0100
committerKay Sievers <kay.sievers@vrfy.org>2010-12-10 01:18:15 +0100
commit4281da1fa6fda10c15bee984825fc607a8385004 (patch)
treec92eaab4296a31bcccd754dc2b23410025158ef1 /libudev
parentdc1791a9e6b59bd070a5f9c01b2214a1f8d69a82 (diff)
udevd: use dev_t or netif ifindex as database key
We need to preserve the database of network interfaces while we rename them. Use the kernel's numbers wherever possible, instead of the device names. Fix wrong database filenames which contain a '/', translated from '!' in the kernel name. Fix segfault for kobject pathes where the subsystem can not be determined from sysfs.
Diffstat (limited to 'libudev')
-rw-r--r--libudev/libudev-device-private.c29
-rw-r--r--libudev/libudev-device.c51
-rw-r--r--libudev/libudev-private.h1
3 files changed, 65 insertions, 16 deletions
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);