]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
c2f1db8f | 2 | #pragma once |
ed5bcfbe | 3 | |
1cf40697 | 4 | #include <syslog.h> |
ed5bcfbe | 5 | |
69a283c5 | 6 | #include "alloc-util.h" |
7a30bc9a | 7 | #include "conf-parser-forward.h" |
69a283c5 | 8 | #include "forward.h" |
a8fbdf54 | 9 | #include "log.h" |
e8e581bf | 10 | |
bcde742e LP |
11 | /* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */ |
12 | ||
13 | typedef enum ConfigParseFlags { | |
94a404cb | 14 | CONFIG_PARSE_RELAXED = 1 << 0, /* Do not warn about unknown non-extension fields */ |
7ade8982 | 15 | CONFIG_PARSE_WARN = 1 << 1, /* Emit non-debug messages */ |
bcde742e | 16 | } ConfigParseFlags; |
ed5bcfbe | 17 | |
f975e971 LP |
18 | /* Wraps information for parsing a specific configuration variable, to |
19 | * be stored in a simple array */ | |
20 | typedef struct ConfigTableItem { | |
21 | const char *section; /* Section */ | |
22 | const char *lvalue; /* Name of the variable */ | |
23 | ConfigParserCallback parse; /* Function that is called to parse the variable's value */ | |
24 | int ltype; /* Distinguish different variables passed to the same callback */ | |
25 | void *data; /* Where to store the variable's data */ | |
26 | } ConfigTableItem; | |
27 | ||
28 | /* Wraps information for parsing a specific configuration variable, to | |
e5a7f173 | 29 | * be stored in a gperf perfect hashtable */ |
f975e971 LP |
30 | typedef struct ConfigPerfItem { |
31 | const char *section_and_lvalue; /* Section + "." + name of the variable */ | |
32 | ConfigParserCallback parse; /* Function that is called to parse the variable's value */ | |
33 | int ltype; /* Distinguish different variables passed to the same callback */ | |
34 | size_t offset; /* Offset where to store data, from the beginning of userdata */ | |
35 | } ConfigPerfItem; | |
36 | ||
37 | /* Prototype for a low-level gperf lookup function */ | |
5996cc34 | 38 | typedef const ConfigPerfItem* (*ConfigPerfItemLookup)(const char *section_and_lvalue, GPERF_LEN_TYPE length); |
f975e971 LP |
39 | |
40 | /* Prototype for a generic high-level lookup function */ | |
41 | typedef int (*ConfigItemLookup)( | |
e9f3d2d5 | 42 | const void *table, |
f975e971 LP |
43 | const char *section, |
44 | const char *lvalue, | |
0b954099 LP |
45 | ConfigParserCallback *ret_func, |
46 | int *ret_ltype, | |
47 | void **ret_data, | |
f975e971 LP |
48 | void *userdata); |
49 | ||
50 | /* Linear table search implementation of ConfigItemLookup, based on | |
51 | * ConfigTableItem arrays */ | |
0b954099 | 52 | int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *ret_func, int *ret_ltype, void **ret_data, void *userdata); |
f975e971 LP |
53 | |
54 | /* gperf implementation of ConfigItemLookup, based on gperf | |
55 | * ConfigPerfItem tables */ | |
0b954099 | 56 | int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *ret_func, int *ret_ltype, void **ret_data, void *userdata); |
f975e971 | 57 | |
43688c49 ZJS |
58 | int config_parse( |
59 | const char *unit, | |
60 | const char *filename, | |
61 | FILE *f, | |
4f9ff96a | 62 | const char *sections, /* nulstr */ |
43688c49 ZJS |
63 | ConfigItemLookup lookup, |
64 | const void *table, | |
bcde742e | 65 | ConfigParseFlags flags, |
4f9ff96a | 66 | void *userdata, |
8524db50 | 67 | struct stat *ret_stat); /* possibly NULL */ |
43688c49 | 68 | |
23bb31aa | 69 | int config_parse_many( |
8b8024f1 | 70 | const char* const* conf_files, /* possibly empty */ |
23bb31aa ZJS |
71 | const char* const* conf_file_dirs, |
72 | const char *dropin_dirname, | |
947f59ba | 73 | const char *root, |
d8a91c6b | 74 | const char *sections, /* nulstr */ |
23bb31aa ZJS |
75 | ConfigItemLookup lookup, |
76 | const void *table, | |
bcde742e | 77 | ConfigParseFlags flags, |
9f83091e | 78 | void *userdata, |
ead3a3fc RP |
79 | Hashmap **ret_stats_by_path, /* possibly NULL */ |
80 | char ***ret_drop_in_files); /* possibly NULL */ | |
23bb31aa | 81 | |
e7e52ff9 ZJS |
82 | int config_parse_standard_file_with_dropins_full( |
83 | const char *root, | |
84 | const char *main_file, /* A path like "systemd/frobnicator.conf" */ | |
85 | const char *sections, | |
86 | ConfigItemLookup lookup, | |
87 | const void *table, | |
88 | ConfigParseFlags flags, | |
89 | void *userdata, | |
90 | Hashmap **ret_stats_by_path, /* possibly NULL */ | |
91 | char ***ret_dropin_files); /* possibly NULL */ | |
92 | ||
6378f257 ZJS |
93 | static inline int config_parse_standard_file_with_dropins( |
94 | const char *main_file, /* A path like "systemd/frobnicator.conf" */ | |
95 | const char *sections, /* nulstr */ | |
96 | ConfigItemLookup lookup, | |
97 | const void *table, | |
98 | ConfigParseFlags flags, | |
99 | void *userdata) { | |
100 | return config_parse_standard_file_with_dropins_full( | |
101 | /* root= */ NULL, | |
102 | main_file, | |
103 | sections, | |
104 | lookup, | |
105 | table, | |
106 | flags, | |
107 | userdata, | |
108 | /* ret_stats_by_path= */ NULL, | |
109 | /* ret_dropin_files= */ NULL); | |
110 | } | |
111 | ||
bdb2d3c6 YW |
112 | int config_get_stats_by_path( |
113 | const char *suffix, | |
114 | const char *root, | |
115 | unsigned flags, | |
116 | const char* const* dirs, | |
3f4dfd9d | 117 | bool check_dropins, |
bdb2d3c6 YW |
118 | Hashmap **ret); |
119 | ||
acfbd71c | 120 | int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const struct stat *st); |
bdb2d3c6 YW |
121 | bool stats_by_path_equal(Hashmap *a, Hashmap *b); |
122 | ||
152b8a4e YW |
123 | typedef struct ConfigSectionParser { |
124 | ConfigParserCallback parser; | |
125 | int ltype; | |
126 | size_t offset; | |
127 | } ConfigSectionParser; | |
128 | ||
129 | int config_section_parse( | |
130 | const ConfigSectionParser *parsers, | |
131 | size_t n_parsers, | |
132 | const char *unit, | |
133 | const char *filename, | |
134 | unsigned line, | |
135 | const char *section, | |
136 | unsigned section_line, | |
137 | const char *lvalue, | |
138 | int ltype, | |
139 | const char *rvalue, | |
140 | void *userdata); | |
141 | ||
307fe3cd YW |
142 | static inline ConfigSection* config_section_free(ConfigSection *cs) { |
143 | return mfree(cs); | |
144 | } | |
145 | DEFINE_TRIVIAL_CLEANUP_FUNC(ConfigSection*, config_section_free); | |
146 | ||
08ca764d | 147 | int config_section_new(const char *filename, unsigned line, ConfigSection **ret); |
b46d1694 YW |
148 | |
149 | void config_section_hash_func(const ConfigSection *c, struct siphash *state); | |
150 | int config_section_compare_func(const ConfigSection *x, const ConfigSection *y); | |
307fe3cd | 151 | extern const struct hash_ops config_section_hash_ops; |
b46d1694 | 152 | |
69a283c5 DDM |
153 | int hashmap_by_section_find_unused_line(Hashmap *entries_by_section, const char *filename, unsigned *ret); |
154 | int ordered_hashmap_by_section_find_unused_line(OrderedHashmap *entries_by_section, const char *filename, unsigned *ret); | |
307fe3cd YW |
155 | |
156 | static inline bool section_is_invalid(ConfigSection *section) { | |
157 | /* If this returns false, then it does _not_ mean the section is valid. */ | |
158 | ||
159 | if (!section) | |
160 | return false; | |
161 | ||
162 | return section->invalid; | |
163 | } | |
164 | ||
75f59c6e YW |
165 | #define log_section_full_errno_zerook(section, level, error, ...) \ |
166 | ({ \ | |
167 | const ConfigSection *_s = (section); \ | |
168 | log_syntax(/* unit = */ NULL, \ | |
169 | level, \ | |
170 | _s ? _s->filename : NULL, \ | |
171 | _s ? _s->line : 0, \ | |
172 | error, \ | |
173 | __VA_ARGS__); \ | |
174 | }) | |
175 | ||
176 | #define log_section_full_errno(section, level, error, ...) \ | |
177 | ({ \ | |
178 | int _error = (error); \ | |
179 | ASSERT_NON_ZERO(_error); \ | |
180 | log_section_full_errno_zerook(section, level, _error, __VA_ARGS__); \ | |
181 | }) | |
182 | ||
183 | #define log_section_full(section, level, fmt, ...) \ | |
184 | ({ \ | |
185 | if (BUILD_MODE_DEVELOPER) \ | |
186 | assert(!strstr(fmt, "%m")); \ | |
187 | (void) log_section_full_errno_zerook(section, level, 0, fmt, ##__VA_ARGS__); \ | |
188 | }) | |
189 | ||
190 | #define log_section_debug(section, ...) log_section_full(section, LOG_DEBUG, __VA_ARGS__) | |
191 | #define log_section_info(section, ...) log_section_full(section, LOG_INFO, __VA_ARGS__) | |
192 | #define log_section_notice(section, ...) log_section_full(section, LOG_NOTICE, __VA_ARGS__) | |
193 | #define log_section_warning(section, ...) log_section_full(section, LOG_WARNING, __VA_ARGS__) | |
194 | #define log_section_error(section, ...) log_section_full(section, LOG_ERR, __VA_ARGS__) | |
195 | ||
196 | #define log_section_debug_errno(section, error, ...) log_section_full_errno(section, LOG_DEBUG, error, __VA_ARGS__) | |
197 | #define log_section_info_errno(section, error, ...) log_section_full_errno(section, LOG_INFO, error, __VA_ARGS__) | |
198 | #define log_section_notice_errno(section, error, ...) log_section_full_errno(section, LOG_NOTICE, error, __VA_ARGS__) | |
199 | #define log_section_warning_errno(section, error, ...) log_section_full_errno(section, LOG_WARNING, error, __VA_ARGS__) | |
200 | #define log_section_error_errno(section, error, ...) log_section_full_errno(section, LOG_ERR, error, __VA_ARGS__) | |
201 | ||
1f12b48a LP |
202 | CONFIG_PARSER_PROTOTYPE(config_parse_int); |
203 | CONFIG_PARSER_PROTOTYPE(config_parse_unsigned); | |
204 | CONFIG_PARSER_PROTOTYPE(config_parse_long); | |
205 | CONFIG_PARSER_PROTOTYPE(config_parse_uint8); | |
206 | CONFIG_PARSER_PROTOTYPE(config_parse_uint16); | |
207 | CONFIG_PARSER_PROTOTYPE(config_parse_uint32); | |
b57ebc60 | 208 | CONFIG_PARSER_PROTOTYPE(config_parse_int32); |
1f12b48a LP |
209 | CONFIG_PARSER_PROTOTYPE(config_parse_uint64); |
210 | CONFIG_PARSER_PROTOTYPE(config_parse_double); | |
211 | CONFIG_PARSER_PROTOTYPE(config_parse_iec_size); | |
50299121 | 212 | CONFIG_PARSER_PROTOTYPE(config_parse_si_uint64); |
1f12b48a | 213 | CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64); |
6e8791a0 | 214 | CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64_infinity); |
1f12b48a | 215 | CONFIG_PARSER_PROTOTYPE(config_parse_bool); |
6db311fd | 216 | CONFIG_PARSER_PROTOTYPE(config_parse_uint32_flag); |
ff616da4 | 217 | CONFIG_PARSER_PROTOTYPE(config_parse_uint32_invert_flag); |
12963533 | 218 | CONFIG_PARSER_PROTOTYPE(config_parse_id128); |
1f12b48a LP |
219 | CONFIG_PARSER_PROTOTYPE(config_parse_tristate); |
220 | CONFIG_PARSER_PROTOTYPE(config_parse_string); | |
fa787a13 YW |
221 | CONFIG_PARSER_PROTOTYPE(config_parse_dns_name); |
222 | CONFIG_PARSER_PROTOTYPE(config_parse_hostname); | |
1f12b48a LP |
223 | CONFIG_PARSER_PROTOTYPE(config_parse_path); |
224 | CONFIG_PARSER_PROTOTYPE(config_parse_strv); | |
225 | CONFIG_PARSER_PROTOTYPE(config_parse_sec); | |
7b61ce3c | 226 | CONFIG_PARSER_PROTOTYPE(config_parse_sec_def_infinity); |
dc653bf4 | 227 | CONFIG_PARSER_PROTOTYPE(config_parse_sec_def_unset); |
1f12b48a LP |
228 | CONFIG_PARSER_PROTOTYPE(config_parse_nsec); |
229 | CONFIG_PARSER_PROTOTYPE(config_parse_mode); | |
230 | CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat); | |
231 | CONFIG_PARSER_PROTOTYPE(config_parse_log_facility); | |
232 | CONFIG_PARSER_PROTOTYPE(config_parse_log_level); | |
233 | CONFIG_PARSER_PROTOTYPE(config_parse_signal); | |
234 | CONFIG_PARSER_PROTOTYPE(config_parse_personality); | |
c07b23ca | 235 | CONFIG_PARSER_PROTOTYPE(config_parse_permille); |
1f12b48a | 236 | CONFIG_PARSER_PROTOTYPE(config_parse_ifname); |
a5053a15 | 237 | CONFIG_PARSER_PROTOTYPE(config_parse_ifnames); |
1f12b48a | 238 | CONFIG_PARSER_PROTOTYPE(config_parse_ip_port); |
1f12b48a LP |
239 | CONFIG_PARSER_PROTOTYPE(config_parse_mtu); |
240 | CONFIG_PARSER_PROTOTYPE(config_parse_rlimit); | |
4df4df5b | 241 | CONFIG_PARSER_PROTOTYPE(config_parse_vlanprotocol); |
99628f36 YW |
242 | CONFIG_PARSER_PROTOTYPE(config_parse_hw_addr); |
243 | CONFIG_PARSER_PROTOTYPE(config_parse_hw_addrs); | |
aa4f7653 YW |
244 | CONFIG_PARSER_PROTOTYPE(config_parse_ether_addr); |
245 | CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs); | |
cf074772 | 246 | CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null); |
0ea6d55a | 247 | CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_data); |
8cde9f6c | 248 | CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_prefix); |
9de5e321 | 249 | CONFIG_PARSER_PROTOTYPE(config_parse_percent); |
0a9f9344 | 250 | CONFIG_PARSER_PROTOTYPE(config_parse_permyriad); |
65a0ede2 | 251 | CONFIG_PARSER_PROTOTYPE(config_parse_pid); |
4ee8176f | 252 | CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0); |
f72e851f | 253 | CONFIG_PARSER_PROTOTYPE(config_parse_timezone); |
0e10c3d8 | 254 | CONFIG_PARSER_PROTOTYPE(config_parse_calendar); |
f7a1e57e | 255 | CONFIG_PARSER_PROTOTYPE(config_parse_ip_protocol); |
015a3b8c | 256 | CONFIG_PARSER_PROTOTYPE(config_parse_loadavg); |
e8e581bf | 257 | |
1e35c5ab RP |
258 | typedef enum Disabled { |
259 | DISABLED_CONFIGURATION, | |
260 | DISABLED_LEGACY, | |
261 | DISABLED_EXPERIMENTAL, | |
262 | } Disabled; | |
263 | ||
3f87eaa5 YW |
264 | typedef enum ConfigParseStringFlags { |
265 | CONFIG_PARSE_STRING_SAFE = 1 << 0, | |
e289ce7f YW |
266 | CONFIG_PARSE_STRING_ASCII = 1 << 1, |
267 | ||
268 | CONFIG_PARSE_STRING_SAFE_AND_ASCII = CONFIG_PARSE_STRING_SAFE | CONFIG_PARSE_STRING_ASCII, | |
3f87eaa5 YW |
269 | } ConfigParseStringFlags; |
270 | ||
42efe5be | 271 | #define DEFINE_CONFIG_PARSE(function, parser) \ |
2d1729ca YW |
272 | CONFIG_PARSER_PROTOTYPE(function) { \ |
273 | int *i = data, r; \ | |
274 | \ | |
275 | assert(filename); \ | |
276 | assert(lvalue); \ | |
277 | assert(rvalue); \ | |
278 | assert(data); \ | |
279 | \ | |
280 | r = parser(rvalue); \ | |
42efe5be YW |
281 | if (r < 0) \ |
282 | return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); \ | |
2d1729ca YW |
283 | \ |
284 | *i = r; \ | |
f4810fe2 | 285 | return 1; \ |
2d1729ca YW |
286 | } |
287 | ||
42efe5be | 288 | #define DEFINE_CONFIG_PARSE_PTR(function, parser, type) \ |
2d1729ca | 289 | CONFIG_PARSER_PROTOTYPE(function) { \ |
99534007 | 290 | type *i = ASSERT_PTR(data); \ |
2d1729ca YW |
291 | int r; \ |
292 | \ | |
293 | assert(filename); \ | |
294 | assert(lvalue); \ | |
295 | assert(rvalue); \ | |
2d1729ca YW |
296 | \ |
297 | r = parser(rvalue, i); \ | |
298 | if (r < 0) \ | |
42efe5be | 299 | return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); \ |
2d1729ca | 300 | \ |
f4810fe2 | 301 | return 1; \ |
2d1729ca YW |
302 | } |
303 | ||
42efe5be | 304 | #define DEFINE_CONFIG_PARSE_ENUM_FULL(function, from_string, type) \ |
2d1729ca YW |
305 | CONFIG_PARSER_PROTOTYPE(function) { \ |
306 | type *i = data, x; \ | |
307 | \ | |
308 | assert(filename); \ | |
309 | assert(lvalue); \ | |
310 | assert(rvalue); \ | |
311 | assert(data); \ | |
312 | \ | |
a2b06dbe | 313 | x = from_string(rvalue); \ |
42efe5be YW |
314 | if (x < 0) \ |
315 | return log_syntax_parse_error(unit, filename, line, x, lvalue, rvalue); \ | |
2d1729ca YW |
316 | \ |
317 | *i = x; \ | |
f4810fe2 | 318 | return 1; \ |
2d1729ca YW |
319 | } |
320 | ||
42efe5be YW |
321 | #define DEFINE_CONFIG_PARSE_ENUM(function, name, type) \ |
322 | DEFINE_CONFIG_PARSE_ENUM_FULL(function, name##_from_string, type) | |
a2b06dbe | 323 | |
42efe5be | 324 | #define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value) \ |
1f12b48a | 325 | CONFIG_PARSER_PROTOTYPE(function) { \ |
487393e9 LP |
326 | type *i = data, x; \ |
327 | \ | |
328 | assert(filename); \ | |
329 | assert(lvalue); \ | |
330 | assert(rvalue); \ | |
331 | assert(data); \ | |
332 | \ | |
2d1729ca YW |
333 | if (isempty(rvalue)) { \ |
334 | *i = default_value; \ | |
f4810fe2 | 335 | return 1; \ |
2d1729ca YW |
336 | } \ |
337 | \ | |
338 | x = name##_from_string(rvalue); \ | |
42efe5be YW |
339 | if (x < 0) \ |
340 | return log_syntax_parse_error(unit, filename, line, x, lvalue, rvalue); \ | |
487393e9 LP |
341 | \ |
342 | *i = x; \ | |
f4810fe2 | 343 | return 1; \ |
487393e9 | 344 | } |
916484f5 | 345 | |
42efe5be | 346 | #define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid) \ |
1f12b48a | 347 | CONFIG_PARSER_PROTOTYPE(function) { \ |
99534007 | 348 | type **enums = ASSERT_PTR(data); \ |
77c10205 | 349 | _cleanup_free_ type *xs = NULL; \ |
3c8dc3a3 | 350 | size_t n = 0; \ |
ecaf258e | 351 | int r; \ |
916484f5 | 352 | \ |
916484f5 | 353 | assert(lvalue); \ |
916484f5 | 354 | \ |
ecaf258e | 355 | for (const char *p = rvalue;;) { \ |
916484f5 | 356 | _cleanup_free_ char *en = NULL; \ |
3c8dc3a3 | 357 | type x; \ |
916484f5 | 358 | \ |
ecaf258e | 359 | r = extract_first_word(&p, &en, NULL, 0); \ |
42efe5be YW |
360 | if (r < 0) \ |
361 | return log_syntax_parse_error(unit, filename, line, r, lvalue, rvalue); \ | |
ecaf258e ZJS |
362 | if (r == 0) \ |
363 | break; \ | |
916484f5 | 364 | \ |
0cbb768a YW |
365 | x = name##_from_string(en); \ |
366 | if (x < 0) { \ | |
367 | log_syntax(unit, LOG_WARNING, filename, line, x, \ | |
42efe5be YW |
368 | "Failed to parse %s in %s=, ignoring.", \ |
369 | en, lvalue); \ | |
916484f5 TG |
370 | continue; \ |
371 | } \ | |
372 | \ | |
3c8dc3a3 YW |
373 | FOREACH_ARRAY(i, xs, n) \ |
374 | if (*i == x) { \ | |
ecaf258e | 375 | log_syntax(unit, LOG_NOTICE, filename, line, 0, \ |
42efe5be YW |
376 | "Duplicate entry %s in %s=, ignoring.", \ |
377 | en, lvalue); \ | |
916484f5 | 378 | x = invalid; \ |
3c8dc3a3 | 379 | break; \ |
916484f5 | 380 | } \ |
916484f5 TG |
381 | \ |
382 | if (x == invalid) \ | |
383 | continue; \ | |
384 | \ | |
3c8dc3a3 YW |
385 | /* Allocate one more for the trailing 'invalid'. */ \ |
386 | if (!GREEDY_REALLOC(xs, n + 2)) \ | |
d96edb2c | 387 | return log_oom(); \ |
83e341a6 | 388 | \ |
3c8dc3a3 YW |
389 | xs[n++] = x; \ |
390 | } \ | |
391 | \ | |
392 | if (n <= 0) { \ | |
393 | /* An empty string, or invalid values only. */ \ | |
394 | *enums = mfree(*enums); \ | |
395 | return 1; \ | |
916484f5 TG |
396 | } \ |
397 | \ | |
3c8dc3a3 YW |
398 | /* Terminate with 'invalid' */ \ |
399 | xs[n] = invalid; \ | |
f4810fe2 YW |
400 | free_and_replace(*enums, xs); \ |
401 | return 1; \ | |
916484f5 | 402 | } |
851cdffd ZJS |
403 | |
404 | int config_parse_unsigned_bounded( | |
405 | const char *unit, | |
406 | const char *filename, | |
407 | unsigned line, | |
408 | const char *section, | |
409 | unsigned section_line, | |
6f12cb91 YW |
410 | const char *lvalue, |
411 | const char *rvalue, | |
851cdffd ZJS |
412 | unsigned min, |
413 | unsigned max, | |
414 | bool ignoring, | |
415 | unsigned *ret); | |
416 | ||
417 | static inline int config_parse_uint32_bounded( | |
418 | const char *unit, | |
419 | const char *filename, | |
420 | unsigned line, | |
421 | const char *section, | |
422 | unsigned section_line, | |
6f12cb91 YW |
423 | const char *lvalue, |
424 | const char *rvalue, | |
851cdffd ZJS |
425 | uint32_t min, |
426 | uint32_t max, | |
427 | bool ignoring, | |
428 | uint32_t *ret) { | |
429 | ||
430 | unsigned t; | |
431 | int r; | |
432 | ||
433 | r = config_parse_unsigned_bounded( | |
6f12cb91 | 434 | unit, filename, line, section, section_line, lvalue, rvalue, |
851cdffd ZJS |
435 | min, max, ignoring, |
436 | &t); | |
437 | if (r <= 0) | |
438 | return r; | |
439 | assert(t <= UINT32_MAX); | |
440 | *ret = t; | |
441 | return 1; | |
442 | } | |
443 | ||
444 | static inline int config_parse_uint16_bounded( | |
445 | const char *unit, | |
446 | const char *filename, | |
447 | unsigned line, | |
448 | const char *section, | |
449 | unsigned section_line, | |
6f12cb91 YW |
450 | const char *lvalue, |
451 | const char *rvalue, | |
851cdffd ZJS |
452 | uint16_t min, |
453 | uint16_t max, | |
454 | bool ignoring, | |
455 | uint16_t *ret) { | |
456 | ||
457 | unsigned t; | |
458 | int r; | |
459 | ||
460 | r = config_parse_unsigned_bounded( | |
6f12cb91 | 461 | unit, filename, line, section, section_line, lvalue, rvalue, |
851cdffd ZJS |
462 | min, max, ignoring, |
463 | &t); | |
464 | if (r <= 0) | |
465 | return r; | |
466 | assert(t <= UINT16_MAX); | |
467 | *ret = t; | |
468 | return 1; | |
469 | } | |
470 | ||
471 | static inline int config_parse_uint8_bounded( | |
472 | const char *unit, | |
473 | const char *filename, | |
474 | unsigned line, | |
475 | const char *section, | |
476 | unsigned section_line, | |
6f12cb91 YW |
477 | const char *lvalue, |
478 | const char *rvalue, | |
851cdffd ZJS |
479 | uint8_t min, |
480 | uint8_t max, | |
481 | bool ignoring, | |
482 | uint8_t *ret) { | |
483 | ||
484 | unsigned t; | |
485 | int r; | |
486 | ||
487 | r = config_parse_unsigned_bounded( | |
6f12cb91 | 488 | unit, filename, line, section, section_line, lvalue, rvalue, |
851cdffd ZJS |
489 | min, max, ignoring, |
490 | &t); | |
491 | if (r <= 0) | |
492 | return r; | |
493 | assert(t <= UINT8_MAX); | |
494 | *ret = t; | |
495 | return 1; | |
496 | } |