Skip to content
Alexey Kuzko edited this page Oct 29, 2024 · 74 revisions

NTFS-3G is an open source cross-platform implementation of the Microsoft Windows NTFS file system with read-write support.

Please note that NTFS-3G and FUSE for macOS are independent projects. Should you run into NTFS-3G related issues please post the issues on Tuxera NTFS-3G or homebrew-fuse.

Installation

The following instructions assume that you know how to use Terminal. Doing this the wrong way could damage your operating system.

First, download and install the latest release of FUSE for macOS from http://osxfuse.github.io. You will need at least version 3.0.

Then, if you don't have it yet, install the package manager "Homebrew" as described on https://brew.sh.

Install NTFS-3G from Homebrew by opening a Terminal and entering the following commands. (#818)

brew tap gromgit/homebrew-fuse
brew install ntfs-3g-mac

After installing NTFS-3G you can manually mount NTFS volumes in read-write mode by executing the following commands in Terminal. Replace /dev/disk1s1 with the actual NTFS partition you want to mount. You can find the partition name using diskutil list.

# unmount if necessary
sudo diskutil unmount /dev/disk1s1
# mount with ntfs-3g
sudo mkdir /Volumes/NTFS
sudo /usr/local/bin/ntfs-3g /dev/disk1s1 /Volumes/NTFS -o local -o allow_other -o auto_xattr -o auto_cache
# alternatively...
sudo /usr/local/sbin/mount_ntfs /dev/disk1s1 /Volumes/NTFS

Auto-remount NTFS volumes in read-write mode without tampering with the system volume

launchd can run a script after a mount, which means that every read-only mounted NTFS volume can be automatically remounted as read-write. Here's an example of such a script:

#!/usr/bin/env zsh

emulate -L zsh
set -euo pipefail -o nullglob
umask 0022

readonly TMP_PREFIX=/tmp/ntfs-remount-rw
readonly LOGFILE="$TMP_PREFIX-$$.log"

log() {
    local time
    time="$(date -Iseconds)"
    printf '%s: %s\n' "$time" "$1" | tee -a "$LOGFILE"
}

# Expand trap right away.
# shellcheck disable=SC2064
trap "log '$0:a:t FINISHED WITH ERROR'" ZERR

release_lock() {
    local -r device="$1" lock_file="$2"
    rm "$lock_file"
    log "Released the lock for $device"
}

ntfs_remount_rw() {
    local -r device="$1" dev_name="$1:t"
    local -r lock_file="$TMP_PREFIX-$dev_name.lock"
    if ( set -o noclobber && printf '%s\n' "$$" > "$lock_file" ); then (
        # Expand trap right away.
        # shellcheck disable=SC2064
        trap "release_lock '$device' '$lock_file'" INT EXIT ZERR

        log "Acquired a lock for $device"

        # Verify that device is still mounted as NTFS.
        local still_ntfs=0
        still_ntfs="$(mount -t ntfs | { grep -c "$device" || :; })"
        if (( still_ntfs == 1 )); then
            log "$device is still mounted as NTFS after lock acquisition"

            local dev_info mnt_point
            dev_info="$(diskutil info -plist "$device")"
            mnt_point="$(plutil -extract MountPoint raw - <<< "$dev_info")"
            log "$device mount point is '$mnt_point'"

            diskutil unmount "$device"
            log "$device was unmounted"

            sudo /opt/homebrew/sbin/mount_ntfs -o nodev,nosuid,noexec "$device" "$mnt_point"
            log "Successfully remounted $device"
        else
            log "$device was probably already remounted"
        fi
    ) else
        log "Failed to acquire a lock for $device"
    fi
}

main() {
    log "About to remount all NTFS volumes as read-write"

    local device
    mount -t ntfs | cut -d' ' -f1 | while read -r device; do
        log "Attempting to remount $device"
        ntfs_remount_rw "$device"
    done
}

main

When the above script is called, it iterates over all NTFS volumes currently mounted, and remounts them read-write with the help of /opt/homebrew/sbin/mount_ntfs. The script attempts to avoid remounting the same volume twice (e.g. when the script was invoked the second time while the previous remount hasn't been finished yet) by checking for the presence of /tmp/ntfs-remount-rw-DEVICE_NAME.lock file. Script operation are logged to stdout and to /tmp/ntfs-remount-rw-SCRIPT_PID.log.

In order to launch the above script automatically on mount:

  1. Copy the content of the script to /opt/ntfs-remount-rw.sh.
  2. Create /Library/LaunchAgents/ntfs-remount-rw.plist with the following content:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Inc//DTD PLIST 1.0//EN"
                           "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <key>Label</key>
        <string>ntfs-remount-rw</string>
        <key>Program</key>
        <string>/opt/ntfs-remount-rw.sh</string>
        <key>StartOnMount</key>
        <true/>
      </dict>
    </plist>
  3. Grant all users the right to run /opt/homebrew/sbin/mount_ntfs by creating /etc/sudoers.d/ntfs-remount-rw with the following content:
    ALL ALL = NOPASSWD: /opt/homebrew/sbin/mount_ntfs \
                        ^-o nodev\,nosuid\,noexec /dev/disk[0-9]+(s[0-9]+){0,2} /Volumes/[^/]+$
    
    WARNING: After this step, /opt/homebrew/sbin/mount_ntfs can be executed as root by any user. Due to the way Homebrew installs software packages, /opt/homebrew/sbin/mount_ntfs is not protected from being tampered by unprivileged attackers, essentially giving those attackers root access to your Mac. Since the automatic remounting requires the right to run /opt/homebrew/sbin/mount_ntfs as root to be given to all users, the method presented here is no more secure than replacing the system's /sbin/mount_ntfs.
  4. Either reboot the system or start the launch agent with:
    launchctl load -w /Library/LaunchAgents/ntfs-remount-rw.plist

Auto-mount NTFS volumes in read-write mode

Even though you have installed NTFS-3G, newly connected NTFS volumes will still be auto-mounted in read-only mode using the original driver. To change this you need to replace Apple's NTFS mount tool /sbin/mount_ntfs with the one provided by NTFS-3G.

It is important that you understand the security implications of what you are about to do. The mount tool is executed with root permissions. This means that NTFS-3G's mount tool will be executed with root permissions, too. Due to the way Homebrew installs software packages, NTFS-3G's mount tool is not protected from being tampered with by unprivileged attackers, essentially giving those attackers root access to your Mac. This is a major security risk. You have been warned.

The System Integrity Protection (SIP) system on Catalina (10.15.x) prevents the modification of system files, including /sbin, by default. (It does not protect against the issue mentioned above.) As a result, the replacement will be done in recovery mode. See https://support.apple.com/en-us/HT201314 for details on how to start the recovery system. We do not yet know how to work with Big Sur's SSV cleanly. Again, tempering with system files is risky and probably bricky. DO NOT proceed if you have trouble understanding ANY of the commands.

  1. Reboot to Recovery mode. (Turn on your Mac and immediately press and hold Command (⌘)-R.)
  2. Disable SIP if macOS is Catalina. Run csrutil disable, and reboot to recovery mode again.
  3. Open Terminal in Recovery Mode from Menu bar -> Utilities -> Terminal
  4. Unlock the system volume if it is APFS:
    1. Run diskutil list.
    2. Find the volume labelled (synthesized). That would be the one with macOS installed. Note its IDENTIFIER (something like disk2s1).
    3. Unlock the volume with diskutil apfs unlockVolume [volume-identifier].
    4. Remount the root volume in read-write with mount -uw /.
  5. Go to the sbin of the system folder with cd "/Volumes/Macintosh HD/sbin".
    • The Volume name might be different if you have changed it. Again, run diskutil list to figure out the name.
  6. Back up the original mount_ntfs using mv mount_ntfs mount_ntfs.orig.
  7. Make NTFS-3G the default mount_ntfs by running:
cat > mount_ntfs << 'EOF'
#!/bin/sh
# fall back to the system version if ntfs-3g is gone.
if [ -x /usr/local/sbin/mount_ntfs ]; then
  exec /usr/local/sbin/mount_ntfs "$@"
else
  exec /sbin/mount_ntfs.orig "$@"
fi
EOF
chmod +x mount_ntfs
  1. If you want to re-enable SIP, run csrutil enable.
  2. Reboot and test.

Big Sur and the SSV

Big Sur has the Sealed System Volume system replacing the SIP. It is much stricter: the system will be very angry if any of the files are changed. It will still run, but everything "sensitive" is disabled. The unlocking command is different, so you are unlikely to accidentally break it.

The big-brand filesystems don't have this issue because they have always handled Automount in the proper way: registering a different filesystem altogether.

Uninstallation

To uninstall NTFS-3G, open a Terminal prompt and enter the following:

brew uninstall ntfs-3g

If you have replaced Apple's NTFS mount tool /sbin/mount_ntfs with the one provided by NTFS-3G to auto-mount NTFS volumes in read-write mode you will need to restore the original mount tool.

SIP notes On OS X El Capitan files in the `/sbin` directory are protected from being tampered with by a new security feature called System Integrity Protection (SIP). You will need to reboot your Mac in recovery mode before proceeding. See above for details.

To restore Apple's NTFS mount tool execute the following command in Terminal.

sudo mv "/Volumes/Macintosh HD/sbin/mount_ntfs.orig" "/Volumes/Macintosh HD/sbin/mount_ntfs"

Frequently Asked Questions

1. Why is NTFS-3G's write performance so poor?

The ntfs-3g program opens and does I/O to the block device /dev/disk[number] of the NTFS volume in question. macOS does not have a VM buffer cache for block devices when they are accessed in this way. That is the most overwhelming factor, because both metadata operations and file data I/O boil down to read-writes by NTFS-3G to the block device.

Suppose we somehow automagically provided unified buffer caching for block devices by essentially making a disk look like a giant file. Even then, macOS and its buffer cache is really happy only when you do I/O that is in units of page size (4KB) and aligned on a page boundary. To get the most out of the I/O subsystem in macOS, ntfs-3g (or any other program for that matter) would really want to do I/O in multiples of 4KB.

For comparison, you should try writing to an NTFS disk image. You will see that it is considerably faster because you do have some caching in that case.

2. After installing NTFS-3G, my Boot Camp volume stopped showing up in the "Startup Disk" preference pane. Is reinstalling macOS, Boot Camp, and Windows the only recourse?

Relax. The "Startup Disk" preference pane is simply filtering out (that is, not displaying) any mounted volumes that it does not consider bootable. Its definition of a Boot Camp volume includes that the mounted volume either be of type msdos or ntfs - this is hardcoded into the preference pane plugin. This does not mean your Boot Camp volume has become unbootable. It is merely not showing up in the graphical user interface. You can hold the "opt" key during startup and choose the Windows partition to boot from. You can also remount it (read-only) using the NTFS file system built into macOS and it should start showing up in "Startup Disk".

3. I don't like the AppleDouble ._ files on my NTFS drive. Can I turn that off?

Yes! There are actually two approaches to removing them:

  • You can add -o noappledouble to forcibly turn off access to these files. This is preferable for removable drives, since permissions don't really matter.
  • You can remove the auto_xattr part from the mount options and replace it with streams_interface=openxattr. This completely opens up the NTFS streams interface for storing extended attributes, so AppleDouble files are no longer required.
    • If your ntfs-3g is built with --enable-extra, you can actually map Windows users onto Unix permissions and use it like a normal drive. You might want to turn off inherit so you can properly use chmod. Also turn on -o extended_security if you want ACL.

Note: AppleDouble files are meant for storing extended attributes like advanced ACL permissions and Spotlight tags when there is no xattr support. If you turn AppleDouble off without an adequate xattr mechanism, stuff can fail.

Note 2: NTFS-3G had a bug that prevents macOS from understanding when an attribute is missing. A fix is available, but the brew people do not want to package the Advanced Release.