macOS can't read a Linux ext4 partition at all, and it mounts Windows
NTFS read-only. The usual fix — macFUSE — is a kernel extension. On Apple
Silicon that means booting into Recovery, lowering your security policy to "Reduced", and
approving a third-party kext that runs in the kernel. A lot of people (reasonably) don't want
to do that to copy some files off a NAS disk. This is how you get full read/write to both
filesystems with no kernel extension at all, and the engineering details that make it
hold together on a signed, notarized app.
FUSE ("Filesystem in Userspace") lets a normal program implement a filesystem. But the
kernel still has to route open()/read()/write() syscalls
out to that userspace program. macFUSE does the routing with a kernel extension: a
/dev/macfuse* character device backed by kext code.
FUSE-T takes a different route. Instead of a kext, it stands up a tiny userspace NFS server on localhost and asks the kernel's built-in, first-party NFS client to mount it. The NFS client already lives in the kernel and is signed by Apple, so there's nothing to approve, no Recovery Mode, no reduced security. Your filesystem driver talks FUSE to a FUSE-T daemon, which translates to NFS, which the kernel speaks natively. Same end result, zero third-party kernel code.
ext4 / NTFS driver ⇄ libfuse ⇄ FUSE-T daemon ⇄ NFS (localhost) ⇄ macOS kernel
There's a trade-off worth stating plainly: NFS semantics aren't identical to a native VFS
mount. A couple of things look different through statfs (more on that below), and
throughput is good but not driver-level. For "write a 30 GB folder to a NAS disk", that's a
fine deal for never touching the kernel.
For ext4 the driver is fuse2fs, which ships with e2fsprogs and
implements the filesystem on top of libext2fs. It mounts read/write over FUSE-T and handles
real ext4 — including the awkward ones from NAS boxes with internal quotas enabled.
The subtle bug everyone hits: fuse2fs does not replay the ext4 journal. A
disk that a Linux box or NAS unmounted uncleanly comes to you "dirty" — the journal has
committed transactions that were never written back to their final blocks. Mount it straight and
you get cannot read block bitmap and a failed mount, on a disk that is actually
fine. The fix is to run a preflight check that replays the journal first:
# replay the journal / repair before mounting read/write
e2fsck -p /dev/diskXsY # -p: automatic, safe repairs only
# if the superblock has error flags set, escalate:
e2fsck -fy /dev/diskXsY
Skip this on a read-only mount (you don't want to touch the disk), but for read/write it's the difference between "it works" and "this app is broken". Give the check a generous timeout, too — a journal replay on a 14 TB NAS volume is not instant.
ntfs-3g is the reference open-source NTFS driver — the same one every Linux
distro ships. The catch on macOS is that the common Homebrew build links against macFUSE's
libfuse, which drags the kext back in. The fix is to build ntfs-3g
against FUSE-T's libfuse instead, so the whole NTFS path is kext-free as well.
One more gotcha: a drive Windows left hibernated (Fast Startup, or not cleanly ejected) mounts read-only or refuses to mount. Clearing the hibernation file lets it mount read/write:
ntfs-3g -o remove_hiberfile /dev/diskXsY /Volumes/mountpoint
macOS will happily auto-mount an NTFS disk itself, read-only, before any third-party
tool acts. Detecting that reliably is trickier than it looks. A "try to write a temp file" probe
gives false results over the NFS-backed FUSE-T mount. The honest signal is the one Disk Utility
uses: the MNT_RDONLY flag from statfs(2). That's what tells you a volume
is genuinely mounted read-only, so you can offer to remount it writable instead of guessing.
None of this matters if the OS blocks the binaries. A distributable build needs:
fuse2fs, ntfs-3g, e2fsck, mke2fs and friends,
plus the app and CLI.fuse2fs and ntfs-3g load FUSE-T's library, which is signed by a
different team, so they need the library-validation entitlement disabled
(com.apple.security.cs.disable-library-validation) or the OS kills them on launch.SMAppService (macOS 13+) registers a helper daemon the app can talk to over XPC —
which is also why kext-free mounting is a macOS 13+ story in practice.Get those three right and you have ext4 and NTFS read/write on a stock Mac with Full Disk Access and nothing else — no Recovery, no kext, no reduced security.
Everything above is open source: FUSE-T, e2fsprogs/fuse2fs,
ntfs-3g. If you enjoy wiring together build scripts, code-signing entitlements and a
privileged helper, go for it — it's a good weekend. Omnimount is what you get when someone already
did that and wrapped it in a menu-bar app; it's GPL-3.0, so you can read exactly how every piece
fits together.
Don't want to assemble the stack yourself? Omnimount ships FUSE-T, fuse2fs/e2fsprogs and ntfs-3g bundled, signed and notarized — mount, write, format, check and clone ext4 and NTFS from the menu bar, no kernel extensions and no Recovery Mode.
Get Omnimount — €9.99 or build it free (GPL)