freebsd-apple-userland-cmds — per-repo, per-binary port audit

A data-grounded audit of six Apple userland reposbootstrap_cmds, file_cmds, shell_cmds, system_cmds, network_cmds, text_cmds — for the question "should we replace FreeBSD's version with Apple's?". Decision rule: port if Apple's version gives Mach IPC integration, libxpc/libdispatch/launchd integration, or a real feature advantage over the FreeBSD equivalent. Skip if there's no advantage. Tables grounded in direct source inspection by five parallel research agents over /Users/jmaloney/Documents/launchd/{bootstrap,file,shell,system,network,text}_cmds/. Tools install at their Apple-canonical paths; FreeBSD-runtime stays installed and we overwrite the conflict paths.

Contents

  1. Decisions made
  2. Scoreboard — total port count per repo
  3. bootstrap_cmds
  4. file_cmds audit
  5. shell_cmds audit
  6. system_cmds audit
  7. network_cmds audit
  8. text_cmds audit
  9. Aggregated port list
  10. Install order in build.sh
  11. Risks & known sharp edges
  12. Out of scope

1. Decisions made

1.1. What FreeBSD-runtime provides that we have no Apple replacement for

Even after the 28-binary port list lands and overwrites every conflict path, FreeBSD-runtime still carries roughly five categories of tools we depend on. None of these has a viable Apple-source replacement on FreeBSD — Apple's equivalents either don't exist, target HFS+/APFS only, or use macOS-kernel-specific interfaces that don't translate.

CategoryTools still needed from FreeBSD-runtimeWhy no Apple replacement
Filesystem mount & checkmount, umount, mount_nullfs, mount_unionfs, mount_tmpfs, mount_devfs, mount_nfs, mount_msdosfs, mount_cd9660, fsck, fsck_ffs, fsck_msdosfs, newfs, newfs_msdos, tunefsApple's system_cmds equivalents target HFS+/APFS via Apple's VFS layer. FreeBSD uses UFS / ZFS / unionfs / nullfs — entirely different kernel interfaces. No code reuse possible.
Kernel module managementkldload, kldunload, kldstat, kldconfig, kldxrefApple uses kexts via kextload / kextunload against a fundamentally different module-loading kernel API. FreeBSD's klds are FreeBSD-only. Critical for boot — mach.ko itself is loaded via kldload.
Storage glueswapon, swapoff, mdconfig, mdmfs, gpart, geom, devfs, dumpon, savecoreFreeBSD-specific subsystems: GEOM stack, devfs rulesets, memory-disk framework, swap layout, dump format. Apple has no equivalents that target these subsystems.
Boot & init (until Phase I3)init, halt *init stays until launchd-842 is PID 1 (Phase I3). halt we don't port from system_cmds — Apple's wraps Apple-specific power-mgmt; FreeBSD's is enough. reboot + shutdown ARE in our PORT list (system_cmds, with launchd-coordination + IOPMLib stubs).
Networking we explicitly didn't portdhclient, mountd, nfsd, nfsiod, traceroute, traceroute6, rtsolddhclient is FreeBSD's DHCP client; Apple's equivalent is IPConfiguration (separate daemon, separate phase). NFS stack is FreeBSD-only. traceroute(6) Apple versions audit SKIP (no Apple-specific feature).
POSIX file ops we audit-skippedchflags, chown, dd, ipcrm, ipcs, ln, mkdir, mkfifo, mknod, rm, rmdir, shar, stat, touch, truncateApple's file_cmds versions have zero integration advantage; FreeBSD's are equivalent. We deliberately don't port these (see §4).
POSIX shell tools we audit-skippedbasename, chroot, date, dirname, echo, env, expr, false, find, getopt, hexdump, hostname, jot, kill, mktemp, nice, nohup, printenv, printf, pwd, realpath, renice, script, seq, sleep, tee, test, time, true, tty, uname, users, w, who, xargs, yesSame — Apple's shell_cmds for these have no Apple-stack integration. FreeBSD's are equivalent. We deliberately don't port these (see §5).
Tracing / introspection FreeBSD does its own wayktrace, kdump, top, vmstat, iostat, ps, pstat, systat, dtrace, dtraceopt, dmesgApple's analogues (fs_usage, sc_usage, latency) audit SKIP — they depend on Apple's kdebug infrastructure. FreeBSD has dtrace; replicating kdebug is not worth it.

* FreeBSD-rc is a separate pkg, not part of FreeBSD-runtime. We keep it for Phases I1/I2 (since FreeBSD's init still calls /etc/rc). Phase I3+ drops FreeBSD-rc when launchd-842 plists own multi-user bring-up.

Bottom line: FreeBSD-runtime isn't going anywhere. Filesystem glue, GEOM, kld, swap, dump, NFS, and the ~40 plain-POSIX tools we audit-skipped all live there. The pkg is doing real work post-port; the conflict overwrites only displace ~17 of its ~200+ files.

2. Scoreboard — total port count per repo

RepoBinaries totalPORTPARTIALSKIPNet "advantage" driver
bootstrap_cmds~4 files400MIG. Pre-req for launchd-842 + every future MIG-using daemon.
file_cmds277317ACL + xattr + clonefile + fcopyfile preservation across cp/mv/ls/etc.
shell_cmds~4522~41Open Directory (id), BSM audit (su).
system_cmds~4045~31Mach IPC introspection (lsmp/hostinfo/stackshot) + IOKit NVRAM.
network_cmds151014SystemConfiguration parity, IFSCOPE routing, LQM, IPv6 secure ND.
text_cmds341033Only sort uses Mach semaphores for parallel sorting.
Total~1652811~126

Roughly 17% of Apple's userland is worth replacing on FreeBSD. The remaining 83% is BSD-derived plain-POSIX code with no integration advantage; FreeBSD's existing versions are as good or better.

3. bootstrap_cmds — install table

Apple binarySource pathFreeBSD path todayInstall pathConflict
migxcodescripts/install-mig.sh(not present)/usr/bin/mignone
migcommigcom.tproj/(not present)/usr/libexec/migcomnone
mig.1, migcom.1migcom.tproj/*.1(not present)/usr/share/man/man1/none

Zero conflicts; pure addition. Smoke marker: MIG-BUILD-OKmig --help exits 0, migcom emits help on stderr. Once installed, generate the seven launchd-842 .defs stubs into a vendored mig-output/ tree.

4. file_cmds audit

BinaryApple-stack integrationApple-specific featureFreeBSD pathVerdict
cpfcopyfile, clonefile, ACL + xattr (cp/utils.c:138-491)APFS clonefile COW; resource-fork + ACL preservation/bin/cpPORT
chmodApple libacl (chmod_acl.c:121-854)Extended ACL manipulation (ACL_EXTENDED_ALLOW/DENY)/bin/chmodPORT
lsgetxattr, acl_get_link_np, SF_DATALESS (ls/ls.c:1113-1147)ACL display (-e), xattr count, dataless-file awareness/bin/lsPORT
mvfcopyfile for ACL+xattr (mv/mv.c:443)Cross-FS move preserves permissions+xattr/bin/mvPORT
installfcopyfile ACL+xattr (install/xinstall.c:1201-1203)ACL preservation in install(1)/usr/bin/installPORT
gzipfgetattrlist, fsetattrlist, fcopyfile (gzip/gzip.c:1385-1507)Preserves ACLs+xattrs across compression/usr/bin/gzipPORT
paxfcopyfile, setattrlist (pax/file_subs.c:845-852)Precise timestamp + ACL+xattr in archives/bin/paxPORT
dfgetattrlist for ATTR_VOL_SPACEUSED (df/df.c:542-553)Volume metadata without traversal/bin/dfPARTIAL
dugetattrlist for SF_DATALESS (du/du.c:595)Accurate dataless-file accounting/usr/bin/duPARTIAL
mtreelibdispatch (mtree/commoncrypto.c:35-84)GCD-parallel hashing/usr/sbin/mtreePARTIAL
17 others
chflags, chown, cksum, compress, dd, ipcrm, ipcs, ln, mkdir, mkfifo, mknod, pathchk, rm, rmdir, shar, stat, touch, truncate, xattr
NoneStandard POSIXvariousSKIP

Driver: Apple's cp/mv/ls/install/gzip/pax preserve ACLs + extended attributes + APFS clonefile semantics through file operations. FreeBSD's POSIX.1e ACLs and extattr(2) overlap but the userland tools don't preserve them uniformly. Porting the seven essentials makes the toolchain Apple-metadata-aware.

Risks: libacl + libdispatch dependencies for chmod/ls/install/mtree. clonefile(2) is APFS-only; Apple's cp falls back to byte-copy on non-clone-capable filesystems — benign on FreeBSD's UFS/ZFS. xattr the tool is SKIP because Apple's xattr(2) API diverges from FreeBSD's extattr(2) too sharply; the wrapper underneath libxpc/launchd uses Apple's API directly so we ship a shim there, not here.

5. shell_cmds audit

BinaryApple-stack integrationApple-specific featureFreeBSD pathVerdict
idCoreFoundation + Open Directory (id/open_directory.c:11-93)OD-backed identity lookups for enterprise LDAP/NIS/usr/bin/idPORT
suBSM audit session (su.c:219-222; bsm/audit_session.h)Audit-session-aware privilege escalation/usr/bin/suPORT
path_helperNone (file I/O only)Reads /etc/paths + /etc/paths.d/ to build PATH(not present)PARTIAL
killallKERN_PROCARGS2 sysctl (killall.c:414)Full-argv match vs FreeBSD's truncated ki_comm/usr/bin/killallPARTIAL
~40 others
basename, chroot, date, dirname, echo, env, expr, false, find, getopt, hexdump, hostname, jot, kill, lastcomm, lockf, logname, mktemp, nice, nohup, printenv, printf, pwd, realpath, renice, script, seq, sh, shlock, sleep, stdbuf, tee, test, time, true, tty, uname, w, who, xargs, yes, …
NoneStandard POSIXvariousSKIP

Driver: two narrow wins. id grows enterprise-directory awareness (Open Directory); su grows BSM audit-session tracking. Everything else is plain BSD/POSIX with no integration value.

Risk callout: Apple id requires libopendirectory, which has no FreeBSD equivalent. Two paths: (a) ship a no-op libopendirectory shim and let id fall back to /etc/passwd; (b) defer the id port until Open Directory or an equivalent enterprise-directory shim lands. Recommendation: ship the no-op shim and defer real OD work to a separate phase.

6. system_cmds audit

This is the most Mach-IPC-heavy of the six repos. The PORT candidates require kernel-side mach.ko work; the SKIP list calls out which tools depend on Apple's kdebug infrastructure (FreeBSD has dtrace instead) and aren't worth replicating.

BinaryApple-stack integrationApple-specific featureFreeBSD pathVerdict
lsmpMach IPC introspection (task_read_for_pid, mach_port_space_info, host_processor_sets)Mach port enumeration — no FreeBSD equivalent(not present)PORT
hostinfoMach: host_info HOST_BASIC_INFO, processor sets (hostinfo.c:65-104)Reports Mach kernel version, processor-set state(not present)PORT
nvramIOKit (IORegistry, IORegistryEntryCreateCFProperty)Firmware-parameter R/W via IOKit(not present)PORT
stackshotMach + stackshot syscallKernel stack snapshots(not present)PORT
lskqEVFILT_MACHPORT in kqueue (lskq.c:100)Mach-aware kqueue analysis/usr/bin/lskqPARTIAL
rebootBootstrap + IOKit kextmanager (reboot.c:67-75)launchd-coordinated reboot, kext locking/sbin/rebootPARTIAL
shutdownIOKit IOPMLib + BSM audit (shutdown.c:64-66, 838)Power-management-aware shutdown, audit-logged/sbin/shutdownPARTIAL
gcoreMach-image introspectionCore dumps with Mach thread-state notes/usr/bin/gcorePARTIAL
loginBSM audit (bsm/audit_session.h)Audit-aware session creation/bin/loginPARTIAL
taskpolicyMach task_policy_set/getQoS + CPU-limit management/usr/bin/taskpolicyPARTIAL
fs_usage, sc_usage, latencykdebug + Mach timingkdebug-based tracingvariousSKIP
kpgo, memory_pressure, vm_stat, vm_purgeable_statApple-only kernel features (PGO, jetsam, purgeable VM)n/a on FreeBSDvariousSKIP
~25 others
arch, at, atrun, accton, chpass, cpuctl, dmesg, dynamic_pager, getconf, getty, hostinfo*, iostat, mean, mkfile, newgrp, nologin, passwd, pagesize, proc_uuid_policy, purge, sa, sync, sysctl, vipw, wait4path, zdump, zic, zlog, zprint, …
None or trivialStandard POSIXvariousSKIP

Kernel-side mach.ko work this implies. Porting the four strong PORTs requires new mach.ko traps:

The first three fit our existing multiplexer slot 219 pattern. IOKit NVRAM is its own subsystem and probably waits.

7. network_cmds audit

Highest port ratio of any repo — 10 of 15. Not because these tools have heavy Mach integration (they don't), but because they're the system-of-record for network state that configd will read. Apple's struct layouts and tool output formats differ from FreeBSD's; for configd to work later, these tools must produce Apple-shaped output.

BinaryApple-stack integrationApple-specific featureFreeBSD pathVerdict
ifconfigIFEF_* flags, LQM (ifconfig.c:2090-3036)AWDL/cellular/companion interface types, LQM quality state/sbin/ifconfigPORT
routeRTF_IFSCOPE parsing (route.c:130, 814-818, 1776-1778)Interface-scoped routes, RTF_PINNED/RTF_IFREF/sbin/routePORT
arpIFSCOPE, IFNET_LQM_THRESH_* (arp.c:1127-1136)Interface-scoped ARP for multi-homed mDNS/usr/sbin/arpPORT
ndpND6_IFF_* flags, prefix list sysctlSEND (secure ND), proxy prefixes, NUD state machine/usr/sbin/ndpPORT
pingIP_NO_IFT_CELLULAR, DSCP marking (ping.c:754-756)Cellular exclusion, QoS class/sbin/pingPORT
ping6IPV6_NO_IFT_CELLULAR, DSCP marking (ping6.c:850-852)IPv6 variant of ping with cellular/QoS/sbin/ping6 (symlink)PORT
rtadvdRDNSS/DNSSL + PVD configIPv6 prefix advertisement with Apple extras/usr/sbin/rtadvdPORT
rtsolIPv6 router-solicitation daemonAuto IPv6 prefix solicitation/usr/sbin/rtsoldPORT
kdumpdlaunchd plist + socket activationEstablishes launchd-managed-daemon pattern(not present)PORT
netstatLQM thresholds, NSTAT cellular link status (if.c:1328-2261)LQM + cellular display/usr/bin/netstatPARTIAL
tracerouteNoneNone Apple-specific/usr/sbin/tracerouteSKIP
traceroute6NoneNone Apple-specific/usr/sbin/traceroute6SKIP
dnctlApple dummynet controlApple-specific QoS scheduling(not present; FreeBSD-ipfw omitted)SKIP
rarpdNoneLegacy RARP server(not present)SKIP
sprayNoneSun-RPC bandwidth measurement(not present)SKIP

Driver: SystemConfiguration parity. configd's job — coming in a later phase — is to read ifconfig -a, route -n get, ndp -pr, arp -a, netstat -i output and turn it into the SC store. Those tools have to emit Apple-shaped state, or configd's parser breaks. kdumpd's launchd plist is independently useful: it's the worked example for launchd-managed-socket-activation we'll copy when we add ntpd, mDNSResponder, etc.

8. text_cmds audit

BinaryApple-stack integrationApple-specific featureFreeBSD pathVerdict
sortMach semaphores (sort/file.c:140-159)Multi-threaded sort via Mach IPC/usr/bin/sortPORT
33 others
banner, bintrans, cat, col, colrm, column, comm, csplit, cut, ed, expand, fmt, fold, grep, head, jq, join, lam, look, md5, nl, paste, pr, rev, rs, sed, split, tail, tr, ul, unexpand, uniq, unvis, vis, wc, …
None — pure POSIX stream processorsLocale and encoding edge cases onlyvariousSKIP

Driver: sort alone uses Mach semaphores for parallelism. Everything else is BSD stream processing with no integration story.

9. Aggregated port list

28 binaries to port across all six repos, ordered by where they land in the build pipeline:

#BinarySource repoInstall pathConflict pkg
1migbootstrap_cmds/usr/bin/mig
2migcombootstrap_cmds/usr/libexec/migcom
3arpnetwork_cmds/usr/sbin/arpFreeBSD-runtime
4ifconfignetwork_cmds/sbin/ifconfigFreeBSD-runtime
5ndpnetwork_cmds/usr/sbin/ndpFreeBSD-runtime
6netstat (PARTIAL)network_cmds/usr/bin/netstatFreeBSD-runtime
7pingnetwork_cmds/sbin/pingFreeBSD-runtime
8ping6network_cmds/sbin/ping6FreeBSD-runtime
9routenetwork_cmds/sbin/routeFreeBSD-runtime
10rtadvdnetwork_cmds/usr/sbin/rtadvdFreeBSD-runtime
11rtsolnetwork_cmds/usr/sbin/rtsolnone (name differs from FreeBSD's rtsold)
12kdumpdnetwork_cmds/usr/libexec/kdumpd
13cpfile_cmds/bin/cpFreeBSD-runtime
14chmodfile_cmds/bin/chmodFreeBSD-runtime
15lsfile_cmds/bin/lsFreeBSD-runtime
16mvfile_cmds/bin/mvFreeBSD-runtime
17installfile_cmds/usr/bin/installFreeBSD-utilities
18gzipfile_cmds/usr/bin/gzipFreeBSD-utilities
19paxfile_cmds/bin/paxFreeBSD-runtime
20idshell_cmds/usr/bin/idFreeBSD-utilities
21sushell_cmds/usr/bin/suFreeBSD-utilities
22lsmpsystem_cmds/usr/bin/lsmp
23hostinfosystem_cmds/usr/bin/hostinfo
24nvramsystem_cmds/usr/sbin/nvram
25stackshotsystem_cmds/usr/bin/stackshot
26reboot (PARTIAL)system_cmds/sbin/rebootFreeBSD-runtime
27shutdown (PARTIAL)system_cmds/sbin/shutdownFreeBSD-runtime
28sorttext_cmds/usr/bin/sortFreeBSD-utilities

Conditional PARTIALs deferred until after the first 28 are stable: df, du, mtree (file_cmds); path_helper, killall (shell_cmds); lskq, gcore, taskpolicy, login (system_cmds).

10. Install order in build.sh

  1. pkg install the pkgbase set (current behavior; FreeBSD-runtime + FreeBSD-utilities land here).
  2. Build bootstrap_cmds; install mig + migcom. Marker: MIG-BUILD-OK.
  3. Run mig against the seven launchd-842 .defs files; cache output in src/launchd/mig-output/.
  4. Build + install network_cmds tools (10 binaries). One smoke marker per tool: NETCMD-IFCONFIG-OK, NETCMD-PING-OK, NETCMD-ROUTE-OK, …
  5. Build + install file_cmds tools (7 binaries). Markers: FILECMD-CP-OK, …
  6. Build + install shell_cmds tools (id, su). Ship a no-op libopendirectory shim so id falls back to /etc/passwd.
  7. Build + install system_cmds tools that don't need new kernel traps yet. Defer lsmp / hostinfo / stackshot until the mach.ko-side traps land.
  8. Build + install sort from text_cmds. Last because it adds Mach-semaphore use to a generic stream tool — isolation matters.

11. Risks & known sharp edges

ABI drift between Apple and FreeBSD kernel structs

Worst in ifconfig, netstat, route, arp, ndp. Apple extends struct ifreq, struct ifmediareq, struct rt_msghdr; some Apple ioctls don't exist on FreeBSD. Apple-only feature paths will fail gracefully (ioctl returns -1, flag never set) — acceptable.

Open Directory dependency for id

Apple's id calls libopendirectory. FreeBSD has no equivalent. Ship a no-op shim; id falls back to /etc/passwd like FreeBSD's. Real OD work is a separate, far-future phase.

Mach traps needed before system_cmds Tier B

4 new traps for lsmp + hostinfo + stackshot (port-space introspection, host info flavors, stackshot syscall). All fit the multiplexer slot 219 pattern; ~600 LOC of mach.ko work. nvram needs an IOKit NVRAM driver — separate track, much bigger.

pkg upgrade restores FreeBSD versions

Same caveat as before. The ISO never pkg upgrades; dev machines run the overwrite step manually after upgrades.

cp --reflink semantics

Apple cp uses clonefile(2) automatically on supported filesystems. On FreeBSD UFS this no-ops to byte-copy. On ZFS we might want it to call zfs_clone_range eventually; not required.

libdispatch dependency for mtree + sort

Both use libdispatch. We already ship /usr/lib/system/libdispatch.so, so this is free.

12. Out of scope

Drafted 2026-05-13 from five parallel agent passes across /Users/jmaloney/Documents/launchd/{bootstrap,file,shell,system,network,text}_cmds/. Companion to the launchd-842 port plan. All file:line citations link back to the verbatim Apple sources.