From 91a656f0b715ea07f5f21179025e9866bb042e70 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 7 Oct 2026 00:17:24 +0800 Subject: [PATCH] =?UTF-8?q?chore(messages):=20VET=20=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=97=B6=E4=B8=AD=E6=96=87=E5=AD=97=E7=AC=A6=E4=B8=B2=E8=8B=B1?= =?UTF-8?q?=E6=96=87=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 VET 下 10 个文件的运行时中文字符串(CLI 用法/帮助、扫描与校验日志、目录表与缓存诊断、PE 解析报错等)共 224 行译为英文。口径:只改字符串字面量内部文字,行数零变化(+224/-224);printf 格式符与转义序列多重集合校验不变(_strcheck 异常 0)。验证:编译 SUCCESS;VET.exe --search-paths 7 条 exit 0;VET.exe scan --cache --once 输出合法 JSON、exit 0。 --- App/lib/VCache.vp | 32 +++++++------- App/lib/VCheck.vp | 28 ++++++------- App/lib/VCli.vp | 104 +++++++++++++++++++++++----------------------- App/lib/VDirs.vp | 36 ++++++++-------- App/lib/VGuard.vp | 72 ++++++++++++++++---------------- App/lib/VJson.vp | 16 +++---- App/lib/VPe.vp | 52 +++++++++++------------ App/lib/VProc.vp | 44 ++++++++++---------- App/lib/VScan.vp | 56 ++++++++++++------------- App/main.vp | 8 ++-- 10 files changed, 224 insertions(+), 224 deletions(-) diff --git a/App/lib/VCache.vp b/App/lib/VCache.vp index 0201a1e..d5d65ce 100644 --- a/App/lib/VCache.vp +++ b/App/lib/VCache.vp @@ -130,7 +130,7 @@ def ClearCache(): def CacheAdd(ExeAnsi: str, Id: str, Ver: str, Arch: str, Src: str, Disp: str) -> int: global Cache_Count if Cache_Count >= CACHE_CAP: - VLog.LogFmt1(" 警告: 缓存条目已达上限 %d,忽略新条目\n", sizet(CACHE_CAP)) + VLog.LogFmt1(" Warning: cache entries reached limit %d, new entry ignored\n", sizet(CACHE_CAP)) return 0 E: str = VFs.DupStr(ExeAnsi) if E is None: @@ -183,7 +183,7 @@ def ValidateCache() -> int: if VFs.PathIsFile(Cache_Exe[j]) != 0: j += 1 else: - VLog.VerboseFmtS1(" [移除] 已不存在: %s\n", Cache_Exe[j]) + VLog.VerboseFmtS1(" [remove] no longer exists: %s\n", Cache_Exe[j]) RemoveAt(j) removed += 1 return removed @@ -199,10 +199,10 @@ def WriteCacheFile(Path: str, Buf: bytes, Len: sizet) -> int: return 0 rc: int = VFs.WriteFileAll(Path, Buf, Len) if rc == 0: - VLog.LogFmt1(" 警告: 缓存写入失败(打开失败, win32 err=%u)\n", wb.GetLastError()) + VLog.LogFmt1(" Warning: cache write failed (open failed, win32 err=%u)\n", wb.GetLastError()) return 0 if rc < 0: - VLog.LogFmt2(" 警告: 缓存写入不完整 (%zu/%zu 字节)\n", VFs.LastWriteDone, Len) + VLog.LogFmt2(" Warning: cache write incomplete (%zu/%zu bytes)\n", VFs.LastWriteDone, Len) return 0 return 1 @@ -247,7 +247,7 @@ def ParseCacheText(Txt: str) -> int: if L == 0: return 0 if L > sizet(CACHE_TEXT_MAX): - VLog.LogFmt2("缓存: 文本 %zu 字节超出解析上限 %zu,按空缓存启动\n", + VLog.LogFmt2("cache: text %zu bytes exceeds parse limit %zu, starting with empty cache\n", L, sizet(CACHE_TEXT_MAX)) return 0 # Pool capacity: worst case ~1 JsonValue node per input byte + key/value copies + temps, scaled @@ -255,32 +255,32 @@ def ParseCacheText(Txt: str) -> int: Cap: sizet = L * sizet(CACHE_ARENA_PER_BYTE) + sizet(CACHE_ARENA_SLACK) Arena: bytes = stdlib.malloc(Cap) if Arena is None: - VLog.LogStr("缓存: 解析工作池分配失败,按空缓存启动\n") + VLog.LogStr("cache: parse pool allocation failed, starting with empty cache\n") return 0 Pool: memhub.MemPool* = memhub.MemPool(Arena, Cap) if Pool is None: stdlib.free(t.CPtr(Arena)) - VLog.LogStr("缓存: 解析工作池构造失败,按空缓存启动\n") + VLog.LogStr("cache: parse pool construction failed, starting with empty cache\n") return 0 # Pool precheck (fail-closed): the whole tree must fit, else json.parse's pool.alloc would # exit(1). Need mirrors Cap, so this fails cleanly (empty-cache fallback) if Cap is too small. Need: sizet = L * sizet(CACHE_ARENA_PER_BYTE) + sizet(CACHE_ARENA_SLACK) if Pool.AllocOk(Need) == 0: stdlib.free(t.CPtr(Arena)) - VLog.LogFmt1("缓存: 解析工作池预检不足(最坏需要 %zu 字节),按空缓存启动\n", + VLog.LogFmt1("cache: parse pool precheck insufficient (worst case needs %zu bytes), starting with empty cache\n", Need) return 0 ConvBuf: bytes = _mbuddy.alloc(VFs.CONV_CAP) if ConvBuf is None: stdlib.free(t.CPtr(Arena)) - VLog.LogStr("缓存: 编码转换缓冲分配失败,按空缓存启动\n") + VLog.LogStr("cache: encoding conversion buffer allocation failed, starting with empty cache\n") return 0 Root: json.JsonValue* = json.parse(Pool, Txt) added: int = 0 if Root == None: - VLog.LogStr("缓存: JSON 解析失败(内容损坏),按空缓存启动\n") + VLog.LogStr("cache: JSON parse failed (corrupt content), starting with empty cache\n") elif Root.vtype != json.JSON_ARRAY: - VLog.LogStr("缓存: 顶层不是 JSON 数组,按空缓存启动\n") + VLog.LogStr("cache: top level is not a JSON array, starting with empty cache\n") else: cu: json.JsonValue* = Root.child while cu != None: @@ -299,17 +299,17 @@ def LoadCache(Path: str) -> int: if buf is None: rc_err: int = VFs.LastReadErr if rc_err == 1: - VLog.VerboseFmtS1("缓存: 未找到/无法打开,按空缓存启动: %s\n", Path) + VLog.VerboseFmtS1("cache: not found / cannot open, starting with empty cache: %s\n", Path) elif rc_err == 2: - VLog.LogStr("缓存: 读取大小失败,按空缓存启动\n") + VLog.LogStr("cache: read size failed, starting with empty cache\n") elif rc_err == 5: - VLog.LogStr("缓存: 分配缓冲失败,按空缓存启动\n") + VLog.LogStr("cache: buffer allocation failed, starting with empty cache\n") else: - VLog.LogStr("缓存: 大小异常/过大,按空缓存启动\n") + VLog.LogStr("cache: size invalid / too large, starting with empty cache\n") return 0 n: int = ParseCacheText(str(buf)) stdlib.free(t.CPtr(buf)) - VLog.VerboseFmt1("缓存: 已载入 %u 项种子\n", sizet(n)) + VLog.VerboseFmt1("cache: loaded %u seed entries\n", sizet(n)) return n diff --git a/App/lib/VCheck.vp b/App/lib/VCheck.vp index cf94e4b..6f10ff0 100644 --- a/App/lib/VCheck.vp +++ b/App/lib/VCheck.vp @@ -158,22 +158,22 @@ def CheckInit() -> int: Check_Conv = _mbuddy.alloc(VFs.CONV_CAP) Check_Arena = stdlib.malloc(CK_REPLY_POOL_CAP) if EnsurePathBuf() == 0: - VLog.LogStr(" 警告: check 缓冲分配失败(请求路径缓冲),check 通道不可用\n") + VLog.LogStr(" Warning: check buffer allocation failed (request path buffer), check channel unavailable\n") return 0 if Check_Ver is None or Check_Arch is None or Check_Probe is None: - VLog.LogStr(" 警告: check 缓冲分配失败(版本/arch/探测缓冲),check 通道不可用\n") + VLog.LogStr(" Warning: check buffer allocation failed (version/arch/probe buffer), check channel unavailable\n") return 0 if Check_Msg is None or Check_Id is None: - VLog.LogStr(" 警告: check 缓冲分配失败(原因串/UUID 缓冲),check 通道不可用\n") + VLog.LogStr(" Warning: check buffer allocation failed (reason string/UUID buffer), check channel unavailable\n") return 0 if Check_Disp is None or Check_Conv is None or Check_Arena is None: - VLog.LogStr(" 警告: check 缓冲分配失败(展示串/转换缓冲/回执 arena),check 通道不可用\n") + VLog.LogStr(" Warning: check buffer allocation failed (display string/conversion buffer/reply arena), check channel unavailable\n") return 0 # Construct the pool in place on the heap (memhub.NewMemPool): Check_Pool outlives this frame # (same reason as VJson.JsonInit). Pool: memhub.MemPool* = memhub.NewMemPool(Check_Arena, CK_REPLY_POOL_CAP) if Pool is None: - VLog.LogStr(" 警告: check 回执工作池构造失败,check 通道不可用\n") + VLog.LogStr(" Warning: check reply pool construction failed, check channel unavailable\n") return 0 Check_Pool = Pool Check_Ready = 1 @@ -337,7 +337,7 @@ def TrackChecked(PathAnsi: str) -> int: return 1 if VCache.CacheAdd(PathAnsi, str(Check_Id), str(Check_Ver), str(Check_Arch), CK_SOURCE, str(Check_Disp)) == 0: - VLog.LogStr(" 警告: check 命中但入库失败(容量已满或分配失败),本轮不跟踪该条目\n") + VLog.LogStr(" Warning: check hit but cache insert failed (capacity full or allocation failed), entry not tracked this round\n") return 0 return 1 @@ -380,7 +380,7 @@ def EmitReplyOk(ReqIdVal: LONGLONG, PathAnsi: str): else: # new hit: generate a UUID then insert (failure only warns; the reply still reports the result) if VGuid.NewGuidStr(Check_Id, VGuid.GUID_STR_CAP) == 0: - VLog.LogStr(" 警告: CoCreateGuid 失败,check 入库项的 id 为空串\n") + VLog.LogStr(" Warning: CoCreateGuid failed, id of the check cache entry is empty\n") Check_Id[0] = 0 Id = str(Check_Id) TrackChecked(PathAnsi) @@ -389,17 +389,17 @@ def EmitReplyOk(ReqIdVal: LONGLONG, PathAnsi: str): ValNeed = ValNeed + string.strlen(Id) + string.strlen(Ver) + string.strlen(Arch) ValNeed = ValNeed + string.strlen(CK_SOURCE) if Check_Pool.AllocOk(sizet(CK_REPLY_NEED_FIXED) + ValNeed) == 0: - VLog.LogStr(" 警告: check 回执工作池不足,未回复(不会写穿缓冲)\n") + VLog.LogStr(" Warning: check reply pool insufficient, not replied (buffer will not be overrun)\n") return Obj: json.JsonValue* = json.object(Check_Pool) if Obj == None: - VLog.LogStr(" 警告: check 回执对象分配失败,未回复\n") + VLog.LogStr(" Warning: check reply object allocation failed, not replied\n") return json.object_set(Check_Pool, Obj, "check_result", json.bool_val(Check_Pool, True)) json.object_set(Check_Pool, Obj, "id", json.int_val(Check_Pool, int64(ReqIdVal))) Sub: json.JsonValue* = json.object(Check_Pool) if Sub == None: - VLog.LogStr(" 警告: check 回执对象分配失败,未回复\n") + VLog.LogStr(" Warning: check reply object allocation failed, not replied\n") return json.object_set(Check_Pool, Sub, "id", json.string_val(Check_Pool, Id)) # convert executable / displayName to UTF-8 and hand to the library immediately (Check_Conv is reused) @@ -415,7 +415,7 @@ def EmitReplyOk(ReqIdVal: LONGLONG, PathAnsi: str): json.object_set(Check_Pool, Obj, "viper", Sub) Txt: str = json.write(Check_Pool, Obj, False) if Txt == None: - VLog.LogStr(" 警告: check 回执序列化失败(工作池不足),未回复\n") + VLog.LogStr(" Warning: check reply serialization failed (pool insufficient), not replied\n") return WriteReplyLine(Txt) @@ -427,18 +427,18 @@ def EmitReplyFail(ReqIdVal: LONGLONG, Msg: str): if Msg != None: Need = Need + string.strlen(Msg) if Check_Pool.AllocOk(Need) == 0: - VLog.LogStr(" 警告: check 回执工作池不足,未回复(不会写穿缓冲)\n") + VLog.LogStr(" Warning: check reply pool insufficient, not replied (buffer will not be overrun)\n") return Obj: json.JsonValue* = json.object(Check_Pool) if Obj == None: - VLog.LogStr(" 警告: check 回执对象分配失败,未回复\n") + VLog.LogStr(" Warning: check reply object allocation failed, not replied\n") return json.object_set(Check_Pool, Obj, "check_result", json.bool_val(Check_Pool, False)) json.object_set(Check_Pool, Obj, "id", json.int_val(Check_Pool, int64(ReqIdVal))) json.object_set(Check_Pool, Obj, "check_msg", json.string_val(Check_Pool, Msg)) Txt: str = json.write(Check_Pool, Obj, False) if Txt == None: - VLog.LogStr(" 警告: check 回执序列化失败(工作池不足),未回复\n") + VLog.LogStr(" Warning: check reply serialization failed (pool insufficient), not replied\n") return WriteReplyLine(Txt) diff --git a/App/lib/VCli.vp b/App/lib/VCli.vp index 42da696..cad1183 100644 --- a/App/lib/VCli.vp +++ b/App/lib/VCli.vp @@ -205,35 +205,35 @@ def ParseUint64(S: str) -> int: def PrintUsage(): VLog.LogStr("VET - Viper Environment Tool\n") - VLog.LogStr("用法:\n") + VLog.LogStr("Usage:\n") VLog.LogStr(" VET.exe ver [--verbose]\n") - VLog.LogStr(" 单次校验指定 exe(常用目录表 + .PRVERSN 段 + --version 前缀);\n") - VLog.LogStr(" --verbose 为与 scan 同名的无值开关(输出目标路径与解析/探测细节)。\n") - VLog.LogStr(" VET.exe scan --cache [--once] [--sleep <毫秒>] [--pace <毫秒>] [--pace-units ]\n") - VLog.LogStr(" [--first-no-pace] [--need-confirm <秒> [--need-confirm-timeout <毫秒>]]\n") + VLog.LogStr(" Validate one exe once (common directory table + .PRVERSN section + --version prefix);\n") + VLog.LogStr(" --verbose is the valueless switch shared with scan (prints the target path and parse/probe details).\n") + VLog.LogStr(" VET.exe scan --cache [--once] [--sleep ] [--pace ] [--pace-units ]\n") + VLog.LogStr(" [--first-no-pace] [--need-confirm [--need-confirm-timeout ]]\n") VLog.LogStr(" [--verbose] [--path ]...\n") - VLog.LogStr(" 常驻扫盘发现器;结果 JSON 写 stdout,缓存写 。\n") + VLog.LogStr(" Resident disk scanner; result JSON goes to stdout, cache is written to .\n") VLog.LogStr(" VET.exe scan --search-paths [--path ]... [--verbose]\n") - VLog.LogStr(" VET.exe --search-paths [--path ]... [--verbose] (同上,可省 scan:纯查询)\n") - VLog.LogStr(" --once 只跑一轮(便于验证)。\n") - VLog.LogStr(" --sleep <毫秒> 每轮间隔(缺省 10000;0 = 不 sleep;上限 86400000)。\n") - VLog.LogStr(" --pace <毫秒> 节流点睡眠时长(缺省 20;0 = 关闭节流;上限 60000)。\n") - VLog.LogStr(" --pace-units 每 N 个文件一个节流点(缺省 64;1 = 每个文件都停;上限 1000000)。\n") - VLog.LogStr(" 显式给出 --pace 或 --pace-units 即启用节流,--once 下也生效;\n") - VLog.LogStr(" 未给出时沿用缺省(常驻启用;--once 关闭)。目录侧粒度恒为 16。\n") - VLog.LogStr(" --first-no-pace 第 1 轮扫盘不启用节流(只影响第 1 轮;之后各轮按常规规则)。\n") - VLog.LogStr(" 与 --pace 0 的区别:后者是全程不限速。仅常驻多轮时才有意义。\n") - VLog.LogStr(" --need-confirm <秒> 心跳确认:独立看门狗子进程每 <秒> 秒要求 stdin 输入一行\n") - VLog.LogStr(" {\"ok\": 1};超时内未输入或 ok!=1 则输出 {\"exit\":1, ...}\n") - VLog.LogStr(" 并终止本进程(退出码 1)。缺省/0 = 关闭;仅 scan 模式生效。\n") - VLog.LogStr(" --need-confirm-timeout <毫秒>\n") - VLog.LogStr(" 确认等待超时(缺省 5000;仅在给出 --need-confirm 时有意义)。\n") - VLog.LogStr(" --verbose 输出详细过程日志(进度/扫描根/逐条过滤/探测细节);\n") - VLog.LogStr(" 缺省安静:只留启动摘要、心跳确认提示、警告与轮末一行。\n") - VLog.LogStr(" --path 强制替换常用目录表(可重复);一出现即不做任何自动建表。\n") - VLog.LogStr(" --search-paths 打印将搜索的路径后退出:建好常用目录表即逐行列出\n") - VLog.LogStr(" (序号 + 路径 + 目录表来源,输出到 stderr),不扫盘、\n") - VLog.LogStr(" 不拉起看门狗、不读写缓存;此时 --cache 非必填。\n") + VLog.LogStr(" VET.exe --search-paths [--path ]... [--verbose] (same as above; scan may be omitted: query only)\n") + VLog.LogStr(" --once run a single round only (for verification).\n") + VLog.LogStr(" --sleep interval per round (default 10000; 0 = no sleep; max 86400000).\n") + VLog.LogStr(" --pace sleep duration at throttle points (default 20; 0 = disable throttling; max 60000).\n") + VLog.LogStr(" --pace-units one throttle point every N files (default 64; 1 = stop at every file; max 1000000).\n") + VLog.LogStr(" giving --pace or --pace-units explicitly enables throttling, also under --once;\n") + VLog.LogStr(" when absent the defaults apply (on for resident; off under --once). directory granularity is always 16.\n") + VLog.LogStr(" --first-no-pace round 1 scans without throttling (affects round 1 only; later rounds follow normal rules).\n") + VLog.LogStr(" differs from --pace 0: the latter disables throttling for the whole run. meaningful only for multi-round resident mode.\n") + VLog.LogStr(" --need-confirm heartbeat confirmation: an independent watchdog child asks for one stdin line every seconds\n") + VLog.LogStr(" {\"ok\": 1}; if no input arrives in time or ok!=1, prints {\"exit\":1, ...}\n") + VLog.LogStr(" and terminates this process (exit code 1). default/0 = off; scan mode only.\n") + VLog.LogStr(" --need-confirm-timeout \n") + VLog.LogStr(" confirmation wait timeout (default 5000; meaningful only when --need-confirm is given).\n") + VLog.LogStr(" --verbose print detailed process logs (progress/scan roots/per-item filtering/probe details);\n") + VLog.LogStr(" quiet by default: only the startup summary, heartbeat prompts, warnings and one round-end line.\n") + VLog.LogStr(" --path force-replace the common directory table (repeatable); once present no auto table is built.\n") + VLog.LogStr(" --search-paths print the paths to search then exit: build the common directory table and list it line by line\n") + VLog.LogStr(" (index + path + table source, to stderr); no scan,\n") + VLog.LogStr(" no watchdog, no cache access; --cache is optional in this case.\n") # Parse scan arguments; returns 0 = success, 1 = argument error (usage/error already printed). @@ -266,7 +266,7 @@ def ParseScanArgs() -> int: Cache_Path = sys._argv[i + 1] i += 1 else: - VLog.LogStr("错误: --cache 需要一个路径参数\n") + VLog.LogStr("Error: --cache requires a path argument\n") return 1 elif string.strcmp(A, "--once") == 0: Once_Flag = 1 @@ -278,7 +278,7 @@ def ParseScanArgs() -> int: if i + 1 < sys._argc and sys._argv[i + 1] is not None: M: int = ParseUint(sys._argv[i + 1], SLEEP_MAX_MS) if M < 0: - VLog.LogFmt1("错误: --sleep 需要一个 0..%u 的整数字面量毫秒数,实际为: ", + VLog.LogFmt1("Error: --sleep requires an integer-literal millisecond value in 0..%u, got: ", sizet(SLEEP_MAX_MS)) VLog.LogFmtS1("%s\n", sys._argv[i + 1]) PrintUsage() @@ -286,14 +286,14 @@ def ParseScanArgs() -> int: Sleep_Ms = M i += 1 else: - VLog.LogStr("错误: --sleep 需要一个毫秒数参数\n") + VLog.LogStr("Error: --sleep requires a millisecond argument\n") PrintUsage() return 1 elif string.strcmp(A, "--pace") == 0: if i + 1 < sys._argc and sys._argv[i + 1] is not None: P: int = ParseUint(sys._argv[i + 1], PACE_SLEEP_MAX_MS) if P < 0: - VLog.LogFmt1("错误: --pace 需要一个 0..%u 的整数字面量毫秒数,实际为: ", + VLog.LogFmt1("Error: --pace requires an integer-literal millisecond value in 0..%u, got: ", sizet(PACE_SLEEP_MAX_MS)) VLog.LogFmtS1("%s\n", sys._argv[i + 1]) PrintUsage() @@ -302,7 +302,7 @@ def ParseScanArgs() -> int: Pace_Set = 1 # explicitly given => throttling on (also under --once) i += 1 else: - VLog.LogStr("错误: --pace 需要一个毫秒数参数\n") + VLog.LogStr("Error: --pace requires a millisecond argument\n") PrintUsage() return 1 elif string.strcmp(A, "--pace-units") == 0: @@ -310,7 +310,7 @@ def ParseScanArgs() -> int: U: int = ParseUint(sys._argv[i + 1], PACE_UNITS_MAX) # 0 and invalid are both errors; 0 makes "a sleep point every 0 files" meaningless if U <= 0: - VLog.LogFmt1("错误: --pace-units 需要一个 1..%u 的整数字面量文件数,实际为: ", + VLog.LogFmt1("Error: --pace-units requires an integer-literal file count in 1..%u, got: ", sizet(PACE_UNITS_MAX)) VLog.LogFmtS1("%s\n", sys._argv[i + 1]) PrintUsage() @@ -319,7 +319,7 @@ def ParseScanArgs() -> int: Pace_Set = 1 # explicitly given => throttling on (also under --once) i += 1 else: - VLog.LogStr("错误: --pace-units 需要一个文件数参数\n") + VLog.LogStr("Error: --pace-units requires a file-count argument\n") PrintUsage() return 1 elif string.strcmp(A, "--first-no-pace") == 0: @@ -331,7 +331,7 @@ def ParseScanArgs() -> int: S: int = ParseSecs(sys._argv[i + 1]) if S < 0: # two fixed-arity calls on one line (LogFmt1 takes ints, LogFmtS1 takes strings) - VLog.LogFmt1("错误: --need-confirm 需要一个 0..%u 的整数字面量秒数,实际为: ", + VLog.LogFmt1("Error: --need-confirm requires an integer-literal second value in 0..%u, got: ", sizet(SECS_MAX)) VLog.LogFmtS1("%s\n", sys._argv[i + 1]) PrintUsage() @@ -339,14 +339,14 @@ def ParseScanArgs() -> int: Need_Confirm = S i += 1 else: - VLog.LogStr("错误: --need-confirm 需要一个秒数参数\n") + VLog.LogStr("Error: --need-confirm requires a second argument\n") PrintUsage() return 1 elif string.strcmp(A, "--need-confirm-timeout") == 0: if i + 1 < sys._argc and sys._argv[i + 1] is not None: T: int = ParseUint(sys._argv[i + 1], CONFIRM_TIMEOUT_MAX_MS) if T < 0: - VLog.LogFmt1("错误: --need-confirm-timeout 需要一个 0..%u 的整数字面量毫秒数,实际为: ", + VLog.LogFmt1("Error: --need-confirm-timeout requires an integer-literal millisecond value in 0..%u, got: ", sizet(CONFIRM_TIMEOUT_MAX_MS)) VLog.LogFmtS1("%s\n", sys._argv[i + 1]) PrintUsage() @@ -355,7 +355,7 @@ def ParseScanArgs() -> int: Has_Timeout = 1 i += 1 else: - VLog.LogStr("错误: --need-confirm-timeout 需要一个毫秒数参数\n") + VLog.LogStr("Error: --need-confirm-timeout requires a millisecond argument\n") PrintUsage() return 1 elif string.strcmp(A, "--path") == 0: @@ -364,23 +364,23 @@ def ParseScanArgs() -> int: VDirs.AddOverridePath(sys._argv[i + 1]) i += 1 else: - VLog.LogStr("错误: --path 需要一个目录参数\n") + VLog.LogStr("Error: --path requires a directory argument\n") return 1 else: - VLog.LogFmtS1("错误: 未知参数 %s\n", A) + VLog.LogFmtS1("Error: unknown argument %s\n", A) PrintUsage() return 1 i += 1 # --search-paths is a pure query switch (build table + print, no cache, no scan), so --cache # is optional; other checks stay strict (a provided --cache is still accepted, just unused). if Cache_Path is None and Search_Paths_Flag == 0: - VLog.LogStr("错误: scan 模式必须提供 --cache \n") + VLog.LogStr("Error: scan mode requires --cache \n") PrintUsage() return 1 # --need-confirm-timeout alone is not an error, only a warning: it is subordinate to # --need-confirm, so erroring would fail needlessly on flag order; the warning avoids silence. if Has_Timeout != 0 and Need_Confirm <= 0: - VLog.LogStr("警告: --need-confirm-timeout 未与 --need-confirm 一起使用,已忽略\n") + VLog.LogStr("Warning: --need-confirm-timeout is used without --need-confirm, ignored\n") return 0 @@ -403,59 +403,59 @@ def ParseWatchArgs() -> int: if i + 1 < sys._argc and sys._argv[i + 1] is not None: S: int = ParseUint(sys._argv[i + 1], SECS_MAX) if S <= 0: - VLog.LogStr("confirm-watch: --interval 需要一个 >=1 的整数字面量秒数\n") + VLog.LogStr("confirm-watch: --interval requires an integer-literal second value >= 1\n") return 1 Watch_Interval = S i += 1 else: - VLog.LogStr("confirm-watch: --interval 需要一个秒数参数\n") + VLog.LogStr("confirm-watch: --interval requires a second argument\n") return 1 elif string.strcmp(A, "--timeout") == 0: if i + 1 < sys._argc and sys._argv[i + 1] is not None: T: int = ParseUint(sys._argv[i + 1], CONFIRM_TIMEOUT_MAX_MS) if T < 0: - VLog.LogStr("confirm-watch: --timeout 需要一个非负整数字面量毫秒数\n") + VLog.LogStr("confirm-watch: --timeout requires a non-negative integer-literal millisecond value\n") return 1 Watch_Timeout = T i += 1 else: - VLog.LogStr("confirm-watch: --timeout 需要一个毫秒数参数\n") + VLog.LogStr("confirm-watch: --timeout requires a millisecond argument\n") return 1 elif string.strcmp(A, "--parent-pid") == 0: if i + 1 < sys._argc and sys._argv[i + 1] is not None: P: LONGLONG = ParseUint(sys._argv[i + 1], PID_MAX) if P <= 0: - VLog.LogStr("confirm-watch: --parent-pid 需要一个正整数\n") + VLog.LogStr("confirm-watch: --parent-pid requires a positive integer\n") return 1 Watch_ParentPid = P Has_Pid = 1 i += 1 else: - VLog.LogStr("confirm-watch: --parent-pid 需要一个 pid 参数\n") + VLog.LogStr("confirm-watch: --parent-pid requires a pid argument\n") return 1 elif string.strcmp(A, "--ipc-write") == 0: if i + 1 < sys._argc and sys._argv[i + 1] is not None: if ParseUint64(sys._argv[i + 1]) == 0: - VLog.LogFmtS1("confirm-watch: --ipc-write 需要一个十进制非负整数字面量句柄值,实际为: ", + VLog.LogFmtS1("confirm-watch: --ipc-write requires a decimal non-negative integer-literal handle value, got: ", sys._argv[i + 1]) VLog.LogStr("\n") return 1 Watch_IpcWrite = U64_Val i += 1 else: - VLog.LogStr("confirm-watch: --ipc-write 需要一个句柄数值参数\n") + VLog.LogStr("confirm-watch: --ipc-write requires a handle-value argument\n") return 1 elif string.strcmp(A, "--verbose") == 0: Watch_Verbose = 1 # valueless switch: appended by the parent when it is verbose else: - VLog.LogFmtS1("confirm-watch: 未知参数 %s\n", A) + VLog.LogFmtS1("confirm-watch: unknown argument %s\n", A) return 1 i += 1 if Watch_Interval <= 0: - VLog.LogStr("confirm-watch: 缺少 --interval <秒>\n") + VLog.LogStr("confirm-watch: missing --interval \n") return 1 if Has_Pid == 0: - VLog.LogStr("confirm-watch: 缺少 --parent-pid \n") + VLog.LogStr("confirm-watch: missing --parent-pid \n") return 1 if Watch_Timeout < 0: Watch_Timeout = DEFAULT_CONFIRM_TIMEOUT_MS diff --git a/App/lib/VDirs.vp b/App/lib/VDirs.vp index 870d2aa..a3870e7 100644 --- a/App/lib/VDirs.vp +++ b/App/lib/VDirs.vp @@ -92,7 +92,7 @@ def AddOverridePath(Path: str) -> int: if Path is None: return 0 if Override_Count >= COMMON_DIR_CAPACITY: - VLog.LogFmtIS(" 警告: --path 数量已达上限 (%d),忽略: %s\n", COMMON_DIR_CAPACITY, Path) + VLog.LogFmtIS(" Warning: --path count reached limit (%d), ignored: %s\n", COMMON_DIR_CAPACITY, Path) return 0 Override_Dir[Override_Count] = Path Override_Count += 1 @@ -109,7 +109,7 @@ def AddCommonDirForce(Path: str) -> int: if string.strcmp(Common_Directory[i], Path) == 0: return 0 if Common_Dir_Count >= COMMON_DIR_CAPACITY: - VLog.LogFmt1(" 警告: 常用目录表已满 (%d),已忽略该条\n", sizet(COMMON_DIR_CAPACITY)) + VLog.LogFmt1(" Warning: common dir table full (%d), entry ignored\n", sizet(COMMON_DIR_CAPACITY)) return 0 Common_Directory[Common_Dir_Count] = Path Common_Dir_Count += 1 @@ -133,7 +133,7 @@ def AddFixedDriveProgramFiles() -> int: SetErrorMode(SEM_FAILCRITICALERRORS) Mask: DWORD = GetLogicalDrives() if Mask == 0: - VLog.LogFmt1(" 警告: GetLogicalDrives 失败 (win32 err=%u)\n", wb.GetLastError()) + VLog.LogFmt1(" Warning: GetLogicalDrives failed (win32 err=%u)\n", wb.GetLastError()) return 0 Added: int = 0 for Letter in range(26): @@ -167,14 +167,14 @@ def AddDesktopFallback(Buf: bytes) -> int: n: DWORD = GetEnvironmentVariableA("USERPROFILE", Buf, VFs.PATH_BUF_CAP) # Also append "\Desktop" (8 bytes) + NUL, so n + 9 must not exceed the buffer capacity if n == 0 or n + uint32(DESKTOP_SUFFIX_CAP) > uint32(VFs.PATH_BUF_CAP): - VLog.LogFmt1(" 桌面兜底: 获取 USERPROFILE 失败或过长 (win32 err=%u)\n", wb.GetLastError()) + VLog.LogFmt1(" desktop fallback: USERPROFILE missing or too long (win32 err=%u)\n", wb.GetLastError()) return 0 Buf[n] = 0 string.strcat(Buf, r"\Desktop") - VLog.VerboseFmtS1(" 桌面兜底: 使用 %s\n", str(Buf)) + VLog.VerboseFmtS1(" desktop fallback: using %s\n", str(Buf)) if AddCommonDir(str(Buf)) != 0: return 1 - VLog.LogStr(" 警告: 桌面兜底路径不存在或非目录,未加入常用目录表\n") + VLog.LogStr(" Warning: desktop fallback path missing or not a directory, not added to common dir table\n") return 0 @@ -183,14 +183,14 @@ def AddDesktopFallback(Buf: bytes) -> int: def AddCurrentUserDesktop() -> int: Buf: bytes = _mbuddy.alloc(VFs.PATH_BUF_CAP) if Buf is None: - VLog.LogStr(" 警告: 桌面路径缓冲区分配失败\n") + VLog.LogStr(" Warning: desktop path buffer allocation failed\n") return 0 # FOLDERID_Desktop {B4BFCC3A-DB2C-424C-B029-7FE99A87C641} as 16 raw LE bytes: # 3A CC BF B4 2C DB 4C 42 B0 29 7F E9 9A 87 C6 41 (wb.GUID mis-models Data4 as a pointer). GuidBuf: BYTEPTR = stdlib.malloc(KNOWNFOLDERID_SIZE) if GuidBuf is None: - VLog.LogStr(" 警告: KNOWNFOLDERID 缓冲分配失败,改用兜底路径\n") + VLog.LogStr(" Warning: KNOWNFOLDERID buffer allocation failed, using fallback path\n") return AddDesktopFallback(Buf) GuidBuf[0] = 0x3A GuidBuf[1] = 0xCC @@ -216,39 +216,39 @@ def AddCurrentUserDesktop() -> int: # On failure *ppszPath is NULL by spec; still free a non-NULL return defensively to avoid leaks if Pwsz is not None: CoTaskMemFree(t.CPtr(Pwsz)) - VLog.LogFmt1(" 桌面: SHGetKnownFolderPath 失败 (hr=0x%X),改用兜底路径\n", sizet(uint32(Hr))) + VLog.LogFmt1(" desktop: SHGetKnownFolderPath failed (hr=0x%X), using fallback path\n", sizet(uint32(Hr))) return AddDesktopFallback(Buf) if Pwsz is None: - VLog.LogStr(" 桌面: SHGetKnownFolderPath 返回空指针,改用兜底路径\n") + VLog.LogStr(" desktop: SHGetKnownFolderPath returned null pointer, using fallback path\n") return AddDesktopFallback(Buf) # UTF-16 -> UTF-8: query needed bytes first (incl. NUL; Needed<=0 means failure) Needed: int = VFs.WideToUtf8Needed(Pwsz) if Needed <= 0 or Needed > VFs.PATH_BUF_CAP: CoTaskMemFree(t.CPtr(Pwsz)) - VLog.LogFmt2(" 桌面: 路径为空或过长 (%d 字节, 上限 %d),改用兜底路径\n", + VLog.LogFmt2(" desktop: path empty or too long (%d bytes, limit %d), using fallback path\n", sizet(uint32(Needed)), sizet(VFs.PATH_BUF_CAP)) return AddDesktopFallback(Buf) Got: int = VFs.WideToUtf8(Pwsz, Buf, VFs.PATH_BUF_CAP) CoTaskMemFree(t.CPtr(Pwsz)) # Free immediately after use: single free point for both branches if Got == 0: - VLog.LogFmt1(" 桌面: UTF-16→UTF-8 转换失败 (win32 err=%u),改用兜底路径\n", wb.GetLastError()) + VLog.LogFmt1(" desktop: UTF-16 to UTF-8 conversion failed (win32 err=%u), using fallback path\n", wb.GetLastError()) return AddDesktopFallback(Buf) if AddCommonDir(str(Buf)) != 0: return 1 - VLog.LogStr(" 警告: 桌面路径不存在或非目录,未加入常用目录表\n") + VLog.LogStr(" Warning: desktop path missing or not a directory, not added to common dir table\n") return 0 # Print the common dir table (verbose only). Returns 0=non-empty, 1=empty def PrintCommonDirs() -> int: if Common_Dir_Count <= 0: - VLog.VerboseStr(" (表为空)\n") + VLog.VerboseStr(" (table empty)\n") return 1 for i in range(Common_Dir_Count): VLog.VerboseFmtIS(" [%d] %s\n", sizet(i), Common_Directory[i]) - VLog.VerboseFmt1(" 合计 %d 个常用目录\n", sizet(Common_Dir_Count)) + VLog.VerboseFmt1(" total %d common dirs\n", sizet(Common_Dir_Count)) return 0 @@ -260,13 +260,13 @@ def BuildTable() -> int: AddCommonDirForce(r"D:\Viper") AddFixedDriveProgramFiles() # Per-drive Program Files / Program Files (x86) AddCurrentUserDesktop() # Current user desktop - VLog.VerboseFmt1(" 目录表来源: 自动表 (%u 条)\n", sizet(Common_Dir_Count)) + VLog.VerboseFmt1(" dir table source: auto table (%u entries)\n", sizet(Common_Dir_Count)) else: # Force replace: no auto-build; table = --path order (de-dup handled by AddCommonDirForce) for i in range(Override_Count): if VFs.PathIsDir(Override_Dir[i]) == 0: - VLog.LogFmtS1(" 警告: --path 不存在或非目录,跳过: %s\n", Override_Dir[i]) + VLog.LogFmtS1(" Warning: --path missing or not a directory, skipped: %s\n", Override_Dir[i]) else: AddCommonDirForce(Override_Dir[i]) - VLog.VerboseFmt1(" 目录表来源: 覆盖表 (%u 条)\n", sizet(Common_Dir_Count)) + VLog.VerboseFmt1(" dir table source: override table (%u entries)\n", sizet(Common_Dir_Count)) return PrintCommonDirs() diff --git a/App/lib/VGuard.vp b/App/lib/VGuard.vp index f99e176..a73c5d6 100644 --- a/App/lib/VGuard.vp +++ b/App/lib/VGuard.vp @@ -310,7 +310,7 @@ def GuardIpcCreate() -> wb.HANDLE: hWrite: wb.HANDLE = None if wf.CreatePipe(&hRead, &hWrite, &Sa, ULONG(IPC_PIPE_SIZE)) == 0: - VLog.LogFmt1("[confirm] 警告: check 通道 CreatePipe 失败 (GetLastError=%u)\n", + VLog.LogFmt1("[confirm] Warning: check channel CreatePipe failed (GetLastError=%u)\n", sizet(wb.GetLastError())) return None # read end is parent-only: clear inherit bit so no child (watchdog, --version probe) inherits it @@ -405,12 +405,12 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: _mbuddy.free(t.CPtr(Self)) if Cmd is not None: _mbuddy.free(t.CPtr(Cmd)) - VLog.LogStr("[confirm] 警告: 看门狗缓冲分配失败,未启动\n") + VLog.LogStr("[confirm] Warning: watchdog buffer allocation failed, not started\n") return 0 if SelfExePath(Self, SELF_PATH_CAP) == 0: _mbuddy.free(t.CPtr(Self)) _mbuddy.free(t.CPtr(Cmd)) - VLog.LogStr("[confirm] 警告: GetModuleFileNameA 取自身路径失败,看门狗未启动\n") + VLog.LogStr("[confirm] Warning: GetModuleFileNameA failed to get own path, watchdog not started\n") return 0 # Build the pipe first (the write-end value must be in the command line before CreateProcessA). @@ -419,7 +419,7 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: if IpcW is None: _mbuddy.free(t.CPtr(Self)) _mbuddy.free(t.CPtr(Cmd)) - VLog.LogStr("[confirm] 警告: check 通道管道建立失败,看门狗未启动\n") + VLog.LogStr("[confirm] Warning: check channel pipe creation failed, watchdog not started\n") return 0 # First token is the self path (quoted for spaces); --verbose is forwarded so the child uses the @@ -444,7 +444,7 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: GuardIpcClose() _mbuddy.free(t.CPtr(Self)) _mbuddy.free(t.CPtr(Cmd)) - VLog.LogStr("[confirm] 警告: stdin 句柄无效,看门狗未启动(心跳确认需要 stdin)\n") + VLog.LogStr("[confirm] Warning: stdin handle invalid, watchdog not started (heartbeat confirmation requires stdin)\n") return 0 # Best-effort mark standard handles inheritable (console handles usually inherit anyway; ignore) wf.SetHandleInformation(hIn, wf.HANDLE_FLAG_INHERIT, wf.HANDLE_FLAG_INHERIT) @@ -469,7 +469,7 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: if Ok == 0: wb.CloseHandle(IpcW) GuardIpcClose() - VLog.LogFmt1("[confirm] 警告: 看门狗 CreateProcessA 失败 (GetLastError=%u),未启动\n", + VLog.LogFmt1("[confirm] Warning: watchdog CreateProcessA failed (GetLastError=%u), not started\n", sizet(CreateErr)) return 0 @@ -485,7 +485,7 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: if Wp == wb.WAIT_OBJECT_0: Ec: ULONG = 0 wp.GetExitCodeProcess(Watch_Process, &Ec) - VLog.LogFmt1("[confirm] 看门狗拉起后立即退出 (exit=%u),心跳确认无法生效\n", + VLog.LogFmt1("[confirm] watchdog exited immediately after spawn (exit=%u), heartbeat confirmation cannot work\n", sizet(Ec)) # Like StopWatchdog, close each handle once and clear the module handles (avoid a later # StopWatchdog / re-Spawn double-closing). @@ -498,9 +498,9 @@ def SpawnWatchdog(IntervalSec: int, TimeoutMs: int) -> int: # the same msg because consumers abort on "exit"==1; the precise reason goes to stderr above. VLog.StdoutWrite("{\"exit\":1, \"msg\": \"timeout/ok!=1\"}\n") return 0 - VLog.LogFmt2("[confirm] 心跳看门狗已启动 (pid=%u, 每 %u 秒一次", + VLog.LogFmt2("[confirm] heartbeat watchdog started (pid=%u, every %u seconds", sizet(Pi.dwProcessId), sizet(IntervalSec)) - VLog.LogFmt1(", 确认超时 %u ms)\n", sizet(TimeoutMs)) + VLog.LogFmt1(", confirmation timeout %u ms)\n", sizet(TimeoutMs)) return 1 @@ -599,16 +599,16 @@ def GuardClassifyLine(Buf: bytes, Len: int) -> int: # stderr-only and does not change heartbeat semantics. def GuardForwardLine(): if Guard_IpcWrite is None or Guard_IpcWrite == wb.INVALID_HANDLE_VALUE: - VLog.LogStr("[confirm] 警告: 收到 check 请求但无 check 通道(未传 --ipc-write),已丢弃该行\n") + VLog.LogStr("[confirm] Warning: check request received but no check channel (--ipc-write not passed), line dropped\n") return bw: ULONG = 0 if Guard_Fill > 0: if wf.WriteFile(Guard_IpcWrite, Guard_Line, ULONG(Guard_Fill), &bw, None) == 0: - VLog.LogStr("[confirm] 警告: check 请求转发失败(写管道失败),已丢弃该行\n") + VLog.LogStr("[confirm] Warning: check request forward failed (pipe write failed), line dropped\n") return if wf.WriteFile(Guard_IpcWrite, "\n", 1, &bw, None) == 0: - VLog.LogStr("[confirm] 警告: check 请求转发失败(写行分隔符失败),该行可能不完整\n") + VLog.LogStr("[confirm] Warning: check request forward failed (line separator write failed), the line may be incomplete\n") # ============================================================ @@ -673,7 +673,7 @@ def GuardFeedPending() -> int: def GuardPendPut(Ch: int): global Guard_PendLen if Guard_PendLen >= GUARD_PEND_CAP: - VLog.LogFmt1("[confirm] 警告: 未消费输入 FIFO 已满(容量 %u),丢弃该批字节\n", + VLog.LogFmt1("[confirm] Warning: unconsumed-input FIFO full (capacity %u), dropping this byte batch\n", sizet(GUARD_PEND_CAP)) return Guard_Pend[Guard_PendLen] = char(Ch) @@ -767,7 +767,7 @@ def GuardEnterRaw(hIn: wb.HANDLE) -> int: if SetConsoleCtrlHandler(GuardCtrlHandler, GUARD_CTRL_ADD) != 0: Guard_CtrlHandlerOn = 1 else: - VLog.LogStr("[confirm] 警告: SetConsoleCtrlHandler 注册失败,Ctrl+C 时该终端可能残留已清行输入的模式\n") + VLog.LogStr("[confirm] Warning: SetConsoleCtrlHandler registration failed; on Ctrl+C this console may keep the mode with line input cleared\n") if wc.SetConsoleMode(hIn, New) == 0: # Clear Guard_RawActive before Guard_SavedMode: the handler writes back only when # RawActive != 0, so it never pushes the zeroed SavedMode to the console. @@ -887,7 +887,7 @@ def GuardPumpStream(hIn: wb.HANDLE, Kind: int) -> int: # TerminateProcess(parent) -> sys.exit(1). The parent is killed with no cleanup (no cache, no JSON). def GuardWatchFail(hParent: wb.HANDLE, Reason: str): if Reason is not None: - VLog.LogFmtS1("[confirm] 失败: %s\n", Reason) + VLog.LogFmtS1("[confirm] Failure: %s\n", Reason) VLog.StdoutWrite("{\"exit\":1, \"msg\": \"timeout/ok!=1\"}\n") if hParent is not None and hParent != wb.INVALID_HANDLE_VALUE: wp.TerminateProcess(hParent, 1) @@ -926,7 +926,7 @@ def GuardWaitConfirm(hIn: wb.HANDLE, hParent: wb.HANDLE, Kind: int, TimeoutMs: i # Clear ENABLE_LINE_INPUT so Enter arrives as a KEY_EVENT we can judge ourselves (see module # head "Console mode tradeoff"). If the mode cannot be read/switched, fail as usual. if GuardEnterRaw(hIn) == 0: - GuardWatchFail(hParent, "控制台模式读取/切换失败") + GuardWatchFail(hParent, "console mode read/switch failed") return 0 Deadline: ULONGLONG = wb.GetTickCount64() + ULONGLONG(uint32(TimeoutMs)) while True: @@ -949,13 +949,13 @@ def GuardWaitConfirm(hIn: wb.HANDLE, hParent: wb.HANDLE, Kind: int, TimeoutMs: i if Cls == GUARD_LINE_BADOK: # valid shape but bad value => fatal failure with the same stderr text GuardLeaveRaw(hIn) - VLog.LogFmtS1("[confirm] 收到非 {\"ok\": 1} 的输入: %s\n", str(Guard_Line)) + VLog.LogFmtS1("[confirm] received input that is not {\"ok\": 1}: %s\n", str(Guard_Line)) GuardWatchFail(hParent, "ok != 1") return 0 # suspect shape (first char not '{' / no '}' / bad length, incl. empty) => echo (truncated) and ignore if Guard_Fill > GUARD_SUSPECT_ECHO_MAX: Guard_Line[GUARD_SUSPECT_ECHO_MAX] = 0 # echo only the prefix (the line is then dropped) - VLog.LogFmtS1("[confirm] 忽略可疑输入行: %s\n", str(Guard_Line)) + VLog.LogFmtS1("[confirm] ignoring suspect input line: %s\n", str(Guard_Line)) Guard_Fill = 0 Guard_Line[0] = 0 # Both ignore paths fall through to the deadline check + wait below. Ignoring does not @@ -964,15 +964,15 @@ def GuardWaitConfirm(hIn: wb.HANDLE, hParent: wb.HANDLE, Kind: int, TimeoutMs: i if R < 0: GuardLeaveRaw(hIn) if R == GUARD_PUMP_EOF: - GuardWatchFail(hParent, "stdin 已到 EOF,不可能再有输入") + GuardWatchFail(hParent, "stdin reached EOF, no more input possible") else: - GuardWatchFail(hParent, "读取 stdin 失败") + GuardWatchFail(hParent, "reading stdin failed") return 0 # (3) nothing read: wait for stdin readable / parent exit / deadline, cap min(remaining, GUARD_POLL_MS) Rem2: ULONG = GuardRemainMs(Deadline) if Rem2 == 0: GuardLeaveRaw(hIn) - GuardWatchFail(hParent, "超时无输入") + GuardWatchFail(hParent, "timeout with no input") return 0 Sl: ULONG = Rem2 if Sl > ULONG(GUARD_POLL_MS): @@ -987,7 +987,7 @@ def GuardWaitConfirm(hIn: wb.HANDLE, hParent: wb.HANDLE, Kind: int, TimeoutMs: i return 0 if Wm == ULONG(wb.WAIT_FAILED): GuardLeaveRaw(hIn) - GuardWatchFail(hParent, "等待输入失败") + GuardWatchFail(hParent, "waiting for input failed") return 0 # other results (stdin signaled / WAIT_TIMEOUT) => loop back and pump again GuardLeaveRaw(hIn) @@ -1007,23 +1007,23 @@ def RunConfirmWatch() -> int: ParentPid: LONGLONG = VCli.WatchParentPid() IntervalMs: ULONG = ULONG(IntervalSec) * ULONG(1000) if GuardWatchInit() == 0: - VLog.LogStr("[confirm] 看门狗: 行/记录/时间戳/未消费输入缓冲分配失败\n") + VLog.LogStr("[confirm] watchdog: line/record/timestamp/unconsumed-input buffer allocation failed\n") return 1 - VLog.LogFmt3("[confirm] 看门狗启动: 每 %u 秒要求一次 {\"ok\": 1},超时 %u ms,父进程 pid=%u\n", + VLog.LogFmt3("[confirm] watchdog started: requires {\"ok\": 1} every %u seconds, timeout %u ms, parent pid=%u\n", sizet(IntervalSec), sizet(TimeoutMs), sizet(ParentPid)) # Parent handle: used both for parent-exit detection (SYNCHRONIZE) and to terminate the parent hParent: wb.HANDLE = wp.OpenProcess(ULONG(WATCH_PARENT_ACCESS), 0, ULONG(ParentPid)) if hParent is None or hParent == wb.INVALID_HANDLE_VALUE: # No parent handle => cannot monitor or terminate; log to stderr and exit 1 - VLog.LogFmt1("[confirm] 看门狗: OpenProcess 父进程失败 (GetLastError=%u),自身退出\n", + VLog.LogFmt1("[confirm] watchdog: OpenProcess on parent failed (GetLastError=%u), exiting\n", sizet(wb.GetLastError())) return 1 hIn: wb.HANDLE = wf.GetStdHandle(wf.STD_INPUT_HANDLE) if hIn is None or hIn == wb.INVALID_HANDLE_VALUE: - GuardWatchFail(hParent, "stdin 句柄无效") + GuardWatchFail(hParent, "stdin handle invalid") return 1 # check channel write end: the handle value passed by the parent via `--ipc-write `, @@ -1035,42 +1035,42 @@ def RunConfirmWatch() -> int: Ch0: int = 0 if Guard_IpcWrite is not None: Ch0 = 1 - VLog.VerboseFmt1("[confirm] 看门狗: check 通道=%u (1=已配置 0=无)\n", sizet(Ch0)) + VLog.VerboseFmt1("[confirm] watchdog: check channel=%u (1=configured 0=none)\n", sizet(Ch0)) # Input kind is classified once (the handle never changes); console and pipe/redirect pump differently. Kind: int = GuardInputKind(hIn) - VLog.VerboseFmt1("[confirm] 看门狗: stdin 形态=%u (1=控制台 2=管道 3=其它流)\n", + VLog.VerboseFmt1("[confirm] watchdog: stdin kind=%u (1=console 2=pipe 3=other stream)\n", sizet(Kind)) # Console pump path (Hardening 1): primary ReadConsoleInputExA+NOWAIT, fallback query+ReadConsoleInputA. # Resolve once here (later rounds reuse the cached state) and log the chosen path under --verbose. if Kind == GUARD_IN_CONSOLE: GuardResolveReadEx() - VLog.VerboseFmt1("[confirm] 看门狗: 控制台取数路径=%u (1=ReadConsoleInputExA+NOWAIT 2=降级查询+ReadConsoleInputA)\n", + VLog.VerboseFmt1("[confirm] watchdog: console read path=%u (1=ReadConsoleInputExA+NOWAIT 2=fallback query+ReadConsoleInputA)\n", sizet(Guard_ReadExState)) while True: # Phase 1: wait interval; if the parent exited first, exit immediately (no orphans) Ws: ULONG = wsync.WaitForSingleObject(hParent, IntervalMs) if Ws == wb.WAIT_OBJECT_0: - VLog.LogStr("[confirm] 看门狗: 父进程已退出,自身退出\n") + VLog.LogStr("[confirm] watchdog: parent exited, exiting\n") wb.CloseHandle(hParent) return 0 if Ws != wb.WAIT_TIMEOUT: - VLog.LogFmt1("[confirm] 看门狗: 等待父进程失败 (wait=%u)\n", sizet(Ws)) - GuardWatchFail(hParent, "等待父进程失败") + VLog.LogFmt1("[confirm] watchdog: waiting for parent failed (wait=%u)\n", sizet(Ws)) + GuardWatchFail(hParent, "waiting for parent failed") return 1 # Phase 2: stderr prompt (deadline starts here) + non-blocking wait for a complete classified line - VLog.LogFmt2("[confirm] 请在 %u ms 内输入 {\"ok\": 1}(每 %u 秒一次)\n", + VLog.LogFmt2("[confirm] please enter {\"ok\": 1} within %u ms (every %u seconds)\n", sizet(TimeoutMs), sizet(IntervalSec)) VLog.TimeStampNow(Guard_Stamp, GUARD_STAMP_CAP) VLog.TimeStampAfter(Guard_Dl, GUARD_STAMP_CAP, sizet(TimeoutMs)) - VLog.LogFmtS2("[confirm] 当前 %s, 本轮期限 %s\n", str(Guard_Stamp), str(Guard_Dl)) + VLog.LogFmtS2("[confirm] now %s, this-round deadline %s\n", str(Guard_Stamp), str(Guard_Dl)) # Failure paths (deadline / bad value / read error / EOF) already finalized the process inside # GuardWaitConfirm; a 0 return only means "parent exited", so the watchdog exits itself. if GuardWaitConfirm(hIn, hParent, Kind, TimeoutMs) == 0: - VLog.LogStr("[confirm] 看门狗: 父进程已退出,自身退出\n") + VLog.LogStr("[confirm] watchdog: parent exited, exiting\n") wb.CloseHandle(hParent) return 0 - VLog.LogFmt1("[confirm] 确认成功 (ok=1),下一次约 %u 秒后\n", sizet(IntervalSec)) + VLog.LogFmt1("[confirm] confirmed (ok=1), next in about %u seconds\n", sizet(IntervalSec)) diff --git a/App/lib/VJson.vp b/App/lib/VJson.vp index 636b6ff..cc7111b 100644 --- a/App/lib/VJson.vp +++ b/App/lib/VJson.vp @@ -95,12 +95,12 @@ def BuildEntry(Idx: int) -> str: ValNeed = ValNeed + string.strlen(VCache.CacheSrc(Idx)) # source ("workspace"/"check") Need: sizet = sizet(JSON_ENTRY_POOL_FIXED) + ValNeed if Json_Pool.AllocOk(Need) == 0: - VLog.VerboseFmtIS(" 警告: JSON 工作池不足(本条需 %zu 字节),已跳过: %s\n", + VLog.VerboseFmtIS(" Warning: JSON pool insufficient (this entry needs %zu bytes), skipped: %s\n", Need, VCache.CacheExe(Idx)) return None Obj: json.JsonValue* = json.object(Json_Pool) if Obj == None: - VLog.VerboseStr(" 警告: JSON 对象分配失败(工作池不足),已跳过该条目\n") + VLog.VerboseStr(" Warning: JSON object allocation failed (pool insufficient), entry skipped\n") return None # Key insertion order = output order. Convert executable/displayName to UTF-8 and hand to the # library at once: Conv_Buf is reused, so a later copy would overwrite the executable string. @@ -130,19 +130,19 @@ def BuildEntry(Idx: int) -> str: N += 1 cu = cu.next if Ok == 0 or N != 6: - VLog.VerboseStr(" 警告: JSON 条目构造不完整(工作池不足),已跳过该条目\n") + VLog.VerboseStr(" Warning: JSON entry construction incomplete (pool insufficient), entry skipped\n") return None # Capacity guard: the library's write default cap=4096 returns None on overflow; guard early # to avoid a dropped entry. Output <= 2*Sum + SLACK(512) <= JSON_ENTRY_MAX. if 2 * Sum + sizet(JSON_ENTRY_SLACK) > sizet(JSON_ENTRY_MAX): - VLog.VerboseFmtIS(" 警告: JSON 条目过长(超过 %zu 字节),已跳过: %s\n", + VLog.VerboseFmtIS(" Warning: JSON entry too long (exceeds %zu bytes), skipped: %s\n", sizet(JSON_ENTRY_MAX), VCache.CacheExe(Idx)) return None Txt: str = json.write(Json_Pool, Obj, False) if Txt is None: - VLog.VerboseStr(" 警告: JSON 序列化失败(工作池不足),已跳过该条目\n") + VLog.VerboseStr(" Warning: JSON serialization failed (pool insufficient), entry skipped\n") return None return Txt @@ -152,7 +152,7 @@ def EmitJson() -> int: JReset() if Json_Pool is None: # invariant: EmitJson is reached only after JsonInit succeeds; this branch is only to avoid a crash - VLog.LogStr(" 警告: JSON 工作池未初始化,跳过本轮 JSON 输出\n") + VLog.LogStr(" Warning: JSON pool not initialized, skipping JSON output this round\n") return 0 Truncated: int = 0 Skipped: int = 0 @@ -183,9 +183,9 @@ def EmitJson() -> int: if JWrite("\n") == 0: Truncated = 1 if Truncated != 0: - VLog.LogFmt2(" 警告: JSON 输出缓冲不足,本轮已截断(已写 %zu 条 / 缓存 %zu 条)\n", + VLog.LogFmt2(" Warning: JSON output buffer insufficient, round truncated (wrote %zu entries / cache %zu entries)\n", sizet(Count), sizet(VCache.CacheCount())) if Skipped != 0: - VLog.LogFmt1(" 警告: 本轮有 %zu 条 JSON 条目因过长/工作池不足被跳过\n", + VLog.LogFmt1(" Warning: %zu JSON entries skipped this round due to excessive length / insufficient pool\n", sizet(Skipped)) return 0 diff --git a/App/lib/VPe.vp b/App/lib/VPe.vp index 6fb77d0..af8bce9 100644 --- a/App/lib/VPe.vp +++ b/App/lib/VPe.vp @@ -294,19 +294,19 @@ def Phase1VersionSection(Target: str) -> int: if buf is None: rc_err: int = VFs.LastReadErr if rc_err == 1: - VLog.LogFmt1(" 打开文件失败 (win32 err=%u)\n", sizet(VFs.LastReadWinErr)) + VLog.LogFmt1(" open file failed (win32 err=%u)\n", sizet(VFs.LastReadWinErr)) elif rc_err == 2: - VLog.LogStr(" 读取文件大小失败\n") + VLog.LogStr(" read file size failed\n") elif rc_err == 3: - VLog.LogStr(" 文件为空\n") + VLog.LogStr(" file is empty\n") else: - VLog.LogStr(" 分配缓冲区失败\n") + VLog.LogStr(" buffer allocation failed\n") return 1 total: sizet = VFs.LastReadSize Pe_DbgGot = total if total < 0x40: - VLog.LogStr(" 不是有效的 PE 文件(文件过短)\n") + VLog.LogStr(" not a valid PE file (file too short)\n") PeDbgPrint(1, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 @@ -315,7 +315,7 @@ def Phase1VersionSection(Target: str) -> int: # DOS header if ReadU16(ub, 0) != DOS_SIGNATURE: - VLog.LogStr(" 不是有效的 PE 文件(缺少 MZ 头)\n") + VLog.LogStr(" not a valid PE file (missing MZ header)\n") PeDbgPrint(2, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 @@ -324,12 +324,12 @@ def Phase1VersionSection(Target: str) -> int: lfanew: uint32 = ReadU32(ub, E_LFANEW_OFF) Pe_DbgLfanew = lfanew if sizet(lfanew) + 24 > total: - VLog.LogStr(" 不是有效的 PE 文件(e_lfanew 越界)\n") + VLog.LogStr(" not a valid PE file (e_lfanew out of range)\n") PeDbgPrint(3, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 if ReadU32(ub, int(lfanew)) != NT_SIGNATURE: - VLog.LogStr(" 不是有效的 PE 文件(缺少 PE 签名)\n") + VLog.LogStr(" not a valid PE file (missing PE signature)\n") PeDbgPrint(4, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 @@ -340,7 +340,7 @@ def Phase1VersionSection(Target: str) -> int: Pe_DbgOptSize = optsize magic: uint32 = ReadU16(ub, int(lfanew) + OPT_MAGIC_OFF) if magic != OPT_MAGIC_PE32 and magic != OPT_MAGIC_PE32P: - VLog.LogFmt1(" 可选头 Magic 未知: 0x%X\n", magic) + VLog.LogFmt1(" unknown optional-header Magic: 0x%X\n", magic) PeDbgPrint(5, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 @@ -348,7 +348,7 @@ def Phase1VersionSection(Target: str) -> int: sec_off: int = int(lfanew) + 24 + int(optsize) Pe_DbgSecOff = uint32(sec_off) if sizet(sec_off) + sizet(nsec) * SEC_ENTRY_SIZE > total: - VLog.LogFmt1(" 节表越界(节数=%u)\n", nsec) + VLog.LogFmt1(" section table out of range (section count=%u)\n", nsec) PeDbgPrint(6, total, uint32(0), uint32(0)) stdlib.free(t.CPtr(buf)) return 1 @@ -366,9 +366,9 @@ def Phase1VersionSection(Target: str) -> int: break if found == 0: - VLog.LogFmtS1(" 未找到 %s 节\n", VERSION_SECTION) + VLog.LogFmtS1(" section %s not found\n", VERSION_SECTION) PeDbgPrint(7, total, uint32(0), uint32(0)) - VLog.LogStr(" 实际节名:\n") + VLog.LogStr(" actual section names:\n") name8: bytes = stdlib.malloc(9) if name8 is not None: for j in range(int(nsec)): @@ -380,7 +380,7 @@ def Phase1VersionSection(Target: str) -> int: # up to the first NUL if sizet(raw_ptr) + sizet(raw_size) > total: - VLog.LogFmt2(" 段内容越界 (offset=%u size=%u)\n", raw_ptr, raw_size) + VLog.LogFmt2(" section content out of range (offset=%u size=%u)\n", raw_ptr, raw_size) PeDbgPrint(6, total, raw_ptr, raw_size) stdlib.free(t.CPtr(buf)) return 1 @@ -388,8 +388,8 @@ def Phase1VersionSection(Target: str) -> int: while vlen < raw_size and ub[int(raw_ptr) + int(vlen)] != 0: vlen += 1 - VLog.LogFmt1(" 原始长度: %u 字节\n", vlen) - VLog.LogFmtS1(" 版本串: %s\n", str(buf + int(raw_ptr))) + VLog.LogFmt1(" raw length: %u bytes\n", vlen) + VLog.LogFmtS1(" version string: %s\n", str(buf + int(raw_ptr))) stdlib.free(t.CPtr(buf)) return 0 @@ -397,33 +397,33 @@ def Phase1VersionSection(Target: str) -> int: # ver subcommand: [0/3] -> [1/3] -> [2/3] checks and exit codes (logs to stderr) def RunVer() -> int: if sys._argc < 3 or sys._argv[2] is None: - VLog.LogStr("用法: VET.exe ver <目标 exe 路径>\n") + VLog.LogStr("Usage: VET.exe ver \n") return 1 target: str = sys._argv[2] # banner (no path) is kept; the target path is process detail, --verbose only VLog.LogFmtS1("VET - Viper Environment Tool %s\n\n", VCli.Version()) - VLog.VerboseFmtS1("目标: %s\n\n", target) + VLog.VerboseFmtS1("target: %s\n\n", target) - VLog.LogStr("[0/3] 常用目录表\n") + VLog.LogStr("[0/3] common directory table\n") rc0: int = VDirs.BuildTable() if rc0 == 0: - VLog.LogStr(" ✓ 通过\n\n") + VLog.LogStr(" ✓ pass\n\n") else: - VLog.LogStr(" ✗ 失败(表为空)\n\n") + VLog.LogStr(" ✗ fail (table empty)\n\n") - VLog.LogFmtS1("[1/3] 内嵌版本段 (%s)\n", VERSION_SECTION) + VLog.LogFmtS1("[1/3] embedded version section (%s)\n", VERSION_SECTION) rc1: int = Phase1VersionSection(target) if rc1 == 0: - VLog.LogStr(" ✓ 通过\n\n") + VLog.LogStr(" ✓ pass\n\n") else: - VLog.LogStr(" ✗ 失败\n\n") + VLog.LogStr(" ✗ fail\n\n") - VLog.LogStr("[2/3] --version 前缀\n") + VLog.LogStr("[2/3] --version prefix\n") rc2: int = VProc.RunVersionPrefixCheck(target) if rc2 == 0: - VLog.LogStr(" ✓ 通过\n") + VLog.LogStr(" ✓ pass\n") else: - VLog.LogStr(" ✗ 失败\n") + VLog.LogStr(" ✗ fail\n") if rc0 == 0 and rc1 == 0 and rc2 == 0: return 0 diff --git a/App/lib/VProc.vp b/App/lib/VProc.vp index 7048264..ef65e57 100644 --- a/App/lib/VProc.vp +++ b/App/lib/VProc.vp @@ -94,23 +94,23 @@ def RunVersionProbe(Target: str, Out: bytes, OutCap: sizet, Trace: int) -> int: if Target is None or Out is None or OutCap < 2: Probe_LaunchStage = 1 if Trace != 0: - VLog.VerboseStr(" [--version] 启动失败 (rc=1): 参数非法\n") + VLog.VerboseStr(" [--version] launch failed (rc=1): invalid arguments\n") return 1 if string.strlen(Target) > sizet(PROBE_TARGET_MAX): Probe_LaunchStage = 1 - VLog.LogStr(" 警告: --version 目标路径过长 (rc=1),已跳过该候选\n") + VLog.LogStr(" Warning: --version target path too long (rc=1), candidate skipped\n") return 1 T0: ULONGLONG = wb.GetTickCount64() if Trace != 0: - VLog.VerboseFmtS1(" [--version] 开始: %s\n", Target) + VLog.VerboseFmtS1(" [--version] start: %s\n", Target) # --- command buffer: "" --version --- n: sizet = string.strlen(Target) + sizet(PROBE_CMD_EXTRA_CAP) CmdLine: bytes = stdlib.malloc(n) if CmdLine is None: Probe_LaunchStage = 2 - VLog.LogStr(" 警告: --version 探测启动失败 (rc=1, 命令缓冲分配失败)\n") + VLog.LogStr(" Warning: --version probe launch failed (rc=1, command buffer allocation failed)\n") return 1 viperlib.snprintf(CmdLine, n, "\"%s\" --version", Target) @@ -130,7 +130,7 @@ def RunVersionProbe(Target: str, Out: bytes, OutCap: sizet, Trace: int) -> int: Probe_LaunchStage = 3 Probe_LaunchErr = PipeErr stdlib.free(t.CPtr(CmdLine)) - VLog.LogStr(" 警告: --version 探测启动失败 (rc=1, CreatePipe)\n") + VLog.LogStr(" Warning: --version probe launch failed (rc=1, CreatePipe)\n") return 1 # The read end is not inherited (write-end inheritance is set by bInheritHandle) wf.SetHandleInformation(hRead, wf.HANDLE_FLAG_INHERIT, 0) @@ -156,7 +156,7 @@ def RunVersionProbe(Target: str, Out: bytes, OutCap: sizet, Trace: int) -> int: Probe_LaunchErr = CreateErr wb.CloseHandle(hRead) wb.CloseHandle(hWrite) - VLog.LogFmt1(" 警告: --version 探测启动失败 (rc=1, CreateProcessA, GetLastError=%u)\n", + VLog.LogFmt1(" Warning: --version probe launch failed (rc=1, CreateProcessA, GetLastError=%u)\n", sizet(CreateErr)) return 1 @@ -199,28 +199,28 @@ def RunVersionProbe(Target: str, Out: bytes, OutCap: sizet, Trace: int) -> int: if TimedOut != 0: # Timeout: report the wait result (WAIT_TIMEOUT=258 / WAIT_FAILED=4294967295) and elapsed. # The candidate path and captured content are per-probe detail shown only with --verbose. - VLog.LogFmt3(" 警告: --version 探测超时 (rc=2, wait=%u, 上限 %u ms),已等待 %u ms 后终止子进程\n", + VLog.LogFmt3(" Warning: --version probe timeout (rc=2, wait=%u, limit %u ms), child process terminated after %u ms\n", sizet(Wr), sizet(VERSION_PROBE_TIMEOUT_MS), KillMs) if total == 0: - VLog.VerboseStr(" 警告: 超时前已捕获 0 字节(空)\n") + VLog.VerboseStr(" Warning: captured 0 bytes before timeout (empty)\n") else: - VLog.VerboseFmt1(" 警告: 超时前已捕获 %u 字节,内容:\n", total) + VLog.VerboseFmt1(" Warning: captured %u bytes before timeout, content:\n", total) VLog.VerboseStr(str(Out)) VLog.VerboseStr("\n") if Trace != 0: - VLog.VerboseFmt4(" [--version] 结束: 耗时 %u ms, 退出码 %u, 超时 %u, 输出 %u 字节\n", + VLog.VerboseFmt4(" [--version] end: elapsed %u ms, exit code %u, timeout %u, output %u bytes\n", Elapsed, sizet(ExitCode), sizet(TimedOut), total) if TimedOut == 0: # Normal exit (rc=0): captured byte count and first line are per-probe detail (verbose only). Line: bytes = stdlib.malloc(PROBE_LINE_CAP) if Line is None: - VLog.VerboseFmt1(" [--version] 捕获 %u 字节(首行缓冲分配失败)\n", total) + VLog.VerboseFmt1(" [--version] captured %u bytes (first-line buffer allocation failed)\n", total) else: CopyFirstLine(Out, Line, PROBE_LINE_CAP) if total == 0: - VLog.VerboseStr(" [--version] 捕获 0 字节(空)\n") + VLog.VerboseStr(" [--version] captured 0 bytes (empty)\n") else: - VLog.VerboseFmtIS(" [--version] 捕获 %u 字节, 首行: %s\n", total, str(Line)) + VLog.VerboseFmtIS(" [--version] captured %u bytes, first line: %s\n", total, str(Line)) stdlib.free(t.CPtr(Line)) if TimedOut != 0: return 2 @@ -235,28 +235,28 @@ def RunVersionPrefixCheck(Target: str) -> int: OutCap: sizet = sizet(VERSION_PROBE_DIAG_CAP) Out: bytes = stdlib.malloc(OutCap) if Out is None: - VLog.LogStr(" 分配缓冲区失败\n") + VLog.LogStr(" buffer allocation failed\n") return 1 rc: int = RunVersionProbe(Target, Out, OutCap, 0) if rc == 1: - VLog.LogStr(" 子进程启动失败\n") + VLog.LogStr(" child process launch failed\n") stdlib.free(t.CPtr(Out)) return 1 if rc == 2: - VLog.LogStr(" 探测超时,判定失败\n") + VLog.LogStr(" probe timeout, marked as failure\n") stdlib.free(t.CPtr(Out)) return 1 - VLog.LogFmt1(" 退出码: %d\n", sizet(uint32(Probe_ExitCode))) + VLog.LogFmt1(" exit code: %d\n", sizet(uint32(Probe_ExitCode))) out: str = str(Out) if out is None: - VLog.LogStr(" 未捕获到 stdout\n") + VLog.LogStr(" no stdout captured\n") stdlib.free(t.CPtr(Out)) return 1 head: bytes = stdlib.malloc(6) if head is None: - VLog.LogStr(" 分配缓冲区失败\n") + VLog.LogStr(" buffer allocation failed\n") stdlib.free(t.CPtr(Out)) return 1 k: int = 0 @@ -266,13 +266,13 @@ def RunVersionPrefixCheck(Target: str) -> int: head[k] = 0 if string.strncmp(out, VERSION_PREFIX, 5) == 0: - VLog.LogFmtS1(" 前 5 字符: %s\n", str(head)) + VLog.LogFmtS1(" first 5 chars: %s\n", str(head)) stdlib.free(t.CPtr(head)) stdlib.free(t.CPtr(Out)) return 0 - VLog.LogFmtS2(" 前 5 字符: %s(期望为 %s)\n", str(head), VERSION_PREFIX) - VLog.LogStr(" 原始输出:\n") + VLog.LogFmtS2(" first 5 chars: %s (expected %s)\n", str(head), VERSION_PREFIX) + VLog.LogStr(" raw output:\n") VLog.LogStr(out) VLog.LogStr("\n") stdlib.free(t.CPtr(head)) diff --git a/App/lib/VScan.vp b/App/lib/VScan.vp index dac18ee..caeeb41 100644 --- a/App/lib/VScan.vp +++ b/App/lib/VScan.vp @@ -160,17 +160,17 @@ def ProgReset(RoundIdx: int, Roots: int): Prog_Cands = 0 Prog_Cur = None VLog.TimeStampNow(Prog_Stamp, PROG_STAMP_CAP) - VLog.VerboseFmt2("==== 扫盘轮次 %u 开始 (roots=%u", sizet(RoundIdx), sizet(Roots)) + VLog.VerboseFmt2("==== scan round %u start (roots=%u", sizet(RoundIdx), sizet(Roots)) VLog.VerboseFmtS1(", t=%s) ====\n", str(Prog_Stamp)) def ProgRootEnter(Dir: str): - VLog.VerboseFmtS1(" [root] 进入: %s\n", Dir) + VLog.VerboseFmtS1(" [root] enter: %s\n", Dir) def ProgRootLeave(Dir: str, ElapsedMs: sizet): global Prog_Cur - VLog.VerboseFmtIS(" [root] 离开 (耗时 %u ms): %s\n", ElapsedMs, Dir) + VLog.VerboseFmtIS(" [root] leave (%u ms elapsed): %s\n", ElapsedMs, Dir) Prog_Cur = None # path buffer is freed after this root; avoid a dangling pointer @@ -216,15 +216,15 @@ def ScanInit() -> int: Prog_Elapsed = _mbuddy.alloc(PROG_ELAPSED_CAP) if Scr_Ver is None or Scr_Arch is None or Scr_Id is None or Scr_Disp is None \ or Probe_Buf is None or Prog_Stamp is None or Prog_Elapsed is None: - VLog.LogStr("[VET] FATAL: 扫盘缓冲分配失败\n") + VLog.LogStr("[VET] FATAL: scan buffer allocation failed\n") return 0 if VJson.JsonInit() == 0: - VLog.LogStr("[VET] FATAL: 扫盘缓冲分配失败\n") + VLog.LogStr("[VET] FATAL: scan buffer allocation failed\n") return 0 # check channel buffers/reply pool: on failure degrade only (check replies # CHANNEL_UNAVAILABLE, no revalidation removal); scan itself is unaffected. if VCheck.CheckInit() == 0: - VLog.LogStr("警告: check 通道缓冲不可用,check 请求只回执失败原因(CHANNEL_UNAVAILABLE)、每轮不重校已发现项\n") + VLog.LogStr("Warning: check channel buffers unavailable; check requests only get the failure reason (CHANNEL_UNAVAILABLE), discovered entries are not revalidated each round\n") return 1 @@ -258,17 +258,17 @@ def HandleCandidate(ExeAnsi: str) -> int: # Poll the check channel before probing (a probe can take 5s; check outranks scanning). VGuard.PollIpc() if ProbeVersion(ExeAnsi) == 0: - VLog.VerboseFmtS1(" [跳过] PE+PRVERSN 命中但 --version 前缀不符: %s\n", ExeAnsi) + VLog.VerboseFmtS1(" [skip] PE+PRVERSN hit but --version prefix mismatch: %s\n", ExeAnsi) return 0 if VGuid.NewGuidStr(Scr_Id, VGuid.GUID_STR_CAP) == 0: - VLog.LogStr(" 警告: CoCreateGuid 失败,跳过该条目\n") + VLog.LogStr(" Warning: CoCreateGuid failed, skipping this entry\n") return 0 viperlib.snprintf(Scr_Disp, sizet(VCache.DISP_CAP), "Viper %s", Scr_Ver) if VCache.CacheAdd(ExeAnsi, str(Scr_Id), str(Scr_Ver), str(Scr_Arch), "workspace", str(Scr_Disp)) == 0: return 0 Round_Added += 1 - VLog.VerboseFmtS2(" [命中] %s (版本 %s)\n", ExeAnsi, str(Scr_Ver)) + VLog.VerboseFmtS2(" [hit] %s (version %s)\n", ExeAnsi, str(Scr_Ver)) return 1 @@ -349,7 +349,7 @@ def RevalidateDiscovered() -> int: Exe: str = VCache.CacheExe(j) # fetch first (RemoveAt frees this slot) VGuard.PollIpc() # poll before probe (check first) if VCheck.VerifyExecutable(Exe) == 0: - VLog.VerboseFmtS1(" [重校剔除] %s\n", Exe) + VLog.VerboseFmtS1(" [revalidate-remove] %s\n", Exe) VCache.RemoveAt(j) removed += 1 else: @@ -391,13 +391,13 @@ def RunScanRound(CachePath: str, RoundIdx: int) -> int: else: # Static auto-table entries and drive letters may not exist; logging each is # process detail, given only with --verbose (explicit --path warnings are in VDirs). - VLog.VerboseFmtS1(" 跳过(不存在或非目录): %s\n", str(AnsiDir)) + VLog.VerboseFmtS1(" skipped (missing or not a directory): %s\n", str(AnsiDir)) _mbuddy.free(t.CPtr(AnsiDir)) # Candidates filtered by PE/.PRVERSN: first REJECT_LOG_MAX were logged in HandleCandidate; # only a summary line is added here (both are process detail, --verbose only). if Reject_Total > REJECT_LOG_MAX: - VLog.VerboseFmt2(" [reject] 其余省略…(本轮累计 %u 条,已逐条打印前 %u 条)\n", + VLog.VerboseFmt2(" [reject] rest omitted... (round total %u, first %u printed individually)\n", sizet(Reject_Total), sizet(REJECT_LOG_MAX)) # Final poll before round end: no wait point before writing, so check hits enter this round's array @@ -410,14 +410,14 @@ def RunScanRound(CachePath: str, RoundIdx: int) -> int: T1: ULONGLONG = wb.GetTickCount64() # Round-end line (kept by default, no paths): liveness signal, or the final line under --once. # "Removed" = revalidation removals (Revalidated) + existence-check removals (removed). - VLog.LogFmt3("轮次 %u 结束: 扫描目录 %u 个, 已知条目 %u 项", + VLog.LogFmt3("round %u end: scanned dirs %u, known entries %u", sizet(RoundIdx), sizet(Dirs), sizet(VCache.CacheCount())) - VLog.LogFmt3(", 新增 %u 项, 移除 %u 项, 耗时 %u ms", + VLog.LogFmt3(", added %u, removed %u, elapsed %u ms", sizet(Round_Added), sizet(Revalidated + removed), sizet(T1 - T0)) # next-round-start timestamp is process detail (--verbose only) if VLog.VerboseOn() != 0: VLog.TimeStampAfter(Prog_Stamp, PROG_STAMP_CAP, sizet(VCli.SleepMs())) - VLog.LogFmtS1(", 下轮开始: %s", str(Prog_Stamp)) + VLog.LogFmtS1(", next round starts: %s", str(Prog_Stamp)) VLog.LogStr("\n") return 0 @@ -442,28 +442,28 @@ def RunScan() -> int: Pace_Configured = 1 Pace_Sleep_Ms = VCli.PaceSleepMs() Pace_File_Units = VCli.PaceFileUnits() - VLog.VerboseFmt2("--pace: 已启用扫描节流 sleep=%u units=%u\n", + VLog.VerboseFmt2("--pace: scan throttling enabled sleep=%u units=%u\n", sizet(Pace_Sleep_Ms), sizet(Pace_File_Units)) elif Once != 0: # No explicit throttle args: --once runs one round with throttle sleep disabled Pace_Enabled = 0 Pace_Configured = 0 - VLog.VerboseStr("--once: 已关闭扫描节流 sleep\n") + VLog.VerboseStr("--once: scan throttling sleep disabled\n") # --first-no-pace: affects round 1's actual switch only (RunScanRound restores + applies it); # so do not set Pace_Enabled here, just log one line (process detail, --verbose only). if VCli.FirstNoPace() != 0: - VLog.VerboseStr("--first-no-pace: 第 1 轮不启用节流 sleep\n") + VLog.VerboseStr("--first-no-pace: round 1 runs without throttle sleep\n") if ScanInit() == 0: return 1 - VLog.VerboseStr("[0/3] 常用目录表\n") + VLog.VerboseStr("[0/3] common directory table\n") rc0: int = VDirs.BuildTable() if rc0 == 0: - VLog.VerboseStr(" ✓ 通过\n\n") + VLog.VerboseStr(" ✓ pass\n\n") else: # Empty table = no scan roots this round: a functional anomaly, still reported by default - VLog.LogStr("警告: 常用目录表为空(本轮无扫描根)\n\n") + VLog.LogStr("Warning: common directory table is empty (no scan roots this round)\n\n") # Cache load moved to each round start (RunScanRound -> VCache.ReloadCache); no separate # read here, avoiding double parsing in round 1 (--once also goes through round 1). @@ -485,18 +485,18 @@ def RunScan() -> int: # stderr, return 0. Reuses VDirs.BuildTable; no scanning, no cache, exit code always 0. def RunSearchPathsQuery() -> int: VDirs.BuildTable() - Src: str = "自动表" + Src: str = "auto table" if VDirs.IsOverride() != 0: - Src = "覆盖表 (--path)" - VLog.LogFmtS1("[search] 目录表来源: %s\n", Src) + Src = "override table (--path)" + VLog.LogFmtS1("[search] directory table source: %s\n", Src) N: int = VDirs.DirCount() if N <= 0: # empty table must be stated explicitly so the user does not think it hung - VLog.LogStr("[search] 没有可搜索的路径(常用目录表为空)\n") + VLog.LogStr("[search] no searchable paths (common directory table is empty)\n") return 0 Ansi: bytes = _mbuddy.alloc(VFs.PATH_BUF_CAP) if Ansi is None: - VLog.LogStr(" 警告: 查询缓冲分配失败,仅列出路径(不标注是否会被扫盘跳过)\n") + VLog.LogStr(" Warning: query buffer allocation failed, listing paths only (no mark for scan-skip)\n") for i in range(N): Path: str = VDirs.DirAt(i) Skip: int = 0 # 1 = will be skipped when scanning; stays 0 if Ansi unavailable @@ -505,10 +505,10 @@ def RunSearchPathsQuery() -> int: if VFs.PathIsDir(str(Ansi)) == 0: Skip = 1 if Skip != 0: - VLog.LogFmtIS(" [search] [%u] %s (不存在或非目录,扫盘时会跳过)\n", sizet(i), Path) + VLog.LogFmtIS(" [search] [%u] %s (missing or not a directory, skipped when scanning)\n", sizet(i), Path) else: VLog.LogFmtIS(" [search] [%u] %s\n", sizet(i), Path) if Ansi is not None: _mbuddy.free(t.CPtr(Ansi)) - VLog.LogFmt1(" [search] 合计 %u 条;未扫盘、未读写缓存,查询到此结束\n", sizet(N)) + VLog.LogFmt1(" [search] total %u; no scan, no cache access, query ends here\n", sizet(N)) return 0 diff --git a/App/main.vp b/App/main.vp index f00798b..d34e116 100644 --- a/App/main.vp +++ b/App/main.vp @@ -45,11 +45,11 @@ def main() -> int: # MemBuddy pool: sys._init_argv and all module allocations depend on it arena: bytes = stdlib.malloc(POOL_SIZE) if arena is None: - VLog.LogStr("[VET] FATAL: 内存池分配失败\n") + VLog.LogStr("[VET] FATAL: memory pool allocation failed\n") return 1 mb: memhub.MemBuddy* = memhub.MemBuddy(arena, POOL_SIZE) if mb is None: - VLog.LogStr("[VET] FATAL: MemBuddy 初始化失败\n") + VLog.LogStr("[VET] FATAL: MemBuddy initialization failed\n") return 1 # Inject the same pool into every module that declares _mbuddy; missing one makes its @@ -95,7 +95,7 @@ def main() -> int: # Failure is fatal: an explicit heartbeat request must not silently run unconfirmed. if VCli.NeedConfirm() > 0: if VGuard.SpawnWatchdog(VCli.NeedConfirm(), VCli.NeedConfirmTimeout()) == 0: - VLog.LogStr("错误: 心跳确认看门狗启动失败,已中止 scan\n") + VLog.LogStr("Error: heartbeat confirm watchdog launch failed, scan aborted\n") return 1 RcScan: int = VScan.RunScan() VGuard.StopWatchdog() # Always reap the watchdog on normal exit (incl. --once) to avoid orphans @@ -103,6 +103,6 @@ def main() -> int: # Hidden internal subcommand: heartbeat watchdog (not in usage; spawned by the scan branch) if string.strcmp(Cmd, "confirm-watch") == 0: return VGuard.RunConfirmWatch() - VLog.LogFmtS1("错误: 未知子命令 %s\n", Cmd) + VLog.LogFmtS1("Error: unknown subcommand %s\n", Cmd) VCli.PrintUsage() return 1