diff --git a/tools/tools.sh b/tools/tools.sh index 595b601..43f09fe 100644 --- a/tools/tools.sh +++ b/tools/tools.sh @@ -49,7 +49,11 @@ user="$user" #1包含數據+安裝包,0僅包安裝包 #此選項設置1時Backup_obb_data,Backup_user_data,blacklist_mode將可設置 0時Backup_user_data,Backup_obb_data,blacklist_mode選項不生效 #此外設置0時將同時忽略appList.txt的!與任何黑名單設置(包括黑名單列表) -Backup_Mode=1 +Backup_Mode="${Backup_Mode:-1}" + +#執行生成應用列表.sh時輸出用於recovery救援的卡刷包? +#1輸出 0不輸出 +recovery_flash="${recovery_flash:-0}" #是否備份使用者數據 (1備份 0不備份 留空強制選擇) Backup_user_data="${Backup_user_data:-1}" @@ -186,10 +190,6 @@ if [[ ! -d $tools_path ]]; then tools_path="${MODDIR%/*}/tools" [[ ! -d $tools_path ]] && echo "$tools_path二進制目錄遺失" && EXIT="true" fi -[[ ! -f $tools_path/zstd ]] && echo "$tools_path/zstd遺失" -[[ ! -f $tools_path/tar ]] && echo "$tools_path/tar遺失" -[[ ! -f $tools_path/classes.dex ]] && echo "$tools_path/classes.dex遺失" -[[ ! -f $tools_path/classes2.dex ]] && echo "$tools_path/classes2.dex遺失" if [[ ! -f $conf_path ]]; then case $operate in backup_media|backup|Getlist|Restore|Restore2|check_file|convert|Restore3|dumpname) @@ -208,6 +208,18 @@ if [[ ! -f $conf_path ]]; then fi [[ ! -f $conf_path ]] && echo "$conf_path遺失" && exit 2 . "$conf_path" &>/dev/null +case $operate in +backup_media|backup|Getlist|Restore|Restore2|check_file|convert|Restore3|dumpname) + if [[ $conf_path != *Backup_* ]]; then + update_backup_settings_conf>"$conf_path" + else + if [[ $conf_path = *Backup_* ]]; then + update_Restore_settings_conf>"$conf_path" + else + echo "$conf_path配置遺失" && exit 1 + fi + fi ;; +esac if [[ $Shell_LANG != "" ]]; then case $Shell_LANG in 1) LANG="CN" ;; @@ -269,17 +281,15 @@ busybox2="$tools_path/busybox" exclude=" update soc.json -busybox_path +update-binary +classes2.dex +classes.dex +notification.dex Device_List" if [[ ! -d $filepath ]]; then mkdir -p "$filepath" [[ $? = 0 ]] && echoRgb "設置busybox環境中" fi -[[ ! -f $tools_path/busybox_path ]] && touch "$tools_path/busybox_path" -if [[ $filepath != $(cat "$tools_path/busybox_path") ]]; then - [[ -d $(cat "$tools_path/busybox_path") ]] && rm -rf "$(cat "$tools_path/busybox_path")" - echoRgb "$filepath" >"$tools_path/busybox_path" -fi #刪除無效軟連結 find -L "$filepath" -maxdepth 1 -type l -exec rm -rf {} \; if [[ -f $busybox && -f $busybox2 ]]; then @@ -309,7 +319,7 @@ find "$tools_path" -maxdepth 1 ! -path "$tools_path/tools.sh" -type f | egrep -v done if [[ -f $busybox ]]; then "$busybox" --list | while read; do - if [[ $REPLY != tar && ! -f $filepath/$REPLY ]]; then + if [[ $REPLY != tar && $REPLY != bc && ! -f $filepath/$REPLY ]]; then ln -fs "$busybox" "$filepath/$REPLY" fi done @@ -318,15 +328,40 @@ fi export PATH="$filepath:$PATH" export TZ=Asia/Taipei export CLASSPATH="$tools_path/classes.dex:$tools_path/classes2.dex:$tools_path/notification.dex" -zstd_sha256sum="55cc57a3d079dd90e74d972c705c4f9389dd00a7175de148e21000eab01f7ed9" -tar_sha256sum="3c605b1e9eb8283555225dcad4a3bf1777ae39c5f19a2c8b8943140fd7555814" -classesdex_sha256sum="09d0058763157b97d6ea2bf74bd7ec53089a9ddb496f089a159ea0027007bb94" -classesdex2_sha256sum="e78b33af047464c225b171da0da3e46fb2932b798ff4cd26de75a1649b5e30d5" -[[ $(sha256sum "$tools_path/zstd" | cut -d" " -f1) != $zstd_sha256sum ]] && echoRgb "zstd效驗失敗" "0" && exit 2 -#[[ $(sha256sum "$tools_path/tar" | cut -d" " -f1) != $tar_sha256sum ]] && echoRgb "tar效驗失敗" "0" && exit 2 -[[ $(sha256sum "$tools_path/classes.dex" | cut -d" " -f1) != $classesdex_sha256sum ]] && echoRgb "classes.dex效驗失敗" "0" && exit 2 -[[ $(sha256sum "$tools_path/classes2.dex" | cut -d" " -f1) != $classesdex2_sha256sum ]] && echoRgb "classes2.dex效驗失敗" "0" && exit 2 +quit=0 +while read -r file expected_hash; do + if [[ -f $tools_path/$file ]]; then + computed_hash="$(sha256sum "$tools_path/$file" | awk '{print $1}')" + if [[ $computed_hash = $expected_hash ]]; then + echoRgb "✅ $file: 驗證通過" + else + echoRgb "❌ $tools_path/$file: SHA-256 不一致" + quit=2 + break + fi + else + echoRgb "⚠️ 檔案 $tools_path/$file 不存在" + quit=1 + break + fi +done <<< "$(cat </dev/null | head -1)" -if [[ $zipFile2 != "" ]]; then - starttime1="$(date -u "+%s")" - PayloadDumper -a -o "$MODDIR/ROM" "$zipFile2" - endtime 1 - exit -fi - if [[ $(unzip -l "$zipFile" 2>/dev/null | awk '{print $4}' | egrep -wo "^backup_settings.conf$") != "" ]]; then update_script else @@ -1173,7 +1199,7 @@ Backup_data() { esac if [[ -d $data_path ]]; then unset Filesize ssaid Get_Permissions result Permissions - Filesize="$(find "$data_path" -type f -printf "%s\n" | awk '{s+=$1} END {print s}')" + Filesize="$(find "$data_path" -type f -printf "%s\n" 2>/dev/null | awk '{s+=$1} END {print s}')" [[ $Filesize != "" ]] && { if [[ $Size != $Filesize ]]; then case $1 in @@ -1212,8 +1238,8 @@ Backup_data() { ;; *) case $Compression_method in - tar | Tar | TAR) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf "$Backup_folder/$1.tar" -C "${data_path%/*}" "${data_path##*/}" ;; - zstd | Zstd | ZSTD) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf - -C "${data_path%/*}" "${data_path##*/}" | zstd --ultra -3 -T0 -q --priority=rt >"$Backup_folder/$1.tar.zst" ;; + tar | Tar | TAR) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}/QQS" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf "$Backup_folder/$1.tar" -C "${data_path%/*}" "${data_path##*/}" ;; + zstd | Zstd | ZSTD) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}/QQS" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf - -C "${data_path%/*}" "${data_path##*/}" | zstd --ultra -3 -T0 -q --priority=rt >"$Backup_folder/$1.tar.zst" ;; esac ;; esac @@ -1494,7 +1520,7 @@ get_name(){ } }" echo "{\n}">"$Folder/app_details.json" - jq --argjson new_content "$extra_content" '. += $new_content' "$Folder/app_details.json" > temp.json && cp temp.json "$Folder/app_details.json" && rm -rf temp.json + jq --argjson new_content "$extra_content" '. += $new_content' "$Folder/app_details.json" > temp.json && cp temp.json "$Folder/app_details.json" && rm -rf temp.json "$Folder/app_details" fi fi [[ ! -f $txt ]] && echo "#不需要恢復還原的應用請在開頭使用#注釋 比如:#酷安 com.coolapk.market" >"$txt" @@ -1887,7 +1913,7 @@ backup) [[ ! -f $Backup/恢復備份.sh ]] && touch_shell "Restore" "$Backup/恢復備份.sh" [[ ! -f $Backup/終止腳本.sh ]] && cp -r "$MODDIR/終止腳本.sh" "$Backup/終止腳本.sh" [[ ! -f $Backup/重新生成應用列表.sh ]] && touch_shell "dumpname" "$Backup/重新生成應用列表.sh" - [[ ! -f $Backup/轉換資料夾名稱.sh ]] && touch_shell "convert" "$Backup/轉換資料夾名稱.sh" + [[ ! -f $Backup/轉換資料夾名稱.sh ]] && touch_shell "convert" "$Backup/轉換資料夾名稱.sh" [[ ! -f $Backup/壓縮檔完整性檢查.sh ]] && touch_shell "check_file" "$Backup/壓縮檔完整性檢查.sh" [[ ! -d $Backup/modules ]] && mkdir -p "$Backup/modules" && echoRgb "$Backup/modules已創建成功\n -請按需要自行放置需要恢復時刷入的模塊在內將自動批量刷入" "1" [[ -d $Backup/Media ]] && touch_shell "Restore3" "$Backup/恢復自定義資料夾.sh" @@ -2486,6 +2512,10 @@ Getlist) [[ $blacklist_mode != "" ]] && isBoolean "$blacklist_mode" "blacklist_mode" && blacklist_mode="$nsx" || { echoRgb "選擇黑名單模式\n -音量上不輸出,音量下輸出應用列表" "2" get_version "不輸出" "輸出應用列表" && blacklist_mode="$branch" + } + [[ $recovery_flash != "" ]] && isBoolean "$recovery_flash" "recovery_flash" && recovery_flash="$nsx" || { + echoRgb "輸出用於recovery救援的卡刷包?\n -音量上輸出,音量下不輸出" "2" + get_version "輸出" "不輸出" && recovery_flash="$branch" } ;; 1) if [[ $(echo "$blacklist" | egrep -v '#|#' | wc -l) -gt 0 ]]; then @@ -2493,12 +2523,21 @@ Getlist) echoRgb "選擇黑名單模式\n -音量上不輸出,音量下輸出應用列表" "2" get_version "不輸出" "輸出應用列表" && blacklist_mode="$branch" } || isBoolean "$blacklist_mode" "blacklist_mode" && blacklist_mode="$nsx" - fi ;; + fi + [[ $recovery_flash = "" ]] && { + echoRgb "輸出用於recovery救援的卡刷包?\n -音量上輸出,音量下不輸出" "2" + get_version "輸出" "不輸出" && recovery_flash="$branch" + } || isBoolean "$recovery_flash" "recovery_flash" && recovery_flash="$nsx" ;; 2) [[ $blacklist_mode = "" ]] && { Enter_options "選擇黑名單模式輸入1不輸出,輸入0輸出應用列表" "不輸出" "輸出應用列表" && isBoolean "$parameter" "blacklist_mode" && blacklist_mode="$nsx" } || { isBoolean "$blacklist_mode" "blacklist_mode" && blacklist_mode="$nsx" + } + [[ $recovery_flash = "" ]] && { + Enter_options "填寫1輸出用於recovery救援的卡刷包,填寫0不輸出" "輸出" "不輸出" && isBoolean "$parameter" "recovery_flash" && recovery_flash="$nsx" + } || { + isBoolean "$recovery_flash" "recovery_flash" && recovery_flash="$nsx" } ;; *) echoRgb "$conf_path Lo=$Lo填寫錯誤,正確值0 1 2" "0" && exit 2 ;; esac @@ -2608,6 +2647,7 @@ Getlist) let rgb_a++ LR++ done if [[ -f $nametxt ]]; then + rm -rf "$TMPDIR"/* while read -r ; do if [[ $(echo "$REPLY" | sed -E 's/^[ \t]*//; /^[ \t]*[##!]/d') != "" ]]; then app=($REPLY $REPLY) @@ -2615,6 +2655,12 @@ Getlist) if [[ $(echo "$Apk_info2" | egrep -o "${app[1]}") != "" ]]; then [[ $Tmplist = "" ]] && Tmplist='#不需要備份的應用請在開頭使用#注釋 比如:#酷安 com.coolapk.market(忽略安裝包和數據\n#不需要備份數據的應用請在開頭使用!注釋 比如:!酷安 com.coolapk.market(僅忽略數據)' Tmplist="$Tmplist\n$REPLY" + [[ $recovery_flash = true ]] && { + apk_path="$(pm path --user "$user" "${app[1]}" 2>/dev/null | cut -f2 -d ':')" + apk_path2="$(echo "$apk_path" | head -1)" + apk_path2="${apk_path2%/*}" + echo "${app[2]} ${app[1]} $apk_path2" >>"$TMPDIR/appList.txt" + } else echoRgb "$REPLY不存在系統,從列表中刪除" "0" fi @@ -2624,6 +2670,26 @@ Getlist) fi done < "$nametxt" [[ $Tmplist != "" ]] && echo "$Tmplist" | sed -e '/^$/d' | sort>"$nametxt" + if [[ $recovery_flash = true ]]; then + if [[ -f $tools_path/update-binary && -f $TMPDIR/appList.txt ]]; then + echoRgb "輸出用於recovery的備份卡刷包" ; rm -rf "$MODDIR/recovery卡刷備份.zip" + touch_shell "Restore" "$TMPDIR/恢復備份.sh" + cp -r "$MODDIR/終止腳本.sh" "$TMPDIR/終止腳本.sh" + touch_shell "dumpname" "$TMPDIR/重新生成應用列表.sh" + touch_shell "convert" "$TMPDIR/轉換資料夾名稱.sh" + touch_shell "check_file" "$TMPDIR/壓縮檔完整性檢查.sh" + touch_shell "Restore2" "$TMPDIR/recover.sh" + touch_shell "Restore3" "$TMPDIR/恢復自定義資料夾.sh" + update_Restore_settings_conf>"$TMPDIR/restore_settings.conf" + mkdir -p "$TMPDIR/META-INF/com/google/android" && cp "$tools_path/update-binary" "$TMPDIR/META-INF/com/google/android" + tar -cpf - -C "${tools_path%/*}" "${tools_path##*/}" | tar --delete "tools/zip" | tar --recursive-unlink -xmpf - -C "$TMPDIR/" + (cd "$TMPDIR" && zip -r "recovery卡刷備份.zip" * -x 'scriptTMP') + echo_log "打包卡刷包" + [[ $result = 0 ]] && (mv "$TMPDIR/recovery卡刷備份.zip" "$MODDIR" && rm -rf "$TMPDIR"/* ; echoRgb "輸出:$MODDIR/recovery卡刷備份.zip" "2") + else + [[ ! -f $tools_path/update-binaryechoRgb ]] && echoRgb "update-binary卡刷腳本遺失" "0" || [[ ! -f $TMPDIR/appList.txt ]] && echoRgb "$TMPDIR/appList.txt 不存在" "0" + fi + fi fi wait endtime 1 @@ -2648,7 +2714,7 @@ backup_media) [[ ! -f $Backup/restore_settings.conf ]] && update_Restore_settings_conf>"$Backup/restore_settings.conf" app_details="$Backup_folder/app_details.json" [[ ! -f $app_details ]] && echo "{\n}">"$app_details" - filesize="$(find "$Backup_folder" -type f -printf "%s\n" | awk '{s+=$1} END {print s}')" + filesize="$(find "$Backup_folder" -type f -printf "%s\n" 2>/dev/null | awk '{s+=$1} END {print s}')" mediatxt="$Backup/mediaList.txt" [[ ! -f $mediatxt ]] && echo "#不需要恢復的資料夾請在開頭使用#注釋 比如:#Download" > "$mediatxt" echo "$script">"$TMPDIR/scriptTMP" diff --git a/tools/update-binary b/tools/update-binary new file mode 100644 index 0000000..3841658 --- /dev/null +++ b/tools/update-binary @@ -0,0 +1,334 @@ +#!/sbin/sh +#初始化 +OUTFD="$2" +ZIPFILE="$3" +Compression_method="zstd" +#设置字符输出 +ui_print() { + echo "ui_print "$@"" > /proc/self/fd/$OUTFD +} +#设置工作目录 +MODDIR=/dev/backup +#安装二进制文件 +rm -rf "$MODDIR" +mkdir -p "$MODDIR" +unzip -o "$ZIPFILE" 'tools/tools.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/busybox' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/find' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/classes.dex' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/classes2.dex' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/tar' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/zstd' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/bc' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/jq' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/keycheck' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/Device_List' -d "$MODDIR" +unzip -o "$ZIPFILE" 'tools/soc.json' -d "$MODDIR" +unzip -o "$ZIPFILE" 'restore_settings.conf' -d "$MODDIR" +unzip -o "$ZIPFILE" '恢復自定義資料夾.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" '恢復備份.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" 'appList.txt' -d "$MODDIR" +unzip -o "$ZIPFILE" '重新生成應用列表.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" '終止腳本.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" '壓縮檔完整性檢查.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" '轉換資料夾名稱.sh' -d "$MODDIR" +unzip -o "$ZIPFILE" 'recover.sh' -d "$MODDIR" +chmod -R 0755 "$MODDIR/tools/" +busybox="$MODDIR/tools/busybox" +"$busybox" --list | while read; do + case $REPLY in + tar|bc|find) ;; + *) + ln -s "$busybox" "$MODDIR/tools/$REPLY" + ;; + esac +done +chmod -R 0755 "$MODDIR/tools/" +Set_back_0() { + return 0 +} +Set_back_1() { + return 1 +} +#设置环境 +export PATH="$MODDIR/tools:$PATH" +i=1 +txt="$MODDIR/appList.txt" +[[ ! -f $txt ]] && ui_print "$txt缺少" && exit 1 +r="$(egrep -v '#|#' "$txt" 2>/dev/null | awk 'NF != 0 { count++ } END { print count }')" +[[ $r = "" ]] && ui_print "爬..appList.txt是空的備份個鬼" && exit 0 +path="/data/media/0/Android" +path2="/data/data" +path3="/data/user_de/0" +data="/data" +ui_print "$(df -h "$data")" +ui_print "$(df -h "$data" | awk 'END{print "剩餘:"$4"使用率:"$5}')" +Backup="/data/media/0/Backup_$Compression_method" +[[ ! -d $Backup ]] && mkdir -p "$Backup" || rm -rf "$Backup"/* +echo "#不需要恢復還原的應用請在開頭注釋# 比如#xxxxxxxx 酷安" >"$Backup/appList.txt" +cp -r "$MODDIR/tools" "$Backup" +cp -r "$MODDIR/轉換資料夾名稱.sh" "$Backup/" +cp -r "$MODDIR/restore_settings.conf" "$Backup/" +cp -r "$MODDIR/壓縮檔完整性檢查.sh" "$Backup/" +cp -r "$MODDIR/終止腳本.sh" "$Backup/" +cp -r "$MODDIR/重新生成應用列表.sh" "$Backup/" +cp -r "$MODDIR/恢復備份.sh" "$Backup/" +cp -r "$MODDIR/恢復自定義資料夾.sh" "$Backup/" +filesize="$(du -ks "$Backup" | awk '{print $1}')" +#調用二進制 +Quantity=0 +#顯示執行結果 +echo_log() { + if [[ $? = 0 ]]; then + ui_print "$1成功" && result=0 + else + ui_print "$1備份失敗,過世了" && result=1 + fi +} +size() { + local b_size get_size + varr="$(echo "$1" | bc 2>/dev/null)" + if [[ $varr != $1 ]]; then + b_size="$(ls -l "$1" 2>/dev/null | awk '{print $5}')" + else + b_size="$1" + fi + if [[ $b_size -eq 0 ]]; then + get_size="0 bytes" + elif [[ $(echo "$b_size < 1024" | bc) -eq 1 ]]; then + get_size="${b_size} bytes" + elif [[ $(echo "$b_size < 1048576" | bc) -eq 1 ]]; then + get_size="$(echo "scale=2; $b_size / 1024" | bc) KB" + elif [[ $(echo "$b_size < 1073741824" | bc) -eq 1 ]]; then + get_size="$(echo "scale=2; $b_size / 1048576" | bc) MB" + else + get_size="$(echo "scale=2; $b_size / 1073741824" | bc) GB" + fi + ui_print "$get_size" +} +Validation_file() { + MODDIR_NAME="${1%/*}" + MODDIR_NAME="${MODDIR_NAME##*/}" + FILE_NAME="${1##*/}" + ui_print "效驗$FILE_NAME" + case ${FILE_NAME##*.} in + zst) zstd -t "$1" 2>/dev/null ;; + tar) tar -tf "$1" &>/dev/null ;; + esac + echo_log "效驗" "效驗壓縮檔" +} +#檢測apk狀態進行備份 +Backup_apk() { + #創建APP備份文件夾 + [[ ! -d $Backup_folder ]] && mkdir -p "$Backup_folder" + echo "{\n}">"$app_details" + #備份apk + ui_print "$1" + rm -rf "$Backup_folder"/*.apk + [[ $(cat "$Backup/appList.txt" | grep -v "#" | sed -e '/^$/d' | awk '{print $2}' | grep -w "^${name2}$" | head -1) = "" ]] && echo "$name1 $name2" >>"$Backup/appList.txt" + unset Filesize + Filesize="$(find "$apk_path" -type f -printf "%s\n" | awk '{s+=$1} END {print s}')" + [[ $lxj -ge 95 ]] && ui_print "$data空間不足,達到$lxj%" && exit 2 + ( + cd "$apk_path" + case $Compression_method in + zstd | Zstd | ZSTD) tar --checkpoint-action="ttyout=%T\r" -cf - *.apk | zstd --ultra -3 -T0 -q --priority=rt >"$Backup_folder/apk.tar.zst" ;; + esac + ) + echo_log "備份$apk_number個Apk" + if [[ $result = 0 ]]; then + ui_print "新增app_details.json" + extra_content="{ + \"$name1\": { + \"PackageName\": \"$name2\" + } + }" + jq --argjson new_content "$extra_content" '. += $new_content' "$app_details" > temp.json && cp temp.json "$app_details" && rm -rf temp.json + cp -r "$MODDIR/recover.sh" "$Backup_folder/" + fi + if [[ $name2 = com.android.chrome ]]; then + #刪除所有舊apk ,保留一個最新apk進行備份 + ReservedNum=1 + FileNum="$(ls /data/app/*/com.google.android.trichromelibrary_*/base.apk 2>/dev/null | wc -l)" + while [[ $FileNum -gt $ReservedNum ]]; do + OldFile="$(ls -rt /data/app/*/com.google.android.trichromelibrary_*/base.apk 2>/dev/null | head -1)" + ui_print "刪除文件:${OldFile%/*/*}" + rm -rf "${OldFile%/*/*}" + let "FileNum--" + done + [[ -f $(ls /data/app/*/com.google.android.trichromelibrary_*/base.apk 2>/dev/null) && $(ls /data/app/*/com.google.android.trichromelibrary_*/base.apk 2>/dev/null | wc -l) = 1 ]] && cp -r "$(ls /data/app/*/com.google.android.trichromelibrary_*/base.apk 2>/dev/null)" "$Backup_folder/nmsl.apk" + fi + [[ $name2 = bin.mt.plus && -f $apk_path/base.apk && ! -f $Backup/$name1.apk ]] && cp -r "$apk_path/base.apk" "$Backup/$name1.apk" + unset PackageName ChineseName ; D=1 +} +#檢測數據位置進行備份 +Backup_data() { + unset zsize + case $1 in + user) data_path="$path2/$name2" ;; + data) data_path="$path/$1/$name2" ;; + obb) data_path="$path/$1/$name2" ;; + user_de) data_path="$path3/$name2" ;; + *) + data_path="$2" + if [[ $1 != storage-isolation && $1 != thanox ]]; then + Compression_method1="$Compression_method" + Compression_method=tar + fi + zsize=1 + zmediapath=1 + ;; + esac + if [[ -d $data_path ]]; then + [[ $lxj -ge 95 ]] && ui_print "$data空間不足,達到$lxj%" && exit 2 + unset Filesize + Filesize="$(find "$data_path" -type f -printf "%s\n" 2>/dev/null | awk '{s+=$1} END {print s}')" + [[ $Filesize != "" ]] && { + ui_print "備份$1數據" + # 判斷是否超過指定大小 + if [[ $Filesize2 != *"bytes"* ]]; then + if [[ $Filesize2 = *"KB"* ]]; then + if [[ $(echo "${Filesize2% KB}" | bc) > 1 ]]; then + Start_backup="true" + else + Start_backup="false" + fi + else + Start_backup="true" + fi + else + Start_backup="false" + fi + [[ $Start_backup = true ]] && { + case $1 in + user|user_de) + case $Compression_method in + zstd | Zstd | ZSTD) tar --checkpoint-action="ttyout=%T\r" --exclude="${data_path##*/}/.ota" --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}/lib" --exclude="${data_path##*/}/code_cache" --exclude="${data_path##*/}/no_backup" --warning=no-file-changed -cpf - -C "${data_path%/*}" "${data_path##*/}" | zstd --ultra -3 -T0 -q --priority=rt >"$Backup_folder/$1.tar.zst" 2>/dev/null ;; + esac + ;; + *) + case $Compression_method in + tar | Tar | TAR) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}/QQS" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf "$Backup_folder/$1.tar" -C "${data_path%/*}" "${data_path##*/}" ;; + zstd | Zstd | ZSTD) tar --checkpoint-action="ttyout=%T\r" --exclude="Backup_"* --exclude="${data_path##*/}/cache" --exclude="${data_path##*/}/QQS" --exclude="${data_path##*/}"/.* --warning=no-file-changed -cpf - -C "${data_path%/*}" "${data_path##*/}" | zstd --ultra -3 -T0 -q --priority=rt >"$Backup_folder/$1.tar.zst" ;; + esac + ;; + esac + } || { + ui_print "$1數據$Filesize2太小" && Set_back_1 + } + echo_log "備份$1數據" "備份" "$name1" + if [[ $result = 0 ]]; then + Validation_file "$Backup_folder/$1.tar"* + if [[ $result = 0 ]]; then + #[[ ${Backup_folder##*/} = Media ]] && [[ $(sed -e '/^$/d' "$mediatxt" | grep -w "${REPLY##*/}.tar$" | head -1) = "" ]] && echo "$FILE_NAME" >> "$mediatxt" + if [[ $zsize != "" ]]; then + extra_content="{ + \"$1\": { + \"path\": \"$2\", + \"Size\": \"$Filesize\" + } + }" + jq --argjson new_content "$extra_content" '. += $new_content' "$app_details" > temp.json && cp temp.json "$app_details" && rm -rf temp.json + else + extra_content="{ + \"$1\": { + \"Size\": \"$Filesize\" + } + }" + jq --argjson new_content "$extra_content" '. += $new_content' "$app_details" > temp.json && cp temp.json "$app_details" && rm -rf temp.json + fi + else + rm -rf "$Backup_folder/$1".tar.* + fi + fi + [[ $Compression_method1 != "" ]] && Compression_method="$Compression_method1" + unset Compression_method1 + } || ui_print "$1資料夾是空的" "0" + else + [[ -f $data_path ]] && ui_print "$1是一個文件 不支持備份" || ui_print "$1數據不存在跳過備份" + fi +} +endtime() { + #計算總體切換時長耗費 + case $1 in + 1) starttime="$starttime1" ;; + 2) starttime="$starttime2" ;; + esac + endtime="$(date -u "+%s")" + duration="$(echo "$((endtime - starttime))" | awk '{t=split("60 秒 60 分 24 時 999 天",a);for(n=1;n/dev/null | wc -l)" + if [[ $apk_number = 1 ]]; then + Backup_apk "非Split Apk" + else + Backup_apk "Split Apk支持備份" + fi + if [[ $D != "" && $result = 0 && $No_backupdata = "" ]]; then + #備份data數據 + Backup_data "data" + #備份obb數據 + Backup_data "obb" + #備份user數據 + Backup_data "user" + fi + endtime 2 "$name1備份" + lxj="$(echo "$Occupation_status" | awk '{print $3}' | sed 's/%//g')" + ui_print "完成$((i*100/r))% $hx$(df -h "$data" | awk 'END{print "剩餘:"$4"使用率:"$5}')" + else + ui_print "$name1[$name2]不在安裝列表,備份個寂寞?" + fi + ui_print " + " + let i++ +done +ui_print "批量備份完成" +filesizee="$(du -ks "$Backup" | awk '{print $1}')" +dsize="$(($((filesizee - filesize)) / 1024))" +ui_print "備份資料夾路徑:$Backup" +ui_print "備份資料夾總體大小$(du -ksh "$Backup" | awk '{print $1}')" +if [[ $dsize -gt 0 ]]; then + if [[ $((dsize / 1024)) -gt 0 ]]; then + ui_print "本次備份: $((dsize / 1024))gb" + else + ui_print "本次備份: ${dsize}mb" + fi +else + ui_print "本次備份: $(($((filesizee - filesize)) * 1000 / 1024))kb" +fi +endtime 1 "批量備份開始到結束" +chmod -R 0777 "$Backup/" +rm -rf "$MODDIR" +exit 0 \ No newline at end of file diff --git a/tools/zip b/tools/zip new file mode 100644 index 0000000..05407ae Binary files /dev/null and b/tools/zip differ