1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "analyze-compare-versions.h"
6 #include "compare-operator.h"
8 #include "string-util.h"
11 int verb_compare_versions(int argc
, char *argv
[], void *userdata
) {
12 const char *v1
= ASSERT_PTR(argv
[1]), *v2
= ASSERT_PTR(argv
[argc
-1]);
15 assert(IN_SET(argc
, 3, 4));
18 /* We only output a warning on invalid version strings (instead of failing), since the comparison
19 * functions try to handle invalid strings gracefully and it's still interesting to see what the
20 * comparison result will be. */
21 if (!version_is_valid_versionspec(v1
))
22 log_warning("Version string 1 contains disallowed characters, they will be treated as separators: %s", v1
);
23 if (!version_is_valid_versionspec(v2
))
24 log_warning("Version string 2 contains disallowed characters, they will be treated as separators: %s", v2
);
27 r
= strverscmp_improved(v1
, v2
);
29 isempty(v1
) ? "''" : v1
,
30 comparison_operator(r
),
31 isempty(v2
) ? "''" : v2
);
33 /* This matches the exit convention used by rpmdev-vercmp.
34 * We don't use named values because 11 and 12 don't have names. */
35 return r
< 0 ? 12 : r
> 0 ? 11 : 0;
38 const char *op
= ASSERT_PTR(argv
[2]);
39 CompareOperator
operator;
42 operator = parse_compare_operator(&op
, COMPARE_ALLOW_TEXTUAL
);
43 if (operator < 0 || !isempty(op
))
44 return log_error_errno(SYNTHETIC_ERRNO(EINVAL
), "Unknown operator \"%s\".", op
);
46 r
= version_or_fnmatch_compare(operator, v1
, v2
);
48 return log_error_errno(r
, "Failed to compare versions: %m");
50 return r
? EXIT_SUCCESS
: EXIT_FAILURE
;