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), butmount_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.