1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
import json
import re
import subprocess
from pathlib import Path
from raveos_center import rendszerinfo
SNAP_PAC = Path("/usr/share/libalpm/hooks/05-snap-pac-pre.hook")
TIPUSOK = {"pre": "csomagművelet előtt", "post": "csomagművelet után", "single": "kézi"}
def _futtat(parancs, ido=30):
try:
return subprocess.run(parancs, capture_output=True, text=True, timeout=ido)
except (OSError, subprocess.TimeoutExpired):
return None
def fajlrendszer():
kimenet = _futtat(["findmnt", "-no", "FSTYPE", "/"])
return kimenet.stdout.strip() if kimenet and kimenet.returncode == 0 else ""
def gyoker_alvolumen():
kimenet = _futtat(["findmnt", "-no", "OPTIONS", "/"])
if not kimenet:
return ""
for opcio in kimenet.stdout.strip().split(","):
if opcio.startswith("subvol="):
return opcio[len("subvol="):]
return ""
def snapshots_csatolva():
kimenet = _futtat(["findmnt", "-no", "SOURCE", "/.snapshots"])
return bool(kimenet and kimenet.returncode == 0 and kimenet.stdout.strip())
def snap_pac():
return SNAP_PAC.exists()
def _elem(nyers):
tipus = nyers.get("type", "single")
adat = nyers.get("userdata") or {}
return {
"szam": nyers.get("number", 0),
"datum": (nyers.get("date") or "")[:16],
"tipus": tipus,
"tipus_nev": "telepítés" if adat.get("important") == "yes" and tipus == "single" else TIPUSOK.get(tipus, tipus),
"leiras": nyers.get("description") or "",
"pre_szam": nyers.get("pre-number"),
"aktiv": bool(nyers.get("active")),
}
def allapot():
fs = fajlrendszer()
adat = {
"fajlrendszer": fs,
"snapper": rendszerinfo.snapper_elerheto(),
"snap_pac": snap_pac(),
"alvolumen": gyoker_alvolumen(),
"csatolva": snapshots_csatolva(),
"lista": [],
"hiba": "",
}
if fs != "btrfs" or not adat["snapper"]:
return adat
kimenet = _futtat(["snapper", "--jsonout", "-c", "root", "list"])
if not kimenet or kimenet.returncode != 0:
adat["hiba"] = (kimenet.stderr.strip() if kimenet else "") or "A snapshotok listája nem olvasható."
return adat
try:
nyers = json.loads(kimenet.stdout).get("root", [])
except ValueError:
adat["hiba"] = "A snapper válasza nem értelmezhető."
return adat
adat["lista"] = [_elem(n) for n in reversed(nyers) if n.get("number", 0) != 0]
return adat
def ervenyes_leiras(szoveg):
return 1 <= len(szoveg) <= 80 and all(c.isalnum() or c.isspace() or c in "._:,()-" for c in szoveg)
def kernel_valtozas(szam):
gyoker = Path(f"/.snapshots/{int(szam)}/snapshot")
valtozasok = []
try:
if not (gyoker / "usr/lib/modules").is_dir():
return None
pkgbase_fajlok = list(gyoker.glob("usr/lib/modules/*/pkgbase"))
except OSError:
return None
for pb in pkgbase_fajlok:
try:
nev = pb.read_text().strip()
except OSError:
continue
if not re.fullmatch(r"[a-z0-9][a-z0-9._+-]*", nev):
continue
regi = _futtat(["pacman", "--dbpath", str(gyoker / "var/lib/pacman"), "-Q", nev])
most = _futtat(["pacman", "-Q", nev])
regi_v = regi.stdout.split()[1] if regi and regi.returncode == 0 and len(regi.stdout.split()) > 1 else ""
most_v = most.stdout.split()[1] if most and most.returncode == 0 and len(most.stdout.split()) > 1 else ""
if regi_v and regi_v != most_v:
cache = any(
not p.name.endswith(".sig") for p in Path("/var/cache/pacman/pkg").glob(f"{nev}-{regi_v}-*.pkg.tar.*")
)
valtozasok.append({"nev": nev, "regi": regi_v, "most": most_v, "cache": cache})
return valtozasok
def snapper_telepitheto(adat):
return adat["fajlrendszer"] == "btrfs" and not adat["snapper"] and adat["alvolumen"] == "/@" and adat["csatolva"]
|