mtree(8) is a surprisingly unknown tool! It operates in one of three modes: it compares a file hierarchy against a specification, it creates a specification for a file hierarchy, or it modifies a specification. The specification provides for a range of properties, typically including names (and symlink targets), ownership information, permission bits, and timestamps, and may also include checksums of the files. As a result of its age — its first “real” release was likely 4.3BSD-Reno — it’s propagated into all BSD-derived operating systems: a version of mtree(8) ships in all of FreeBSD, OpenBSD, NetBSD, DragonflyBSD, and macOS.

I’ve recently had the pleasure of diving deep into its convoluted history, so I thought I might write up some of what I found.

mtree(8) was initially developed fairly late in the life of the Berkeley Software Distribution. Source artefacts from the Computer Systems Research Group suggest it was likely written by Keith Bostic in 1989 — though I don’t know how far to trust the timestamps preserved by SCCS here — and slowly evolved along with the rest of the distribution. For example, mtree(8) predates fts(3), but was reworked to support it when it arrived.

As CSRG wound down in the early 1990s, other groups picked up and ran with the unencumbered parts of the distribution — The Lawsuit was ongoing at the time — and we find that the NetBSD project (and, later, the OpenBSD and FreeBSD projects) pick up the story here. The history gets somewhat clearer here, as most of the downstream projects adopted CVS.

The BSD projects cross-pollinate freely, so features in one implementation will wind up in others. FreeBSD maintained their own implementation for many years, but have since switched to tracking NetBSD’s implementation. OpenBSD derived from NetBSD, but tracks much less closely.

A “portable” version ships with pkgsrc, but this version seems unmaintained, and is missing improvements from the last decade. It may be this is a deliberate choice to preserve compatibility and portability, but that’s speculation on my part.

In an attempt to put together an authoritative, up-to-date, portable version, I’ve attempted to reconstruct its history which you can browse as a Git repository on GitLab or on Github. This was also an interesting adventure, and I ended up writing some tooling to produce git-fast-import input from the constellation of history variously stored in SCCS, CVS, Subversion, Git, and Mercurial.

I’m planning to fix up and expand the set of tests, and work through the changes made in FreeBSD and OpenBSD to try to capture any features that may otherwise be lost.