This commit is contained in:
gcw_4spBpAfv
2026-01-23 11:28:40 +08:00
parent 42bfdd033c
commit 28fb62e5d6
12 changed files with 648 additions and 67 deletions

View File

@@ -210,6 +210,64 @@ class OTAManager:
self.logger.error(f"[OTA] 错误:{downloaded_file} 不存在")
return False
# ====== 第一步:如果是 AEAD 加密包,先解密成临时 zip再走原有 unzip 流程) ======
downloaded_file_original = downloaded_file
decrypted_tmp_zip = None
try:
magic = b"AROTAE1" # must match packager/C++ side
is_enc_ext = downloaded_file.lower().endswith((".enc", ".zip.enc"))
is_enc_magic = False
try:
with open(downloaded_file, "rb") as f:
head = f.read(len(magic))
is_enc_magic = (head == magic)
except Exception:
is_enc_magic = False
if is_enc_ext or is_enc_magic:
# Choose output zip path (same dir)
tmp_zip = downloaded_file
if tmp_zip.lower().endswith(".zip.enc"):
tmp_zip = tmp_zip[:-4] # remove ".enc" -> ".zip"
elif tmp_zip.lower().endswith(".enc"):
tmp_zip = tmp_zip[:-4]
if not tmp_zip.lower().endswith(".zip"):
tmp_zip = tmp_zip + ".zip"
else:
tmp_zip = tmp_zip + ".zip"
decrypted_tmp_zip = tmp_zip
# Remove stale tmp if exists
try:
if os.path.exists(decrypted_tmp_zip):
os.remove(decrypted_tmp_zip)
except Exception:
pass
self.logger.info(f"[OTA] 检测到加密包,开始解密: {downloaded_file} -> {decrypted_tmp_zip}")
ok = False
try:
core = getattr(network_manager, "_netcore", None)
if core and hasattr(core, "decrypt_ota_file"):
ok = bool(core.decrypt_ota_file(downloaded_file, decrypted_tmp_zip))
else:
import archery_netcore as _netcore
ok = bool(_netcore.decrypt_ota_file(downloaded_file, decrypted_tmp_zip))
except Exception as e:
self.logger.error(f"[OTA] 解密异常: {e}")
ok = False
if not ok or (not os.path.exists(decrypted_tmp_zip)):
self.logger.error("[OTA] 解密失败,终止更新")
return False
downloaded_file = decrypted_tmp_zip
self.logger.info(f"[OTA] 解密成功后续使用明文ZIP: {downloaded_file}")
except Exception as e:
self.logger.error(f"[OTA] 解密流程异常: {e}")
return False
# 备份
backup_base = config.BACKUP_BASE
backup_dir = None
@@ -437,17 +495,35 @@ class OTAManager:
# 清理下载文件
try:
if os.path.exists(downloaded_file):
# 删除下载的文件
# 删除下载的文件(可能包含:原始加密包 + 临时明文zip
files_to_remove = []
try:
if 'downloaded_file_original' in locals() and downloaded_file_original:
files_to_remove.append(downloaded_file_original)
except Exception:
pass
try:
if 'decrypted_tmp_zip' in locals() and decrypted_tmp_zip:
files_to_remove.append(decrypted_tmp_zip)
except Exception:
pass
# 兼容:如果变量不存在,至少清理当前 downloaded_file
if not files_to_remove:
files_to_remove = [downloaded_file]
removed_any = False
for fp in list(dict.fromkeys(files_to_remove)):
try:
os.remove(downloaded_file)
self.logger.info(f"[OTA] 已删除下载文件: {downloaded_file}")
if fp and os.path.exists(fp):
os.remove(fp)
removed_any = True
self.logger.info(f"[OTA] 已删除下载文件: {fp}")
except Exception as e:
self.logger.warning(f"[OTA] 删除下载文件失败(可忽略): {e}")
# 尝试删除时间戳目录(如果为空)
try:
download_dir = os.path.dirname(downloaded_file)
download_dir = os.path.dirname(files_to_remove[0] if files_to_remove else downloaded_file)
if download_dir.startswith("/tmp/download/"):
# 检查时间戳目录是否为空
if os.path.exists(download_dir):
@@ -567,7 +643,7 @@ class OTAManager:
# 根据文件扩展名判断是否为二进制文件
filename_lower = filename.lower()
is_binary = filename_lower.endswith(('.zip', '.bin', '.tar', '.gz', '.exe', '.dll', '.so', '.dylib'))
is_binary = filename_lower.endswith(('.zip', '.zip.enc', '.enc', '.bin', '.tar', '.gz', '.exe', '.dll', '.so', '.dylib'))
if is_binary:
# 二进制文件:使用二进制模式写入