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

systemd / systemd / 18668483236

20 Oct 2025 10:56PM UTC coverage: 72.32% (+0.06%) from 72.264%
18668483236

push

github

yuwata
hwdb: Add V64x_V65xAU to list of Clevo models where scancode f7+f8 get mapped to touchpad-toggle

Fn + F1 which is the shortcut for toggling the touchpad on/off sends
atkbd scancodes f7 (first press) + f8 (second press) just like on various
other Clevo models. Add the V64x_V65xAU model to the list of models where
these scancodes are mapped to touchpad-toggle.

304594 of 421177 relevant lines covered (72.32%)

1093501.54 hits per line

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

76.82
/src/shared/hostname-setup.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sched.h>
4
#include <stdio.h>
5
#include <sys/utsname.h>
6
#include <unistd.h>
7

8
#include "sd-daemon.h"
9

10
#include "alloc-util.h"
11
#include "creds-util.h"
12
#include "fd-util.h"
13
#include "fileio.h"
14
#include "fs-util.h"
15
#include "hexdecoct.h"
16
#include "hostname-setup.h"
17
#include "hostname-util.h"
18
#include "initrd-util.h"
19
#include "io-util.h"
20
#include "log.h"
21
#include "namespace-util.h"
22
#include "pidref.h"
23
#include "proc-cmdline.h"
24
#include "process-util.h"
25
#include "siphash24.h"
26
#include "string-table.h"
27
#include "string-util.h"
28

29
static int sethostname_idempotent_full(const char *s, bool really) {
284✔
30
        struct utsname u;
284✔
31

32
        assert(s);
284✔
33

34
        if (uname(&u) < 0)
284✔
35
                return -errno;
×
36

37
        if (streq_ptr(s, u.nodename))
284✔
38
                return 0;
39

40
        if (really &&
344✔
41
            sethostname(s, strlen(s)) < 0)
172✔
42
                return -errno;
×
43

44
        return 1;
45
}
46

47
int sethostname_idempotent(const char *s) {
248✔
48
        return sethostname_idempotent_full(s, true);
248✔
49
}
50

51
int shorten_overlong(const char *s, char **ret) {
86✔
52
        _cleanup_free_ char *h = NULL;
86✔
53

54
        /* Shorten an overlong name to HOST_NAME_MAX or to the first dot,
55
         * whatever comes earlier. */
56

57
        assert(s);
86✔
58
        assert(ret);
86✔
59

60
        h = strdup(s);
86✔
61
        if (!h)
86✔
62
                return -ENOMEM;
63

64
        if (hostname_is_valid(h, 0)) {
86✔
65
                *ret = TAKE_PTR(h);
83✔
66
                return 0;
83✔
67
        }
68

69
        char *p = strchr(h, '.');
3✔
70
        if (p)
3✔
71
                *p = 0;
2✔
72

73
        strshorten(h, HOST_NAME_MAX);
3✔
74

75
        if (!hostname_is_valid(h, /* flags= */ 0))
3✔
76
                return -EDOM;
77

78
        *ret = TAKE_PTR(h);
2✔
79
        return 1;
2✔
80
}
81

82
static int acquire_hostname_from_credential(char **ret) {
×
83
        _cleanup_free_ char *cred = NULL;
×
84
        int r;
×
85

86
        assert(ret);
×
87

88
        r = read_credential_with_decryption("system.hostname", (void **) &cred, /* ret_size= */ NULL);
×
89
        if (r < 0)
×
90
                return log_warning_errno(r, "Failed to read system.hostname credential, ignoring: %m");
×
91
        if (r == 0) /* not found */
×
92
                return -ENXIO;
93

94
        if (!hostname_is_valid(cred, VALID_HOSTNAME_TRAILING_DOT)) /* check that the hostname we return is valid */
×
95
                return log_warning_errno(SYNTHETIC_ERRNO(EBADMSG), "Hostname specified in system.hostname credential is invalid, ignoring: %s", cred);
×
96

97
        log_info("Initializing hostname from credential.");
×
98
        *ret = TAKE_PTR(cred);
×
99
        return 0;
×
100
}
101

102
int read_etc_hostname_stream(FILE *f, bool substitute_wildcards, char **ret) {
65✔
103
        int r;
65✔
104

105
        assert(f);
65✔
106
        assert(ret);
65✔
107

108
        for (;;) {
73✔
109
                _cleanup_free_ char *line = NULL;
69✔
110

111
                r = read_stripped_line(f, LONG_LINE_MAX, &line);
69✔
112
                if (r < 0)
69✔
113
                        return r;
114
                if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */
69✔
115
                        return -ENOENT;
116

117
                /* File may have empty lines or comments, ignore them */
118
                if (IN_SET(line[0], '\0', '#'))
13✔
119
                        continue;
4✔
120

121
                if (substitute_wildcards) {
9✔
122
                        r = hostname_substitute_wildcards(line);
1✔
123
                        if (r < 0)
1✔
124
                                return r;
125
                }
126

127
                hostname_cleanup(line); /* normalize the hostname */
9✔
128

129
                /* check that the hostname we return is valid */
130
                if (!hostname_is_valid(
17✔
131
                                    line,
132
                                    VALID_HOSTNAME_TRAILING_DOT|
133
                                    (substitute_wildcards ? 0 : VALID_HOSTNAME_QUESTION_MARK)))
134
                        return -EBADMSG;
135

136
                *ret = TAKE_PTR(line);
9✔
137
                return 0;
9✔
138
        }
139
}
140

141
int read_etc_hostname(const char *path, bool substitute_wildcards, char **ret) {
218✔
142
        _cleanup_fclose_ FILE *f = NULL;
218✔
143

144
        assert(ret);
218✔
145

146
        if (!path)
218✔
147
                path = etc_hostname();
210✔
148

149
        f = fopen(path, "re");
218✔
150
        if (!f)
218✔
151
                return -errno;
208✔
152

153
        return read_etc_hostname_stream(f, substitute_wildcards, ret);
10✔
154
}
155

156
void hostname_update_source_hint(const char *hostname, HostnameSource source) {
111✔
157
        int r;
111✔
158

159
        assert(hostname);
111✔
160

161
        /* Why save the value and not just create a flag file? This way we will
162
         * notice if somebody sets the hostname directly (not going through hostnamed).
163
         */
164

165
        if (source == HOSTNAME_DEFAULT) {
111✔
166
                r = write_string_file("/run/systemd/default-hostname", hostname,
35✔
167
                                      WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
168
                if (r < 0)
35✔
169
                        log_warning_errno(r, "Failed to create \"/run/systemd/default-hostname\", ignoring: %m");
×
170
        } else
171
                (void) unlink_or_warn("/run/systemd/default-hostname");
76✔
172
}
111✔
173

174
int hostname_setup(bool really) {
36✔
175
        _cleanup_free_ char *hn = NULL;
36✔
176
        HostnameSource source;
36✔
177
        bool enoent = false;
36✔
178
        int r;
36✔
179

180
        r = proc_cmdline_get_key("systemd.hostname", 0, &hn);
36✔
181
        if (r < 0)
36✔
182
                log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
×
183
        else if (r > 0) {
36✔
184
                if (hostname_is_valid(hn, VALID_HOSTNAME_TRAILING_DOT))
36✔
185
                        source = HOSTNAME_TRANSIENT;
186
                else  {
187
                        log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", hn);
×
188
                        hn = mfree(hn);
×
189
                }
190
        }
191

192
        if (!hn) {
36✔
193
                r = read_etc_hostname(/* path= */ NULL, /* substitute_wildcards= */ true, &hn);
×
194
                if (r == -ENOENT)
×
195
                        enoent = true;
196
                else if (r < 0)
×
197
                        log_warning_errno(r, "Failed to read configured hostname, ignoring: %m");
×
198
                else
199
                        source = HOSTNAME_STATIC;
200
        }
201

202
        if (!hn) {
36✔
203
                r = acquire_hostname_from_credential(&hn);
×
204
                if (r >= 0)
×
205
                        source = HOSTNAME_TRANSIENT;
×
206
        }
207

208
        if (!hn) {
36✔
209
                /* Don't override the hostname if it is already set and not explicitly configured */
210

211
                r = gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hn);
×
212
                if (r == -ENOMEM)
×
213
                        return log_oom();
×
214
                if (r >= 0) {
×
215
                        log_debug("No hostname configured, leaving existing hostname <%s> in place.", hn);
×
216
                        goto finish;
×
217
                }
218

219
                if (enoent)
×
220
                        log_info("No hostname configured, using default hostname.");
×
221

222
                hn = get_default_hostname();
×
223
                if (!hn)
×
224
                        return log_oom();
×
225

226
                source = HOSTNAME_DEFAULT;
227
        }
228

229
        r = sethostname_idempotent_full(hn, really);
36✔
230
        if (r < 0)
36✔
231
                return log_warning_errno(r, "Failed to set hostname to <%s>: %m", hn);
×
232
        if (r == 0)
36✔
233
                log_debug("Hostname was already set to <%s>.", hn);
4✔
234
        else
235
                log_info("Hostname %s to <%s>.",
32✔
236
                         really ? "set" : "would have been set",
237
                         hn);
238

239
        if (really)
36✔
240
                hostname_update_source_hint(hn, source);
35✔
241

242
finish:
1✔
243
        if (!in_initrd())
36✔
244
                (void) sd_notifyf(/* unset_environment= */ false, "X_SYSTEMD_HOSTNAME=%s", hn);
25✔
245

246
        return 0;
247
}
248

249
static const char* const hostname_source_table[] = {
250
        [HOSTNAME_STATIC]    = "static",
251
        [HOSTNAME_TRANSIENT] = "transient",
252
        [HOSTNAME_DEFAULT]   = "default",
253
};
254

255
DEFINE_STRING_TABLE_LOOKUP(hostname_source, HostnameSource);
163✔
256

257
int hostname_substitute_wildcards(char *name) {
224✔
258
        static const sd_id128_t key = SD_ID128_MAKE(98,10,ad,df,8d,7d,4f,b5,89,1b,4b,56,ac,c2,26,8f);
224✔
259
        sd_id128_t mid = SD_ID128_NULL;
224✔
260
        size_t left_bits = 0, counter = 0;
224✔
261
        uint64_t h = 0;
224✔
262
        int r;
224✔
263

264
        assert(name);
224✔
265

266
        /* Replaces every occurrence of '?' in the specified string with a nibble hashed from
267
         * /etc/machine-id. This is supposed to be used on /etc/hostname files that want to automatically
268
         * configure a hostname derived from the machine ID in some form.
269
         *
270
         * Note that this does not directly use the machine ID, because that's not necessarily supposed to be
271
         * public information to be broadcast on the network, while the hostname certainly is. */
272

273
        for (char *n = name; ; n++) {
23✔
274
                n = strchr(n, '?');
270✔
275
                if (!n)
247✔
276
                        return 0;
224✔
277

278
                if (left_bits <= 0) {
23✔
279
                        if (sd_id128_is_null(mid)) {
3✔
280
                                r = sd_id128_get_machine(&mid);
2✔
281
                                if (r < 0)
2✔
282
                                        return r;
×
283
                        }
284

285
                        struct siphash state;
3✔
286
                        siphash24_init(&state, key.bytes);
3✔
287
                        siphash24_compress(&mid, sizeof(mid), &state);
3✔
288
                        siphash24_compress(&counter, sizeof(counter), &state); /* counter mode */
3✔
289
                        h = siphash24_finalize(&state);
3✔
290
                        left_bits = sizeof(h) * 8;
3✔
291
                        counter++;
3✔
292
                }
293

294
                assert(left_bits >= 4);
23✔
295
                *n = hexchar(h & 0xf);
23✔
296
                h >>= 4;
23✔
297
                left_bits -= 4;
23✔
298
        }
299
}
300

301
char* get_default_hostname(void) {
47✔
302
        int r;
47✔
303

304
        _cleanup_free_ char *h = get_default_hostname_raw();
94✔
305
        if (!h)
47✔
306
                return NULL;
307

308
        r = hostname_substitute_wildcards(h);
47✔
309
        if (r < 0) {
47✔
310
                log_debug_errno(r, "Failed to substitute wildcards in hostname, falling back to built-in name: %m");
×
311
                return strdup(FALLBACK_HOSTNAME);
×
312
        }
313

314
        return TAKE_PTR(h);
315
}
316

317
int gethostname_full(GetHostnameFlags flags, char **ret) {
1,573✔
318
        _cleanup_free_ char *buf = NULL, *fallback = NULL;
1,573✔
319
        struct utsname u;
1,573✔
320
        const char *s;
1,573✔
321

322
        assert(ret);
1,573✔
323

324
        if (uname(&u) < 0)
1,573✔
325
                return -errno;
×
326

327
        s = u.nodename;
1,573✔
328
        if (isempty(s) || streq(s, "(none)") ||
1,573✔
329
            (!FLAGS_SET(flags, GET_HOSTNAME_ALLOW_LOCALHOST) && is_localhost(s)) ||
1,573✔
330
            (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')) {
1,573✔
331
                if (!FLAGS_SET(flags, GET_HOSTNAME_FALLBACK_DEFAULT))
×
332
                        return -ENXIO;
333

334
                s = fallback = get_default_hostname();
×
335
                if (!s)
×
336
                        return -ENOMEM;
337

338
                if (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')
×
339
                        return -ENXIO;
340
        }
341

342
        if (FLAGS_SET(flags, GET_HOSTNAME_SHORT))
12✔
343
                buf = strdupcspn(s, ".");
12✔
344
        else
345
                buf = strdup(s);
1,561✔
346
        if (!buf)
1,573✔
347
                return -ENOMEM;
348

349
        *ret = TAKE_PTR(buf);
1,573✔
350
        return 0;
1,573✔
351
}
352

353
int pidref_gethostname_full(PidRef *pidref, GetHostnameFlags flags, char **ret) {
4✔
354
        int r;
4✔
355

356
        assert(pidref);
4✔
357
        assert(ret);
4✔
358

359
        r = pidref_in_same_namespace(pidref, NULL, NAMESPACE_UTS);
4✔
360
        if (r < 0)
4✔
361
                return r;
4✔
362
        if (r > 0)
4✔
363
                return gethostname_full(flags, ret);
2✔
364

365
        _cleanup_close_ int utsns_fd = r = pidref_namespace_open_by_type(pidref, NAMESPACE_UTS);
6✔
366
        if (r < 0)
2✔
367
                return r;
368

369
        _cleanup_close_pair_ int errno_pipe[2] = EBADF_PAIR;
2✔
370
        r = pipe2(errno_pipe, O_CLOEXEC);
2✔
371
        if (r < 0)
2✔
372
                return -errno;
×
373

374
        _cleanup_close_pair_ int result_pipe[2] = EBADF_PAIR;
2✔
375
        r = pipe2(result_pipe, O_CLOEXEC);
2✔
376
        if (r < 0)
2✔
377
                return -errno;
×
378

379
        _cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
2✔
380
        r = pidref_safe_fork("(gethostname)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &child);
2✔
381
        if (r < 0)
4✔
382
                return r;
383
        if (r == 0) {
4✔
384
                errno_pipe[0] = safe_close(errno_pipe[0]);
2✔
385
                result_pipe[0] = safe_close(result_pipe[0]);
2✔
386

387
                if (setns(utsns_fd, CLONE_NEWUTS) < 0)
2✔
388
                        report_errno_and_exit(errno_pipe[1], -errno);
×
389

390
                char *t;
2✔
391
                r = gethostname_full(flags, &t);
2✔
392
                if (r < 0)
2✔
393
                        report_errno_and_exit(errno_pipe[1], r);
×
394

395
                r = loop_write(result_pipe[1], t, strlen(t) + 1);
2✔
396
                report_errno_and_exit(errno_pipe[1], r);
2✔
397
        }
398

399
        errno_pipe[1] = safe_close(errno_pipe[1]);
2✔
400
        result_pipe[1] = safe_close(result_pipe[1]);
2✔
401

402
        r = read_errno(errno_pipe[0]);
2✔
403
        if (r < 0)
2✔
404
                return r;
405

406
        char buf[HOST_NAME_MAX+1];
2✔
407
        ssize_t n = loop_read(result_pipe[0], buf, sizeof(buf), /* do_poll = */ false);
2✔
408
        if (n < 0)
2✔
409
                return n;
×
410
        if (n == 0 || buf[n - 1] != '\0')
2✔
411
                return -EPROTO;
412

413
        return strdup_to(ret, buf);
2✔
414
}
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