From d471be96c075ce20ed75fbbe4c7164de74b5eaa5 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 4 Apr 2024 15:46:24 +0200 Subject: [PATCH 1/4] Let sfdisk generate new disk id when initializing This removes the old disk id from the info passed to sfdisk, forcing it to generate a new disk id instead of preserving the old disk id when updating the partition table. This allows removing the code that randomizes the disk id after sfdisk updated the partition table. Also note that this code was previously already redudundant because after initializing there is more code that changes the disk id if it is identical (to support the non-initializing flow, but that is also run when initializing). --- rpi-clone | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/rpi-clone b/rpi-clone index 22e53a4..2752389 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1426,6 +1426,9 @@ Use -U for unattended even if initializing. part="${src_part_base}$n_image_parts" sfd1=$(echo "$sfd0" | sed "\/dev\/$part/s/size=[^,]*,//") + # Strip label-id, to let sfdisk generate a new disk id + sfd1=$(echo "$sfd1" | grep -v '^label-id: ') + if ((ext_part_num > 0 && !force_2_parts)) then part="${src_part_base}$ext_part_num" @@ -1466,17 +1469,11 @@ Use -U for unattended even if initializing. fi done printf "\n Resize success.\n" - printf " Changing destination Disk ID ..." - sync - sleep 2 - new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") - qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk > /dev/null sync sleep 2 partprobe "/dev/$dst_disk" sleep 2 - echo "" for ((p = n_image_parts + 1; p <= n_src_parts; p++)) do From e2b3f56521106cddfc9a95420b7b0719ccbfddb4 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 4 Apr 2024 15:52:14 +0200 Subject: [PATCH 2/4] Introduce change_disk_id() function This removes some duplicate code, preparing for making that code more complex to support GPT in an upcoming commit. --- rpi-clone | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rpi-clone b/rpi-clone index 2752389..368aa41 100755 --- a/rpi-clone +++ b/rpi-clone @@ -567,6 +567,12 @@ ext_label() printf -v "${4}" "%s" "$label_arg" } +change_disk_id() + { + new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + sfdisk --disk-id "$1" "$new_id" + } + get_src_disk() { partition=${1#/dev/} @@ -1463,8 +1469,7 @@ Use -U for unattended even if initializing. printf " Try running $PGM again.\n\n" # Don't let dst disk keep source disk ID. Can lead to remounts. - new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") - qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk > /dev/null + change_disk_id "/dev/$dst_disk" exit 1 fi done @@ -1634,8 +1639,7 @@ dst_disk_ID=${line#*x} if [ "$dst_disk_ID" == "$src_disk_ID" ] then qecho "Destination disk has same Disk ID as source, changing it." - new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") - qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk | grep changed + change_disk_id "/dev/$dst_disk" sync sleep 2 partprobe "/dev/$dst_disk" From b43dd66a4d14f0670c44f5d28336f68cc38a6480 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 4 Apr 2024 15:53:13 +0200 Subject: [PATCH 3/4] Use sfdisk for getting the disk id The sfdisk command has a convenient `--disk-id` option, saving the need to use grep to parse fdisk output. --- rpi-clone | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/rpi-clone b/rpi-clone index 368aa41..d773ebb 100755 --- a/rpi-clone +++ b/rpi-clone @@ -652,9 +652,7 @@ src_df_table=$(echo "$tmp" | sed "s/root/$dev/") n_src_parts=$(echo "$src_partition_table" | tail -n 1 | cut -d ":" -f 1) src_disk_size=$(echo "$src_partition_table" \ | grep "^/dev/$src_disk" | cut -d ":" -f 2 | tr -d 's') - -line=$(fdisk -l /dev/$src_disk | grep "Disk identifier:") -src_disk_ID=${line#*x} +src_disk_ID=$(sfdisk --disk-id "/dev/$src_disk") src_mount_table=$(findmnt -o source,target -n -l \ | grep -e "^/dev/$src_disk" -e "^$src_root_dev" | tr -s " ") @@ -1634,8 +1632,7 @@ else start_sec=$(date '+%s') fi -line=$(fdisk -l /dev/$dst_disk | grep "Disk identifier:") -dst_disk_ID=${line#*x} +dst_disk_ID=$(sfdisk --disk-id "/dev/$dst_disk") if [ "$dst_disk_ID" == "$src_disk_ID" ] then qecho "Destination disk has same Disk ID as source, changing it." @@ -1645,8 +1642,7 @@ then partprobe "/dev/$dst_disk" sleep 2 - line=$(fdisk -l /dev/$dst_disk | grep "Disk identifier:") - dst_disk_ID=${line#*x} + dst_disk_ID=$(sfdisk --disk-id "/dev/$dst_disk") if [ "$dst_disk_ID" == "$src_disk_ID" ] then qecho " Failed to set a new Disk ID." From 9bb92c228212548c282317b54cf56812552e3cd3 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 4 Apr 2024 15:54:13 +0200 Subject: [PATCH 4/4] Support GPT partition tables The sfdisk command already handles most of what is needed. This just removes the last-lba entry from sfdisk partition info (which is based on the source disk size and would otherwise limit the available destination space, if it is omitted the entire destination disk is usable), and makes change_disk_id support generating a longer UUID disk id when a GPT table is in use. --- rpi-clone | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/rpi-clone b/rpi-clone index d773ebb..e769e7f 100755 --- a/rpi-clone +++ b/rpi-clone @@ -62,8 +62,8 @@ confirm() } # sfdisk is in fdisk package -commands="rsync parted fdisk findmnt column fsck.vfat" -packages="rsync parted util-linux mount bsdmainutils dosfstools" +commands="rsync parted fdisk findmnt column fsck.vfat uuidgen" +packages="rsync parted util-linux mount bsdmainutils dosfstools uuid-runtime" need_packages="" idx=1 @@ -569,7 +569,18 @@ ext_label() change_disk_id() { - new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + case "$src_disk_table_type" in + msdos) + new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + ;; + gpt) + new_id=$(uuidgen) + ;; + *) + qecho " Unsupported partition table, cannot change Disk ID." + return 1 + ;; + esac sfdisk --disk-id "$1" "$new_id" } @@ -652,6 +663,8 @@ src_df_table=$(echo "$tmp" | sed "s/root/$dev/") n_src_parts=$(echo "$src_partition_table" | tail -n 1 | cut -d ":" -f 1) src_disk_size=$(echo "$src_partition_table" \ | grep "^/dev/$src_disk" | cut -d ":" -f 2 | tr -d 's') +src_disk_table_type=$(echo "$src_partition_table" \ + | grep "^/dev/$src_disk" | cut -d ":" -f 6 ) src_disk_ID=$(sfdisk --disk-id "/dev/$src_disk") src_mount_table=$(findmnt -o source,target -n -l \ @@ -1430,6 +1443,8 @@ Use -U for unattended even if initializing. part="${src_part_base}$n_image_parts" sfd1=$(echo "$sfd0" | sed "\/dev\/$part/s/size=[^,]*,//") + # Strip gpt last-lba marker, if any, that will needlessly limit to the src disk size. + sfd1=$(echo "$sfd1" | grep -v '^last-lba: ') # Strip label-id, to let sfdisk generate a new disk id sfd1=$(echo "$sfd1" | grep -v '^label-id: ')