@@ -6,6 +6,7 @@
|
||||
#include "sd-forward.h"
|
||||
#include "iterator.h"
|
||||
|
||||
#define OLDEST_UDEV_DATABASE_VERSION 1
|
||||
#define LATEST_UDEV_DATABASE_VERSION 1
|
||||
|
||||
struct sd_device {
|
||||
@@ -51,7 +52,7 @@ struct sd_device {
|
||||
/* The database version indicates the supported features by the udev database.
|
||||
* This is saved and parsed in V field.
|
||||
*
|
||||
* 0: None of the following features are supported (systemd version <= 246).
|
||||
* 0: None of the following features are supported (systemd version <= 246), unsupported since v261.
|
||||
* 1: The current tags (Q) and the database version (V) features are implemented (>= 247).
|
||||
*/
|
||||
unsigned database_version;
|
||||
|
||||
@@ -912,7 +912,7 @@ int device_update_db(sd_device *device) {
|
||||
fprintf(f, "Q:%s\n", ct); /* Current tag */
|
||||
|
||||
/* Always write the latest database version here, instead of the value stored in
|
||||
* device->database_version, as which may be 0. */
|
||||
* device->database_version. */
|
||||
fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION) "\n", f);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ int device_new_aux(sd_device **ret) {
|
||||
.devuid = UID_INVALID,
|
||||
.devgid = GID_INVALID,
|
||||
.action = _SD_DEVICE_ACTION_INVALID,
|
||||
.database_version = OLDEST_UDEV_DATABASE_VERSION,
|
||||
};
|
||||
|
||||
*ret = device;
|
||||
@@ -1966,26 +1967,11 @@ _public_ const char* sd_device_get_tag_next(sd_device *device) {
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool device_database_supports_current_tags(sd_device *device) {
|
||||
assert(device);
|
||||
|
||||
(void) device_read_db(device);
|
||||
|
||||
/* The current tags (saved in Q field) feature is implemented in database version 1.
|
||||
* If the database version is 0, then the tags (NOT current tags, saved in G field) are not
|
||||
* sticky. Thus, we can safely bypass the operations for the current tags (Q) to tags (G). */
|
||||
|
||||
return device->database_version >= 1;
|
||||
}
|
||||
|
||||
_public_ const char* sd_device_get_current_tag_first(sd_device *device) {
|
||||
void *v;
|
||||
|
||||
assert_return(device, NULL);
|
||||
|
||||
if (!device_database_supports_current_tags(device))
|
||||
return sd_device_get_tag_first(device);
|
||||
|
||||
(void) device_read_db(device);
|
||||
|
||||
device->current_tags_iterator_generation = device->tags_generation;
|
||||
@@ -2000,9 +1986,6 @@ _public_ const char* sd_device_get_current_tag_next(sd_device *device) {
|
||||
|
||||
assert_return(device, NULL);
|
||||
|
||||
if (!device_database_supports_current_tags(device))
|
||||
return sd_device_get_tag_next(device);
|
||||
|
||||
(void) device_read_db(device);
|
||||
|
||||
if (device->current_tags_iterator_generation != device->tags_generation)
|
||||
@@ -2273,9 +2256,6 @@ _public_ int sd_device_has_current_tag(sd_device *device, const char *tag) {
|
||||
assert_return(device, -EINVAL);
|
||||
assert_return(tag, -EINVAL);
|
||||
|
||||
if (!device_database_supports_current_tags(device))
|
||||
return sd_device_has_tag(device, tag);
|
||||
|
||||
(void) device_read_db(device);
|
||||
|
||||
return set_contains(device->current_tags, tag);
|
||||
|
||||
+22
-58
@@ -79,84 +79,48 @@ static int node_create_symlink(sd_device *dev, const char *devnode, const char *
|
||||
}
|
||||
|
||||
static int stack_directory_read_one(int dirfd, const char *id, char **devnode, int *priority) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
int tmp_prio, r;
|
||||
int r;
|
||||
|
||||
assert(dirfd >= 0);
|
||||
assert(id);
|
||||
assert(priority);
|
||||
|
||||
/* This reads priority and device node from the symlink under /run/udev/links (or udev database).
|
||||
/* This reads priority and device node from the symlink under /run/udev/links/ directory.
|
||||
* If 'devnode' is NULL, obtained priority is always set to '*priority'. If 'devnode' is non-NULL,
|
||||
* this updates '*devnode' and '*priority'. */
|
||||
* this updates '*devnode' and '*priority' if the obtained one has a higher priority. */
|
||||
|
||||
/* First, let's try to read the entry with the new format, which should replace the old format pretty
|
||||
* quickly. */
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
r = readlinkat_malloc(dirfd, id, &buf);
|
||||
if (r >= 0) {
|
||||
char *colon;
|
||||
if (r < 0)
|
||||
return r == -ENOENT ? -ENODEV : r;
|
||||
|
||||
/* With the new format, the devnode and priority can be obtained from symlink itself. */
|
||||
char *colon = strchr(buf, ':');
|
||||
if (!colon || colon == buf)
|
||||
return -EINVAL;
|
||||
|
||||
colon = strchr(buf, ':');
|
||||
if (!colon || colon == buf)
|
||||
return -EINVAL;
|
||||
*colon = '\0';
|
||||
|
||||
*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 -ENODEV;
|
||||
|
||||
/* 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 -ENODEV;
|
||||
|
||||
r = safe_atoi(buf, &tmp_prio);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!devnode)
|
||||
goto finalize;
|
||||
int tmp_prio;
|
||||
r = safe_atoi(buf, &tmp_prio);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (devnode) {
|
||||
if (*devnode && tmp_prio <= *priority)
|
||||
return 0; /* Unchanged */
|
||||
|
||||
r = free_and_strdup(devnode, colon + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
} else if (r == -EINVAL) { /* Not a symlink ? try the old format */
|
||||
_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)
|
||||
goto finalize;
|
||||
|
||||
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;
|
||||
|
||||
} else
|
||||
return r == -ENOENT ? -ENODEV : r;
|
||||
|
||||
finalize:
|
||||
*priority = tmp_prio;
|
||||
return 1; /* Updated */
|
||||
}
|
||||
|
||||
+10
-11
@@ -337,21 +337,20 @@ static int udev_watch_restore(Manager *manager) {
|
||||
return log_warning_errno(errno, "Failed to open old watches directory '%s': %m", old);
|
||||
|
||||
FOREACH_DIRENT(de, dir, break) {
|
||||
|
||||
/* For backward compatibility, read symlink from watch handle to device ID. This is necessary
|
||||
* when udevd is restarted after upgrading from v248 or older. The new format (ID -> wd) was
|
||||
* introduced by e7f781e473f5119bf9246208a6de9f6b76a39c5d (v249). */
|
||||
|
||||
int wd;
|
||||
if (safe_atoi(de->d_name, &wd) < 0)
|
||||
continue; /* This should be ID -> wd symlink. Skipping. */
|
||||
if (in_charset(de->d_name, DIGITS))
|
||||
continue; /* This should be wd -> ID symlink. Skipping. */
|
||||
|
||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||
r = device_new_from_watch_handle_at(&dev, dirfd(dir), wd);
|
||||
r = sd_device_new_from_device_id(&dev, de->d_name);
|
||||
if (r < 0) {
|
||||
_cleanup_free_ char *wd_str = NULL;
|
||||
|
||||
if (ERRNO_IS_NEG_DEVICE_ABSENT(r) || DEBUG_LOGGING)
|
||||
(void) readlinkat_malloc(dirfd(dir), de->d_name, &wd_str);
|
||||
|
||||
log_full_errno(ERRNO_IS_NEG_DEVICE_ABSENT(r) ? LOG_DEBUG : LOG_WARNING, r,
|
||||
"Failed to create sd_device object from saved watch handle '%i', ignoring: %m",
|
||||
wd);
|
||||
"Failed to create sd_device object from device ID '%s' for watch handle '%s', ignoring: %m",
|
||||
de->d_name, strna(wd_str));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user