• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14895667988

07 May 2025 08:57PM UTC coverage: 72.225% (-0.007%) from 72.232%
14895667988

push

github

yuwata
network: log_link_message_debug_errno() automatically append %m if necessary

Follow-up for d28746ef5.
Fixes CID#1609753.

0 of 1 new or added line in 1 file covered. (0.0%)

20297 existing lines in 338 files now uncovered.

297407 of 411780 relevant lines covered (72.22%)

695716.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.33
/src/shared/parse-helpers.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/socket.h>
4

5
#include "af-list.h"
6
#include "alloc-util.h"
7
#include "extract-word.h"
8
#include "ip-protocol-list.h"
9
#include "log.h"
10
#include "mountpoint-util.h"
11
#include "parse-helpers.h"
12
#include "parse-util.h"
13
#include "path-util.h"
14
#include "string-util.h"
15
#include "utf8.h"
16

17
static bool validate_api_vfs(const char *path, PathSimplifyWarnFlags flags) {
21,275✔
18

19
        assert(path);
21,275✔
20

21
        if ((flags & (PATH_CHECK_NON_API_VFS|PATH_CHECK_NON_API_VFS_DEV_OK)) == 0)
21,275✔
22
                return true;
23

24
        if (!path_below_api_vfs(path))
537✔
25
                return true;
26

27
        if (FLAGS_SET(flags, PATH_CHECK_NON_API_VFS_DEV_OK) && path_startswith(path, "/dev"))
2✔
UNCOV
28
                return true;
×
29

30
        return false;
31
}
32

33
int path_simplify_and_warn(
21,286✔
34
                char *path,
35
                PathSimplifyWarnFlags flags,
36
                const char *unit,
37
                const char *filename,
38
                unsigned line,
39
                const char *lvalue) {
40

41
        bool fatal = flags & PATH_CHECK_FATAL;
21,286✔
42
        int level = fatal ? LOG_ERR : LOG_WARNING;
21,286✔
43

44
        assert(path);
21,286✔
45
        assert(!FLAGS_SET(flags, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE));
21,286✔
46
        assert(!FLAGS_SET(flags, PATH_CHECK_NON_API_VFS | PATH_CHECK_NON_API_VFS_DEV_OK));
21,286✔
47
        assert(lvalue);
21,286✔
48

49
        if (!utf8_is_valid(path))
21,286✔
50
                return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path);
1✔
51

52
        if (flags & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) {
21,285✔
53
                bool absolute;
20,725✔
54

55
                absolute = path_is_absolute(path);
20,725✔
56

57
                if (!absolute && (flags & PATH_CHECK_ABSOLUTE))
20,725✔
58
                        return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
7✔
59
                                          "%s= path is not absolute%s: %s",
60
                                          lvalue, fatal ? "" : ", ignoring", path);
61

62
                if (absolute && (flags & PATH_CHECK_RELATIVE))
20,721✔
63
                        return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
3✔
64
                                          "%s= path is absolute%s: %s",
65
                                          lvalue, fatal ? "" : ", ignoring", path);
66
        }
67

68
        path_simplify_full(path, flags & PATH_KEEP_TRAILING_SLASH ? PATH_SIMPLIFY_KEEP_TRAILING_SLASH : 0);
21,279✔
69

70
        if (!path_is_valid(path))
21,279✔
71
                return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
3✔
72
                                  "%s= path has invalid length (%zu bytes)%s.",
73
                                  lvalue, strlen(path), fatal ? "" : ", ignoring");
74

75
        if (!path_is_normalized(path))
21,277✔
76
                return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
3✔
77
                                  "%s= path is not normalized%s: %s",
78
                                  lvalue, fatal ? "" : ", ignoring", path);
79

80
        if (!validate_api_vfs(path, flags))
21,275✔
81
                return log_syntax(unit, level, filename, line, SYNTHETIC_ERRNO(EINVAL),
3✔
82
                                  "%s= path is below API VFS%s: %s",
83
                                  lvalue, fatal ? ", refusing" : ", ignoring",
84
                                  path);
85

86
        return 0;
87
}
88

89
static int parse_af_token(
49✔
90
                const char *token,
91
                int *family,
92
                int *ip_protocol,
93
                uint16_t *nr_ports,
94
                uint16_t *port_min) {
95

96
        int af;
49✔
97

98
        assert(token);
49✔
99
        assert(family);
49✔
100

101
        af = af_from_ipv4_ipv6(token);
49✔
102
        if (af == AF_UNSPEC)
49✔
103
                return -EINVAL;
104

105
        *family = af;
28✔
106
        return 0;
28✔
107
}
108

109
static int parse_ip_protocol_token(
45✔
110
                const char *token,
111
                int *family,
112
                int *ip_protocol,
113
                uint16_t *nr_ports,
114
                uint16_t *port_min) {
115

116
        int proto;
45✔
117

118
        assert(token);
45✔
119
        assert(ip_protocol);
45✔
120

121
        proto = ip_protocol_from_tcp_udp(token);
45✔
122
        if (proto < 0)
45✔
123
                return -EINVAL;
124

125
        *ip_protocol = proto;
24✔
126
        return 0;
24✔
127
}
128

129
static int parse_ip_ports_token(
39✔
130
                const char *token,
131
                int *family,
132
                int *ip_protocol,
133
                uint16_t *nr_ports,
134
                uint16_t *port_min) {
135

136
        int r;
39✔
137

138
        assert(token);
39✔
139
        assert(nr_ports);
39✔
140
        assert(port_min);
39✔
141

142
        if (streq(token, "any"))
39✔
143
                *nr_ports = *port_min = 0;
9✔
144
        else {
145
                uint16_t mn = 0, mx = 0;
30✔
146
                r = parse_ip_port_range(token, &mn, &mx, /* allow_zero = */ true);
30✔
147
                if (r < 0)
30✔
148
                        return r;
13✔
149

150
                *nr_ports = mx - mn + 1;
17✔
151
                *port_min = mn;
17✔
152
        }
153

154
        return 0;
155
}
156

157
typedef int (*parse_token_f)(
158
                const char *,
159
                int *,
160
                int *,
161
                uint16_t *,
162
                uint16_t *);
163

164
int parse_socket_bind_item(
52✔
165
                const char *str,
166
                int *address_family,
167
                int *ip_protocol,
168
                uint16_t *nr_ports,
169
                uint16_t *port_min) {
170

171
        /* Order of token parsers is important. */
172
        const parse_token_f parsers[] = {
52✔
173
                &parse_af_token,
174
                &parse_ip_protocol_token,
175
                &parse_ip_ports_token,
176
        };
177
        parse_token_f const *parser_ptr = parsers;
52✔
178
        int af = AF_UNSPEC, proto = 0, r;
52✔
179
        uint16_t nr = 0, mn = 0;
52✔
180
        const char *p = ASSERT_PTR(str);
52✔
181

182
        assert(address_family);
52✔
183
        assert(ip_protocol);
52✔
184
        assert(nr_ports);
52✔
185
        assert(port_min);
52✔
186

187
        if (isempty(p))
52✔
188
                return -EINVAL;
52✔
189

190
        for (;;) {
155✔
191
                _cleanup_free_ char *token = NULL;
56✔
192

193
                r = extract_first_word(&p, &token, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
103✔
194
                if (r == 0)
103✔
195
                        break;
196
                if (r < 0)
95✔
197
                        return r;
198

199
                if (isempty(token))
99✔
200
                        return -EINVAL;
201

202
                while (parser_ptr != parsers + ELEMENTSOF(parsers)) {
146✔
203
                        r = (*parser_ptr)(token, &af, &proto, &nr, &mn);
133✔
204
                        if (r == -ENOMEM)
133✔
205
                                return r;
206

207
                        ++parser_ptr;
133✔
208
                        /* Continue to next token if parsing succeeded,
209
                         * otherwise apply next parser to the same token.
210
                         */
211
                        if (r >= 0)
133✔
212
                                break;
213
                }
214
                if (parser_ptr == parsers + ELEMENTSOF(parsers))
91✔
215
                                break;
216
        }
217

218
        /* Failed to parse a token. */
219
        if (r < 0)
47✔
220
                return r;
221

222
        /* Parsers applied successfully, but end of the string not reached. */
223
        if (p)
34✔
224
                return -EINVAL;
225

226
        *address_family = af;
28✔
227
        *ip_protocol = proto;
28✔
228
        *nr_ports = nr;
28✔
229
        *port_min = mn;
28✔
230

231
        return 0;
28✔
232
}
233

234
int config_parse_path_or_ignore(
31✔
235
                const char *unit,
236
                const char *filename,
237
                unsigned line,
238
                const char *section,
239
                unsigned section_line,
240
                const char *lvalue,
241
                int ltype,
242
                const char *rvalue,
243
                void *data,
244
                void *userdata) {
245

246
        _cleanup_free_ char *n = NULL;
31✔
247
        bool fatal = ltype;
31✔
248
        char **s = ASSERT_PTR(data);
31✔
249
        int r;
31✔
250

251
        assert(filename);
31✔
252
        assert(lvalue);
31✔
253
        assert(rvalue);
31✔
254

255
        if (isempty(rvalue))
31✔
256
                goto finalize;
×
257

258
        n = strdup(rvalue);
31✔
259
        if (!n)
31✔
UNCOV
260
                return log_oom();
×
261

262
        if (streq(n, "-"))
31✔
263
                goto finalize;
4✔
264

265
        r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue);
54✔
266
        if (r < 0)
27✔
UNCOV
267
                return fatal ? -ENOEXEC : 0;
×
268

269
finalize:
27✔
270
        return free_and_replace(*s, n);
31✔
271
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc