#!/usr/bin/env python3 """Root-owned, read-only pstore snapshot; never clears kernel/archive records.""" from datetime import datetime import grp import json import os from pathlib import Path import tempfile folder = Path('/var/lib/vdi-observer') folder.mkdir(mode=0o750, exist_ok=True) if folder.is_symlink() or folder.stat().st_uid != 0: raise RuntimeError('Unsafe pstore snapshot directory') gid = grp.getgrnam('systemd-journal').gr_gid os.chown(folder, 0, gid); os.chmod(folder, 0o750) data = {'captured_at': datetime.now().astimezone().isoformat(), 'boot_id': Path('/proc/sys/kernel/random/boot_id').read_text().strip(), 'sources': {}} for root in (Path('/sys/fs/pstore'), Path('/var/lib/systemd/pstore')): try: entries = {} for p in sorted(root.iterdir())[:8]: if p.is_symlink() or not p.is_file(): continue with p.open('rb') as stream: raw = stream.read(32768) entries[p.name] = {'mtime': p.stat().st_mtime, 'text': raw.decode(errors='replace'), 'truncated': p.stat().st_size > 32768} data['sources'][str(root)] = entries except OSError as e: data['sources'][str(root)] = {'error': str(e)} name = None try: with tempfile.NamedTemporaryFile(mode='w', encoding='utf-8', dir=folder, delete=False) as f: name = f.name; os.fchown(f.fileno(), 0, gid); os.fchmod(f.fileno(), 0o640) json.dump(data, f, ensure_ascii=False); f.flush(); os.fsync(f.fileno()) os.replace(name, folder/'pstore.json'); name = None fd = os.open(folder, os.O_RDONLY | os.O_DIRECTORY) try: os.fsync(fd) finally: os.close(fd) finally: if name: os.unlink(name)