Init
This commit is contained in:
59
ptdiag/filesystem.py
Normal file
59
ptdiag/filesystem.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""Read-only filesystem and hash verification helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from hashlib import sha256
|
||||
from pathlib import Path
|
||||
from typing import Mapping
|
||||
|
||||
|
||||
KNOWN_GAME_HASHES: dict[str, str] = {
|
||||
"Game.exe": "3cc0980aac0f65b379ff340ec61750498fb9f620fb6c88aa66281e8ab27023a5",
|
||||
"game.dll": "7ea85b19f452962a39c91f967cad22495f066b2d52e8ac37f4e234463d5c4f09",
|
||||
"gamese.exe": "c3443e50a93c6c778eff456122c351e5c7d2c1ceaea50e5a650bffe846a05c87",
|
||||
"gamese.dll": "0ae6822f5f347f04bd2b0dc947f0286089c711c84703e110f6f8fc6e0d626131",
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HashVerification:
|
||||
path: Path
|
||||
expected_sha256: str
|
||||
actual_sha256: str | None
|
||||
ok: bool
|
||||
error: str | None = None
|
||||
|
||||
def to_dict(self) -> dict[str, str | bool | None]:
|
||||
data = asdict(self)
|
||||
data["path"] = str(self.path)
|
||||
return data
|
||||
|
||||
|
||||
def sha256_file(path: Path, chunk_size: int = 1024 * 1024) -> str:
|
||||
if chunk_size <= 0:
|
||||
raise ValueError("chunk_size must be positive")
|
||||
digest = sha256()
|
||||
with path.open("rb") as handle:
|
||||
for chunk in iter(lambda: handle.read(chunk_size), b""):
|
||||
digest.update(chunk)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def verify_file_hash(path: Path, expected_sha256: str) -> HashVerification:
|
||||
expected = expected_sha256.casefold()
|
||||
try:
|
||||
actual = sha256_file(path)
|
||||
except (OSError, ValueError) as exc:
|
||||
return HashVerification(path, expected, None, False, str(exc))
|
||||
return HashVerification(path, expected, actual, actual == expected)
|
||||
|
||||
|
||||
def verify_hashes(expected: Mapping[Path, str]) -> list[HashVerification]:
|
||||
return [verify_file_hash(path, digest) for path, digest in expected.items()]
|
||||
|
||||
|
||||
def verify_known_game_hashes(live_game: Path) -> list[HashVerification]:
|
||||
expected = {live_game / name: digest for name, digest in KNOWN_GAME_HASHES.items()}
|
||||
return verify_hashes(expected)
|
||||
|
||||
Reference in New Issue
Block a user