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

systemd / systemd / 25238955322

01 May 2026 10:09AM UTC coverage: 71.943% (-0.2%) from 72.134%
25238955322

push

github

bluca
po: Translated using Weblate (Greek)

Currently translated at 100.0% (266 of 266 strings)

Co-authored-by: Jim Spentzos <jimspentzos2000@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/el/
Translation: systemd/main

324741 of 451384 relevant lines covered (71.94%)

1387736.3 hits per line

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

86.44
/src/bootctl/bootspec-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include "alloc-util.h"
4
#include "boot-entry.h"
5
#include "bootspec-util.h"
6
#include "devnum-util.h"
7
#include "efi-loader.h"
8
#include "errno-util.h"
9
#include "log.h"
10
#include "parse-util.h"
11
#include "path-util.h"
12
#include "stdio-util.h"
13
#include "string-util.h"
14
#include "strv.h"
15
#include "utf8.h"
16

17
int boot_config_load_and_select(
43✔
18
                BootConfig *config,
19
                const char *root,
20
                const char *esp_path,
21
                dev_t esp_devid,
22
                const char *xbootldr_path,
23
                dev_t xbootldr_devid) {
24

25
        int r;
43✔
26

27
        /* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
28
         * find the same entries twice. */
29
        bool same = esp_path && xbootldr_path && devnum_set_and_equal(esp_devid, xbootldr_devid);
43✔
30

31
        r = boot_config_load(config, esp_path, same ? NULL : xbootldr_path);
43✔
32
        if (r < 0)
43✔
33
                return r;
34

35
        if (!root) {
43✔
36
                _cleanup_strv_free_ char **efi_entries = NULL;
×
37

38
                r = efi_loader_get_entries(&efi_entries);
29✔
39
                if (r == -ENOENT || ERRNO_IS_NEG_NOT_SUPPORTED(r))
29✔
40
                        log_debug_errno(r, "Boot loader reported no entries.");
×
41
                else if (r < 0)
29✔
42
                        log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
29✔
43
                else
44
                        (void) boot_config_augment_from_loader(config, efi_entries, /* auto_only= */ false);
29✔
45
        }
46

47
        return boot_config_select_special_entries(config, /* skip_efivars= */ !!root);
43✔
48
}
49

50
int boot_entry_make_commit_filename(
22✔
51
                const char *entry_token,
52
                uint64_t entry_commit,
53
                const char *version,
54
                unsigned profile_nr,
55
                unsigned tries_left,
56
                char **ret) {
57

58
        assert(entry_token);
22✔
59
        assert(ret);
22✔
60

61
        /* Generate a new entry filename from the entry token, the commit number, and (optionally) the
62
         * image/OS version, (if non-zero) the profile number, and (unless UINT_MAX) the number of tries
63
         * left. */
64

65
        if (!boot_entry_token_valid(entry_token))
22✔
66
                return -EINVAL;
22✔
67
        if (!entry_commit_valid(entry_commit))
21✔
68
                return -EINVAL;
69

70
        _cleanup_free_ char *filename = asprintf_safe("%s-commit_%" PRIu64, entry_token, entry_commit);
38✔
71
        if (!filename)
19✔
72
                return -ENOMEM;
73
        if (version && !strextend(&filename, ".", version))
19✔
74
                return -ENOMEM;
75
        if (profile_nr > 0 && strextendf(&filename, "@%u", profile_nr) < 0)
19✔
76
                return -ENOMEM;
77
        if (tries_left != UINT_MAX && strextendf(&filename, "+%u", tries_left) < 0)
19✔
78
                return -ENOMEM;
79
        if (!strextend(&filename, ".conf"))
19✔
80
                return -ENOMEM;
81

82
        if (!filename_is_valid(filename) || string_has_cc(filename, /* ok= */ NULL) || !utf8_is_valid(filename))
19✔
83
                return -EINVAL;
84

85
        *ret = TAKE_PTR(filename);
19✔
86
        return 0;
19✔
87
}
88

89
int boot_entry_parse_commit_filename(
28✔
90
                const char *filename,
91
                char **ret_entry_token,
92
                uint64_t *ret_entry_commit) {
93

94
        int r;
28✔
95

96
        assert(filename);
28✔
97

98
        if (!filename_is_valid(filename))
28✔
99
                return -EINVAL;
28✔
100

101
        _cleanup_free_ char *stripped = NULL;
28✔
102
        r = boot_filename_extract_tries(filename, &stripped, /* ret_tries_left= */ NULL, /* ret_tries_done= */ NULL);
28✔
103
        if (r < 0)
28✔
104
                return r;
105

106
        const char *a = strrstr_no_case(stripped, "-commit_");
28✔
107
        if (!a)
28✔
108
                return -EBADMSG;
109

110
        const char *c = endswith_no_case(stripped, ".conf");
27✔
111
        if (!c)
27✔
112
                return -EBADMSG;
113

114
        assert(a < c);
27✔
115

116
        _cleanup_free_ char *entry_token = strndup(stripped, a - stripped);
27✔
117
        if (!entry_token)
27✔
118
                return -ENOMEM;
119

120
        if (!boot_entry_token_valid(entry_token))
27✔
121
                return -EBADMSG;
122

123
        const char *b = a + STRLEN("-commit_");
27✔
124
        size_t n = strspn(b, DIGITS);
27✔
125
        if (n <= 0 || !IN_SET(b[n], '+', '.', '@'))
27✔
126
                return -EBADMSG;
127

128
        _cleanup_free_ char *entry_commit_string = strndup(b, n);
25✔
129
        if (!entry_commit_string)
25✔
130
                return -ENOMEM;
131

132
        uint64_t entry_commit;
25✔
133
        r = safe_atou64_full(entry_commit_string, 10, &entry_commit);
25✔
134
        if (r < 0)
25✔
135
                return r;
136
        if (!entry_commit_valid(entry_commit))
25✔
137
                return -EBADMSG;
138

139
        if (ret_entry_token)
24✔
140
                *ret_entry_token = TAKE_PTR(entry_token);
24✔
141
        if (ret_entry_commit)
24✔
142
                *ret_entry_commit = entry_commit;
24✔
143

144
        return 0;
145
}
146

147
int boot_entry_parse_commit(
44✔
148
                BootEntry *entry,
149
                char **ret_entry_token,
150
                uint64_t *ret_entry_commit) {
151

152
        int r;
44✔
153

154
        assert(entry);
44✔
155

156
        if (entry->type != BOOT_ENTRY_TYPE1)
44✔
157
                return -EADDRNOTAVAIL;
44✔
158

159
        _cleanup_free_ char *fn = NULL;
16✔
160
        r = path_extract_filename(entry->path, &fn);
16✔
161
        if (r < 0)
16✔
162
                return r;
163

164
        return boot_entry_parse_commit_filename(fn, ret_entry_token, ret_entry_commit);
16✔
165
}
166

167
int boot_config_find_oldest_commit(
4✔
168
                BootConfig *config,
169
                const char *entry_token,
170
                char ***ret_ids) {
171

172
        int r;
4✔
173

174
        assert(config);
4✔
175
        assert(entry_token);
4✔
176
        assert(ret_ids);
4✔
177

178
        uint64_t commit_oldest = UINT64_MAX, commit_2nd_oldest = UINT64_MAX, commit_blocked = UINT64_MAX;
4✔
179

180
        /* First, determine which commit is the oldest (that isn't the current one), and hence the candidate
181
         * to be removed */
182
        FOREACH_ARRAY(b, config->entries, config->n_entries) {
28✔
183
                _cleanup_free_ char *et = NULL;
24✔
184
                uint64_t ec;
24✔
185

186
                r = boot_entry_parse_commit(b, &et, &ec);
24✔
187
                if (r == -EADDRNOTAVAIL)
24✔
188
                        continue;
16✔
189
                if (r < 0) {
8✔
190
                        log_debug_errno(r, "Failed to parse entry filename of '%s', ignoring: %m", strna(b->id));
×
191
                        continue;
×
192
                }
193

194
                if (!streq(et, entry_token)) /* Not ours? */
8✔
195
                        continue;
×
196

197
                if (ec < commit_oldest) {
8✔
198
                        commit_2nd_oldest = commit_oldest;
199
                        commit_oldest = ec;
200
                } else if (ec > commit_oldest && ec < commit_2nd_oldest)
×
201
                        commit_2nd_oldest = ec;
×
202

203
                if (boot_config_selected_entry(config) == b) {
8✔
204
                        assert(commit_blocked == UINT64_MAX);
×
205
                        commit_blocked = ec;
×
206
                }
207
        }
208

209
        uint64_t commit_picked;
4✔
210
        if (commit_oldest == UINT64_MAX)
4✔
211
                return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "No matching entry found while determining oldest entry.");
4✔
212
        if (commit_oldest != commit_blocked)
3✔
213
                commit_picked = commit_oldest;
214
        else {
215
                if (commit_2nd_oldest == UINT64_MAX)
×
216
                        return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), "Only matching entry found while determining oldest entry is current one, skipping it.");
×
217

218
                assert(commit_2nd_oldest != commit_blocked);
×
219
                commit_picked = commit_2nd_oldest;
220
        }
221

222
        log_debug("Determined commit %" PRIu64 " to be oldest.", commit_picked);
3✔
223

224
        /* Second loop: actually remove all entries matching this commit (which can be multiple, since UKIs
225
         * have profiles) */
226
        _cleanup_(strv_freep) char **l = NULL;
3✔
227
        FOREACH_ARRAY(b, config->entries, config->n_entries) {
23✔
228
                _cleanup_free_ char *et = NULL;
20✔
229
                uint64_t ec;
20✔
230

231
                r = boot_entry_parse_commit(b, &et, &ec);
20✔
232
                if (r == -EADDRNOTAVAIL)
20✔
233
                        continue;
12✔
234
                if (r < 0) {
8✔
235
                        log_debug_errno(r, "Failed to parse entry filename of '%s', ignoring: %m", strna(b->id));
×
236
                        continue;
×
237
                }
238

239
                if (!streq(et, entry_token)) /* Not ours? */
8✔
240
                        continue;
×
241

242
                if (ec != commit_picked)
8✔
243
                        continue;
5✔
244

245
                r = strv_extend(&l, b->id);
3✔
246
                if (r < 0)
3✔
247
                        return r;
×
248
        }
249

250
        /* The list cannot be empty, the first loop above and the 2nd loop must have found the same matching
251
         * entries, and if the first loop didn't find any we'd not come this far. */
252
        assert(!strv_isempty(l));
3✔
253
        *ret_ids = TAKE_PTR(l);
3✔
254
        return 0;
3✔
255
}
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