diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-05-17 16:28:45 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-05-19 09:07:34 +0200 |
commit | bc012a3e913075d14ac39d33a090c5dcddce2e09 (patch) | |
tree | aaca9e491b34bd4ca37edf12295b7bb04352827e /src/analyze | |
parent | fddad5f4a66a68682892e3fa7f22ec2689786d33 (diff) | |
download | systemd-bc012a3e913075d14ac39d33a090c5dcddce2e09.tar.gz |
analyze: add compare-versions
The interface, output, and exit status convention are all taken directly from
rpmdev-vercmp and dpkg --compare-versions. The implementation is different
though. See test-string-util for a list of known cases where we compare
strings incompatibly.
The idea is that this string comparison function will be declared as "the"
method to use for boot entry ordering in the specification and similar
uses. Thus it's nice to allow users to compare strings.
Diffstat (limited to 'src/analyze')
-rw-r--r-- | src/analyze/analyze-compare-versions.c | 47 | ||||
-rw-r--r-- | src/analyze/analyze-compare-versions.h | 3 | ||||
-rw-r--r-- | src/analyze/analyze.c | 4 | ||||
-rw-r--r-- | src/analyze/meson.build | 2 |
4 files changed, 56 insertions, 0 deletions
diff --git a/src/analyze/analyze-compare-versions.c b/src/analyze/analyze-compare-versions.c new file mode 100644 index 0000000000..9545326fa9 --- /dev/null +++ b/src/analyze/analyze-compare-versions.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include <stdio.h> + +#include "analyze-compare-versions.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" + +int verb_compare_versions(int argc, char *argv[], void *userdata) { + int r; + + assert(argc == 3 || argc == 4); + assert(argv); + + if (argc == 3) { + r = strverscmp_improved(ASSERT_PTR(argv[1]), ASSERT_PTR(argv[2])); + printf("%s %s %s\n", + argv[1], + r < 0 ? "<" : r > 0 ? ">" : "==", + argv[2]); + + /* This matches the exit convention used by rpmdev-vercmp. + * We don't use named values because 11 and 12 don't have names. */ + return r < 0 ? 12 : r > 0 ? 11 : 0; + + } else { + const char *op = ASSERT_PTR(argv[2]); + + r = strverscmp_improved(ASSERT_PTR(argv[1]), ASSERT_PTR(argv[3])); + + if (STR_IN_SET(op, "lt", "<")) + return r < 0 ? EXIT_SUCCESS : EXIT_FAILURE; + if (STR_IN_SET(op, "le", "<=")) + return r <= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + if (STR_IN_SET(op, "eq", "==")) + return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + if (STR_IN_SET(op, "ne", "!=")) + return r != 0 ? EXIT_SUCCESS : EXIT_FAILURE; + if (STR_IN_SET(op, "ge", ">=")) + return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; + if (STR_IN_SET(op, "gt", ">")) + return r > 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown operator \"%s\".", op); + } +} diff --git a/src/analyze/analyze-compare-versions.h b/src/analyze/analyze-compare-versions.h new file mode 100644 index 0000000000..ac90ede2f0 --- /dev/null +++ b/src/analyze/analyze-compare-versions.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +int verb_compare_versions(int argc, char *argv[], void *userdata); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 2935ecea7a..4968946963 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -35,6 +35,7 @@ #include "analyze-timestamp.h" #include "analyze-unit-files.h" #include "analyze-unit-paths.h" +#include "analyze-compare-versions.h" #include "analyze-verify.h" #include "bus-error.h" #include "bus-locator.h" @@ -199,6 +200,8 @@ static int help(int argc, char *argv[], void *userdata) { " syscall-filter [NAME...] List syscalls in seccomp filters\n" " filesystems [NAME...] List known filesystems\n" " condition CONDITION... Evaluate conditions and asserts\n" + " compare-versions VERSION1 [OP] VERSION2\n" + " Compare two version strings\n" " verify FILE... Check unit files for correctness\n" " calendar SPEC... Validate repetitive calendar time\n" " events\n" @@ -564,6 +567,7 @@ static int run(int argc, char *argv[]) { { "capability", VERB_ANY, VERB_ANY, 0, verb_capabilities }, { "filesystems", VERB_ANY, VERB_ANY, 0, verb_filesystems }, { "condition", VERB_ANY, VERB_ANY, 0, verb_condition }, + { "compare-versions", 3, 4, 0, verb_compare_versions }, { "verify", 2, VERB_ANY, 0, verb_verify }, { "calendar", 2, VERB_ANY, 0, verb_calendar }, { "timestamp", 2, VERB_ANY, 0, verb_timestamp }, diff --git a/src/analyze/meson.build b/src/analyze/meson.build index f0cfbb195e..24ef94149c 100644 --- a/src/analyze/meson.build +++ b/src/analyze/meson.build @@ -9,6 +9,8 @@ systemd_analyze_sources = files( 'analyze-capability.h', 'analyze-cat-config.c', 'analyze-cat-config.h', + 'analyze-compare-versions.c', + 'analyze-compare-versions.h', 'analyze-condition.c', 'analyze-condition.h', 'analyze-critical-chain.c', |