chiark / gitweb /
Allow block and char classes in DeviceAllow bus properties (#4353)
[elogind.git] / src / basic / path-util.c
index 123b4ce8c89e8db5f58660c31581b33667004a60..3af2bd0fd4ab82aeb5ede0d7fbd8274f2a9285d2 100644 (file)
@@ -817,8 +817,79 @@ bool is_device_path(const char *path) {
         /* Returns true on paths that refer to a device, either in
          * sysfs or in /dev */
 
-        return
-                path_startswith(path, "/dev/") ||
-                path_startswith(path, "/sys/");
+        return path_startswith(path, "/dev/") ||
+               path_startswith(path, "/sys/");
+}
+
+bool is_deviceallow_pattern(const char *path) {
+        return path_startswith(path, "/dev/") ||
+               startswith(path, "block-") ||
+               startswith(path, "char-");
 }
 #endif // 0
+
+int systemd_installation_has_version(const char *root, unsigned minimal_version) {
+        const char *pattern;
+        int r;
+
+        /* Try to guess if systemd installation is later than the specified version. This
+         * is hacky and likely to yield false negatives, particularly if the installation
+         * is non-standard. False positives should be relatively rare.
+         */
+
+        NULSTR_FOREACH(pattern,
+                       /* /lib works for systems without usr-merge, and for systems with a sane
+                        * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary
+                        * for Gentoo which does a merge without making /lib a symlink.
+                        */
+                       "lib/systemd/libsystemd-shared-*.so\0"
+                       "usr/lib/systemd/libsystemd-shared-*.so\0") {
+
+                _cleanup_strv_free_ char **names = NULL;
+                _cleanup_free_ char *path = NULL;
+                char *c, **name;
+
+                path = prefix_root(root, pattern);
+                if (!path)
+                        return -ENOMEM;
+
+                r = glob_extend(&names, path);
+                if (r == -ENOENT)
+                        continue;
+                if (r < 0)
+                        return r;
+
+                assert_se((c = endswith(path, "*.so")));
+                *c = '\0'; /* truncate the glob part */
+
+                STRV_FOREACH(name, names) {
+                        /* This is most likely to run only once, hence let's not optimize anything. */
+                        char *t, *t2;
+                        unsigned version;
+
+                        t = startswith(*name, path);
+                        if (!t)
+                                continue;
+
+                        t2 = endswith(t, ".so");
+                        if (!t2)
+                                continue;
+
+                        t2[0] = '\0'; /* truncate the suffix */
+
+                        r = safe_atou(t, &version);
+                        if (r < 0) {
+                                log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name);
+                                continue;
+                        }
+
+                        log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).",
+                                  *name, version,
+                                  version >= minimal_version ? "OK" : "too old");
+                        if (version >= minimal_version)
+                                return true;
+                }
+        }
+
+        return false;
+}