[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