[Toybox] Toybox vs Bustbox

Rob Landley rob at landley.net
Tue Jan 7 07:08:50 PST 2025


On 1/6/25 19:21, scsijon wrote:
> Please don't yell at the messenger.
> 
> I was asked if there is a list online showing the differences between 
> Toybox's packages (?toys) and Busybox's since I use it.

I gave a busybox vs toybox talk in 2019 (linked from the about page), 
but that was more history and 10k foot view and only went side by side 
over over one actual command to give a flavor of the thing.

> From a little 
> more messaging back at them. It seems that what they want is a 
> comparison list for the commands, and not further details (at least at 
> this point). I thought this would be a quick lookup and link, but I 
> can't see / find one anywhere, so before I spend time and create one 
> from scratch, has anyone already created it, and can I either have a 
> copy or a link I can use please?

There's some stuff in roadmap.html but both busybox and toybox are 
moving targets, and it's mostly a question of "what were you trying to 
do" = what did you hit...

I occasionally check busybox commands' --help output to see what options 
they support (to make sure I'm not missing anything obvious, or as 
arguing against implementing something if they never bothered), but 
haven't systematically tracked (let alone catalogued) the differences.

Commands in toybox that aren't in busybox defconfig:

$ diff -u <(toybox|tr ' ' '\n') <(busybox --list)|sed -n 's/^-//p'|xargs
acpi base32 bash chattr chrt cksum comm count eject file flock fmt 
fstype fsync getconf gpiodetect gpiofind gpioget gpioinfo gpioset help 
hexedit host iconv inotifyd install iorenice iotop killall5 lsattr lspci 
lsusb makedevs mcookie memeater mix mountpoint nbd-client nbd-server 
netcat nice nohup oneit pgrep pkill pmap printenv prlimit pwdx pwgen 
readahead readelf rfkill rtcwake setfattr sha224sum sha384sum sntp split 
su toysh tsort tunctl uclampset ulimit unicode uuidgen vmstat

Commands in busybox that aren't (yet) in toybox.

$ diff -u <(toybox|tr ' ' '\n') <(busybox --list)|sed -n 's/^+//p'|xargs
[[ acpid adjtimex ar arp arping ash awk bc brctl bzip2 cttyhack dc 
depmod diff dumpkmap dumpleases expr fatattr fdisk findfs fstrim getty 
gzip hexdump hostid ifdown ifup init ip ipcalc ipneigh klogd last less 
linux64 linuxrc loadfont loadkmap logread lsscsi lzcat lzma lzop mdev 
mim mkdosfs mke2fs modprobe more mt nameif nologin nslookup nuke rdate 
resume rpm rpm2cpio run-init run-parts setkeycodes setpriv ssl_client 
start-stop-daemon stty svc svok syslogd telnet tftp tr traceroute 
traceroute6 ubirename udhcpc udhcpd uevent uncompress unexpand unlzma 
unxz unzip vi xz xzcat

Several of which are in pending and/or the roadmap, and I guess maybe 
findfs is worth adding? And/or fstrim?

Why would you install a _symlink_ for [[ isn't the difference from [ is 
to interact with shell internal state...? How would that work?

The toybox faq has an entry on why we don't have "cttyhack". (Even oneit 
is kinda obsolete these days.)

I am unclear what "linux64" would DO: you _start_ from 64 bits. Note 
that this is NOT about running 32 bit vs 64 bit binaries, the kernel's 
ELF loader does that during exec, this is about a specific hack to make 
"uname -m" lie about the architecture to lie to autoconf, because 
listening to the compiler macros:

$ :|cc -E -dM - | grep 86_
#define __x86_64 1
#define __x86_64__ 1
$ :|i686-cc -E -dM - | grep 86_
#define __i686__ 1
#define __i386__ 1

Is WAY too complicated for gnu/gnu which needs to ask ALL THE WRONG 
QUESTIONS and then use the results inappropriately. ("Autoconf is 
useless" may be sung to "every sperm is sacred".)

"linuxrc" was the magic init name initial ramdisks used in the 1.x 
kernels back before initramfs was invented: mkroot uses an /init shell 
script and toybox can follow symlink chains to figure out what name a 
command actually has even if you did want to "ln -s /sbin/init /initrd", 
and I think the kernel changed the plumbing so even initrd calls /init 
now? (And there's a rdinit= kernel command line argument...)

dumpkmap/loadkmap is sort of conceptually terrible (it's a binary dump 
of state subject to version skew, where you basically copy state from a 
"real" system that actually sets it up properly). I vaguely recall 
"loadfont" and "setfont" were something similar (for remapping the font 
in text mode console on VGA cards, might work in framebuffer too? But 
the design was pre-unicode so don't ask me what it does _now_ or how its 
file format would have changed...) and note that both commands SET the 
font (no idea the difference between them), so where you get the font 
file FROM is... And "setkeycodes" is also for the text mode kernel 
consoles. (I mean, I could? But neither serial consoles nor xterm will 
care.)

There's a hostid in toys/example because it's an obsolete command. A 
"globally unique 32 bit ID" on a planet with more than 4 billion 
computers ran into conceptual issues back around y2k.

"mim" was the evil witch in disney's "sword in the stone" who turned 
into a purple dragon and was defeated with germ warfare, and in this 
case claims to be a "makefile-like" embedded shell script for no 
apparent reason: https://git.busybox.net/busybox/commit/?id=981b2eff814b

"mt" is short for "magnetic tape", which was not a common piece of 
hardware even back in 2006.

"nameif" is, for some reason, a standalone version of ifconfig rename.

"nologin" seems a bit like initrd, in that busybox can't follow symlinks 
to determine behavior so if you make a symlink to "false" busybox 
doesn't know what to do with it and toybox does? I guess?

I have NO idea why a defconfig build of current busybox git is showing 
"nuke" in --list but saying applet not found for ./busybox --help nuke. 
The help text at the top of klibc-utils/nuke.c says:

//config:config NUKE
//config:       bool "nuke (2.9 kb)"
//config:       default n  # off by default: too "accidentally destructive"
//config:       help
//config:       Alias to "rm -rf".

Did their plumbing get confused by having a comment after the default n 
maybe? No idea.

Toybox implemented sntp (which is a receive-compatible subset of ntp) 
instead of rdate because the rfc 868 "time" protocol is FSCKING stupid, 
it gives a 32 bit value for seconds since 1900 (not 1970) meaning the 
unix epoch was over halfway through the 32 bit space it runs out in 
something like 2031? I pondered implementing it anyway because I vaguely 
recall it used to be built into qemu's virtual network stack, but if so 
they removed it a while back...

I guess "setpriv" would be interesting to someone who actually uses 
selinux? Or no, is this capability bits? I've had a hard time taking 
those seriously since:

https://forums.grsecurity.net/viewtopic.php?f=7&t=2522

But I guess it's vaguely adjacent to "unshare"? (Which toybox already 
has. I've meant to do a "contain" command that set all that nonsense 
from one command line, so you can make a wrapper script to enter a 
container...)

I would LOVE an "ssl_client" command, Denys implemented his own https 
stack! That's a solid month of work, at least. (And that's picking one 
algorithm at each layer.) For the moment we're stuck pulling in an ssl 
library for that stuff. Anything more is post-1.0 (and the big blocker 
for 1.0 is finishing up the shell, just got going on that again recently).

Denys is a big fan of "runsv" and I've never quite seen the appeal.

Does "ubirename" come up much? I've never encountered it, and nobody's 
asked. (UBI is an optional layer of flash plumbing, inserting a software 
block remapping layer for devices that don't do hardware block 
remapping. As far as I know its only consumer is ubifs ala 
https://docs.kernel.org/filesystems/ubifs.html but for some reason "ubi" 
is a separate layer of plumbing ubifs depends on. You'd THINK it would 
let you mount ext2 and friends on top of flash with wear levelling, but 
no! It does not. Jazzhands!) Why does busybox have a "rename" command 
but not the corresponding "mkfs"? Your guess is as good as mine. I've 
only ever had to use ubifs once and it was a pain: jffs2, yaffs, and 
f2fs don't use ubi. Nor did logfs back when that was a thing.

I guess "uevent" might be useful, the sketch I had for mdev here built 
the netlink plumbing in. Are there any uevents OTHER than mdev we should 
care about...? (Android ain't ever gonna use that, and the embedded 
systems I've been playing with don't hotplug much after startup, so...)

Ah, "uncompress". But not "compress". Yes posix still has 
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/compress.html 
but the actual compression TYPE was patented in the 1980s (the above 
page says 2 patents, issued 1984 and 1985 respectively) and EVERYBODY 
abandoned it for gzip because of the patent trolling, and by the time 
the patent expired (2005-ish I'd guess) compress was LONG dead. I have 
chosen not to implement it for the same reason I haven't got "arj" and 
"zoo".

Huh, I thought I had "unexpand". (Wasn't there some horrible utf8 
fontmetrics corner case? Hmmm, nope it's still in status.html on the 
posix list. Odd.)

As for "unlzma": remember the recent discussion about the tar -Z patch 
for zstd? Which is not xz. Which is not lzma. Seriously, the 6.13-rc5 
kernel's menuconfig has:

[*]   Support initial ramdisk/ramfs compressed using gzip
[*]   Support initial ramdisk/ramfs compressed using bzip2
[*]   Support initial ramdisk/ramfs compressed using LZMA
[*]   Support initial ramdisk/ramfs compressed using XZ
[*]   Support initial ramdisk/ramfs compressed using LZO
[*]   Support initial ramdisk/ramfs compressed using LZ4
[*]   Support initial ramdisk/ramfs compressed using ZSTD

I've written gzip and bzip2 decompressors, have a public domain xz in 
pending (with a big todo list of commits to apply to it _and_ it needs a 
giant cleanup), and I honestly don't understand the difference between 
the other 4 on the list and xz. (It's the arj/zoo/pak days all over 
again. We only remember 'zip' from that period because it won but there 
were TONS. And zip itself had a bunch of algorithms before 2.0 gave us 
"deflate", I have an old button somewhere "unzip, expand, explode, what 
pervert came up with this" from Nancy Lebovitz's catalogue.)

So findfs, fstrim, and maybe setpriv and/or uevent? And remember to do 
unexpand. And the rest of the roadmap entries. See also 
https://mstdn.jp/@landley/113777106743267398 and so on. (I have a todo 
heap.)

Again, differences _within_ a command, I dunno about, but other than 
lack of builtin https and not micromanaging binary size with 
UNUSED_PARAM and MAIN_EXTERNALLY_VISIBLE style black magic (our 
standalone "false" is probably way bigger than theirs), I'm unaware of 
any places an existing promoted toybox command is functionally WORSE 
than busybox. (If you find one, tell me.)

Rob


More information about the Toybox mailing list