build: the sysroot was 194 MB of duplicated toybox, and links exposed a bug
ports/toybox already installed its applets as hard links to one multicall binary, with a cp fallback. The links had never happened: the install is stamped, the stamp predated the ln, and 236 separate 784 KB copies had been sitting in sysroot/bin ever since. Forcing the install: 194 MB -> 13 MB. Which immediately broke everything, in a way worth writing down. **/bin/ping exists twice.** toybox has a ping applet and cmd/ping is a first-party program that talks to lwIP directly. The install rule for cmd/ programs was `cp`, and cp onto an existing hard link writes *through* it -- so copying cmd/ping over the applet of the same name replaced the contents of the shared inode and all 236 links became ping. `cat /proc/uptime` answered "ping: not a dotted-quad address". Invisible until the links existed: while the applets were separate copies, overwriting one affected exactly one. Fixed from both directions, because it can be hit either way -- the cmd/ rule removes the target before copying, and toybox skips names SchOS provides itself. **The USB test image stopped fitting.** mkfs writes each hard link as its own copy, so /bin expanded to over 60 MB on the way in. That image exists to prove the USB driver can read one block, and bootcheck asserts on its 16 MB size, so it excludes /bin rather than growing. The ISO is the point of all this: 196 MB before, 62 MB now, and it boots to a shell with RAMROOT=1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
This commit is contained in:
parent
f9e68779ee
commit
52e6e9b756
2 changed files with 33 additions and 2 deletions
22
Makefile
22
Makefile
|
|
@ -773,7 +773,18 @@ $(BUILD)/cmd/%: cmd/%/main.c $(ULIB)
|
|||
$(LD) $(LDFLAGS) $(LD_LOWBASE) -e _start -Ttext 0x4000 -o $@ $(BUILD)/cmd/$*.o $(ULIB)
|
||||
$(OBJCOPY) -S $@
|
||||
|
||||
# rm before cp, and it is not tidiness.
|
||||
#
|
||||
# toybox installs its 236 applets as hard links to one multicall binary, and
|
||||
# some of those names collide with first-party programs here -- /bin/ping is
|
||||
# both. `cp` onto an existing hard link writes *through* it, so copying this
|
||||
# program over the applet of the same name replaced the contents of the shared
|
||||
# inode, and every one of the 236 links became this program. `cat` ran ping.
|
||||
#
|
||||
# It was invisible until the applets became links: while they were separate
|
||||
# copies, overwriting one affected exactly one.
|
||||
$(SYSROOT)/bin/%: $(BUILD)/cmd/% | $(SYSROOT)/bin
|
||||
rm -f $@
|
||||
cp $< $@
|
||||
chmod 755 $@
|
||||
|
||||
|
|
@ -971,12 +982,19 @@ $(BUILD)/sysroot.stamp: sysroot-install
|
|||
# - build/fs.img is no longer built by anything, since SchFS became the root,
|
||||
# so pointing at it meant QEMU refused to start at all;
|
||||
# - at FSSIZE blocks it would now be ~600 MB, because BSIZE went from 1024 to
|
||||
# 4096. 16 MB is plenty to read one block from.
|
||||
# 4096. The size is load-bearing: tools/windows/bootcheck.ps1 asserts on
|
||||
# READ CAPACITY returning 32768 sectors of 512 bytes, which is this.
|
||||
#
|
||||
# --exclude bin, because this image exists to prove the USB driver can read
|
||||
# a block and for no other reason. mkfs writes each hard link as its own
|
||||
# copy, so once toybox's 236 applets became links to one binary the /bin
|
||||
# tree expanded to more than 60 MB on the way in -- 236 copies of something
|
||||
# nothing here will ever execute.
|
||||
USBSTICK = $(BUILD)/usbstick.img
|
||||
$(USBSTICK): $(MKFS) $(BUILD)/sysroot.stamp
|
||||
@mkdir -p $(BUILD)
|
||||
@rm -f $@
|
||||
$(MKFS) $@ --size 4096 --sysroot $(SYSROOT)
|
||||
$(MKFS) $@ --size 4096 --exclude bin --sysroot $(SYSROOT)
|
||||
|
||||
usbstick: $(USBSTICK)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue