]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/parse-helpers.c
hwdb: Add mapping for Xiaomi Mipad 2 bottom bezel capacitive buttons
[thirdparty/systemd.git] / src / shared / parse-helpers.c
CommitLineData
c3eaba2d
ZJS
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3fb72d63
ZJS
3#include "af-list.h"
4#include "extract-word.h"
5#include "ip-protocol-list.h"
c3eaba2d 6#include "log.h"
0d133284 7#include "mountpoint-util.h"
c3eaba2d 8#include "parse-helpers.h"
3fb72d63 9#include "parse-util.h"
c3eaba2d
ZJS
10#include "path-util.h"
11#include "utf8.h"
12
13int path_simplify_and_warn(
14 char *path,
0d133284 15 PathSimplifyWarnFlags flags,
c3eaba2d
ZJS
16 const char *unit,
17 const char *filename,
18 unsigned line,
19 const char *lvalue) {
20
0d133284 21 bool fatal = flags & PATH_CHECK_FATAL;
e0f6eaeb 22 int level = fatal ? LOG_ERR : LOG_WARNING;
c3eaba2d 23
0d133284
LP
24 assert(path);
25 assert(!FLAGS_SET(flags, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
26 assert(lvalue);
c3eaba2d
ZJS
27
28 if (!utf8_is_valid(path))
29 return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
30
0d133284 31 if (flags & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
c3eaba2d
ZJS
32 bool absolute;
33
34 absolute = path_is_absolute(path);
35
0d133284 36 if (!absolute && (flags & PATH_CHECK_ABSOLUTE))
e0f6eaeb 37 return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
c3eaba2d
ZJS
38 "%s= path is not absolute%s: %s",
39 lvalue, fatal ? "" : ", ignoring", path);
40
0d133284 41 if (absolute && (flags & PATH_CHECK_RELATIVE))
e0f6eaeb 42 return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
c3eaba2d
ZJS
43 "%s= path is absolute%s: %s",
44 lvalue, fatal ? "" : ", ignoring", path);
45 }
46
0d133284 47 path_simplify_full(path, flags & PATH_KEEP_TRAILING_SLASH ? PATH_SIMPLIFY_KEEP_TRAILING_SLASH : 0);
c3eaba2d
ZJS
48
49 if (!path_is_valid(path))
e0f6eaeb 50 return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
c3eaba2d
ZJS
51 "%s= path has invalid length (%zu bytes)%s.",
52 lvalue, strlen(path), fatal ? "" : ", ignoring");
53
54 if (!path_is_normalized(path))
e0f6eaeb 55 return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
c3eaba2d
ZJS
56 "%s= path is not normalized%s: %s",
57 lvalue, fatal ? "" : ", ignoring", path);
58
0d133284 59 if (FLAGS_SET(flags, PATH_CHECK_NON_API_VFS) && path_below_api_vfs(path))
e0f6eaeb 60 return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
0d133284
LP
61 "%s= path is below API VFS%s: %s",
62 lvalue, fatal ? ", refusing" : ", ignoring",
63 path);
64
c3eaba2d
ZJS
65 return 0;
66}
3fb72d63
ZJS
67
68static int parse_af_token(
69 const char *token,
70 int *family,
71 int *ip_protocol,
72 uint16_t *nr_ports,
73 uint16_t *port_min) {
74
75 int af;
76
77 assert(token);
78 assert(family);
79
80 af = af_from_ipv4_ipv6(token);
81 if (af == AF_UNSPEC)
82 return -EINVAL;
83
84 *family = af;
85 return 0;
86}
87
88static int parse_ip_protocol_token(
89 const char *token,
90 int *family,
91 int *ip_protocol,
92 uint16_t *nr_ports,
93 uint16_t *port_min) {
94
95 int proto;
96
97 assert(token);
98 assert(ip_protocol);
99
100 proto = ip_protocol_from_tcp_udp(token);
101 if (proto < 0)
102 return -EINVAL;
103
104 *ip_protocol = proto;
105 return 0;
106}
107
108static int parse_ip_ports_token(
109 const char *token,
110 int *family,
111 int *ip_protocol,
112 uint16_t *nr_ports,
113 uint16_t *port_min) {
114
dcfac3a3 115 int r;
116
3fb72d63
ZJS
117 assert(token);
118 assert(nr_ports);
119 assert(port_min);
120
121 if (streq(token, "any"))
122 *nr_ports = *port_min = 0;
123 else {
124 uint16_t mn = 0, mx = 0;
dcfac3a3 125 r = parse_ip_port_range(token, &mn, &mx, /* allow_zero = */ true);
3fb72d63
ZJS
126 if (r < 0)
127 return r;
128
129 *nr_ports = mx - mn + 1;
130 *port_min = mn;
131 }
132
133 return 0;
134}
135
136typedef int (*parse_token_f)(
137 const char *,
138 int *,
139 int *,
140 uint16_t *,
141 uint16_t *);
142
143int parse_socket_bind_item(
144 const char *str,
145 int *address_family,
146 int *ip_protocol,
147 uint16_t *nr_ports,
148 uint16_t *port_min) {
149
150 /* Order of token parsers is important. */
151 const parse_token_f parsers[] = {
152 &parse_af_token,
153 &parse_ip_protocol_token,
154 &parse_ip_ports_token,
155 };
156 parse_token_f const *parser_ptr = parsers;
157 int af = AF_UNSPEC, proto = 0, r;
158 uint16_t nr = 0, mn = 0;
99534007 159 const char *p = ASSERT_PTR(str);
3fb72d63 160
3fb72d63
ZJS
161 assert(address_family);
162 assert(ip_protocol);
163 assert(nr_ports);
164 assert(port_min);
165
166 if (isempty(p))
167 return -EINVAL;
168
169 for (;;) {
170 _cleanup_free_ char *token = NULL;
171
172 r = extract_first_word(&p, &token, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
173 if (r == 0)
174 break;
175 if (r < 0)
176 return r;
177
178 if (isempty(token))
179 return -EINVAL;
180
181 while (parser_ptr != parsers + ELEMENTSOF(parsers)) {
182 r = (*parser_ptr)(token, &af, &proto, &nr, &mn);
183 if (r == -ENOMEM)
184 return r;
185
186 ++parser_ptr;
187 /* Continue to next token if parsing succeeded,
188 * otherwise apply next parser to the same token.
189 */
190 if (r >= 0)
191 break;
192 }
193 if (parser_ptr == parsers + ELEMENTSOF(parsers))
194 break;
195 }
196
197 /* Failed to parse a token. */
198 if (r < 0)
199 return r;
200
201 /* Parsers applied successfully, but end of the string not reached. */
202 if (p)
203 return -EINVAL;
204
205 *address_family = af;
206 *ip_protocol = proto;
207 *nr_ports = nr;
208 *port_min = mn;
dcfac3a3 209
3fb72d63
ZJS
210 return 0;
211}
d7085bcc
FS
212
213int config_parse_path_or_ignore(
214 const char *unit,
215 const char *filename,
216 unsigned line,
217 const char *section,
218 unsigned section_line,
219 const char *lvalue,
220 int ltype,
221 const char *rvalue,
222 void *data,
223 void *userdata) {
224
225 _cleanup_free_ char *n = NULL;
226 bool fatal = ltype;
227 char **s = ASSERT_PTR(data);
228 int r;
229
230 assert(filename);
231 assert(lvalue);
232 assert(rvalue);
233
234 if (isempty(rvalue))
235 goto finalize;
236
237 n = strdup(rvalue);
238 if (!n)
239 return log_oom();
240
241 if (streq(n, "-"))
242 goto finalize;
243
244 r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
245 if (r < 0)
246 return fatal ? -ENOEXEC : 0;
247
248finalize:
249 return free_and_replace(*s, n);
250}