mirror of
https://github.com/systemd/systemd.git
synced 2025-03-13 00:58:27 +03:00
Merge pull request #24691 from yuwata/udev-node-check-existence
udev: check existence of device node
This commit is contained in:
commit
4f0d1cd011
@ -122,6 +122,78 @@ static int node_symlink(sd_device *dev, const char *devnode, const char *slink)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stack_directory_read_one(int dirfd, const char *id, bool is_symlink, char **devnode, int *priority) {
|
||||
int tmp_prio, r;
|
||||
|
||||
assert(dirfd >= 0);
|
||||
assert(id);
|
||||
assert(devnode);
|
||||
assert(priority);
|
||||
|
||||
if (is_symlink) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
char *colon;
|
||||
|
||||
/* New format. The devnode and priority can be obtained from symlink. */
|
||||
|
||||
r = readlinkat_malloc(dirfd, id, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
colon = strchr(buf, ':');
|
||||
if (!colon || colon == buf)
|
||||
return -EINVAL;
|
||||
|
||||
*colon = '\0';
|
||||
|
||||
/* Of course, this check is racy, but it is not necessary to be perfect. Even if the device
|
||||
* node will be removed after this check, we will receive 'remove' uevent, and the invalid
|
||||
* symlink will be removed during processing the event. The check is just for shortening the
|
||||
* timespan that the symlink points to a non-existing device node. */
|
||||
if (access(colon + 1, F_OK) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_atoi(buf, &tmp_prio);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*devnode && tmp_prio <= *priority)
|
||||
return 0; /* Unchanged */
|
||||
|
||||
r = free_and_strdup(devnode, colon + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
} else {
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
const char *val;
|
||||
|
||||
/* Old format. The devnode and priority must be obtained from uevent and udev database. */
|
||||
|
||||
r = sd_device_new_from_device_id(&dev, id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = device_get_devlink_priority(dev, &tmp_prio);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*devnode && tmp_prio <= *priority)
|
||||
return 0; /* Unchanged */
|
||||
|
||||
r = sd_device_get_devname(dev, &val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = free_and_strdup(devnode, val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*priority = tmp_prio;
|
||||
return 1; /* Updated */
|
||||
}
|
||||
|
||||
static int stack_directory_find_prioritized_devnode(sd_device *dev, const char *dirname, bool add, char **ret) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
_cleanup_free_ char *devnode = NULL;
|
||||
@ -160,8 +232,6 @@ static int stack_directory_find_prioritized_devnode(sd_device *dev, const char *
|
||||
return r;
|
||||
|
||||
FOREACH_DIRENT_ALL(de, dir, break) {
|
||||
int tmp_prio;
|
||||
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
@ -169,61 +239,14 @@ static int stack_directory_find_prioritized_devnode(sd_device *dev, const char *
|
||||
if (streq(de->d_name, id))
|
||||
continue;
|
||||
|
||||
if (de->d_type == DT_LNK) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
char *colon;
|
||||
|
||||
/* New format. The devnode and priority can be obtained from symlink. */
|
||||
|
||||
r = readlinkat_malloc(dirfd(dir), de->d_name, &buf);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to read symlink %s, ignoring: %m", de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
colon = strchr(buf, ':');
|
||||
if (!colon || colon == buf)
|
||||
continue;
|
||||
|
||||
*colon = '\0';
|
||||
|
||||
if (safe_atoi(buf, &tmp_prio) < 0)
|
||||
continue;
|
||||
|
||||
if (devnode && tmp_prio <= priority)
|
||||
continue;
|
||||
|
||||
r = free_and_strdup(&devnode, colon + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
} else if (de->d_type == DT_REG) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *tmp_dev = NULL;
|
||||
const char *val;
|
||||
|
||||
/* Old format. The devnode and priority must be obtained from uevent and
|
||||
* udev database files. */
|
||||
|
||||
if (sd_device_new_from_device_id(&tmp_dev, de->d_name) < 0)
|
||||
continue;
|
||||
|
||||
if (device_get_devlink_priority(tmp_dev, &tmp_prio) < 0)
|
||||
continue;
|
||||
|
||||
if (devnode && tmp_prio <= priority)
|
||||
continue;
|
||||
|
||||
if (sd_device_get_devname(tmp_dev, &val) < 0)
|
||||
continue;
|
||||
|
||||
r = free_and_strdup(&devnode, val);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
} else
|
||||
if (!IN_SET(de->d_type, DT_LNK, DT_REG))
|
||||
continue;
|
||||
|
||||
priority = tmp_prio;
|
||||
r = stack_directory_read_one(dirfd(dir), de->d_name, /* is_symlink = */ de->d_type == DT_LNK, &devnode, &priority);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read '%s/%s', ignoring: %m", dirname, de->d_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(devnode);
|
||||
|
Loading…
x
Reference in New Issue
Block a user