🔒 Repository is read-only – file editing is disabled.

PaganLinux/tmp-fill-sums.py main

151 linii Raw ← Powrót
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
#!/usr/bin/env python3
"""Uzupelnia sha256sums dla receptur krytycznych (tylko wpisy SKIP).

- lokalne pliki (paczki, configi) hashowane z katalogu receptury
- URL-e: podstawienie ${pkgname}/${pkgver}/${pkgrel}, pobranie, hash
- wpisy nierozwiazywalne (git://, brak pliku, blad sieci) zostaja jako SKIP
Format pliku poza blokiem sha256sums nie jest zmieniany.
"""
import hashlib, os, re, sys, tempfile, urllib.request, yaml

R = "/var/lib/pagan-sync/recipes"
APPLY = "--apply" in sys.argv
CRIT = {"glibc", "gcc", "binutils", "openssl", "gnutls", "nettle", "sudo", "shadow", "pam",
        "systemd", "dbus", "bash", "coreutils", "util-linux", "curl", "wget", "gnupg",
        "libgcrypt", "libgpg-error", "libassuan", "libksba", "libxcrypt", "make-ca",
        "openssh", "polkit", "seatd", "kernel", "kernel-lts", "kernel-mainline",
        "libcap", "e2fsprogs", "procps-ng", "python", "perl", "zlib", "xz", "tar",
        "libarchive", "pcre2", "expat", "iproute2", "kmod", "elfutils", "attr", "acl",
        "gzip", "bzip2", "less", "sed", "grep", "findutils", "gawk"}


def sha256_file(path, chunk=1 << 20):
    h = hashlib.sha256()
    with open(path, "rb") as f:
        while True:
            b = f.read(chunk)
            if not b:
                break
            h.update(b)
    return h.hexdigest()


def expand(s, pkgname, pkgver, pkgrel):
    for k, v in (("pkgname", pkgname), ("pkgver", pkgver), ("pkgrel", pkgrel)):
        s = s.replace("${%s}" % k, str(v)).replace("$%s" % k, str(v))
    return s


def as_list(v):
    if v is None:
        return []
    return v if isinstance(v, list) else [v]


def rewrite_sums(text, new_sums):
    lines = text.split("\n")
    out, i, handled = [], 0, False
    while i < len(lines):
        line = lines[i]
        if not handled and re.match(r"^sha256sums:", line):
            handled = True
            rest = line.split(":", 1)[1].strip()
            if rest.startswith("["):
                if not rest.endswith("]"):
                    return None
                out.append("sha256sums: [" + ", ".join(new_sums) + "]")
                i += 1
                continue
            out.append("sha256sums:")
            i += 1
            while i < len(lines) and re.match(r"^\s*-\s*", lines[i]):
                i += 1
            for v in new_sums:
                out.append("- " + v)
            continue
        out.append(line)
        i += 1
    return "\n".join(out) if handled else None


targets = []
for dp, _d, fs in os.walk(R):
    if "PAGBUILD.yaml" not in fs:
        continue
    p = os.path.join(dp, "PAGBUILD.yaml")
    try:
        d = yaml.safe_load(open(p, encoding="utf-8")) or {}
    except Exception:
        continue
    if d.get("pkgname") not in CRIT:
        continue
    sums = as_list(d.get("sha256sums"))
    if any(str(s).strip().upper().startswith("SKIP") for s in sums):
        targets.append((p, d))

print(f"receptur krytycznych z SKIP: {len(targets)}")
changed = filled = failed = 0
report = []
for path, d in sorted(targets):
    text = open(path, encoding="utf-8").read()
    srcs = as_list(d.get("source"))
    sums = as_list(d.get("sha256sums"))
    rel = path[len(R) + 1:]
    if len(srcs) != len(sums):
        report.append(f"POMINIETO (src={len(srcs)} sums={len(sums)}): {rel}")
        failed += 1
        continue
    new_sums, tmpfiles = [], []
    for src, cur in zip(srcs, sums):
        if not str(cur).strip().upper().startswith("SKIP"):
            new_sums.append(str(cur))
            continue
        raw = str(src)
        sub = expand(raw, d.get("pkgname"), d.get("pkgver"), d.get("pkgrel"))
        try:
            if sub.startswith(("http://", "https://", "ftp://")):
                tmp = tempfile.NamedTemporaryFile(delete=False)
                req = urllib.request.Request(sub, headers={"User-Agent": "pagan-audit/1.0"})
                with urllib.request.urlopen(req, timeout=300) as r, open(tmp.name, "wb") as f:
                    while True:
                        b = r.read(1 << 20)
                        if not b:
                            break
                        f.write(b)
                tmpfiles.append(tmp.name)
                h = sha256_file(tmp.name)
                new_sums.append(h)
                filled += 1
            else:
                local = os.path.join(os.path.dirname(path), sub)
                if os.path.isfile(local):
                    new_sums.append(sha256_file(local))
                    filled += 1
                else:
                    new_sums.append("SKIP")
                    report.append(f"  brak pliku lokalnego: {rel} :: {sub}")
                    failed += 1
        except Exception as e:
            new_sums.append("SKIP")
            report.append(f"  BLAD {rel} :: {sub} ({type(e).__name__})")
            failed += 1
    for t in tmpfiles:
        try:
            os.unlink(t)
        except OSError:
            pass
    new_text = rewrite_sums(text, new_sums)
    if new_text is None:
        report.append(f"POMINIETO (format sum): {rel}")
        failed += 1
        continue
    if new_text != text:
        if APPLY:
            open(path, "w", encoding="utf-8").write(new_text)
        changed += 1
        report.append(f"UZUPELNIONO: {rel}")

print(f"uzupelnionych wpisow: {filled} | plikow zmienionych: {changed} | problemow: {failed}")
print("tryb:", "APPLY" if APPLY else "DRY-RUN")
for line in report:
    print(line)