From 06abdd47ffb8df68e48b182c6650752fa24eaed9 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Mon, 13 Jul 2020 21:40:10 +0200 Subject: [PATCH 01/17] Use lsblk to show all FS labels Previously, e2label was used, but that only works for ext partitions. Using lsblk allows showing the filesystem labels for all filesystems supported by the kernel. --- rpi-clone | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/rpi-clone b/rpi-clone index b6baf53..5f2c397 100755 --- a/rpi-clone +++ b/rpi-clone @@ -739,13 +739,10 @@ do src_name[p]="${src_mounted_dir[p]}" fi - if [[ "$part_type" == *"ext"* ]] + label=`lsblk --raw --output label --noheadings "${src_device[p]}"` + if [ "$label" != "" ] then - label=`e2label ${src_device[p]} 2> /dev/null` - if [ "$label" != "" ] - then - src_label[p]="$label" - fi + src_label[p]="$label" fi done @@ -1139,16 +1136,15 @@ do if [[ "$part_type" == *"linux-swap"* ]] then dst_fs_type[p]="swap" - elif [[ "$part_type" == *"ext"* ]] + elif ((p == ext_num)) then - label=`e2label ${dst_device[p]} 2> /dev/null` + dst_fs_type[p]="EXT" + else + label=`lsblk --raw --output label --noheadings "${dst_device[p]}"` if [ "$label" != "" ] then dst_label[p]="$label" fi - elif ((p == ext_num)) - then - dst_fs_type[p]="EXT" fi done From 74eb6a75721e0f52e166d7de314fd71421989a62 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 14 Jul 2020 14:26:42 +0200 Subject: [PATCH 02/17] Use previously retrieved destination root FS label Now labels are retrieved for all destination partitions, there is no longer any point in separately retrieving the destination root label, just use the previously retrieved label. --- rpi-clone | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/rpi-clone b/rpi-clone index 5f2c397..4ff5380 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1766,12 +1766,7 @@ fi rm -f $clone/etc/udev/rules.d/70-persistent-net.rules -dst_root_vol_name=`e2label $dst_root_dev` - -if [ "$dst_root_vol_name" = "" ] -then - dst_root_vol_name="no label" -fi +dst_root_vol_name=${dst_label[$root_part_num]} if ((have_grub)) then From 3441dace223580ca45d5877de0b8ccb952873747 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Mon, 13 Jul 2020 21:44:46 +0200 Subject: [PATCH 03/17] Preserve existing FS labels where possible Instead of only setting FS labels on ext partitions when specified with the --label-partitions option and leave all other partitions unlabeled, this tries to copy the source filesystem labels to the destination where possible. Setting labels requires filesystem-specific commands or mkfs options, so not all filesystems are supported. For changing labels on existing partitions, only ext and fat partitions are supported. For mkfs a few more are supported, though these are probably not used in practice. This also refactors some of the code, introducing a `mkfs_label()` and `change_label()` function to prevent having to duplicate the filesystem-type checking code. This fixes #100. --- rpi-clone | 109 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 38 deletions(-) diff --git a/rpi-clone b/rpi-clone index 4ff5380..611f7bd 100755 --- a/rpi-clone +++ b/rpi-clone @@ -546,26 +546,80 @@ print_options() printf "%-23s:\n" "-----------------------" } -ext_label() +dst_part_label() { pnum=$1 fs_type=$2 - flag=$3 - label_arg="" + label="" if [ "$ext_label" != "" ] && [[ "$fs_type" == *"ext"* ]] then rep="${ext_label: -1}" if [ "$rep" == "#" ] then - label_arg=${ext_label:: -1} - label_arg="$flag $label_arg$pnum" + label="${ext_label:: -1}" elif ((pnum == root_part_num)) then - label_arg="$flag $ext_label" + label="$ext_label" fi fi - printf -v "${4}" "%s" "$label_arg" + + if [ -z "$label" -a -n "${src_label[$pnum]}" ] + then + label="${src_label[$pnum]}" + fi + printf -v "${3}" "%s" "$label" + } + +mkfs_label() + { + pnum=$1 + fs_type=$2 + + label_flag="" + case "$fs_type" in + # This list is probably overcomplete, but might simplify + # future additions. + vfat|msdos|exfat|fat16|fat32) + label_flag=-n + ;; + ext2|ext3|ext4|ntfs|xfs) + label_flag=-L + ;; + hfs|hfsplus) + label_flag=-v + ;; + reiserfs) + label_flag=-l + ;; + esac + + + label_arg="" + dst_part_label "$pnum" "$fs_type" label + if [ -n "$label" -a -n "$label_flag" ] + then + label_arg="$label_flag $label" + fi + printf -v "${3}" "%s" "$label_arg" + } + +change_label() + { + pnum=$1 + fs_type=$2 + dev=$3 + + dst_part_label "$pnum" "$fs_type" label + if [ "$label" != "" ] && [[ "$fs_type" == *"ext"* ]] + then + echo " e2label $dev $label" + e2label $dev $label + elif [ "$label" != "" ] && [[ "$fs_type" == *"fat"* ]] + then + echo " fatlabel $dev $label" + fatlabel $dev $label + fi } get_src_disk() @@ -1501,9 +1555,9 @@ Use -U for unattended even if initializing. if [ "${src_mounted_dir[p]}" == "/boot" ] && ((p == 1)) then - ext_label $p "$fs_type" "-L" label - printf " => mkfs -t $mkfs_type $label $dst_dev ..." - yes | mkfs -t $mkfs_type $label $dst_dev &>> /tmp/$PGM-output + mkfs_label $p "$fs_type" label_opt + printf " => mkfs -t $fs_type $label_opt $dst_dev ..." + yes | mkfs -t $mkfs_type $label_opt $dst_dev &>> /tmp/$PGM-output echo "" else if [ "$fs_type" == "swap" ] @@ -1514,9 +1568,9 @@ Use -U for unattended even if initializing. then if [ "${src_mounted_dir[p]}" != "" ] || ((p == n_image_parts)) then - ext_label $p $fs_type "-L" label - printf " => mkfs -t $mkfs_type $label $dst_dev ..." - yes | mkfs -t $mkfs_type $label $dst_dev &>> /tmp/$PGM-output + mkfs_label "$p" "$fs_type" label_opt + printf " => mkfs -t $mkfs_type $label_opt $dst_dev ..." + yes | mkfs -t $mkfs_type $label_opt $dst_dev &>> /tmp/$PGM-output echo "" if ((p == n_image_parts)) then @@ -1536,12 +1590,7 @@ Use -U for unattended even if initializing. else echo "" fi - ext_label $p $fs_type "" label - if [ "$label" != "" ] - then - echo " e2label $dst_dev $label" - e2label $dst_dev $label - fi + change_label "$p" "$fs_type" "$dst_dev" fi fi fi @@ -1663,13 +1712,7 @@ do sync_msg_done=1 dst_dev=/dev/${dst_part_base}${p} fs_type=${src_fs_type[$p]} - ext_label $p $fs_type "" label - if [ "$label" != "" ] - then - qecho " e2label $dst_dev $label" - e2label $dst_dev $label - fi - + change_label "$p" "$fs_type" "$dst_dev" mount_partition ${src_device[p]} $clone_src "" mount_partition $dst_dev $clone "$clone_src" unmount_list="$clone_src $clone" @@ -1681,12 +1724,7 @@ done qprintf "Syncing mounted partitions:\n" fs_type=${src_fs_type[$root_part_num]} -ext_label $root_part_num $fs_type "" label -if [ "$label" != "" ] -then - qecho " e2label $dst_root_dev $label" - e2label $dst_root_dev $label -fi +change_label "$root_part_num" "$fs_type" "$dst_root_dev" mount_partition $dst_root_dev $clone "" unmount_list="$clone" @@ -1709,12 +1747,7 @@ do dst_dev=/dev/${dst_part_base}${p} fs_type=${src_fs_type[$p]} - ext_label $p $fs_type "" label - if [ "$label" != "" ] - then - qecho " e2label $dst_dev $label" - e2label $dst_dev $label - fi + change_label "$p" "$fs_type" "$dst_dev" mount_partition "$dst_dev" "$dst_dir" "$unmount_list" rsync_file_system "${src_mounted_dir[p]}/" "${dst_dir}" "" From 2f062a9589958b0ababca97aaa67808426e36cc3 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 14:54:52 +0100 Subject: [PATCH 04/17] Run parted with --script This makes it non-interactive and prevents the script from silently hanging when parted finds something weird, e.g.: $ sudo rpi-clone /dev/sda Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes. This just hangs, because parted is waiting for an answer: $ sudo parted -m /dev/sda unit s print Warning: The driver descriptor says the physical block size is 2048 bytes, but Linux says it is 512 bytes. Ignore/Cancel? --- rpi-clone | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpi-clone b/rpi-clone index 611f7bd..32abda5 100755 --- a/rpi-clone +++ b/rpi-clone @@ -690,7 +690,7 @@ fi # src_root_dev, if on device other than booted, is not in src_partition_table # and src_fdisk_table, but is in src_df_table and src_mount_table # -src_partition_table=$(parted -m "/dev/$src_disk" unit s print | tr -d ';') +src_partition_table=$(parted --script -m "/dev/$src_disk" unit s print | tr -d ';') src_fdisk_table=$(fdisk -l /dev/$src_disk | grep "^/dev/") tmp=$(df | grep -e "^/dev/$src_disk" -e "^/dev/root" -e "$src_root_dev" \ @@ -1137,7 +1137,7 @@ then exit 1 fi -dst_partition_table=$(parted -m "/dev/$dst_disk" unit s print | tr -d ';') +dst_partition_table=$(parted --script -m "/dev/$dst_disk" unit s print | tr -d ';') n_dst_parts=$(echo "$dst_partition_table" | tail -n 1 | cut -d ":" -f 1) if [ "$n_dst_parts" == "/dev/$dst_disk" ] then From 0ca374dcd8fd873678d831af671032387f9e53ea Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 16:59:19 +0100 Subject: [PATCH 05/17] Run udevadm settle after running parted It seems that parted can force a partition scan (observed on a removable USB disk), which temporaly clears the filesystem labels from lsblk output. To prevent this, call udevadm settle to wait until all udev events are processed before continuing. --- rpi-clone | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpi-clone b/rpi-clone index 32abda5..cbf8e24 100755 --- a/rpi-clone +++ b/rpi-clone @@ -692,6 +692,9 @@ fi # src_partition_table=$(parted --script -m "/dev/$src_disk" unit s print | tr -d ';') src_fdisk_table=$(fdisk -l /dev/$src_disk | grep "^/dev/") +# Parted seems to force a partition rescan, which hides fs labels from +# lsblk output. Wait for kernel/udev to be done processing. +udevadm settle tmp=$(df | grep -e "^/dev/$src_disk" -e "^/dev/root" -e "$src_root_dev" \ | tr -s " ") @@ -1138,6 +1141,10 @@ then fi dst_partition_table=$(parted --script -m "/dev/$dst_disk" unit s print | tr -d ';') +# Parted seems to force a partition rescan, which hides fs labels from +# lsblk output. Wait for kernel/udev to be done processing. +udevadm settle + n_dst_parts=$(echo "$dst_partition_table" | tail -n 1 | cut -d ":" -f 1) if [ "$n_dst_parts" == "/dev/$dst_disk" ] then From 21227567cc8b286fb8ea167622d0e451e39c5009 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 17:04:58 +0100 Subject: [PATCH 06/17] Support UUID in addition to PARTUUID This supports systems where the filesystem's UUID is specified in fstab and on the kernel commandline. This is the first step in supporting Armbian, which uses UUID rather than PARTUUID. --- rpi-clone | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/rpi-clone b/rpi-clone index cbf8e24..a65d19e 100755 --- a/rpi-clone +++ b/rpi-clone @@ -801,6 +801,12 @@ do then src_label[p]="$label" fi + + fsuuid=`lsblk --raw --output UUID --noheadings "${src_device[p]}"` + if [ "$fsuuid" != "" ] + then + src_fsuuid[p]="$fsuuid" + fi done @@ -1118,7 +1124,8 @@ then SD_slot_dst=1 dst_part_base=${dst_disk}p if [ "$edit_fstab_name" == "" ] \ - && ! grep -q "^PARTUUID=" /etc/fstab + && ! grep -q "^PARTUUID=" /etc/fstab \ + && ! grep -q "^UUID=" /etc/fstab then edit_fstab_name=$dst_part_base assumed_fstab_edit=1 @@ -1206,6 +1213,11 @@ do then dst_label[p]="$label" fi + fsuuid=`lsblk --raw --output UUID --noheadings "${dst_device[p]}"` + if [ "$fsuuid" != "" ] + then + dst_fsuuid[p]="$fsuuid" + fi fi done @@ -1598,9 +1610,20 @@ Use -U for unattended even if initializing. echo "" fi change_label "$p" "$fs_type" "$dst_dev" + # TODO: Change uuid in case filesystem uuid is used in fstab? fi fi fi + + # Wait for kernel and udev to process changes (i.e. new + # UUIDs and labels) + udevadm settle + # Update UUID, just in case it changed + fsuuid=`lsblk --raw --output UUID --noheadings "$dst_dev"` + if [ "$fsuuid" != "" ] + then + dst_fsuuid[p]="$fsuuid" + fi done ext_label="" else @@ -1780,6 +1803,11 @@ then then qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "$cmdline_txt" + elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "$cmdline_txt" + then + new_fsuuid=${dst_fsuuid[root_part_num]} + qecho "Editing $cmdline_txt UUID to use $new_fsuuid" + sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "$cmdline_txt" elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $cmdline_txt then qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" @@ -1797,6 +1825,20 @@ if grep -q $src_disk_ID $fstab then qecho "Editing $fstab PARTUUID to use $dst_disk_ID" sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$fstab" +elif grep -q ^UUID= $fstab +then + for ((p = 1; p <= n_src_parts; p++)) + do + old_fsuuid=${src_fsuuid[p]} + new_fsuuid=${dst_fsuuid[p]} + if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$fstab"; + then + continue + fi + + qecho "Editing $fstab partition $p UUID to use $new_fsuuid" + sed -i "s/$old_fsuuid/${new_fsuuid}/" "$fstab" + done elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $fstab then qecho "Editing $fstab references from $src_part_base to $edit_fstab_name" From 0505ad9f3980952fa6c559c79cc1c1ce056ce09e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 17:17:03 +0100 Subject: [PATCH 07/17] Refactor cmdline.txt with more variables This removes all hardcoded references to cmdline.txt and cmdline.boot by removing the `$clone` prefix from cmdline_txt and introducing a cmdline_txt variable. In addition, this adds some quoting to any lines modified to be a bit more robust when spaces are involved. This should not change behavior (apart from maybe in cases with spaces that were previously broken), the commands ran should be identical. --- rpi-clone | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/rpi-clone b/rpi-clone index a65d19e..79d50ee 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1789,35 +1789,38 @@ qecho "" # Fix PARTUUID or device name references in cmdline.txt and fstab # fstab=${clone}/etc/fstab -cmdline_txt=${clone}/boot/cmdline.txt +cmdline_txt=/boot/cmdline.txt +cmdline_boot=/boot/cmdline.boot -if [ -f $cmdline_txt ] +if [ -f "${clone}${cmdline_txt}" ] then if ((leave_sd_usb_boot && SD_slot_dst)) then qecho "Leaving SD to USB boot alone." - cp $cmdline_txt ${clone}/boot/cmdline.boot - cmdline_txt=${clone}/boot/cmdline.boot + cp "${clone}${cmdline_txt}" "${clone}${cmdline_boot}" + cmdline_txt=${cmdline_boot} fi - if grep -q $src_disk_ID $cmdline_txt + if grep -q "$src_disk_ID" "${clone}${cmdline_txt}" then qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "$cmdline_txt" - elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "$cmdline_txt" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${clone}${cmdline_txt}" + elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${clone}${cmdline_txt}" then new_fsuuid=${dst_fsuuid[root_part_num]} qecho "Editing $cmdline_txt UUID to use $new_fsuuid" - sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "$cmdline_txt" - elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $cmdline_txt + sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${clone}${cmdline_txt}" + elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${clone}${cmdline_txt}" then qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/$edit_fstab_name/" "$cmdline_txt" + sed -i "s/${src_part_base}/$edit_fstab_name/" "${clone}${cmdline_txt}" fi if ((leave_sd_usb_boot && SD_slot_boot)) then qecho "Copying USB cmdline.txt to SD card to set up USB boot." - cp /boot/cmdline.txt /boot/cmdline.boot - cp $cmdline_txt /boot/cmdline.txt + # Note that this leaves out $clone to modify the original SD + # card to boot from the clone instead + cp "${cmdline_txt}" "${cmdline_boot}" + cp "${clone}${cmdline_txt}" "${cmdline_txt}" fi fi From ec4405b158c13a1eef214d34aba634a76973aae8 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 17:06:27 +0100 Subject: [PATCH 08/17] Support Armbian by modifying armbianEnv.txt On Armbian, the kernel commandline (or at least the root device to use) is stored in armbianEnv.txt rather than cmdline.txt, so update that if it exists and cmdline.txt does not. The actual operation on this file is just replacing UUIDs inside the file, so it works even though the syntax of the file is different. --- rpi-clone | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rpi-clone b/rpi-clone index 79d50ee..843f3c7 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1791,6 +1791,10 @@ qecho "" fstab=${clone}/etc/fstab cmdline_txt=/boot/cmdline.txt cmdline_boot=/boot/cmdline.boot +if [ ! -f "${clone}${cmdline_txt}" ]; then + cmdline_txt=/boot/armbianEnv.txt + cmdline_boot=/boot/armbianEnv.boot +fi if [ -f "${clone}${cmdline_txt}" ] then From 34dda4f718a9e69caedfc18c402d3451c959454e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 15 Mar 2022 17:06:27 +0100 Subject: [PATCH 09/17] Support Ubuntu by modifying /boot/firmware/cmdline.txt On Ubuntu, cmdline.txt is stored in a subdirectory, so if the file does not exist in the usual location, fall back to the Ubuntu location (and fall back to the Armbian version if the Ubuntu version does not exist either). Note that this does not support Ubuntu completely out of the box, since it uses filesystem labels instead of UUIDs for mounting, but if you manualy change them to UUIDs, this change allows cloning to work. --- rpi-clone | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpi-clone b/rpi-clone index 843f3c7..cda3f63 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1791,6 +1791,11 @@ qecho "" fstab=${clone}/etc/fstab cmdline_txt=/boot/cmdline.txt cmdline_boot=/boot/cmdline.boot +if [ ! -f "${clone}${cmdline_txt}" ]; then + # Ubuntu + cmdline_txt=/boot/firmware/cmdline.txt + cmdline_boot=/boot/firmware/cmdline.boot +fi if [ ! -f "${clone}${cmdline_txt}" ]; then cmdline_txt=/boot/armbianEnv.txt cmdline_boot=/boot/armbianEnv.boot From 31b2c6b11bf8fc47b030c7ac5c46b517ceabaec8 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 20:38:39 +0200 Subject: [PATCH 10/17] Refactor cmdline/fstab updating into functions This mostly moves code into functions, but also makes minor changes to how the code is called to prepare for more reuse of this code. Moving these functions up in the file with the other functions is left for the next commit to make review easier. Diff best viewed with --ignore-all-space. --- rpi-clone | 137 +++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 63 deletions(-) diff --git a/rpi-clone b/rpi-clone index cda3f63..f49c3f3 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1786,77 +1786,88 @@ do done qecho "" -# Fix PARTUUID or device name references in cmdline.txt and fstab -# -fstab=${clone}/etc/fstab -cmdline_txt=/boot/cmdline.txt -cmdline_boot=/boot/cmdline.boot -if [ ! -f "${clone}${cmdline_txt}" ]; then - # Ubuntu - cmdline_txt=/boot/firmware/cmdline.txt - cmdline_boot=/boot/firmware/cmdline.boot -fi -if [ ! -f "${clone}${cmdline_txt}" ]; then - cmdline_txt=/boot/armbianEnv.txt - cmdline_boot=/boot/armbianEnv.boot -fi +# Fix PARTUUID/UUID or device name references in cmdline.txt +fixup_boot_partition() + { + src_mount=$1 + dst_mount=$2 + + # Just try all flavors + # Paths are below the /boot directory/mountpoint + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /cmdline.txt /cmdline.boot + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /armbianEnv.txt /armbianEnv.boot + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /firmware/cmdline.txt /firmware/cmdline.boot # Ubuntu + } -if [ -f "${clone}${cmdline_txt}" ] -then - if ((leave_sd_usb_boot && SD_slot_dst)) +fixup_cmdline_txt() + { + src_mount=$1 + dst_mount=$2 + cmdline_txt=$3 + cmdline_boot=$4 + + if [ -f "${dst_mount}${cmdline_txt}" ] then - qecho "Leaving SD to USB boot alone." - cp "${clone}${cmdline_txt}" "${clone}${cmdline_boot}" - cmdline_txt=${cmdline_boot} + if ((leave_sd_usb_boot && SD_slot_dst)) + then + qecho "Leaving SD to USB boot alone." + cp "${dst_mount}${cmdline_txt}" "${dst_mount}${cmdline_boot}" + cmdline_txt=${cmdline_boot} + fi + if grep -q "$src_disk_ID" "${dst_mount}${cmdline_txt}" + then + qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${dst_mount}${cmdline_txt}" + elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${dst_mount}${cmdline_txt}" + then + new_fsuuid=${dst_fsuuid[root_part_num]} + qecho "Editing $cmdline_txt UUID to use $new_fsuuid" + sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${dst_mount}${cmdline_txt}" + elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${dst_mount}${cmdline_txt}" + then + qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/$edit_fstab_name/" "${dst_mount}${cmdline_txt}" + fi + if ((leave_sd_usb_boot && SD_slot_boot)) + then + qecho "Copying USB cmdline.txt to SD card to set up USB boot." + # Note that this leaves out $clone to modify the original SD + # card to boot from the clone instead + cp "${src_mount}${cmdline_txt}" "${src_mount}${cmdline_boot}" + cp "${dst_mount}${cmdline_txt}" "${src_mount}${cmdline_txt}" + fi fi - if grep -q "$src_disk_ID" "${clone}${cmdline_txt}" - then - qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${clone}${cmdline_txt}" - elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${clone}${cmdline_txt}" + } + +fixup_device_references_in_file() { + file=$1 + if grep -q $src_disk_ID $file then - new_fsuuid=${dst_fsuuid[root_part_num]} - qecho "Editing $cmdline_txt UUID to use $new_fsuuid" - sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${clone}${cmdline_txt}" - elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${clone}${cmdline_txt}" + qecho "Editing $file PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$file" + elif grep -q ^UUID= $file then - qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/$edit_fstab_name/" "${clone}${cmdline_txt}" - fi - if ((leave_sd_usb_boot && SD_slot_boot)) + for ((p = 1; p <= n_src_parts; p++)) + do + old_fsuuid=${src_fsuuid[p]} + new_fsuuid=${dst_fsuuid[p]} + if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$file"; + then + continue + fi + + qecho "Editing $file partition $p UUID to use $new_fsuuid" + sed -i "s/$old_fsuuid/${new_fsuuid}/" "$file" + done + elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $file then - qecho "Copying USB cmdline.txt to SD card to set up USB boot." - # Note that this leaves out $clone to modify the original SD - # card to boot from the clone instead - cp "${cmdline_txt}" "${cmdline_boot}" - cp "${clone}${cmdline_txt}" "${cmdline_txt}" + qecho "Editing $file references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/${edit_fstab_name}/" "$file" fi -fi - -if grep -q $src_disk_ID $fstab -then - qecho "Editing $fstab PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$fstab" -elif grep -q ^UUID= $fstab -then - for ((p = 1; p <= n_src_parts; p++)) - do - old_fsuuid=${src_fsuuid[p]} - new_fsuuid=${dst_fsuuid[p]} - if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$fstab"; - then - continue - fi - - qecho "Editing $fstab partition $p UUID to use $new_fsuuid" - sed -i "s/$old_fsuuid/${new_fsuuid}/" "$fstab" - done -elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $fstab -then - qecho "Editing $fstab references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/${edit_fstab_name}/" "$fstab" -fi +} +fixup_boot_partition /boot "${clone}/boot" +fixup_device_references_in_file "${clone}/etc/fstab" rm -f $clone/etc/udev/rules.d/70-persistent-net.rules From 0c23cb23e53114dfdc4beca6d058d1f7f6f6c88e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 20:57:20 +0200 Subject: [PATCH 11/17] Move cmdline/fstab updating functions up in file This puts them together with the other function. This commit only moves code, without making any changes. --- rpi-clone | 161 +++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/rpi-clone b/rpi-clone index f49c3f3..c657547 100755 --- a/rpi-clone +++ b/rpi-clone @@ -637,6 +637,87 @@ get_src_disk() printf -v "${3}" "%s" "$num" } +# Fix PARTUUID/UUID or device name references in cmdline.txt +fixup_boot_partition() + { + src_mount=$1 + dst_mount=$2 + + # Just try all flavors + # Paths are below the /boot directory/mountpoint + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /cmdline.txt /cmdline.boot + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /armbianEnv.txt /armbianEnv.boot + fixup_cmdline_txt "${src_mount}" "${dst_mount}" /firmware/cmdline.txt /firmware/cmdline.boot # Ubuntu + } + +fixup_cmdline_txt() + { + src_mount=$1 + dst_mount=$2 + cmdline_txt=$3 + cmdline_boot=$4 + + if [ -f "${dst_mount}${cmdline_txt}" ] + then + if ((leave_sd_usb_boot && SD_slot_dst)) + then + qecho "Leaving SD to USB boot alone." + cp "${dst_mount}${cmdline_txt}" "${dst_mount}${cmdline_boot}" + cmdline_txt=${cmdline_boot} + fi + if grep -q "$src_disk_ID" "${dst_mount}${cmdline_txt}" + then + qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${dst_mount}${cmdline_txt}" + elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${dst_mount}${cmdline_txt}" + then + new_fsuuid=${dst_fsuuid[root_part_num]} + qecho "Editing $cmdline_txt UUID to use $new_fsuuid" + sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${dst_mount}${cmdline_txt}" + elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${dst_mount}${cmdline_txt}" + then + qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/$edit_fstab_name/" "${dst_mount}${cmdline_txt}" + fi + if ((leave_sd_usb_boot && SD_slot_boot)) + then + qecho "Copying USB cmdline.txt to SD card to set up USB boot." + # Note that this leaves out $clone to modify the original SD + # card to boot from the clone instead + cp "${src_mount}${cmdline_txt}" "${src_mount}${cmdline_boot}" + cp "${dst_mount}${cmdline_txt}" "${src_mount}${cmdline_txt}" + fi + fi + } + +fixup_device_references_in_file() { + file=$1 + if grep -q $src_disk_ID $file + then + qecho "Editing $file PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$file" + elif grep -q ^UUID= $file + then + for ((p = 1; p <= n_src_parts; p++)) + do + old_fsuuid=${src_fsuuid[p]} + new_fsuuid=${dst_fsuuid[p]} + if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$file"; + then + continue + fi + + qecho "Editing $file partition $p UUID to use $new_fsuuid" + sed -i "s/$old_fsuuid/${new_fsuuid}/" "$file" + done + elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $file + then + qecho "Editing $file references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/${edit_fstab_name}/" "$file" + fi +} + + # ==== source (booted) disk info and default mount list # @@ -1786,86 +1867,6 @@ do done qecho "" -# Fix PARTUUID/UUID or device name references in cmdline.txt -fixup_boot_partition() - { - src_mount=$1 - dst_mount=$2 - - # Just try all flavors - # Paths are below the /boot directory/mountpoint - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /cmdline.txt /cmdline.boot - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /armbianEnv.txt /armbianEnv.boot - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /firmware/cmdline.txt /firmware/cmdline.boot # Ubuntu - } - -fixup_cmdline_txt() - { - src_mount=$1 - dst_mount=$2 - cmdline_txt=$3 - cmdline_boot=$4 - - if [ -f "${dst_mount}${cmdline_txt}" ] - then - if ((leave_sd_usb_boot && SD_slot_dst)) - then - qecho "Leaving SD to USB boot alone." - cp "${dst_mount}${cmdline_txt}" "${dst_mount}${cmdline_boot}" - cmdline_txt=${cmdline_boot} - fi - if grep -q "$src_disk_ID" "${dst_mount}${cmdline_txt}" - then - qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${dst_mount}${cmdline_txt}" - elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${dst_mount}${cmdline_txt}" - then - new_fsuuid=${dst_fsuuid[root_part_num]} - qecho "Editing $cmdline_txt UUID to use $new_fsuuid" - sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${dst_mount}${cmdline_txt}" - elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${dst_mount}${cmdline_txt}" - then - qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/$edit_fstab_name/" "${dst_mount}${cmdline_txt}" - fi - if ((leave_sd_usb_boot && SD_slot_boot)) - then - qecho "Copying USB cmdline.txt to SD card to set up USB boot." - # Note that this leaves out $clone to modify the original SD - # card to boot from the clone instead - cp "${src_mount}${cmdline_txt}" "${src_mount}${cmdline_boot}" - cp "${dst_mount}${cmdline_txt}" "${src_mount}${cmdline_txt}" - fi - fi - } - -fixup_device_references_in_file() { - file=$1 - if grep -q $src_disk_ID $file - then - qecho "Editing $file PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$file" - elif grep -q ^UUID= $file - then - for ((p = 1; p <= n_src_parts; p++)) - do - old_fsuuid=${src_fsuuid[p]} - new_fsuuid=${dst_fsuuid[p]} - if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$file"; - then - continue - fi - - qecho "Editing $file partition $p UUID to use $new_fsuuid" - sed -i "s/$old_fsuuid/${new_fsuuid}/" "$file" - done - elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $file - then - qecho "Editing $file references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/${edit_fstab_name}/" "$file" - fi -} - fixup_boot_partition /boot "${clone}/boot" fixup_device_references_in_file "${clone}/etc/fstab" From 31ec209e43e9c2d79d33e4b978e9413f8e331e39 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 21:03:37 +0200 Subject: [PATCH 12/17] Simplify fixup_cmdline_txt() This applied largely the same operations to cmdline.txt as fixup_device_references_in_file did to fstab, so this can just call the latter. This should work the same, except that the PARTUUID is not replaced with the g flag (all occurences instead of just one), all filesystem UUIDs are replaced (instead of just the root partition), and progress output messages are slightly different. Also, fstab UUID= replacements are now done anywhere in the file, instead of just at the start of a line. --- rpi-clone | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/rpi-clone b/rpi-clone index c657547..47a51f5 100755 --- a/rpi-clone +++ b/rpi-clone @@ -665,20 +665,9 @@ fixup_cmdline_txt() cp "${dst_mount}${cmdline_txt}" "${dst_mount}${cmdline_boot}" cmdline_txt=${cmdline_boot} fi - if grep -q "$src_disk_ID" "${dst_mount}${cmdline_txt}" - then - qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "${dst_mount}${cmdline_txt}" - elif [ "${src_fsuuid[root_part_num]}" != "" ] && grep -q "${src_fsuuid[root_part_num]}" "${dst_mount}${cmdline_txt}" - then - new_fsuuid=${dst_fsuuid[root_part_num]} - qecho "Editing $cmdline_txt UUID to use $new_fsuuid" - sed -i "s/${src_fsuuid[root_part_num]}/${new_fsuuid}/" "${dst_mount}${cmdline_txt}" - elif [ "$edit_fstab_name" != "" ] && grep -q "${src_part_base}" "${dst_mount}${cmdline_txt}" - then - qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/$edit_fstab_name/" "${dst_mount}${cmdline_txt}" - fi + + fixup_device_references_in_file "${dst_mount}${cmdline_txt}" + if ((leave_sd_usb_boot && SD_slot_boot)) then qecho "Copying USB cmdline.txt to SD card to set up USB boot." @@ -696,7 +685,7 @@ fixup_device_references_in_file() { then qecho "Editing $file PARTUUID to use $dst_disk_ID" sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$file" - elif grep -q ^UUID= $file + elif grep -q UUID= $file then for ((p = 1; p <= n_src_parts; p++)) do From f083e6be5dc15ea05853cb08bf9ebf29d7cd255a Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 21:49:03 +0200 Subject: [PATCH 13/17] Improve output for cmdline/fstab updates This modifies fixup_device_references_in_file to accept the mountpoint and filename separately to prevent printing the destination mountpoint (which might be ugly and meaningless). fixup_boot_partition already had this. Then, a partition label is passed which is prefixed to this plain filename to tell the user which partition is being modified. This could just have used src_mount, but passing a separate label prepares for using this code for non-mounted partitions too. Finally, the UUID output is slightly reworded and some indentation is added (preparing for this output to also be intermixed with mounting and rsync calls later). --- rpi-clone | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/rpi-clone b/rpi-clone index 47a51f5..b84ccd7 100755 --- a/rpi-clone +++ b/rpi-clone @@ -640,22 +640,24 @@ get_src_disk() # Fix PARTUUID/UUID or device name references in cmdline.txt fixup_boot_partition() { - src_mount=$1 - dst_mount=$2 + partition=$1 + src_mount=$2 + dst_mount=$3 # Just try all flavors # Paths are below the /boot directory/mountpoint - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /cmdline.txt /cmdline.boot - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /armbianEnv.txt /armbianEnv.boot - fixup_cmdline_txt "${src_mount}" "${dst_mount}" /firmware/cmdline.txt /firmware/cmdline.boot # Ubuntu + fixup_cmdline_txt "${partition}" "${src_mount}" "${dst_mount}" /cmdline.txt /cmdline.boot + fixup_cmdline_txt "${partition}" "${src_mount}" "${dst_mount}" /armbianEnv.txt /armbianEnv.boot + fixup_cmdline_txt "${partition}" "${src_mount}" "${dst_mount}" /firmware/cmdline.txt /firmware/cmdline.boot # Ubuntu } fixup_cmdline_txt() { - src_mount=$1 - dst_mount=$2 - cmdline_txt=$3 - cmdline_boot=$4 + partition=$1 + src_mount=$2 + dst_mount=$3 + cmdline_txt=$4 + cmdline_boot=$5 if [ -f "${dst_mount}${cmdline_txt}" ] then @@ -666,7 +668,7 @@ fixup_cmdline_txt() cmdline_txt=${cmdline_boot} fi - fixup_device_references_in_file "${dst_mount}${cmdline_txt}" + fixup_device_references_in_file "${partition}" "${dst_mount}" "${cmdline_txt}" if ((leave_sd_usb_boot && SD_slot_boot)) then @@ -680,29 +682,31 @@ fixup_cmdline_txt() } fixup_device_references_in_file() { - file=$1 - if grep -q $src_disk_ID $file + partition=$1 + dst_mount=$2 + file=$3 + if grep -q "${src_disk_ID}" "${dst_mount}${file}" then - qecho "Editing $file PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$file" - elif grep -q UUID= $file + qecho " Editing $partition$file PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "${dst_mount}${file}" + elif grep -q UUID= "${dst_mount}${file}" then for ((p = 1; p <= n_src_parts; p++)) do old_fsuuid=${src_fsuuid[p]} new_fsuuid=${dst_fsuuid[p]} - if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "$file"; + if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "${dst_mount}${file}"; then continue fi - qecho "Editing $file partition $p UUID to use $new_fsuuid" - sed -i "s/$old_fsuuid/${new_fsuuid}/" "$file" + qecho " Editing $partition$file UUID to use $new_fsuuid for partition $p" + sed -i "s/$old_fsuuid/${new_fsuuid}/" "${dst_mount}${file}" done - elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $file + elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} "${dst_mount}${file}" then - qecho "Editing $file references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/${edit_fstab_name}/" "$file" + qecho " Editing $partition$file references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/${edit_fstab_name}/" "${dst_mount}${file}" fi } @@ -1856,8 +1860,8 @@ do done qecho "" -fixup_boot_partition /boot "${clone}/boot" -fixup_device_references_in_file "${clone}/etc/fstab" +fixup_boot_partition /boot /boot "${clone}/boot" +fixup_device_references_in_file "" "${clone}" /etc/fstab rm -f $clone/etc/udev/rules.d/70-persistent-net.rules From d610218d2fb84eca3409d830e274f927c05b3b17 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 21:59:05 +0200 Subject: [PATCH 14/17] Apply cmdline/fstab on non-mounted partitions too This facilitates the case where some of the non-mounted partitions contain a second operating system (possibly for a different system/board), and updates these so that system also stays working. --- rpi-clone | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpi-clone b/rpi-clone index b84ccd7..7b7634d 100755 --- a/rpi-clone +++ b/rpi-clone @@ -1821,6 +1821,11 @@ do mount_partition $dst_dev $clone "$clone_src" unmount_list="$clone_src $clone" rsync_file_system "${clone_src}/" "${clone}" "" + + # This partition *might* be a boot or root partition, so try fixups for both + fixup_boot_partition "partition $p " "${clone_src}" "${clone}" + fixup_device_references_in_file "partition $p " "${clone}" /etc/fstab + unmount_list "$unmount_list" fi done From a26aaff088d0080fd8ae041b126b49cb87793ce7 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 23:17:41 +0200 Subject: [PATCH 15/17] Ignore missing files in fixup_device_references_in_file Since this is called for fstab on unmounted partitions now, without checking if the file exists, just silently do nothing if the file does not exist. --- rpi-clone | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/rpi-clone b/rpi-clone index 7b7634d..b50ffaa 100755 --- a/rpi-clone +++ b/rpi-clone @@ -685,28 +685,32 @@ fixup_device_references_in_file() { partition=$1 dst_mount=$2 file=$3 - if grep -q "${src_disk_ID}" "${dst_mount}${file}" - then - qecho " Editing $partition$file PARTUUID to use $dst_disk_ID" - sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "${dst_mount}${file}" - elif grep -q UUID= "${dst_mount}${file}" - then - for ((p = 1; p <= n_src_parts; p++)) - do - old_fsuuid=${src_fsuuid[p]} - new_fsuuid=${dst_fsuuid[p]} - if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "${dst_mount}${file}"; - then - continue - fi - qecho " Editing $partition$file UUID to use $new_fsuuid for partition $p" - sed -i "s/$old_fsuuid/${new_fsuuid}/" "${dst_mount}${file}" - done - elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} "${dst_mount}${file}" + if [ -f "${dst_mount}${file}" ] then - qecho " Editing $partition$file references from $src_part_base to $edit_fstab_name" - sed -i "s/${src_part_base}/${edit_fstab_name}/" "${dst_mount}${file}" + if grep -q "${src_disk_ID}" "${dst_mount}${file}" + then + qecho " Editing $partition$file PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "${dst_mount}${file}" + elif grep -q UUID= "${dst_mount}${file}" + then + for ((p = 1; p <= n_src_parts; p++)) + do + old_fsuuid=${src_fsuuid[p]} + new_fsuuid=${dst_fsuuid[p]} + if [ "$old_fsuuid" == "" -o "$new_fsuuid" == "" ] || ! grep -q "$old_fsuuid" "${dst_mount}${file}"; + then + continue + fi + + qecho " Editing $partition$file UUID to use $new_fsuuid for partition $p" + sed -i "s/$old_fsuuid/${new_fsuuid}/" "${dst_mount}${file}" + done + elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} "${dst_mount}${file}" + then + qecho " Editing $partition$file references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/${edit_fstab_name}/" "${dst_mount}${file}" + fi fi } From 94b2bccc52557ec38fb42305090f8b655b0dd8c7 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 28 Jul 2022 23:37:49 +0200 Subject: [PATCH 16/17] Add fixup_root_partition() function This adds some consistency with fixup_boot_partition, making code easier to read, and removes duplication of the list of files to update (currently only fstab). --- rpi-clone | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/rpi-clone b/rpi-clone index b50ffaa..8335db3 100755 --- a/rpi-clone +++ b/rpi-clone @@ -681,6 +681,15 @@ fixup_cmdline_txt() fi } +fixup_root_partition() + { + partition=$1 + src_mount=$2 + dst_mount=$3 + + fixup_device_references_in_file "${partition}" "${dst_mount}" /etc/fstab + } + fixup_device_references_in_file() { partition=$1 dst_mount=$2 @@ -1828,7 +1837,7 @@ do # This partition *might* be a boot or root partition, so try fixups for both fixup_boot_partition "partition $p " "${clone_src}" "${clone}" - fixup_device_references_in_file "partition $p " "${clone}" /etc/fstab + fixup_root_partition "partition $p " "${clone_src}" "${clone}" unmount_list "$unmount_list" fi @@ -1870,7 +1879,7 @@ done qecho "" fixup_boot_partition /boot /boot "${clone}/boot" -fixup_device_references_in_file "" "${clone}" /etc/fstab +fixup_root_partition "" / "${clone}" rm -f $clone/etc/udev/rules.d/70-persistent-net.rules From e559954a08aac7f22418c4d2616d086993422f8c Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 29 Jul 2022 01:55:43 +0200 Subject: [PATCH 17/17] Do not sync owner/group for FAT filesystems This can potentially cause rsync error messages, especially if the filesystem is already mounted with a uid= option (which will not be copied to the destination mount, leading to different owners and thus rsync trying and failing to fix the owner). --- rpi-clone | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/rpi-clone b/rpi-clone index 8335db3..1f6453d 100755 --- a/rpi-clone +++ b/rpi-clone @@ -20,6 +20,7 @@ PGM=`basename $0` setup_command="$PGM-setup" rsync_options="--force -rltWDEHXAgoptx" +rsync_options_fat="--force -rltWDEHXAptx" if [ `id -u` != 0 ] then @@ -286,14 +287,22 @@ mount_partition() rsync_file_system() { - src_dir="$1" - dst_dir="$2" + part_num="$1" + src_dir="$2" + dst_dir="$3" - qprintf " => rsync $1 $2 $3 ..." + qprintf " => rsync $1 $2 $3 $4..." + + effective_options=${rsync_options} + fstype=${src_fs_type[part_num]} + if [[ "$fstype" == *"fat"* ]] + then + effective_options=${rsync_options_fat} + fi if [ "$3" == "with-root-excludes" ] then - rsync $rsync_options --delete \ + rsync $effective_options --delete \ $exclude_useropt \ $exclude_swapfile \ --exclude '.gvfs' \ @@ -307,7 +316,7 @@ rsync_file_system() $src_dir \ $dst_dir else - rsync $rsync_options --delete \ + rsync $effective_options --delete \ $exclude_useropt \ --exclude '.gvfs' \ --exclude 'lost\+found/*' \ @@ -1833,7 +1842,7 @@ do mount_partition ${src_device[p]} $clone_src "" mount_partition $dst_dev $clone "$clone_src" unmount_list="$clone_src $clone" - rsync_file_system "${clone_src}/" "${clone}" "" + rsync_file_system "${p}" "${clone_src}/" "${clone}" "" # This partition *might* be a boot or root partition, so try fixups for both fixup_boot_partition "partition $p " "${clone_src}" "${clone}" @@ -1851,7 +1860,7 @@ change_label "$root_part_num" "$fs_type" "$dst_root_dev" mount_partition $dst_root_dev $clone "" unmount_list="$clone" -rsync_file_system "//" "$clone" "with-root-excludes" +rsync_file_system "$root_part_num" "//" "$clone" "with-root-excludes" for ((p = 1; p <= n_src_parts; p++)) do @@ -1872,7 +1881,7 @@ do change_label "$p" "$fs_type" "$dst_dev" mount_partition "$dst_dev" "$dst_dir" "$unmount_list" - rsync_file_system "${src_mounted_dir[p]}/" "${dst_dir}" "" + rsync_file_system "${p}" "${src_mounted_dir[p]}/" "${dst_dir}" "" unmount_list="$dst_dir $unmount_list" fi done