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 1572Shell 203Rust 109Markdown 993728 Definiciones

install-image: la guarda del init estaba INVERTIDA, y el staging no podía cruzar el montaje

Dos cosas encontradas armando la primera imagen del `perfil.servidor` (SDD 28 §1b).

**1. `[ -e "$ROOTFS/sbin/init" ]` rechazaba el rootfs CORRECTO y aceptaba el equivocado.** `-e`
sigue el symlink y lo resuelve contra el HOST. El `/sbin/init` del product-rootfs es un symlink
ABSOLUTO a `/usr/bin/arje-zero`, que en el host no existe ⇒ la guarda daba falso. Y al revés: un
rootfs cuyo init es `../bin/busybox` —symlink RELATIVO, que sí resuelve dentro del árbol— la pasaba
sin chistar. O sea que la única guarda que separaba «esto arranca takana» de «esto arranca otra
cosa» estaba exactamente al revés. Ahora acepta `-L`, y se probó en los dos sentidos: acepta el
symlink absoluto a arje-zero, sigue rechazando un directorio sin init.

Esto no es teórico: hidratar `perfil.servidor` sobre el product-rootfs **pisa `/sbin/init`** —
busybox entra en la clausura y su symlink gana por llegar después—. La imagen habría arrancado
perfecto con el init de busybox en vez de arje-zero, que es peor que no arrancar. Se restaura el
symlink al ensamblar y el cmdline lleva `init=/usr/bin/arje-zero` explícito, por las dos puntas.

**2. `STAGE` estaba cableado a `work/.install-stage`.** El staging HARDLINKEA desde `$ROOTFS`, y un
hardlink no cruza un montaje aunque sea el mismo disco. Con el layout normal de este repo —`store`
y `work/out` son bind-mounts de /dev/sdb, `work/` está en /dev/sdc— el rootfs vive del otro lado y
`cp -al` muere con EXDEV fichero por fichero. Ahora es env, documentado en la cabecera.

De paso: el fichero no tenía bit de ejecución (100644) mientras sus siete hermanos son 100755, así
que su propio ejemplo de uso `./scripts/install-image.sh` no funcionaba. Venía de antes; corregido.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x

c809a1786b6dc2e774b122ca36c5235605403b18 · por Sergio · (hace 1 mes) · padre f287b3045 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

1 archivos · +13 −2

diff --git a/scripts/install-image.sh b/scripts/install-image.sh
old mode 100644
new mode 100755
index 8e99ea1a..711be9c9
--- a/scripts/install-image.sh
+++ b/scripts/install-image.sh
@@ -24,6 +24,8 @@
 #
 # Variables:
 #   ROOTFS      dir rootfs a empaquetar       (default work/builder-rootfs)
+#   STAGE       dir de staging                 (default work/.install-stage) — DEBE estar en el
+#               mismo montaje que ROOTFS: el staging hardlinkea y un hardlink no cruza montajes
 #   PREALLOC    1 ⇒ trata IMG como target pre-dimensionado in-place (no trunca; prueba el camino device)
 #   KERNEL      bzImage a embeber en /boot     (default el del store: store/*-linux/boot/bzImage)
 #   IMG         imagen de salida               (default work/takana-install.img)
@@ -47,7 +49,12 @@ KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
 GRUB_LIB="${GRUB_LIB:-/usr/lib/grub/i386-pc}"
 
 [ -d "$ROOTFS" ] || { echo "no existe ROOTFS: $ROOTFS (corré selfhost-verify para armar el builder)" >&2; exit 1; }
-[ -e "$ROOTFS/sbin/init" ] || { echo "ROOTFS sin /sbin/init (arje-zero)" >&2; exit 1; }
+# `-e` sigue el symlink y lo resuelve contra el HOST, no contra el rootfs. El `/sbin/init` del
+# product-rootfs es un symlink ABSOLUTO a `/usr/bin/arje-zero`, que en el host no existe ⇒ `-e` da
+# falso y esta guarda rechazaba el rootfs CORRECTO. Peor: un rootfs con el init equivocado
+# (`../bin/busybox`, symlink RELATIVO que sí resuelve dentro del árbol) la pasaba sin chistar.
+# O sea que la guarda estaba exactamente invertida. `-L` acepta el symlink por lo que es.
+[ -e "$ROOTFS/sbin/init" ] || [ -L "$ROOTFS/sbin/init" ] || { echo "ROOTFS sin /sbin/init (arje-zero)" >&2; exit 1; }
 [ -n "$KERNEL" ] && [ -r "$KERNEL" ] || { echo "no encuentro el kernel a embeber (set KERNEL=<bzImage>)" >&2; exit 1; }
 [ -d "$GRUB_LIB" ] && [ -r "$GRUB_LIB/boot.img" ] || { echo "faltan los módulos GRUB i386-pc en $GRUB_LIB" >&2; exit 1; }
 for t in sfdisk mke2fs grub-mkimage grub-bios-setup; do
@@ -55,7 +62,11 @@ for t in sfdisk mke2fs grub-mkimage grub-bios-setup; do
 done
 unshare -r true 2>/dev/null || { echo "se requiere 'unshare -r' (ficheros root-owned sin sudo)" >&2; exit 1; }
 
-STAGE="work/.install-stage"
+# El staging ENLAZA (hardlink) desde $ROOTFS, y un hardlink no cruza un montaje aunque sea el mismo
+# disco. Con el store en un volumen aparte —el layout normal de este repo: `store` y `work/out` son
+# bind-mounts de /dev/sdb y `work/` está en /dev/sdc— el rootfs vive del otro lado y `cp -al` muere
+# con EXDEV fichero por fichero. Por eso es env: ponelo bajo el MISMO montaje que $ROOTFS.
+STAGE="${STAGE:-work/.install-stage}"
 rm -rf "$STAGE"
 mkdir -p "$STAGE"
 ROOT_TREE="$STAGE/root"