hwdb: fix screen rotation for EXO Wings 2in1 w1125 (#36283)
[systemd.io.git] / test / units / TEST-58-REPART.sh
blobb3181cea9963587d5ec5ef3bf2f21cf86f847d47
1 #!/usr/bin/env bash
2 # SPDX-License-Identifier: LGPL-2.1-or-later
3 # shellcheck disable=SC2317
4 set -eux
5 set -o pipefail
7 if ! command -v systemd-repart >/dev/null; then
8 echo "no systemd-repart" >/skipped
9 exit 77
12 # shellcheck source=test/units/test-control.sh
13 . "$(dirname "$0")"/test-control.sh
14 # shellcheck source=test/units/util.sh
15 . "$(dirname "$0")"/util.sh
17 export SYSTEMD_LOG_LEVEL=debug
18 export PAGER=cat
20 # Disable use of special glyphs such as →
21 export SYSTEMD_UTF8=0
23 seed=750b6cd5c4ae4012a15e7be3c29e6a47
25 if ! systemd-detect-virt --quiet --container; then
26 udevadm control --log-level debug
29 esp_guid=C12A7328-F81F-11D2-BA4B-00A0C93EC93B
30 xbootldr_guid=BC13C2FF-59E6-4262-A352-B275FD6F7172
32 machine="$(uname -m)"
33 if [ "${machine}" = "x86_64" ]; then
34 root_guid=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709
35 root_uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0
36 root_uuid2=73A4CCD2-EAF5-44DA-A366-F99188210FDC
37 usr_guid=8484680C-9521-48C6-9C11-B0720656F69E
38 usr_uuid=7E3369DD-D653-4513-ADF5-B993A9F20C16
39 architecture="x86-64"
40 elif [ "${machine}" = "i386" ] || [ "${machine}" = "i686" ] || [ "${machine}" = "x86" ]; then
41 root_guid=44479540-F297-41B2-9AF7-D131D5F0458A
42 root_uuid=02B4253F-29A4-404E-8972-1669D3B03C87
43 root_uuid2=268E0FD3-B468-4806-A823-E533FE9BB9CC
44 usr_guid=75250D76-8CC6-458E-BD66-BD47CC81A812
45 usr_uuid=7B42FFB0-B0E1-4395-B20B-C78F4A571648
46 architecture="x86"
47 elif [ "${machine}" = "aarch64" ] || [ "${machine}" = "aarch64_be" ] || [ "${machine}" = "armv8b" ] || [ "${machine}" = "armv8l" ]; then
48 root_guid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE
49 root_uuid=055D0227-53A6-4033-85C3-9A5973EFF483
50 root_uuid2=F7DBBE48-8FD0-4833-8411-AA34E7C8E60A
51 usr_guid=B0E01050-EE5F-4390-949A-9101B17104E9
52 usr_uuid=FCE3C75E-D6A4-44C0-87F0-4C105183FB1F
53 architecture="arm64"
54 elif [ "${machine}" = "arm" ]; then
55 root_guid=69DAD710-2CE4-4E3C-B16C-21A1D49ABED3
56 root_uuid=567DA89E-8DE2-4499-8D10-18F212DFF034
57 root_uuid2=813ECFE5-4C89-4193-8A52-437493F2F96E
58 usr_guid=7D0359A3-02B3-4F0A-865C-654403E70625
59 usr_uuid=71E93DC2-5073-42CB-8A84-A354E64D8966
60 architecture="arm"
61 elif [ "${machine}" = "loongarch64" ]; then
62 root_guid=77055800-792C-4F94-B39A-98C91B762BB6
63 root_uuid=D8EFC2D2-0133-41E4-BDCB-3B9F4CFDDDE8
64 root_uuid2=36499F9E-0688-40C1-A746-EA8FD9543C56
65 usr_guid=E611C702-575C-4CBE-9A46-434FA0BF7E3F
66 usr_uuid=031FFA75-00BB-49B6-A70D-911D2D82A5B7
67 architecture="loongarch64"
68 elif [ "${machine}" = "ia64" ]; then
69 root_guid=993D8D3D-F80E-4225-855A-9DAF8ED7EA97
70 root_uuid=DCF33449-0896-4EA9-BC24-7D58AEEF522D
71 root_uuid2=C2A6CAB7-ABEA-4FBA-8C48-CB4C52E6CA38
72 usr_guid=4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA
73 usr_uuid=BC2BCCE7-80D6-449A-85CC-637424CE5241
74 architecture="ia64"
75 elif [ "${machine}" = "s390x" ]; then
76 root_guid=5EEAD9A9-FE09-4A1E-A1D7-520D00531306
77 root_uuid=7EBE0C85-E27E-48EC-B164-F4807606232E
78 root_uuid2=2A074E1C-2A19-4094-A0C2-24B1A5D52FCB
79 usr_guid=8A4F5770-50AA-4ED3-874A-99B710DB6FEA
80 usr_uuid=51171D30-35CF-4A49-B8B5-9478B9B796A5
81 architecture="s390x"
82 elif [ "${machine}" = "ppc64le" ]; then
83 root_guid=C31C45E6-3F39-412E-80FB-4809C4980599
84 root_uuid=061E67A1-092F-482F-8150-B525D50D6654
85 root_uuid2=A6687CEF-4E4F-44E7-90B3-CDA52EA81739
86 usr_guid=15BB03AF-77E7-4D4A-B12B-C0D084F7491C
87 usr_uuid=C0D0823B-8040-4C7C-A629-026248E297FB
88 architecture="ppc64-le"
89 else
90 echo "Unexpected uname -m: ${machine} in TEST-58-REPART.sh, please fix me"
91 exit 1
94 testcase_basic() {
95 local defs imgs output
96 local loop volume
98 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
99 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
100 # shellcheck disable=SC2064
101 trap "rm -rf '$defs' '$imgs'" RETURN
102 chmod 0755 "$defs"
104 echo "*** 1. create an empty image ***"
106 systemd-repart --offline="$OFFLINE" \
107 --empty=create \
108 --size=1G \
109 --seed="$seed" \
110 "$imgs/zzz"
112 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
114 assert_eq "$output" "label: gpt
115 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
116 device: $imgs/zzz
117 unit: sectors
118 first-lba: 2048
119 last-lba: 2097118"
121 echo "*** 2. Testing with root, root2, home, and swap ***"
123 tee "$defs/root.conf" <<EOF
124 [Partition]
125 Type=root
128 ln -s root.conf "$defs/root2.conf"
130 tee "$defs/home.conf" <<EOF
131 [Partition]
132 Type=home
133 Label=home-first
134 Label=home-always-too-long-xxxxxxxxxxxxxx-%v
137 tee "$defs/swap.conf" <<EOF
138 [Partition]
139 Type=swap
140 SizeMaxBytes=64M
141 PaddingMinBytes=92M
144 systemd-repart --offline="$OFFLINE" \
145 --definitions="$defs" \
146 --dry-run=no \
147 --seed="$seed" \
148 --include-partitions=home,swap \
149 --offline="$OFFLINE" \
150 "$imgs/zzz"
152 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
154 assert_eq "$output" "label: gpt
155 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
156 device: $imgs/zzz
157 unit: sectors
158 first-lba: 2048
159 last-lba: 2097118
160 $imgs/zzz1 : start= 2048, size= 1775576, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
161 $imgs/zzz2 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
163 systemd-repart --offline="$OFFLINE" \
164 --definitions="$defs" \
165 --empty=create \
166 --size=50M \
167 --seed="$seed" \
168 --include-partitions=root,home \
169 "$imgs/qqq"
171 sfdisk -d "$imgs/qqq" | grep -v -e 'sector-size' -e '^$'
173 systemd-repart --offline="$OFFLINE" \
174 --empty=create \
175 --size=1G \
176 --dry-run=no \
177 --seed="$seed" \
178 --definitions "" \
179 --copy-from="$imgs/qqq" \
180 --copy-from="$imgs/qqq" \
181 "$imgs/copy"
183 output=$(sfdisk -d "$imgs/copy" | grep -v -e 'sector-size' -e '^$')
185 assert_eq "$output" "label: gpt
186 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
187 device: $imgs/copy
188 unit: sectors
189 first-lba: 2048
190 last-lba: 2097118
191 $imgs/copy1 : start= 2048, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
192 $imgs/copy2 : start= 35480, size= 33440, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
193 $imgs/copy3 : start= 68920, size= 33440, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
194 $imgs/copy4 : start= 102360, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
195 $imgs/copy5 : start= 135792, size= 33440, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
196 $imgs/copy6 : start= 169232, size= 33440, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\""
198 rm "$imgs/qqq" "$imgs/copy" # Save disk space
200 systemd-repart --offline="$OFFLINE" \
201 --definitions="$defs" \
202 --dry-run=no \
203 --seed="$seed" \
204 --empty=force \
205 --defer-partitions=home,root \
206 "$imgs/zzz"
208 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
210 assert_eq "$output" "label: gpt
211 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
212 device: $imgs/zzz
213 unit: sectors
214 first-lba: 2048
215 last-lba: 2097118
216 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
218 systemd-repart --offline="$OFFLINE" \
219 --definitions="$defs" \
220 --dry-run=no \
221 --seed="$seed" \
222 "$imgs/zzz"
224 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
226 assert_eq "$output" "label: gpt
227 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
228 device: $imgs/zzz
229 unit: sectors
230 first-lba: 2048
231 last-lba: 2097118
232 $imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
233 $imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
234 $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
235 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\""
237 echo "*** 3. Testing with root, root2, home, swap, and another partition ***"
239 tee "$defs/swap.conf" <<EOF
240 [Partition]
241 Type=swap
242 SizeMaxBytes=64M
245 tee "$defs/extra.conf" <<EOF
246 [Partition]
247 Type=linux-generic
248 Label=custom_label
249 UUID=a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
252 echo "Label=ignored_label" >>"$defs/home.conf"
253 echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>"$defs/home.conf"
255 systemd-repart --offline="$OFFLINE" \
256 --definitions="$defs" \
257 --dry-run=no \
258 --seed="$seed" \
259 "$imgs/zzz"
261 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
263 assert_eq "$output" "label: gpt
264 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
265 device: $imgs/zzz
266 unit: sectors
267 first-lba: 2048
268 last-lba: 2097118
269 $imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
270 $imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
271 $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
272 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
273 $imgs/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\""
275 echo "*** 4. Resizing to 2G ***"
277 systemd-repart --offline="$OFFLINE" \
278 --definitions="$defs" \
279 --size=2G \
280 --dry-run=no \
281 --seed="$seed" \
282 "$imgs/zzz"
284 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
286 assert_eq "$output" "label: gpt
287 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
288 device: $imgs/zzz
289 unit: sectors
290 first-lba: 2048
291 last-lba: 4194270
292 $imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
293 $imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
294 $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
295 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
296 $imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\""
298 echo "*** 5. Testing with root, root2, home, swap, another partition, and partition copy ***"
300 dd if=/dev/urandom of="$imgs/block-copy" bs=4096 count=10240
302 tee "$defs/extra2.conf" <<EOF
303 [Partition]
304 Type=linux-generic
305 Label=block-copy
306 UUID=2a1d97e1d0a346cca26eadc643926617
307 CopyBlocks=$imgs/block-copy
310 systemd-repart --offline="$OFFLINE" \
311 --definitions="$defs" \
312 --size=3G \
313 --dry-run=no \
314 --seed="$seed" \
315 "$imgs/zzz"
317 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
319 assert_eq "$output" "label: gpt
320 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
321 device: $imgs/zzz
322 unit: sectors
323 first-lba: 2048
324 last-lba: 6291422
325 $imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
326 $imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
327 $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
328 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
329 $imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
330 $imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\""
332 cmp --bytes=$((4096*10240)) --ignore-initial=0:$((512*4194264)) "$imgs/block-copy" "$imgs/zzz"
334 echo "*** 6. Testing Format=/Encrypt=/CopyFiles= ***"
336 tee "$defs/extra3.conf" <<EOF
337 [Partition]
338 Type=linux-generic
339 Label=luks-format-copy
340 UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
341 Format=ext4
342 Encrypt=yes
343 CopyFiles=$defs:/def
344 SizeMinBytes=48M
347 systemd-repart --offline="$OFFLINE" \
348 --definitions="$defs" \
349 --size=auto \
350 --dry-run=no \
351 --seed="$seed" \
352 "$imgs/zzz"
354 output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$')
356 assert_eq "$output" "label: gpt
357 label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD
358 device: $imgs/zzz
359 unit: sectors
360 first-lba: 2048
361 last-lba: 6422494
362 $imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\"
363 $imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"
364 $imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"
365 $imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"
366 $imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"
367 $imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\"
368 $imgs/zzz7 : start= 6291416, size= 131072, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\""
370 if systemd-detect-virt --quiet --container; then
371 echo "Skipping encrypt mount tests in container."
372 return
375 loop="$(losetup -P --show --find "$imgs/zzz")"
376 udevadm wait --timeout 60 --settle "${loop:?}p7"
378 volume="test-repart-$RANDOM"
380 touch "$imgs/empty-password"
381 cryptsetup open --type=luks2 --key-file="$imgs/empty-password" "${loop}p7" "$volume"
382 mkdir -p "$imgs/mount"
383 mount -t ext4 "/dev/mapper/$volume" "$imgs/mount"
384 # Use deferred closing on the mapper and autoclear on the loop, so they are cleaned up on umount
385 cryptsetup close --deferred "$volume"
386 losetup -d "$loop"
387 diff -r "$imgs/mount/def" "$defs" >/dev/null
388 umount "$imgs/mount"
391 testcase_dropin() {
392 local defs imgs output
394 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
395 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
396 # shellcheck disable=SC2064
397 trap "rm -rf '$defs' '$imgs'" RETURN
398 chmod 0755 "$defs"
400 tee "$defs/root.conf" <<EOF
401 [Partition]
402 Type=swap
403 SizeMaxBytes=64M
404 UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
407 mkdir -p "$defs/root.conf.d"
408 tee "$defs/root.conf.d/override1.conf" <<EOF
409 [Partition]
410 Label=label1
411 SizeMaxBytes=32M
414 tee "$defs/root.conf.d/override2.conf" <<EOF
415 [Partition]
416 Label=label2
419 output=$(systemd-repart --offline="$OFFLINE" \
420 --definitions="$defs" \
421 --empty=create \
422 --size=100M \
423 --json=pretty \
424 "$imgs/zzz")
426 diff -u - <<EOF <(echo "$output")
429 "type" : "swap",
430 "label" : "label2",
431 "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
432 "partno" : 0,
433 "file" : "$defs/root.conf",
434 "node" : "$imgs/zzz1",
435 "offset" : 1048576,
436 "old_size" : 0,
437 "raw_size" : 33554432,
438 "size" : "-> 32M",
439 "old_padding" : 0,
440 "raw_padding" : 0,
441 "padding" : "-> 0B",
442 "activity" : "create",
443 "drop-in_files" : [
444 "$defs/root.conf.d/override1.conf",
445 "$defs/root.conf.d/override2.conf"
452 testcase_multiple_definitions() {
453 local defs imgs output
455 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
456 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
457 # shellcheck disable=SC2064
458 trap "rm -rf '$defs' '$imgs'" RETURN
459 chmod 0755 "$defs"
461 mkdir -p "$defs/1"
462 tee "$defs/1/root1.conf" <<EOF
463 [Partition]
464 Type=swap
465 SizeMaxBytes=32M
466 UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0
467 Label=label1
470 mkdir -p "$defs/2"
471 tee "$defs/2/root2.conf" <<EOF
472 [Partition]
473 Type=swap
474 SizeMaxBytes=32M
475 UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3
476 Label=label2
479 output=$(systemd-repart --offline="$OFFLINE" \
480 --definitions="$defs/1" \
481 --definitions="$defs/2" \
482 --empty=create \
483 --size=100M \
484 --json=pretty \
485 "$imgs/zzz")
487 diff -u - <<EOF <(echo "$output")
490 "type" : "swap",
491 "label" : "label1",
492 "uuid" : "7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0",
493 "partno" : 0,
494 "file" : "$defs/1/root1.conf",
495 "node" : "$imgs/zzz1",
496 "offset" : 1048576,
497 "old_size" : 0,
498 "raw_size" : 33554432,
499 "size" : "-> 32M",
500 "old_padding" : 0,
501 "raw_padding" : 0,
502 "padding" : "-> 0B",
503 "activity" : "create"
506 "type" : "swap",
507 "label" : "label2",
508 "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3",
509 "partno" : 1,
510 "file" : "$defs/2/root2.conf",
511 "node" : "$imgs/zzz2",
512 "offset" : 34603008,
513 "old_size" : 0,
514 "raw_size" : 33554432,
515 "size" : "-> 32M",
516 "old_padding" : 0,
517 "raw_padding" : 0,
518 "padding" : "-> 0B",
519 "activity" : "create"
525 testcase_copy_blocks() {
526 local defs imgs output
528 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
529 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
530 # shellcheck disable=SC2064
531 trap "rm -rf '$defs' '$imgs'" RETURN
532 chmod 0755 "$defs"
534 echo "*** First, create a disk image and verify its in order ***"
536 tee "$defs/esp.conf" <<EOF
537 [Partition]
538 Type=esp
539 SizeMinBytes=10M
540 Format=vfat
543 tee "$defs/usr.conf" <<EOF
544 [Partition]
545 Type=usr-${architecture}
546 SizeMinBytes=10M
547 Format=ext4
548 ReadOnly=yes
551 tee "$defs/root.conf" <<EOF
552 [Partition]
553 Type=root-${architecture}
554 SizeMinBytes=10M
555 Format=ext4
556 MakeDirectories=/usr /efi
559 systemd-repart --offline="$OFFLINE" \
560 --definitions="$defs" \
561 --empty=create \
562 --size=auto \
563 --seed="$seed" \
564 "$imgs/zzz"
566 output=$(sfdisk --dump "$imgs/zzz")
568 assert_in "$imgs/zzz1 : start= 2048, size= 20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" "$output"
569 assert_in "$imgs/zzz2 : start= 22528, size= 65536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
570 assert_in "$imgs/zzz3 : start= 88064, size= 65536, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" "$output"
572 if systemd-detect-virt --quiet --container; then
573 echo "Skipping second part of copy blocks tests in container."
574 return
577 echo "*** Second, create another image with CopyBlocks=auto ***"
579 tee "$defs/esp.conf" <<EOF
580 [Partition]
581 Type=esp
582 CopyBlocks=auto
585 tee "$defs/usr.conf" <<EOF
586 [Partition]
587 Type=usr-${architecture}
588 ReadOnly=yes
589 CopyBlocks=auto
592 tee "$defs/root.conf" <<EOF
593 [Partition]
594 Type=root-${architecture}
595 CopyBlocks=auto
598 systemd-repart --offline="$OFFLINE" \
599 --definitions="$defs" \
600 --empty=create \
601 --size=auto \
602 --seed="$seed" \
603 --image="$imgs/zzz" \
604 "$imgs/yyy"
606 cmp "$imgs/zzz" "$imgs/yyy"
609 testcase_unaligned_partition() {
610 local defs imgs output
612 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
613 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
614 # shellcheck disable=SC2064
615 trap "rm -rf '$defs' '$imgs'" RETURN
616 chmod 0755 "$defs"
618 echo "*** Operate on an image with unaligned partition ***"
620 tee "$defs/root.conf" <<EOF
621 [Partition]
622 Type=root-${architecture}
625 truncate -s 10g "$imgs/unaligned"
626 sfdisk "$imgs/unaligned" <<EOF
627 label: gpt
629 start=2048, size=69044
630 start=71092, size=3591848
633 systemd-repart --offline="$OFFLINE" \
634 --definitions="$defs" \
635 --seed="$seed" \
636 --dry-run=no \
637 "$imgs/unaligned"
639 output=$(sfdisk --dump "$imgs/unaligned")
641 assert_in "$imgs/unaligned1 : start= 2048, size= 69044," "$output"
642 assert_in "$imgs/unaligned2 : start= 71092, size= 3591848," "$output"
643 assert_in "$imgs/unaligned3 : start= 3662944, size= 17308536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
646 testcase_issue_21817() {
647 local defs imgs output
649 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
650 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
651 # shellcheck disable=SC2064
652 trap "rm -rf '$defs' '$imgs'" RETURN
653 chmod 0755 "$defs"
655 echo "*** testcase for #21817 ***"
657 tee "$defs/test.conf" <<EOF
658 [Partition]
659 Type=root
662 truncate -s 100m "$imgs/21817.img"
663 sfdisk "$imgs/21817.img" <<EOF
664 label: gpt
666 size=50M, type=${root_guid}
670 systemd-repart --offline="$OFFLINE" \
671 --pretty=yes \
672 --definitions "$imgs" \
673 --seed="$seed" \
674 --dry-run=no \
675 "$imgs/21817.img"
677 output=$(sfdisk --dump "$imgs/21817.img")
679 assert_in "$imgs/21817.img1 : start= 2048, size= 102400, type=${root_guid}," "$output"
680 # Accept both unpadded (pre-v2.38 util-linux) and padded (v2.38+ util-linux) sizes
681 assert_in "$imgs/21817.img2 : start= 104448, size= (100319| 98304)," "$output"
684 testcase_issue_24553() {
685 local defs imgs output
687 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
688 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
689 # shellcheck disable=SC2064
690 trap "rm -rf '$defs' '$imgs'" RETURN
691 chmod 0755 "$defs"
693 echo "*** testcase for #24553 ***"
695 tee "$defs/root.conf" <<EOF
696 [Partition]
697 Type=root
698 SizeMinBytes=10G
699 SizeMaxBytes=120G
702 tee "$imgs/partscript" <<EOF
703 label: gpt
704 label-id: C9FFE979-A415-C449-B729-78C7AA664B10
705 unit: sectors
706 first-lba: 40
708 start=40, size=524288, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=F2E89C8A-DC5D-4C4C-A29C-6CFB643B74FD, name="ESP System Partition"
709 start=524328, size=14848000, type=${root_guid}, uuid=${root_uuid}, name="root-${architecture}"
712 echo "*** 1. Operate on a small image compared with SizeMinBytes= ***"
713 truncate -s 8g "$imgs/zzz"
714 sfdisk "$imgs/zzz" <"$imgs/partscript"
716 # This should fail, but not trigger assertions.
717 assert_rc 1 systemd-repart --offline="$OFFLINE" \
718 --definitions="$defs" \
719 --seed="$seed" \
720 --dry-run=no \
721 "$imgs/zzz"
723 output=$(sfdisk --dump "$imgs/zzz")
724 assert_in "$imgs/zzz2 : start= 524328, size= 14848000, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output"
726 echo "*** 2. Operate on an larger image compared with SizeMinBytes= ***"
727 rm -f "$imgs/zzz"
728 truncate -s 12g "$imgs/zzz"
729 sfdisk "$imgs/zzz" <"$imgs/partscript"
731 # This should succeed.
732 systemd-repart --offline="$OFFLINE" \
733 --definitions="$defs" \
734 --seed="$seed" \
735 --dry-run=no \
736 "$imgs/zzz"
738 output=$(sfdisk --dump "$imgs/zzz")
739 assert_in "$imgs/zzz2 : start= 524328, size= 24641456, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output"
741 echo "*** 3. Multiple partitions with Priority= (small disk) ***"
742 tee "$defs/root.conf" <<EOF
743 [Partition]
744 Type=root
745 SizeMinBytes=10G
746 SizeMaxBytes=120G
747 Priority=100
750 tee "$defs/usr.conf" <<EOF
751 [Partition]
752 Type=usr
753 SizeMinBytes=10M
754 Priority=10
757 rm -f "$imgs/zzz"
758 truncate -s 8g "$imgs/zzz"
759 sfdisk "$imgs/zzz" <"$imgs/partscript"
761 # This should also succeed, but root is not extended.
762 systemd-repart --offline="$OFFLINE" \
763 --definitions="$defs" \
764 --seed="$seed" \
765 --dry-run=no \
766 "$imgs/zzz"
768 output=$(sfdisk --dump "$imgs/zzz")
769 assert_in "$imgs/zzz2 : start= 524328, size= 14848000, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output"
770 assert_in "$imgs/zzz3 : start= 15372328, size= 1404848, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:59\"" "$output"
772 echo "*** 4. Multiple partitions with Priority= (large disk) ***"
773 rm -f "$imgs/zzz"
774 truncate -s 12g "$imgs/zzz"
775 sfdisk "$imgs/zzz" <"$imgs/partscript"
777 # This should also succeed, and root is extended.
778 systemd-repart --offline="$OFFLINE" \
779 --definitions="$defs" \
780 --seed="$seed" \
781 --dry-run=no \
782 "$imgs/zzz"
784 output=$(sfdisk --dump "$imgs/zzz")
785 assert_in "$imgs/zzz2 : start= 524328, size= 20971520, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output"
786 assert_in "$imgs/zzz3 : start= 21495848, size= 3669936, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:59\"" "$output"
789 testcase_zero_uuid() {
790 local defs imgs output
792 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
793 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
794 # shellcheck disable=SC2064
795 trap "rm -rf '$defs' '$imgs'" RETURN
796 chmod 0755 "$defs"
798 echo "*** Test image with zero UUID ***"
800 tee "$defs/root.conf" <<EOF
801 [Partition]
802 Type=root-${architecture}
803 UUID=null
806 systemd-repart --offline="$OFFLINE" \
807 --definitions="$defs" \
808 --seed="$seed" \
809 --dry-run=no \
810 --empty=create \
811 --size=auto \
812 "$imgs/zero"
814 output=$(sfdisk --dump "$imgs/zero")
816 assert_in "$imgs/zero1 : start= 2048, size= 20480, type=${root_guid}, uuid=00000000-0000-0000-0000-000000000000" "$output"
819 testcase_verity() {
820 local defs imgs output
822 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
823 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
824 # shellcheck disable=SC2064
825 trap "rm -rf '$defs' '$imgs'" RETURN
826 chmod 0755 "$defs"
828 echo "*** dm-verity ***"
830 tee "$defs/verity-data.conf" <<EOF
831 [Partition]
832 Type=root-${architecture}
833 CopyFiles=${defs}
834 Verity=data
835 VerityMatchKey=root
836 Minimize=guess
839 tee "$defs/verity-hash.conf" <<EOF
840 [Partition]
841 Type=root-${architecture}-verity
842 Verity=hash
843 VerityMatchKey=root
844 Minimize=yes
847 tee "$defs/verity-sig.conf" <<EOF
848 [Partition]
849 Type=root-${architecture}-verity-sig
850 Verity=signature
851 VerityMatchKey=root
854 # Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
855 tee >"$defs/verity.openssl.cnf" <<EOF
856 [ req ]
857 prompt = no
858 distinguished_name = req_distinguished_name
860 [ req_distinguished_name ]
861 C = DE
862 ST = Test State
863 L = Test Locality
864 O = Org Name
865 OU = Org Unit Name
866 CN = Common Name
867 emailAddress = test@email.com
870 openssl req \
871 -config "$defs/verity.openssl.cnf" \
872 -new -x509 \
873 -newkey rsa:1024 \
874 -keyout "$defs/verity.key" \
875 -out "$defs/verity.crt" \
876 -days 365 \
877 -nodes
879 mkdir -p /run/verity.d
880 ln -sf "$defs/verity.crt" /run/verity.d/ok.crt
882 output=$(systemd-repart --offline="$OFFLINE" \
883 --definitions="$defs" \
884 --seed="$seed" \
885 --dry-run=no \
886 --empty=create \
887 --size=auto \
888 --json=pretty \
889 --private-key="$defs/verity.key" \
890 --certificate="$defs/verity.crt" \
891 "$imgs/verity")
893 drh=$(jq -r ".[] | select(.type == \"root-${architecture}\") | .roothash" <<<"$output")
894 hrh=$(jq -r ".[] | select(.type == \"root-${architecture}-verity\") | .roothash" <<<"$output")
895 srh=$(jq -r ".[] | select(.type == \"root-${architecture}-verity-sig\") | .roothash" <<<"$output")
897 assert_eq "$drh" "$hrh"
898 assert_eq "$hrh" "$srh"
900 # Check that we can dissect, mount and unmount a repart verity image. (and that the image UUID is deterministic)
902 if systemd-detect-virt --quiet --container; then
903 echo "Skipping verity test dissect part in container."
904 return
907 systemd-dissect "$imgs/verity" --root-hash "$drh"
908 systemd-dissect "$imgs/verity" --root-hash "$drh" --json=short | grep -q '"imageUuid":"1d2ce291-7cce-4f7d-bc83-fdb49ad74ebd"'
909 systemd-dissect "$imgs/verity" --root-hash "$drh" -M "$imgs/mnt"
910 systemd-dissect -U "$imgs/mnt"
913 testcase_verity_explicit_block_size() {
914 local defs imgs loop
916 if systemd-detect-virt --quiet --container; then
917 echo "Skipping verity block size tests in container."
918 return
921 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
922 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
924 # shellcheck disable=SC2064
925 trap "rm -rf '$defs' '$imgs'" RETURN
926 chmod 0755 "$defs"
928 echo "*** varying-dm-verity-block-sizes ***"
930 tee "$defs/verity-data.conf" <<EOF
931 [Partition]
932 Type=root-${architecture}
933 CopyFiles=${defs}
934 Verity=data
935 VerityMatchKey=root
936 Minimize=guess
939 tee "$defs/verity-hash.conf" <<EOF
940 [Partition]
941 Type=root-${architecture}-verity
942 Verity=hash
943 VerityMatchKey=root
944 VerityHashBlockSizeBytes=1024
945 VerityDataBlockSizeBytes=4096
946 Minimize=yes
949 systemd-repart --offline="$OFFLINE" \
950 --definitions="$defs" \
951 --seed="$seed" \
952 --dry-run=no \
953 --empty=create \
954 --size=auto \
955 --json=pretty \
956 "$imgs/verity"
958 loop="$(losetup --partscan --show --find "$imgs/verity")"
960 # Make sure the loopback device gets cleaned up
961 # shellcheck disable=SC2064
962 trap "rm -rf '$defs' '$imgs' ; losetup -d '$loop'" RETURN ERR
964 udevadm wait --timeout 60 --settle "${loop:?}p1" "${loop:?}p2"
966 # Check that the verity block sizes are as expected
967 veritysetup dump "${loop}p2" | grep 'Data block size:' | grep -q '4096'
968 veritysetup dump "${loop}p2" | grep 'Hash block size:' | grep -q '1024'
971 testcase_verity_hash_size_from_data_size() {
972 local defs imgs loop
974 if systemd-detect-virt --quiet --container; then
975 echo "Skipping verity hash size from data size test in container."
976 return
979 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
980 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
982 # shellcheck disable=SC2064
983 trap "rm -rf '$defs' '$imgs'" RETURN
984 chmod 0755 "$defs"
986 echo "*** dm-verity-hash-size-from-data-size ***"
988 # create minimized data partition with SizeMaxBytes=
989 tee "$defs/verity-data.conf" <<EOF
990 [Partition]
991 Type=root-${architecture}
992 CopyFiles=${defs}
993 Verity=data
994 VerityMatchKey=root
995 Minimize=guess
996 SizeMaxBytes=10G
999 # create hash partition, its size will be derived from SizeMaxBytes= of the data partition
1000 tee "$defs/verity-hash.conf" <<EOF
1001 [Partition]
1002 Type=root-${architecture}-verity
1003 Verity=hash
1004 VerityMatchKey=root
1005 VerityHashBlockSizeBytes=4096
1006 VerityDataBlockSizeBytes=4096
1009 systemd-repart --offline="$OFFLINE" \
1010 --definitions="$defs" \
1011 --seed="$seed" \
1012 --dry-run=no \
1013 --empty=create \
1014 --size=auto \
1015 --json=pretty \
1016 "$imgs/verity"
1018 loop="$(losetup --partscan --show --find "$imgs/verity")"
1020 # Make sure the loopback device gets cleaned up
1021 # shellcheck disable=SC2064
1022 trap "rm -rf '$defs' '$imgs' ; losetup -d '$loop'" RETURN ERR
1024 udevadm wait --timeout 60 --settle "${loop:?}p1" "${loop:?}p2"
1026 output=$(sfdisk -J "$loop")
1028 # size of the hash partition, as determined by calculate_verity_hash_size()
1029 # for 10GiB data partition and hash / data block size of 4096B
1030 hash_bytes=84557824
1031 hash_sectors_expected=$((hash_bytes / 512))
1033 hash_sectors_actual=$(jq -r ".partitiontable.partitions | map(select(.name == \"root-${architecture}-verity\")) | .[].size" <<<"$output")
1035 assert_eq "$hash_sectors_expected" "$hash_sectors_actual"
1037 data_sectors=$(jq -r ".partitiontable.partitions | map(select(.name == \"root-${architecture}\")) | .[].size" <<<"$output")
1038 data_bytes=$((data_sectors * 512))
1039 data_verity_blocks=$((data_bytes / 4096))
1041 # The actual data partition is much smaller than 10GiB, i.e. also smaller than 100MiB
1042 assert_rc 0 test $data_bytes -lt $((100 * 1024 * 1024))
1044 # Check that the verity hash tree is created from the actual on-disk data, not the custom size
1045 veritysetup dump "${loop}p2" | grep 'Data blocks:' | grep -q "$data_verity_blocks"
1048 testcase_exclude_files() {
1049 local defs imgs root output
1051 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1052 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1053 root="$(mktemp --directory "/var/tmp/test-repart.root.XXXXXXXXXX")"
1054 # shellcheck disable=SC2064
1055 trap "rm -rf '$defs' '$imgs' '$root'" RETURN
1056 chmod 0755 "$defs"
1058 echo "*** file exclusion ***"
1060 touch "$root/abc"
1061 mkdir "$root/usr"
1062 touch "$root/usr/def"
1063 touch "$root/usr/qed"
1064 mkdir "$root/tmp"
1065 touch "$root/tmp/prs"
1066 mkdir "$root/proc"
1067 touch "$root/proc/prs"
1068 mkdir "$root/zzz"
1069 mkdir "$root/zzz/usr"
1070 touch "$root/zzz/usr/prs"
1071 mkdir "$root/zzz/proc"
1072 touch "$root/zzz/proc/prs"
1074 tee "$defs/00-root.conf" <<EOF
1075 [Partition]
1076 Type=root-${architecture}
1077 CopyFiles=/
1078 CopyFiles=/zzz:/
1079 CopyFiles=/:/oiu
1080 ExcludeFilesTarget=/oiu/usr
1083 tee "$defs/10-usr.conf" <<EOF
1084 [Partition]
1085 Type=usr-${architecture}
1086 CopyFiles=/usr:/
1087 ExcludeFiles=/usr/qed
1090 output=$(systemd-repart --offline="$OFFLINE" \
1091 --definitions="$defs" \
1092 --seed="$seed" \
1093 --dry-run=no \
1094 --empty=create \
1095 --size=auto \
1096 --json=pretty \
1097 --root="$root" \
1098 "$imgs/zzz")
1100 if systemd-detect-virt --quiet --container; then
1101 echo "Skipping issue 24786 test loop/mount parts in container."
1102 return
1105 loop=$(losetup -P --show -f "$imgs/zzz")
1106 udevadm wait --timeout 60 --settle "${loop:?}p1" "${loop:?}p2"
1108 # Test that /usr/def did not end up in the root partition but other files did.
1109 mkdir "$imgs/mnt"
1110 mount -t ext4 "${loop}p1" "$imgs/mnt"
1111 assert_rc 0 ls "$imgs/mnt/abc"
1112 assert_rc 0 ls "$imgs/mnt/usr"
1113 assert_rc 2 ls "$imgs/mnt/usr/def"
1115 # Test that /zzz/usr/prs did not end up in the root partition under /usr but did end up in /zzz/usr/prs
1116 assert_rc 2 ls "$imgs/mnt/usr/prs"
1117 assert_rc 0 ls "$imgs/mnt/zzz/usr/prs"
1119 # Test that /tmp/prs did not end up in the root partition but /tmp did.
1120 assert_rc 0 ls "$imgs/mnt/tmp"
1121 assert_rc 2 ls "$imgs/mnt/tmp/prs"
1123 # Test that /usr/qed did not end up in the usr partition but /usr/def did.
1124 mount -t ext4 "${loop}p2" "$imgs/mnt/usr"
1125 assert_rc 0 ls "$imgs/mnt/usr/def"
1126 assert_rc 2 ls "$imgs/mnt/usr/qed"
1128 # Test that /zzz/proc/prs did not end up in the root partition but /proc did.
1129 assert_rc 0 ls "$imgs/mnt/proc"
1130 assert_rc 2 ls "$imgs/mnt/proc/prs"
1132 # Test that /zzz/usr/prs did not end up in the usr partition.
1133 assert_rc 2 ls "$imgs/mnt/usr/prs"
1135 # Test that /oiu/ and /oiu/zzz ended up in the root partition but /oiu/usr did not.
1136 assert_rc 0 ls "$imgs/mnt/oiu"
1137 assert_rc 0 ls "$imgs/mnt/oiu/zzz"
1138 assert_rc 2 ls "$imgs/mnt/oiu/usr"
1140 umount -R "$imgs/mnt"
1141 losetup -d "$loop"
1144 testcase_minimize() {
1145 local defs imgs output
1147 echo "*** minimization ***"
1149 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1150 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1151 # shellcheck disable=SC2064
1152 trap "rm -rf '$defs' '$imgs'" RETURN
1154 for format in ext4 vfat erofs; do
1155 if ! command -v "mkfs.$format" >/dev/null; then
1156 continue
1159 tee "$defs/root-$format.conf" <<EOF
1160 [Partition]
1161 Type=root-${architecture}
1162 Format=${format}
1163 CopyFiles=${defs}
1164 Minimize=guess
1166 done
1168 if command -v mksquashfs >/dev/null; then
1169 tee "$defs/root-squashfs.conf" <<EOF
1170 [Partition]
1171 Type=root-${architecture}
1172 Format=squashfs
1173 CopyFiles=${defs}
1174 Minimize=best
1178 output=$(systemd-repart --offline="$OFFLINE" \
1179 --definitions="$defs" \
1180 --seed="$seed" \
1181 --dry-run=no \
1182 --empty=create \
1183 --size=auto \
1184 --json=pretty \
1185 "$imgs/zzz")
1187 # Check that we can dissect, mount and unmount a minimized image.
1189 if systemd-detect-virt --quiet --container; then
1190 echo "Skipping minimize dissect, mount and unmount test in container."
1191 return
1194 systemd-dissect "$imgs/zzz"
1195 systemd-dissect "$imgs/zzz" -M "$imgs/mnt"
1196 systemd-dissect -U "$imgs/mnt"
1199 testcase_free_area_calculation() {
1200 local defs imgs output
1202 if ! command -v mksquashfs >/dev/null; then
1203 echo "Skipping free area calculation test without squashfs."
1204 return
1207 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1208 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1209 # shellcheck disable=SC2064
1210 trap "rm -rf '$defs' '$imgs'" RETURN
1211 chmod 0755 "$defs"
1213 # https://github.com/systemd/systemd/issues/28225
1214 echo "*** free area calculation ***"
1216 tee "$defs/00-ESP.conf" <<EOF
1217 [Partition]
1218 Type = esp
1219 Label = ESP
1220 Format = vfat
1222 SizeMinBytes = 128M
1223 SizeMaxBytes = 128M
1225 # Sufficient for testing
1226 CopyFiles = /etc:/
1229 tee "$defs/10-os.conf" <<EOF
1230 [Partition]
1231 Type = root-${architecture}
1232 Label = test
1233 Format = squashfs
1235 Minimize = best
1236 # Sufficient for testing
1237 CopyFiles = /etc/:/
1239 VerityMatchKey = os
1240 Verity = data
1243 tee "$defs/11-os-verity.conf" <<EOF
1244 [Partition]
1245 Type = root-${architecture}-verity
1246 Label = test
1248 Minimize = best
1250 VerityMatchKey = os
1251 Verity = hash
1254 # Set sector size for VFAT to 512 bytes because there will not be enough FAT clusters otherwise
1255 output1=$(SYSTEMD_REPART_MKFS_OPTIONS_VFAT="-S 512" systemd-repart \
1256 --definitions="$defs" \
1257 --seed="$seed" \
1258 --dry-run=no \
1259 --empty=create \
1260 --size=auto \
1261 --sector-size=4096 \
1262 --defer-partitions=esp \
1263 --json=pretty \
1264 "$imgs/zzz")
1266 # The second invocation
1267 output2=$(SYSTEMD_REPART_MKFS_OPTIONS_VFAT="-S 512" systemd-repart \
1268 --definitions="$defs" \
1269 --seed="$seed" \
1270 --dry-run=no \
1271 --empty=allow \
1272 --size=auto \
1273 --sector-size=4096 \
1274 --defer-partitions=esp \
1275 --json=pretty \
1276 "$imgs/zzz")
1278 diff -u <(echo "$output1" | grep -E "(offset|raw_size|raw_padding)") \
1279 <(echo "$output2" | grep -E "(offset|raw_size|raw_padding)")
1282 test_sector() {
1283 local defs imgs output loop
1284 local start size ratio
1285 local sector="${1?}"
1287 if systemd-detect-virt --quiet --container; then
1288 echo "Skipping sector size tests in container."
1289 return
1292 echo "*** sector sizes ***"
1294 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1295 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1296 # shellcheck disable=SC2064
1297 trap "rm -rf '$defs' '$imgs'" RETURN
1299 tee "$defs/a.conf" <<EOF
1300 [Partition]
1301 Type=root
1302 SizeMaxBytes=15M
1303 SizeMinBytes=15M
1305 tee "$defs/b.conf" <<EOF
1306 [Partition]
1307 Type=linux-generic
1308 Weight=250
1311 tee "$defs/c.conf" <<EOF
1312 [Partition]
1313 Type=linux-generic
1314 Weight=750
1317 truncate -s 100m "$imgs/$sector.img"
1318 loop=$(losetup -b "$sector" -P --show -f "$imgs/$sector.img" )
1319 udevadm wait --timeout 60 --settle "${loop:?}"
1321 systemd-repart --offline="$OFFLINE" \
1322 --pretty=yes \
1323 --definitions="$defs" \
1324 --seed="$seed" \
1325 --empty=require \
1326 --dry-run=no \
1327 "$loop"
1329 sfdisk --verify "$loop"
1330 output=$(sfdisk --dump "$loop")
1331 losetup -d "$loop"
1333 ratio=$(( sector / 512 ))
1334 start=$(( 2048 / ratio ))
1335 size=$(( 30720 / ratio ))
1336 assert_in "${loop}p1 : start= *${start}, size= *${size}, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output"
1337 start=$(( start + size ))
1338 size=$(( 42992 / ratio ))
1339 assert_in "${loop}p2 : start= *${start}, size= *${size}, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=DF71F5E3-080A-4D16-824B-18591B881380, name=\"linux-generic\"" "$output"
1340 start=$(( start + size ))
1341 size=$(( 129000 / ratio ))
1342 assert_in "${loop}p3 : start= *${start}, size= *${size}, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=DB081670-07AE-48CA-9F5E-813D5E40B976, name=\"linux-generic-2\"" "$output"
1345 testcase_dropped_partitions() {
1346 local workdir image defs
1348 workdir="$(mktemp --directory "/tmp/test-repart.dropped-partitions.XXXXXXXXXX")"
1349 # shellcheck disable=SC2064
1350 trap "rm -rf '${workdir:?}'" RETURN
1352 image="$workdir/image.img"
1353 truncate -s 32M "$image"
1355 defs="$workdir/defs"
1356 mkdir "$defs"
1357 echo -ne "[Partition]\nType=root\n" >"$defs/10-part1.conf"
1358 echo -ne "[Partition]\nType=root\nSizeMinBytes=1T\nPriority=1\n" >"$defs/11-dropped-first.conf"
1359 echo -ne "[Partition]\nType=root\n" >"$defs/12-part2.conf"
1360 echo -ne "[Partition]\nType=root\nSizeMinBytes=1T\nPriority=2\n" >"$defs/13-dropped-second.conf"
1362 systemd-repart --empty=allow --pretty=yes --dry-run=no --definitions="$defs" "$image"
1364 sfdisk -q -l "$image"
1365 [[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 2 ]]
1368 testcase_urandom() {
1369 local workdir image defs
1371 workdir="$(mktemp --directory "/tmp/test-repart.urandom.XXXXXXXXXX")"
1372 # shellcheck disable=SC2064
1373 trap "rm -rf '${workdir:?}'" RETURN
1375 image="$workdir/image.img"
1376 truncate -s 32M "$image"
1378 defs="$workdir/defs"
1379 mkdir "$defs"
1380 echo -ne "[Partition]\nType=swap\nCopyBlocks=/dev/urandom\n" >"$defs/10-urandom.conf"
1382 systemd-repart --empty=force --pretty=yes --dry-run=no --definitions="$defs" "$image"
1384 sfdisk -q -l "$image"
1385 [[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 1 ]]
1388 testcase_list_devices() {
1389 systemd-repart --list-devices
1392 testcase_compression() {
1393 local workdir image defs
1395 workdir="$(mktemp --directory "/tmp/test-repart.compression.XXXXXXXXXX")"
1396 # shellcheck disable=SC2064
1397 trap "rm -rf '${workdir:?}'" RETURN
1399 image="$workdir/image.img"
1400 defs="$workdir/defs"
1401 mkdir "$defs"
1403 # TODO: add btrfs once btrfs-progs v6.11 is available in distributions.
1404 for format in squashfs erofs; do
1405 case "$format" in
1406 squashfs)
1407 command -v mksquashfs >/dev/null || continue ;;
1409 command -v "mkfs.$format" || continue ;;
1410 esac
1412 [[ "$format" == "squashfs" ]] && compression=zstd
1413 [[ "$format" == "erofs" ]] && compression=lz4hc
1415 tee "$defs/10-root.conf" <<EOF
1416 [Partition]
1417 Type=root
1418 Format=$format
1419 Compression=$compression
1420 CompressionLevel=3
1421 CopyFiles=$defs:/def
1422 SizeMinBytes=48M
1425 rm -f "$image"
1426 systemd-repart --empty=create --size=auto --pretty=yes --dry-run=no --definitions="$defs" "$image"
1427 done
1430 testcase_random_seed() {
1431 local defs imgs output
1433 # For issue #34257
1435 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1436 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1437 # shellcheck disable=SC2064
1438 trap "rm -rf '$defs' '$imgs'" RETURN
1439 chmod 0755 "$defs"
1441 tee "$defs/root.conf" <<EOF
1442 [Partition]
1443 Type=root
1446 tee "$defs/home.conf" <<EOF
1447 [Partition]
1448 Type=home
1449 Label=home-first
1452 tee "$defs/swap.conf" <<EOF
1453 [Partition]
1454 Type=swap
1455 SizeMaxBytes=64M
1456 PaddingMinBytes=92M
1459 systemd-repart --offline="$OFFLINE" \
1460 --definitions="$defs" \
1461 --empty=create \
1462 --size=1G \
1463 --dry-run=no \
1464 --seed=random \
1465 --offline="$OFFLINE" \
1466 --json=pretty \
1467 "$imgs/zzz"
1469 sfdisk -d "$imgs/zzz"
1470 [[ "$(sfdisk -d "$imgs/zzz" | grep -F 'uuid=' | awk '{ print $8 }' | sort -u | wc -l)" == "3" ]]
1473 testcase_make_symlinks() {
1474 local defs imgs output
1476 if systemd-detect-virt --quiet --container; then
1477 echo "Skipping MakeSymlinks= test in container."
1478 return
1481 # For issue #34257
1483 defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")"
1484 imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")"
1485 # shellcheck disable=SC2064
1486 trap "rm -rf '$defs' '$imgs'" RETURN
1487 chmod 0755 "$defs"
1489 tee "$defs/root.conf" <<EOF
1490 [Partition]
1491 Type=root
1492 MakeDirectories=/dir
1493 MakeSymlinks=/foo:/bar
1494 MakeSymlinks=/dir/foo:/bar
1497 systemd-repart --offline="$OFFLINE" \
1498 --definitions="$defs" \
1499 --empty=create \
1500 --size=1G \
1501 --dry-run=no \
1502 --offline="$OFFLINE" \
1503 --json=pretty \
1504 "$imgs/zzz"
1506 systemd-dissect "$imgs/zzz" -M "$imgs/mnt"
1507 assert_eq "$(readlink "$imgs/mnt/foo")" "/bar"
1508 assert_eq "$(readlink "$imgs/mnt/dir/foo")" "/bar"
1509 systemd-dissect -U "$imgs/mnt"
1512 testcase_fallback_partitions() {
1513 local workdir image defs
1515 workdir="$(mktemp --directory "/tmp/test-repart.fallback.XXXXXXXXXX")"
1516 # shellcheck disable=SC2064
1517 trap "rm -rf '${workdir:?}'" RETURN
1519 image="$workdir/image.img"
1520 defs="$workdir/defs"
1521 mkdir "$defs"
1523 tee "$defs/10-esp.conf" <<EOF
1524 [Partition]
1525 Type=esp
1526 Format=vfat
1527 SizeMinBytes=10M
1530 tee "$defs/20-xbootldr.conf" <<EOF
1531 [Partition]
1532 Type=xbootldr
1533 Format=vfat
1534 SizeMinBytes=100M
1535 SupplementFor=10-esp
1538 # Blank disk => big ESP should be created
1540 systemd-repart --empty=create --size=auto --dry-run=no --definitions="$defs" "$image"
1542 output=$(sfdisk -d "$image")
1543 assert_in "${image}1 : start= 2048, size= 204800, type=${esp_guid}" "$output"
1544 assert_not_in "${image}2" "$output"
1546 # Disk with small ESP => ESP grows
1548 sfdisk "$image" <<EOF
1549 label: gpt
1550 size=10M, type=${esp_guid}
1553 systemd-repart --dry-run=no --definitions="$defs" "$image"
1555 output=$(sfdisk -d "$image")
1556 assert_in "${image}1 : start= 2048, size= 204800, type=${esp_guid}" "$output"
1557 assert_not_in "${image}2" "$output"
1559 # Disk with small ESP that can't grow => XBOOTLDR created
1561 truncate -s 150M "$image"
1562 sfdisk "$image" <<EOF
1563 label: gpt
1564 size=10M, type=${esp_guid},
1565 size=10M, type=${root_guid},
1568 systemd-repart --dry-run=no --definitions="$defs" "$image"
1570 output=$(sfdisk -d "$image")
1571 assert_in "${image}1 : start= 2048, size= 20480, type=${esp_guid}" "$output"
1572 assert_in "${image}3 : start= 43008, size= 264152, type=${xbootldr_guid}" "$output"
1574 # Disk with existing XBOOTLDR partition => XBOOTLDR grows, small ESP created
1576 sfdisk "$image" <<EOF
1577 label: gpt
1578 size=10M, type=${xbootldr_guid},
1581 systemd-repart --dry-run=no --definitions="$defs" "$image"
1583 output=$(sfdisk -d "$image")
1584 assert_in "${image}1 : start= 2048, size= 204800, type=${xbootldr_guid}" "$output"
1585 assert_in "${image}2 : start= 206848, size= 100312, type=${esp_guid}" "$output"
1588 OFFLINE="yes"
1589 run_testcases
1591 # Online image builds need loop devices so we can't run them in nspawn.
1592 if ! systemd-detect-virt --container; then
1593 OFFLINE="no"
1594 run_testcases
1597 # Valid block sizes on the Linux block layer are >= 512 and <= PAGE_SIZE, and
1598 # must be powers of 2. Which leaves exactly four different ones to test on
1599 # typical hardware
1600 test_sector 512
1601 test_sector 1024
1602 test_sector 2048
1603 test_sector 4096
1605 touch /testok