Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Log in or create an account to edit The Apple Wiki.

Dev:Mounting APFS

From The Apple Wiki

APFS is a file system developed and deployed by Apple Inc..

Mounting APFS requires pointer to data specific to apfs to be passed to the fourth argument of mount(2). The struct for this data is supposedly available in apfs/apfs_mount.h, but this header is not public.

Reverse Engineered Header

#include <sys/types.h>

/* APFS mode modes */
#define APFS_MOUNT_DEFAULT_SNAPSHOT         0x0 /* mount the default snapshot */
#define APFS_MOUNT_LIVEFS                   0x1 /* mount live fs */
#define APFS_MOUNT_CUSTOM_SNAPSHOT          0x2 /* mount custom snapshot in args->snapshot */
#define APFS_MOUNT_AUTHENTICATED_SNAPSHOT   0x3 /* authenticated snapshot mount with im4p and im4m */
#define APFS_MOUNT_FUSION_T1_T2             0x4 /* Fusion mount with tier 1 & 2, set by mount_apfs when -C is used (Conversion mount) */
#define APFS_MOUNT_FUSION_T1_ONLY           0x5 /* Fusion mount with tier 1 only, set by mount_apfs when -c is used */
#define APFS_MOUNT_MODE_SIX                 0x6 /* ??????? */
#define APFS_MOUNT_FOR_INVERT               0x7 /* ??? mount for invert */
#define APFS_MOUNT_IMG4                     0x8 /* authenticated mount with im4p and im4m */
/* End APFS mount modes*/

#define APFS_MOUNT_IMG4_MAXSZ               0x100000

#define APFS_AUTH_ENV_GENERIC               4
#define APFS_AUTH_ENV_SUPPLEMENTAL          5
#define APFS_AUTH_ENV_PDI_NONCE             6

#define APFS_CRYPTEX_TYPE_GENERIC           0x67746776 /* vgtg */
#define APFS_CRYPTEX_TYPE_BRAIN             0x73796162 /* bays */

#define APFS_FLAGS_SMALL_N_OPT              0x400000000 /* mount_apfs -n */
#define APFS_FLAGS_LARGE_R_OPT              0x200000000 /* mount_apfs -R */
#define APFS_FLAGS_LARGET_S_OPT             0x800000000 /* mount_apfs -S */

/* Fourth argument to mount(2) when mounting apfs */
struct apfs_mount_args {
#ifndef KERNEL
    char* fspec; /* path to device to mount from */
#endif
    uint64_t apfs_flags; /* The standard mount flags, OR'd with apfs-specific flags (APFS_FLAGS_* above) */
    uint32_t mount_mode; /* APFS_MOUNT_* */
    uint32_t pad1; /* padding */
    uint32_t unk_flags; /* yet another type some sort of flags (bitfield), possibly volume role related */
    union {
        char snapshot[256]; /* snapshot name */
        struct {
            char tier1_dev[128]; /* Tier 1 device (Fusion mount) */
            char tier2_dev[128]; /* Tier 2 device (Fusion mount) */
        };
    };
    void* im4p_ptr;
    uint32_t im4p_size;
    uint32_t pad2; /* padding */
    void* im4m_ptr;
    uint32_t im4m_size;
    uint32_t pad3; /* padding */
    uint32_t cryptex_type; /* APFS_CRYPTEX_TYPE_* */
    int32_t auth_mode; /* APFS_AUTH_ENV_* */
    uid_t uid;
    gid_t gid;
}__attribute__((packed, aligned(4)));

typedef struct apfs_mount_args apfs_mount_args_t;

Mounting Live FS

To mount /dev/disk0s1s1 onto / in read-write mode:

apfs_mount_args_t args = { "/dev/disk0s1s1", 0, APFS_MOUNT_LIVEFS };
mount("apfs", "/", 0, &args);

To mount /dev/disk0s1s1 onto / in read-only mode:

apfs_mount_args_t args = { "/dev/disk0s1s1", MNT_RDONLY, APFS_MOUNT_LIVEFS };
mount("apfs", "/", MNT_RDONLY, &args);
  • Setting args->apfs_flags is not required for the mount to go through (0 works), but mount_apfs does it.

Mounting snapshot

To mount the default snapshot com.apple.os.update-${boot_manifest_hash} of /dev/disk0s1s1 onto /:

apfs_mount_args_t args = { "/dev/disk0s1s1", MNT_RDONLY, APFS_MOUNT_DEFAULT_SNAPSHOT };
mount("apfs", "/", MNT_RDONLY, &args); /* remember the snapshots must be read-only */

To mount a custom snapshot named orig-fs:

apfs_mount_args_t args = { "/dev/disk0s1s1", MNT_RDONLY, APFS_MOUNT_CUSTOM_SNAPSHOT, 0, 0, "orig-fs" };
mount("apfs", "/", MNT_RDONLY, &args); /* remember the snapshots must be read-only */

Update mount

To remount an APFS volume /dev/disk0s1s3 mounted at /private/preboot as read-write:

apfs_mount_args_t args = { "/dev/disk0s1s3", MNT_UPDATE, APFS_MOUNT_LIVEFS };
mount("apfs", "/", MNT_UPDATE, &args);
  • args->fspec can actually be arbitrary values, which allows for spoofing source volumes.