One
Apple File System(APFS)の Firmlink を読み解く

本記事は以下の言語でもご覧いただけます: English | 中文

macOS Catalina 以降、Apple は APFS コンテナ内でシステムデータとユーザーデータを分離する新しいファイルシステム階層を導入しました。システムファイル用に読み取り専用でマウントされる Macintosh HD、アプリケーションや環境設定などユーザーが扱うファイル用に書き込み可能でマウントされる Macintosh HD - Data です。RecoveryOS に使われる Recovery など、ほかのボリュームもあります。

$ diskutil list
/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *1.0 TB     disk0
   1:             Apple_APFS_ISC Container disk2         524.3 MB   disk0s1
   2:                 Apple_APFS Container disk3         994.7 GB   disk0s2
   3:        Apple_APFS_Recovery Container disk1         5.4 GB     disk0s3

/dev/disk3 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +994.7 GB   disk3
                                 Physical Store disk0s2
   1:                APFS Volume Macintosh HD - Data     410.4 GB   disk3s1
   2:                APFS Volume Macintosh HD            8.9 GB     disk3s3
   3:              APFS Snapshot com.apple.os.update-... 8.9 GB     disk3s3s1
   4:                APFS Volume Preboot                 4.7 GB     disk3s4
   5:                APFS Volume Recovery                769.9 MB   disk3s5
   6:                APFS Volume VM                      2.1 GB     disk3s6

各ボリュームの役割は、Apple の APFS Reference に記載されたスーパーブロック構造(apfs_superblock_t)で定義されています。

#define APFS_VOL_ROLE_NONE      0x0000
#define APFS_VOL_ROLE_SYSTEM    0x0001
#define APFS_VOL_ROLE_USER      0x0002
#define APFS_VOL_ROLE_RECOVERY  0x0004
#define APFS_VOL_ROLE_VM        0x0008
#define APFS_VOL_ROLE_PREBOOT   0x0010
#define APFS_VOL_ROLE_INSTALLER 0x0020
#define APFS_VOL_ROLE_DATA      0x0040
#define APFS_VOL_ROLE_BASEBAND  0x0080

これは当時の macOS では新しい仕組みでしたが、iOS では以前から使われていました。システムの起動時には、Macintosh HDAPFS_VOL_ROLE_SYSTEM)と Macintosh HD - DataAPFS_VOL_ROLE_DATA)の内容が firmlink によって結合され、単一の論理ボリュームとして表示されます。

Firmlink はシンボリックリンクに似ていますが、ディレクトリ専用で双方向にたどれます。これにより macOS は Macintosh HDMacintosh HD - Data の内容を結合できます。たとえば読み取り専用の Macintosh HD にある /Users は、書き込み可能な Macintosh HD - Data/Shared への firmlink です。Apple の System Integrity Protection(SIP)も自然に機能します。SIP で保護されたシステムアプリケーションは読み取り専用の /System/Applications にあり、ユーザーのアプリケーションは /Applications にインストールされますが、利用者にはどちらもルートの /Applications に統合して見えます。

システムの firmlink は /usr/share/firmlinks にあります。

$ cat /usr/share/firmlinks
/AppleInternal	AppleInternal
/Applications	Applications
/Library	Library
/System/Library/Caches	System/Library/Caches
/System/Library/Assets	System/Library/Assets
/System/Library/PreinstalledAssets	System/Library/PreinstalledAssets
/System/Library/AssetsV2	System/Library/AssetsV2
/System/Library/PreinstalledAssetsV2	System/Library/PreinstalledAssetsV2
/System/Library/CoreServices/CoreTypes.bundle/Contents/Library	System/Library/CoreServices/CoreTypes.bundle/Contents/Library
/System/Library/Speech	System/Library/Speech
/Users	Users
/Volumes	Volumes
/cores	cores
/opt	opt
/private	private
/usr/local	usr/local
/usr/libexec/cups	usr/libexec/cups
/usr/share/snmp	usr/share/snmp

Catalina 以降でルート直下のディレクトリを作成するには、synthetic firmlink を使います。

  • /etcsynthetic.conf というファイルを作成します。
  • 権限が次のように設定されていることを確認します。
root: read, write
wheel: read
everyone: read

通常は “sudo touch /etc/synthetic.conf” で上記を満たせます。

ディレクトリ /Users/foo/bar/baz にリンクするには、作成したファイルに次のエントリを追加します。

# create a firmlink named "baz" at / which points to "Users/foo/bar"
baz Users/foo/bar

利用可能なオプションは man synthetic.conf でも確認できます。2 つの値はスペースではなくタブで区切る必要があり、パスの先頭には / を付けない点に注意してください。システムを再起動すると、変更が反映されます。