X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbasic%2Fpath-util.c;h=3af95bf24e2365e74d59cc9b5a35fc220baf03a9;hp=123b4ce8c89e8db5f58660c31581b33667004a60;hb=f7afdbbb986bed7022976612a740027697ce93ec;hpb=35eec258c4523c92fe985d764198b266ebc3881a diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 123b4ce8c..3af95bf24 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -290,9 +290,7 @@ char **path_strv_resolve(char **l, const char *prefix) { } else { /* canonicalized path goes outside of * prefix, keep the original path instead */ - free(u); - u = orig; - orig = NULL; + free_and_replace(u, orig); } } else free(t); @@ -358,6 +356,16 @@ char* path_startswith(const char *path, const char *prefix) { assert(path); assert(prefix); + /* Returns a pointer to the start of the first component after the parts matched by + * the prefix, iff + * - both paths are absolute or both paths are relative, + * and + * - each component in prefix in turn matches a component in path at the same position. + * An empty string will be returned when the prefix and path are equivalent. + * + * Returns NULL otherwise. + */ + if ((path[0] == '/') != (prefix[0] == '/')) return NULL; @@ -817,8 +825,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; +}