summaryrefslogtreecommitdiff
path: root/draft/other-tools/clonezilla/ocs-expand-mbr-pt
diff options
context:
space:
mode:
Diffstat (limited to 'draft/other-tools/clonezilla/ocs-expand-mbr-pt')
-rwxr-xr-xdraft/other-tools/clonezilla/ocs-expand-mbr-pt369
1 files changed, 369 insertions, 0 deletions
diff --git a/draft/other-tools/clonezilla/ocs-expand-mbr-pt b/draft/other-tools/clonezilla/ocs-expand-mbr-pt
new file mode 100755
index 0000000..eeb9759
--- /dev/null
+++ b/draft/other-tools/clonezilla/ocs-expand-mbr-pt
@@ -0,0 +1,369 @@
+#!/bin/bash
+# Author: Steven Shiau <steven _at_ nchc org tw>
+# License: GPL
+# A script to expand the partition table by disk size ratio.
+# ///NOTE/// This program only works for MBR partition table, not for GPT.
+
+# 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_gpt_partitition_table_disk $target_disk`; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+ echo "Disk $target_disk is GPT format. This program only works for MBR format."
+ [ "$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 -n "No partition table exists in target disk $target_disk, try to initialize one so that we can get the disk size by sfdisk... "
+ echo 1,,83 | sfdisk -f $target_disk &>/dev/null
+ echo "done!"
+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")"
+
+# If target_disk size is larger than 2 TiB (~2.2 TB = 2,199,023,255,040 bytes), exit. It's over the MBR's limitation.
+check_mbr_disk_size_gt_2TiB $target_disk exit
+
+#
+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:
+# # partition table of /dev/sda
+# unit: sectors
+#
+# /dev/sda1 : start= 63, size= 586782, Id=83, bootable
+# /dev/sda2 : start= 586845, size= 391230, Id=82
+# /dev/sda3 : start= 978075, size= 977130, Id=83
+# /dev/sda4 : start= 1955205, size= 14821380, Id= 5
+# /dev/sda5 : start= 1955268, size= 196497, Id=83
+# /dev/sda6 : start= 2151828, size= 391167, Id=83
+# /dev/sda7 : start= 2543058, size= 14233527, Id=83
+#
+# Or
+# /dev/sda1 : start= 63, size= 196497, Id=83
+# /dev/sda2 : start= 196560, size= 16580025, Id= 5
+# /dev/sda3 : start= 0, size= 0, Id= 0
+# /dev/sda4 : start= 0, size= 0, Id= 0
+# /dev/sda5 : start= 196623, size= 16579962, Id=83
+
+# We only need those required info
+grep -E "^/dev" $orig_sf > $new_sf_tmp
+# Format the output, since something like "Id= 5" is not a good idea for us to parse
+perl -pi -e "s/Id=[[:space:]]+/Id=/g" $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:
+## partition table of /dev/sda
+#unit: sectors
+#
+#/dev/sda1 : start= 63, size= 976562, Id=83
+#/dev/sda2 : start= 976625, size= 1171875, Id=83
+#/dev/sda3 : start= 2148500, size= 1367187, Id=83
+#/dev/sda4 : start= 3515687, size= 13256173, Id= f
+#/dev/sda5 : start= 3515750, size= 195312, Id=83
+#/dev/sda6 : start= 3711063, size= 390624, Id=83
+#/dev/sda7 : start= 4101688, size= 585936, Id=83
+#/dev/sda8 : start= 4687625, size= 781249, Id=83
+#/dev/sda9 : start= 5468875, size= 976561, Id=83
+#/dev/sda10: start= 6445437, size= 976561, Id=83 <-- No space before ":"
+#/dev/sda11: start= 7421999, size= 976561, Id=83
+
+# 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
+
+#
+echo "unit: sectors" > $new_sf
+echo "" >> $new_sf
+start_no_keep=""
+size_no_keep=""
+extended_part=""
+flag_1st_logic_drv="off"
+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 id flag; do
+ pt_no="$(LC_ALL=C get_part_number $dev | sed -r -e "s|^[^[:digit:]]*||g")"
+ if `is_partition $dev` && [ "$pt_no" -le 4 ]; then
+ # primary/extended partitions
+ [ -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 MS Windows (Vista, 7) "system reserved partition", i.e. size is about 100 MB (204800) or 200 MB (409600 sectors), and Id=7, and flag is bootable, not to expand it. i.e.:
+ # /dev/sda1 : start= 2048, size= 204800, Id= 7, bootable
+ # The files and dirs in MS Windows (Vista, 7) "system reserved partition"
+ # drwxrwxrwx 1 root root 4.0K 2011-07-20 06:22 Boot/
+ # -rwxrwxrwx 1 root root 375K 2009-07-14 01:38 bootmgr*
+ # -rwxrwxrwx 1 root root 8.0K 2011-07-20 06:22 BOOTSECT.BAK*
+ # drwxrwxrwx 1 root root 0 2011-07-20 06:31 System Volume Information/
+ # //NOTE// The above files and dirs will be shown after restoring, not the time when creating partition table. Therefore we can not mount the partition and parse them.
+ # Ref: http://windows7forums.com/windows-7-discussion/15629-hack-remove-100-mb-system-reserved-partition-when-installing-windows-7-a.html
+ expand="true"
+ if [ "${size_no/,/}" -eq "409600" -o "${size_no/,/}" -eq "204800" ]; then
+ if [ -n "$(echo $id | grep -iE "(id|type)=7")" -a \
+ -n "$(echo $flag | grep -iE "bootable")" ]; then
+ expand="false"
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "MS Windows (Vista or 7) \"system reserved partition\" found. Not to expand this partition."
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+ fi
+ 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 $id | grep -iE "(id|type)=82")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$id\" 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.
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "${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
+ if [ -n "$(echo $id | grep -iE "((id|type)=5|(id|type)=f)")" ]; then
+ # keep the extended partition, we need it for logical partitions.
+ extended_part="$dev"
+ extended_start_no="$start_no"
+ extended_size_no="$size_no"
+ fi
+ echo $dev : $start $start_no, $size $size_no, $id $flag >> $new_sf
+ [ "$start_no" -ne 0 ] && start_no_keep="${start_no/,/}"
+ [ "$size_no" -ne 0 ] && size_no_keep="${size_no/,/}"
+ else
+ # logical partitions
+ if [ "$flag_1st_logic_drv" = "off" ]; then
+ start_no_keep="$((extended_start_no))"
+ size_no_keep="0"
+ flag_1st_logic_drv="on"
+ fi
+ if [ "${size_no/,/}" -eq 0 ]; then
+ start_no=0
+ size_no=0
+ else
+ expand="true"
+ # For Linux Swap partition
+ if [ -n "$(echo $id | grep -iE "(id|type)=82")" ]; then
+ [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+ echo "Linux swap partition \"$id\" 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+$logical_part_gap)" | bc -l)")"
+ size_no="$(LC_ALL=C printf "%.0f" "$(echo "${size_no/,/}*$ratio + $append_to_next" | bc -l)")"
+ logical_part_gap="0"
+ # 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+$logical_part_gap)" | bc -l)")"
+ size_no="${size_no/,/}"
+ # Since we do not expand the "swap partition", we append the space to the next partition.
+ append_to_next="$(LC_ALL=C printf "%.0f" "$(echo "${size_no}*$ratio - ${size_no}" | bc -l)")"
+ fi
+ fi
+ echo $dev : $start $start_no, $size $size_no, $id $flag >> $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
+# For sfdisk <= 0.25, only "Id=" is accepted, not "type=".
+perl -pi -e "s/type=/Id=/g" $new_sf
+
+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"
+
+[ -e "$new_sf" ] && rm -f $new_sf
+[ -e "$new_sf_tmp" ] && rm -f $new_sf_tmp