tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1346Shell 97Rust 63Markdown 571650 Definiciones

⎇ a87b16dd852a3a6e7be7ad0f080b3ad97c75fdbc crates/hammerd/src/main.rs Rust · 75 líneas · 2.6 KB Historia Quién tocó qué crudo

Fase 3 — diario de mutaciones (hammer-journal + fanotify + hammer journal) a87b16dd8 · Sergio ·

1//! `hammerd` — daemon de hammer. Dos responsabilidades:
2//!   1. Diario de mutaciones: fanotify sobre /bin,/sbin,/lib,/etc → `hammer-journal`.
3//!   2. Bus de agente: /run/agent.sock (JSON-líneas, SO_PEERCRED). Ver `docs/07-agent-bus.md`.
4//!
5//! Fase 3 implementa (1). Fase 5 añadirá (2). Si el daemon arranca sin CAP_SYS_ADMIN, el
6//! watcher falla en init y el daemon sigue corriendo sin él (warn claro). Esto es
7//! deliberado para que puedas correr `hammerd` en dev sin sudo y aún así probar la parte
8//! del bus.
9
10use std::path::PathBuf;
11
12use clap::Parser;
13
14mod watcher;
15
16#[derive(Parser)]
17#[command(name = "hammerd", version, about = "Daemon de hammer: bus de agente + diario.")]
18struct Args {
19    /// Socket del bus de agente.
20    #[arg(long, default_value = "/run/agent.sock")]
21    agent_sock: String,
22    /// FIFO de control humano del init.
23    #[arg(long, default_value = "/run/init.control")]
24    init_control: String,
25    /// Directorio del diario de mutaciones.
26    #[arg(long, default_value = "/var/lib/hammer/journal")]
27    journal: String,
28    /// Directorio raíz de overlays (para que el watcher pueda filtrar eventos bajo overlays
29    /// activos). Default coincide con `hammer try`.
30    #[arg(long, default_value = hammer_overlay::DEFAULT_STATE_ROOT)]
31    overlay_state_root: String,
32    /// Directorios extra a vigilar; si vacío, usa los defaults del FHS (SDD 05 §2).
33    #[arg(long = "watch")]
34    extra_watch: Vec<PathBuf>,
35}
36
37fn main() -> anyhow::Result<()> {
38    tracing_subscriber::fmt()
39        .with_writer(std::io::stderr)
40        .with_env_filter(
41            tracing_subscriber::EnvFilter::try_from_default_env()
42                .unwrap_or_else(|_| "info".into()),
43        )
44        .init();
45
46    let args = Args::parse();
47    tracing::info!(
48        agent_sock = %args.agent_sock,
49        init_control = %args.init_control,
50        journal = %args.journal,
51        "hammerd: arranque"
52    );
53
54    let journal = hammer_journal::Journal::open(&args.journal)?;
55    let mut dirs = watcher::default_watch_dirs();
56    dirs.extend(args.extra_watch);
57
58    let overlay_root = PathBuf::from(&args.overlay_state_root);
59    match watcher::Watcher::start(&dirs, journal, Some(overlay_root)) {
60        Ok(w) => {
61            tracing::info!("watcher fanotify activo");
62            w.run_forever()?;
63        }
64        Err(e) => {
65            tracing::warn!(
66                error = %e,
67                "watcher fanotify NO arrancó; el daemon sigue (sin diario en este run)"
68            );
69            // TODO(fase-5): aquí entra el bus de agente. De momento sólo dormimos para que
70            // el daemon no salga.
71            std::thread::park();
72        }
73    }
74    Ok(())
75}