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