#!/bin/bash
#Author Buquan Liu, liubuquan@kylinos.cn, walt_lbq@163.com
#本程序本质上是对backup-auto/autobackup.cpp的重写.
#因为采用Qt程序则打包进入内核，相应的库会导致内核超过16M，故改为shell程序.

#backup-auto --autobackup ${rootpath} /backup
#backup-auto --autorestore ${rootpath} /backup

echo $*

#xgs备份还原要保留更多的文件或目录:
#kybackup/maindialog.cpp, backup-daemon/mountpoint.cpp, backup-daemon/data/backup-auto-efi
XGS=false

INFO="/etc/.bootinfo"
METAINFO=".METAINFO"
KB=1024
MB=1048576
GB=1073741824

if [ $# -lt 3 ]; then
    exit 18
fi

#是否有/data数据分区
hasDataPartition=0
backupORrestore=$1
rootpath=$2
m_mountPath=$3
m_default_uuid=$4

m_backuplistPath="${rootpath}${m_mountPath}/snapshots/backuplist.xml"

EXCLUDEFILE="${rootpath}${m_mountPath}/snapshots/.exclude"
PLOGFILEDIR="${rootpath}${m_mountPath}/log"
PLOGFILE="$PLOGFILEDIR/grub.log"
SNAPSHOTDIR="${rootpath}${m_mountPath}/snapshots/"
LOGFILE="${rootpath}${m_mountPath}/log.txt" #LOGFILE="/tmp/log.txt"
WHITELISTFILE="${rootpath}${m_mountPath}/snapshots/.whitelist"

#是否是出厂备份
m_isFactory=false
factory_uuid="00000000-0000-0000-0000-000000000000"
auto_uuid="01234567-0123-0123-0123-0123456789ab"
PERSONAL_EXCLUDEFILE=".exclude.user.txt"
PERSONAL_BACKUPFILE=".user.txt"
m_isRetainUserData=false
m_PrefixDestPath=""
m_Position=false

#V11相关参数变量
#repo仓库位置
g_repo_factory="${m_mountPath}/repo_factory"
g_repo_system_update="${m_mountPath}/repo_system_update"
g_repo_system="${m_mountPath}/repo_system"
#xml元数据位置
g_factory_backuplist_xml="${rootpath}${m_mountPath}/snapshots/factory_backuplist.xml"
g_system_update_backuplist_xml="${rootpath}${m_mountPath}/snapshots/sys_update_backuplist.xml"
g_system_backuplist_xml="${rootpath}${m_mountPath}/snapshots/sys_backuplist.xml"

NEEDROOLBACKFILE="${m_mountPath}/roolback.txt"

#备份点哈希
m_restore_uuid=""
m_system_hash=""
m_ovl_hash=""
m_home_hash=""
m_restore_repo=""
m_username=""

#是否涉及到升级备份点还原
m_isSystemUpdate=false


#如果/backup不存在，则创建该目录
mkdir -p ${rootpath}${m_mountPath}
if [ $? -ne 0 ]; then
    echo "Could not create /backup in initrd!"
    exit 20
fi
m_restoreUuid=""
m_enabled=""
global_system_usedDisk=0
m_size=0
newSize=0

#-----------------------------------------------------------------
get_is_990_9a0() {
    local ret=false
    # 匹配 kirin 990 5g, kirin990, kirin 9006c
    if egrep -qi 'kirin.?9[09]0' /proc/cpuinfo; then
        ret=true
    elif egrep -qi 'PANGU' /proc/cpuinfo; then
	ret=true

    fi
    echo $ret
}
is_990_9a0=$(get_is_990_9a0)
#see backup-auto/autobackup.cpp
getBackupInfo() {
    if [ "$rootpath" = "/" ]; then
        bootinfo=$INFO
    else
        bootinfo=${rootpath}${INFO}
    fi

    if [ ! -e "$bootinfo" ]; then
	# 系统崩坏，如操作失误删除了/etc目录
	if [ -e $INFO ]; then
	    bootinfo=$INFO
	else
            echo "$bootinfo file not exist!"
            m_restoreUuid=""
            # exit 1
            return
	fi
    fi

    which_line=0
    content=$(cat "$bootinfo" | grep -Ev "^#" | grep "=" | awk '{print $1}')
    for line in $content; 
    do
        #parse_device "$device"
        #只读第1行：RECOVERY_DEV_UUID=c965e712-9903-4139-b8da-c6e1eef0af6a
        if [ $which_line -eq 0 ]; then
            m_restoreUuid=$(echo $line | sed 's:.*=::' | tr -d "\n")
            which_line=$(expr $which_line + 1)
        else
            m_enabled=$(echo $line | sed 's:.*=::' | tr -d "\n")
            which_line=$(expr $which_line + 1)
        fi
    done
}

#-----------------------------------------------------------------

#该函数是对backup-daemon/parsebackuplist.cpp中相应函数的替换
createBackupList() {
    local backuplistDir="${m_mountPath}/snapshots/"

    if [ ! -e "$backuplistDir" ]; then
        mkdir -p $backuplistDir
    fi

    if [ ! -e "$m_backuplistPath" ]; then
        #echo "$m_backuplistPath file not exist!"

        #第1行'>'会清空后写文件
        echo "<?xml version='1.0'?>" >$m_backuplistPath
        #echo "<backupList>" >>$m_backuplistPath
        #echo "</backupList>" >>$m_backuplistPath
        echo "<backupList/>" >>$m_backuplistPath #QDomDocument在节点为空时如此生成根节点
    fi
}

#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
mountBackup() {

	# 无备份分区时
	if [ "${m_restoreUuid}xy" = "xy" ]; then
    	echo "No backup partation. Log for backuping and restoring...."
		mount -o defaults,bind  ${rootpath}/backup ${m_mountPath}
		sleep 1
	else
		local myuuid="/dev/disk/by-uuid/"$m_restoreUuid
    		#echo "myuuid: $myuuid"

    		#support lvm by zhangze
    		tmp_root_dev=$(mount | grep " /root " | cut -d ' ' -f 1)
    		case "$tmp_root_dev" in
    		/dev/mapper/*)
        		eval $(dmsetup splitname --nameprefixes --noheadings --rows "${tmp_root_dev#/dev/mapper/}")
        		if [ "$DM_VG_NAME" ] && [ "$DM_LV_NAME" ]; then
            			lvm lvchange -aay -y --sysinit --ignoreskippedcluster "$DM_VG_NAME"
        		fi
        		;;
    		esac

    		#mount $myuuid $m_mountPath
    		mount -o defaults,rw -U $m_restoreUuid $m_mountPath
    		if [ $? -ne 0 ]; then
        		echo "Mount backup failed!"
        		exit 21
    		fi
	fi

    mkdir -p $PLOGFILEDIR
    if [ $? -ne 0 ]; then
        echo "Could not create log directory in /backup"
        exit 22
    fi

    touch $PLOGFILE
    if [ $? -ne 0 ]; then
        echo "Could not create log file"
        exit 23
    fi

    echo "Log for backuping and restoring...." > $PLOGFILE
    createBackupList #创建备份信息
}

#-----------------------------------------------------------------
#see backup-auto/autobackup.cpp
umountBackup() {
    umount $m_mountPath
}

#-----------------------------------------------------------------
#see backup-auto/backupcommon.cpp
#在grub时，根分区为/root；在进入系统后，根分区为/
#parameters: rootDiskName
#返回值 elements=( $totalSize $freeDisk $usedDisk )
caculateDiskSize() {
    local origalParas

    origalParas=($(echo "$@"))
    num=$(($#))

    #if [ $# -ne 2 ]; then
    if [ $num -ne 2 ]; then
        echo "You shoud input the rootDiskName and disk"
        exit 19
    fi

    local fullDiskName
    local totalSize
    local freeDisk
    local usedDisk

    if [ "${origalParas[1]}" = "/" ]; then
        fullDiskName=${origalParas[0]}
    else
        fullDiskName=${origalParas[0]}${origalParas[1]}
    fi

    if [ ! -e "$fullDiskName" ]; then
        ##因为要返回数组，所以下面的echo没有上面用，不会显示，只会作为返回值
        #echo "$fullDiskName not exist!"
        elements=(0 0 0)
        echo ${elements[*]}
        return
    fi

    ##因为要返回数组，这里不能echo "fullDiskName: $fullDiskName"
    sss=$(df -k $fullDiskName | sed '1d' | tr -d "\n")
    freeDisk=$(echo $sss | awk '{print $4}')
    freeDisk=$(expr 1024 \* $freeDisk)
    usedDisk=$(echo $sss | awk '{print $3}')
    usedDisk=$(expr 1024 \* $usedDisk)

    #totalSize没有从df命令的第2列来取，该值比下面2个的和还要大
    totalSize=$(expr $usedDisk + $freeDisk)

    ##因为要返回数组，这里不能echo "freeDisk=$freeDisk"
    ##因为要返回数组，这里不能echo "usedDisk=$usedDisk"
    ##因为要返回数组，这里不能echo "totalSize=$totalSize"

    #local elements
    elements=($totalSize $freeDisk $usedDisk)
    echo ${elements[*]}
}

parse_device() {
    device=$1
    if echo $device | grep -E -q "^UUID="; then
        echo $device | sed 's:^UUID=:/dev/disk/by-uuid/:' | tr -d "\n"
    elif echo $device | grep -E -q "^LABEL="; then
        echo $device | sed 's:^LABEL=:/dev/disk/by-label/:' | tr -d "\n"
    else
        echo $device | tr -d "\n"
    fi
}

is_remote() {
    fstype=$1
    if [ nfs = "$fstype" ] || [ nfs4 = "$fstype" ] || [ smbfs = "$fstype" ] || [ cifs = "$fstype" ] || [ coda = "$fstype" ] || [ ncp = "$fstype" ]; then
        echo yes
    elif [ ncpfs = "$fstype" ] || [ ocfs2 = "$fstype" ] || [ gfs = "$fstype" ] || [ gfs2 = "$fstype" ] || [ ceph = "$fstype" ]; then
        echo yes
    else
        echo no
    fi
}

function caculateDirSize() {
  mkdir -p /backup/snapshots/check/data
  local total_file_size=$(rsync  -aAHXrn --stats --ignore-missing-args --exclude=/backup --exclude=/cdrom --exclude=/dev --exclude=/etc/uid_list --exclude=/ghost --exclude=/data/ghost --exclude=/lost+found --exclude=/media --exclude=/mnt --exclude=/proc --exclude=/run --exclude=/swap_file --exclude=/sys --exclude=/tmp --exclude=/var/lib/docker/overlay2 --exclude=/var/lib/kmre/data --exclude=/var/lib/kmre/kmre-*-*/data/media/0/0-麒麟* --exclude=/var/lib/udisks2 --exclude=/var/log --exclude=*/backup/snapshots --exclude=/data/home --exclude=/data/root "${rootpath}/" /backup/snapshots/check/data/ | grep "Total file size:" | awk '{print $4}' | sed 's/,//g')
  total_file_size=$(expr ${total_file_size} + 200000000)
  echo "备份所需空间大小：${total_file_size}" >>$PLOGFILE
  echo "${total_file_size}"
}

#parameters: 无
#返回值：(system_totalSize system_freeDisk system_usedDisk)
caculateSystemSize() {
    local root_totalSize root_freeDisk root_usedDisk
    local system_totalSize system_freeDisk system_usedDisk
    local origalParas
    local found item result
    local device mntdir fstype options dump passno
    #local -a alreadyDisks #数组，已经分析过的磁盘目录
    local -a elements     #存放返回值

    #alreadyDisks=(${alreadyDisks[*]} "/boot") #插入一个元素"/boot"

    #result=(`caculateDiskSize "$rootpath" "$rootpath"`)
    #origalParas=($rootpath "/")
    #arg1=$(echo ${origalParas[*]})

    #result=($(caculateDiskSize $arg1))
    #root_totalSize=${result[0]}
    #root_freeDisk=${result[1]}
    #root_usedDisk=${result[2]}

    #system_totalSize=$root_totalSize
    #system_freeDisk=$root_freeDisk
    #system_usedDisk=$root_usedDisk

    #echo "system_totalSize="$system_totalSize
    #echo "system_freeDisk="$system_freeDisk
    #echo "system_usedDisk="$system_usedDisk

    ##############3#caculateDiskSize / /backup
    fstab_path=${rootpath}/etc/fstab

    if [ ! -e "$fstab_path" ]; then
	fstab_path=/etc/fstab-backup
        if [ ! -e "$fstab_path" ]; then
            echo "$fstab_path file not exist!"
            exit 16
	fi
    fi

    system_totalSize=0
    system_freeDisk=0
    system_usedDisk=0
    while read line; do
        #取第1个字符
        if [ "${line:0:1}" = "#" ]; then
            continue
        fi

        echo $line
	echo $line >>$PLOGFILE

        device=$(echo "$line" | awk '{print $1}')
        mntdir=$(echo "$line" | awk '{print $2}')
        fstype=$(echo "$line" | awk '{print $3}')
        options=$(echo "$line" | awk '{print $4}')
        dump=$(echo "$line" | awk '{print $5}')
        passno=$(echo "$line" | awk '{print $6}')

        device=$(parse_device $device)
	
	if [[ $options =~ "bind" ]]; then
	    continue
        fi

        # nodev filesystems
        (cat /proc/filesystems | grep "$fstype" | grep -q nodev) && continue

        # virtual or network filesystems
        [ none = "$mntdir" ] || [ yes = $(is_remote $fstype) ] && continue

        # swap or rootfs
        [ swap = "$fstype" ] && continue
        #[ swap = "$fstype" ] || [ / = "$mntdir" ] || [ /home = "$mntdir" ] || [ /var/log = "$mntdir" ]&& continue

        #取第1个字符
        if [ "${mntdir:0:1}" != "/" ]; then
            continue
        fi

        if [ $mntdir = "/backup" ]; then #没有写成$m_mountPath,看下面if
            continue
        fi

        if [ $mntdir = $m_mountPath ]; then #没有写成$m_mountPath
            continue
        fi

        #注意: 没有备份数据分区
        if [ $mntdir = "/data" ]; then
            hasDataPartition=1
        fi

        #echo "1: " $device
        #echo "2: " $mntdir
        #echo "3: " $fstype
        #echo "4: " $options
        #echo "5: " $dump
        #echo "6: " $passno

        # not system partition
        #		[ no = $(is_system_partition $mntdir) ] && continue

        ################计算df $target_mntdir的各项值
        origalParas=($rootpath $mntdir)
        arg1=$(echo ${origalParas[*]})

        result=($(caculateDiskSize $arg1))
        disk_totalSize=${result[0]}
        disk_freeDisk=${result[1]}
        disk_usedDisk=${result[2]}

        #echo "disk_totalSize="$disk_totalSize
        #echo "disk_freeDisk="$disk_freeDisk
        #echo "disk_usedDisk="$disk_usedDisk

        system_totalSize=$(expr $system_totalSize + $disk_totalSize)
        system_freeDisk=$(expr $system_freeDisk + $disk_freeDisk)
        system_usedDisk=$(expr $system_usedDisk + $disk_usedDisk)

        #echo "system_totalSize="$system_totalSize
        #echo "system_freeDisk="$system_freeDisk
        #echo "system_usedDisk="$system_usedDisk

    done <"$fstab_path"

    #echo "system_totalSize="$system_totalSize
    #echo "system_freeDisk="$system_freeDisk
    #echo "system_usedDisk="$system_usedDisk

    #local elements
    elements=($system_totalSize $system_freeDisk $system_usedDisk)
    echo ${elements[*]}
}

#-----------------------------------------------------------------
#//检查备份还原分区/backup剩余空间是否满足备份需求
#see backup-auto/backupcommon.cpp
#返回值: 0表示/backup剩余容量不能够满足备份需求；1表示满足
checkBackupCapacity() { #(m_rootPath.toStdString().c_str(), retstatus))
    local origalParas
    local root_totalSize root_freeDisk root_usedDisk
    local backup_totalSize backup_freeDisk backup_usedDisk
    local system_totalSize system_freeDisk system_usedDisk
    ###which_line=`expr $which_line + 1`

    #从函数caculateSystemSize取返回值
    result=($(caculateSystemSize))
    system_totalSize=${result[0]}
    system_freeDisk=${result[1]}
    system_usedDisk=${result[2]}

    #global_system_usedDisk=$system_usedDisk
    global_system_usedDisk=$(caculateDirSize)

    #echo "--system_totalSize="$system_totalSize
    #echo "--system_freeDisk="$system_freeDisk
    #echo "--system_usedDisk="$system_usedDisk

    #--------------------------------------------------------
    #result=(`caculateDiskSize "$rootpath" "$rootpath"`)
    origalParas=($rootpath "/")
    arg1=$(echo ${origalParas[*]})

    result=($(caculateDiskSize $arg1))
    root_totalSize=${result[0]}
    root_freeDisk=${result[1]}
    root_usedDisk=${result[2]}
    #echo "--root_totalSize="$root_totalSize
    #echo "--root_freeDisk="$root_freeDisk
    #echo "--root_usedDisk="$root_usedDisk

    #--------------------------------------------------------
    #caculateDiskSize / /backup
    #origalParas=($rootpath "/backup")
    #origalParas=("/" "/backup") #/backup不会是/root/backup
    origalParas=("/" $m_mountPath) #/backup不会是/root/backup
    arg1=$(echo ${origalParas[*]})

    result=($(caculateDiskSize $arg1))
    backup_totalSize=${result[0]}
    backup_freeDisk=${result[1]}
    backup_usedDisk=${result[2]}

    #echo "--backup_totalSize="$backup_totalSize
    #echo "--backup_freeDisk="$backup_freeDisk
    #echo "--backup_usedDisk="$backup_usedDisk

    if [[ $root_totalSize = $backup_totalSize && $root_freeDisk = $backup_freeDisk && $root_usedDisk = $backup_usedDisk ]]; then #"/backup"是不是一个独立的盘
        echo "Cannot find the /backup disk or not be mounted!"
        exit 12
    fi

    echo "free size : $backup_freeDisk; sys_size : $global_system_usedDisk"
    echo "free size : $backup_freeDisk; sys_size : $global_system_usedDisk" >>$PLOGFILE
    if [ ${backup_freeDisk} -gt ${global_system_usedDisk} ]; then
        return 1
    else
        return 0
    fi
}

updateStateByComment() {
    tmpFile=${g_factory_backuplist_xml}".tmp"
    #echo "tmpFile: $tmpFile"
    is_first_line=1

    foundComment=0 #是否发现了要修改的comment

    #如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
    IFS_old=$IFS
    IFS=$'\n'
    while read line; do
        #去除了前后空格
        xxx=$(echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g")
        echo "xxx: $xxx"

		#用于检测脚本时间，针对同一次备份过程中执行update
        if [[ "$xxx" =~ "<Comment>" ]]; then
            if [ $xxx = "<Comment>${m_comment}</Comment>" ]; then
                foundComment=1 #当前comment是要修改的mycomment
            else
                foundComment=0 #当前comment不是要修改的mycomment
            fi
        fi

		if [[ "$xxx" =~ "<Size>" ]]; then
            if [[ $foundComment -eq 1 ]]; then
                line="        <Size>${newSize}</Size>"
            fi
        fi


        if [[ "$xxx" =~ "<State>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="        <State>${m_state}</State>"
            fi
        fi
		
		if [[ "$xxx" =~ "<SystemHash>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="        <SystemHash>${m_system_hash}</SystemHash>"
            fi
        fi
		
        if [[ "$xxx" =~ "<ovl>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <ovl>${m_ovl_hash}</ovl>"
            fi
        fi

		
		if [[ "$xxx" =~ "<home>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <home>${m_home_hash}</home>"
            fi
        fi
		
		if [[ "$xxx" =~ "<User>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <User>${m_username}</User>"
            fi
        fi

        if [ "$is_first_line" -eq 1 ]; then
            echo "$line" >$tmpFile
        else
            echo "$line" >>$tmpFile
        fi

        is_first_line=0

    done <"$g_factory_backuplist_xml"
    IFS=$IFS_old

    cp -f $tmpFile ${g_factory_backuplist_xml}
    rm -f $tmpFile
}

#参照backup-daemon/backupmanager.cpp, 写日志文件
writeLogFile() {
    echo $1 >>$LOGFILE
}

#参照backup-daemon/mountpoint.cpp
bFileExists() {
    local theFile theOldFile
    theOldFile=$1 #必须以"/"开始，但本身是个相对路径，因为没有加rootpath.

    if [ $rootpath = "/" ]; then
        theFile=$theOldFile
    else
        theFile=$theOldFile
        theFile="$rootpath""$theFile"
    fi

    if [ -e "$theFile" ]; then
        echo "$theOldFile" >>$EXCLUDEFILE
    fi
}

#参照backup-daemon/mountpoint.cpp
generateExcludeFile() {
    local backupOrRestore
    backupOrRestore=$1         #0: backup 1:restore

    #exclude的必须是相对目录，其实在efi启动时为/root/data
    #see backup-daemon/mountpoint.cpp, backup-daemon/data/backup-auto-efi
    #also kybackup: exclude.ui databackupdirs.ui dataincbackupdirs.ui
    #if [ ! -e "$restoreDir" ]; then
    #注意下面的>和>>-----------------------------------------------
    echo "/efi" >$EXCLUDEFILE 
    echo "/backup" >>$EXCLUDEFILE
    #echo "/boot/efi" >>$EXCLUDEFILE
    echo "/dev" >>$EXCLUDEFILE
    echo "/ghost" >>$EXCLUDEFILE #ghost镜像文件
    echo "/mnt" >>$EXCLUDEFILE
    echo "/proc" >>$EXCLUDEFILE
    echo "/run" >>$EXCLUDEFILE
    echo "/sys" >>$EXCLUDEFILE
    echo "/media" >>$EXCLUDEFILE
    echo "/tmp" >>$EXCLUDEFILE
    echo "*/lost+found" >>$EXCLUDEFILE
    echo "/var/lib/udisks2" >>$EXCLUDEFILE
    #echo "/data/home/*" >>$EXCLUDEFILE
    #echo "/data/root/*" >>$EXCLUDEFILE
    #if [ -e "${rootpath}/data/home" ]; then
    #	echo "/home" >>$EXCLUDEFILE
    #	echo "/root" >>$EXCLUDEFILE
    #fi
    echo "/cdrom" >>$EXCLUDEFILE
    echo "/swap_file" >>$EXCLUDEFILE
    echo "/var/lib/docker/overlay2" >>$EXCLUDEFILE
    echo "*/backup/snapshots" >>$EXCLUDEFILE
    echo "/var/log" >>$EXCLUDEFILE
    echo "/data/security-dir" >>$EXCLUDEFILE

    #bind挂载的目录不进行备份或还原
    if [ -z $fstab_path ]; then
      fstab_path=${rootpath}/etc/fstab

      if [ ! -e "$fstab_path" ]; then
          fstab_path=/etc/fstab-backup
          if [ ! -e "$fstab_path" ]; then
              echo "$fstab_path file not exist!"
              exit 16
          fi
      fi
    fi
    cat $fstab_path | awk '{if($4~/bind/) print $1}' |
    while read excludePath
    do
        echo "$excludePath" >>$EXCLUDEFILE
    done

    #bFileExists "/etc/.bootinfo"
    #bFileExists "/etc/fpb" 	#管控,暂时
    #echo "/etc/.bootinfo" >>$EXCLUDEFILE

    #数据分区是否使用由用户输入，最终放到/backup/snapshots/.excludeuser
    #因为GRUB没有界面，所以是不是先在其他模式下做一次备份，生成这个文件；然后GRUB就可以了。
    #echo "/data/*" >>$EXCLUDEFILE   #用户可以把数据放到该分区或者目录

    #是否覆盖备份还原工具自身，因为grub备份还原使用的工具是initrd.img里面的东西，故不存在时可以还原备份还原工具本身(例如工具被删除的场景)
    #if [ $backupOrRestore -eq 1 ]; then
    #  bFileExists "/usr/bin/backup-daemon"
    #  bFileExists "/usr/bin/kybackup"
    #  bFileExists "/usr/bin/backup-auto"
    #  bFileExists "/usr/bin/mount_fstab_efi"
    #  bFileExists "/usr/bin/backup-auto-efi"
    #  bFileExists "/usr/bin/rsync"
    #  bFileExists "/usr/share/rsync"
    #  bFileExists "/usr/share/initramfs-tools/hooks/kybackup-hooks"
    #  bFileExists "/usr/share/initramfs-tools/scripts/local-bottom/kybackup"
    #fi

    # 安全模块会将文件/usr/share/kysec-utils/data/readonly_list中的文件列表限制只读，无法修改、备份（包含扩展属性时）、删除等
    # 现在里面仅有/etc/uid_list，先暂时排除掉；等后续安全模块有其它保护方案后再进一步修改
    # 新：用安全保护程序/usr/bin/setstatus可以关闭保护，故不再排除此文件
    # echo "/etc/uid_list" >>$EXCLUDEFILE
    #if [ $backupOrRestore -eq 1 ]; then
    #    bFileExists "/usr/bin/backup-daemon"  	#备份还原
    #    bFileExists "/usr/bin/kybackup"		#备份还原
    #    bFileExists "/usr/bin/mount_fstab"  	#备份还原
    #    bFileExists "/usr/bin/backup-auto"  	#备份还原
    #    bFileExists "/usr/bin/mount_fstab_efi" 	#备份还原
    #    bFileExists "/usr/bin/backup-auto-efi" 	#备份还原
    #fi

    #是否使用由用户输入，最终放到/backup/snapshots/.excludeuser
    #if [ "$XGS" = true ]; then
    #    echo "/etc/passwd" >>$EXCLUDEFILE
    #    echo "/etc/group" >>$EXCLUDEFILE
    #    echo "/etc/shadow" >>$EXCLUDEFILE
    #    if [ -e "/etc/uid_list" ]; then
    #	echo "/etc/uid_list" >>$EXCLUDEFILE
    #    fi

    #    echo "/home/*" >>$EXCLUDEFILE
    #    echo "/opt/softmanager/log/log_cur.txt" >>$EXCLUDEFILE
    #    echo "/opt/softmanager/conf/audit/auditLogCur.txt" >>$EXCLUDEFILE
    #    echo "/opt/xgs/Audit/*" >>$EXCLUDEFILE
    #    echo "/opt/LinuxKpc/log/*" >>$EXCLUDEFILE
    #    echo "/var/log/*" >>$EXCLUDEFILE
    #    echo "/var/run/*" >>$EXCLUDEFILE
    #    echo "/root/*" >>$EXCLUDEFILE
    #    echo "/var/mail/*" >>$EXCLUDEFILE
    #    echo "/boot/efi/*" >>$EXCLUDEFILE #xgs出厂还原时会失败
    #fi
    #fi
}

backuping() {
    local src dst

    src=$1
    dst=$2

    #0:backup 1:restore
    generateExcludeFile 0
	echo "/" > ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_BACKUPFILE
	cp $EXCLUDEFILE ${m_mountPath}/snapshots/$m_uuid/$PERSONAL_EXCLUDEFILE

    #echo "Begin to backup efi directory..." >>$PLOGFILE
    #echo "Begin to backup efi directory..."
    # /boot/efi不再单独备份
    #if [ -d "${src}/boot/efi" ]; then
    #    mkdir -p ${dst}/boot
    #    rsync -av --ignore-missing-args ${src}/boot/efi ${dst}/boot >/dev/null 2>>$PLOGFILE
    #    if [ $? -ne 0 -a $? -ne 24 -a $? -ne 23 ]; then
    #        echo "backup update backuplist.xml failed for updateBackupAutoFinishedState!"
    #        echo "backup update backuplist.xml failed for updateBackupAutoFinishedState!" >>$PLOGFILE
    #        m_state="backup unfinished"
    #        updateStateByComment
    #        echo "System backuping failed, please reboot your system!"
    #        echo "System backuping failed, please reboot your system!" >>$PLOGFILE
    #        exit 14
    #    fi
    #fi

    echo "Begin to backup other directories..." >>$PLOGFILE
    echo "Begin to backup other directories..."
    #是否有数据分区
    if [ $hasDataPartition -eq 0 ]; then
        #exclude的必须是相对目录，其实在efi启动时为/root/data
        #echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst
        #rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst

        #不是目录，也不备份
        echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >/dev/null 2>>$PLOGFILE
        rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >/dev/null 2>>$PLOGFILE
    else
        #exclude的必须是相对目录，其实在efi启动时为/root/data
        #echo rsync -avAXH --ignore-missing-args --exclude data --exclude-from=$EXCLUDEFILE $src $dst
        #The question is that the 'data' directories can not be copied
        echo rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >/dev/null 2>>$PLOGFILE
        rsync -avAXH --ignore-missing-args --exclude-from $EXCLUDEFILE $src $dst >/dev/null 2>>$PLOGFILE
    fi

    if [ $? -eq 0 -o $? -eq 24 -o $? -eq 23 ]; then
        #updateStateByComment $m_comment 0
	sync
        m_state="backup finished"
        touch $dst/.exectl
	#caculateDirSize $dst

        updateStateByComment

    else
        #将状态从"backup unfinished"改成"backup failed"
        echo "backup update backuplist.xml failed for updateBackupAutoFinishedState!"
        echo "backup update backuplist.xml failed for updateBackupAutoFinishedState!" >>$PLOGFILE
        m_state="backup unfinished"
        updateStateByComment
        echo "System backuping failed, please reboot your system!"
        echo "System backuping failed, please reboot your system!" >>$PLOGFILE
        exit 14
    fi

    #写文件
    metainfo_file="${m_mountPath}/snapshots/$m_uuid/$METAINFO"
    #echo "metainfo_file="$metainfo_file
    #第1行清空写
    #这里写的不是xml文件，是一个文本文件，这时候的状态是0或者backup failed
    echo "COMMENT=$m_comment" >$metainfo_file
    echo "TIME=$m_time" >>$metainfo_file
    echo "UUID=$m_uuid" >>$metainfo_file
    echo "SIZE=$m_size" >>$metainfo_file
    echo "STATE=$m_state" >>$metainfo_file

    #写日志文件
    writeLogFile "${m_time},${m_uuid},0,grub备份,${newSize}" #grub时只有全盘备份，没有增量备份
    sync
}

CreateUuid() {
	local uuid=`cat /proc/sys/kernel/random/uuid|tr -d "\n"`
	while [ "$uuid" = $factory_uuid -o "$uuid" = $auto_uuid ]
    do
    	uuid=`cat /proc/sys/kernel/random/uuid|tr -d "\n"`
    done
    echo $uuid
}

findCommentByUuid() {

	local ret=1
	local local_uuid=$1
	local comment0
	local ret_comment

	#如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
	IFS_old=$IFS
	IFS=$'\n'
	while read line;
	do
	#去除了前后空格
		xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
		#echo "xxx: $xxx"

		if [[ "$xxx" =~ "<Comment>" ]]; then
        	comment0=`echo $xxx | awk -F "<Comment>" '{print $2}' |awk -F "</Comment>" '{print $1}' | tr -d "\n"`
        fi

        if [[ "$xxx" =~ "<Uuid>" ]]; then
        	if [ $xxx = "<Uuid>${local_uuid}</Uuid>" ]; then
            	ret=0
                ret_comment=$comment0
                break
            fi
        fi
    done < "$m_backuplistPath";
    IFS=$IFS_old

	echo $ret_comment
	return $ret
}

deleteItemByUUID() {
	local local_uuid=$1
	echo "需要删除的UUID = $local_uuid"

	tmpFile=${g_system_update_backuplist_xml}".tmp"
	cp -f ${g_system_update_backuplist_xml} $tmpFile
#        echo "tmpFile: $tmpFile"

	local foundUuid=0 #是否发现了要修改的comment
	local i=0
	local ii=0
	local iii=0
	local backupPointTmp=0

	#如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
	IFS_old=$IFS
	IFS=$'\n'
	while read line;
	do
		let i+=1
		#去除了前后空格
		xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
		#echo "xxx: $xxx"

		if [[ "$xxx" =~ "<BackupPoint>" ]]; then
			backupPointTmp=$i		#记录行号
		fi
		if [[ "$xxx" =~ "<Uuid>" ]]; then
			if [ $xxx = "<Uuid>$local_uuid</Uuid>" ]; then
				foundUuid=1 #当前comment是要修改的mycomment
                ii=$backupPointTmp
			else
				foundUuid=0 #当前comment不是要修改的mycomment
			fi
		fi
		if [[ "$xxx" =~ "</BackupPoint>" ]]; then
			if [ $foundUuid -eq 1 ]; then
				iii=$i
				break
            fi
        fi
	done < "$tmpFile";
	IFS=$IFS_old

#        echo "ii: $ii, iii: $iii"

	if [ $iii -ne 0 ]; then
		sed -i "${ii},${iii}d" $tmpFile
        cp -f $tmpFile ${g_system_update_backuplist_xml}
    fi
    rm -f $tmpFile
}

deleteItemByComment() {
	local local_comment=$1
	echo "arg local_comment = $local_comment"

	tmpFile=${m_backuplistPath}".tmp"
	cp -f ${m_backuplistPath} $tmpFile
#        echo "tmpFile: $tmpFile"

	local foundComment=0 #是否发现了要修改的comment
	local i=0
	local ii=0
	local iii=0
	local backupPointTmp=0

	#如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
	IFS_old=$IFS
	IFS=$'\n'
	while read line;
	do
		let i+=1
		#去除了前后空格
		xxx=$( echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g" )
		#echo "xxx: $xxx"

		if [[ "$xxx" =~ "<BackupPoint>" ]]; then
			backupPointTmp=$i		#记录行号
		fi
		if [[ "$xxx" =~ "<Comment>" ]]; then
			if [ $xxx = "<Comment>$local_comment</Comment>" ]; then
				foundComment=1 #当前comment是要修改的mycomment
					ii=$backupPointTmp
					#echo "delete foundComment = 1"
			else
				foundComment=0 #当前comment不是要修改的mycomment
			fi
		fi
		if [[ "$xxx" =~ "</BackupPoint>" ]]; then
			if [ $foundComment -eq 1 ]; then
				iii=$i
				break
            fi
        fi
	done < "$tmpFile";
	IFS=$IFS_old

#        echo "ii: $ii, iii: $iii"

	if [ $iii -ne 0 ]; then
		sed -i "${ii},${iii}d" $tmpFile
        cp -f $tmpFile ${m_backuplistPath}
    fi
    rm -f $tmpFile
}

DeleteFactoryBackup() {
	if [ -e "/backup/snapshots/{${factory_uuid}}" ]; then
		rm /backup/snapshots/{${factory_uuid}} -rf
	fi

	local comment=$(findCommentByUuid "{${factory_uuid}}")
#       echo "DeleteFactoryBackup comment is $comment"
	if [ $? -eq 0 ]; then
		deleteItemByComment "$comment"
	fi
}

#see backup-auto/autobackup.cpp
backupAuto() { #备份
    if [ $m_isFactory = true ]; then
		DeleteFactoryBackup
    fi

    local xxx
    checkBackupCapacity
    ret=$?
    if [ "$ret" -eq 0 ]; then
        echo "The backup disk space is not enough"
        exit 4
    fi

    #global_system_usedDisk
    #创建一个uuid
    if [ $m_isFactory = false ]; then
		m_uuid=$(CreateUuid)
    else
		m_uuid="$factory_uuid"
	fi
    m_uuid="{"${m_uuid}"}"
#    echo "BYbobbi: m_uuid is $m_uuid"
    m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
    m_comment=$m_time #这个是全局变量
    dst="${m_mountPath}/snapshots/$m_uuid/data"
    #echo "dst: $dst"
    mkdir -p $dst
    m_size=$global_system_usedDisk

    #m_size=188248
    newSize1=$(echo "scale=2;$m_size / $GB" | bc)
    newSize2=$(echo "scale=2;$m_size / $MB" | bc)
    newSize3=$(echo "scale=2;$m_size / $KB" | bc)

    if [ $(echo "$newSize1 > 1.0" | bc) = 1 ]; then
        newSize=$newSize1"GB"
    elif [ $(echo "$newSize2 > 1.0" | bc) = 1 ]; then
        newSize=$newSize2"MB"
    else
        newSize=$newSize3"KB"
    fi

    state="backup unfinished"

    #写入文件m_backuplistPath=$m_mountPath"/snapshots/backuplist1.xml"
    #bool AutoBackup::backupAuto()251 if (!m_parse->addItem(m_comment, time, m_uuid, newsize, "backup unfinished")) {
    #
    tmpFile=${m_backuplistPath}".tmp"
    #echo "tmpFile: $tmpFile"
    new_content=""
    is_first_line=1

    hasHead=false #有头吗"<backupList>"

    #如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
    IFS_old=$IFS
    IFS=$'\n'

    while read line; do
        #去除了前后空格
        xxx=$(echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g")
        #echo "xxx: $xxx"

        if [[ "$xxx" =~ "<backupList>" ]]; then
            hasHead=true
        fi

        if [[ "$xxx" =~ "<backupList/>" ]]; then
            xxx="</backupList>" #与图形界面一致
            line="</backupList>"
        fi

        #插入新的记录
        if [ $xxx = "</backupList>" ]; then
            if [ "$hasHead" = false ]; then
                echo "<backupList>" >>$tmpFile
                hasHead=true
            fi

            echo "    <BackupPoint>" >>$tmpFile
            echo "        <Comment>$m_comment</Comment>" >>$tmpFile
            echo "        <Time>$m_time</Time>" >>$tmpFile
            echo "        <Uuid>$m_uuid</Uuid>" >>$tmpFile
            echo "        <Size>$newSize</Size>" >>$tmpFile
            echo "        <State>$state</State>" >>$tmpFile
            echo "        <Type>0</Type>" >>$tmpFile
            echo "    </BackupPoint>" >>$tmpFile
        fi

        if [ "$is_first_line" -eq 1 ]; then
            echo "$line" >$tmpFile
        else
            echo "$line" >>$tmpFile
        fi

        is_first_line=0

    done <"$m_backuplistPath"
    IFS=$IFS_old$

    cp -f $tmpFile ${m_backuplistPath}
    rm -f $tmpFile

    #写文件
    metainfo_file="${m_mountPath}/snapshots/$m_uuid/$METAINFO"
    #echo "metainfo_file="$metainfo_file
    #第1行清空写
    #这里写的不是xml文件，是一个文本文件，这时候的状态是backup unfinished
    echo "COMMENT=$m_comment" >$metainfo_file
    echo "TIME=$m_time" >>$metainfo_file
    echo "UUID=$m_uuid" >>$metainfo_file
    echo "SIZE=$m_size" >>$metainfo_file
    echo "STATE=$state" >>$metainfo_file
    echo "TYPE=0" >>$metainfo_file

    backuping ${rootpath}/ $dst
}


prepare()
{
	#出厂备份特定UUID
    m_uuid="$factory_uuid"
	#获取当前时间
    m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
    m_comment=$m_time #这个是全局变量

    #创建出厂还原repo仓库
	#ostree --repo=${g_repo_factory} init --mode=archive-z2
	$(chroot "${rootmnt}" /bin/bash -c "ostree --repo=${g_repo_factory} init --mode=bare ")
	#当前备份状态为未完成
    state="backup unfinished"
	
	#写入文件m_backuplistPath=$m_mountPath"/snapshots/backuplist1.xml"
	echo "出厂备份点XML元数据文件：${g_factory_backuplist_xml}" >>$PLOGFILE
    tmpFile=${g_factory_backuplist_xml}".tmp"
    echo "tmpFile: $tmpFile" >>$PLOGFILE
    

    #如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
    IFS_old=$IFS
    IFS=$'\n'

	echo "<backupList>" >>$tmpFile
	echo "    <BackupPoint>" >>$tmpFile
    echo "        <Comment>$m_comment</Comment>" >>$tmpFile
    echo "        <Time>$m_time</Time>" >>$tmpFile
    echo "        <Uuid>$m_uuid</Uuid>" >>$tmpFile
    echo "        <Size>0</Size>" >>$tmpFile
    echo "        <State>$state</State>" >>$tmpFile
    echo "        <Type>0</Type>" >>$tmpFile
    echo "        <SystemHash></SystemHash>" >>$tmpFile
    echo "        <SystemCommitHashMap>" >>$tmpFile
    echo "            <home></home>" >>$tmpFile
    echo "            <etc></etc>" >>$tmpFile
    echo "            <usr></usr>" >>$tmpFile
    echo "            <var></var>" >>$tmpFile
    echo "        </SystemCommitHashMap>" >>$tmpFile
    echo "    </BackupPoint>" >>$tmpFile
	echo "</backupList>" >>$tmpFile
	
    IFS=$IFS_old$

    cp -f $tmpFile ${g_factory_backuplist_xml}
    rm -f $tmpFile

}

#计算当前系统哈希，并更新xml
recordSystemHash()
{
	#m_system_hash=`ostree admin status |grep '*' | awk -F ' ' '{print $3}'`
	m_system_hash=$(chroot "${rootmnt}" /bin/bash -c "ostree admin status --skip-signatures | grep 'kylin' |grep -v 'refspec' |head -1 | awk -F ' ' '{print \$2}'")
	updateXmlByComment ${g_factory_backuplist_xml}
}

cpOvl()
{
	mkdir -p ${rootpath}${m_mountPath}/temp
	#目前grub阶段直接cp，会导致大量报错，因此使用rsync将数据导出
	#cp -aL -P -rf ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/etc-ovl  ${rootpath}${m_mountPath}/temp/
	#cp -aL -P -rf ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/usr-ovl  ${rootpath}${m_mountPath}/temp/
	#cp -aL -P -rf ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/var-ovl  ${rootpath}${m_mountPath}/temp/
	rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/etc-ovl ${rootpath}${m_mountPath}/temp/etc-ovl
	rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/usr-ovl ${rootpath}${m_mountPath}/temp/usr-ovl
	rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/var-ovl ${rootpath}${m_mountPath}/temp/var-ovl
}

cleanSBCTypeFiles()
{
	find ${rootpath}${m_mountPath}/temp/ -type s -exec rm -f {} \;
	find ${rootpath}${m_mountPath}/temp/ -type b -exec rm -f {} \;
	find ${rootpath}${m_mountPath}/temp/ -type c -exec rm -f {} \;
}

commitToRepo()
{
	#m_etc_hash=$(chroot "${rootmnt}" /bin/bash -c "ostree --repo=${g_repo_factory} commit -b branch --tree=dir=${rootpath}${m_mountPath}/temp/etc-ovl -s \"etc\" ")
	#m_usr_hash=$(chroot "${rootmnt}" /bin/bash -c "ostree --repo=${g_repo_factory} commit -b branch --tree=dir=${rootpath}${m_mountPath}/temp/usr-ovl -s \"usr\" ")
	#m_var_hash=$(chroot "${rootmnt}" /bin/bash -c "ostree --repo=${g_repo_factory} commit -b branch --tree=dir=${rootpath}${m_mountPath}/temp/var-ovl -s \"var\" ")
	m_state="backup finished"
	updateXmlByComment ${g_factory_backuplist_xml}
}

cleanTmpDir()
{
	rm -fr ${rootpath}${m_mountPath}/temp/*
	rm -f $WHITELISTFILE
}

updateXmlByComment() {
    tmpFile=$1".tmp"
    #echo "tmpFile: $tmpFile"
    is_first_line=1

    foundComment=0 #是否发现了要修改的comment

    #如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
    IFS_old=$IFS
    IFS=$'\n'
    while read line; do
        #去除了前后空格
        xxx=$(echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g")
        echo "xxx: $xxx"

		#用于检测脚本时间，针对同一次备份过程中执行update
        if [[ "$xxx" =~ "<Comment>" ]]; then
            if [ $xxx = "<Comment>${m_comment}</Comment>" ]; then
                foundComment=1 #当前comment是要修改的mycomment
            else
                foundComment=0 #当前comment不是要修改的mycomment
            fi
        fi

		if [[ "$xxx" =~ "<Size>" ]]; then
            if [[ $foundComment -eq 1 ]]; then
                line="        <Size>${newSize}</Size>"
            fi
        fi


        if [[ "$xxx" =~ "<State>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="        <State>${m_state}</State>"
            fi
        fi
		
		if [[ "$xxx" =~ "<SystemHash>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="        <SystemHash>${m_system_hash}</SystemHash>"
            fi
        fi

        if [[ "$xxx" =~ "<ovl>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <ovl>${m_ovl_hash}</ovl>"
            fi
        fi
		
		
		if [[ "$xxx" =~ "<home>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <home>${m_home_hash}</home>"
            fi
        fi
		
		if [[ "$xxx" =~ "<User>" ]]; then
            if [ $foundComment -eq 1 ]; then
                line="            <User>${m_username}</User>"
            fi
        fi

        if [ "$is_first_line" -eq 1 ]; then
            echo "$line" >$tmpFile
        else
            echo "$line" >>$tmpFile
        fi

        is_first_line=0

    done <"$1"
    IFS=$IFS_old

    cp -f $tmpFile $1
    rm -f $tmpFile
}


checkEnvForSystemRestore()
{
	if [ ! -d "${rootpath}${g_repo_system_update}" ] && [ ! -d "${rootpath}${g_repo_system}" ]; then
		echo "不存在 ${rootpath}${g_repo_system_update}" >>$PLOGFILE
		echo "不存在 ${rootpath}${g_repo_system}" >>$PLOGFILE
		exit 32
	fi
	#系统还原涉及到两个xml表
	getLastUsefulBackupPointUuid
	#根据返回结果获取UUID
	m_restore_uuid=$lastUsefulBackupPointUuid
	
	echo "要还原的备份点所在repo仓库：m_restore_repo:${m_restore_repo}" >>$PLOGFILE
	echo "要还原的备份点UUID：m_restore_uuid:${m_restore_uuid}" >>$PLOGFILE
	echo "要还原的系统哈希：m_system_hash:${m_system_hash}" >>$PLOGFILE
	echo "要还原的备份点home哈希：m_home_hash:${m_home_hash}" >>$PLOGFILE
    echo "要还原的备份点ovl哈希：m_ovl_hash:${m_ovl_hash}" >>$PLOGFILE
	echo "要还原的备份点用户名字：m_username:${m_username}" >>$PLOGFILE
    echo "要还原的备份点分支名字：m_branchname:${m_branchname}" >>$PLOGFILE
}

checkEnvForFactoryRestore()
{
	if [ ! -d ${rootpath}${g_repo_factory} ]; then
		echo  "不存在${rootpath}${g_repo_factory}" >>$PLOGFILE
		exit 30
	fi
	
	if [ ! -e ${g_factory_backuplist_xml} ]; then
		echo  "不存在${g_factory_backuplist_xml}" >>$PLOGFILE
		exit 31
	fi
	
	#出厂备份只涉及到一个xml表
	getLastUsefulBackupPoint ${g_factory_backuplist_xml}
	#根据返回结果获取UUID
	m_restore_repo=${g_repo_factory}
	m_restore_uuid=$ret_lastUsefulUuid
	m_system_hash=$ret_SystemHash
	m_home_hash=$ret_home
    m_ovl_hash=$ret_ovl
	m_username=$ret_username
	echo "要还原的备份点所在repo仓库：m_restore_repo:${m_restore_repo}" >>$PLOGFILE
	echo "要还原的备份点UUID：m_restore_uuid:${m_restore_uuid}" >>$PLOGFILE
	echo "要还原的系统哈希：m_system_hash:${m_system_hash}" >>$PLOGFILE
	echo "要还原的备份点home哈希：m_home_hash:${m_home_hash}" >>$PLOGFILE
    echo "要还原的备份点ovl哈希：m_ovl_hash:${m_ovl_hash}" >>$PLOGFILE
	echo "要还原的备份点用户名字：m_username:${m_username}" >>$PLOGFILE
}

DeleteSystemUpdateBackupPoint() {
    # 检查仓库或分支是否存在
    if [ ! -d "${rootpath}${g_repo_system_update}" ] || ! chroot ${rootmnt} /bin/bash -c "ostree refs --repo=${g_repo_system_update}"; then
		echo "不存在或无效 ${rootpath}${g_repo_system_update}" >>$PLOGFILE
		exit 32
	fi

    # 删除分支
    echo "删除分支 $m_branchname..."
    chroot ${rootmnt} /bin/bash -c "ostree refs --repo=$m_restore_repo --delete $m_branchname"

    # 删除提交
    echo "删除home提交 $m_home_hash..."
    chroot ${rootmnt} /bin/bash -c "ostree prune --repo==$m_restore_repo --delete-commit=$m_home_hash"
    echo "删除etc提交 $m_etc_hash..."
    chroot ${rootmnt} /bin/bash -c "ostree prune --repo==$m_restore_repo --delete-commit=$m_etc_hash"
    echo "删除usr提交 $m_usr_hash..."
    chroot ${rootmnt} /bin/bash -c "ostree prune --repo==$m_restore_repo --delete-commit=$m_usr_hash"
    echo "删除var提交 $m_var_hash..."
    chroot ${rootmnt} /bin/bash -c "ostree prune --repo==$m_restore_repo --delete-commit=$m_var_hash"

    echo "删除系统升级备份点操作完成"
}

deleteNeedRollBackFile() {
    # 删除NEEDROOLBACKFILE标志文件
    echo "删除NEEDROOLBACKFILE $NEEDROOLBACKFILE..."  >>$PLOGFILE
    if [ -f "${rootpath}$NEEDROOLBACKFILE" ]; then
            echo "NEEDROOLBACKFILE存在 ${rootpath}$NEEDROOLBACKFILE"  >>$PLOGFILE
            chroot ${rootmnt} /bin/bash -c "rm $NEEDROOLBACKFILE"
    else
            echo "NEEDROOLBACKFILE不存在 ${rootpath}$NEEDROOLBACKFILE"  >>$PLOGFILE
    fi
}

getLastUsefulBackupPoint() {
    local xmlFile=$1
    echo "xmlFile=${xmlFile}"

    local currentUuid=""
    local currentState=false
    local currentType=true
    local currentComment=""
    local backupPositionMode=false
    local backupPrefixDestPath=""
    local Time=""
	
	local SystemHash=""
	local home=""
    local ovl=""

	local username=""
    
	#下面的变量作为返回值存在
    ret_lastUsefulUuid=""
    ret_time=""
    ret_isPosition=false
    ret_prefixDestPath=""
    ret_lastbackupname=""
	
	ret_SystemHash=""
	ret_home=""
    ret_ovl=""

	ret_username=""

    IFS_old=$IFS
    IFS=$'\n'
    while read line; do
        #去除了前后空格和制表符
        line=$(echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g")
       
        if [[ "$line" =~ "<Comment>" ]]; then
            currentComment=${line#<Comment>}
            currentComment=${currentComment%</Comment>}
        fi

        if [[ "$line" =~ "<Time>" ]]; then
            Time=${line#<Time>}
            Time=${Time%</Time>}
        fi

        if [[ "$line" =~ "<Uuid>" ]]; then
            echo "uuid=${line} , m_default_uuid = ${m_default_uuid}" >>$PLOGFILE
            currentUuid=${line#<Uuid>}
            currentUuid=${currentUuid%</Uuid>}
            currentState=false
            currentType=true
	        backupPositionMode=false
	        backupPrefixDestPath=""
        fi

        if [[ "$line" =~ "<State>backup finished</State>" ]]; then
            currentState=true
        fi

        if [[ "$line" =~ "<Type>2</Type>" ]]; then
            currentType=false
        fi

        if [[ "$line" =~ "<Type>3</Type>" ]]; then
            currentType=false
        fi

        if [[ "$line" =~ "<Position>3</Position>" ]]; then
            backupPositionMode=true
        fi

        if [[ "$line" =~ "<PrefixDestPath>" ]]; then
            backupPrefixDestPath=${line#<PrefixDestPath>}
            backupPrefixDestPath=${backupPrefixDestPath%</PrefixDestPath>}
            # if [[ x"$backupPrefixDestPath" = x"" || "$backupPrefixDestPath" = "/" || $backupPrefixDestPath =~ ^/data || $backupPrefixDestPath =~ ^/autobackup ]]; then
            if [[ ! $backupPrefixDestPath =~ ^/media/ ]]; then
                backupPositionMode=true
            else
                currentType=false
            fi
        fi
		
		#获取ostree提交哈希
		if [[ "$line" =~ "<SystemHash>" ]]; then
            SystemHash=${line#<SystemHash>}
            SystemHash=${SystemHash%</SystemHash>}
        fi
		if [[ "$line" =~ "<home>" ]]; then
            home=${line#<home>}
            home=${home%</home>}
        fi
        if [[ "$line" =~ "<ovl>" ]]; then
            ovl=${line#<ovl>}
            ovl=${ovl%</ovl>}
        fi
		if [[ "$line" =~ "<User>" ]]; then
            username=${line#<User>}
            username=${username%</User>}
        fi
        if [[ "$line" =~ "<BranchName>" ]]; then
            branchname=${line#<BranchName>}
            branchname=${branchname%</BranchName>}
        fi
		

        if [[ "$line" =~ "</BackupPoint>" ]]; then
            if [ "$currentState" = "true" -a "$currentType" = "true" ]; then #"/backup"是不是一个独立的盘
				echo "存在合适的备份点">>$PLOGFILE
                ret_lastUsefulUuid=$currentUuid
		        ret_isPosition=$backupPositionMode
		        ret_prefixDestPath=$backupPrefixDestPath
                ret_lastbackupname=$currentComment
                ret_time=$Time
				ret_SystemHash=$SystemHash
				ret_home=$home
                ret_ovl=$ovl
				ret_username=$username
                ret_branchname=$branchname
				
				echo "ret_SystemHash=${SystemHash}">>$PLOGFILE
            fi
        fi
    done <"$xmlFile"
    IFS=$IFS_old


    if [ -z "${ret_lastUsefulUuid}" ]; then
        echo "${xmlFile} no usable uuid" 
        echo "${xmlFile} no usable uuid" >> $PLOGFILE
    else
        echo "Found uuid in ${xmlFile}  ：${ret_lastUsefulUuid}" >>$PLOGFILE
        echo "Found uuid in ${xmlFile}  ：${ret_lastUsefulUuid}"
    fi
}

#返回值：
getLastUsefulBackupPointUuid() {
    local xxx=""
    local currentUuid=""
    local currentState=false
    local currentType=true
    lastUsefulBackupPointUuid=""
    foundComment=0 #是否发现了要修改的comment
    local currentComment=""
    lastbackupname=""
    local backupPositionMode=false
    local backupPrefixDestPath=""

    local Time=""
    local backupTime=""
	
	
	local SystemHash=""
	local home=""
    local ovl=""
	local username=""

    #如果不定义IFS，则echo $line会去掉前后空格，导致写到文件中去时没有格式
    IFS_old=$IFS
    IFS=$'\n'
    while read line; do
        #去除了前后空格
        xxx=$(echo "$line" | sed "s/^[ \t]*//g" | sed "s/[ \t]*$//g")
        #echo "xxx: $xxx"
       
        if [[ "$xxx" =~ "<Comment>" ]]; then
            currentComment=$xxx
        fi

        if [[ "$xxx" =~ "<Time>" ]]; then
            Time=${xxx#<Time>}
            Time=${Time%</Time>}
        fi

        if [[ "$xxx" =~ "<Uuid>" ]]; then
            echo "uuid=${xxx} , m_default_uuid = ${m_default_uuid}" >>$PLOGFILE
            currentUuid=${xxx}
            currentState=false
            currentType=true
	        backupPositionMode=false
	        backupPrefixDestPath=""
        fi

        if [[ "$xxx" =~ "<State>backup finished</State>" ]]; then
            currentState=true
        fi

        if [[ "$xxx" =~ "<Type>2</Type>" ]]; then
            currentType=false
        fi

        if [[ "$xxx" =~ "<Type>3</Type>" ]]; then
            currentType=false
        fi

	if [[ "$xxx" =~ "<Position>3</Position>" ]]; then
        #    currentType=false
	    backupPositionMode=true
    fi
	
	#获取ostree提交哈希
	if [[ "$line" =~ "<SystemHash>" ]]; then
		SystemHash=${line#<SystemHash>}
		SystemHash=${SystemHash%</SystemHash>}
	fi
	if [[ "$line" =~ "<home>" ]]; then
		home=${line#<home>}
		home=${home%</home>}
	fi
    if [[ "$line" =~ "<ovl>" ]]; then
		ovl=${line#<ovl>}
		ovl=${ovl%</ovl>}
	fi
	
	if [[ "$line" =~ "<User>" ]]; then
		username=${line#<User>}
		username=${username%</User>}
	fi

	if [[ "$xxx" =~ "<PrefixDestPath>" ]]; then
		backupPrefixDestPath=${xxx#<PrefixDestPath>}
		backupPrefixDestPath=${backupPrefixDestPath%</PrefixDestPath>}
		# if [[ x"$backupPrefixDestPath" = x"" || "$backupPrefixDestPath" = "/" || $backupPrefixDestPath =~ ^/data || $backupPrefixDestPath =~ ^/autobackup ]]; then
        if [[ ! $backupPrefixDestPath =~ ^/media/ ]]; then
			backupPositionMode=true
		else
			currentType=false
		fi
	fi

	if [[ "$xxx" =~ "</BackupPoint>" ]]; then
		if [ "$currentState" = "true" -a "$currentType" = "true" ]; then #"/backup"是不是一个独立的盘
			lastUsefulBackupPointUuid=$currentUuid
			m_Position=$backupPositionMode
			m_PrefixDestPath=$backupPrefixDestPath
			lastbackupname=$currentComment
			backupTime=${Time}
			if [[ -n "${m_default_uuid}" && "${currentUuid}" =~ "${m_default_uuid}" ]]; then
				echo "找到了指定的备份点${currentUuid}" >>$PLOGFILE
				break
			elif [ -n "${m_default_uuid}" ]; then
				echo "${currentUuid}不是指定的备份点${m_default_uuid}，继续下一个" >>$PLOGFILE
				lastUsefulBackupPointUuid=""
				m_Position=false
				m_PrefixDestPath=""
				lastbackupname=""
				backupTime=""
			fi
		fi
	fi
    done <"$g_system_backuplist_xml"
    IFS=$IFS_old

    getLastUsefulBackupPoint ${g_system_update_backuplist_xml}

    if [[ -z "$lastUsefulBackupPointUuid" && -z "${ret_lastUsefulUuid}" ]]; then
        echo "can't find a useful backup for restoring"
        exit 6
    elif [[ -n "$lastUsefulBackupPointUuid" && -n "${ret_lastUsefulUuid}" ]]; then
        if [[ "${backupTime}" < "${ret_time}" ]]; then
            lastUsefulBackupPointUuid=${ret_lastUsefulUuid}
            lastbackupname=${ret_lastbackupname}
            m_Position=${ret_isPosition}
            m_PrefixDestPath=${ret_prefixDestPath}
			
			m_restore_repo=${g_repo_system_update}
			m_system_hash=${ret_SystemHash}
			m_home_hash=${ret_home}
            m_ovl_hash=${ret_ovl}
			m_username=${ret_username}
            m_branchname=${ret_branchname}

            #此时的还原点是系统升级还原点
            m_isSystemUpdate=true
			
        else
            lastUsefulBackupPointUuid=$(echo $lastUsefulBackupPointUuid | sed 's:<Uuid>::' | tr -d "\n")
            lastUsefulBackupPointUuid=$(echo $lastUsefulBackupPointUuid | sed 's:</Uuid>.*::' | tr -d "\n")
            lastbackupname=$(echo $lastbackupname | sed 's:<Comment>::' | tr -d "\n")
            lastbackupname=$(echo $lastbackupname | sed 's:</Comment>.*::' | tr -d "\n")
            SystemHash=$(echo $SystemHash | sed 's:<SystemHash>::' | tr -d "\n")
            SystemHash=$(echo $SystemHash | sed 's:</SystemHash>.*::' | tr -d "\n")
            home=$(echo $home | sed 's:<home>::' | tr -d "\n")
            home=$(echo $home | sed 's:</home>.*::' | tr -d "\n")
            ovl=$(echo $ovl | sed 's:<ovl>::' | tr -d "\n")
            ovl=$(echo $ovl | sed 's:</ovl>.*::' | tr -d "\n")
			username=$(echo $username | sed 's:<User>::' | tr -d "\n")
			username=$(echo $username | sed 's:</User>.*::' | tr -d "\n")
			m_restore_repo=${g_repo_system}
			m_system_hash=$SystemHash
			m_home_hash=$home
            m_ovl_hash=$ovl
			m_username=$username

        fi
    elif [[ -n "${ret_lastUsefulUuid}" ]]; then
        lastUsefulBackupPointUuid=${ret_lastUsefulUuid}
        lastbackupname=${ret_lastbackupname}
        m_Position=${ret_isPosition}
        m_PrefixDestPath=${ret_prefixDestPath}
		
		m_restore_repo=${g_repo_system_update}
		m_system_hash=${ret_SystemHash}
		m_home_hash=${ret_home}
        m_ovl_hash=${ret_ovl}
		m_username=${ret_username}
        m_branchname=${ret_branchname}

        #此时的还原点是系统升级还原点
        m_isSystemUpdate=true
		
    else
        lastUsefulBackupPointUuid=$(echo $lastUsefulBackupPointUuid | sed 's:<Uuid>::' | tr -d "\n")
        lastUsefulBackupPointUuid=$(echo $lastUsefulBackupPointUuid | sed 's:</Uuid>.*::' | tr -d "\n")
        lastbackupname=$(echo $lastbackupname | sed 's:<Comment>::' | tr -d "\n")
        lastbackupname=$(echo $lastbackupname | sed 's:</Comment>.*::' | tr -d "\n")
		SystemHash=$(echo $SystemHash | sed 's:<SystemHash>::' | tr -d "\n")
		SystemHash=$(echo $SystemHash | sed 's:</SystemHash>.*::' | tr -d "\n")
		home=$(echo $home | sed 's:<home>::' | tr -d "\n")
		home=$(echo $home | sed 's:</home>.*::' | tr -d "\n")
		ovl=$(echo $ovl | sed 's:<ovl>::' | tr -d "\n")
		ovl=$(echo $ovl | sed 's:</ovl>.*::' | tr -d "\n")
		username=$(echo $username | sed 's:<User>::' | tr -d "\n")
		username=$(echo $username | sed 's:</User>.*::' | tr -d "\n")
		m_restore_repo=${g_repo_system}
		m_system_hash=$SystemHash
		m_home_hash=$home
        m_ovl_hash=$ovl
		m_username=$username
    fi

    echo "UUID to be restored：${lastUsefulBackupPointUuid}" >>$PLOGFILE
    echo "UUID to be restored：${lastUsefulBackupPointUuid}"
}

checkoutFromRepo()
{
	mkdir -p ${rootpath}${m_mountPath}/temp
	chroot ${rootmnt} /bin/bash -c "ostree  checkout  --repo=$m_restore_repo $m_home_hash ${m_mountPath}/temp/home"
    chroot ${rootmnt} /bin/bash -c "ostree  checkout  --repo=$m_restore_repo $m_ovl_hash ${m_mountPath}/temp/ovl"
	echo "checkoutFromRepo到${m_mountPath}/temp/的数据内容："
	ls -l ${rootpath}${m_mountPath}/temp  >>$PLOGFILE
}

checkoutFromFactoryRepo()
{
        mkdir -p ${rootpath}${m_mountPath}/temp
        echo "仓库路径：${rootpath}$m_restore_repo" >> $PLOGFILE
        echo "home哈希：$m_home_hash" >> $PLOGFILE
        chroot ${rootmnt} /bin/bash -c "ostree  checkout  --repo=$m_restore_repo $m_home_hash ${m_mountPath}/temp/home"  >>$PLOGFILE
        #chroot ${rootmnt} /bin/bash -c "ostree  checkout  --repo=$m_restore_repo $m_ovl_hash ${m_mountPath}/temp/ovl"
        echo "checkoutFromFactoryRepo到${rootpath}${m_mountPath}/temp/的数据内容："  >>$PLOGFILE
        ls -al ${rootpath}${m_mountPath}/temp  >>$PLOGFILE
}

generateWhiteList() {
    touch $WHITELISTFILE
    if [ $? -ne 0 ]; then
        echo "Could not create .whitelist file"
        exit 23
    fi

        # 用户数据白名单，添加排除路径，防止用户数据被还原（被删掉或者被备份点中的旧数据覆盖）
        #注意下面的>和>>-----------------------------------------------
        # (1)排除指纹数据，用户密码、角色、权限、生物识别等信息
        echo "lib/biometric-auth" >$WHITELISTFILE
        echo "passwd" >>$WHITELISTFILE
        echo "shadow" >>$WHITELISTFILE
        echo "group" >>$WHITELISTFILE
        echo "gshadow" >>$WHITELISTFILE
        echo "sudoers" >>$WHITELISTFILE
        # (2)云图片作为桌面背景的路径属于用户数据
        echo "lib/AccountsService" >>$WHITELISTFILE
        # (3)保留域用户数据
        echo "sssd" >>$WHITELISTFILE
        echo "lib/sss" >>$WHITELISTFILE
        echo "share/sssd" >>$WHITELISTFILE
        echo "ipa" >>$WHITELISTFILE
        echo "krb5.keytab" >>$WHITELISTFILE
        echo "krb5.conf" >>$WHITELISTFILE
        echo "lib/ipa-client" >>$WHITELISTFILE
        echo "nsswitch.conf" >>$WHITELISTFILE
        echo "pam.d" >>$WHITELISTFILE
        echo "hosts" >>$WHITELISTFILE
        echo "hostname" >>$WHITELISTFILE
        echo "hedron" >>$WHITELISTFILE
        echo "kcm" >>$WHITELISTFILE
        echo "hedron/hedronagent" >>$WHITELISTFILE
        echo ".kyinfo" >>$WHITELISTFILE
        echo "LICENSE" >>$WHITELISTFILE
        echo "ssl/certs" >>$WHITELISTFILE
        echo "share/ca-certificates" >>$WHITELISTFILE
        echo "NetworkManager" >>$WHITELISTFILE
        echo "lib/pam" >>$WHITELISTFILE
        echo "kim" >>$WHITELISTFILE
        echo "lib/kim" >>$WHITELISTFILE
        echo "systemd/system/multi-user.target.wants/kimbackend.service" >>$WHITELISTFILE
        echo "lib/polkit-1/localauthority/40-domain.d" >>$WHITELISTFILE
        echo "lib/libsudo-kim.so" >>$WHITELISTFILE
        #（4）保留激活状态
        echo "LICENSE" >>$WHITELISTFILE
        echo ".kyinfo" >>$WHITELISTFILE
        echo ".kyactivation" >>$WHITELISTFILE
        echo ".kyhwid" >>$WHITELISTFILE
        echo ".product" >>$WHITELISTFILE
        echo "share/plymouth" >>$WHITELISTFILE
}

rsyncFromTemp()
{
    generateWhiteList

    echo "Rsync传输ovl目录：">>$PLOGFILE
    echo "rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}${m_mountPath}/temp/ovl/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/" >>$PLOGFILE
    rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}${m_mountPath}/temp/ovl/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/ >>$PLOGFILE 2>&1
    # echo "rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude-from=$WHITELISTFILE ${rootpath}${m_mountPath}/temp/ovl/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/" >>$PLOGFILE
    # rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude-from=$WHITELISTFILE ${rootpath}${m_mountPath}/temp/ovl/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/ >>$PLOGFILE 2>&1

    #echo "Rsync传输etc目录：">>$PLOGFILE
    #rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude-from=$WHITELISTFILE ${rootpath}${m_mountPath}/temp/etc/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/etc-ovl/ >>$PLOGFILE 2>&1
    #echo "Rsync传输usr目录：">>$PLOGFILE
    #rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude-from=$WHITELISTFILE ${rootpath}${m_mountPath}/temp/usr/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/usr-ovl/ >>$PLOGFILE 2>&1
    #echo "Rsync传输var目录：">>$PLOGFILE
    #rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude-from=$WHITELISTFILE ${rootpath}${m_mountPath}/temp/var/  ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/var-ovl/ >>$PLOGFILE 2>&1
	echo "Rsync传输home目录：">>$PLOGFILE
    echo "Rsync传输home目录：${rootpath}/data/home/${m_username}">>$PLOGFILE
    echo "rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude=.box/ --include=.* --include=*/.* --include=*/* --exclude=* ${rootpath}${m_mountPath}/temp/home/  ${rootpath}/data/home/${m_username}" >>$PLOGFILE
    rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args --exclude=.box/ --include=.* --include=*/.* --include=*/* --exclude=*  ${rootpath}${m_mountPath}/temp/home/  ${rootpath}/data/home/${m_username} >>$PLOGFILE 2>&1
}

rsyncFactoryFromTemp()
{
	echo "Rsync传输home目录：">>$PLOGFILE
	rsync -avAHXr --delete  --info=progress2 --no-inc-recursive --ignore-missing-args ${rootpath}${m_mountPath}/temp/home/ ${rootpath}/data/home/ >>$PLOGFILE 2>&1
}

catFstabDataPath()
{
	echo "开始查看data分区" >>$PLOGFILE
	local name=$1
	echo "name: {$name}"  >>$PLOGFILE
	#RC10系统下，initrd阶段，fstab文件为空，需要找一个ovl下得目录获取fstab
	local ovlhash=`ls -l ${rootmnt}/sysroot/ostree/pkgs/|grep ovl-.*\.0$ | tail -1 |awk -F ' ' '{print $9}'`
	echo "ovlhash: {$ovlhash}"  >>$PLOGFILE
	local fstabpath=${rootmnt}/sysroot/ostree/pkgs/${ovlhash}/etc-ovl/etc-lower/fstab
	echo "fstabpath: {$fstabpath}"  >>$PLOGFILE
	#获取对应分区得UUID
	local Uuid=$(cat ${fstabpath} |grep ${name} |grep UUID |awk  -F ' ' '{print $1}' | awk  -F '=' '{print $2}')
	echo "Uuid: {$Uuid}"  >>$PLOGFILE
	#根据UUID获取对应分区名称
	local devName=`ls -l /dev/disk/by-uuid/|grep ${Uuid} | awk  -F '../..' '{print $2}'`
	echo "devName: {$devName}"  >>$PLOGFILE
	devPathData=/dev${devName}
	echo "devPathData: {$devPathData}"  >>$PLOGFILE
}

catFstabBootPath()
{
        echo "开始查看boot分区"  >>$PLOGFILE
        local name=$1
        echo "name: {$name}"  >>$PLOGFILE
        #RC10系统下，initrd阶段，fstab文件为空，需要找一个ovl下得目录获取fstab
        local ovlhash=`ls -l ${rootmnt}/sysroot/ostree/pkgs/|grep ovl-.*\.0$ | tail -1 |awk -F ' ' '{print $9}'`
        echo "ovlhash: {$ovlhash}"  >>$PLOGFILE
        local fstabpath=${rootmnt}/sysroot/ostree/pkgs/${ovlhash}/etc-ovl/etc-lower/fstab
        echo "fstabpath: {$fstabpath}"  >>$PLOGFILE
        #获取对应分区得UUID
        local Uuid=$(cat ${fstabpath} |grep ${name} |grep UUID |grep -v /boot/efi |awk  -F ' ' '{print $1}' | awk  -F '=' '{print $2}')
        echo "Uuid: {$Uuid}"  >>$PLOGFILE
        #根据UUID获取对应分区名称
        local devName=`ls -l /dev/disk/by-uuid/|grep ${Uuid} | awk  -F '../..' '{print $2}'`
        echo "devName: {$devName}"  >>$PLOGFILE
        devPathBoot=/dev${devName}
        echo "devPathBoot: {$devPathBoot}"  >>$PLOGFILE
}

roolback()
{
	echo "查看系统部署点：">>$PLOGFILE
	chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures" >>$PLOGFILE 2>&1
	num=$(chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures| grep kylin | grep -v refspec |grep -n ${m_system_hash} | awk -F ':' '{print \$1}'  ")
	#实际操作的行号要减一
	new_num=$((num - 1))
	echo "实际回滚时的序列号：$new_num">>$PLOGFILE
    catFstabBootPath "/boot"
    catFstabDataPath "/data"
    umountOtherPath
	backup-setdefault $new_num $devPathBoot $devPathData
    mountOtherPath
}

updateAfterRestore()
{
	echo "执行update-initramfs -u：">>$PLOGFILE
	chroot ${rootmnt} /bin/bash -c "update-initramfs -u" >>$PLOGFILE 2>&1
	if [ $? -ne 0 ]; then
		echo "chroot run 'update-initramfs -u' error!"
		echo "chroot run 'update-initramfs -u' error!" >>$PLOGFILE
	else
		echo "chroot run 'update-initramfs -u' ok!"
		echo "chroot run 'update-initramfs -u' ok!" >>$PLOGFILE
		sync
	fi
	
	echo "执行update-grub：">>$PLOGFILE
	chroot ${rootmnt} /bin/bash -c "update-grub" >>$PLOGFILE 2>&1
	if [ $? -ne 0 ]; then
		echo "chroot run 'update-grub' error!"
		echo "chroot run 'update-grub' error!" >>$PLOGFILE
	else
		echo "chroot run 'update-grub' ok!"
		echo "chroot run 'update-grub' ok!" >>$PLOGFILE
		sync
	fi
	
	#需要挂载/boot和/boot/efi两个目录
	echo "执行grub-install：">>$PLOGFILE
	device_boot=$(mount | grep /boot | grep -v /efi | awk '{print $1}')
	echo "device_boot：${device_boot}">>$PLOGFILE
	chroot ${rootmnt} /bin/bash -c "grub-install -v --boot-directory=/boot/ --efi-directory=/boot/efi/ ${device_boot}" >>$PLOGFILE 2>&1
	if [ $? -ne 0 ]; then
		echo "chroot run 'grub-install' error!"
		echo "chroot run 'grub-install' error!" >>$PLOGFILE
	else
		echo "chroot run 'grub-install' ok!"
		echo "chroot run 'grub-install' ok!" >>$PLOGFILE
		sync
	fi
}

resignKsaf()
{
	echo "还原完成之后执行全盘打标：">>$PLOGFILE
	#设置软模式
	setstatus softmode
	echo 8 > /etc/ksaf/tmp/.status
	echo 8 > ${rootpath}/etc/ksaf/tmp/.status
	echo 8 > ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/etc-ovl/etc-tmpupper/ksaf/tmp/.status
	echo 8 > ${rootpath}/sysroot/ostree/pkgs/ovl-${m_system_hash}/etc-ovl/etc-upper/ksaf/tmp/.status
}


#see backup-auto/autobackup.cpp
restoreAuto() { #还原
    local xxx
    local uuid
    if [ $m_isFactory = true ]; then
    	m_default_uuid="{00000000-0000-0000-0000-000000000000}"
    fi
    getLastUsefulBackupPointUuid
	uuid=$lastUsefulBackupPointUuid
	if [ "${uuid}" = "{00000000-0000-0000-0000-000000000000}" ]; then
		m_isFactory=true
	fi

    #写日志文件
    local m_time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
    writeLogFile "${m_time},${uuid},4,grub系统还原,,,${lastbackupname}" #grub时只有一键还原，没有增量还原

    restoreDir="${m_mountPath}/snapshots/${uuid}"
    restoreDataPath="${restoreDir}/data"

    if [ $m_Position = true ]; then
	    local prePath=""
	    # if [[ $m_PrefixDestPath =~ ^/data || $m_PrefixDestPath =~ ^/autobackup ]]; then
	    if [[ "x${m_PrefixDestPath}y" != "xy" && "x${m_PrefixDestPath}y" != "x/y" ]]; then
		    prePath="${rootpath}${m_PrefixDestPath}"
	    fi

	    local imgFile="${prePath}/backup/snapshots/${uuid}/data/dst.img"
        local bootDir="${prePath}/backup/snapshots/${uuid}/data/boot"
        echo "imgFile = ${imgFile}"
	    echo "imgFile = ${imgFile}" >> $PLOGFILE
        echo "bootDir = ${bootDir}"
	    echo "bootDir = ${bootDir}" >> $PLOGFILE
	    if [ -e $imgFile ]; then
            local imgPath="${m_mountPath}/imgbackup"
		    mkdir -p $imgPath
		    mount -o loop,ro "${imgFile}" "${imgPath}"
		    sleep 1
		    mount | grep imgbackup >> ${PLOGFILE}
		    if [ ! -e "${imgPath}/boot" ]; then
			    echo "${imgFile} does not mounted on ${imgPath}"
			    exit 9
		    fi
		    restoreDataPath=${imgPath}
	        restoreDir="${prePath}/backup/snapshots/${uuid}"
        elif [ -e $bootDir ]; then
            restoreDir="${prePath}/backup/snapshots/${uuid}"
            restoreDataPath="${restoreDir}/data"
            echo "非压缩备份点${restoreDir}" >> $PLOGFILE
	    else
		    echo "$imgFile does not exist!"
		    exit 7 #备份文件不存在，不能还原系统
	    fi
    fi

    if [ ! -e "${restoreDataPath}/boot" ]; then
        echo "full restore directory not exists!"
        exit 7 #备份文件不存在，不能还原系统
    fi

    if [ "$uuid" = "{$auto_uuid}" ]; then
	    m_isRetainUserData=true
    fi

    #0:backup 1:restore
    #generateExcludeFile 1
    echo "Begin to restore efi directory..." >>$PLOGFILE
    echo "Begin to restore efi directory..."
    #额外排除目录或文件
    local excludes=
    if [ -d ${restoreDataPath}/efi ]; then
        rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${restoreDataPath}/efi ${rootpath}/boot >/dev/null 2>>$PLOGFILE
        if [ $? -ne 0 -a $? -ne 24 -a $? -ne 23 ]; then
            echo "System restoring failed, please reboot your system!"
            echo "System restoring failed, please reboot your system!" >>$PLOGFILE
            exit 9
        fi
    elif [ -d ${restoreDataPath}/boot/efi ]; then
        rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${restoreDataPath}/boot/efi ${rootpath}/boot >/dev/null 2>>$PLOGFILE
        if [ $? -ne 0 -a $? -ne 24 -a $? -ne 23 ]; then
            echo "System restoring failed, please reboot your system!"
            echo "System restoring failed, please reboot your system!" >>$PLOGFILE
            exit 9
        fi
    fi

    echo "Begin to restore other directories..."
    echo "Begin to restore other directories..." >>$PLOGFILE
    #保留用户数据还原
    if [[ x${m_isRetainUserData} = x"true" ]]; then
        echo "保留用户数据还原" >> ${rootpath}/var/log/backup.log
        # 用户数据目录或文件
        if [ -e "${rootpath}/var/lib/biometric-auth" ]; then
            excludes="${excludes} --exclude=/var/lib/biometric-auth"
        fi
        if [ -e "${rootpath}/data/sec_storage_data" ]; then
            excludes="${excludes} --exclude=/data/sec_storage_data"
        fi
        if [ -e "${rootpath}/etc/passwd" ]; then
            excludes="${excludes} --exclude=/etc/passwd"
        fi
        if [ -e "${rootpath}/etc/shadow" ]; then
            excludes="${excludes} --exclude=/etc/shadow"
        fi
        if [ -e "${rootpath}/etc/group" ]; then
            excludes="${excludes} --exclude=/etc/group"
        fi
        if [ -e "${rootpath}/etc/gshadow" ]; then
            excludes="${excludes} --exclude=/etc/gshadow"
        fi
        if [ -e "${rootpath}/etc/sudoers" ]; then
            excludes="${excludes} --exclude=/etc/sudoers"
        fi
        excludes="${excludes} --exclude=/home --exclude=/root --exclude=/var/lib/AccountsService"
        #下面是域用户相关信息，保留用户数据还原后不退域
        #excludes="${excludes} --exclude=/etc/sssd --exclude=/var/lib/sss --exclude=/usr/share/sssd --exclude=/etc/ipa --exclude=/etc/krb5.keytab"
        #excludes="${excludes} --exclude=/etc/krb5.conf --exclude=/var/lib/ipa-client --exclude=/etc/nsswitch.conf --exclude=/etc/pam.d --exclude=/etc/hosts"
        #excludes="${excludes} --exclude=/etc/hostname --exclude=/etc/hedron --exclude=/etc/kcm --exclude=/usr/hedron/hedronagent --exclude=/etc/.kyinfo --exclude=/etc/LICENSE"
        #excludes="${excludes} --exclude=/etc/ssl/certs --exclude=/usr/share/ca-certificates --exclude=/etc/NetworkManager --exclude=/var/lib/pam"
        #excludes="${excludes} --exclude=/etc/kim --exclude=/var/lib/kim --exclude=/etc/systemd/system/multi-user.target.wants/kimbackend.service"
        #excludes="${excludes} --exclude=/var/lib/polkit-1/localauthority/40-domain.d --exclude=/lib/*/libsss_sudo.so"
        #excludes="${excludes} --exclude=/usr/share/applications/kylin-os-installer.desktop"
        #excludes="${excludes} --exclude=*/.local/share/applications/kylin-os-installer.desktop"
        #excludes="${excludes} --exclude=/etc/xdg/autostart/kylin-os-installer.desktop"


        #下面是域用户相关信息，保留用户数据还原后不退域
       if [ -e "${rootpath}/etc/sssd" ]; then
         excludes="${excludes} --exclude=/etc/sssd"
       fi   
       if [ -e "${rootpath}/var/lib/sss" ]; then
         excludes="${excludes} --exclude=/var/lib/sss"
       fi
       if [ -e "${rootpath}/usr/share/sssd" ]; then
         excludes="${excludes} --exclude=/usr/share/sssd"
       fi
       if [ -e "${rootpath}/etc/ipa" ]; then
         excludes="${excludes} --exclude=/etc/ipa"
        fi
       if [ -e "${rootpath}/etc/krb5.keytab" ]; then
         excludes="${excludes} --exclude=/etc/krb5.keytab"
       fi
       if [ -e "${rootpath}/etc/krb5.conf" ]; then
         excludes="${excludes} --exclude=/etc/krb5.conf"
       fi
       if [ -e "${rootpath}/var/lib/ipa-client" ]; then
         excludes="${excludes} --exclude=/var/lib/ipa-client"
       fi
       if [ -e "${rootpath}/etc/nsswitch.conf" ]; then
         excludes="${excludes} --exclude=/etc/nsswitch.conf"
       fi
       if [ -e "${rootpath}/etc/pam.d" ]; then
         excludes="${excludes} --exclude=/etc/pam.d"
       fi
       if [ -e "${rootpath}/etc/hosts" ]; then
         excludes="${excludes} --exclude=/etc/hosts"
       fi
       if [ -e "${rootpath}/etc/hostname" ]; then
         excludes="${excludes} --exclude=/etc/hostname"
       fi
       if [ -e "${rootpath}/etc/hedron" ]; then
         excludes="${excludes} --exclude=/etc/hedron"
       fi
       if [ -e "${rootpath}/etc/kcm" ]; then
         excludes="${excludes} --exclude=/etc/kcm"
       fi
       if [ -e "${rootpath}/usr/hedron/hedronagent" ]; then
         excludes="${excludes} --exclude=/usr/hedron/hedronagent"
        fi
        if [ -e "${rootpath}/etc/.kyinfo" ]; then
         excludes="${excludes} --exclude=/etc/.kyinfo"
        fi
        if [ -e "${rootpath}/etc/LICENSE" ]; then
         excludes="${excludes} --exclude=/etc/LICENSE"
        fi
        if [ -e "${rootpath}/etc/ssl/certs" ]; then
         excludes="${excludes} --exclude=/etc/ssl/certs"
        fi
        if [ -e "${rootpath}/usr/share/ca-certificates" ]; then
         excludes="${excludes} --exclude=/usr/share/ca-certificates"
        fi
        if [ -e "${rootpath}/etc/NetworkManager" ]; then
         excludes="${excludes} --exclude=/etc/NetworkManager"
        fi
        if [ -e "${rootpath}/var/lib/pam" ]; then
         excludes="${excludes} --exclude=/var/lib/pam"
        fi
        
        if [ -e "${rootpath}/usr/share/applications/kylin-os-installer.desktop" ]; then
       excludes="${excludes} --exclude=/usr/share/applications/kylin-os-installer.desktop"
       fi
       if [ -e "${rootpath}*/.local/share/applications/kylin-os-installer.desktop" ]; then
       excludes="${excludes} --exclude=*/.local/share/applications/kylin-os-installer.desktop"
       fi
       if [ -e "${rootpath}/etc/xdg/autostart/kylin-os-installer.desktop" ]; then
       excludes="${excludes} --exclude=/etc/xdg/autostart/kylin-os-installer.desktop"
       fi

        #如果是990，排除/data；否则，排除/data/usershare
        #if [ x${is_990_9a0} == x"true" ]; then
            excludes="${excludes} --exclude=/data"
        #else
        #    excludes="${excludes} --exclude=/data/usershare"
        #fi
        #如果是出厂备份的还原，还需要保留语言和时区配置
        # if [[ ${uuid} = "{${factory_uuid}}" && x${is_990_9a0} != x"true" ]]; then
        if [  "${m_isFactory}" = "true" ]; then
            if [ -e "${rootpath}/etc/localtime" ]; then
                excludes="${excludes} --exclude=/etc/localtime"
            fi
            if [ -e "${rootpath}/usr/share/zoneinfo" ]; then
                excludes="${excludes} --exclude=/usr/share/zoneinfo"
            fi
            if [ -e "${rootpath}/etc/default/locale" ]; then
                excludes="${excludes} --exclude=/etc/default/locale"
            fi
            if [ -e "${rootpath}/usr/share/i18n" ]; then
                excludes="${excludes} --exclude=/usr/share/i18n"
            fi

            if [ -e "${rootpath}/etc/lightdm/lightdm.conf" ]; then
                excludes="${exclude} --exclude=/etc/lightdm/lightdm.conf"
            fi
        fi

        # 系统更新的还原不还原下面目录
        if [ "${uuid}" = "{01234567-0123-0123-0123-0123456789ab}" ]; then
            #  excludes="${excludes} --exclude=/var/lib/kylin-system-updater"
            #  excludes="${excludes} --exclude=/var/cache/kylin-system-updater"
            excludes="${excludes} --exclude=/var/lib/kylin-system-updater/remain"
        fi
    fi
    # 兼容以前的老备份数据，后面可以尝试去掉此条件的逻辑
    # 出厂还原时，还原文件/etc/uid_list，其它场景不还原:等保四级标准操作系统使用周期内有uid唯一性的要求
    if [ "${m_isFactory}" != "true" ]; then
    	if [ ! -e "${restoreDir}/data/etc/uid_list" ]; then
    		excludes="${excludes} --exclude=/etc/uid_list"
    	fi
    fi
    if [ ! -e "${restoreDir}/data/boot/efi" ]; then
        excludes="${excludes} --exclude=/boot/efi"
    fi
    excludes="${excludes} --exclude=/var/log"
    excludes="${excludes} --exclude=*/backup/snapshots"
    excludes="${excludes} --exclude=/data/security-dir"
    # 还原后仍然保持激活状态
    #excludes="${excludes} --exclude=/etc/LICENSE --exclude=/etc/.kyinfo --exclude=/etc/.kyactivation --exclude=/etc/.kyhwid"

    if [ -e "${rootpath}/etc/LICENSE" ]; then
         excludes="${excludes} --exclude=/etc/LICENSE"
    fi
    if [ -e "${rootpath}/etc/.kyinfo" ]; then
         excludes="${excludes} --exclude=/etc/.kyinfo"
    fi
    if [ -e "${rootpath}/etc/.kyactivation" ]; then
         excludes="${excludes} --exclude=/etc/.kyactivation"
    fi
    if [ -e "${rootpath}/etc/.kyhwid" ]; then
         excludes="${excludes} --exclude=/etc/.kyhwid"
    fi


    # 还原保留kylin-backup-server包安装的程序
    excludes="${excludes} --exclude=/usr/bin/kylin-backup-daemon --exclude=/usr/bin/backup_mount_fstab --exclude=/usr/bin/restore-system"
    excludes="${excludes} --exclude=/usr/share/initramfs-tools/hooks/kylin-backup-hooks"
    excludes="${excludes} --exclude=/usr/share/initramfs-tools/scripts/init-bottom/kylin-backup"
    excludes="${excludes} --exclude=/usr/share/initramfs-tools/conf-hooks.d/kylin-backup"
    #excludes="${excludes} --exclude=/etc/extra_backup_or_restore.conf"

    if [ -e "${rootpath}/etc/extra_backup_or_restore.conf" ]; then
         excludes="${excludes} --exclude=/etc/extra_backup_or_restore.conf"
    fi

    excludes="${excludes} --exclude=/usr/share/plymouth"
    #yi jian huan yuan
    if [ ! -e "${restoreDir}/data/data" ]; then
        #这两行要一致
        echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude=/data ${excludes}  --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE ${restoreDataPath}/ $rootpath" >>${rootpath}/var/log/backup.log 2>&1
        rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --exclude=/data ${excludes} --exclude-from $restoreDir/$PERSONAL_EXCLUDEFILE "${restoreDataPath}/" $rootpath >>${rootpath}/var/log/backup.log 2>&1

    else
        #这两行要一致
        echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${excludes} --exclude-from=$restoreDir/$PERSONAL_EXCLUDEFILE ${restoreDataPath}/ $rootpath" >>${rootpath}/var/log/backup.log 2>&1
        rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete ${excludes} --exclude-from=$restoreDir/$PERSONAL_EXCLUDEFILE "${restoreDataPath}/" $rootpath >>${rootpath}/var/log/backup.log 2>&1

    fi

    if [ $? -ne 0 -a $? -ne 24 -a $? -ne 23 ]; then
        echo "System restoring failed, please reboot your system!"
        echo "System restoring failed, please reboot your system!" >>$PLOGFILE
        exit 9
    fi

    echo "restore other directories end"
    echo "restore other directories end" >>$PLOGFILE

    # 还原额外数据  
	local restoreExtraDataPath="${restoreDir}/extra_data" 
    local PERSONAL_EXARTALFILE=".user_extra.txt"
    if [ -e "${restoreExtraDataPath}" ]; then
        if [ -e ${restoreDir}/${PERSONAL_EXARTALFILE} ]; then
            echo "restore extra data"
            echo "restore extra data" >>$PLOGFILE
            
            #这两行要一致
            echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --files-from=${restoreDir}/${PERSONAL_EXARTALFILE} ${restoreExtraDataPath}/ $rootpath" >>${rootpath}/var/log/backup.log 2>&1
            rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete --files-from=${restoreDir}/${PERSONAL_EXARTALFILE} "${restoreExtraDataPath}/" $rootpath >>${rootpath}/var/log/backup.log 2>&1

        fi
    fi

    sync
    
    # TODO : 解决问题：系统更新后，grub系统还原(桌面系统还原没有问题)，然后自动引导不起来，需要手动引导系统
    #       问题1——grub-install命令的--target参数不同架构不一样；
    #       问题2——命令执行报错：failed to register the EFI boot entry: Operation not permitted.
    #       问题3——未知
    #  由于问题不常见，且桌面系统还原没有问题，暂时不修改grub还原部分
    device_boot=$(mount | grep /boot | grep -v /efi | awk '{print $1}')
    device_efi=$(mount | grep /boot/efi | awk '{print $1}')
    echo "device_boot=${device_boot} device_efi=${device_efi}" >>$PLOGFILE
    device_boot=${device_boot#${rootmnt}}
    device_efi=${device_efi#${rootmnt}}
    echo "After chroot: device_boot=${device_boot} device_efi=${device_efi}" >>$PLOGFILE
    if [ "x${device_efi}" = "x" ]; then
        echo "efi partition not mounted, please check if loss vfat type filesystem module"
        echo "efi分区未挂载，请检查内核或initrd中是否缺少vfat文件系统类型模块"  >>$PLOGFILE
    else
        if [ "x${device_boot}" != "x" ]; then
            echo "grub-install -v --force  --boot-directory=/boot/ --efi-directory=/boot/efi/ ${device_boot}"  >>$PLOGFILE
            chroot ${rootmnt} /bin/bash -c "mount -t proc proc /proc"
            chroot ${rootmnt} /bin/bash -c "mount -t sysfs sys /sys"
            chroot ${rootmnt} /bin/bash -c "mount -t devtmpfs devtmpfs /dev"
            chroot ${rootmnt} /bin/bash -c "mount -t devpts devpts /dev/pts"
            chroot ${rootmnt} /bin/bash -c "grub-install -v --boot-directory=/boot/ --efi-directory=/boot/efi/ ${device_boot}"
			chroot ${rootmnt} /bin/bash -c "update-grub"
            if [ $? -ne 0 ]; then
                echo "chroot run 'grub-install' error!"
                echo "chroot run 'grub-install' error!" >>$PLOGFILE
            else
                echo "chroot run 'grub-install' ok!"
                echo "chroot run 'grub-install' ok!" >>$PLOGFILE
                sync
            fi
        fi
    fi

    if [[ x${m_isRetainUserData} = x"true" && "${m_isFactory}" = "true" ]]; then
          rm -rf ${rootpath}/lib/systemd/system/kylin-os-installer.service
          rm -rf ${rootpath}/usr/bin/kylin-os-installer
          rm -rf ${rootpath}/usr/bin/kylin-os-installer-dm
          rm -rf ${rootpath}/usr/bin/kylin-os-installer-live
          rm -rf ${rootpath}/usr/bin/kylin-os-installer-oem
          rm -rf ${rootpath}/usr/bin/kylin-os-installer-oem-automatic
          rm -rf ${rootpath}/usr/bin/kylin-os-installer-wrapper
          rm -rf ${rootpath}/usr/share/doc/kylin-os-installer*
          rm -rf ${rootpath}/usr/share/kylin-os-installer*
          rm -rf ${rootpath}/usr/share/lightdm/lightdm.conf.d/96-kylin-os-installer.conf
          rm -rf ${rootpath}/home/*/.config/customAudio.xml
        # #这两行要一致
        #   local restoreExtraDataFile="${rootpath}/home/*/.config/customAudio.xml";
        #   local restoreFactoryExtraDataPath="${rootpath}/home/*/config";
        #   echo "rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete=$restoreExtraDataFile $restoreFactoryExtraDataPath/  $rootpath" >>${rootpath}/var/log/backup.log 2>&1
        #   rsync -avAXHr --no-inc-recursive --ignore-missing-args --delete=$restoreExtraDataFile "$restoreFactoryExtraDataPath/" $rootpath >>${rootpath}/var/log/backup.log 2>&1
 
   fi
#        echo 'chroot ${rootpath} /bin/bash -c "apt remove kylin-os-installer -y"'  >>$PLOGFILE
#        chroot ${rootpath} /bin/bash -c "apt remove kylin-os-installer -y"
#    fi

    sync
}

getAllSystemHash()
{
	echo "查看所有系统部署点：">>$PLOGFILE
	chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures" >>$PLOGFILE 2>&1

    # 获取所有hash并存储到变量
    HASHES=$(chroot "${rootmnt}" /bin/sh -c "
    ostree admin status --skip-signatures | \
    grep kylin | \
    grep -v refspec | \
    awk -F 'kylin' '{print \$2}' | \
    awk '{print \$1}' | \
    while IFS= read -r hash; do
        if [ -n \"\$hash\" ]; then
            echo \"\$hash\"
        fi
    done
    ")

    # # 后续循环使用
    # echo "存储的哈希值:"
    # echo "$HASHES"

    # # 循环处理每个hash
    # echo "$HASHES" | while IFS= read -r hash; do
    #     if [ -n "$hash" ]; then
    #         echo "处理哈希: $hash"
    #         # 执行实际操作
    #     fi
    # done
}

getHashNum()
{
    echo "查看系统部署点对应的序列号：">>$PLOGFILE
	num=$(chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures| grep kylin | grep -v refspec |grep -n $1 | awk -F ':' '{print \$1}'  ")
	#实际操作的行号要减一
	ret_num=$((num - 1))
}

getHashTotalNum()
{
	echo "查询系统部署点数量：" >>$PLOGFILE
	totalNum=$(chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures |grep kylin |grep -v refspec |wc -l ")
	echo "系统部署点数量：$totalNum" >>$PLOGFILE
}

getFactoryRefs()
{
	echo "查询系统出厂部署点refs：" >>$PLOGFILE
	factoryRefs=$(chroot ${rootmnt} /bin/bash -c "ostree admin status|grep refspec | tail -1 |awk -F 'refspec:' '{print \$2}' ")
	echo "系统出厂部署点refs：$refs" >> $PLOGFILE
}

doUndeploy()
{
	# 确保num是数字
	tempNum=$((totalNum))

	# 如果num小于等于2，则无需循环
	if [ $tempNum -le 1 ]; then
		echo "部署点数量小于等于1，无需执行循环" >> $PLOGFILE
	else
		# 从 tempNum-2 开始循环到 0
		echo "部署点数量为： ${tempNum}" >> $PLOGFILE
		startNum=$((tempNum - 2))
		echo "起始执行下标为：${startNum}"  >> $PLOGFILE
			
		echo "开始循环，从 $startNum 到 0" >> $PLOGFILE
        catFstabBootPath "/boot"
        catFstabDataPath "/data"
		for ((i = startNum; i >= 0; i--)); do
			echo "执行第 $i 次循环" >> $PLOGFILE
			backup-undeploy $i $devPathBoot $devPathData
		done
			
		echo "循环执行完成" >> $PLOGFILE
	fi
}

undeployHash()
{
    echo "需要避开的部署点：$m_system_hash" >>$PLOGFILE
    # 循环处理每个hash
    echo "$HASHES" | while IFS= read -r hash; do
        if [ -n "$hash" -a "$m_system_hash" != "$hash" ]; then
            echo "处理哈希: $hash" >>$PLOGFILE
            # 执行实际操作
            getHashNum "$hash"
            echo "部署点对应的序列号:$ret_num"  >>$PLOGFILE
	    echo "chroot ${rootmnt} /bin/sh -c 'ostree admin undeploy 1' " >>$PLOGFILE
	    chroot ${rootmnt} /bin/sh -c "ostree admin undeploy 1" >>$PLOGFILE 

        fi
    done
}

deployDescHash()
{
    needDeployHash=$(echo $m_system_hash |awk -F '.' '{print $1}')
	echo "即将新部署的部署点：$needDeployHash" >>$PLOGFILE
	chroot ${rootmnt} /bin/sh -c "/usr/lib/ostree/ostree-remount" >>$PLOGFILE 2>&1
    #chroot ${rootmnt} /bin/sh -c "ostree admin deploy $needDeployHash --retain " >>$PLOGFILE 2>&1
    chroot /root /bin/sh -c "ostree admin deploy kylin:kylin/desktop/v11/2603/xc/general/all/rc4/amd64  --os='kylin' --retain" >>$PLOGFILE
}

getDescHash()
{
    echo "获取出厂还原之后目标哈希值：">>$PLOGFILE
	m_system_hash=$(chroot ${rootmnt} /bin/bash -c "ostree admin status --skip-signatures| grep pending |awk -F ' ' '{print \$2}'")
    echo "修正之后出厂还原目标哈希值：">>$PLOGFILE
}


#see backup-auto/autobackup.cpp
updateBackupAutoFinishedState() {
    echo "this is updateBackupAutoFinishedState"
}

restoreBackupSelf() {
    restoreDir="${rootpath}/var/log/yhkylin-backup-tools"
    echo $restoreDir

    if [ ! -e "$restoreDir" ]; then
	echo "restoreBackupSelf error: no files"
	return 1
    fi
    
    # 还原rsync/kybackup/backup-daemon等程序
    rsync -avAXHr ${restoreDir}/backup-daemon ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1
    rsync -avAXHr ${restoreDir}/kybackup ${rootpath}/usr/bin/ >> ${rootpath}/var/log/backup.log 2>&1

    rm -rf ${restoreDir}
}


mountFstabPath()
{
	echo "开始挂载分区" >>$PLOGFILE
	name=$1
	echo "name: {$name}"  >>$PLOGFILE
	#RC10系统下，initrd阶段，fstab文件为空，需要找一个ovl下得目录获取fstab
	ovlhash=`ls -l ${rootmnt}/sysroot/ostree/pkgs/|grep ovl-.*\.0$ | tail -1 |awk -F ' ' '{print $9}'`
	echo "ovlhash: {$ovlhash}"  >>$PLOGFILE
	fstabpath=${rootmnt}/sysroot/ostree/pkgs/${ovlhash}/etc-ovl/etc-lower/fstab
	echo "fstabpath: {$fstabpath}"  >>$PLOGFILE
	#获取对应分区得UUID
	Uuid=$(cat ${fstabpath} |grep ${name} |grep UUID |awk  -F ' ' '{print $1}' | awk  -F '=' '{print $2}')
	echo "Uuid: {$Uuid}"  >>$PLOGFILE
	#根据UUID获取对应分区名称
	devName=`ls -l /dev/disk/by-uuid/|grep ${Uuid} | awk  -F '../..' '{print $2}'`
	echo "devName: {$devName}"  >>$PLOGFILE
	devPath=/dev${devName}
	echo "devPath: {$devPath}"  >>$PLOGFILE
	#挂载对应分区
	echo "mount ${devPath} ${rootmnt}${name}"  >>$PLOGFILE
	mount ${devPath} ${rootmnt}${name}
}

mountFstabBootPath()
{
        echo "开始挂载分区"  >>$PLOGFILE
        name=$1
        echo "name: {$name}"  >>$PLOGFILE
        #RC10系统下，initrd阶段，fstab文件为空，需要找一个ovl下得目录获取fstab
        ovlhash=`ls -l ${rootmnt}/sysroot/ostree/pkgs/|grep ovl-.*\.0$ | tail -1 |awk -F ' ' '{print $9}'`
        echo "ovlhash: {$ovlhash}"  >>$PLOGFILE
        fstabpath=${rootmnt}/sysroot/ostree/pkgs/${ovlhash}/etc-ovl/etc-lower/fstab
        echo "fstabpath: {$fstabpath}"  >>$PLOGFILE
        #获取对应分区得UUID
        Uuid=$(cat ${fstabpath} |grep ${name} |grep UUID |grep -v /boot/efi |awk  -F ' ' '{print $1}' | awk  -F '=' '{print $2}')
        echo "Uuid: {$Uuid}"  >>$PLOGFILE
        #根据UUID获取对应分区名称
        devName=`ls -l /dev/disk/by-uuid/|grep ${Uuid} | awk  -F '../..' '{print $2}'`
        echo "devName: {$devName}"  >>$PLOGFILE
        devPath=/dev${devName}
        echo "devPath: {$devPath}"  >>$PLOGFILE
        #挂载对应分区
	echo "mount ${devPath} ${rootmnt}${name}"  >>$PLOGFILE
        mount ${devPath} ${rootmnt}${name}
}

mountOtherPath()
{
	#mount /dev/nvme0n1p2 /root/boot/
        #mount /dev/nvme0n1p1 /root/boot/efi/
	#mount /dev/nvme0n1p5 /root/data
	mount --bind /proc /root/proc
	mount --bind /dev /root/dev
	mount --bind /dev/pts /root/dev/pts
	mount --bind /run /root/run
	mount --bind /sys /root/sys

	mountFstabPath "/data"
	mountFstabBootPath "/boot"
	mountFstabPath "/boot/efi"
}

umountOtherPath()
{
	umount /root/proc >>$PLOGFILE
	umount /root/dev >>$PLOGFILE
	umount /root/dev/pts >>$PLOGFILE
	umount /root/run >>$PLOGFILE
	umount /root/sys >>$PLOGFILE
	umount /root/boot >>$PLOGFILE
	umount /root/data >>$PLOGFILE
}

#-----------------------------------------------------------------
#--------主程序从这里开始-----------------------------------------

if [ "${rootpath}" = "/" ]; then
    echo "This program is used in boot time"
#	exit
fi

#挂载环境分区，用于后面chroot之后使用ostree环境，优先挂载/data，输出日志

mountOtherPath
echo "**************mount**************start" >>$PLOGFILE
mount >>$PLOGFILE
echo "**************mount**************end" >>$PLOGFILE

#创建必要的路径  日志路径，snapshot路径
mkdir -p ${PLOGFILEDIR}
mkdir -p ${SNAPSHOTDIR}


time=$(date "+%y-%m-%d %H:%M:%S" | tr -d "\n")
echo "" >> $PLOGFILE
echo "=========================${time}：备份还原操作开始！=========================" >> $PLOGFILE

echo $PLOGFILE
echo "参数:" $* >> $PLOGFILE
echo "m_isRetainUserData=" $m_isRetainUserData >>$PLOGFILE

# 临时关闭安全，因为有些文件安全保护为只读，造成备份还原无法操作
#sm_status=$(cat /sys/kernel/security/kysec/sm)
#file_protect=$(cat /sys/kernel/security/kysec/fpro)
#echo "文件保护状态：${file_protect} sm_status=${sm_status}" >> ${rootpath}/var/log/backup.log
#echo 0 > /sys/kernel/security/kysec/sm
#echo 0 > /sys/kernel/security/kysec/fpro

if [ $backupORrestore = "--autobackup" ]; then
	#备份前准备
	prepare		
	##记录当前系统哈希
	#recordSystemHash	
	##拷贝ovl到临时目录
	#cpOvl
	##清理s、b、c类数据
	#cleanSBCTypeFiles
	##提交到repo仓库，并更新xml
	#commitToRepo
	#清理临时数据
	#cleanTmpDir
	
    #backupAuto #备份, grub时只有全盘备份，没有增量备份
    #updateBackupAutoFinishedState
    #umountBackup

    echo "This is autobackup"

elif [ $backupORrestore = "--autorestore" ]; then
	#检测xml是否有备份点，检测ostree仓库是否存在
	checkEnvForSystemRestore
	#执行checkout步骤
	checkoutFromRepo
	
	#执行rsync同步
	rsyncFromTemp
	
	#执行系统哈希切换
	roolback

	#清理临时数据
	cleanTmpDir
	
	#sync落盘数据
	sync
	
	#执行更新grub等操作
	updateAfterRestore
	
	#还原后需要安全重新打标记
	resignKsaf

    #还原完成之后，如果是还原的系统升级备份点，需要删除对应的元数据
    if [ $m_isSystemUpdate = true ]; then
        echo "删除备份点:" $m_restore_uuid >> $PLOGFILE
        DeleteSystemUpdateBackupPoint
        echo "删除备份点元数据:" $m_restore_uuid >> $PLOGFILE
        deleteItemByUUID $m_restore_uuid
    fi
    
    echo "This is autorestore"

elif [ $backupORrestore = "--continueautorestore" ]; then
	#0.检测xml是否有备份点，检测ostree仓库是否存在
	checkEnvForFactoryRestore
    #1.判断需要undeploy部署点
    getAllSystemHash
    #2.通过undeploy清除备份点
    undeployHash
    #3.通过deploy生成目标部署点
    deployDescHash
    getDescHash
    #4.还原对应ovl数据
    #5.还原home数据
    checkoutFromRepo
    rsyncFactoryFromTemp
    #6.清理临时数据
	cleanTmpDir
	#7.sync落盘数据
	sync
	#8.执行更新grub等操作
	updateAfterRestore
	#9.还原后需要安全重新打标记
	resignKsaf

    #还原完成之后，如果是还原的系统升级备份点，需要删除对应的元数据
    if [ $m_isSystemUpdate = true ]; then
        echo "删除备份点:" $m_restore_uuid >> $PLOGFILE
        DeleteSystemUpdateBackupPoint
        echo "删除备份点元数据:" $m_restore_uuid >> $PLOGFILE
        deleteItemByUUID $m_restore_uuid
    fi

    #还原成功，清理 NEEDROOLBACKFILE 标志文件
    deleteNeedRollBackFile

    echo "This is continueautorestore"

elif [ $backupORrestore = "--factorybackup" ]; then
    m_isFactory=true
    mountBackup
    backupAuto              #备份, grub时只有全盘备份，没有增量备份
    updateBackupAutoFinishedState
    #umountBackup
elif [ $backupORrestore = "--restoreretainuserdata" ]; then
    m_isRetainUserData=true
    mountBackup
    mount >>$PLOGFILE
    restoreAuto
elif [ $backupORrestore = "--factoryrestore" ]; then
	#0.检测xml是否有备份点，检测ostree仓库是否存在
	checkEnvForFactoryRestore
    #1.判断需要undeploy部署点的数量，并且查询.0部署点对应的refs分支
    getHashTotalNum
	getFactoryRefs
    #2.通过undeploy清除备份点
    #卸载已挂在磁盘，然后执行undeploy操作，之后通过传入refs参数，执行deploy生成逻辑
    umountOtherPath
    doUndeploy
    backup-deploy  ${factoryRefs}
    #getDescHash
    #4.还原对应ovl数据
    #5.还原home数据,此时需要重新挂载磁盘
	mountOtherPath
    checkoutFromFactoryRepo
    rsyncFactoryFromTemp
    #6.清理临时数据
	cleanTmpDir
	#7.sync落盘数据
	sync
	#8.执行更新grub等操作
	updateAfterRestore
	#9.还原后需要安全重新打标记
	#resignKsaf

    echo "This is factorybackup"
elif [ $backupORrestore = "--restorebackupself" ]; then
    # 出厂备份安全没有打标记，恢复出厂后再进行其它系统还原就会造成标记丢失，无法进入系统，故不在此进行操作
    #restoreBackupSelf
    echo "Do nothing"
else
    echo "Not correct command"
    #exit 18
fi

#卸载已挂在磁盘
umountOtherPath

exit 0
