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

systemd / systemd / 14554080340

19 Apr 2025 11:46AM UTC coverage: 72.101% (-0.03%) from 72.13%
14554080340

push

github

web-flow
Add two new paragraphs to coding style about header files (#37188)

296880 of 411754 relevant lines covered (72.1%)

687547.52 hits per line

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

90.12
/src/basic/hostname-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <errno.h>
4
#include <limits.h>
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <sys/utsname.h>
8
#include <unistd.h>
9

10
#include "alloc-util.h"
11
#include "env-file.h"
12
#include "hostname-util.h"
13
#include "log.h"
14
#include "os-util.h"
15
#include "string-util.h"
16
#include "strv.h"
17

18
char* get_default_hostname_raw(void) {
44✔
19
        int r;
44✔
20

21
        /* Returns the default hostname, and leaves any ??? in place. */
22

23
        const char *e = secure_getenv("SYSTEMD_DEFAULT_HOSTNAME");
44✔
24
        if (e) {
44✔
25
                if (hostname_is_valid(e, VALID_HOSTNAME_QUESTION_MARK))
×
26
                        return strdup(e);
44✔
27

28
                log_debug("Invalid hostname in $SYSTEMD_DEFAULT_HOSTNAME, ignoring: %s", e);
×
29
        }
30

31
        _cleanup_free_ char *f = NULL;
44✔
32
        r = parse_os_release(NULL, "DEFAULT_HOSTNAME", &f);
44✔
33
        if (r < 0)
44✔
34
                log_debug_errno(r, "Failed to parse os-release, ignoring: %m");
×
35
        else if (f) {
44✔
36
                if (hostname_is_valid(f, VALID_HOSTNAME_QUESTION_MARK))
×
37
                        return TAKE_PTR(f);
×
38

39
                log_debug("Invalid hostname in os-release, ignoring: %s", f);
×
40
        }
41

42
        return strdup(FALLBACK_HOSTNAME);
44✔
43
}
44

45
bool valid_ldh_char(char c) {
67,360✔
46
        /* "LDH" → "Letters, digits, hyphens", as per RFC 5890, Section 2.3.1 */
47

48
        return ascii_isalpha(c) ||
67,360✔
49
                ascii_isdigit(c) ||
67,360✔
50
                c == '-';
51
}
52

53
bool hostname_is_valid(const char *s, ValidHostnameFlags flags) {
3,672✔
54
        unsigned n_dots = 0;
3,672✔
55
        const char *p;
3,672✔
56
        bool dot, hyphen;
3,672✔
57

58
        /* Check if s looks like a valid hostname or FQDN. This does not do full DNS validation, but only
59
         * checks if the name is composed of allowed characters and the length is not above the maximum
60
         * allowed by Linux (c.f. dns_name_is_valid()). A trailing dot is allowed if
61
         * VALID_HOSTNAME_TRAILING_DOT flag is set and at least two components are present in the name. Note
62
         * that due to the restricted charset and length this call is substantially more conservative than
63
         * dns_name_is_valid(). Doesn't accept empty hostnames, hostnames with leading dots, and hostnames
64
         * with multiple dots in a sequence. Doesn't allow hyphens at the beginning or end of label. */
65

66
        if (isempty(s))
3,672✔
67
                return false;
68

69
        if (streq(s, ".host")) /* Used by the container logic to denote the "root container" */
3,663✔
70
                return FLAGS_SET(flags, VALID_HOSTNAME_DOT_HOST);
60✔
71

72
        for (p = s, dot = hyphen = true; *p; p++)
70,646✔
73
                if (*p == '.') {
67,083✔
74
                        if (dot || hyphen)
9,952✔
75
                                return false;
76

77
                        dot = true;
9,940✔
78
                        hyphen = false;
9,940✔
79
                        n_dots++;
9,940✔
80

81
                } else if (*p == '-') {
57,131✔
82
                        if (dot)
2,186✔
83
                                return false;
84

85
                        dot = false;
86
                        hyphen = true;
87

88
                } else {
89
                        if (!valid_ldh_char(*p) && (*p != '?' || !FLAGS_SET(flags, VALID_HOSTNAME_QUESTION_MARK)))
54,945✔
90
                                return false;
91

92
                        dot = false;
93
                        hyphen = false;
94
                }
95

96
        if (dot && (n_dots < 2 || !FLAGS_SET(flags, VALID_HOSTNAME_TRAILING_DOT)))
3,563✔
97
                return false;
98
        if (hyphen)
3,557✔
99
                return false;
100

101
        if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on Linux, but DNS allows domain names up to
3,557✔
102
                                  * 255 characters */
103
                return false;
5✔
104

105
        return true;
106
}
107

108
char* hostname_cleanup(char *s) {
406✔
109
        char *p, *d;
406✔
110
        bool dot, hyphen;
406✔
111

112
        assert(s);
406✔
113

114
        for (p = s, d = s, dot = hyphen = true; *p && d - s < HOST_NAME_MAX; p++)
13,259✔
115
                if (*p == '.') {
12,853✔
116
                        if (dot || hyphen)
735✔
117
                                continue;
16✔
118

119
                        *(d++) = '.';
719✔
120
                        dot = true;
719✔
121
                        hyphen = false;
719✔
122

123
                } else if (*p == '-') {
12,118✔
124
                        if (dot)
1,453✔
125
                                continue;
4✔
126

127
                        *(d++) = '-';
1,449✔
128
                        dot = false;
1,449✔
129
                        hyphen = true;
1,449✔
130

131
                } else if (valid_ldh_char(*p) || *p == '?') {
10,665✔
132
                        *(d++) = *p;
10,641✔
133
                        dot = false;
10,641✔
134
                        hyphen = false;
10,641✔
135
                }
136

137
        if (d > s && IN_SET(d[-1], '-', '.'))
406✔
138
                /* The dot can occur at most once, but we might have multiple
139
                 * hyphens, hence the loop */
140
                d--;
7✔
141
        *d = 0;
406✔
142

143
        return s;
406✔
144
}
145

146
bool is_localhost(const char *hostname) {
140,447✔
147
        assert(hostname);
140,447✔
148

149
        /* This tries to identify local host and domain names
150
         * described in RFC6761 plus the redhatism of localdomain */
151

152
        return STRCASE_IN_SET(
140,447✔
153
                        hostname,
154
                        "localhost",
155
                        "localhost.",
156
                        "localhost.localdomain",
157
                        "localhost.localdomain.") ||
140,345✔
158
                endswith_no_case(hostname, ".localhost") ||
280,660✔
159
                endswith_no_case(hostname, ".localhost.") ||
280,600✔
160
                endswith_no_case(hostname, ".localhost.localdomain") ||
420,987✔
161
                endswith_no_case(hostname, ".localhost.localdomain.");
140,255✔
162
}
163

164
int get_pretty_hostname(char **ret) {
12✔
165
        _cleanup_free_ char *n = NULL;
12✔
166
        int r;
12✔
167

168
        assert(ret);
12✔
169

170
        r = parse_env_file(NULL, "/etc/machine-info", "PRETTY_HOSTNAME", &n);
12✔
171
        if (r < 0)
12✔
172
                return r;
173

174
        if (isempty(n))
12✔
175
                return -ENXIO;
176

177
        *ret = TAKE_PTR(n);
×
178
        return 0;
×
179
}
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