mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-30 23:21:08 +03:00
check the udevdb before assigning a new %e
A second "add" event created a new enumeration with %e. Check the udevdb first and if a matching name is already used. Signed-off-by: Kay Sievers <kay.sievers@suse.de>
This commit is contained in:
parent
a8586078fc
commit
2983db9745
61
udev_rules.c
61
udev_rules.c
@ -267,16 +267,58 @@ static int import_parent_into_env(struct udevice *udev, struct sysfs_class_devic
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finds the lowest positive N such that <name>N isn't present in the udevdb
|
static int match_name_and_get_number(const char *base, const char *devname)
|
||||||
* if <name> doesn't exist, 0 is returned, N otherwise
|
{
|
||||||
*/
|
size_t baselen;
|
||||||
static int find_free_number(const char *name, const char *devpath)
|
char *endptr;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
baselen = strlen(base);
|
||||||
|
if (strncmp(base, devname, baselen) != 0)
|
||||||
|
return -1;
|
||||||
|
if (devname[baselen] == '\0')
|
||||||
|
return 0;
|
||||||
|
if (!isdigit(devname[baselen]))
|
||||||
|
return -1;
|
||||||
|
num = strtoul(&devname[baselen], &endptr, 10);
|
||||||
|
if (endptr[0] != '\0')
|
||||||
|
return -1;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* finds the lowest positive device number such that <name>N isn't present in the udevdb
|
||||||
|
* if <name> doesn't exist, 0 is returned, N otherwise */
|
||||||
|
static int find_free_number(const char *base, const char *devpath)
|
||||||
{
|
{
|
||||||
char db_devpath[PATH_SIZE];
|
char db_devpath[PATH_SIZE];
|
||||||
char filename[PATH_SIZE];
|
char filename[PATH_SIZE];
|
||||||
|
struct udevice udev_db;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
strlcpy(filename, name, sizeof(filename));
|
/* check if the device already owns a matching name */
|
||||||
|
udev_init_device(&udev_db, NULL, NULL, NULL);
|
||||||
|
if (udev_db_get_device(&udev_db, devpath) == 0) {
|
||||||
|
struct name_entry *name_loop;
|
||||||
|
int devnum;
|
||||||
|
|
||||||
|
devnum = match_name_and_get_number(base, udev_db.name);
|
||||||
|
if (devnum >= 0) {
|
||||||
|
num = devnum;
|
||||||
|
dbg("device '%s', already has the node '%s' with num %u, use it", devpath, base, num);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
list_for_each_entry(name_loop, &udev_db.symlink_list, node) {
|
||||||
|
devnum = match_name_and_get_number(base, name_loop->name);
|
||||||
|
if (devnum >= 0) {
|
||||||
|
num = devnum;
|
||||||
|
dbg("device '%s', already has a symlink '%s' with num %u, use it", devpath, base, num);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* just search the database again and again until a free name is found */
|
||||||
|
strlcpy(filename, base, sizeof(filename));
|
||||||
while (1) {
|
while (1) {
|
||||||
dbg("look for existing node '%s'", filename);
|
dbg("look for existing node '%s'", filename);
|
||||||
if (udev_db_lookup_name(filename, db_devpath, sizeof(db_devpath)) != 0) {
|
if (udev_db_lookup_name(filename, db_devpath, sizeof(db_devpath)) != 0) {
|
||||||
@ -290,10 +332,12 @@ static int find_free_number(const char *name, const char *devpath)
|
|||||||
num = -1;
|
num = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snprintf(filename, sizeof(filename), "%s%d", name, num);
|
snprintf(filename, sizeof(filename), "%s%d", base, num);
|
||||||
filename[sizeof(filename)-1] = '\0';
|
filename[sizeof(filename)-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
udev_cleanup_device(&udev_db);
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,12 +389,12 @@ static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
|
|||||||
|
|
||||||
while (--loop) {
|
while (--loop) {
|
||||||
if (stat(filename, &stats) == 0) {
|
if (stat(filename, &stats) == 0) {
|
||||||
dbg("file appeared after %i loops", (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
|
info("file appeared after %i loops", (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
|
usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
|
||||||
}
|
}
|
||||||
dbg("waiting for '%s' failed", filename);
|
info("waiting for '%s' failed", filename);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,6 +713,7 @@ static int match_key(const char *key_name, struct udev_rule *rule, struct key *k
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* match a single rule against a given device and possibly its parent devices */
|
||||||
static int match_rule(struct udevice *udev, struct udev_rule *rule,
|
static int match_rule(struct udevice *udev, struct udev_rule *rule,
|
||||||
struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device)
|
struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user