feat: Initial commit for OnEver Drive centralized backup system with Windows PyQt6 agent and Proxmox LXC deployment
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import math
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
|
||||
def compute_file_sha256(filepath: Path, buffer_size: int = 1024 * 1024) -> str:
|
||||
"""Calculates full SHA-256 checksum of a file using streaming buffers to avoid memory overhead."""
|
||||
hasher = hashlib.sha256()
|
||||
with open(filepath, "rb") as f:
|
||||
while True:
|
||||
chunk = f.read(buffer_size)
|
||||
if not chunk:
|
||||
break
|
||||
hasher.update(chunk)
|
||||
return hasher.hexdigest()
|
||||
|
||||
class FileChunker:
|
||||
"""Handles splitting large files into discrete chunks and calculating block hashes."""
|
||||
|
||||
def __init__(self, filepath: Path, chunk_size: int = 4 * 1024 * 1024):
|
||||
self.filepath = Path(filepath).resolve()
|
||||
if not self.filepath.exists():
|
||||
raise FileNotFoundError(f"File {filepath} not found")
|
||||
|
||||
self.file_size = self.filepath.stat().st_size
|
||||
self.chunk_size = chunk_size
|
||||
self.total_chunks = max(1, math.ceil(self.file_size / self.chunk_size))
|
||||
self._cached_sha256 = None
|
||||
|
||||
@property
|
||||
def full_sha256(self) -> str:
|
||||
if self._cached_sha256 is None:
|
||||
self._cached_sha256 = compute_file_sha256(self.filepath)
|
||||
return self._cached_sha256
|
||||
|
||||
def get_chunk(self, chunk_index: int) -> Tuple[bytes, str]:
|
||||
"""
|
||||
Reads the bytes for chunk `chunk_index` and returns (chunk_data, chunk_sha256).
|
||||
"""
|
||||
if chunk_index < 0 or chunk_index >= self.total_chunks:
|
||||
raise IndexError(f"Chunk index {chunk_index} out of bounds (total: {self.total_chunks})")
|
||||
|
||||
offset = chunk_index * self.chunk_size
|
||||
with open(self.filepath, "rb") as f:
|
||||
f.seek(offset)
|
||||
data = f.read(self.chunk_size)
|
||||
|
||||
chunk_sha256 = hashlib.sha256(data).hexdigest()
|
||||
return data, chunk_sha256
|
||||
Reference in New Issue
Block a user