summaryrefslogtreecommitdiff
path: root/draft/other-tools/clonezilla/ocs-expand-gpt-pt
diff options
context:
space:
mode:
Diffstat (limited to 'draft/other-tools/clonezilla/ocs-expand-gpt-pt')
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-expand-gpt-pt386
1 files changed, 386 insertions, 0 deletions
diff --git a/draft/other-tools/clonezilla/ocs-expand-gpt-pt b/draft/other-tools/clonezilla/ocs-expand-gpt-pt
new file mode 100755
index 0000000..191bc06
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-expand-gpt-pt
@@ -0,0 +1,386 @@
+#!/bin/bash
+# Author: Steven Shiau <steven _at_ nchc org tw>
+# License: GPL
+# A script to expand the GPT partition table by disk size ratio.
+# ///NOTE/// This program only works for GPT partition table, not for MBR.
+
+# Load DRBL setting and functions
+DRBL_SCRIPT_PATH="${DRBL_SCRIPT_PATH:-/usr/share/drbl}"
+
+. $DRBL_SCRIPT_PATH/sbin/drbl-conf-functions
+. /etc/drbl/drbl-ocs.conf
+. $DRBL_SCRIPT_PATH/sbin/ocs-functions
+
+# Settings
+# Flag to check target disk size before creating partition table
+chk_tgt_disk_size_bf_mk_pt="yes"
+
+#
+cmd_name="$(basename $0)"
+#
+USAGE() {
+ echo "$cmd_name: To create a proportional MBR partition table (not GPT) in a disk based on a existing partition table (sfdisk format)"
+ echo "Usage:"
+ echo " $cmd_name [OPTION] PARTITION_TABLE_FILE TARGET_DEVICE"
+ echo
+ echo "OPTION:"
+ echo " -b, --batch Run $cmd_name in batch mode, i.e. without any prompt or wait to press enter. VERY DANGEROUS!"
+ echo "$cmd_name will honor experimental variable EXTRA_SFDISK_OPT and use it as the option for sfdisk."
+ echo " -icds, --ignore-chk-dsk-size-pt Skip checking destination disk size before creating the partition table on it. By default it will be checked and if the size is smaller than the source disk, quit."
+ echo "Example:"
+ echo " To create a proportional partition table on disk /dev/sda based on /home/partimag/IMAGE/sda-pt.sf, use:"
+ echo "$cmd_name /home/partimag/IMAGE/sda-pt.sf /dev/sda"
+}
+
+# Parse command-line options
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b|--batch)
+ batch_mode="yes"
+ shift;;
+ -icds|--ignore-chk-dsk-size-pt)
+ chk_tgt_disk_size_bf_mk_pt="no"
+ shift;;
+ -*) echo "${0}: ${1}: invalid option" >&2
+ USAGE >& 2
+ exit 2 ;;
+ *) break ;;
+ esac
+done
+
+# Original sfdisk format file
+orig_sf=$1 # orig_sf is like: /home/partimag/IMAGE/sda-pt.sf
+target_disk=$2 # target_disk is like: /dev/sda
+
+#
+ask_and_load_lang_set $specified_lang
+
+#
+if [ -z "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No source partition table file was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ USAGE
+ echo "$msg_program_stop!"
+ exit 1
+fi
+if [ ! -f "$orig_sf" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Source partition table file \"$orig_sf\" was _NOT_ found"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+if [ -z "$target_disk" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "No target disk was assigned!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ USAGE
+ exit 1
+fi
+
+#
+if [ "$batch_mode" != "yes" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "This program will create a partition table in $target_disk"
+ echo "ALL THE DATA IN THE TARGET DEVICE WILL BE ERASED!!!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo -n "$msg_are_u_sure_u_want_to_continue ? (y/N) "
+ read continue_confirm_ans
+ case "$continue_confirm_ans" in
+ y|Y|[yY][eE][sS])
+ echo "$msg_ok_let_do_it!"
+ ;;
+ *)
+ echo "$msg_program_stop!"
+ exit 1
+ esac
+fi
+
+# Check if GPT disk, if yes, exit
+if `is_mbr_partitition_table_disk $target_disk`; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Disk $target_disk is MBR format. This program only works for GPT format."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# Check if the format of sfdisk is created by sfdisk >= 2.26
+if [ -z "$(LC_ALL=C grep -E "^label: gpt" $orig_sf)" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Partition table file \"$orig_sf\" does not contain GPT info."
+ echo "Make sure it's GPT format and outputted by sfdisk >= 2.26."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# No size info in sda-pt.sf, we have to use sda-pt.parted.
+orig_parted_tab="${orig_sf/.sf/.parted}"
+orig_parted_dir="$(dirname $orig_sf)"
+if [ ! -e "$orig_parted_tab" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "$orig_parted_tab was not found! It is required so that we know the original disk size! Maybe your Clonezilla image is too old ? You can try to create such an file in your source machine by: \"parted -s /dev/$SOURCE_DEV unit s print > $orig_parted_tab\" (Replace $SOURCE_DEV with your device name)"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+
+# parted output format example:
+# Disk /dev/sda: 16777215s
+# Sector size (logical/physical): 512B/512B
+# Partition Table: msdos
+#
+# Number Start End Size Type File system Flags
+# 1 63s 586844s 586782s primary boot
+# 2 586845s 978074s 391230s primary
+# 3 978075s 1955204s 977130s primary
+# 4 1955205s 16776584s 14821380s extended
+# 5 1955268s 2151764s 196497s logical
+# 6 2151828s 2542994s 391167s logical
+# 7 2543058s 16776584s 14233527s logical
+
+ori_disk_size="$(LC_ALL=C grep -E "^Disk /dev" $orig_parted_tab | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+# If nothing in target disk, parted will show like this:
+# sudo parted -s /dev/sda unit s print
+# Error: Unable to open /dev/sda - unrecognised disk label.
+
+if ! LC_ALL=C parted -s $target_disk unit s print &>/dev/null; then
+ # Try to create a partition table so that we can read the size via parted -s $dev unit s print
+ echo "No initial GPT table on disk $target_disk. Create one now by:" | tee --append $OCS_LOGFILE
+ echo "parted -s $target_disk mklabel gpt" | tee --append $OCS_LOGFILE
+ LC_ALL=C parted -s $target_disk mklabel gpt | tee --append $OCS_LOGFILE
+fi
+tgt_disk_size="$(LC_ALL=C parted -s $target_disk unit s print | grep -E "^Disk /dev" | awk -F":" '{print $2}' | sed -e "s/s$//g")"
+
+#
+ratio=$(echo "scale=10; $tgt_disk_size / $ori_disk_size" | bc -l) || exit 1
+echo "The ratio for target disk size to original disk size is $ratio."
+if [ "$chk_tgt_disk_size_bf_mk_pt" = "yes" ]; then
+ if [ "$(LC_ALL=C echo "$ratio < 1" | bc -l)" = "1" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The target disk (size=$tgt_disk_size sectors) is smaller than the source disk (size=$ori_disk_size sectors)!"
+ echo "Clonezilla won't be able to restore a partition image to smaller partition!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "Program terminated!"
+ exit 1
+ fi
+fi
+
+new_sf="$(mktemp /tmp/new_sf.XXXXXX)" || exit 1
+new_sf_tmp="$(mktemp /tmp/new_sf_tmp.XXXXXX)" || exit 1
+# Increase. Example for sfdisk format:
+# =====================================
+# label: gpt
+# label-id: ADC40CC4-77D7-4858-8F0E-8BC2447052AE
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 409600, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=E8D785ED-A65F-4EA1-ADF0-CC61E75677EB
+# /dev/sda2 : start= 411648, size= 1024000, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=AB72A495-4141-4500-AE48-B7AC492160B4
+# /dev/sda3 : start= 1435648, size= 40505344, type=E6D6D379-F507-44C2-A23C-238F2A3DF928, uuid=C7A87C41-72FD-41DB-9B10-DF3568A4089D
+# =====================================
+# label: gpt
+# label-id: D4165706-2FAD-491E-82CA-7866982D196B
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 614400, type=DE94BBA4-06D1-4D40-A16A-BFD50179D6AC, uuid=0802BFF4-2549-4CD4-A1CA-93D54AEE26F0, name="Basic data partition", attrs="RequiredPartiton GUID:63"
+# /dev/sda2 : start= 616448, size= 202752, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=C9C164D5-5E0F-476D-B2EA-A4D818A266CF, name="EFI system partition", attrs="GUID:63"
+# /dev/sda3 : start= 819200, size= 262144, type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE, uuid=15D5A869-5C6E-4F2C-B234-7D6B91B58555, name="Microsoft reserved partition", attrs="GUID:63"
+# /dev/sda4 : start= 1081344, size= 124745728, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=E53DEA7E-2639-4AE9-9DFD-DDD2406C3EC0, name="Basic data partition"
+# =====================================
+
+# We only need those required info
+grep -E "^/dev" $orig_sf > $new_sf_tmp
+# start=291579750 or size=291563622 is not a good format for us to parse, we need a space between "=" and "number"
+# i.e.
+# No good:
+# /dev/sda1 : start= 63, size=291563622, Id= 7, bootable
+# /dev/sda2 : start=291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+#
+# Good:
+# /dev/sda1 : start= 63, size= 291563622, Id= 7, bootable
+# /dev/sda2 : start= 291579750, size= 20980890, Id= 7
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+
+# //NOTE// For partitions number >=10, it looks like:
+# label: gpt
+# label-id: 56C0DC13-942C-493F-B141-F9903658453B
+# device: /dev/sda
+# unit: sectors
+# first-lba: 34
+# last-lba: 125829086
+#
+# /dev/sda1 : start= 2048, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=4F5FF221-D350-4CE7-BADA-20022DA453CC, name="Linux filesystem"
+# /dev/sda2 : start= 2099200, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=975A9722-E2ED-46CC-B0E1-995095A6BB66, name="Linux filesystem"
+# /dev/sda3 : start= 4196352, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=A27C9E16-70B1-48D0-9A3F-915AFBA8FCC7, name="Linux filesystem"
+# /dev/sda4 : start= 6293504, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=3E134963-5B14-49C1-9F83-9BAF9C5F61C9, name="Linux filesystem"
+# /dev/sda5 : start= 8390656, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=FB1FB744-E6DC-48FA-9891-256AD0F3CF7C, name="Linux filesystem"
+# /dev/sda6 : start= 10487808, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=BB764A64-35BF-4415-A8D6-84642339FB3F, name="Linux filesystem"
+# /dev/sda7 : start= 12584960, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B0D77252-85AB-4AFB-8866-38C21605DB7B, name="Linux filesystem"
+# /dev/sda8 : start= 14682112, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=79E8897A-B821-4C5D-A481-5F8628C57D2E, name="Linux filesystem"
+# /dev/sda9 : start= 16779264, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=2CA8A44E-9A2B-475A-BFC8-1E6295847F6A, name="Linux filesystem"
+# /dev/sda10 : start= 18876416, size= 2097152, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B454EC36-562F-4844-B8D9-28C5C1C111C9, name="Linux filesystem"
+# /dev/sda11 : start= 20973568, size= 104855519, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=FA55D210-62EE-4948-A853-FDD4360CDCB5, name="Linux filesystem"
+
+# Therefore we force to put a space no matter there is already space or not
+perl -pi -e "s/start=/start= /g" $new_sf_tmp
+perl -pi -e "s/size=/size= /g" $new_sf_tmp
+# Remove ":" in the temp file, since it's only for parsing, won't be used for sfdisk /dev/... < $new_sf_tmp ...
+perl -pi -e "s/://g" $new_sf_tmp
+
+# Get the line number of "last-lba:"
+header_line="$(LC_ALL=C grep -E -n "^last-lba:" $orig_sf | awk -F":" '{print $1}')"
+if [ -z "$header_line" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Failed to find the line \"last-lba:\" in $orig_sf!"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+fi
+# We do not output the line "last-lba:" in the generated line. Otherwise we have to calculate the last-lba number.
+LC_ALL=C head -n "$((header_line -1))" $orig_sf > $new_sf
+echo "" >> $new_sf
+start_no_keep=""
+size_no_keep=""
+append_to_next="0"
+# Initial gap for the 1st partition. After this, it should be 0.
+logical_part_gap="2"
+while read dev start start_no size size_no type uuid name attrs; do
+ pt_no="$(LC_ALL=C get_part_number $dev | sed -r -e "s|^[^[:digit:]]*||g")"
+ if `is_partition $dev` ; then
+ [ -z "$start_no_keep" ] && start_no_keep=${start_no/,/} # The 1st one
+ [ -z "$size_no_keep" ] && size_no_keep=0
+ if [ "${size_no/,/}" -eq 0 ]; then
+ start_no=0
+ size_no=0
+ else
+ # If we found the partition is EFI System partition, keep the size.
+ # EFI System partition: C12A7328-F81F-11D2-BA4B-00A0C93EC93B,
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ expand="true"
+ if [ -n "$(echo $type | grep -iE "type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"EFI System partition\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # If we found the partition is MS Windows "system reserved partition", keep the size.
+ # Microsoft Reserved Partition (MSR): E3C9E316-0B5C-4DB8-817D-F92DF00215AE
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ if [ -n "$(echo $type | grep -iE "type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"Microsoft Reserved Partition (MSR)\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # If we found the partition is MS Windows "system reserved partition", keep the size.
+ # Windows Recovery Environment DE94BBA4-06D1-4D40-A16A-BFD50179D6AC
+ # Ref: https://en.wikipedia.org/wiki/GUID_Partition_Table
+ if [ -n "$(echo $type | grep -iE "type=DE94BBA4-06D1-4D40-A16A-BFD50179D6AC")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "\"Windows Recovery Environment\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ # For newer Clonezilla (>=2.4.36-1drbl), a tag file (sda1.info) might exist
+ if [ -e "$orig_parted_dir/$(to_filename ${dev}).info" ]; then
+ . $orig_parted_dir/$(to_filename ${dev}).info
+ if [ "$PARTITION_TYPE" = "Win_boot_reserved" ]; then
+ expand="false"
+ fi
+ fi
+ # For Linux Swap partition
+ if [ -n "$(echo $type | grep -iE "type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$type\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ expand="false"
+ fi
+
+ if [ "$expand" = "true" ]; then
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="$(LC_ALL=C printf "%.0f" "$(echo "${size_no/,/}*$ratio + $append_to_next" | bc -l)")"
+ # Reset the space append_to_next.
+ append_to_next="0"
+ else
+ start_no="$(LC_ALL=C printf "%.0f" "$(echo "($start_no_keep + $size_no_keep)" | bc -l)")"
+ size_no="${size_no/,/}"
+ # Since we do not expand this "system reserved partition" or "swap partition",
+ # we append the space to the next partition.
+ # It's possible that there are more than one partition which will be
+ # kept as original size, e.g.
+ # Number Start End Size File system Name Flags
+ # 1 1049kB 106MB 105MB EFI system partition boot, esp
+ # 2 106MB 240MB 134MB Microsoft reserved partition msftres
+ # 3 240MB 128GB 128GB Basic data partition msftdata
+ # In the above, partition 1 and 2 will not be expanded. Therefore we
+ # might need to add the previous $append_to_next
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "$append_to_next + ${size_no}*$ratio - ${size_no}" | bc -l)")"
+ fi
+ fi
+ if [ "$size_no" -lt 0 ]; then
+ # append_to_next might be nagtive when "-icds" is enabled and ration is < 1, therefore
+ # we have to check the size_no.
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "The calculated size of $dev is < 0!"
+ echo "Unable to create a smaller partitions layout."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ echo "$msg_program_stop!"
+ exit 1
+ fi
+ echo $dev : $start $start_no, $size $size_no, $type $uuid $name $attrs >> $new_sf
+ [ "$start_no" -ne 0 ] && start_no_keep="${start_no/,/}"
+ [ "$size_no" -ne 0 ] && size_no_keep="${size_no/,/}"
+ fi
+done < $new_sf_tmp
+
+echo "The partition table to write in $target_disk:"
+echo "*****************************************"
+cat $new_sf
+echo "*****************************************"
+
+# EXTRA_SFDISK_OPT is environment variable
+# If not --force, we force to append it since by default if sfdisk find some CHS it does not like, it won't do it without --force
+if [ -z "$(echo $EXTRA_SFDISK_OPT | grep -Ew -- "--force")" ]; then
+ EXTRA_SFDISK_OPT="$EXTRA_SFDISK_OPT --force"
+fi
+echo "Running: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+LC_ALL=C sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf
+echo "Partition table was created by: sfdisk $EXTRA_SFDISK_OPT $target_disk < $new_sf"
+
+# Use parted to fill the last partitition to the end of disk because
+# there might be some resudial in the calculation.
+# Thanks to Conan for this suggestion.
+# Ref: https://sourceforge.net/p/clonezilla/discussion/
+# Clonezilla_live/thread/c5e92d87/?limit=25#080c
+if [ -n "$(LC_ALL=C parted -h | grep -w resizepart)" ]; then
+ # Find the last partition number.
+ # Firstly we get the line number for "Number Start End Size
+ # File system Name Flags"
+ line_after="$(LC_ALL=C parted -s $target_disk print | \
+ grep -n -Ew "^Number[[:space:]]+Start[[:space:]]+End.*" | \
+ awk -F":" '{print $1}')"
+ line_after="$((line_after +1))"
+ last_part_no="$(LC_ALL=C parted -s $target_disk print | \
+ tail -n +${line_after} | awk -F" " '{print $1}' | sort -V | tail -n 1)"
+ if [ -n "$last_part_no" ]; then
+ echo "Trying to extend the last partition to the end of disk by:"
+ echo "parted -s $target_disk resizepart $last_part_no 100%"
+ LC_ALL=C parted -s $target_disk resizepart $last_part_no 100%
+ fi
+fi
+
+[ -e "$new_sf" ] && rm -f $new_sf
+[ -e "$new_sf_tmp" ] && rm -f $new_sf_tmp