/src/systemd/src/shared/compare-operator.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | |
3 | | #include <fnmatch.h> |
4 | | |
5 | | #include "compare-operator.h" |
6 | | #include "string-util.h" |
7 | | |
8 | 12.2k | CompareOperator parse_compare_operator(const char **s, CompareOperatorParseFlags flags) { |
9 | | |
10 | 12.2k | static const struct { |
11 | 12.2k | CompareOperator op; |
12 | 12.2k | const char *str; |
13 | 12.2k | CompareOperatorParseFlags valid_mask; /* If this operator appears when flags in mask not set, fail */ |
14 | 12.2k | CompareOperatorParseFlags need_mask; /* Skip over this operator when flags in mask not set */ |
15 | 12.2k | } table[] = { |
16 | 12.2k | { COMPARE_FNMATCH_EQUAL, "$=", .valid_mask = COMPARE_ALLOW_FNMATCH }, |
17 | 12.2k | { COMPARE_FNMATCH_UNEQUAL, "!$=", .valid_mask = COMPARE_ALLOW_FNMATCH }, |
18 | | |
19 | 12.2k | { COMPARE_UNEQUAL, "<>" }, |
20 | 12.2k | { COMPARE_LOWER_OR_EQUAL, "<=" }, |
21 | 12.2k | { COMPARE_GREATER_OR_EQUAL, ">=" }, |
22 | 12.2k | { COMPARE_LOWER, "<" }, |
23 | 12.2k | { COMPARE_GREATER, ">" }, |
24 | 12.2k | { COMPARE_EQUAL, "==" }, |
25 | 12.2k | { COMPARE_STRING_EQUAL, "=", .need_mask = COMPARE_EQUAL_BY_STRING }, |
26 | 12.2k | { COMPARE_EQUAL, "=" }, |
27 | 12.2k | { COMPARE_STRING_UNEQUAL, "!=", .need_mask = COMPARE_EQUAL_BY_STRING }, |
28 | 12.2k | { COMPARE_UNEQUAL, "!=" }, |
29 | | |
30 | 12.2k | { COMPARE_LOWER, "lt", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
31 | 12.2k | { COMPARE_LOWER_OR_EQUAL, "le", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
32 | 12.2k | { COMPARE_EQUAL, "eq", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
33 | 12.2k | { COMPARE_UNEQUAL, "ne", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
34 | 12.2k | { COMPARE_GREATER_OR_EQUAL, "ge", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
35 | 12.2k | { COMPARE_GREATER, "gt", .valid_mask = COMPARE_ALLOW_TEXTUAL }, |
36 | 12.2k | }; |
37 | | |
38 | 12.2k | assert(s); |
39 | | |
40 | 12.2k | if (!*s) /* Hmm, we already reached the end, for example because extract_first_word() and |
41 | | * parse_compare_operator() are use on the same string? */ |
42 | 0 | return _COMPARE_OPERATOR_INVALID; |
43 | | |
44 | 94.1k | FOREACH_ELEMENT(i, table) { |
45 | 94.1k | const char *e; |
46 | | |
47 | 94.1k | if (i->need_mask != 0 && !FLAGS_SET(flags, i->need_mask)) |
48 | 0 | continue; |
49 | | |
50 | 94.1k | e = startswith(*s, i->str); |
51 | 94.1k | if (e) { |
52 | 10.6k | if (i->valid_mask != 0 && !FLAGS_SET(flags, i->valid_mask)) |
53 | 3 | return _COMPARE_OPERATOR_INVALID; |
54 | | |
55 | 10.6k | *s = e; |
56 | 10.6k | return i->op; |
57 | 10.6k | } |
58 | 94.1k | } |
59 | | |
60 | 1.58k | return _COMPARE_OPERATOR_INVALID; |
61 | 12.2k | } |
62 | | |
63 | 8.80k | int test_order(int k, CompareOperator op) { |
64 | | |
65 | 8.80k | switch (op) { |
66 | | |
67 | 2.42k | case COMPARE_LOWER: |
68 | 2.42k | return k < 0; |
69 | | |
70 | 1.07k | case COMPARE_LOWER_OR_EQUAL: |
71 | 1.07k | return k <= 0; |
72 | | |
73 | 26 | case COMPARE_EQUAL: |
74 | 26 | return k == 0; |
75 | | |
76 | 559 | case COMPARE_UNEQUAL: |
77 | 559 | return k != 0; |
78 | | |
79 | 664 | case COMPARE_GREATER_OR_EQUAL: |
80 | 664 | return k >= 0; |
81 | | |
82 | 4.06k | case COMPARE_GREATER: |
83 | 4.06k | return k > 0; |
84 | | |
85 | 0 | default: |
86 | 0 | return -EINVAL; |
87 | 8.80k | } |
88 | 8.80k | } |
89 | | |
90 | | int version_or_fnmatch_compare( |
91 | | CompareOperator op, |
92 | | const char *a, |
93 | 12.0k | const char *b) { |
94 | 12.0k | int r; |
95 | | |
96 | 12.0k | switch (op) { |
97 | | |
98 | 159 | case COMPARE_STRING_EQUAL: |
99 | 159 | return streq_ptr(a, b); |
100 | | |
101 | 884 | case COMPARE_STRING_UNEQUAL: |
102 | 884 | return !streq_ptr(a, b); |
103 | | |
104 | 1.72k | case COMPARE_FNMATCH_EQUAL: |
105 | 1.72k | r = fnmatch(b, a, 0); |
106 | 1.72k | return r == 0 ? true : |
107 | 1.72k | r == FNM_NOMATCH ? false : -EINVAL; |
108 | | |
109 | 462 | case COMPARE_FNMATCH_UNEQUAL: |
110 | 462 | r = fnmatch(b, a, 0); |
111 | 462 | return r == FNM_NOMATCH ? true: |
112 | 462 | r == 0 ? false : -EINVAL; |
113 | | |
114 | 8.80k | case _COMPARE_OPERATOR_ORDER_FIRST..._COMPARE_OPERATOR_ORDER_LAST: |
115 | 8.80k | return test_order(strverscmp_improved(a, b), op); |
116 | | |
117 | 0 | default: |
118 | | return -EINVAL; |
119 | 12.0k | } |
120 | 12.0k | } |