#!/bin/sh
# 只检查安装/卸载操作

# 记录日志以便调试
# 获取主机名
hostname=$(hostname)
log() {
    # 生成ISO 8601格式的时间戳
    timestamp=$(date -Iseconds)
    # 输出标准syslog格式的日志
    echo "${timestamp} ${hostname} ostree-pkgs-guard: $1" >> /var/log/ostree.log
}

# 检测操作类型
detect_operation() {
    # 1. 尝试从 DPKG_HOOK_ACTION 获取
    case "$DPKG_HOOK_ACTION" in
        install|remove|purge|deconfigure|unpack|configure)
            echo "$DPKG_HOOK_ACTION"
            return
            ;;
    esac
}

# 判断是否在 Live Build 环境的函数 (POSIX 兼容)
is_live_build() {
    # 检查目录
    if [ -d "/lib/live" ] || [ -d "/usr/lib/live" ]; then
        log "检测到Live Build环境: 存在/lib/live或/usr/lib/live"
        return 0  # 是Live环境返回0
    fi
    
    # 检查内核参数
    if grep -q "boot=live" /proc/cmdline 2>/dev/null; then
        log "检测到Live Build环境: 内核参数包含boot=live"
        return 0
    fi
    
    # 检查文件
    if [ -e "/etc/live" ] || [ -e "/lib/live/mount/medium" ] || [ -e "/var/lib/live" ]; then
        log "检测到Live Build环境: 存在Live标志文件"
        return 0
    fi
    
    # 检查环境变量
    if [ -n "$LIVE_BUILD" ] || [ -n "$LB_BUILD_IMAGE" ]; then
        log "检测到Live Build环境: 存在Live环境变量"
        return 0
    fi
    
    return 1  # 不是Live环境返回1
}

is_chroot() {
    # 获取当前根目录的设备和inode标识
    current_root=$(stat -c "%d:%i" / 2>/dev/null)
    # 正确解析init进程的根目录（处理符号链接）
    init_root=$(stat -c "%d:%i" /proc/1/root/. 2>/dev/null)

    # 比较标识符
    if [ -z "$init_root" ]; then
        log "无法访问/proc/1/root，可能不在Linux系统或权限不足"
        return 0  # 无法确定，保守返回chroot
    fi

    if [ "$current_root" != "$init_root" ]; then
        log "检测到chroot环境: 当前根目录标识($current_root) != 系统根目录标识($init_root)"
        return 0  # 是chroot环境返回0
    fi
    
    return 1  # 不是chroot环境返回1
}

# 判断是否为 Live CD 环境的函数（POSIX 兼容）
is_live_cd() {
    # 检查内核参数中是否包含 boot=casper
    if grep -q "boot=casper" /proc/cmdline 2>/dev/null; then
        log "检测到Live CD环境: 内核参数包含boot=casper"
        return 0  # 是Live CD环境返回0
    fi

    return 1  # 不是Live CD环境返回1
}

# 判断是否在 unshare -m 创建的挂载命名空间中（POSIX 兼容）
is_unshare_mount_ns() {
    # 检查当前进程的挂载命名空间和init进程的挂载命名空间是否不同
    # 如果不同，说明在 unshare -m 创建的命名空间中
    if [ ! -e "/proc/self/ns/mnt" ] || [ ! -e "/proc/1/ns/mnt" ]; then
        # 无法访问命名空间信息，保守返回非unshare环境
        return 1
    fi
    
    # 比较命名空间inode，如果不同则说明在不同的命名空间中
    current_mnt_ns=$(readlink /proc/self/ns/mnt 2>/dev/null)
    init_mnt_ns=$(readlink /proc/1/ns/mnt 2>/dev/null)
    
    if [ -z "$current_mnt_ns" ] || [ -z "$init_mnt_ns" ]; then
        # 无法读取命名空间信息，保守返回非unshare环境
        return 1
    fi
    
    if [ "$current_mnt_ns" != "$init_mnt_ns" ]; then
        log "检测到unshare -m挂载命名空间: 当前命名空间($current_mnt_ns) != init命名空间($init_mnt_ns)"
        return 0  # 是unshare -m命名空间返回0
    fi
    
    return 1  # 不是unshare -m命名空间返回1
}

is_normal_mode() {
    boot_mode=$(gdbus call --system \
        -d com.kylin.MaintainMode \
        -o /com/kylin/MaintainMode/Object \
        -m com.kylin.MaintainMode.interface.GetBootMode | awk -F\' '{print $2}')

    if [ "$boot_mode" = "normal" ]; then
        log "检测到normal模式"
        return 0  # 是normal模式返回0
    fi
    
    log "当前不是normal模式: $boot_mode"
    return 1  # 不是normal模式返回1
}

# 检查是否应该执行操作
should_execute_operation() {
    # 如果在 unshare -m 命名空间中，允许操作继续（不阻塞）
    if is_unshare_mount_ns; then
        log "检测到unshare -m命名空间，允许操作继续"
        return 1  # 返回1表示不满足拦截条件，允许操作
    fi
    
    # 如果不是Live Build环境 且 不是chroot环境 且 不是Live CD环境 且 是normal模式
    if ! is_live_build && ! is_chroot && ! is_live_cd && is_normal_mode; then
        log "满足所有条件: 非Live Build、非chroot、非Live CD、normal模式"
        return 0  # 应该执行操作
    fi
    
    # 记录不满足的具体条件
    if is_live_build; then
        log "不满足条件: 当前是Live Build环境"
    fi
    
    if is_chroot; then
        log "不满足条件: 当前是chroot环境"
    fi
    
    if is_live_cd; then
        log "不满足条件: 当前是Live CD环境"
    fi
    
    if ! is_normal_mode; then
        log "不满足条件: 当前不是normal模式"
    fi
    
    return 1  # 不应该执行操作
}

# 主逻辑
operation=$(detect_operation "$@")
log "检测到操作: $operation, 参数: $*"

# 只有在非live-build且非chroot且是normal模式时才执行操作拦截
if should_execute_operation; then
    # 需要阻止的操作类型
    case "$operation" in
        install|remove|purge|reinstall|autoremove|unpack|configure)
            log "**当前模式禁止执行（$operation）操作**"
            echo "\033[31m ** 当前模式禁止执行（$operation）操作** \033[0m" >&2
            exit 1
            ;;
        *)
            log "允许操作: $operation"
            exit 0
            ;;
    esac
else
    log "不满足拦截条件，允许操作继续"
    exit 0
fi