• 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

67.24
/src/sysupdate/sysupdate-partition.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <sys/file.h>
4

5
#include "alloc-util.h"
6
#include "extract-word.h"
7
#include "gpt.h"
8
#include "id128-util.h"
9
#include "log.h"
10
#include "parse-util.h"
11
#include "stdio-util.h"
12
#include "string-util.h"
13
#include "sysupdate-partition.h"
14

15
void partition_info_destroy(PartitionInfo *p) {
4,510✔
16
        assert(p);
4,510✔
17

18
        p->label = mfree(p->label);
4,510✔
19
        p->device = mfree(p->device);
4,510✔
20
}
4,510✔
21

22
int read_partition_info(
864✔
23
                struct fdisk_context *c,
24
                struct fdisk_table *t,
25
                size_t i,
26
                PartitionInfo *ret) {
27

28
        _cleanup_free_ char *label_copy = NULL, *device = NULL;
864✔
29
        const char *label;
864✔
30
        struct fdisk_partition *p;
864✔
31
        uint64_t start, size, flags;
864✔
32
        unsigned long ssz;
864✔
33
        sd_id128_t ptid, id;
864✔
34
        GptPartitionType type;
864✔
35
        size_t partno;
864✔
36
        int r;
864✔
37

38
        assert(c);
864✔
39
        assert(t);
864✔
40
        assert(ret);
864✔
41

42
        p = fdisk_table_get_partition(t, i);
864✔
43
        if (!p)
864✔
44
                return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read partition metadata.");
×
45

46
        if (fdisk_partition_is_used(p) <= 0) {
864✔
47
                *ret = (PartitionInfo) PARTITION_INFO_NULL;
×
48
                return 0; /* not found! */
×
49
        }
50

51
        if (fdisk_partition_has_partno(p) <= 0 ||
1,728✔
52
            fdisk_partition_has_start(p) <= 0 ||
1,728✔
53
            fdisk_partition_has_size(p) <= 0)
864✔
54
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a number, position or size.");
×
55

56
        partno = fdisk_partition_get_partno(p);
864✔
57

58
        start = fdisk_partition_get_start(p);
864✔
59
        ssz = fdisk_get_sector_size(c);
864✔
60
        assert(start <= UINT64_MAX / ssz);
864✔
61
        start *= ssz;
864✔
62

63
        size = fdisk_partition_get_size(p);
864✔
64
        assert(size <= UINT64_MAX / ssz);
864✔
65
        size *= ssz;
864✔
66

67
        label = fdisk_partition_get_name(p);
864✔
68
        if (!label)
864✔
69
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Found a partition without a label.");
×
70

71
        r = fdisk_partition_get_type_as_id128(p, &ptid);
864✔
72
        if (r < 0)
864✔
73
                return log_error_errno(r, "Failed to read partition type UUID: %m");
×
74

75
        r = fdisk_partition_get_uuid_as_id128(p, &id);
864✔
76
        if (r < 0)
864✔
77
                return log_error_errno(r, "Failed to read partition UUID: %m");
×
78

79
        r = fdisk_partition_get_attrs_as_uint64(p, &flags);
864✔
80
        if (r < 0)
864✔
81
                return log_error_errno(r, "Failed to get partition flags: %m");
×
82

83
        r = fdisk_partition_to_string(p, c, FDISK_FIELD_DEVICE, &device);
864✔
84
        if (r != 0)
864✔
85
                return log_error_errno(r, "Failed to get partition device name: %m");
×
86

87
        label_copy = strdup(label);
864✔
88
        if (!label_copy)
864✔
89
                return log_oom();
×
90

91
        type = gpt_partition_type_from_uuid(ptid);
864✔
92

93
        *ret = (PartitionInfo) {
1,728✔
94
                .partno = partno,
95
                .start = start,
96
                .size = size,
97
                .flags = flags,
98
                .type = ptid,
99
                .uuid = id,
100
                .label = TAKE_PTR(label_copy),
864✔
101
                .device = TAKE_PTR(device),
864✔
102
                .no_auto = FLAGS_SET(flags, SD_GPT_FLAG_NO_AUTO) && gpt_partition_type_knows_no_auto(type),
864✔
103
                .read_only = FLAGS_SET(flags, SD_GPT_FLAG_READ_ONLY) && gpt_partition_type_knows_read_only(type),
864✔
104
                .growfs = FLAGS_SET(flags, SD_GPT_FLAG_GROWFS) && gpt_partition_type_knows_growfs(type),
864✔
105
        };
106

107
        return 1; /* found! */
864✔
108
}
109

110
int find_suitable_partition(
28✔
111
                const char *device,
112
                uint64_t space,
113
                sd_id128_t *partition_type,
114
                PartitionInfo *ret) {
115

116
        _cleanup_(partition_info_destroy) PartitionInfo smallest = PARTITION_INFO_NULL;
×
117
        _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
28✔
118
        _cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
28✔
119
        size_t n_partitions;
28✔
120
        int r;
28✔
121

122
        assert(device);
28✔
123
        assert(ret);
28✔
124

125
        r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
28✔
126
        if (r < 0)
28✔
127
                return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
×
128

129
        if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
28✔
130
                return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
×
131

132
        r = fdisk_get_partitions(c, &t);
28✔
133
        if (r < 0)
28✔
134
                return log_error_errno(r, "Failed to acquire partition table: %m");
×
135

136
        n_partitions = fdisk_table_get_nents(t);
28✔
137
        for (size_t i = 0; i < n_partitions; i++)  {
140✔
138
                _cleanup_(partition_info_destroy) PartitionInfo pinfo = PARTITION_INFO_NULL;
84✔
139

140
                r = read_partition_info(c, t, i, &pinfo);
112✔
141
                if (r < 0)
112✔
142
                        return r;
×
143
                if (r == 0) /* not assigned */
112✔
144
                        continue;
×
145

146
                /* Filter out non-matching partition types */
147
                if (partition_type && !sd_id128_equal(pinfo.type, *partition_type))
168✔
148
                        continue;
56✔
149

150
                if (!streq_ptr(pinfo.label, "_empty")) /* used */
56✔
151
                        continue;
24✔
152

153
                if (space != UINT64_MAX && pinfo.size < space) /* too small */
32✔
154
                        continue;
×
155

156
                if (smallest.partno != SIZE_MAX && smallest.size <= pinfo.size) /* already found smaller */
32✔
157
                        continue;
4✔
158

159
                smallest = pinfo;
28✔
160
                pinfo = (PartitionInfo) PARTITION_INFO_NULL;
28✔
161
        }
162

163
        if (smallest.partno == SIZE_MAX)
28✔
164
                return log_error_errno(SYNTHETIC_ERRNO(ENOSPC), "No available partition of a suitable size found.");
×
165

166
        *ret = smallest;
28✔
167
        smallest = (PartitionInfo) PARTITION_INFO_NULL;
28✔
168

169
        return 0;
28✔
170
}
171

172
int patch_partition(
48✔
173
                const char *device,
174
                const PartitionInfo *info,
175
                PartitionChange change) {
176

177
        _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *pa = NULL;
48✔
178
        _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
48✔
179
        bool tweak_no_auto, tweak_read_only, tweak_growfs;
48✔
180
        GptPartitionType type;
48✔
181
        int r, fd;
48✔
182

183
        assert(device);
48✔
184
        assert(info);
48✔
185
        assert(change <= _PARTITION_CHANGE_MAX);
48✔
186

187
        if (change == 0) /* Nothing to do */
48✔
188
                return 0;
189

190
        r = fdisk_new_context_at(AT_FDCWD, device, /* read_only= */ false, /* sector_size= */ UINT32_MAX, &c);
48✔
191
        if (r < 0)
48✔
192
                return log_error_errno(r, "Failed to create fdisk context from '%s': %m", device);
×
193

194
        assert_se((fd = fdisk_get_devfd(c)) >= 0);
48✔
195

196
        /* Make sure udev doesn't read the device while we make changes (this lock is released automatically
197
         * by the kernel when the fd is closed, i.e. when the fdisk context is freed, hence no explicit
198
         * unlock by us here anywhere.) */
199
        if (flock(fd, LOCK_EX) < 0)
48✔
200
                return log_error_errno(errno, "Failed to lock block device '%s': %m", device);
×
201

202
        if (!fdisk_is_labeltype(c, FDISK_DISKLABEL_GPT))
48✔
203
                return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON), "Disk %s has no GPT disk label, not suitable.", device);
×
204

205
        r = fdisk_get_partition(c, info->partno, &pa);
48✔
206
        if (r < 0)
48✔
207
                return log_error_errno(r, "Failed to read partition %zu of GPT label of '%s': %m", info->partno, device);
×
208

209
        if (change & PARTITION_LABEL) {
48✔
210
                r = fdisk_partition_set_name(pa, info->label);
48✔
211
                if (r < 0)
48✔
212
                        return log_error_errno(r, "Failed to update partition label: %m");
×
213
        }
214

215
        if (change & PARTITION_UUID) {
48✔
216
                r = fdisk_partition_set_uuid(pa, SD_ID128_TO_UUID_STRING(info->uuid));
×
217
                if (r < 0)
×
218
                        return log_error_errno(r, "Failed to update partition UUID: %m");
×
219
        }
220

221
        type = gpt_partition_type_from_uuid(info->type);
48✔
222

223
        /* Tweak the read-only flag, but only if supported by the partition type */
224
        tweak_no_auto =
96✔
225
                FLAGS_SET(change, PARTITION_NO_AUTO) &&
48✔
226
                gpt_partition_type_knows_no_auto(type);
×
227
        tweak_read_only =
96✔
228
                FLAGS_SET(change, PARTITION_READ_ONLY) &&
48✔
229
                gpt_partition_type_knows_read_only(type);
×
230
        tweak_growfs =
96✔
231
                FLAGS_SET(change, PARTITION_GROWFS) &&
48✔
232
                gpt_partition_type_knows_growfs(type);
×
233

234
        if (change & PARTITION_FLAGS) {
48✔
235
                uint64_t flags;
×
236

237
                /* Update the full flags parameter, and import the read-only flag into it */
238

239
                flags = info->flags;
×
240
                if (tweak_no_auto)
×
241
                        SET_FLAG(flags, SD_GPT_FLAG_NO_AUTO, info->no_auto);
×
242
                if (tweak_read_only)
×
243
                        SET_FLAG(flags, SD_GPT_FLAG_READ_ONLY, info->read_only);
×
244
                if (tweak_growfs)
×
245
                        SET_FLAG(flags, SD_GPT_FLAG_GROWFS, info->growfs);
×
246

247
                r = fdisk_partition_set_attrs_as_uint64(pa, flags);
×
248
                if (r < 0)
×
249
                        return log_error_errno(r, "Failed to update partition flags: %m");
×
250

251
        } else if (tweak_no_auto || tweak_read_only || tweak_growfs) {
48✔
252
                uint64_t old_flags, new_flags;
×
253

254
                /* So we aren't supposed to update the full flags parameter, but we are supposed to update
255
                 * the RO flag of it. */
256

257
                r = fdisk_partition_get_attrs_as_uint64(pa, &old_flags);
×
258
                if (r < 0)
×
259
                        return log_error_errno(r, "Failed to get old partition flags: %m");
×
260

261
                new_flags = old_flags;
×
262
                if (tweak_no_auto)
×
263
                        SET_FLAG(new_flags, SD_GPT_FLAG_NO_AUTO, info->no_auto);
×
264
                if (tweak_read_only)
×
265
                        SET_FLAG(new_flags, SD_GPT_FLAG_READ_ONLY, info->read_only);
×
266
                if (tweak_growfs)
×
267
                        SET_FLAG(new_flags, SD_GPT_FLAG_GROWFS, info->growfs);
×
268

269
                if (new_flags != old_flags) {
×
270
                        r = fdisk_partition_set_attrs_as_uint64(pa, new_flags);
×
271
                        if (r < 0)
×
272
                                return log_error_errno(r, "Failed to update partition flags: %m");
×
273
                }
274
        }
275

276
        r = fdisk_set_partition(c, info->partno, pa);
48✔
277
        if (r < 0)
48✔
278
                return log_error_errno(r, "Failed to update partition: %m");
×
279

280
        r = fdisk_write_disklabel(c);
48✔
281
        if (r < 0)
48✔
282
                return log_error_errno(r, "Failed to write updated partition table: %m");
×
283

284
        return 0;
285
}
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