fix(cli): wintun.dll 不再只按存在性判断
此前仅当 wintun.dll 不存在时才释放内嵌版本,损坏或被替换的旧版 dll 会永久残留,后续创建 TUN 设备时才以难以理解的方式失败。 改为与内嵌版本做内容比较,不一致(不存在/损坏/旧版)即重写。 测试:缺失时写入、损坏时重写、一致时跳过。
This commit is contained in:
@@ -25,9 +25,55 @@ fn extract_wintun_impl() -> io::Result<()> {
|
|||||||
.and_then(|p| p.parent().map(|d| d.join("wintun.dll")))
|
.and_then(|p| p.parent().map(|d| d.join("wintun.dll")))
|
||||||
.unwrap_or_else(|| Path::new("wintun.dll").to_path_buf());
|
.unwrap_or_else(|| Path::new("wintun.dll").to_path_buf());
|
||||||
|
|
||||||
if !path.exists() {
|
ensure_dll(&path)?;
|
||||||
let mut file = fs::File::create(&path)?;
|
|
||||||
file.write_all(WINTUN_DLL)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 确保 path 处的 dll 与内嵌版本一致,不一致(不存在/损坏/旧版)时重写。
|
||||||
|
/// 返回是否发生了写入。只按存在性判断会让损坏或旧版 dll 永久残留。
|
||||||
|
fn ensure_dll(path: &Path) -> io::Result<bool> {
|
||||||
|
let up_to_date = fs::read(path)
|
||||||
|
.map(|content| content.as_slice() == WINTUN_DLL)
|
||||||
|
.unwrap_or(false);
|
||||||
|
if up_to_date {
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
let mut file = fs::File::create(path)?;
|
||||||
|
file.write_all(WINTUN_DLL)?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn temp_dll_path(tag: &str) -> std::path::PathBuf {
|
||||||
|
std::env::temp_dir().join(format!("vnt_wintun_test_{}_{}.dll", std::process::id(), tag))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ensure_dll_writes_when_missing() {
|
||||||
|
let path = temp_dll_path("missing");
|
||||||
|
let _ = fs::remove_file(&path);
|
||||||
|
assert!(ensure_dll(&path).unwrap());
|
||||||
|
assert_eq!(fs::read(&path).unwrap(), WINTUN_DLL);
|
||||||
|
let _ = fs::remove_file(&path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ensure_dll_rewrites_corrupt() {
|
||||||
|
let path = temp_dll_path("corrupt");
|
||||||
|
fs::write(&path, b"corrupt").unwrap();
|
||||||
|
assert!(ensure_dll(&path).unwrap());
|
||||||
|
assert_eq!(fs::read(&path).unwrap(), WINTUN_DLL);
|
||||||
|
let _ = fs::remove_file(&path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ensure_dll_skips_when_up_to_date() {
|
||||||
|
let path = temp_dll_path("uptodate");
|
||||||
|
fs::write(&path, WINTUN_DLL).unwrap();
|
||||||
|
assert!(!ensure_dll(&path).unwrap());
|
||||||
|
let _ = fs::remove_file(&path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user