# #!/bin/bash 

if [ "$MOUNT_IMMUTABLE" = "no" ]; then
	exit
fi

# 把这个文件放在 /usr/share/initramfs-tools/scripts/init-bottom/ 目录下。
# 权限为 0755，在自动更新initrd时，这个脚本就被放到initrd中了，例如，
# update-initramfs -u
# 更新后，这个脚本将在initrd 运行到 local-bottom 阶段时自动执行。
# 此时根分区已经挂载到了/tmproot下，可以直接访问该分区的文件。

# PREREQ指定需要在什么脚本之后执行（同目录下的），也就是指定该脚本的依赖，以确定执行顺序。
# 如果没有依赖，就可以是空字符串。 
PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
	prereqs)
		prereqs
		exit 0
		;;
esac

# 上述部分是initramfs脚本的固定格式，不用动它。
# 除非有依赖，才需要改 PREREQ 的值。

#. /scripts/security-functions

SYSOVL_CONF="/root/sysroot/ostree/pkgs/system-ovl.conf"
root_real_path=$(readlink -f "/tmproot${OSTREEROOT}")

##处理更新升级后SYSOVL_CONF不存在的问题
if [ ! -d /root/sysroot/ostree/pkgs ]; then
    mkdir -p /root/sysroot/ostree/pkgs
    echo "Created /root/sysroot/ostree/pkgs directory."
fi

if [ ! -f ${SYSOVL_CONF} ] || [ ! -s ${SYSOVL_CONF} ] ; then
    cp -rf "${root_real_path}/sysroot/ostree/pkgs/system-ovl.conf" ${SYSOVL_CONF}
    echo "copy system-ovl.conf..."
fi

show_text_mesg()
{
        echo "$1"
}

plymouth_is_running()
{
        #if [ -e "/bin/plymouth" ] && /bin/plymouth --ping; then
        if [ -e "/bin/plymouth" ]; then
                return 0
        else
                return 1
        fi
}

show_message()
{
        if plymouth_is_running; then
                /bin/plymouth message --text="$1"
                show_text_mesg "$1"
        else
                show_text_mesg "$1"
        fi
}

clear_message()
{
        if plymouth_is_running; then
                plymouth message --text=""
        fi
        clear
}

isEnglish()
{
        LOCALFILE="/tmproot/etc/default/locale"
	if [ ! -e "$LOCALFILE" ]; then
	    return 0
	fi

        localcontent=`grep -E  "^LANG" $LOCALFILE | grep -i "zh_CN.UTF"`

        #echo "localcontent: $localcontent"

        if [ -z $localcontent ]; then
                #echo "This is English"
                return 1
        else
                #echo "系统支持中文"
                return 0
        fi
}

isEnglish
v_isEnglish=$?

myoutput()
{

        if [ $v_isEnglish -eq 1 ]; then
                echo $1
                #plymouth message --text=$1
                #echo "English"
		show_message "$1"
        else
                echo $2
                #plymouth message --text=$2
                #echo "中文"
		show_message "$2"
        fi
}

#***配置读取与设置
# key和value的分隔符，即等号两边有没有空格
delimeter='='
#delimeter=' = '

# 获取配置文件指定section指定key的value
get_value() {
    file=$1
    section=$2
    key=$3
    #val=$(awk -F "$delimeter" '/\['${section}'\]/{a=1}a==1&&$1~/'${key}'/{print $2;exit}' $file)
    #/^[[:space:]]*#/:跳过#注释行
    #{if ($0 ~ /\['${section}'\]/) {a=1} else if (a) {exit}}:匹配到[${section}]时将a设置为1
    #a==1 && $1~/'${key}'/ {print $2; exit}:在对应的组中（a==1）且匹配到键值key时打印并退出
    val=$(awk -F "$delimeter" '/^[[:space:]]*#/ {next} /\[/ {if ($0 ~ /\['${section}'\]/) {a=1} else if (a) {exit}} a==1 && $1~/'${key}'/ {print $2; exit}' "$file")
    echo ${val}
}


# 更新配置文件指定section指定key的value
set_value() {
    local file="$1"
    local section="$2"
    local key="$3"
    local val="$4"
    local delimiter="="  # 明确指定分隔符为等号

    # 创建临时文件
    tmpfile=$(mktemp) || return 1

    # 使用awk处理并输出到临时文件
    awk -F "$delimiter" -v sect="$section" -v k="$key" -v v="$val" '
        BEGIN { OFS=FS; in_section=0; modified=0 }
        /^[[:space:]]*#/ { print; next }   # 跳过注释行
        /^\[/ {                            # 处理 [section] 行
            if ($0 == "[" sect "]") {
                in_section = 1
            } else {
                in_section = 0
            }
            print
            next
        }
        in_section && $1 == k {            # 在目标 section 中找到目标 key
            $2 = v                         # 仅替换值部分（保留原键名）
            print $1 OFS $2
            modified = 1
            next
        }
        { print }                          # 其他行原样输出
    ' "$file" > "$tmpfile"
    # 将临时文件内容覆盖原文件，避免权限变更
    cat "$tmpfile" > "$file"

    # 清理临时文件
    rm -f "$tmpfile"
}
#***配置读取与设置

#root_real_path=$(readlink -f "/tmproot${OSTREEROOT}")
deploy_csum_serial="${root_real_path##*/}"  ##313543dcccf89686e998d728f4e54dc2c89dc4d876b56efec00055271db46d8b.1

##更新配置文件中deploy数据
set_value $SYSOVL_CONF "General" "Deploy" $deploy_csum_serial

OSTREE_PKG=${rootmnt}/sysroot/ostree/pkgs
# OSTREE_OVL=${OSTREE_PKG}/ovl-${deploy_csum_serial}

###获取当前处于哪种模式-通过配置文件，如果存在[boot] mode=maintain则表示处于运维模式，否则处于用户模式
# MODE=
# ### 模式0：运维 、模式1：用户
conf_file="${OSTREE_PKG}/ostree-ovl.conf"  
#配置文件是否表示为运维
#is_maintain_conf=N
is_maintain_mode=N ##表示当前(mode)是否为maintain
is_maintain_next_mode=N ##表示下次(next_mode)是否为maintain
if [ "$(get_value $conf_file "boot" "mode")" = "maintain" ];then
        is_maintain_mode=Y
fi

if [ "$(get_value $conf_file "boot" "next_mode")" = "maintain" ];then
        is_maintain_next_mode=Y
fi


###锁文件判断
is_maintain_lock=N
get_mode_lock()
{
    if [ -f "${OSTREE_PKG}/mm.lock" ];then
        echo "----${OSTREE_PKG}/mm.lock exist!"
        is_maintain_lock=Y
    else
        echo "----${OSTREE_PKG}/mm.lock not exist!"
    fi
}

##批量处理字符串替换，入参为：原始字符串，待替换A1，替换B1，待替换A2，替换B2.....
##例:replace_string $LowerDir "<PathPre>" $PathPre "<stage>" $StageInitrd "<Deploy>" $Deploy
##      字符串LowerDir中，"<PathPre>"替换为变量PathPre，"<stage>"替换为变量StageInitrd，"<Deploy>"替换为变量SDeploy
replace_string() {
    if [ $# -lt 1 ]; then
        echo "Usage: replace_string original_str target1 replacement1 ..."
        return 1
    fi
    original_str=$1
    shift # 移除原始字符串参数，后续参数为替换对
    while [ $# -ge 2 ]; do
        target=$1
        replacement=$2
        original_str=$(echo "$original_str" | sed "s#$target#$replacement#g")  # 全局替换
        shift 2	 # 移动到下一组替换对
    done
    echo "$original_str"
}


##****字符串替换自动化流程

#运维模式与用户模式共同存在变量
StageInitrd=$(get_value $SYSOVL_CONF "Overlay" "StageInitrd")
PathPre=$(get_value $SYSOVL_CONF "Overlay" "PathPre")
Deploy=$(get_value $SYSOVL_CONF "General" "Deploy")

#通用替换处理流程，将字符串中的变量替换为对应的值，保存在变量中
#替换关系为：
#       "<PathPre>"     $PathPre
#       "<stage>"       $StageInitrd
#       "<Deploy>"      $Deploy
#生成的值保存在${dir_type}_${suffix}变量中，例如$LowerDir_etc
#拼接后值为：LowerDir_etc=/root/sysroot/ostree/pkgs/ovl-abc.1/etc-ovl/etc-upper:/root/sysroot/ostree/pkgs/ovl-abc.1/etc-ovl/etc-lower:/root/etc
process_section() {
    section="$1"
    suffix="$2"
    dir_types="LowerDir UpperDir WorkDir MergeDir"

    for dir_type in $dir_types; do
        pend_value=$(get_value "$SYSOVL_CONF" "$section" "$dir_type")
        resolved_value=$(replace_string "$pend_value" \
            "<PathPre>" "$PathPre" \
            "<stage>" "$StageInitrd" \
            "<Deploy>" "$Deploy")

        eval "${dir_type}_${suffix}=\"\$resolved_value\""
        echo "${dir_type}_${suffix}=$resolved_value"
    done
}
##****字符串替换自动化流程

##****根据配置自动化处理挂载
auto_mount_process() {
    sections="$1"
    IFS=' '

    if [ ! -d "${OSTREE_PKG}/ovl-${deploy_csum_serial}/usr-ovl/usr-upper" ]; then
        mkdir "${OSTREE_PKG}/ovl-${deploy_csum_serial}/usr-ovl/usr-upper"
        echo "mkdir ${OSTREE_PKG}/ovl-${deploy_csum_serial}/usr-ovl/usr-upper"
    fi

    for section in $sections; do
        old_ifs="$IFS"
        IFS=':'
        set -- $section
        section="$1"
        suffix="$2"
        IFS="$old_ifs"
	# 使用间接扩展获取变量值,设置lower_dir的值为LowerDir_$section变量的值
        eval "lower_dir=\$LowerDir_$suffix"
        eval "upper_dir=\$UpperDir_$suffix"
        eval "work_dir=\$WorkDir_$suffix"
        eval "merge_dir=\$MergeDir_$suffix"

 	# 参数验证 - lower_dir、merge_dir对应目录必须存在
        if [ -z "$lower_dir" ] || [ -z "$merge_dir" ]; then
            echo "[ERROR] Missing parameters for $suffix" >&2
            continue
        fi

	# 动态构建挂载参数
        mount_options="lowerdir=$lower_dir"
        if [ -n "$upper_dir" ]; then  ## upper_dir对应目录存在时，workdir必须存在
            mount_options="$mount_options,upperdir=$upper_dir"
            if [ -z "$work_dir" ]; then
                echo "[ERROR] WorkDir required for $suffix"
                continue
            fi
            mount_options="$mount_options,workdir=$work_dir"
        elif [ -n "$work_dir" ]; then  ## upper_dir对应目录不存在时，workdir可以存在
            mount_options="$mount_options,workdir=$work_dir"
        fi

        machine=`uname -m`
        if [ "x$machine" != "xsw_64" ];then 
            mount_cmd=$(printf 'mount -t overlay overlay -o "%s" "%s"'  "$mount_options" "$merge_dir")
        else    ##sw架构额外处理，增加index=off
            mount_cmd=$(printf 'mount -t overlay overlay -o "%s" "%s"'  "${mount_options},index=off" "$merge_dir")
        fi
        
	echo mount_cmd=$mount_cmd
	# 执行挂载命令
    if eval "$mount_cmd"; then
        echo "[OK] $suffix mounted to $merge_dir"
    else
        echo "[FAIL] $suffix mount failed (code:$?)" 
    fi
    done
}
##****根据配置自动化处理挂载

## 运维模式挂载
maintain_mode_mount() {
    # 定义运维模式需要处理的配置块（空格分隔字符串）
    sections="etc-M:etc usr-M:usr var.lib-M:varlib"

    # 循环处理所有配置块
    for entry in $sections; do
        IFS=':' read -r section suffix <<EOF
$entry
EOF
        process_section "$section" "$suffix"
    done

    # 自动化挂载对应模块
    auto_mount_process "$sections"

    if [ "$is_maintain_mode" = "N" ]; then
        set_value "$conf_file" "boot" "mode" "maintain"
    fi
    if [ "$is_maintain_next_mode" = "N" ]; then
        set_value "$conf_file" "boot" "next_mode" "maintain"
    fi
    if [ "$is_maintain_lock" = "N" ]; then
        echo "touch maintain lock"
        touch "${OSTREE_PKG}/mm.lock"
    fi
    set_value "$SYSOVL_CONF" "General" "Mode" "maintain"
}

## 用户模式挂载
user_mode_mount() {
    # 定义用户模式需要处理的配置块
    sections="etc-N:etc usr-N:usr var.lib-N:varlib"

    # 循环处理所有配置块
    for entry in $sections; do
        IFS=':' read -r section suffix <<EOF
$entry
EOF
        process_section "$section" "$suffix"
    done

    # 自动化挂载对应模块
    auto_mount_process "$sections"

    ##同步配置文件、锁文件为用户模式
        if [ "${is_maintain_mode}" = "Y" ]; then
                ###修改配置文件模式标记
                set_value $conf_file "boot" "mode" "normal"
        fi
        
        if [ "${is_maintain_next_mode}" = "Y" ]; then
                ###修改配置文件模式标记
                set_value $conf_file "boot" "next_mode" "normal"
        fi

        if [ "${is_maintain_lock}" = "Y" ]; then
                ###删除标记文件
                echo "delete maintain lock"
                rm -rf /tmproot/ostree/pkgs/mm.lock
        fi

        set_value $SYSOVL_CONF "General" "Mode" "normal" ##更新配置文件中Mode为用户模式
}


# 判断是否存在backup|restore|rollback-backup等字段，如果存在以上字段则为备份、还原、恢复出厂等模式，不走这套运维不运维的模式 
IS_BACKUP=
IS_OSTREE_RESTORE=
if [ -f "/proc/cmdline" ]; then  
    # 使用grep检查文件中是否包含特定的字段  如果grep找到匹配项，它将返回状态码0（成功），否则返回非0状态码  
    if grep -qE "backup|restore|rollback-backup|restore-retain-userdata|factory-restore|ostree-factory-restore" "/proc/cmdline"; then  
        IS_BACKUP=Y
        if grep -qE "ostree-factory-restore" "/proc/cmdline"; then 
                IS_OSTREE_RESTORE=Y
                ##ostree的恢复出厂设置则直接挂载为用户模式，且恢复配置文件以及锁文件
                user_mode_mount
        fi
        echo "is backup、restore、rollback-backup STOP"  
    else  
        # 如果都不存在，则设置变量a为y，并继续执行  
        IS_BACKUP=N
        echo "is not backup。"  
        # 在这里添加你的后续操作  
    fi  
else  
    echo "文件 /proc/cmdline 不存在。"  
fi

# ##ostree的恢复出厂设置则直接挂载为用户模式，且恢复配置文件以及锁文件
# if [ "${IS_OSTREE_RESTORE}" = "Y" ]; then 
#         user_mode_mount
# fi

## 非恢复出厂设置等标记
if [ "${IS_BACKUP}" = "N" ]; then 
        get_mode_lock
        echo "----is_maintain_conf=${is_maintain_conf}  is_maintain_lock=${is_maintain_lock}--------"
        if [ "${is_maintain_mode}" = "${is_maintain_lock}" ];then
                ##配置文件mode与锁文件状态一致，则上一次是正常退出
                if [ "$is_maintain_next_mode" = "Y" ]; then
                        maintain_mode_mount
                else
                        user_mode_mount
                fi
        else
                ##配置文件mode与锁文件状态不一致，则上一次是异常退出，plymouth询问
                while plymouth_is_running
                do
                        myoutput "There may be an abnormal exit before shutting down. Do you want to continue starting the system in [Operational Mode] ? [y/n]" "关机前可能存在异常退出，是否继续以 [运维模式] 启动系统？[y/n]"
                        is_sure=$(/bin/plymouth watch-keystroke)

                        case $is_sure in
                                y|Y)
                                        myoutput "Start the system in operation and maintenance mode" " 正在以运维模式启动系统 "
                                        maintain_mode_mount
                                        break
                                        ;;
                                n|N)
                                        myoutput "Start the system in normal mode" " 正在以用户模式启动系统 "
                                        #挂载用户目录
                                        user_mode_mount
                                        break
                                        ;;
                                *)      
                                        ;;
                        esac
                done
        fi
fi

exit 0
