busybox: los 23 applets sin dueño eran 79 — el reparto era juicio, y medido no da
El plan de botar busybox decía de sí mismo que el reparto applet→dueño era «juicio, no medida». Medido contra los 1407 artefactos del store: de los 277 applets vivos, 167 los provee el dueño que el TSV nombra, 31 los provee OTRO paquete, y 79 no los provee NADIE salvo busybox — 56 más de los 23 previstos. El hallazgo transversal es que una receta de LIBRERÍA no es un paquete de HERRAMIENTAS, y build-state no distingue: `xz` figura en SEIS perfiles con el `usr/bin` VACÍO (su receta pasa --disable-xz --disable-xzdec --disable-scripts, o sea liblzma y nada más), y `ncurses` instala sólo install.libs/install.includes ⇒ ni clear, ni reset, ni tput. Las dos viajan, las dos dicen `sealed`, y el único binario que hay adentro de la imagen es el applet de busybox. Y al revés: `switch_root` y `sulogin` los trae util-linux, `partprobe` lo trae parted, y `getty` tiene sustituto — `agetty` de util-linux, en los 7 perfiles ⇒ deja de ser ESCRIBIR y pasa a ser migrar el exec de la card. Seis de los 18 huecos de iproute2 (ipaddr iplink ipneigh iproute iprule iptunnel) no son comandos de nadie: son nombres internos de busybox y se borran del defconfig. uutils traía 78 applets, no los 90 que el plan le atribuía: el multicall contestaba `coreutils: unknown program 'chmod'`. Construía con las default features (feat_common_core) y el resto vive detrás de feat_os_unix_musl, que cubre exactamente los 25 que faltaban. Construido y verificado contra un store tirable: 79 → 106 applets, 27 nuevos y CERO perdidos, chmod/uname/id ejecutan, y `stdbuf` correctamente ausente (por eso la variante _musl y no feat_os_unix: upstream lo excluye en musl porque necesita un cdylib). Importaba más de lo que parece: USERLAND_COMPONENTS hidrata uutils DESPUÉS de busybox para ensombrecerlo, y lo que no existe no ensombrece nada — chmod, chown, id, uname y stat los seguía dando busybox con el userland Rust instalado encima. ⚠ Dicho en la receta y en el documento: who/users/uptime/pinky compilan contra los stubs de utmpx de musl y contestan vacío. No es regresión, tampoco es sustitución. El censo queda como script (scripts/busybox-censo-proveedores.py) y como dos columnas del TSV, no como una tabla escrita a mano que vuelva a envejecer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1032,3 +1032,118 @@ reemplaza el proceso** (si el shell forkea, arje supervisa al shell y no al daem
|
||||
(`product-boot-test.sh`) y `takana-live-install.sh` en la imagen viva.
|
||||
5. **La shell interactiva de `getty`**, que es el consumidor que falta entero.
|
||||
6. **El sandbox de build sigue con busybox**, y con razón: eso es otro planeta y no está prometido.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# El censo de proveedores — el reparto applet→dueño, MEDIDO (2026-09-21)
|
||||
|
||||
**Instrumento:** `scripts/busybox-censo-proveedores.py` · **columnas nuevas del TSV:**
|
||||
`proveedor_medido`, `medido_el` · **qué mide:** índice inverso de
|
||||
`<store>/<hash>-<paquete>/{bin,sbin,usr/bin,usr/sbin,libexec}` sobre los 1407 artefactos del store
|
||||
del hub, cruzado con los 277 applets vivos.
|
||||
|
||||
## Por qué había que medirlo
|
||||
|
||||
Este documento decía, arriba y en letra clara: «**el reparto applet→destino es juicio, no medida**.
|
||||
La asignación de dueño la escribí yo y hay que revisarla receta a receta». Revisada:
|
||||
|
||||
| | n | qué significa |
|
||||
|---|---|---|
|
||||
| el dueño que el TSV nombra **sí lo provee** | 167 | el reparto era correcto |
|
||||
| **lo provee OTRO paquete** | 31 | el dueño estaba mal escrito, pero hay sustituto |
|
||||
| **no lo provee NADIE salvo busybox** | **79** | el trabajo real, y son 56 más de los 23 previstos |
|
||||
|
||||
> **Los 23 applets «sin dueño» eran 79.** No porque falte escribir más userland, sino porque
|
||||
> **nueve paquetes que el TSV daba por dueños no instalan el binario que se les atribuía.**
|
||||
|
||||
## Lo que aparece cuando se mira el artefacto en vez de la tabla
|
||||
|
||||
**`xz` es el caso que más duele, y no es un olvido: es la receta haciendo lo que pide.**
|
||||
`recipes/xz.toml` pasa `--disable-xz --disable-xzdec --disable-lzmadec --disable-lzmainfo
|
||||
--disable-scripts` ⇒ el artefacto sellado tiene **`usr/bin` vacío**: es liblzma y nada más. Y `xz`
|
||||
figura **en seis perfiles**. O sea que la imagen declara `xz` y el único `xz` que hay adentro es el
|
||||
applet de busybox. Lo mismo, por la misma razón, con **`ncurses`**: su receta instala
|
||||
`make install.libs install.includes` ⇒ ni `clear`, ni `reset`, ni `tput`, ni `infocmp`.
|
||||
|
||||
**Es un patrón, no dos accidentes: una receta de LIBRERÍA no es un paquete de HERRAMIENTAS**, y
|
||||
`build-state.json` no distingue entre las dos — las dos salen `sealed` y con sus perfiles. Es
|
||||
[[catalogo-no-es-imagen]] un piso más abajo: ahí el paquete existía y no viajaba; acá **viaja y no
|
||||
trae el binario**. Ninguna métrica actual lo ve; el censo sí.
|
||||
|
||||
Los demás huecos nuevos, por qué cada uno:
|
||||
|
||||
| dueño | applets que NO provee | causa |
|
||||
|---|---|---|
|
||||
| `iproute2` | 18 | 12 son net-tools (ya marcados NO-drop-in) y **6 son nombres internos de busybox** — `ipaddr iplink ipneigh iproute iprule iptunnel` son `ip addr`/`ip link`/… escritos como applet. **No son comandos de nadie: se BORRAN del defconfig**, no se reemplazan |
|
||||
| `shadow` | 8 | `addgroup adduser delgroup deluser mkpasswd cryptpw` ya estaban marcados; `add-shell` y `remove-shell` son de debianutils y nadie los trae |
|
||||
| `xz` | 6 | receta de librería (arriba) |
|
||||
| `kbd` | 4 | `loadfont loadkmap dumpkmap` son los NOMBRES de busybox de `setfont`/`loadkeys`/`dumpkeys`, que kbd **sí** trae ⇒ es NO-drop-in de nombre, no hueco de función. `vlock` no lo trae nadie |
|
||||
| `iputils` | 3 | trae `ping arping tracepath clockdiff`; `traceroute`/`traceroute6` son otro paquete y `ping6` es `ping -6` |
|
||||
| `ncurses` | 2 | receta de librería (arriba) |
|
||||
| `util-linux` | 2 | `hd` es el alias de `hexdump`, que sí trae ⇒ falso hueco. **`setpriv` es hueco real**: el `configure` lo desactivó |
|
||||
| `uutils` | 2 | `arch` y `hostname` — ver abajo, los cubre el feature |
|
||||
| `vim` | 1 | instala `vim ex view rvim vimdiff xxd`, **no `vi`**: falta el symlink, una línea |
|
||||
| `cronie` | 1 | `run-parts` es de debianutils |
|
||||
| `libarchive` | 1 | instala `bsdcpio`, no `cpio` |
|
||||
| `socat` `chrony` `dhcpcd` | 6 | los NO-drop-in ya conocidos |
|
||||
|
||||
## Y tres correcciones al revés — el dueño estaba mal, pero el sustituto EXISTE
|
||||
|
||||
Los 31 «otro proveedor» son casi todos `coreutils` (GNU, sellado, sin perfil) cubriendo lo que
|
||||
`uutils` no traía. Los tres que cambian una conclusión del plan:
|
||||
|
||||
- **`switch_root` lo trae `util-linux`** — es uno de los cinco indultos del paso 1, y tiene
|
||||
sustituto real. (El `/init` del initramfs sigue necesitando el de busybox porque ahí no hay
|
||||
util-linux, pero eso es el initramfs, no la imagen.)
|
||||
- **`sulogin` lo trae `util-linux`**, no shadow. **`partprobe` lo trae `parted`**, no util-linux.
|
||||
- **`getty` tiene sustituto: `agetty`, de `util-linux`, que está en los 7 perfiles.** El TSV lo
|
||||
daba como `getty-ESCRIBIR`. No es escritura: es cambiar el `exec` de la card
|
||||
(`takana-bootstrap/src/lib.rs:240`) y medirlo. Lo que sigue faltando entero es la **shell
|
||||
interactiva**, que es otro consumidor — `simi` no trae edición de línea ni historial.
|
||||
|
||||
## `uutils` no traía 25 de sus 90 — arreglado en la receta
|
||||
|
||||
El artefacto sellado `b3:9005da83…` instala **78 symlinks**, no los 90 que este documento le
|
||||
atribuía, y el propio multicall lo dice sin ambigüedad:
|
||||
|
||||
```
|
||||
$ …-uutils/usr/bin/coreutils chmod --version
|
||||
coreutils: unknown program 'chmod'
|
||||
```
|
||||
|
||||
Faltaban exactamente estos 25: `arch chgrp chmod chown chroot groups hostid hostname id install
|
||||
kill logname mkfifo mknod nice nohup nproc stat stty sync timeout uname users who whoami`. La causa
|
||||
es que `recipes/uutils.toml` construía con las **default features** (`feat_common_core`), y el
|
||||
`Cargo.toml` del tag pineado pone el resto detrás de `feat_os_unix_musl` — que cubre **esos 25 y
|
||||
ninguno más**. Arreglado con un flag en la receta.
|
||||
|
||||
⚠ **Esto importaba más de lo que parece:** `USERLAND_COMPONENTS` hidrata `uutils` DESPUÉS de
|
||||
busybox para que lo ensombrezca, y **lo que no existe no ensombrece nada**. O sea que en el producto
|
||||
de hoy `chmod`, `chown`, `id`, `uname` y `stat` los sigue dando busybox, con el userland Rust
|
||||
instalado encima y la métrica diciendo que están cubiertos.
|
||||
|
||||
⚠ **Lo que el feature NO arregla:** `who`, `users`, `uptime` y `pinky` compilan contra los stubs de
|
||||
utmpx de musl y **contestan vacío**. No es regresión (el `who` de busybox en musl está igual de
|
||||
ciego), pero tampoco es sustitución.
|
||||
|
||||
## Qué cambia en el orden de ataque
|
||||
|
||||
1. **`xz` y `ncurses` necesitan su paquete de herramientas** — variante de receta, no perilla: tocar
|
||||
`--disable-xz` re-hashea xz y arrastra a todos sus dependientes. Patrón `elfutils-libdw`.
|
||||
2. **Los 6 `ipaddr/iplink/…` salen del defconfig** en el próximo recorte: 277 → 271 sin escribir nada.
|
||||
3. **`vi` en la receta de vim** y **`cpio`→`bsdcpio` en libarchive**: un symlink cada uno.
|
||||
4. **`getty` deja de ser escritura** y pasa a ser migración de card a `agetty`.
|
||||
5. **Falta un guardián nuevo**, hermano del vigía de applets retirados: uno que falle cuando una
|
||||
receta declare un perfil y su artefacto **no instale el binario homónimo**. El censo es el
|
||||
instrumento; falta cablearlo a CI.
|
||||
|
||||
## Lo que este censo NO mide
|
||||
|
||||
- **Equivalencia de nombre, no de banderas.** `nc` de socat cuenta como proveedor aunque su sintaxis
|
||||
difiera. La columna `equivalencia` del TSV sigue haciendo falta y sigue diciendo `sin-verificar`
|
||||
en 230 filas.
|
||||
- **El store del HUB.** Un artefacto sellado sólo en el worker no aparece; `build-state.json` dice
|
||||
`sealed` igual. Los 79 hay que releerlos como «no está en el store del hub».
|
||||
- **Qué applets EJECUTA el producto de verdad**, que sigue sin medirse y sigue siendo lo que
|
||||
abarataría todo lo demás.
|
||||
|
||||
Reference in New Issue
Block a user