Usa API Win32 per verificare share

This commit is contained in:
2026-07-02 11:12:39 +02:00
parent afe08a89cb
commit 5d106c9dc6
2 changed files with 28 additions and 30 deletions

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import json
import socket
import subprocess
import ctypes
from dataclasses import asdict, dataclass
from datetime import datetime, timezone
from pathlib import Path
@@ -10,6 +10,10 @@ from pathlib import Path
from .config import BackupConfig
INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF
FILE_ATTRIBUTE_DIRECTORY = 0x00000010
@dataclass(frozen=True)
class ServerStatus:
reachable: bool
@@ -60,19 +64,15 @@ def check_backup_target(config: BackupConfig) -> ServerStatus:
def share_is_reachable(destination: str, timeout_seconds: int) -> bool:
probe = destination.rstrip("\\/") + "\\."
command = ["cmd.exe", "/d", "/c", f'if exist "{probe}" (exit /b 0) else (exit /b 1)']
del timeout_seconds
normalized = destination.rstrip("\\/")
try:
completed = subprocess.run(
command,
capture_output=True,
text=True,
timeout=max(timeout_seconds, 1),
check=False,
)
except (OSError, subprocess.TimeoutExpired):
attributes = ctypes.windll.kernel32.GetFileAttributesW(str(normalized))
except OSError:
return False
return completed.returncode == 0
if attributes == INVALID_FILE_ATTRIBUTES:
return False
return bool(attributes & FILE_ATTRIBUTE_DIRECTORY)
def write_status(path: Path, status: ServerStatus, pending_count: int) -> None:

View File

@@ -1,32 +1,30 @@
from __future__ import annotations
import subprocess
from bakrest.server_check import share_is_reachable
from bakrest.server_check import FILE_ATTRIBUTE_DIRECTORY, INVALID_FILE_ATTRIBUTES, share_is_reachable
def test_share_is_reachable_returns_true_on_zero_exit(monkeypatch) -> None:
def fake_run(*args, **kwargs):
return subprocess.CompletedProcess(args[0], 0)
monkeypatch.setattr("bakrest.server_check.subprocess.run", fake_run)
def test_share_is_reachable_returns_true_for_directory_attributes(monkeypatch) -> None:
monkeypatch.setattr(
"bakrest.server_check.ctypes.windll.kernel32.GetFileAttributesW",
lambda path: FILE_ATTRIBUTE_DIRECTORY,
)
assert share_is_reachable("\\\\server\\share", 3)
def test_share_is_reachable_returns_false_on_nonzero_exit(monkeypatch) -> None:
def fake_run(*args, **kwargs):
return subprocess.CompletedProcess(args[0], 1)
monkeypatch.setattr("bakrest.server_check.subprocess.run", fake_run)
def test_share_is_reachable_returns_false_for_invalid_attributes(monkeypatch) -> None:
monkeypatch.setattr(
"bakrest.server_check.ctypes.windll.kernel32.GetFileAttributesW",
lambda path: INVALID_FILE_ATTRIBUTES,
)
assert not share_is_reachable("\\\\server\\share", 3)
def test_share_is_reachable_returns_false_on_timeout(monkeypatch) -> None:
def fake_run(*args, **kwargs):
raise subprocess.TimeoutExpired(args[0], 3)
monkeypatch.setattr("bakrest.server_check.subprocess.run", fake_run)
def test_share_is_reachable_returns_false_for_non_directory(monkeypatch) -> None:
monkeypatch.setattr(
"bakrest.server_check.ctypes.windll.kernel32.GetFileAttributesW",
lambda path: 0,
)
assert not share_is_reachable("\\\\server\\share", 3)