Support UUID= (filesystem UUIDs), Armbian and partially Ubuntu #140

Open
matthijskooijman wants to merge 17 commits from matthijskooijman/support-fsuuid-and-armbian into master

329
rpi-clone
View File

@@ -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/*' \
@@ -546,26 +555,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()
@@ -583,6 +646,93 @@ get_src_disk()
printf -v "${3}" "%s" "$num"
}
# Fix PARTUUID/UUID or device name references in cmdline.txt
fixup_boot_partition()
{
partition=$1
src_mount=$2
dst_mount=$3
# Just try all flavors
# Paths are below the /boot directory/mountpoint
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()
{
partition=$1
src_mount=$2
dst_mount=$3
cmdline_txt=$4
cmdline_boot=$5
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
fixup_device_references_in_file "${partition}" "${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."
# 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_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
file=$3
if [ -f "${dst_mount}${file}" ]
then
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
}
# ==== source (booted) disk info and default mount list
#
@@ -636,8 +786,11 @@ 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/")
# 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 " ")
@@ -739,13 +892,16 @@ 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
fsuuid=`lsblk --raw --output UUID --noheadings "${src_device[p]}"`
if [ "$fsuuid" != "" ]
then
src_fsuuid[p]="$fsuuid"
fi
done
@@ -1064,7 +1220,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
@@ -1086,7 +1243,11 @@ 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 ';')
# 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
@@ -1139,16 +1300,20 @@ 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"
fsuuid=`lsblk --raw --output UUID --noheadings "${dst_device[p]}"`
if [ "$fsuuid" != "" ]
then
dst_fsuuid[p]="$fsuuid"
fi
fi
done
@@ -1505,9 +1670,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" ]
@@ -1518,9 +1683,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
@@ -1540,15 +1705,21 @@ 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"
# 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
@@ -1667,17 +1838,16 @@ 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"
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}"
fixup_root_partition "partition $p " "${clone_src}" "${clone}"
unmount_list "$unmount_list"
fi
done
@@ -1685,17 +1855,12 @@ 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"
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
@@ -1713,69 +1878,21 @@ 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}" ""
rsync_file_system "${p}" "${src_mounted_dir[p]}/" "${dst_dir}" ""
unmount_list="$dst_dir $unmount_list"
fi
done
qecho ""
# Fix PARTUUID or device name references in cmdline.txt and fstab
#
fstab=${clone}/etc/fstab
cmdline_txt=${clone}/boot/cmdline.txt
if [ -f $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
fi
if grep -q $src_disk_ID $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 [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $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"
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
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 [ "$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 /boot "${clone}/boot"
fixup_root_partition "" / "${clone}"
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