path-util: add a function to peek into a container and guess systemd version
This is a bit crude and only works for new systemd versions which have libsystemd-shared.
This commit is contained in:
parent
1644102735
commit
5a46d55fc8
|
@ -34,9 +34,11 @@
|
|||
#include "alloc-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fs-util.h"
|
||||
#include "glob-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
@ -814,3 +816,69 @@ bool is_device_path(const char *path) {
|
|||
path_startswith(path, "/dev/") ||
|
||||
path_startswith(path, "/sys/");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -125,3 +125,5 @@ char *file_in_same_dir(const char *path, const char *filename);
|
|||
bool hidden_or_backup_file(const char *filename) _pure_;
|
||||
|
||||
bool is_device_path(const char *path);
|
||||
|
||||
int systemd_installation_has_version(const char *root, unsigned minimal_version);
|
||||
|
|
|
@ -511,7 +511,24 @@ static void test_hidden_or_backup_file(void) {
|
|||
assert_se(!hidden_or_backup_file("test.dpkg-old.foo"));
|
||||
}
|
||||
|
||||
static void test_systemd_installation_has_version(const char *path) {
|
||||
int r;
|
||||
const unsigned versions[] = {0, 231, atoi(PACKAGE_VERSION), 999};
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(versions); i++) {
|
||||
r = systemd_installation_has_version(path, versions[i]);
|
||||
assert_se(r >= 0);
|
||||
log_info("%s has systemd >= %u: %s",
|
||||
path ?: "Current installation", versions[i], yes_no(r));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
log_set_max_level(LOG_DEBUG);
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
test_path();
|
||||
test_find_binary(argv[0]);
|
||||
test_prefixes();
|
||||
|
@ -526,5 +543,7 @@ int main(int argc, char **argv) {
|
|||
test_filename_is_valid();
|
||||
test_hidden_or_backup_file();
|
||||
|
||||
test_systemd_installation_has_version(argv[1]); /* NULL is OK */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue