Skip to content
Merged

v2.1 #10

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 76 additions & 55 deletions module_files/post-fs-data.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/system/bin/sh
# OneUI CSC Features - Refactored post-fs-data.sh
# OneUI CSC Features

MODDIR=${0%/*}
LOG_FILE="$MODDIR/log.txt"
CONFIG_PATH="/data/adb/csc_config"
ARCH=$(getprop ro.product.cpu.abi)
CSC=$(getprop ro.boot.sales_code)
TOOL="$MODDIR/libs/$ARCH/csc_tool"
HASH_DIR="$MODDIR/hashes"

# ===== Debug 开关 =====
DEBUG=0 # 0=关闭 1=开启
Expand All @@ -19,62 +20,67 @@ log() {
echo "$1" >&2
}

# Debug 日志
debug() {
[ "$DEBUG" = "1" ] && log "[DEBUG] $1"
}

# 每次启动重新生成日志
prepare_log() {
: > "$LOG_FILE"
mkdir -p "$HASH_DIR"
log "=== 模块启动: CSC=$CSC, ARCH=$ARCH, DEBUG=$DEBUG ==="
}

# 动态寻找文件路径
# 动态寻找原始文件路径
find_file() {
local filename=$1
local base="/optics/configs/carriers/$CSC"

debug "查找文件: $filename (base=$base)"

local path=$(find "$base" -name "$filename" 2>/dev/null | head -n 1)

if [ -f "$path" ]; then
debug "找到文件: $path"
echo "$path"
return 0
fi

debug "未找到文件: $filename"
return 1
}

# 安全挂载函数
safe_mount() {
local src=$1
local target=$2

debug "准备挂载: $src -> $target"
# 计算文件联合 Hash
# 参数: 传入需要纳入校验的多个文件路径
calc_hash() {
# 将存在的文件内容合并后计算 md5
cat "$@" 2>/dev/null | md5sum | awk '{print $1}'
}

if [ ! -f "$src" ] || [ ! -f "$target" ]; then
log "错误: 挂载源或目标不存在 ($src -> $target)"
return 1
fi
# 部署文件以供 Magisk/KSU 原生 OverlayFS/Magic Mount 挂载
deploy_for_mount() {
local src_file=$1
local origin_path=$2

umount -l "$target" >/dev/null 2>&1
mount --bind "$src" "$target"
# 路径标准化: 如果是 /etc 开头,转为 /system/etc,确保 Magisk/KSU 正确识别挂载点
local target_path="$origin_path"
case "$target_path" in
/etc/*) target_path="/system$target_path" ;;
esac

local ret=$?

if [ $ret -eq 0 ]; then
log "成功挂载: $target"
debug "mount 返回值: $ret"
return 0
else
log "失败: 无法挂载 $target"
debug "mount 返回值: $ret"
return 1
local module_target_path="$MODDIR$target_path"

debug "准备部署挂载点: $module_target_path"

# 创建对应的目录树
mkdir -p "$(dirname "$module_target_path")"

# 复制文件到模块对应目录,KSU/Magisk 会在稍后自动 OverlayFS 挂载它
cp -f "$src_file" "$module_target_path"

# 同步 SELinux 上下文
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: 当所选的 origin 路径不存在时,SELinux 上下文复制可能会静默失败。

deploy_for_mount 中,调用者可能会传入一个“合成”的 origin_path(例如 "/system$origin_path"),这个路径可能尚不存在,因此该检查会直接跳过上下文复制,让覆盖层文件保持默认的 SELinux 上下文。如果你确实需要镜像原始文件的 SELinux 上下文,建议使用一个一定存在的路径作为 ls -Z 的来源(例如真实的原始文件路径或某个规范化路径);或者当 $origin_path 不存在时,退回到对 "$module_target_path" 调用 restorecon,而不是什么也不做。

Suggested change
# 同步 SELinux 上下文
# 同步 SELinux 上下文
# 优先从真实存在的 origin_path 复制 SELinux 上下文;
# 若 origin_path 不存在或无法获取上下文,则回退为对目标执行 restorecon。
if [ -n "$origin_path" ] && [ -e "$origin_path" ]; then
local ctx
ctx=$(ls -Z "$origin_path" 2>/dev/null | awk '{print $1}')
if [ -n "$ctx" ]; then
chcon "$ctx" "$module_target_path" 2>/dev/null || {
# chcon 失败时回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
}
else
# 未能解析出上下文,直接回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
fi
else
# origin_path 不存在或为空时,不再静默跳过,改为回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
fi
Original comment in English

suggestion: SELinux context copy may fail silently when the chosen origin path does not exist.

In deploy_for_mount, callers may pass a synthetic origin_path (e.g. "/system$origin_path") that doesn’t exist yet, so this check just skips context copy and leaves the overlay with a default context. If you need to mirror the original file’s SELinux context, consider using a path that’s guaranteed to exist as the ls -Z source (e.g. the real origin file or a canonical path), or falling back to restorecon "$module_target_path" when $origin_path is missing instead of doing nothing.

Suggested change
# 同步 SELinux 上下文
# 同步 SELinux 上下文
# 优先从真实存在的 origin_path 复制 SELinux 上下文;
# 若 origin_path 不存在或无法获取上下文,则回退为对目标执行 restorecon。
if [ -n "$origin_path" ] && [ -e "$origin_path" ]; then
local ctx
ctx=$(ls -Z "$origin_path" 2>/dev/null | awk '{print $1}')
if [ -n "$ctx" ]; then
chcon "$ctx" "$module_target_path" 2>/dev/null || {
# chcon 失败时回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
}
else
# 未能解析出上下文,直接回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
fi
else
# origin_path 不存在或为空时,不再静默跳过,改为回退 restorecon(若可用)
if command -v restorecon >/dev/null 2>&1; then
restorecon "$module_target_path" 2>/dev/null
fi
fi

if [ -f "$origin_path" ]; then
local ctx=$(ls -Z "$origin_path" | awk '{print $1}')
[ -n "$ctx" ] && chcon "$ctx" "$module_target_path"
fi

log "成功部署待挂载文件: $target_path"
}

# 处理单个文件逻辑
Expand All @@ -92,9 +98,13 @@ process_feature_file() {
local decoded_file="$MODDIR/decoded_$label"
local patched_file="$MODDIR/patched_$label"
local final_file="$MODDIR/final_$label"
local user_config="$CONFIG_PATH/$config_name"

if [ -z "$origin_path" ]; then
if [ "$label" = "ff" ] && [ -f "/etc/floating_feature.xml" ]; then
if [ "$label" = "ff" ] && [ -f "/system/etc/floating_feature.xml" ]; then
origin_path="/system/etc/floating_feature.xml"
debug "使用 fallback floating_feature: $origin_path"
elif [ "$label" = "ff" ] && [ -f "/etc/floating_feature.xml" ]; then
origin_path="/etc/floating_feature.xml"
debug "使用 fallback floating_feature: $origin_path"
else
Expand All @@ -103,35 +113,47 @@ process_feature_file() {
fi
fi

debug "origin_path=$origin_path"
# --- 增量更新与 Hash 校验逻辑 ---
local hash_file="$HASH_DIR/$label.md5"
local current_hash=$(calc_hash "$origin_path" "$user_config" "$TOOL")
local old_hash=""
[ -f "$hash_file" ] && old_hash=$(cat "$hash_file")

# 检查标准化后的部署路径是否存在文件
local check_path="$origin_path"
case "$check_path" in
/etc/*) check_path="/system$check_path" ;;
esac

if [ "$current_hash" = "$old_hash" ] && [ -f "$MODDIR$check_path" ]; then
Comment on lines +123 to +128
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 基于 Hash 的“短路”逻辑使用的目标路径与后续部署使用的目标路径不同,会导致不必要的重复处理。

在非 ff 流程中,你最终部署到 /system$origin_path,但 Hash 短路逻辑检查的是 $MODDIR$origin_path(只有 /etc/* 会加上 /system 前缀)。对于非 /etc 路径,这会保证 -f 检查必然失败,从而在 Hash 相同的情况下仍然强制重复处理。请考虑:(a)让 check_path 与最终 deploy_for_mount 的目标路径保持一致,或者(b)把“目标路径计算”抽取成一个共享的辅助函数,供 Hash 检查和部署逻辑共同使用。

Original comment in English

issue (bug_risk): Hash-based short‑circuit uses a different target path than the later deployment, causing unnecessary reprocessing.

In non-ff flows you deploy to /system$origin_path, but the hash short‑circuit probes $MODDIR$origin_path (only /etc/* gets the /system prefix). For non-/etc paths this guarantees the -f check fails and forces reprocessing even when hashes match. Please either (a) make check_path match the final deploy_for_mount target, or (b) factor target-path computation into a shared helper used by both the hash check and deployment.

log "增量更新校验通过: $label 无变动,跳过处理。"
return
fi

log "检测到 $label 变动或首次运行,开始处理..."
# -------------------------------

# ========================
# floating_feature 特殊逻辑
# floating_feature 特殊逻辑 (明文模式)
# ========================
if [ "$label" = "ff" ]; then

debug "floating_feature 走明文模式"

cp "$origin_path" "$decoded_file"

local user_config="$CONFIG_PATH/$config_name"
cp -f "$origin_path" "$decoded_file"

if [ -f "$user_config" ]; then
debug "执行 patch (ff)"
$TOOL --patch "$decoded_file" "$user_config" "$patched_file" >> "$LOG_FILE" 2>&1
else
log "注意: 未找到用户配置 $config_name,将保持原始状态"
cp "$decoded_file" "$patched_file"
cp -f "$decoded_file" "$patched_file"
fi

if [ -f "$patched_file" ]; then
debug "挂载明文 floating_feature"
safe_mount "$patched_file" "$origin_path"
restorecon "$origin_path"
deploy_for_mount "$patched_file" "$origin_path"
echo "$current_hash" > "$hash_file" # 记录 Hash
else
log "错误: patch 失败 ($label)"
fi

return
fi

Expand All @@ -141,7 +163,6 @@ process_feature_file() {

# 2. 解码
debug "执行 decode: $TOOL --decode $origin_path $decoded_file"

$TOOL --decode "$origin_path" "$decoded_file" >> "$LOG_FILE" 2>&1

if [ ! -f "$decoded_file" ]; then
Expand All @@ -150,31 +171,29 @@ process_feature_file() {
fi

# 3. Patch
local user_config="$CONFIG_PATH/$config_name"

debug "user_config=$user_config"

if [ -f "$user_config" ]; then
debug "执行 patch"
$TOOL --patch "$decoded_file" "$user_config" "$patched_file" >> "$LOG_FILE" 2>&1
else
log "注意: 未找到用户配置 $config_name,将保持原始状态"
cp "$decoded_file" "$patched_file"
cp -f "$decoded_file" "$patched_file"
fi

# 4. Encode
debug "执行 encode"
$TOOL --encode "$patched_file" "$final_file" >> "$LOG_FILE" 2>&1

# 5. 挂载
# 5. 部署挂载
if [ -f "$final_file" ]; then
debug "使用加密文件挂载"
safe_mount "$final_file" "$origin_path"
restorecon "$origin_path"
debug "部署加密文件以供挂载"
deploy_for_mount "$final_file" "/system$origin_path"
echo "$current_hash" > "$hash_file" # 记录 Hash
else
log "注意: 加密失败,尝试挂载明文文件"
safe_mount "$patched_file" "$origin_path"
restorecon "$origin_path"
log "注意: 加密失败,尝试部署明文文件"
deploy_for_mount "$patched_file" "/system$origin_path"
Comment on lines +190 to +194
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 在这里使用 "/system$origin_path" 很可能会生成错误的覆盖目标路径。

在这个分支中,origin_path 已经是真实的源路径(例如 /optics/configs/...),之前也被直接作为挂载目标使用。把调用改成 deploy_for_mount "$final_file" "/system$origin_path" 会把路径重写为 /system/optics/...,这是另一个位置,可能会导致覆盖层无法作用于真正的配置文件。同时也把 /etc -> /system/etc 的细节泄露到了调用方。请传递真实的目标路径(例如 origin_path 或其规范化结果),并把所有 /system 相关的规范化逻辑都保留在 deploy_for_mount 内部。

Original comment in English

issue (bug_risk): Using "/system$origin_path" here likely produces an incorrect overlay target path.

In this branch, origin_path is already the real source path (e.g. /optics/configs/...) and was previously used directly as the mount target. Changing the call to deploy_for_mount "$final_file" "/system$origin_path" rewrites that to /system/optics/..., which is a different location and may prevent the overlay from affecting the actual config file. It also spreads /etc -> /system/etc concerns into the caller. Please pass the real target path (e.g. origin_path or a canonicalized variant) and keep any /system normalization inside deploy_for_mount.

# 即使失败使用明文,依然保存Hash,避免每次重启重复失败操作
echo "$current_hash" > "$hash_file"
fi
}

Expand All @@ -191,8 +210,10 @@ if [ ! -f "$TOOL" ]; then
exit 1
fi

chmod +x "$TOOL"

process_feature_file "csc" "cscfeature.xml" "csc.json"
process_feature_file "carrier" "customer_carrier_feature.json" "carrier.json"
process_feature_file "ff" "floating_feature.xml" "ff.json"

log "=== 处理完成 ==="
log "=== 脚本执行完毕,等待系统 OverlayFS 挂载 ==="
2 changes: 1 addition & 1 deletion module_files/service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
settings put system aiprel_switch_status 1

# 理论上来说开启了这个可以开启 lab 菜单,本来以为可以一次性秒杀 应用程序状态恢复 和 智能启动应用程序
# 结果 应用程序状态恢复 还受其他影响,一路反编译到,弄到 iaft 后弄不动了,等个大神搞吧((
# 结果 应用程序状态恢复 还受其他影响,一路反编译到,弄到 iaft 后弄不动了,等个大神搞吧((