diff options
Diffstat (limited to 'test/units/TEST-58-REPART.sh')
-rwxr-xr-x | test/units/TEST-58-REPART.sh | 1307 |
1 files changed, 1307 insertions, 0 deletions
diff --git a/test/units/TEST-58-REPART.sh b/test/units/TEST-58-REPART.sh new file mode 100755 index 0000000..8a014ac --- /dev/null +++ b/test/units/TEST-58-REPART.sh @@ -0,0 +1,1307 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +# shellcheck disable=SC2317 +set -eux +set -o pipefail + +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + +if ! command -v systemd-repart >/dev/null; then + echo "no systemd-repart" >/skipped + exit 77 +fi + +# shellcheck source=test/units/test-control.sh +. "$(dirname "$0")"/test-control.sh +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + +export SYSTEMD_LOG_LEVEL=debug +export PAGER=cat + +# Disable use of special glyphs such as → +export SYSTEMD_UTF8=0 + +seed=750b6cd5c4ae4012a15e7be3c29e6a47 + +if ! systemd-detect-virt --quiet --container; then + udevadm control --log-level debug +fi + +machine="$(uname -m)" +if [ "${machine}" = "x86_64" ]; then + root_guid=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 + root_uuid=60F33797-1D71-4DCB-AA6F-20564F036CD0 + root_uuid2=73A4CCD2-EAF5-44DA-A366-F99188210FDC + usr_guid=8484680C-9521-48C6-9C11-B0720656F69E + usr_uuid=7E3369DD-D653-4513-ADF5-B993A9F20C16 + architecture="x86-64" +elif [ "${machine}" = "i386" ] || [ "${machine}" = "i686" ] || [ "${machine}" = "x86" ]; then + root_guid=44479540-F297-41B2-9AF7-D131D5F0458A + root_uuid=02B4253F-29A4-404E-8972-1669D3B03C87 + root_uuid2=268E0FD3-B468-4806-A823-E533FE9BB9CC + usr_guid=75250D76-8CC6-458E-BD66-BD47CC81A812 + usr_uuid=7B42FFB0-B0E1-4395-B20B-C78F4A571648 + architecture="x86" +elif [ "${machine}" = "aarch64" ] || [ "${machine}" = "aarch64_be" ] || [ "${machine}" = "armv8b" ] || [ "${machine}" = "armv8l" ]; then + root_guid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE + root_uuid=055D0227-53A6-4033-85C3-9A5973EFF483 + root_uuid2=F7DBBE48-8FD0-4833-8411-AA34E7C8E60A + usr_guid=B0E01050-EE5F-4390-949A-9101B17104E9 + usr_uuid=FCE3C75E-D6A4-44C0-87F0-4C105183FB1F + architecture="arm64" +elif [ "${machine}" = "arm" ]; then + root_guid=69DAD710-2CE4-4E3C-B16C-21A1D49ABED3 + root_uuid=567DA89E-8DE2-4499-8D10-18F212DFF034 + root_uuid2=813ECFE5-4C89-4193-8A52-437493F2F96E + usr_guid=7D0359A3-02B3-4F0A-865C-654403E70625 + usr_uuid=71E93DC2-5073-42CB-8A84-A354E64D8966 + architecture="arm" +elif [ "${machine}" = "loongarch64" ]; then + root_guid=77055800-792C-4F94-B39A-98C91B762BB6 + root_uuid=D8EFC2D2-0133-41E4-BDCB-3B9F4CFDDDE8 + root_uuid2=36499F9E-0688-40C1-A746-EA8FD9543C56 + usr_guid=E611C702-575C-4CBE-9A46-434FA0BF7E3F + usr_uuid=031FFA75-00BB-49B6-A70D-911D2D82A5B7 + architecture="loongarch64" +elif [ "${machine}" = "ia64" ]; then + root_guid=993D8D3D-F80E-4225-855A-9DAF8ED7EA97 + root_uuid=DCF33449-0896-4EA9-BC24-7D58AEEF522D + root_uuid2=C2A6CAB7-ABEA-4FBA-8C48-CB4C52E6CA38 + usr_guid=4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA + usr_uuid=BC2BCCE7-80D6-449A-85CC-637424CE5241 + architecture="ia64" +elif [ "${machine}" = "s390x" ]; then + root_guid=5EEAD9A9-FE09-4A1E-A1D7-520D00531306 + root_uuid=7EBE0C85-E27E-48EC-B164-F4807606232E + root_uuid2=2A074E1C-2A19-4094-A0C2-24B1A5D52FCB + usr_guid=8A4F5770-50AA-4ED3-874A-99B710DB6FEA + usr_uuid=51171D30-35CF-4A49-B8B5-9478B9B796A5 + architecture="s390x" +elif [ "${machine}" = "ppc64le" ]; then + root_guid=C31C45E6-3F39-412E-80FB-4809C4980599 + root_uuid=061E67A1-092F-482F-8150-B525D50D6654 + root_uuid2=A6687CEF-4E4F-44E7-90B3-CDA52EA81739 + usr_guid=15BB03AF-77E7-4D4A-B12B-C0D084F7491C + usr_uuid=C0D0823B-8040-4C7C-A629-026248E297FB + architecture="ppc64-le" +else + echo "Unexpected uname -m: ${machine} in TEST-58-REPART.sh, please fix me" + exit 1 +fi + +testcase_basic() { + local defs imgs output + local loop volume + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** 1. create an empty image ***" + + systemd-repart --offline="$OFFLINE" \ + --empty=create \ + --size=1G \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118" + + echo "*** 2. Testing with root, root2, home, and swap ***" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root +EOF + + ln -s root.conf "$defs/root2.conf" + + tee "$defs/home.conf" <<EOF +[Partition] +Type=home +Label=home-first +Label=home-always-too-long-xxxxxxxxxxxxxx-%v +EOF + + tee "$defs/swap.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=64M +PaddingMinBytes=92M +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + --include-partitions=home,swap \ + --offline="$OFFLINE" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz1 : start= 2048, size= 1775576, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --empty=create \ + --size=50M \ + --seed="$seed" \ + --include-partitions=root,home \ + "$imgs/qqq" + + sfdisk -d "$imgs/qqq" | grep -v -e 'sector-size' -e '^$' + + systemd-repart --offline="$OFFLINE" \ + --empty=create \ + --size=1G \ + --dry-run=no \ + --seed="$seed" \ + --definitions "" \ + --copy-from="$imgs/qqq" \ + --copy-from="$imgs/qqq" \ + "$imgs/copy" + + output=$(sfdisk -d "$imgs/copy" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/copy +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/copy1 : start= 2048, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/copy2 : start= 35480, size= 33440, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/copy3 : start= 68920, size= 33440, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/copy4 : start= 102360, size= 33432, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/copy5 : start= 135792, size= 33440, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/copy6 : start= 169232, size= 33440, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\"" + + rm "$imgs/qqq" "$imgs/copy" # Save disk space + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + --empty=force \ + --defer-partitions=home,root \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" + + echo "*** 3. Testing with root, root2, home, swap, and another partition ***" + + tee "$defs/swap.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=64M +EOF + + tee "$defs/extra.conf" <<EOF +[Partition] +Type=linux-generic +Label=custom_label +UUID=a0a1a2a3a4a5a6a7a8a9aaabacadaeaf +EOF + + echo "Label=ignored_label" >>"$defs/home.conf" + echo "UUID=b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" >>"$defs/home.conf" + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\" +$imgs/zzz5 : start= 1908696, size= 188416, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"" + + echo "*** 4. Resizing to 2G ***" + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --size=2G \ + --dry-run=no \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 4194270 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\" +$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\"" + + echo "*** 5. Testing with root, root2, home, swap, another partition, and partition copy ***" + + dd if=/dev/urandom of="$imgs/block-copy" bs=4096 count=10240 + + tee "$defs/extra2.conf" <<EOF +[Partition] +Type=linux-generic +Label=block-copy +UUID=2a1d97e1d0a346cca26eadc643926617 +CopyBlocks=$imgs/block-copy +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --size=3G \ + --dry-run=no \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 6291422 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\" +$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\" +$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\"" + + cmp --bytes=$((4096*10240)) --ignore-initial=0:$((512*4194264)) "$imgs/block-copy" "$imgs/zzz" + + echo "*** 6. Testing Format=/Encrypt=/CopyFiles= ***" + + tee "$defs/extra3.conf" <<EOF +[Partition] +Type=linux-generic +Label=luks-format-copy +UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0 +Format=ext4 +Encrypt=yes +CopyFiles=$defs:/def +SizeMinBytes=48M +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --size=auto \ + --dry-run=no \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 6389726 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz2 : start= 593904, size= 591856, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\" +$imgs/zzz3 : start= 1185760, size= 591864, type=${root_guid}, uuid=${root_uuid2}, name=\"root-${architecture}-2\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\" +$imgs/zzz5 : start= 1908696, size= 2285568, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A0A1A2A3-A4A5-A6A7-A8A9-AAABACADAEAF, name=\"custom_label\" +$imgs/zzz6 : start= 4194264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2A1D97E1-D0A3-46CC-A26E-ADC643926617, name=\"block-copy\" +$imgs/zzz7 : start= 6291416, size= 98304, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=7B93D1F2-595D-4CE3-B0B9-837FBD9E63B0, name=\"luks-format-copy\"" + + if systemd-detect-virt --quiet --container; then + echo "Skipping encrypt mount tests in container." + return + fi + + loop="$(losetup -P --show --find "$imgs/zzz")" + udevadm wait --timeout 60 --settle "${loop:?}p7" + + volume="test-repart-$RANDOM" + + touch "$imgs/empty-password" + cryptsetup open --type=luks2 --key-file="$imgs/empty-password" "${loop}p7" "$volume" + mkdir -p "$imgs/mount" + mount -t ext4 "/dev/mapper/$volume" "$imgs/mount" + # Use deferred closing on the mapper and autoclear on the loop, so they are cleaned up on umount + cryptsetup close --deferred "$volume" + losetup -d "$loop" + diff -r "$imgs/mount/def" "$defs" >/dev/null + umount "$imgs/mount" +} + +testcase_dropin() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=64M +UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3 +EOF + + mkdir -p "$defs/root.conf.d" + tee "$defs/root.conf.d/override1.conf" <<EOF +[Partition] +Label=label1 +SizeMaxBytes=32M +EOF + + tee "$defs/root.conf.d/override2.conf" <<EOF +[Partition] +Label=label2 +EOF + + output=$(systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --empty=create \ + --size=100M \ + --json=pretty \ + "$imgs/zzz") + + diff -u <(echo "$output") - <<EOF +[ + { + "type" : "swap", + "label" : "label2", + "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3", + "partno" : 0, + "file" : "$defs/root.conf", + "node" : "$imgs/zzz1", + "offset" : 1048576, + "old_size" : 0, + "raw_size" : 33554432, + "size" : "-> 32M", + "old_padding" : 0, + "raw_padding" : 0, + "padding" : "-> 0B", + "activity" : "create", + "drop-in_files" : [ + "$defs/root.conf.d/override1.conf", + "$defs/root.conf.d/override2.conf" + ] + } +] +EOF +} + +testcase_multiple_definitions() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + mkdir -p "$defs/1" + tee "$defs/1/root1.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=32M +UUID=7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0 +Label=label1 +EOF + + mkdir -p "$defs/2" + tee "$defs/2/root2.conf" <<EOF +[Partition] +Type=swap +SizeMaxBytes=32M +UUID=837c3d67-21b3-478e-be82-7e7f83bf96d3 +Label=label2 +EOF + + output=$(systemd-repart --offline="$OFFLINE" \ + --definitions="$defs/1" \ + --definitions="$defs/2" \ + --empty=create \ + --size=100M \ + --json=pretty \ + "$imgs/zzz") + + diff -u <(echo "$output") - <<EOF +[ + { + "type" : "swap", + "label" : "label1", + "uuid" : "7b93d1f2-595d-4ce3-b0b9-837fbd9e63b0", + "partno" : 0, + "file" : "$defs/1/root1.conf", + "node" : "$imgs/zzz1", + "offset" : 1048576, + "old_size" : 0, + "raw_size" : 33554432, + "size" : "-> 32M", + "old_padding" : 0, + "raw_padding" : 0, + "padding" : "-> 0B", + "activity" : "create" + }, + { + "type" : "swap", + "label" : "label2", + "uuid" : "837c3d67-21b3-478e-be82-7e7f83bf96d3", + "partno" : 1, + "file" : "$defs/2/root2.conf", + "node" : "$imgs/zzz2", + "offset" : 34603008, + "old_size" : 0, + "raw_size" : 33554432, + "size" : "-> 32M", + "old_padding" : 0, + "raw_padding" : 0, + "padding" : "-> 0B", + "activity" : "create" + } +] +EOF +} + +testcase_copy_blocks() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** First, create a disk image and verify its in order ***" + + tee "$defs/esp.conf" <<EOF +[Partition] +Type=esp +SizeMinBytes=10M +Format=vfat +EOF + + tee "$defs/usr.conf" <<EOF +[Partition] +Type=usr-${architecture} +SizeMinBytes=10M +Format=ext4 +ReadOnly=yes +EOF + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root-${architecture} +SizeMinBytes=10M +Format=ext4 +MakeDirectories=/usr /efi +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --empty=create \ + --size=auto \ + --seed="$seed" \ + "$imgs/zzz" + + output=$(sfdisk --dump "$imgs/zzz") + + assert_in "$imgs/zzz1 : start= 2048, size= 20480, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=39107B09-615D-48FB-BA37-C663885FCE67, name=\"esp\"" "$output" + assert_in "$imgs/zzz2 : start= 22528, size= 20480, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output" + assert_in "$imgs/zzz3 : start= 43008, size= 20480, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:60\"" "$output" + + if systemd-detect-virt --quiet --container; then + echo "Skipping second part of copy blocks tests in container." + return + fi + + echo "*** Second, create another image with CopyBlocks=auto ***" + + tee "$defs/esp.conf" <<EOF +[Partition] +Type=esp +CopyBlocks=auto +EOF + + tee "$defs/usr.conf" <<EOF +[Partition] +Type=usr-${architecture} +ReadOnly=yes +CopyBlocks=auto +EOF + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root-${architecture} +CopyBlocks=auto +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --empty=create \ + --size=auto \ + --seed="$seed" \ + --image="$imgs/zzz" \ + "$imgs/yyy" + + cmp "$imgs/zzz" "$imgs/yyy" +} + +testcase_unaligned_partition() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** Operate on an image with unaligned partition ***" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root-${architecture} +EOF + + truncate -s 10g "$imgs/unaligned" + sfdisk "$imgs/unaligned" <<EOF +label: gpt + +start=2048, size=69044 +start=71092, size=3591848 +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/unaligned" + + output=$(sfdisk --dump "$imgs/unaligned") + + assert_in "$imgs/unaligned1 : start= 2048, size= 69044," "$output" + assert_in "$imgs/unaligned2 : start= 71092, size= 3591848," "$output" + assert_in "$imgs/unaligned3 : start= 3662944, size= 17308536, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output" +} + +testcase_issue_21817() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** testcase for #21817 ***" + + tee "$defs/test.conf" <<EOF +[Partition] +Type=root +EOF + + truncate -s 100m "$imgs/21817.img" + sfdisk "$imgs/21817.img" <<EOF +label: gpt + +size=50M, type=${root_guid} +, +EOF + + systemd-repart --offline="$OFFLINE" \ + --pretty=yes \ + --definitions "$imgs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/21817.img" + + output=$(sfdisk --dump "$imgs/21817.img") + + assert_in "$imgs/21817.img1 : start= 2048, size= 102400, type=${root_guid}," "$output" + # Accept both unpadded (pre-v2.38 util-linux) and padded (v2.38+ util-linux) sizes + assert_in "$imgs/21817.img2 : start= 104448, size= (100319| 98304)," "$output" +} + +testcase_issue_24553() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** testcase for #24553 ***" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root +SizeMinBytes=10G +SizeMaxBytes=120G +EOF + + tee "$imgs/partscript" <<EOF +label: gpt +label-id: C9FFE979-A415-C449-B729-78C7AA664B10 +unit: sectors +first-lba: 40 + +start=40, size=524288, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=F2E89C8A-DC5D-4C4C-A29C-6CFB643B74FD, name="ESP System Partition" +start=524328, size=14848000, type=${root_guid}, uuid=${root_uuid}, name="root-${architecture}" +EOF + + echo "*** 1. Operate on a small image compared with SizeMinBytes= ***" + truncate -s 8g "$imgs/zzz" + sfdisk "$imgs/zzz" <"$imgs/partscript" + + # This should fail, but not trigger assertions. + assert_rc 1 systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/zzz" + + output=$(sfdisk --dump "$imgs/zzz") + assert_in "$imgs/zzz2 : start= 524328, size= 14848000, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output" + + echo "*** 2. Operate on an larger image compared with SizeMinBytes= ***" + rm -f "$imgs/zzz" + truncate -s 12g "$imgs/zzz" + sfdisk "$imgs/zzz" <"$imgs/partscript" + + # This should succeed. + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/zzz" + + output=$(sfdisk --dump "$imgs/zzz") + assert_in "$imgs/zzz2 : start= 524328, size= 24641456, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output" + + echo "*** 3. Multiple partitions with Priority= (small disk) ***" + tee "$defs/root.conf" <<EOF +[Partition] +Type=root +SizeMinBytes=10G +SizeMaxBytes=120G +Priority=100 +EOF + + tee "$defs/usr.conf" <<EOF +[Partition] +Type=usr +SizeMinBytes=10M +Priority=10 +EOF + + rm -f "$imgs/zzz" + truncate -s 8g "$imgs/zzz" + sfdisk "$imgs/zzz" <"$imgs/partscript" + + # This should also succeed, but root is not extended. + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/zzz" + + output=$(sfdisk --dump "$imgs/zzz") + assert_in "$imgs/zzz2 : start= 524328, size= 14848000, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output" + assert_in "$imgs/zzz3 : start= 15372328, size= 1404848, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:59\"" "$output" + + echo "*** 4. Multiple partitions with Priority= (large disk) ***" + rm -f "$imgs/zzz" + truncate -s 12g "$imgs/zzz" + sfdisk "$imgs/zzz" <"$imgs/partscript" + + # This should also succeed, and root is extended. + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + "$imgs/zzz" + + output=$(sfdisk --dump "$imgs/zzz") + assert_in "$imgs/zzz2 : start= 524328, size= 20971520, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\"" "$output" + assert_in "$imgs/zzz3 : start= 21495848, size= 3669936, type=${usr_guid}, uuid=${usr_uuid}, name=\"usr-${architecture}\", attrs=\"GUID:59\"" "$output" +} + +testcase_zero_uuid() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** Test image with zero UUID ***" + + tee "$defs/root.conf" <<EOF +[Partition] +Type=root-${architecture} +UUID=null +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + "$imgs/zero" + + output=$(sfdisk --dump "$imgs/zero") + + assert_in "$imgs/zero1 : start= 2048, size= 20480, type=${root_guid}, uuid=00000000-0000-0000-0000-000000000000" "$output" +} + +testcase_verity() { + local defs imgs output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** dm-verity ***" + + tee "$defs/verity-data.conf" <<EOF +[Partition] +Type=root-${architecture} +CopyFiles=${defs} +Verity=data +VerityMatchKey=root +Minimize=guess +EOF + + tee "$defs/verity-hash.conf" <<EOF +[Partition] +Type=root-${architecture}-verity +Verity=hash +VerityMatchKey=root +Minimize=yes +EOF + + tee "$defs/verity-sig.conf" <<EOF +[Partition] +Type=root-${architecture}-verity-sig +Verity=signature +VerityMatchKey=root +EOF + + # Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents + tee >"$defs/verity.openssl.cnf" <<EOF +[ req ] +prompt = no +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +C = DE +ST = Test State +L = Test Locality +O = Org Name +OU = Org Unit Name +CN = Common Name +emailAddress = test@email.com +EOF + + openssl req \ + -config "$defs/verity.openssl.cnf" \ + -new -x509 \ + -newkey rsa:1024 \ + -keyout "$defs/verity.key" \ + -out "$defs/verity.crt" \ + -days 365 \ + -nodes + + mkdir -p /run/verity.d + ln -sf "$defs/verity.crt" /run/verity.d/ok.crt + + output=$(systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + --json=pretty \ + --private-key="$defs/verity.key" \ + --certificate="$defs/verity.crt" \ + "$imgs/verity") + + drh=$(jq -r ".[] | select(.type == \"root-${architecture}\") | .roothash" <<<"$output") + hrh=$(jq -r ".[] | select(.type == \"root-${architecture}-verity\") | .roothash" <<<"$output") + srh=$(jq -r ".[] | select(.type == \"root-${architecture}-verity-sig\") | .roothash" <<<"$output") + + assert_eq "$drh" "$hrh" + assert_eq "$hrh" "$srh" + + # Check that we can dissect, mount and unmount a repart verity image. (and that the image UUID is deterministic) + + if systemd-detect-virt --quiet --container; then + echo "Skipping verity test dissect part in container." + return + fi + + systemd-dissect "$imgs/verity" --root-hash "$drh" + systemd-dissect "$imgs/verity" --root-hash "$drh" --json=short | grep -q '"imageUuid":"1d2ce291-7cce-4f7d-bc83-fdb49ad74ebd"' + systemd-dissect "$imgs/verity" --root-hash "$drh" -M "$imgs/mnt" + systemd-dissect -U "$imgs/mnt" +} + +testcase_verity_explicit_block_size() { + local defs imgs loop + + if systemd-detect-virt --quiet --container; then + echo "Skipping verity block size tests in container." + return + fi + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + echo "*** varying-dm-verity-block-sizes ***" + + tee "$defs/verity-data.conf" <<EOF +[Partition] +Type=root-${architecture} +CopyFiles=${defs} +Verity=data +VerityMatchKey=root +Minimize=guess +EOF + + tee "$defs/verity-hash.conf" <<EOF +[Partition] +Type=root-${architecture}-verity +Verity=hash +VerityMatchKey=root +VerityHashBlockSizeBytes=1024 +VerityDataBlockSizeBytes=4096 +Minimize=yes +EOF + + systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + --json=pretty \ + "$imgs/verity" + + loop="$(losetup --partscan --show --find "$imgs/verity")" + + # Make sure the loopback device gets cleaned up + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs' ; losetup -d '$loop'" RETURN ERR + + udevadm wait --timeout 60 --settle "${loop:?}p1" "${loop:?}p2" + + # Check that the verity block sizes are as expected + veritysetup dump "${loop}p2" | grep 'Data block size:' | grep -q '4096' + veritysetup dump "${loop}p2" | grep 'Hash block size:' | grep -q '1024' +} + +testcase_exclude_files() { + local defs imgs root output + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + root="$(mktemp --directory "/var/tmp/test-repart.root.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs' '$root'" RETURN + chmod 0755 "$defs" + + echo "*** file exclusion ***" + + touch "$root/abc" + mkdir "$root/usr" + touch "$root/usr/def" + touch "$root/usr/qed" + mkdir "$root/tmp" + touch "$root/tmp/prs" + mkdir "$root/proc" + touch "$root/proc/prs" + mkdir "$root/zzz" + mkdir "$root/zzz/usr" + touch "$root/zzz/usr/prs" + mkdir "$root/zzz/proc" + touch "$root/zzz/proc/prs" + + tee "$defs/00-root.conf" <<EOF +[Partition] +Type=root-${architecture} +CopyFiles=/ +CopyFiles=/zzz:/ +CopyFiles=/:/oiu +ExcludeFilesTarget=/oiu/usr +EOF + + tee "$defs/10-usr.conf" <<EOF +[Partition] +Type=usr-${architecture} +CopyFiles=/usr:/ +ExcludeFiles=/usr/qed +EOF + + output=$(systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + --json=pretty \ + --root="$root" \ + "$imgs/zzz") + + if systemd-detect-virt --quiet --container; then + echo "Skipping issue 24786 test loop/mount parts in container." + return + fi + + loop=$(losetup -P --show -f "$imgs/zzz") + udevadm wait --timeout 60 --settle "${loop:?}p1" "${loop:?}p2" + + # Test that /usr/def did not end up in the root partition but other files did. + mkdir "$imgs/mnt" + mount -t ext4 "${loop}p1" "$imgs/mnt" + assert_rc 0 ls "$imgs/mnt/abc" + assert_rc 0 ls "$imgs/mnt/usr" + assert_rc 2 ls "$imgs/mnt/usr/def" + + # Test that /zzz/usr/prs did not end up in the root partition under /usr but did end up in /zzz/usr/prs + assert_rc 2 ls "$imgs/mnt/usr/prs" + assert_rc 0 ls "$imgs/mnt/zzz/usr/prs" + + # Test that /tmp/prs did not end up in the root partition but /tmp did. + assert_rc 0 ls "$imgs/mnt/tmp" + assert_rc 2 ls "$imgs/mnt/tmp/prs" + + # Test that /usr/qed did not end up in the usr partition but /usr/def did. + mount -t ext4 "${loop}p2" "$imgs/mnt/usr" + assert_rc 0 ls "$imgs/mnt/usr/def" + assert_rc 2 ls "$imgs/mnt/usr/qed" + + # Test that /zzz/proc/prs did not end up in the root partition but /proc did. + assert_rc 0 ls "$imgs/mnt/proc" + assert_rc 2 ls "$imgs/mnt/proc/prs" + + # Test that /zzz/usr/prs did not end up in the usr partition. + assert_rc 2 ls "$imgs/mnt/usr/prs" + + # Test that /oiu/ and /oiu/zzz ended up in the root partition but /oiu/usr did not. + assert_rc 0 ls "$imgs/mnt/oiu" + assert_rc 0 ls "$imgs/mnt/oiu/zzz" + assert_rc 2 ls "$imgs/mnt/oiu/usr" + + umount -R "$imgs/mnt" + losetup -d "$loop" +} + +testcase_minimize() { + local defs imgs output + + if systemd-detect-virt --quiet --container; then + echo "Skipping minimize test in container." + return + fi + + echo "*** minimization ***" + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + + for format in ext4 vfat erofs; do + if ! command -v "mkfs.$format" >/dev/null; then + continue + fi + + tee "$defs/root-$format.conf" <<EOF +[Partition] +Type=root-${architecture} +Format=${format} +CopyFiles=${defs} +Minimize=guess +EOF + done + + if command -v mksquashfs >/dev/null; then + tee "$defs/root-squashfs.conf" <<EOF +[Partition] +Type=root-${architecture} +Format=squashfs +CopyFiles=${defs} +Minimize=best +EOF + fi + + output=$(systemd-repart --offline="$OFFLINE" \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + --json=pretty \ + "$imgs/zzz") + + # Check that we can dissect, mount and unmount a minimized image. + + systemd-dissect "$imgs/zzz" + systemd-dissect "$imgs/zzz" -M "$imgs/mnt" + systemd-dissect -U "$imgs/mnt" +} + +testcase_free_area_calculation() { + local defs imgs output + + if ! command -v mksquashfs >/dev/null; then + echo "Skipping free area calculation test without squashfs." + return + fi + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + chmod 0755 "$defs" + + # https://github.com/systemd/systemd/issues/28225 + echo "*** free area calculation ***" + + tee "$defs/00-ESP.conf" <<EOF +[Partition] +Type = esp +Label = ESP +Format = vfat + +SizeMinBytes = 128M +SizeMaxBytes = 128M + +# Sufficient for testing +CopyFiles = /etc:/ +EOF + + tee "$defs/10-os.conf" <<EOF +[Partition] +Type = root-${architecture} +Label = test +Format = squashfs + +Minimize = best +# Sufficient for testing +CopyFiles = /etc/:/ + +VerityMatchKey = os +Verity = data +EOF + + tee "$defs/11-os-verity.conf" <<EOF +[Partition] +Type = root-${architecture}-verity +Label = test + +Minimize = best + +VerityMatchKey = os +Verity = hash +EOF + + # Set sector size for VFAT to 512 bytes because there will not be enough FAT clusters otherwise + output1=$(SYSTEMD_REPART_MKFS_OPTIONS_VFAT="-S 512" systemd-repart \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=create \ + --size=auto \ + --sector-size=4096 \ + --defer-partitions=esp \ + --json=pretty \ + "$imgs/zzz") + + # The second invocation + output2=$(SYSTEMD_REPART_MKFS_OPTIONS_VFAT="-S 512" systemd-repart \ + --definitions="$defs" \ + --seed="$seed" \ + --dry-run=no \ + --empty=allow \ + --size=auto \ + --sector-size=4096 \ + --defer-partitions=esp \ + --json=pretty \ + "$imgs/zzz") + + diff -u <(echo "$output1" | grep -E "(offset|raw_size|raw_padding)") <(echo "$output2" | grep -E "(offset|raw_size|raw_padding)") +} + +test_sector() { + local defs imgs output loop + local start size ratio + local sector="${1?}" + + if systemd-detect-virt --quiet --container; then + echo "Skipping sector size tests in container." + return + fi + + echo "*** sector sizes ***" + + defs="$(mktemp --directory "/tmp/test-repart.defs.XXXXXXXXXX")" + imgs="$(mktemp --directory "/var/tmp/test-repart.imgs.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '$defs' '$imgs'" RETURN + + tee "$defs/a.conf" <<EOF +[Partition] +Type=root +SizeMaxBytes=15M +SizeMinBytes=15M +EOF + tee "$defs/b.conf" <<EOF +[Partition] +Type=linux-generic +Weight=250 +EOF + + tee "$defs/c.conf" <<EOF +[Partition] +Type=linux-generic +Weight=750 +EOF + + truncate -s 100m "$imgs/$sector.img" + loop=$(losetup -b "$sector" -P --show -f "$imgs/$sector.img" ) + udevadm wait --timeout 60 --settle "${loop:?}" + + systemd-repart --offline="$OFFLINE" \ + --pretty=yes \ + --definitions="$defs" \ + --seed="$seed" \ + --empty=require \ + --dry-run=no \ + "$loop" + + sfdisk --verify "$loop" + output=$(sfdisk --dump "$loop") + losetup -d "$loop" + + ratio=$(( sector / 512 )) + start=$(( 2048 / ratio )) + size=$(( 30720 / ratio )) + assert_in "${loop}p1 : start= *${start}, size= *${size}, type=${root_guid}, uuid=${root_uuid}, name=\"root-${architecture}\", attrs=\"GUID:59\"" "$output" + start=$(( start + size )) + size=$(( 42992 / ratio )) + assert_in "${loop}p2 : start= *${start}, size= *${size}, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=DF71F5E3-080A-4D16-824B-18591B881380, name=\"linux-generic\"" "$output" + start=$(( start + size )) + size=$(( 129000 / ratio )) + 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" +} + +testcase_dropped_partitions() { + local workdir image defs + + workdir="$(mktemp --directory "/tmp/test-repart.dropped-partitions.XXXXXXXXXX")" + # shellcheck disable=SC2064 + trap "rm -rf '${workdir:?}'" RETURN + + image="$workdir/image.img" + truncate -s 32M "$image" + + defs="$workdir/defs" + mkdir "$defs" + echo -ne "[Partition]\nType=root\n" >"$defs/10-part1.conf" + echo -ne "[Partition]\nType=root\nSizeMinBytes=1T\nPriority=1\n" >"$defs/11-dropped-first.conf" + echo -ne "[Partition]\nType=root\n" >"$defs/12-part2.conf" + echo -ne "[Partition]\nType=root\nSizeMinBytes=1T\nPriority=2\n" >"$defs/13-dropped-second.conf" + + systemd-repart --empty=allow --pretty=yes --dry-run=no --definitions="$defs" "$image" + + sfdisk -q -l "$image" + [[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 2 ]] +} + +OFFLINE="yes" +run_testcases + +# Online image builds need loop devices so we can't run them in nspawn. +if ! systemd-detect-virt --container; then + OFFLINE="no" + run_testcases +fi + +# Valid block sizes on the Linux block layer are >= 512 and <= PAGE_SIZE, and +# must be powers of 2. Which leaves exactly four different ones to test on +# typical hardware +test_sector 512 +test_sector 1024 +test_sector 2048 +test_sector 4096 + +touch /testok |