#!/bin/sh
#
# LLC «DACOM M»
#


#Remove from stdout lvm commands 'File descriptor 7 ...'
export LVM_SUPPRESS_FD_WARNINGS=1
ECHO=':'
DEV_NULL=' >/dev/null 2>&1'
ERR_NULL=' 2>/dev/null'
if [ "_$1" = '_-v' ]; then
    ECHO='echo'
    DEV_NULL=''
    ERR_NULL=''
    shift
fi
while [ -n "$1" ]; do
    ARGS="$ARGS$1\n"
    shift
done
LIST_OPTS='list\nextract\nrestore\ntar\nhelp\nextract_cfg\nextract_script\n'
SCRIPT_NAME=`printf "$0" |sed 's/.*\///'`
LENGTH_NAME=`printf "$SCRIPT_NAME" |wc -m`
SPACES_NAME=`printf "%0.s " $(seq 1 $LENGTH_NAME)`
SCRIPT_PATH=`realpath $0`
SCRIPT_LEN=%SCRIPT_SIZE%
CFG_LEN=%CFG_SIZE%


# Help using.
helpf() {
help_msg=\
"Usage: sh $SCRIPT_NAME [-v] [[list] |
          $SPACES_NAME [-v] [extract <dir to extract>] |
          $SPACES_NAME [-v] [restore <disk to restore>] |
          $SPACES_NAME [-v] [tar <keys tar>] |
          $SPACES_NAME [help]]

    -v:                          Verbose output for debug.
    list:                        Show list files in backup. WARNING: this output very large,
                                 it use for 'grep' or output to file.
    extract <dir to extract>:    Extract files the backuped OS to a passed directory.
    restore <disk to restore>:   Restore OS to a passed disk.
    tar <keys tar>:              Use tar keys for archive with data OS from backup.
                                 Don't need use option '-f <archive>'
    help:                        Print this help.

Examples:
    sh $SCRIPT_NAME list | grep 'etc/fstab'
    sh $SCRIPT_NAME extract ./123
    sh $SCRIPT_NAME restore /dev/sda
    sh $SCRIPT_NAME tar -xC ./123 'etc/fstab'
    Typical restore with verbose logging:
    echo 'y' | sudo sh $SCRIPT_NAME -v restore /dev/sda 2>&1 | sudo tee restore.log

"
printf "$help_msg"
}


# Add a command to the pseudo array for run before exiting if a kill signal is caught.
trap_array=
add_trap() {
    local cmd="$1"
    local cmd_str=
    $ECHO "> add_trap $cmd"
    trap_array="$cmd\n$trap_array"
    IFS_SAVE=$IFS
    IFS='
'
    for i in $(printf $trap_array); do
        test -z "${i%%\\n}" && continue
        cmd_str=" ${cmd_str}${i%%\\n}; "
    done
    IFS="$IFS_SAVE"
    $ECHO ">> trap \"$cmd_str\" HUP INT TERM"
    trap "$cmd_str" HUP INT TERM
}

# Func run commands from the pseudo array before exiting.
clear_before_exit() {
    local cmd_str=
    if [ -n "$trap_array" ]; then
        IFS_SAVE=$IFS
        IFS='
'
        for i in $(printf $trap_array); do
            test -z "${i%%\\n}" && continue
            cmd_str="${cmd_str}${i%%\\n}; "
        done
        IFS="$IFS_SAVE"
        trap_array=
    fi
    if [ -n "$cmd_str" ]; then
        $ECHO "> eval \"$cmd_str\""
        eval "$cmd_str"
    fi
}

# Exit if error.
die() {
    clear_before_exit
    if [ -n "$1" ]; then
        printf "Error: $1\n" >&2;
        exit;
    else
        printf "Error undefined.\n" >&2;
        exit;
    fi
}

# Check of the validate arguments
check_args() {
    local local_args="$1";
    local local_opts="$2";


    # Arguments not should be less then one.
    if [ -z "$local_args" ]; then
        if [ -n "$DESCRIPTION" ]; then
            printf "$DESCRIPTION";
        fi
        exit 0;
    fi

    # If first argument is "help" show help and exit.
    fist_arg="$(printf $local_args| sed -n '1p')"
    if test "$fist_arg" = "$(printf $local_opts |sed -n '5p')"; then
        helpf; exit;
    fi

    # Argumet is exists?
    $ECHO "Operation: "`printf "$local_opts" | grep "^$fist_arg$"`
    if ! printf "$local_opts" | grep -q "^$fist_arg$"; then
        die "Wrong arguments.";
    fi
}

# Attach a archive with support files as loop device.
attach_cfg_archive() {
    archive=`losetup -f`
    $ECHO "> losetup -o $SCRIPT_LEN $archive $SCRIPT_PATH"
    losetup -o $SCRIPT_LEN $archive $SCRIPT_PATH || \
        ( losetup -d $archive; die "Can't offset config archive from backup $SCRIPT_PATH" );
    add_trap "losetup -d $archive"
}

# Attach a archive with root os as loop device.
attach_data_archive() {
    archive=`losetup -f`
    $ECHO "> losetup -o $(($SCRIPT_LEN + $CFG_LEN)) $archive $SCRIPT_PATH"
    losetup -o $(($SCRIPT_LEN + $CFG_LEN)) $archive $SCRIPT_PATH || \
        ( losetup -d $archive; die "Can't offset data archive from backup $SCRIPT_PATH" );
    add_trap "losetup -d $archive"
}

# Check of the validate arguments.
check_args "$ARGS" "$LIST_OPTS"

test $(id -u) -ne 0 && die "This script must be run as root"

# list
if test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '1p')"; then
    command -v losetup > /dev/null || die "This option need command 'losetup', but that not found."
    attach_data_archive
    if [ -b "$archive" ]; then
        tar -tf $archive
    else
        die "Block device \"$archive\" not found.";
    fi
# extract
elif test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '2p')"; then
    if [ `printf $ARGS| wc -l` -lt 2 ]; then
        helpf
        die "Not enough arguments.";
    fi
    if command -v losetup > /dev/null; then
        attach_data_archive
        if [ -b "$archive" ]; then
            extract_dir="$(printf $ARGS | sed -n '2p')"
            if [ -d "$extract_dir" ]; then
                $ECHO "> tar -xzf $archive -C $extract_dir"
                tar -xzf $archive -C $extract_dir || \
                    die "Tar extract via 'losetup' has trables."
            else
                die "Extract directory \"$extract_dir\" not found.";
            fi
        else
            die "Block device \"$archive\" not found.";
        fi
    else
        $ECHO "Command 'losetup' not found, try extact via 'dd'."
        extract_dir="$(printf $ARGS | sed -n '2p')"
        if [ -d "$extract_dir" ]; then
            $ECHO "dd if=$SCRIPT_PATH bs=512 skip=$(( ($SCRIPT_LEN + $CFG_LEN) / 512)) | tar -xz -C $extract_dir"
            eval "dd if=$SCRIPT_PATH bs=512 skip=$(( ($SCRIPT_LEN + $CFG_LEN) / 512)) $ERR_NULL | tar -xz -C $extract_dir" || \
                die "Tar extract via 'dd' has trables."
        else
            die "Extract directory \"$extract_dir\" not found.";
        fi
    fi
# extract_cfg
elif test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '6p')"; then
    if [ `printf $ARGS| wc -l` -lt 2 ]; then
        helpf
        die "Not enough arguments.";
    fi
    if command -v losetup > /dev/null; then
        attach_cfg_archive
        if [ -b "$archive" ]; then
            extract_dir="$(printf $ARGS | sed -n '2p')"
            if [ -d "$extract_dir" ]; then
                $ECHO "> tar -xzf $archive -C $extract_dir"
                tar -xzf $archive -C $extract_dir || \
                    die "Tar extract configs files via 'losetup' has trables."
            else
                die "Extract directory \"$extract_dir\" not found.";
            fi
        else
            die "Block device \"$archive\" not found.";
        fi
    else
        $ECHO "Command 'losetup' not found, try extact via 'dd'."
        extract_dir="$(printf $ARGS | sed -n '2p')"
        if [ -d "$extract_dir" ]; then
            $ECHO "> dd if=$SCRIPT_PATH bs=512 skip=$(($SCRIPT_LEN/512)) count=$(($CFG_LEN/512)) | tar -xz -C $extract_dir"
            eval "dd if=$SCRIPT_PATH bs=512 skip=$(($SCRIPT_LEN/512)) count=$(($CFG_LEN/512)) $ERR_NULL | tar -xz -C $extract_dir" || \
            die "Tar extract configs files via 'dd' has trables."
        else
            die "Extract directory \"$extract_dir\" not found.";
        fi
    fi
# extract_script
elif test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '7p')"; then
    if [ `printf $ARGS| wc -l` -lt 2 ]; then
        helpf
        die "Not enough arguments.";
    fi
    extract_file="$(printf $ARGS | sed -n '2p')"
    if [ ! -f "$extract_file" ]; then
        $ECHO "> dd if=$SCRIPT_PATH bs=512 count=$(($SCRIPT_LEN/512)) of=$extract_file"
        eval "dd if=$SCRIPT_PATH bs=512 count=$(($SCRIPT_LEN/512)) of=$extract_file $ERR_NULL" || \
        die "Tar extract the self unpuack script file via 'dd' has trables."
    else
        die "The file with name \"$extract_file\" already is exists.";
    fi
# tar
elif test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '4p')"; then
    command -v losetup > /dev/null || die "This option need command 'losetup', but that not found."
    if [ `printf $ARGS | wc -l` -lt 2 ]; then
        helpf
        die "Not enough arguments.";
    fi
    attach_data_archive
    if [ -b "$archive" ]; then
        tar_args="$(printf $ARGS | sed -e '1d' | tr '\n' ' ')"
        $ECHO "> tar -f $archive $tar_args"
        tar -f $archive $tar_args || die "Use tar with has trables. Arguments passed: $tar_args"
    else
        die "Block device \"$archive\" not found.";
    fi
# restore
elif test "$fist_arg" = "$(printf $LIST_OPTS |sed -n '3p')"; then
    count_args=`printf $ARGS | wc -l`
    if [ $count_args -lt 2 ]; then
        helpf
        die "Not enough arguments.";
    fi
    disk="$(printf $ARGS | sed -n '2p')"
    echo "WARNING. All data on the disk \"$disk\" will be delete!!!"
    read -p "Enter 'y' or 'Y' to accept: " accept
    if [ `echo "$accept" | tr '[:upper:]' '[:lower:]'` != 'y' ]; then
        exit 0
    fi

    if [ ! -b $disk ]; then
        die "Disk \"$disk\" not found."
    fi

    if command -v mkfs > /dev/null; then
        MKFS='mkfs -t '
    elif command -v mkfs.ext2 > /dev/null; then
        MKFS='mkfs.'
    else
        die "Command 'mkfs' not found."
    fi
    # there are bugs, some busybox utils do not distinguish 'n' and '\n', so the last symbol should be not 'n'
    temp_dir=`mktemp -d /tmp/cfg.XXXXXX`
    mv "$temp_dir" "${temp_dir}_"
    temp_dir="${temp_dir}_"
    $ECHO "TMP CONFIG DIR: $temp_dir"
    add_trap "rm -rf $temp_dir"

    if command -v losetup > /dev/null; then
        attach_cfg_archive
        [ ! -b "$archive" ] && die "Block device \"$archive\" not found."
        [ `tar -tf "$archive" 2>/dev/null | \
            grep '^part_table.bin$\|^fdisk.sfd$\|^fdisk.txt$\|^fstab$\|^df.txt$\|^blkid.txt$' |wc -l` = 6 ] || \
            die "One or more files in config backup from: fdisk.sfd, fdisk.txt, fstab  not found."
        $ECHO "> tar -xf \"$archive\" -C $temp_dir"
        tar -xf "$archive" -C $temp_dir
    else
        $ECHO "> dd if=$SCRIPT_PATH bs=512 skip=$(($SCRIPT_LEN/512)) count=$(($CFG_LEN/512)) | tar -xz -C $temp_dir"
        eval "dd if=$SCRIPT_PATH bs=512 skip=$(($SCRIPT_LEN/512)) count=$(($CFG_LEN/512)) $ERR_NULL | tar -xz -C $temp_dir" || \
            die "Tar extract configs files via 'dd' has trables."
    fi

    test -f $temp_dir/fdisk.txt || die "File 'fdisk.txt' not found in config backup."
    test -f $temp_dir/fdisk.sfd || die "File 'fdisk.sfd' not found in config backup."
    if command -v hdparm > /dev/null; then
        REFRESH_PART='hdparm -z'
    elif command -v blockdev > /dev/null; then
        REFRESH_PART='blockdev --rereadpt'
    elif command -v partprobe > /dev/null; then
        REFRESH_PART='partprobe'
    elif command -v kpartx > /dev/null; then
        REFRESH_PART='kpartx -u'
    else
        die "Utility for refresh partitions not found."
    fi
    test -f $temp_dir/blkid.txt || die "File 'blkid.txt' not found in config backup."
    $ECHO "> cat $temp_dir/blkid.txt"
    cat $temp_dir/blkid.txt $DEV_NULL

    if grep -q 'label: gpt' $temp_dir/fdisk.sfd; then
        fdisk --help 2>&1 | grep -q gpt || die "'fdisk' GPT not support."
        $ECHO "> printf 'g\nw\n' | fdisk --lock=yes -W always $disk"
        printf 'g\nw\n' | fdisk --lock=yes -W always $disk $DEV_NULL || die "Clean gpt tables don't set."
        PART_LABEL='gpt'
        $ECHO "> $REFRESH_PART $disk"
        $REFRESH_PART $disk $DEV_NULL
    elif grep -q 'label: dos' $temp_dir/fdisk.sfd; then
        $ECHO "> printf 'o\nw\n' | fdisk --lock=yes -W always $disk $DEV_NULL"
        printf 'o\nw\n' | fdisk --lock=yes -W always $disk $DEV_NULL || die "Clean dos tables don't set."
        PART_LABEL='dos'
        $ECHO "> $REFRESH_PART $disk"
        $REFRESH_PART $disk $DEV_NULL
    else
        die "Not support partition table."
    fi

    disk_sectors=`fdisk -l $disk | sed -n '/sectors$/ s/.*, \([0-9]*\) sectors$/\1/p'`
    number_of_parts=`cat $temp_dir/fdisk.sfd | sed -n '/^$/ { :a; n; p; ba; }' | wc -l`
    if [ "_$PART_LABEL" = '_gpt' ]; then
        number=0
        while read line; do
            $ECHO ">> $line"
            number=$((number+1))
            part=`echo $line |sed 's/[[:space:]].*//'`
            uuid=`cat $temp_dir/blkid.txt | grep "$part" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
            type_fs=`grep "$part" $temp_dir/blkid.txt | sed 's/.* TYPE="\([^"]*\).*/\1/'`
            type=`echo $line | sed 's/.* type=\(.*\)*/\1/;{s/,.*//}'`
            size=`echo $line | sed 's/.*size=[[:space:]]*\([0-9][0-9]*\).*/\1/'`
            [ -z "$size" ] && die "Filed get size from line: $line"
            start=`echo $line | sed 's/.*start=[[:space:]]*\([0-9][0-9]*\).*/\1/'`
            if [ $number -gt 1 ] && [ -n "$end" ]; then
                start=$(($end + 1))
            else
                alignment=$((2048 - ($start % 2048) ))
                start=$(($start + $alignment))
            fi
            [ $start -gt $disk_sectors ] && die "Partition abroad disk space, all sectors: $disk_sectors, start: $start"
            # if LVM
            if [ "_$type" = '_E6D6D379-F507-44C2-A23C-238F2A3DF928' ]; then
                if [ $number -eq $number_of_parts ]; then
                    size=$(($disk_sectors - $start - 2048))
                    size=$(($size - ($size % 8192) ))
                    lvm_size=$size
                else
                    size=$(($size - ($size % 8192) ))
                    lvm_size=$size
                fi
            elif [ '_'`grep "$part" $temp_dir/fstab | sed -n '/^#/! s/^[^[:space:]]*[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\1/p'` = '_/' ] || \
                [ '_'`grep "$uuid" $temp_dir/fstab | sed -n '/^#/! s/^[^[:space:]]*[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\1/p'` = '_/' ]; then
                tmp_size=$((58*1024*1024*2))
                if [ $size -gt $tmp_size ]; then
                    size=$tmp_size
                fi
                root=true
            else
                alignment=$((2048 - ($size % 2048) ))
                size=$(($size + $alignment))
            fi
            end=$(($start + $size - 1))
            if [ $end -gt $disk_sectors ]; then
                end=$(($disk_sectors - ($disk_sectors % 2028)))
            fi
            $ECHO "Create partition number: ${number}, type: ${type}"
            if [ $number -eq 1 ]; then
                $ECHO "> printf \"n\n${number}\n${start}\n${end}\nt\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                printf "n\n${number}\n${start}\n${end}\nt\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                    die "'fdisk' do not create ${type} partition on the \"$disk\"."
            else
                $ECHO "> printf \"n\n${number}\n${start}\n${end}\nt\n${number}\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                printf "n\n${number}\n${start}\n${end}\nt\n${number}\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                    die "'fdisk' do not create ${type} partition on the \"$disk\"."
            fi
            $ECHO "> sleep 1; sync; $REFRESH_PART $disk; sleep 5 # be on the safe side"
            sleep 1; sync; $REFRESH_PART $disk $DEV_NULL; sleep 5 # be on the safe side
            # if UEFI
            if [ "_$type" = '_C12A7328-F81F-11D2-BA4B-00A0C93EC93B' ]; then
                OLD_UEFI_PART=$part
                NEW_UEFI_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                OLD_UEFI_UUID=$uuid
                uefi_type_fs=`sed -n '/^#/! {/\/boot\/efi/ s/^[^[:space:]]*[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\2/p}' $temp_dir/fstab`
                if [ "$MKFS" = 'mkfs.' ] && ! command -v mkfs.$uefi_type_fs > /dev/null && command -v mkfs.fat > /dev/null; then
                        uefi_type_fs='fat -F 32'
                fi
                if [ -b "$NEW_UEFI_PART" ]; then
                    $ECHO "> printf 'y\n' | $MKFS$uefi_type_fs $NEW_UEFI_PART"
                    printf 'y\n' | $MKFS$uefi_type_fs $NEW_UEFI_PART $DEV_NULL || \
                        die "Not make filesystem $uefi_type_fs on $NEW_UEFI_PART"
                fi
                NEW_UEFI_UUID=`blkid | grep "$NEW_UEFI_PART" |sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_UEFI_PART: $OLD_UEFI_PART"
                $ECHO "OLD_UEFI_UUID: $OLD_UEFI_UUID"
                $ECHO "NEW_UEFI_PART: $NEW_UEFI_PART"
                $ECHO "NEW_UEFI_UUID: $NEW_UEFI_UUID"
            elif $root; then
                OLD_ROOT_PART=$part
                OLD_ROOT_UUID=$uuid
                NEW_ROOT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_ROOT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_ROOT_PART $DEV_NULL || \
                    die "Not make filesystem $type_fs on $NEW_ROOT_PART"
                NEW_ROOT_UUID=`blkid | grep "$NEW_ROOT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_ROOT_PART: $OLD_ROOT_PART"
                $ECHO "OLD_ROOT_UUID: $OLD_ROOT_UUID"
                $ECHO "NEW_ROOT_PART: $NEW_ROOT_PART"
                $ECHO "NEW_ROOT_UUID: $NEW_ROOT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /boot$"; then
                OLD_BOOT_PART=$part
                OLD_BOOT_UUID=$uuid
                NEW_BOOT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_BOOT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_BOOT_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_BOOT_PART\""
                NEW_BOOT_UUID=`blkid | grep "$NEW_BOOT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_BOOT_PART: $OLD_BOOT_PART"
                $ECHO "OLD_BOOT_UUID: $OLD_BOOT_UUID"
                $ECHO "NEW_BOOT_PART: $NEW_BOOT_PART"
                $ECHO "NEW_BOOT_UUID: $NEW_BOOT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /storages/local$"; then
                OLD_LOCAL_DEFAULT_PART=$part
                OLD_LOCAL_DEFAULT_UUID=$uuid
                NEW_LOCAL_DEFAULT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_LOCAL_DEFAULT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_LOCAL_DEFAULT_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_LOCAL_DEFAULT_PART\""
                NEW_LOCAL_DEFAULT_UUID=`blkid | grep "$NEW_LOCAL_DEFAULT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_LOCAL_DEFAULT_PART: $OLD_LOCAL_DEFAULT_PART"
                $ECHO "OLD_LOCAL_DEFAULT_UUID: $OLD_LOCAL_DEFAULT_UUID"
                $ECHO "NEW_LOCAL_DEFAULT_PART: $NEW_LOCAL_DEFAULT_PART"
                $ECHO "NEW_LOCAL_DEFAULT_UUID: $NEW_LOCAL_DEFAULT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /var/log$"; then
                OLD_LOG_PART=$part
                OLD_LOG_UUID=$uuid
                NEW_LOG_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_LOG_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_LOG_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_LOG_PART\""
                NEW_LOG_UUID=`blkid | grep "$NEW_LOG_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_LOG_PART: $OLD_LOG_PART"
                $ECHO "OLD_LOG_UUID: $OLD_LOG_UUID"
                $ECHO "NEW_LOG_PART: $NEW_LOG_PART"
                $ECHO "NEW_LOG_UUID: $NEW_LOG_UUID"
            elif ! $root && [ "_$type" = "_swap" ] || [ "_$type" = "_0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" ]; then
                OLD_SWAP_PART=$part
                OLD_SWAP_UUID=$uuid
                NEW_SWAP_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> mkswap $NEW_SWAP_PART"
                mkswap $NEW_SWAP_PART $DEV_NULL
                NEW_SWAP_UUID=`blkid | grep "$NEW_SWAP_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_SWAP_PART: $OLD_SWAP_PART"
                $ECHO "OLD_SWAP_UUID: $OLD_SWAP_UUID"
                $ECHO "NEW_SWAP_PART: $NEW_SWAP_PART"
                $ECHO "NEW_SWAP_UUID: $NEW_SWAP_UUID"
            fi

            root=false
            $ECHO "> sleep 1; sync; $REFRESH_PART $disk; sleep 5 # be on the safe side"
            sleep 1; sync; $REFRESH_PART $disk  $DEV_NULL; sleep 5 # be on the safe side
        done <<EOF
$(cat $temp_dir/fdisk.sfd | sed -n '/^$/ { :a; n; p; ba; }')
EOF
    elif [ "_$PART_LABEL" = '_dos' ]; then
        number=0
        pnumber=0
        extend=false
        root=false
        sign_logical=false
        # if disk greater 2TB (2199023255040/512 = 4294967295 # available sectors)
        if [ $disk_sectors -gt 4294967295 ]; then
            disk_sectors=4294967295
            sign_logical=true
        fi
        while read line; do
            $ECHO ">> $line"
            number=$((number+1))
            if $extend; then
                pnumber=5
                extend=false
            else
                pnumber=$((pnumber+1))
            fi
            part=`echo $line |sed 's/[[:space:]].*//'`
            uuid=`cat $temp_dir/blkid.txt | grep "$part" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
            type_fs=`grep "$part" $temp_dir/blkid.txt | sed 's/.* TYPE="\([^"]*\).*/\1/'`
            type=`echo $line | sed 's/.* type=\(.*\)*/\1/;{s/,.*//}'`
            size=`echo $line | sed 's/.*size=[[:space:]]*\([0-9][0-9]*\).*/\1/'`
            [ -z "$size" ] && die "Filed get size from line: $line"
            start=`echo $line | sed 's/.*start=[[:space:]]*\([0-9][0-9]*\).*/\1/'`

            if [ $pnumber -eq 5 ]; then
                start=$(($ext_start + 2048))
            elif [ $pnumber -gt 5 ] && [ -n "$end" ]; then
                start=$(($end + 2049))
            elif [ $number -gt 1 ] && [ -n "$end" ]; then
                start=$(($end + 1))
            elif [ $start -ne 2048 ]; then
                alignment=$((2048 - ($start % 2048) ))
                start=$(($start + $alignment))
            fi
            [ $start -gt $disk_sectors ] && die "Partition abroad disk space, all sectors: $disk_sectors, start: $start"
            # if LVM
            if [ "_$type" = '_5' ]; then
                size=$(($disk_sectors - $start - 2048))
                size=$(($size - ($size % 2048) ))
                extend=true
                ext_start=$start
            elif [ "_$type" = '_8e' ]; then
                if [ $number -eq $number_of_parts ]; then
                    size=$(($disk_sectors - $start - 4096)) # because we added into start 2048
                    size=$(($size - ($size % 8192) ))
                    lvm_size=$size
                else
                    size=$(($size - ($size % 8192) ))
                    lvm_size=$size
                fi
            elif [ '_'`grep "$part" $temp_dir/fstab | sed -n '/^#/! s/^[^[:space:]]*[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\1/p'` = '_/' ] || \
                [ '_'`grep "$uuid" $temp_dir/fstab | sed -n '/^#/! s/^[^[:space:]]*[[:space:]]*\([^[:space:]]*\)[[:space:]]*\([^[:space:]]*\)[[:space:]].*/\1/p'` = '_/' ]; then
                tmp_size=$((58*1024*1024*2))
                if [ $size -gt $tmp_size ]; then
                    size=$tmp_size
                fi
                root=true
            else
                alignment=$((2048 - ($size % 2048) ))
                size=$(($size + $alignment))
            fi
            end=$(($start + $size - 1))

            if [ $end -gt $disk_sectors ]; then
                if [ -n "$ext_end" ]; then
                    end=$(($ext_end - ($ext_end % 2048)))
                else
                    end=$(($disk_sectors - ($disk_sectors % 2048)))
                fi
            fi
            if [ -n "$ext_end" ] && [ $(($disk_sectors - $ext_end)) -gt 2050 ]; then
                 sign_logical=true
            fi
            if [ "_$type" = '_5' ]; then
                if [ $(($disk_sectors - $end)) -lt 2050 ]; then
                    end=$(($end - 2048))
                fi
                ext_end=$end
            fi

            $ECHO "Create partition number: ${pnumber}, type: ${type}"
            if [ $pnumber -ge 5 ] ;then
                if $sign_logical ; then
                    $ECHO "> printf \"n\nl\n${start}\n${end}\nt\n${pnumber}\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                    printf "n\nl\n${start}\n${end}\nt\n${pnumber}\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                        die "'fdisk' do not create ${type} logical partition on the \"$disk\"."
                else
                    $ECHO "> printf \"n\n${start}\n${end}\nt\n${pnumber}\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                    printf "n\n${start}\n${end}\nt\n${pnumber}\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                        die "'fdisk' do not create ${type} logical partition on the \"$disk\"."
                fi
            elif $extend ;then
                $ECHO "> printf \"n\ne\n${number}\n${start}\n${end}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                printf "n\ne\n${number}\n${start}\n${end}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                    die "'fdisk' do not create extended (${type}) partition on the \"$disk\"."
            elif [ $number -eq 1 ]; then
                $ECHO "> printf \"n\np\n${number}\n${start}\n${end}\nt\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                printf "n\np\n${number}\n${start}\n${end}\nt\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                    die "'fdisk' do not create ${type} partition on the \"$disk\"."
            else
                $ECHO "> printf \"n\np\n${number}\n${start}\n${end}\nt\n${number}\n${type}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                printf "n\np\n${number}\n${start}\n${end}\nt\n${number}\n${type}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                    die "'fdisk' do not create ${type} partition on the \"$disk\"."
            fi
            $ECHO "> sleep 1; sync; $REFRESH_PART $disk; sleep 5 # be on the safe side"
            sleep 1; sync; $REFRESH_PART $disk  $DEV_NULL; sleep 5 # be on the safe side
            # if bootable
            if echo $line | grep -q 'bootable'; then
                if [ $number -eq 1 ]; then
                    $ECHO "> printf \"a\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                    printf "a\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                        die "'fdisk' do not set bootable on partition $pnumber on the \"$disk\"."
                else
                    $ECHO "> printf \"a\n${number}\nw\nq\n\" | fdisk --lock=yes -W always $disk"
                    printf "a\n${number}\nw\nq\n" | fdisk --lock=yes -W always $disk $DEV_NULL || \
                        die "'fdisk' do not set bootable on partition $pnumber on the \"$disk\"."
                fi
            fi
            if $root; then
                OLD_ROOT_PART=$part
                OLD_ROOT_UUID=$uuid
                NEW_ROOT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_ROOT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_ROOT_PART $DEV_NULL || \
                    die "Not make filesystem $type_fs on $NEW_ROOT_PART"
                NEW_ROOT_UUID=`blkid | grep "$NEW_ROOT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_ROOT_PART: $OLD_ROOT_PART"
                $ECHO "OLD_ROOT_UUID: $OLD_ROOT_UUID"
                $ECHO "NEW_ROOT_PART: $NEW_ROOT_PART"
                $ECHO "NEW_ROOT_UUID: $NEW_ROOT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /boot$"; then
                OLD_BOOT_PART=$part
                OLD_BOOT_UUID=$uuid
                NEW_BOOT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_BOOT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_BOOT_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_BOOT_PART\""
                NEW_BOOT_UUID=`blkid | grep "$NEW_BOOT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_BOOT_PART: $OLD_BOOT_PART"
                $ECHO "OLD_BOOT_UUID: $OLD_BOOT_UUID"
                $ECHO "NEW_BOOT_PART: $NEW_BOOT_PART"
                $ECHO "NEW_BOOT_UUID: $NEW_BOOT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /storages/local$"; then
                OLD_LOCAL_DEFAULT_PART=$part
                OLD_LOCAL_DEFAULT_UUID=$uuid
                NEW_LOCAL_DEFAULT_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_LOCAL_DEFAULT_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_LOCAL_DEFAULT_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_LOCAL_DEFAULT_PART\""
                NEW_LOCAL_DEFAULT_UUID=`blkid | grep "$NEW_LOCAL_DEFAULT_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_LOCAL_DEFAULT_PART: $OLD_LOCAL_DEFAULT_PART"
                $ECHO "OLD_LOCAL_DEFAULT_UUID: $OLD_LOCAL_DEFAULT_UUID"
                $ECHO "NEW_LOCAL_DEFAULT_PART: $NEW_LOCAL_DEFAULT_PART"
                $ECHO "NEW_LOCAL_DEFAULT_UUID: $NEW_LOCAL_DEFAULT_UUID"
            elif ! $root && grep "$part" $temp_dir/df.txt | grep -q " /var/log$"; then
                OLD_LOG_PART=$part
                OLD_LOG_UUID=$uuid
                NEW_LOG_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> printf 'y\n' | $MKFS$type_fs $NEW_LOG_PART"
                printf 'y\n' | $MKFS$type_fs $NEW_LOG_PART $DEV_NULL || \
                    die "Not make filesystem \"$type_fs\" on \"$NEW_LOG_PART\""
                NEW_LOG_UUID=`blkid | grep "$NEW_LOG_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_LOG_PART: $OLD_LOG_PART"
                $ECHO "OLD_LOG_UUID: $OLD_LOG_UUID"
                $ECHO "NEW_LOG_PART: $NEW_LOG_PART"
                $ECHO "NEW_LOG_UUID: $NEW_LOG_UUID"
            elif ! $root && [ "_$type" = "_swap" ]; then
                OLD_SWAP_PART=$part
                OLD_SWAP_UUID=$uuid
                NEW_SWAP_PART=`fdisk -l $disk |tail -1 |sed 's/[[:space:]].*//'`
                $ECHO "> mkswap $NEW_SWAP_PART"
                mkswap $NEW_SWAP_PART $DEV_NULL
                NEW_SWAP_UUID=`blkid | grep "$NEW_SWAP_PART" | sed 's/.* UUID="\([^"]*\)".*/\1/'`
                $ECHO "OLD_SWAP_PART: $OLD_SWAP_PART"
                $ECHO "OLD_SWAP_UUID: $OLD_SWAP_UUID"
                $ECHO "NEW_SWAP_PART: $NEW_SWAP_PART"
                $ECHO "NEW_SWAP_UUID: $NEW_SWAP_UUID"
            fi
            root=false
            $ECHO "> sleep 1; sync; $REFRESH_PART $disk; sleep 5 # be on the safe side"
            sleep 1; sync; $REFRESH_PART $disk  $DEV_NULL; sleep 5 # be on the safe side
        done <<EOF
$(cat $temp_dir/fdisk.sfd | sed -n '/^$/ { :a; n; p; ba; }')
EOF
    fi
    # there are bugs, some busybox utils do not distinguish 'n' and '\n', so the last symbol should be not 'n'
    root_dir=`mktemp -d /tmp/root.XXXXXX`
    mv "$root_dir" "${root_dir}_"
    root_dir="${root_dir}_"
    $ECHO "ROOT DIR: $root_dir"
    add_trap "rm -rf $root_dir"

    lvm_part=`fdisk -l $disk |sed -n '/Linux LVM/ s/[[:space:]].*//p'`
    if [ -n "$lvm_part" ]; then
        IS_LVM=true
        $ECHO "USED LVM PARTITIONS"
        command -v pvcreate > /dev/null || die "Commands from lvm utils: pvcreate was not found."
        command -v vgcfgrestore > /dev/null || die "Commands from lvm utils: vgcfgrestore was not found."
        uuid_old_pv=`sed -n '/PV UUID/ s/.*PV UUID[[:space:]]*//p' $temp_dir/pvdisplay.txt`
        volum_group=`sed -n '/VG Name/ s/.*VG Name[[:space:]]*//p' $temp_dir/pvdisplay.txt`

        lvm_extent_size=`sed -n '/^[[:space:]]*extent_size/ s/.*extent_size = \([0-9]*\)[[:space:]].*/\1/p'  $temp_dir/$volum_group`
        $ECHO "LVM SIZE: $lvm_size"
        $ECHO "LVM_EXTENT_SIZE: $lvm_extent_size"
        $ECHO "Change size physical volume in restore file"
        # busybox sed can't so deep :-(
        $ECHO 'sed -i "/physical_volumes/{:x;n;/dev_size/by;bx;:y;s/^\([[:space:]]*dev_size = \).*/\1'$(($lvm_size - $lvm_extent_size))'/}" '$temp_dir/$volum_group
        sed -i "/physical_volumes/{:x;n;/dev_size/by;bx;:y;s/^\([[:space:]]*dev_size = \).*/\1$(($lvm_size - $lvm_extent_size))/}" $temp_dir/$volum_group
        pe_count=$(( ($lvm_size/$lvm_extent_size) - 2))
        $ECHO 'sed -i "/physical_volumes/{:x;n;/pe_count/by;bx;:y;s/^\([[:space:]]*pe_count = \).*/\1'$pe_count'/}" '$temp_dir/$volum_group
        sed -i "/physical_volumes/{:x;n;/pe_count/by;bx;:y;s/^\([[:space:]]*pe_count = \).*/\1$pe_count/}" $temp_dir/$volum_group
		array_logical_volumes="$(sed -n '/{/{/'"$volum_group"'/,/logical_volumes/d;/segment1/d;s/^[[:space:]]*\([^[:space:]}][^[:space:]}]*\)[[:space:]]*{.*/\1/p}' $temp_dir/$volum_group)"
		volume_swap=`echo "$array_logical_volumes" | tail -1`
		root_extend=false
		if `echo $volume_swap | grep -q "swap"`; then
    		swap_extent_count=`sed -n "/logical_volumes/{:x;n;/$volume_swap/by;bx;:y;{:x1;n;/extent_count \= /by1;bx1;:y1;s/^[[:space:]]*\extent_count \= \([[:digit:]]*\).*/\1/p}}" $temp_dir/$volum_group`
    		$ECHO "SWAP_EXTENT_COUNT: $swap_extent_count"
    		swap_pv0=`sed -n "/logical_volumes/{:x;n;/$volume_swap/by;bx;:y;{:x1;n;/\"pv0\", /by1;bx1;:y1;s/^[[:space:]]*\"pv0\", \([[:digit:]]*\).*/\1/p}}" $temp_dir/$volum_group`
    		$ECHO "SWAP_PV0: $swap_pv0"
		    if [ $pe_count -lt $(($swap_extent_count + $swap_pv0)) ]; then
		        swap_extent_count=$(($pe_count - $swap_pv0))
		        $ECHO "Change extent_count to new: $swap_extent_count"
		        $ECHO "sed -i \"/logical_volumes/{:x;n;/$volume_swap/by;bx;:y;{:x1;n;/extent_count \= /by1;bx1;:y1;s/^\([[:space:]]*\extent_count \= \).*/\1$swap_extent_count/}}\" $temp_dir/$volum_group"
		        sed -i "/logical_volumes/{:x;n;/$volume_swap/by;bx;:y;{:x1;n;/extent_count \= /by1;bx1;:y1;s/^\([[:space:]]*\extent_count \= \).*/\1$swap_extent_count/}}" $temp_dir/$volum_group
    		elif [ `echo "$array_logical_volumes" | wc -l` -eq 2 ] && [ `echo "$array_logical_volumes" | tail -2 | head -1` = "root" ]; then
				root_extend=true
	    		fi
		fi
        $ECHO "> printf 'y\n' | pvcreate --uuid $uuid_old_pv --restorefile $temp_dir/$volum_group $lvm_part"
        printf 'y\n' | pvcreate --uuid $uuid_old_pv --restorefile $temp_dir/$volum_group $lvm_part $DEV_NULL || \
            die "Can not create phisical volume on part: $lvm_part."
        $ECHO "> vgcfgrestore -f $temp_dir/$volum_group $volum_group"
        vgcfgrestore -f $temp_dir/$volum_group $volum_group $DEV_NULL || \
            die "Can not restore volume group: $volum_group."
        $ECHO "> vgchange -ay $volum_group"
        vgchange -ay $volum_group $DEV_NULL || die "Problems with active volumes on volume group: $volum_group."
        $ECHO "> lvs -olv_name --noheadings $volum_group"
        lvs -olv_name --noheadings $volum_group $DEV_NULL
        for i in `lvs -olv_name --noheadings $volum_group`; do
            type_fs=`grep "$volum_group-$i" $temp_dir/blkid.txt | sed 's/.* TYPE="\([^"]*\).*/\1/'`
            if [ "_$type_fs" = "_swap" ] && [ -b "/dev/mapper/$volum_group-$i" ]; then
                #IS_LVM_SWAP=true
                $ECHO "> mkswap /dev/mapper/$volum_group-$i"
                mkswap /dev/mapper/$volum_group-$i $DEV_NULL
            elif [ -b "/dev/mapper/$volum_group-$i" ]; then
                if [ "_$i" = '_local_storage' ]; then
                    $ECHO "> pvresize $lvm_part"
                    pvresize $lvm_part $DEV_NULL || die "Failed to resize phisical volume $lvm_part"
                    $ECHO "> lvextend -l +100%FREE /dev/mapper/$volum_group-local_storage"
                    lvextend -l +100%FREE /dev/mapper/$volum_group-local_storage $DEV_NULL || \
                        die "Can not resize volume: /dev/mapper/$volum_group-local_storage."
                elif [ "_$i" = '_root' ] && $root_extend; then
                    $ECHO "> pvresize $lvm_part"
                    pvresize $lvm_part $DEV_NULL || die "Failed to resize phisical volume $lvm_part"
                    $ECHO "> lvextend -l +100%FREE /dev/mapper/$volum_group-root"
                    lvextend -l +100%FREE /dev/mapper/$volum_group-root $DEV_NULL || \
                        die "Can not resize volume: /dev/mapper/$volum_group-root."
                fi
                $ECHO "> printf 'y\n' | $MKFS$type_fs /dev/mapper/$volum_group-$i"
                printf 'y\n' | $MKFS$type_fs /dev/mapper/$volum_group-$i $DEV_NULL || \
                    die "Not make filesystem $type_fs on /dev/mapper/$volum_group-$i"
            fi
        done
        OLD_ROOT_UUID=`grep "/dev/mapper/${volum_group}-root" $temp_dir/blkid.txt |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "OLD ROOT UUID: $OLD_ROOT_UUID"
        NEW_ROOT_UUID=`blkid "/dev/mapper/${volum_group}-root" |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "NEW ROOT UUID: $NEW_ROOT_UUID"

        OLD_LOCAL_DEFAULT_UUID=`grep "/dev/mapper/${volum_group}-local_storage" $temp_dir/blkid.txt |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "OLD LOCAL_DEFAULT UUID: $OLD_LOCAL_DEFAULT_UUID"
        NEW_LOCAL_DEFAULT_UUID=`blkid "/dev/mapper/${volum_group}-local_storage" |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "NEW LOCAL_DEFAULT UUID: $NEW_LOCAL_DEFAULT_UUID"

        OLD_LOG_UUID=`grep "/dev/mapper/${volum_group}-log_storage" $temp_dir/blkid.txt |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "OLD LOG UUID: $OLD_LOG_UUID"
        NEW_LOG_UUID=`blkid "/dev/mapper/${volum_group}-log_storage" |sed 's/.* UUID="\([^"]*\).*/\1/'`
        $ECHO "NEW LOG UUID: $NEW_LOG_UUID"

        $ECHO "> mount /dev/mapper/${volum_group}-root $root_dir"
        mount /dev/mapper/${volum_group}-root $root_dir || \
            die "Not mounted /dev/mapper/${volum_group}-root to temp dir $root_dir."
        add_trap "umount $root_dir"

        $ECHO "> mkdir -p $root_dir/storages/local"
        mkdir -p $root_dir/storages/local
        $ECHO "> mount /dev/mapper/${volum_group}-local_storage $root_dir/storages/local"
        mount /dev/mapper/${volum_group}-local_storage $root_dir/storages/local
        add_trap "umount $root_dir/storages/local"

        $ECHO "> mkdir -p $root_dir/var/log"
        mkdir -p $root_dir/var/log
        $ECHO "> mount /dev/mapper/${volum_group}-log_storage $root_dir/var/log"
        mount /dev/mapper/${volum_group}-log_storage $root_dir/var/log
        add_trap "umount $root_dir/var/log"
    else
        if [ -b "$NEW_ROOT_PART" ]; then
            $ECHO "> mount $NEW_ROOT_PART $root_dir"
            mount $NEW_ROOT_PART $root_dir || die "Not mounted \"$NEW_ROOT_PART\" to temp dir \"$root_dir\"."
            add_trap "umount $root_dir"
        else
            die "Not exist partitional $NEW_ROOT_PART."
        fi
        if [ -n "$NEW_LOCAL_DEFAULT_PART" ] && [ -b "$NEW_LOCAL_DEFAULT_PART" ]; then
            $ECHO "> mkdir -p $root_dir/storages/local"
            mkdir -p $root_dir/storages/local
            $ECHO "> mount $NEW_LOCAL_DEFAULT_PART $root_dir/storages/local"
            mount $NEW_LOCAL_DEFAULT_PART $root_dir/storages/local \
                || die "Not mounted $NEW_LOCAL_DEFAULT_PART to $root_dir/storages/local."
            add_trap "umount $root_dir/storages/local"
        fi
        if [ -n "$NEW_LOG_PART" ] && [ -b "$NEW_LOG_PART" ]; then
            $ECHO "> mkdir -p $root_dir/var/log"
            mkdir -p $root_dir/var/log
            $ECHO "> mount $NEW_LOG_PART $root_dir/var/log"
            mount $NEW_LOG_PART $root_dir/var/log \
                || die "Not mounted $NEW_LOG_PART to $root_dir/var/log."
            add_trap "umount $root_dir/var/log"
        fi
    fi
    if [ -n "$NEW_BOOT_PART" ]; then
        $ECHO "NEW BOOT PART: \"$NEW_BOOT_PART\""
        test -b "$NEW_BOOT_PART" || die "Disk partitional for boot: \"$NEW_BOOT_PART\" not found."
        $ECHO "> mkdir -p $root_dir/boot"
        mkdir -p $root_dir/boot
        $ECHO "> mount $NEW_BOOT_PART $root_dir/boot"
        mount $NEW_BOOT_PART $root_dir/boot || die "Not mounted \"$NEW_BOOT_PART\" to \"$root_dir/boot\"."
        add_trap "umount $root_dir/boot"
    fi
    if [ -n "$NEW_UEFI_PART" ]; then
        $ECHO "Mount UEFI boot part."
        $ECHO "NEW UEFI PART: \"$NEW_UEFI_PART\""
        test -b "$NEW_UEFI_PART" || die "Disk partitional for uefi: \"$NEW_UEFI_PART\" not found."
        if [ ! -d $root_dir/boot/efi ]; then
        	$ECHO "mkdir -p $root_dir/boot/efi"
            mkdir -p $root_dir/boot/efi
        fi
        $ECHO "> mount $NEW_UEFI_PART $root_dir/boot/efi"
        mount $NEW_UEFI_PART $root_dir/boot/efi || die "Not mounted \"$NEW_UEFI_PART\" to \"$root_dir/boot/efi\"."
        add_trap "umount $root_dir/boot/efi"
    fi
    if command -v losetup > /dev/null; then
        attach_data_archive
        if [ -b "$archive" ]; then
            $ECHO "> tar -xzf $archive -C $root_dir"
            eval "tar -xzf $archive -C $root_dir $DEV_NULL" || die "Problem with extract data from backup."
        else
            die "Block device \"$archive\" not found."
        fi
    else
        $ECHO "> dd if=$SCRIPT_PATH bs=512 skip=$(( ($SCRIPT_LEN + $CFG_LEN) / 512)) | tar -xz -C $root_dir"
        eval "dd if=$SCRIPT_PATH bs=512 skip=$(( ($SCRIPT_LEN + $CFG_LEN) / 512)) $ERR_NULL | tar -xz -C $root_dir" || \
            die "Tar extract root files via 'dd' has trables."
    fi
    $ECHO "> mkdir -p $root_dir/dev $root_dir/run $root_dir/sys $root_dir/proc $root_dir/tmp $root_dir/var/lib/ntp/proc $root_dir/var/lib/lxcfs $root_dir/var/tmp"
    mkdir -p $root_dir/dev $root_dir/run $root_dir/sys $root_dir/proc $root_dir/tmp \
        $root_dir/var/lib/ntp/proc $root_dir/var/lib/lxcfs $root_dir/var/tmp

    [ -f $root_dir/etc/fstab ] || die "Not exist $root_dir/etc/fstab."
    [ -f $root_dir/boot/grub/grub.cfg ] || die "Not exist $root_dir/boot/grub/grub.cfg."
    if [ -n "$OLD_BOOT_UUID" ] && [ -n "$NEW_BOOT_UUID" ]; then
        $ECHO "Replace uuid for boot part."
        $ECHO "> sed -i \"s/$OLD_BOOT_UUID/$NEW_BOOT_UUID/g\" $root_dir/etc/fstab"
        sed -i "s/$OLD_BOOT_UUID/$NEW_BOOT_UUID/g" $root_dir/etc/fstab
        $ECHO "> sed -i \"s/$OLD_BOOT_UUID/$NEW_BOOT_UUID/g\" $root_dir/boot/grub/grub.cfg"
        sed -i "s/$OLD_BOOT_UUID/$NEW_BOOT_UUID/g" $root_dir/boot/grub/grub.cfg
    fi
    if [ -n "$OLD_BOOT_PART" ] && [ -n "$NEW_BOOT_PART" ]; then
        $ECHO "Replace partition for boot part."
        $ECHO "> sed -i \"s|$OLD_BOOT_PART|$NEW_BOOT_PART|g\" $root_dir/etc/fstab"
        sed -i "s|$OLD_BOOT_PART|$NEW_BOOT_PART|g" $root_dir/etc/fstab
        $ECHO "> sed -i \"s|$OLD_BOOT_PART|$NEW_BOOT_PART|g\" $root_dir/boot/grub/grub.cfg"
        sed -i "s|$OLD_BOOT_PART|$NEW_BOOT_PART|g" $root_dir/boot/grub/grub.cfg
    fi

    if [ -n "$OLD_ROOT_UUID" ] && [ -n "$NEW_ROOT_UUID" ]; then
        $ECHO "Replace uuid for root part."
        $ECHO "> sed -i \"s/$OLD_ROOT_UUID/$NEW_ROOT_UUID/g\" $root_dir/etc/fstab"
        sed -i "s/$OLD_ROOT_UUID/$NEW_ROOT_UUID/g" $root_dir/etc/fstab
        $ECHO "> sed -i \"s/$OLD_ROOT_UUID/$NEW_ROOT_UUID/g\" $root_dir/boot/grub/grub.cfg"
        sed -i "s/$OLD_ROOT_UUID/$NEW_ROOT_UUID/g" $root_dir/boot/grub/grub.cfg
    fi

    if [ -n "$OLD_LOCAL_DEFAULT_UUID" ] && [ -n "$NEW_LOCAL_DEFAULT_UUID" ]; then
        $ECHO "Replace uuid for storages_local part."
        $ECHO "> sed -i \"s/$OLD_LOCAL_DEFAULT_UUID/$NEW_LOCAL_DEFAULT_UUID/g\" $root_dir/etc/fstab"
        sed -i "s/$OLD_LOCAL_DEFAULT_UUID/$NEW_LOCAL_DEFAULT_UUID/g" $root_dir/etc/fstab
    fi

    if [ -n "$OLD_LOG_UUID" ] && [ -n "$NEW_LOG_UUID" ]; then
        $ECHO "Replace uuid for log_storage part."
        $ECHO "> sed -i \"s/$OLD_LOG_UUID/$NEW_LOG_UUID/g\" $root_dir/etc/fstab"
        sed -i "s/$OLD_LOG_UUID/$NEW_LOG_UUID/g" $root_dir/etc/fstab
    fi

    if [ -n "$NEW_UEFI_PART" ]; then
        if [ -n "$OLD_UEFI_UUID" ] &&[ -n "$NEW_UEFI_UUID" ]; then
            $ECHO "Replace uuid for uefi part."
            $ECHO "> sed -i \"s/$OLD_UEFI_UUID/$NEW_UEFI_UUID/g\" $root_dir/etc/fstab"
            sed -i "s/$OLD_UEFI_UUID/$NEW_UEFI_UUID/g" $root_dir/etc/fstab
        fi
        if [ -n "$OLD_UEFI_PART" ]; then
            $ECHO "Replace uuid for uefi part."
            $ECHO "> sed -i \"s:$OLD_UEFI_PART:$NEW_UEFI_PART:g\" $root_dir/etc/fstab"
            sed -i "s:$OLD_UEFI_PART:$NEW_UEFI_PART:g" $root_dir/etc/fstab
        fi
    fi
    if [ -f "$root_dir/etc/initramfs-tools/conf.d/resume" ]; then
        IS_RESUME=true
        RESUME=`sed -n '/^RESUME=/ s/^RESUME=//p' "$root_dir/etc/initramfs-tools/conf.d/resume"`
        if echo $RESUME | grep -q 'UUID='; then
            IS_UUID_RESUME=true
        else
            IS_UUID_RESUME=false
        fi
    else
        IS_RESUME=false
    fi
    if [ -n "$NEW_SWAP_PART" ];then
        if [ -n "$NEW_SWAP_UUID" ];then
            $ECHO "> sed -i '/^#/! {/swap/ s/.*/#&/g}' $root_dir/etc/fstab"
            sed -i '/^#/! {/swap/ s/.*/#&/g}' $root_dir/etc/fstab
            $ECHO "> echo \"UUID=$NEW_SWAP_UUID none            swap    sw              0       0\" >> $root_dir/etc/fstab"
            echo "$NEW_SWAP_UUID none            swap    sw              0       0" >> $root_dir/etc/fstab
            if $IS_RESUME; then
                $ECHO "> sed -i \"/^RESUME=/ s:.*:RESUME=UUID=$NEW_SWAP_UUID:\" $root_dir/etc/initramfs-tools/conf.d/resume"
                sed -i "/^RESUME=/ s:.*:RESUME=UUID=$NEW_SWAP_UUID:" $root_dir/etc/initramfs-tools/conf.d/resume
            fi
        else
            $ECHO "> sed -i '/^#/! {/swap/ s/.*/#&/g}' $root_dir/etc/fstab"
            sed -i '/^#/! {/swap/ s/.*/#&/g}' $root_dir/etc/fstab
            $ECHO "> echo \"$NEW_SWAP_PART none            swap    sw              0       0\" >> $root_dir/etc/fstab"
            echo "$NEW_SWAP_PART none            swap    sw              0       0" >> $root_dir/etc/fstab
            if $IS_RESUME; then
                $ECHO "> sed -i \"/^RESUME=/ s:.*:RESUME=$NEW_SWAP_PART:\" $root_dir/etc/initramfs-tools/conf.d/resume"
                sed -i "/^RESUME=/ s:.*:RESUME=$NEW_SWAP_PART:" $root_dir/etc/initramfs-tools/conf.d/resume
            fi
        fi
    fi
    add_trap "umount $root_dir/proc"
    $ECHO "> mount -t proc none $root_dir/proc"
    mount -t proc none $root_dir/proc || die "Failed to mount proc"
    add_trap "umount $root_dir/sys"
    $ECHO "> mount -t sysfs none $root_dir/sys"
    mount -t sysfs none $root_dir/sys || die "Failed to mount sys"
    add_trap "umount $root_dir/dev"
    $ECHO "> mount -o bind /dev $root_dir/dev"
    mount -o bind /dev $root_dir/dev || die "Failed to mount dev"
    add_trap "umount $root_dir/dev/pts"
    $ECHO "> mount -o bind /dev/pts $root_dir/dev/pts"
    mount -o bind /dev/pts $root_dir/dev/pts || die "Failed to mount dev/pts"

    $ECHO "> mv $root_dir/root/.bashrc $root_dir/root/.bashrc.save"
    mv $root_dir/root/.bashrc $root_dir/root/.bashrc.save
    cat <<EOF | chroot $root_dir /bin/bash
$ECHO "> source /etc/profile"
source /etc/profile $DEV_NULL
$ECHO "> update-initramfs -u -k all"
update-initramfs -u -k all $DEV_NULL
$ECHO "> grub-install --bootloader-id=debian $disk"
grub-install --bootloader-id=debian $disk $DEV_NULL
EOF
    $ECHO "> mv $root_dir/root/.bashrc.save $root_dir/root/.bashrc"
    mv $root_dir/root/.bashrc.save $root_dir/root/.bashrc
    if grep -q 'controller=1' $root_dir/etc/veil/media.conf; then
    	$ECHO "> echo $SCRIPT_NAME > $root_dir/var/lib/ecp-veil/backup_os.txt"
		echo $SCRIPT_NAME > $root_dir/var/lib/ecp-veil/backup_os.txt
		$ECHO "> du -b $SCRIPT_PATH | sed \"s/\s.*//\" >> $root_dir/var/lib/ecp-veil/backup_os.txt"
		du -b $SCRIPT_PATH | sed "s/\s.*//" >> $root_dir/var/lib/ecp-veil/backup_os.txt
		$ECHO "> chmod 666 $root_dir/var/lib/ecp-veil/backup_os.txt"
		chmod 666 $root_dir/var/lib/ecp-veil/backup_os.txt
	fi
    clear_before_exit
    echo "Restore to $disk successful."
fi
clear_before_exit
exit 0
