🔒 Repository is read-only – file editing is disabled.
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)