summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-11-26 12:48:05 +0100
committerGitHub <noreply@github.com>2020-11-26 12:48:05 +0100
commit18c4e13457a0535186418851c41b2f1657b7cca0 (patch)
tree9cfa5503b976f2489b898c272ec350b7985ca26c
parent362ddd775690684ce32246395550a48149304b99 (diff)
parent6ece7cd2b7d5a9a916958a93f108a2fc1c9a0c0c (diff)
downloadsystemd-18c4e13457a0535186418851c41b2f1657b7cca0.tar.gz
Merge pull request #17622 from yuwata/udev-database-set-udev-version
sd-device: make sd_device_has_current_tag() compatible with udev database generated by older udevd
-rw-r--r--src/libsystemd/sd-device/device-internal.h14
-rw-r--r--src/libsystemd/sd-device/device-private.c4
-rw-r--r--src/libsystemd/sd-device/sd-device.c31
3 files changed, 44 insertions, 5 deletions
diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h
index 3f81cef796..3321c8e2dc 100644
--- a/src/libsystemd/sd-device/device-internal.h
+++ b/src/libsystemd/sd-device/device-internal.h
@@ -8,9 +8,19 @@
#include "set.h"
#include "time-util.h"
+#define LATEST_UDEV_DATABASE_VERSION 1
+
struct sd_device {
unsigned n_ref;
+ /* 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).
+ * 1: The current tags (Q) and the database version (V) features are implemented (>= 247).
+ */
+ unsigned database_version;
+
int watch_handle;
sd_device *parent;
@@ -88,7 +98,9 @@ struct sd_device {
int device_new_aux(sd_device **ret);
int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db);
-int device_add_property_internal(sd_device *device, const char *key, const char *value);
+static inline int device_add_property_internal(sd_device *device, const char *key, const char *value) {
+ return device_add_property_aux(device, key, value, false);
+}
int device_read_uevent_file(sd_device *device);
int device_set_syspath(sd_device *device, const char *_syspath, bool verify);
diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c
index 1c7bb033d3..2801ebdcbe 100644
--- a/src/libsystemd/sd-device/device-private.c
+++ b/src/libsystemd/sd-device/device-private.c
@@ -948,6 +948,10 @@ int device_update_db(sd_device *device) {
SET_FOREACH(tag, device->current_tags)
fprintf(f, "Q:%s\n", tag); /* Current tag */
+
+ /* Always write the latest database version here, instead of the value stored in
+ * device->database_version, as which may be 0. */
+ fputs("V:" STRINGIFY(LATEST_UDEV_DATABASE_VERSION) "\n", f);
}
r = fflush_and_check(f);
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c
index bfa0781773..d06f90ce1d 100644
--- a/src/libsystemd/sd-device/sd-device.c
+++ b/src/libsystemd/sd-device/sd-device.c
@@ -128,10 +128,6 @@ int device_add_property_aux(sd_device *device, const char *_key, const char *_va
return 0;
}
-int device_add_property_internal(sd_device *device, const char *key, const char *value) {
- return device_add_property_aux(device, key, value, false);
-}
-
int device_set_syspath(sd_device *device, const char *_syspath, bool verify) {
_cleanup_free_ char *syspath = NULL;
const char *devpath;
@@ -1209,6 +1205,12 @@ static int handle_db_line(sd_device *device, char key, const char *value) {
return r;
break;
+ case 'V':
+ r = safe_atou(value, &device->database_version);
+ if (r < 0)
+ return r;
+
+ break;
default:
log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key);
}
@@ -1442,11 +1444,26 @@ _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;
@@ -1461,6 +1478,9 @@ _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)
@@ -1763,6 +1783,9 @@ _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);