From c809a1786b6dc2e774b122ca36c5235605403b18 Mon Sep 17 00:00:00 2001 From: Sergio Date: Thu, 10 Sep 2026 19:56:17 +0000 Subject: [PATCH] =?UTF-8?q?install-image:=20la=20guarda=20del=20init=20est?= =?UTF-8?q?aba=20INVERTIDA,=20y=20el=20staging=20no=20pod=C3=ADa=20cruzar?= =?UTF-8?q?=20el=20montaje?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x --- scripts/install-image.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) mode change 100644 => 100755 scripts/install-image.sh 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=)" >&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"