diff options
Diffstat (limited to 'raveos-center/raveos_center/mentesek.py')
| -rw-r--r-- | raveos-center/raveos_center/mentesek.py | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/raveos-center/raveos_center/mentesek.py b/raveos-center/raveos_center/mentesek.py new file mode 100644 index 0000000..7afae01 --- /dev/null +++ b/raveos-center/raveos_center/mentesek.py @@ -0,0 +1,156 @@ +import io +import json +import subprocess +import tarfile +import time +from pathlib import Path + +from raveos_center import katalogus +from raveos_center.muveletek import HELPER + +JEGYZEK = "raveos-mentes.json" +JEGYZEK_VERZIO = 1 + + +def csoportok(): + utvonal = katalogus.adat_mappa() / "mentes" / "backup-paths.json" + return json.loads(utvonal.read_text(encoding="utf-8")).get("groups", []) + + +def elemek(): + lista = [] + for csoport in csoportok(): + for elem in csoport.get("items", []): + lista.append(dict(elem, csoport=csoport["id"])) + return lista + + +def abszolut(elem): + if elem.get("scope") == "system": + return Path(elem["path"]) + return Path.home() / elem["path"] + + +class Megszakitva(Exception): + pass + + +def _pkexec_hiba(kimenet): + if kimenet.returncode in (126, 127): + raise Megszakitva("a hitelesítés elmaradt, a további rendszerelemek kimaradnak") + + +def _root_tar(elem_id): + kimenet = subprocess.run(["pkexec", HELPER, "mentes-root", elem_id], capture_output=True, timeout=600) + _pkexec_hiba(kimenet) + if kimenet.returncode != 0: + raise RuntimeError(kimenet.stderr.decode(errors="replace").strip()[:200] or "a rendszerelem mentése nem sikerült") + return kimenet.stdout + + +def mentes(cel, kivalasztott, naplo, haladas): + jegyzek = {"verzio": JEGYZEK_VERZIO, "letrehozva": int(time.time()), "elemek": []} + megszakitva = False + with tarfile.open(cel, "w:gz") as tar: + for i, elem in enumerate(kivalasztott): + ut = abszolut(elem) + naplo(f"+ {katalogus.loc(elem.get('label'))} ({ut})") + try: + if elem.get("scope") == "system": + if megszakitva: + naplo(" kihagyva, mert a hitelesítés elmaradt") + continue + adat = _root_tar(elem["id"]) + info = tarfile.TarInfo(f"rendszer/{elem['id']}.tar") + info.size = len(adat) + info.mtime = int(time.time()) + tar.addfile(info, io.BytesIO(adat)) + elif ut.exists(): + tar.add(ut.resolve() if ut.is_symlink() else ut, arcname=f"home/{elem['path']}") + else: + naplo(" nincs ilyen mappa ezen a gépen, kihagyva") + continue + jegyzek["elemek"].append( + {"id": elem["id"], "label": elem.get("label"), "scope": elem.get("scope", "home"), "path": elem["path"]} + ) + except Megszakitva as e: + naplo(f" MEGSZAKÍTVA: {e}") + megszakitva = True + except Exception as e: + naplo(f" HIBA, kihagyva: {e}") + haladas(int((i + 1) * 100 / max(1, len(kivalasztott)))) + adat = json.dumps(jegyzek, ensure_ascii=False, indent=2).encode() + info = tarfile.TarInfo(JEGYZEK) + info.size = len(adat) + info.mtime = int(time.time()) + tar.addfile(info, io.BytesIO(adat)) + return len(jegyzek["elemek"]) + + +def tartalom(forras): + with tarfile.open(forras, "r:gz") as tar: + try: + tag = tar.getmember(JEGYZEK) + except KeyError: + return _regi_tartalom(tar) + return json.load(tar.extractfile(tag))["elemek"] + + +def _regi_tartalom(tar): + nevek = {t.name.split("/")[0] for t in tar.getmembers()} + talalt = [] + for elem in elemek(): + if Path(elem["path"]).name in nevek: + talalt.append( + {"id": elem["id"], "label": elem.get("label"), "scope": elem.get("scope", "home"), "path": elem["path"], "regi": True} + ) + return talalt + + +def _home_tagok(tar, elem): + if elem.get("regi"): + elotag = Path(elem["path"]).name + cel_szulo = (Path.home() / elem["path"]).parent + else: + elotag = f"home/{elem['path']}" + cel_szulo = Path.home() + for tag in tar.getmembers(): + if tag.name == elotag or tag.name.startswith(elotag + "/"): + if not elem.get("regi"): + tag.name = tag.name[len("home/"):] + if tag.islnk() and tag.linkname.startswith("home/"): + tag.linkname = tag.linkname[len("home/"):] + yield tag, cel_szulo + + +def visszaallitas(forras, kivalasztott, naplo, haladas): + kesz = 0 + megszakitva = False + with tarfile.open(forras, "r:gz") as tar: + for i, elem in enumerate(kivalasztott): + naplo(f"< {katalogus.loc(elem.get('label'))}") + try: + if elem.get("scope") == "system": + if elem.get("regi"): + raise RuntimeError("régi formátumú mentésből a rendszerelemek nem állíthatók vissza") + adat = tar.extractfile(tar.getmember(f"rendszer/{elem['id']}.tar")).read() + if megszakitva: + naplo(" kihagyva, mert a hitelesítés elmaradt") + continue + kimenet = subprocess.run( + ["pkexec", HELPER, "visszaallit-root", elem["id"]], input=adat, capture_output=True, timeout=600 + ) + _pkexec_hiba(kimenet) + if kimenet.returncode != 0: + raise RuntimeError(kimenet.stderr.decode(errors="replace").strip()[:200] or "sikertelen") + else: + for tag, cel_szulo in _home_tagok(tar, elem): + tar.extract(tag, path=cel_szulo, filter="data") + kesz += 1 + except Megszakitva as e: + naplo(f" MEGSZAKÍTVA: {e}") + megszakitva = True + except Exception as e: + naplo(f" HIBA, kihagyva: {e}") + haladas(int((i + 1) * 100 / max(1, len(kivalasztott)))) + return kesz |