From 40ae4a46cff9bbb2e2f968ffca11d583491aaf4f Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 00:17:25 +0000 Subject: [PATCH 01/20] Correct some struct comments --- src/apfs/struct/spaceman.h | 2 +- src/apfs/struct/xf.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apfs/struct/spaceman.h b/src/apfs/struct/spaceman.h index fe663df..e1bc243 100644 --- a/src/apfs/struct/spaceman.h +++ b/src/apfs/struct/spaceman.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §16 "Space Manager" + * §17 "Space Manager" */ #include diff --git a/src/apfs/struct/xf.h b/src/apfs/struct/xf.h index fb6e906..41c8e35 100644 --- a/src/apfs/struct/xf.h +++ b/src/apfs/struct/xf.h @@ -20,7 +20,7 @@ typedef struct { uint16_t x_size; } x_field_t; -/// Extended-Field Types /// +/** Extended-Field Types **/ #define DREC_EXT_TYPE_SIBLING_ID 1 @@ -40,7 +40,7 @@ typedef struct { #define INO_EXT_TYPE_RDEV 14 -/// Extended-Field Flags /// +/** Extended-Field Flags **/ #define XF_DATA_DEPENDENT 0x0001 #define XF_DO_NOT_COPY 0x0002 From b2e837fedcfcce80a34557d5431a6436b2d1632f Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 12:56:38 +0000 Subject: [PATCH 02/20] Correct name of `APFS_FS_FLAGS_VALID_MASK` --- src/apfs/struct/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index 6ef8ae4..3dbe85f 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -96,7 +96,7 @@ typedef struct { #define APFS_FS_RUN_SPILLOVER_CLEANER 0x00000020LL #define APFS_FS_ALWAYS_CHECK_EXTENTREF 0x00000040LL -#define APFS_FS_FALGS_VALID_MASK ( \ +#define APFS_FS_FLAGS_VALID_MASK ( \ APFS_FS_UNENCRYPTED \ | APFS_FS_RESERVED_2 \ | APFS_FS_RESERVED_4 \ From 6e1d1e38097832b1743229c0465ad14e70a5db7f Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Wed, 3 Feb 2021 21:08:59 +0000 Subject: [PATCH 03/20] Create list of new symbols to add (notes.md) --- notes.md | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 notes.md diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..ec6fcb4 --- /dev/null +++ b/notes.md @@ -0,0 +1,157 @@ +# §3 Objects + + ## Object Types + + - [ ] OBJECT_TYPE_ER_RECOVERY_BLOCK + - [ ] OBJECT_TYPE_SNAP_META_EXT + - [ ] OBJECT_TYPE_FEXT_TREE + - [ ] OBJECT_TYPE_INTEGRITY_META + - [ ] OBJECT_TYPE_MEDIA_KEYBAG + - [ ] OBJECT_TYPE_RESERVED_20 + +# §5 Container + + ## `nx_superblock_t` + + - [ ] nx_newest_mounted_version + - [ ] nx_mkb_locker + +# §6 Object Maps + + ## Object Map Flags + + - [ ] OMAP_VALID_FLAGS + +# §7 Volumes + + ## `apfs_superblock_t` + + - [ ] apfs_cloneinfo_id_epoch + - [ ] apfs_cloneinfo_xid + - [ ] apfs_snap_meta_ext_oid + - [ ] apfs_volume_group_id + - [ ] apfs_integrity_meta_oid + - [ ] apfs_fext_tree_oid + - [ ] apfs_fext_tree_type + - [ ] reserved_type + - [ ] reserved_oid + + ## Volume Flags + + - [ ] APFS_FS_RESERVED_80 + - [ ] APFS_FS_RESERVED_100 + + ## Volume Roles + + - [ ] APFS_VOL_ROLE_UPDATE + - [ ] APFS_VOL_ROLE_XART + - [ ] APFS_VOL_ROLE_HARDWARE + - [ ] APFS_VOL_ROLE_BACKUP + - [ ] APFS_VOL_ROLE_RESERVED_7 + - [ ] APFS_VOL_ROLE_RESERVED_8 + - [ ] APFS_VOL_ROLE_ENTERPRISE + - [ ] APFS_VOL_ROLE_RESERVED_10 + - [ ] APFS_VOL_ROLE_PRELOGIN + + ## Optional Volume Feature Flags + + - [ ] APFS_FEATURE_STRICTATIME + - [ ] APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE + + ## Incompatible Volume Feature Flags + + - [ ] APFS_INCOMPAT_INCOMPLETE_RESTORE + - [ ] APFS_INCOMPAT_SEALED_VOLUME + +# §8 File-System Objects + + ## `j_key_t` + + - [x] SYSTEM_OBJ_ID_MARK + + ## `j_inode_val_t` + + - [x] uncompressed_size + +# §9 File-System Constants + + ## `j_obj_types` + + - [x] APFS_TYPE_FILE_INFO + + ## `j_inode_flags` + + - [ ] INODE_FAST_PROMOTE + - [ ] INODE_HAS_UNCOMPRESSED_SIZE + - [ ] INODE_IS_PURGEABLE + - [ ] INODE_WANTS_TO_BE_PURGEABLE + - [ ] INODE_IS_SYNC_ROOT + - [ ] INODE_SNAPSHOT_COW_EXEMPTION + + ## Inode Numbers + + - [ ] PURGEABLE_DIR_INO_NUM + - [ ] UNIFIED_ID_SPACE_MARK + + ## Extended Attributes Constants + + - [ ] FIRMLINK_EA_NAME + - [ ] APFS_COW_EXEMPT_COUNT_NAME + +# §11 Extended Fields + + ## Extended-Field Types + + - [ ] INO_EXT_TYPE_PURGEABLE_FLAGS + - [ ] INO_EXT_TYPE_ORIG_SYNC_ROOT_ID + +# §13 Snapshot Metadata + + ## `snap_meta_ext_obj_phys_t` + + - [ ] *New datatype* `snap_meta_ext_obj_phys_t` + + ## `snap_meta_ext_t` + + - [ ] *New datatype* `snap_meta_ext_t` + +# §14 B-Trees + + ## `btn_index_node_val_t` + + - [ ] *New datatype* `btn_index_node_val_t` + + ## B-Tree Flags + + - [ ] BTREE_HASHED + - [ ] BTREE_NOHEADER + + ## B-Tree Node Flags + + - [ ] BTNODE_HASHED + - [ ] BTNODE_NOHEADER + +# §15 Encryption + + ## Protection Classes + + - [ ] PROTECTION_CLASS_M + + ## Encryption Identifiers + + - [ ] APFS_UNASSIGNED_CRYPTO_ID + + ## Keybag Tags + + - [ ] KB_TAG_WRAPPING_M_KEY + - [ ] KB_TAG_VOLUME_M_KEY + +# §16 Sealed Volumes + +- [ ] *New chapter* Sealed Volumes + +# §17 Space Manager + + ## `spaceman_free_queue_entry_t` + + - [ ] *New datatype* `spaceman_free_queue_entry_t` From d667b7c01aa1e38d3698579581ec276560198d80 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Wed, 3 Feb 2021 23:18:54 +0000 Subject: [PATCH 04/20] =?UTF-8?q?Update=20=C2=A73=20Objects:=20Object=20Ty?= =?UTF-8?q?pes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 12 ++++++------ src/apfs/string/object.c | 19 +++++++++++++------ src/apfs/struct/object.h | 7 +++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/notes.md b/notes.md index ec6fcb4..093fbaf 100644 --- a/notes.md +++ b/notes.md @@ -2,12 +2,12 @@ ## Object Types - - [ ] OBJECT_TYPE_ER_RECOVERY_BLOCK - - [ ] OBJECT_TYPE_SNAP_META_EXT - - [ ] OBJECT_TYPE_FEXT_TREE - - [ ] OBJECT_TYPE_INTEGRITY_META - - [ ] OBJECT_TYPE_MEDIA_KEYBAG - - [ ] OBJECT_TYPE_RESERVED_20 + - [x] OBJECT_TYPE_ER_RECOVERY_BLOCK + - [x] OBJECT_TYPE_SNAP_META_EXT + - [x] OBJECT_TYPE_INTEGRITY_META + - [x] OBJECT_TYPE_FEXT_TREE + - [x] OBJECT_TYPE_RESERVED_20 + - [x] OBJECT_TYPE_MEDIA_KEYBAG # §5 Container diff --git a/src/apfs/string/object.c b/src/apfs/string/object.c index ff74908..4c7fbe6 100644 --- a/src/apfs/string/object.c +++ b/src/apfs/string/object.c @@ -126,7 +126,7 @@ char* get_o_type_string(uint32_t o_type) { // This string is a legal `sprintf()` format string. char* default_string = "Unknown type (0x%08x) --- perhaps this type was introduced in a later version of APFS than that published on 2019-02-27."; - size_t NUM_FLAGS = 22; + size_t NUM_FLAGS = 26; uint32_t flag_constants[] = { OBJECT_TYPE_NX_SUPERBLOCK, OBJECT_TYPE_BTREE, @@ -146,6 +146,10 @@ char* get_o_type_string(uint32_t o_type) { OBJECT_TYPE_ER_STATE, OBJECT_TYPE_GBITMAP, OBJECT_TYPE_GBITMAP_BLOCK, + OBJECT_TYPE_ER_RECOVERY_BLOCK, + OBJECT_TYPE_SNAP_META_EXT, + OBJECT_TYPE_INTEGRITY_META, + OBJECT_TYPE_RESERVED_20, OBJECT_TYPE_INVALID, OBJECT_TYPE_TEST, OBJECT_TYPE_CONTAINER_KEYBAG, @@ -170,7 +174,11 @@ char* get_o_type_string(uint32_t o_type) { "Encryption-rolling state", "General-purpose bitmap", "General purpose bitmap block", - "(none/invalid)", + "Encryption-rolling recovery block", + "Additional snapshot metadata", + "Integrity metadata", + "Reserved type/subtype (0x20)", + "(invalid type / no subtype)", "A type reserved for testing (should never appear on disk --- if it does, file a bug against the APFS implementation that created this object)", "Container keybag", "Volume keybag", @@ -243,8 +251,7 @@ char* get_o_subtype_string(uint32_t o_subtype) { // This string is a legal `sprintf()` format string. char* default_string = "Unknown subtype (0x%08x) --- perhaps this subtype was introduced in a later version of APFS than that published on 2019-02-27."; - size_t NUM_FLAGS = 8; - + size_t NUM_FLAGS = 9; uint32_t flag_constants[] = { OBJECT_TYPE_SPACEMAN_FREE_QUEUE, OBJECT_TYPE_EXTENT_LIST_TREE, @@ -254,9 +261,8 @@ char* get_o_subtype_string(uint32_t o_subtype) { OBJECT_TYPE_OMAP_SNAPSHOT, OBJECT_TYPE_FUSION_MIDDLE_TREE, OBJECT_TYPE_GBITMAP_TREE, - + OBJECT_TYPE_FEXT_TREE, }; - char* flag_strings[] = { "Space manager free-space queue", "Extents-list tree", @@ -266,6 +272,7 @@ char* get_o_subtype_string(uint32_t o_subtype) { "Object map snapshots tree", "Fusion inter-drive block-mapping tree", "B-tree of general-purpose bitmaps", + "B-tree of file extents", }; // Allocate sufficient memory to store the longest flag string. diff --git a/src/apfs/struct/object.h b/src/apfs/struct/object.h index 1a3fb31..85f6585 100644 --- a/src/apfs/struct/object.h +++ b/src/apfs/struct/object.h @@ -75,11 +75,18 @@ typedef struct { #define OBJECT_TYPE_GBITMAP_TREE 0x0000001a #define OBJECT_TYPE_GBITMAP_BLOCK 0x0000001b +#define OBJECT_TYPE_ER_RECOVERY_BLOCK 0x0000001c +#define OBJECT_TYPE_SNAP_META_EXT 0x0000001d +#define OBJECT_TYPE_INTEGRITY_META 0x0000001e +#define OBJECT_TYPE_FEXT_TREE 0x0000001f +#define OBJECT_TYPE_RESERVED_20 0x00000020 + #define OBJECT_TYPE_INVALID 0x00000000 #define OBJECT_TYPE_TEST 0x000000ff #define OBJECT_TYPE_CONTAINER_KEYBAG 'keys' #define OBJECT_TYPE_VOLUME_KEYBAG 'recs' +#define OBJECT_TYPE_MEDIA_KEYBAG 'mkey' /** Object Type Flags **/ From 2bd79f79e1267731ae0055564efb3eb2e1a6d9c5 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 00:08:17 +0000 Subject: [PATCH 05/20] =?UTF-8?q?Update=20=C2=A75=20Container:=20`nx=5Fsup?= =?UTF-8?q?erblock=5Ft`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/string/nx.c | 45 +++++++++++++++++++++++++++++++++++++++++--- src/apfs/struct/nx.h | 4 ++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/notes.md b/notes.md index 093fbaf..6cb3fc8 100644 --- a/notes.md +++ b/notes.md @@ -13,8 +13,8 @@ ## `nx_superblock_t` - - [ ] nx_newest_mounted_version - - [ ] nx_mkb_locker + - [x] nx_newest_mounted_version + - [x] nx_mkb_locker # §6 Object Maps diff --git a/src/apfs/string/nx.c b/src/apfs/string/nx.c index a5610ef..f21ac43 100644 --- a/src/apfs/string/nx.c +++ b/src/apfs/string/nx.c @@ -304,10 +304,35 @@ char* get_nx_flags_string(nx_superblock_t* nxsb) { void print_nx_superblock(nx_superblock_t* nxsb) { print_obj_phys(nxsb); // `nxsb` is equivalent to `&(nxsb->nx_o)`. - printf("Keybag location: starts at %#llx, spans %#llx blocks\n", nxsb->nx_keylocker.pr_start_paddr, nxsb->nx_keylocker.pr_block_count); + printf("Keybag location: "); + if (nxsb->nx_keylocker.pr_block_count == 0) { + printf("none (spans 0 blocks)\n"); + } else { + printf( + "first block %#llx, spans %llu (%#llx) blocks (last block %#llx)\n", + nxsb->nx_keylocker.pr_start_paddr, + nxsb->nx_keylocker.pr_block_count, + nxsb->nx_keylocker.pr_block_count, + nxsb->nx_keylocker.pr_start_paddr + nxsb->nx_keylocker.pr_block_count - 1 + ); + } + + printf("Media keybag location: "); + if (nxsb->nx_mkb_locker.pr_block_count == 0) { + printf("none (spans 0 blocks)\n"); + } else { + printf( + "first block %#llx, spans %llu (%#llx) blocks (last block %#llx)\n", + nxsb->nx_mkb_locker.pr_start_paddr, + nxsb->nx_mkb_locker.pr_block_count, + nxsb->nx_mkb_locker.pr_block_count, + nxsb->nx_mkb_locker.pr_start_paddr + nxsb->nx_mkb_locker.pr_block_count - 1 + ); + } + char magic_string[] = { - (char)nxsb->nx_magic, + (char)(nxsb->nx_magic), (char)(nxsb->nx_magic >> 8), (char)(nxsb->nx_magic >> 16), (char)(nxsb->nx_magic >> 24), @@ -315,8 +340,22 @@ void print_nx_superblock(nx_superblock_t* nxsb) { }; printf("Magic string: %s\n", magic_string); + printf( + "Latest version of Apple APFS software that mounted this container: " + "%llu.%llu.%llu.%llu.%llu\n", + + nxsb->nx_newest_mounted_version >> 40, + (nxsb->nx_newest_mounted_version >> 30) & ~(~0ULL << 10), + (nxsb->nx_newest_mounted_version >> 20) & ~(~0ULL << 10), + (nxsb->nx_newest_mounted_version >> 10) & ~(~0ULL << 10), + (nxsb->nx_newest_mounted_version) & ~(~0ULL << 10) + ); + printf("Block size: %u bytes\n", nxsb->nx_block_size); - printf("Block count: %llu\n", nxsb->nx_block_count); + printf("Block count: %llu (last block %#llx)\n", + nxsb->nx_block_count, + nxsb->nx_block_count - 1 + ); char* features_string = get_nx_features_string(nxsb); printf("Supported features:\n%s", features_string); diff --git a/src/apfs/struct/nx.h b/src/apfs/struct/nx.h index b27f993..aba95e1 100644 --- a/src/apfs/struct/nx.h +++ b/src/apfs/struct/nx.h @@ -78,6 +78,10 @@ typedef struct { oid_t nx_fusion_mt_oid; oid_t nx_fusion_wbc_oid; prange_t nx_fusion_wbc; + + uint64_t nx_newest_mounted_version; + + prange_t nx_mkb_locker; } nx_superblock_t; /** Container Flags **/ From f3e44cec6fea75bf76b59d63ee4de556116d36f1 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 00:12:17 +0000 Subject: [PATCH 06/20] =?UTF-8?q?Update=20=C2=A76=20Object=20Maps:=20Objec?= =?UTF-8?q?t=20Map=20Flags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 2 +- src/apfs/struct/omap.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/notes.md b/notes.md index 6cb3fc8..a745134 100644 --- a/notes.md +++ b/notes.md @@ -20,7 +20,7 @@ ## Object Map Flags - - [ ] OMAP_VALID_FLAGS + - [x] OMAP_VALID_FLAGS # §7 Volumes diff --git a/src/apfs/struct/omap.h b/src/apfs/struct/omap.h index 5c69c33..df9bde2 100644 --- a/src/apfs/struct/omap.h +++ b/src/apfs/struct/omap.h @@ -69,6 +69,8 @@ typedef struct { #define OMAP_KEYROLLING 0x00000008 #define OMAP_CRYPTO_GENERATION 0x00000010 +#define OMAP_VALID_FLAGS 0x0000001f + /** Object Map Constants **/ #define OMAP_MAX_SNAP_COUNT UINT32_MAX From ed9df071a964ea92f3515e965893319d7fb0b6b9 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 00:16:08 +0000 Subject: [PATCH 07/20] =?UTF-8?q?Update=20=C2=A77=20Volumes:=20Optional=20?= =?UTF-8?q?Volume=20Feature=20Flags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/string/fs.c | 6 +++++- src/apfs/struct/fs.h | 20 ++++++++++++-------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/notes.md b/notes.md index a745134..7367109 100644 --- a/notes.md +++ b/notes.md @@ -55,8 +55,8 @@ ## Optional Volume Feature Flags - - [ ] APFS_FEATURE_STRICTATIME - - [ ] APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE + - [x] APFS_FEATURE_STRICTATIME + - [x] APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE ## Incompatible Volume Feature Flags diff --git a/src/apfs/string/fs.c b/src/apfs/string/fs.c index 62ab3de..4081687 100644 --- a/src/apfs/string/fs.c +++ b/src/apfs/string/fs.c @@ -28,18 +28,22 @@ char* get_apfs_features_string(apfs_superblock_t* apsb) { char* default_string = "- No volume feature flags are set.\n"; size_t default_string_len = strlen(default_string); - const int NUM_FLAGS = 3; + const int NUM_FLAGS = 5; uint64_t flag_constants[] = { APFS_FEATURE_DEFRAG_PRERELEASE, APFS_FEATURE_HARDLINK_MAP_RECORDS, APFS_FEATURE_DEFRAG, + APFS_FEATURE_STRICTATIME, + APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE, }; char* flag_strings[] = { "Reserved --- To avoid data corruption, this flag must not be set; this flag enabled a prerelease version of the defragmentation system in macOS 10.13 versions. Itʼs ignored by macOS 10.13.6 and later.", "This volume has hardlink map records.", "Defragmentation is supported.", + "File access times are updated every time a file is read.", + "This volume supports mounting a system and data volume as a single user-visible volume.", }; // Allocate sufficient memory for the result string diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index 3dbe85f..e3c2797 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -130,14 +130,18 @@ typedef struct { /** Optional Volume Feature Flags **/ -#define APFS_FEATURE_DEFRAG_PRERELEASE 0x00000001LL -#define APFS_FEATURE_HARDLINK_MAP_RECORDS 0x00000002LL -#define APFS_FEATURE_DEFRAG 0x00000004LL - -#define APFS_SUPPORTED_FEATURES_MASK ( \ - APFS_FEATURE_DEFRAG \ - | APFS_FEATURE_DEFRAG_PRERELEASE \ - | APFS_FEATURE_HARDLINK_MAP_RECORDS \ +#define APFS_FEATURE_DEFRAG_PRERELEASE 0x00000001LL +#define APFS_FEATURE_HARDLINK_MAP_RECORDS 0x00000002LL +#define APFS_FEATURE_DEFRAG 0x00000004LL +#define APFS_FEATURE_STRICTATIME 0x00000008LL +#define APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE 0x00000010LL + +#define APFS_SUPPORTED_FEATURES_MASK ( \ + APFS_FEATURE_DEFRAG \ + | APFS_FEATURE_DEFRAG_PRERELEASE \ + | APFS_FEATURE_HARDLINK_MAP_RECORDS \ + | APFS_FEATURE_STRICTATIME \ + | APFS_FEATURE_VOLGRP_SYSTEM_INO_SPACE \ ) /** Read-Only Comaptible Volume Feature Flags **/ From 1e4fb30c08a643af158795ac107306a420b79e4a Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 00:16:59 +0000 Subject: [PATCH 08/20] =?UTF-8?q?Update=20=C2=A77=20Volumes:=20Incompatibl?= =?UTF-8?q?e=20Volume=20Feature=20Flags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/string/fs.c | 8 +++++++- src/apfs/struct/fs.h | 14 ++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/notes.md b/notes.md index 7367109..5a988ae 100644 --- a/notes.md +++ b/notes.md @@ -60,8 +60,8 @@ ## Incompatible Volume Feature Flags - - [ ] APFS_INCOMPAT_INCOMPLETE_RESTORE - - [ ] APFS_INCOMPAT_SEALED_VOLUME + - [x] APFS_INCOMPAT_INCOMPLETE_RESTORE + - [x] APFS_INCOMPAT_SEALED_VOLUME # §8 File-System Objects diff --git a/src/apfs/string/fs.c b/src/apfs/string/fs.c index 4081687..802dea0 100644 --- a/src/apfs/string/fs.c +++ b/src/apfs/string/fs.c @@ -172,13 +172,16 @@ char* get_apfs_incompatible_features_string(apfs_superblock_t* apsb) { char* default_string = "- No backward-incompatible volume feature flags are set.\n"; size_t default_string_len = strlen(default_string); - const int NUM_FLAGS = 4; + const int NUM_FLAGS = 7; uint64_t flag_constants[] = { APFS_INCOMPAT_CASE_INSENSITIVE, APFS_INCOMPAT_DATALESS_SNAPS, APFS_INCOMPAT_ENC_ROLLED, APFS_INCOMPAT_NORMALIZATION_INSENSITIVE, + APFS_INCOMPAT_INCOMPLETE_RESTORE, + APFS_INCOMPAT_SEALED_VOLUME, + APFS_INCOMPAT_RESERVED_40, }; char* flag_strings[] = { @@ -186,6 +189,9 @@ char* get_apfs_incompatible_features_string(apfs_superblock_t* apsb) { "At least one snapshot with no data exists for this volume.", "This volume's encryption has changed keys at least once.", "Filenames on this volume are normalization insensitive.", + "This volume is being restored, or a restore operation to this volume was uncleanly aborted.", + "This volume is sealed (cannot be modified).", + "Reserved flag (0x40).", }; // Allocate sufficient memory for the result string diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index e3c2797..786f673 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -150,16 +150,22 @@ typedef struct { /** Incompatible Volume Feature Flags **/ -#define APFS_INCOMPAT_CASE_INSENSITIVE 0x000000001LL -#define APFS_INCOMPAT_DATALESS_SNAPS 0x000000002LL -#define APFS_INCOMPAT_ENC_ROLLED 0x000000004LL -#define APFS_INCOMPAT_NORMALIZATION_INSENSITIVE 0x000000008LL +#define APFS_INCOMPAT_CASE_INSENSITIVE 0x00000001LL +#define APFS_INCOMPAT_DATALESS_SNAPS 0x00000002LL +#define APFS_INCOMPAT_ENC_ROLLED 0x00000004LL +#define APFS_INCOMPAT_NORMALIZATION_INSENSITIVE 0x00000008LL +#define APFS_INCOMPAT_INCOMPLETE_RESTORE 0x00000010LL +#define APFS_INCOMPAT_SEALED_VOLUME 0x00000020LL +#define APFS_INCOMPAT_RESERVED_40 0x00000040LL #define APFS_SUPPORTED_INCOMPAT_MASK ( \ APFS_INCOMPAT_CASE_INSENSITIVE \ | APFS_INCOMPAT_DATALESS_SNAPS \ | APFS_INCOMPAT_ENC_ROLLED \ | APFS_INCOMPAT_NORMALIZATION_INSENSITIVE \ + | APFS_INCOMPAT_INCOMPLETE_RESTORE \ + | APFS_INCOMPAT_SEALED_VOLUME \ + | APFS_INCOMPAT_RESERVED_40 \ ) #endif // APFS_STRUCT_FS_H From e150f664199102513cfda235633900afd9c1fd7b Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 12:58:10 +0000 Subject: [PATCH 09/20] =?UTF-8?q?Update=20=C2=A77=20Volumes:=20Volume=20Fl?= =?UTF-8?q?ags?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/string/fs.c | 6 +++++- src/apfs/struct/fs.h | 5 ++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/notes.md b/notes.md index 5a988ae..0fccd13 100644 --- a/notes.md +++ b/notes.md @@ -38,8 +38,8 @@ ## Volume Flags - - [ ] APFS_FS_RESERVED_80 - - [ ] APFS_FS_RESERVED_100 + - [x] APFS_FS_RESERVED_80 + - [x] APFS_FS_RESERVED_100 ## Volume Roles diff --git a/src/apfs/string/fs.c b/src/apfs/string/fs.c index 802dea0..72e3811 100644 --- a/src/apfs/string/fs.c +++ b/src/apfs/string/fs.c @@ -253,7 +253,7 @@ char* get_apfs_fs_flags_string(apfs_superblock_t* apsb) { char* default_string = "- No flags are set.\n"; size_t default_string_len = strlen(default_string); - const int NUM_FLAGS = 7; + const int NUM_FLAGS = 9; uint64_t flag_constants[] = { APFS_FS_UNENCRYPTED, @@ -263,6 +263,8 @@ char* get_apfs_fs_flags_string(apfs_superblock_t* apsb) { APFS_FS_SPILLEDOVER, APFS_FS_RUN_SPILLOVER_CLEANER, APFS_FS_ALWAYS_CHECK_EXTENTREF, + APFS_FS_RESERVED_80, + APFS_FS_RESERVED_100, }; char* flag_strings[] = { @@ -273,6 +275,8 @@ char* get_apfs_fs_flags_string(apfs_superblock_t* apsb) { "Volume has run out of allocated space on SSD, so has spilled over to other drives.", "Volume has spilled over and spillover cleaner must be run.", "When deciding whether to overwrite a file extent, always consult the extent reference tree.", + "Reserved flag (0x80).", + "Reserved flag (0x100).", }; // Allocate sufficient memory for the result string diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index 786f673..8a240a5 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -95,6 +95,8 @@ typedef struct { #define APFS_FS_SPILLEDOVER 0x00000010LL #define APFS_FS_RUN_SPILLOVER_CLEANER 0x00000020LL #define APFS_FS_ALWAYS_CHECK_EXTENTREF 0x00000040LL +#define APFS_FS_RESERVED_80 0x00000080LL +#define APFS_FS_RESERVED_100 0x00000100LL #define APFS_FS_FLAGS_VALID_MASK ( \ APFS_FS_UNENCRYPTED \ @@ -104,11 +106,12 @@ typedef struct { | APFS_FS_SPILLEDOVER \ | APFS_FS_RUN_SPILLOVER_CLEANER \ | APFS_FS_ALWAYS_CHECK_EXTENTREF \ + | APFS_FS_RESERVED_80 \ + | APFS_FS_RESERVED_100 \ ) #define APFS_FS_CRYPTOFLAGS ( \ APFS_FS_UNENCRYPTED \ - | APFS_FS_RESERVED_2 \ | APFS_FS_ONEKEY \ ) From 34cdd858547b203408bf871928ea0879148548ef Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 13:53:25 +0000 Subject: [PATCH 10/20] =?UTF-8?q?Update=20=C2=A77=20Volumes:=20Volume=20Ro?= =?UTF-8?q?les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 18 ++++---- src/apfs/string/fs.c | 106 +++++++++++++++++++++++-------------------- src/apfs/struct/fs.h | 19 ++++++-- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/notes.md b/notes.md index 0fccd13..1124b27 100644 --- a/notes.md +++ b/notes.md @@ -43,15 +43,15 @@ ## Volume Roles - - [ ] APFS_VOL_ROLE_UPDATE - - [ ] APFS_VOL_ROLE_XART - - [ ] APFS_VOL_ROLE_HARDWARE - - [ ] APFS_VOL_ROLE_BACKUP - - [ ] APFS_VOL_ROLE_RESERVED_7 - - [ ] APFS_VOL_ROLE_RESERVED_8 - - [ ] APFS_VOL_ROLE_ENTERPRISE - - [ ] APFS_VOL_ROLE_RESERVED_10 - - [ ] APFS_VOL_ROLE_PRELOGIN + - [x] APFS_VOL_ROLE_UPDATE + - [x] APFS_VOL_ROLE_XART + - [x] APFS_VOL_ROLE_HARDWARE + - [x] APFS_VOL_ROLE_BACKUP + - [x] APFS_VOL_ROLE_RESERVED_7 + - [x] APFS_VOL_ROLE_RESERVED_8 + - [x] APFS_VOL_ROLE_ENTERPRISE + - [x] APFS_VOL_ROLE_RESERVED_10 + - [x] APFS_VOL_ROLE_PRELOGIN ## Optional Volume Feature Flags diff --git a/src/apfs/string/fs.c b/src/apfs/string/fs.c index 72e3811..7b18db9 100644 --- a/src/apfs/string/fs.c +++ b/src/apfs/string/fs.c @@ -324,8 +324,8 @@ char* get_apfs_fs_flags_string(apfs_superblock_t* apsb) { } /** - * Get a human-readable string that lists the role flags that are - * set on a given APFS volume superblock. + * Get a human-readable string describing the role of a given APFS volume + * superblock. * * apsb: A pointer to the APFS volume superblock in question. * @@ -335,13 +335,11 @@ char* get_apfs_fs_flags_string(apfs_superblock_t* apsb) { */ char* get_apfs_role_string(apfs_superblock_t* apsb) { // String to use if no flags are set - char* default_string = "- This volume has no defined roles\n"; - size_t default_string_len = strlen(default_string); + char* default_string = "(unknown role) (role field value %#llx)"; - const int NUM_FLAGS = 9; - - // `APFS_ROLE_NONE` (0x0) is intentionally ommitted from this array. - uint64_t flag_constants[] = { + const int NUM_ROLES = 18; + uint64_t role_constants[] = { + APFS_VOL_ROLE_NONE, APFS_VOL_ROLE_SYSTEM, APFS_VOL_ROLE_USER, APFS_VOL_ROLE_RECOVERY, @@ -350,29 +348,44 @@ char* get_apfs_role_string(apfs_superblock_t* apsb) { APFS_VOL_ROLE_INSTALLER, APFS_VOL_ROLE_DATA, APFS_VOL_ROLE_BASEBAND, - APFS_VOL_ROLE_RESERVED_200, + APFS_VOL_ROLE_UPDATE, + APFS_VOL_ROLE_XART, + APFS_VOL_ROLE_HARDWARE, + APFS_VOL_ROLE_BACKUP, + APFS_VOL_ROLE_RESERVED_7, + APFS_VOL_ROLE_RESERVED_8, + APFS_VOL_ROLE_ENTERPRISE, + APFS_VOL_ROLE_RESERVED_10, + APFS_VOL_ROLE_PRELOGIN, }; - - char* flag_strings[] = { - "Root volume (contains a root directory for the system)", - "Home volume (contains users' home directories)", - "Recovery volume (contains a recovery system)", - "Swap volume (used as swap space for virtual memory)", - "Preboot volume (contains files needed to boot from an encrypted volumes)", - "Installer volume (used by the OS installer)", - "Data volume (contains mutable data)", - "Baseband volume (sed by the radio firmware)", - "Reserved flag (0x200)", + char* role_strings[] = { + "(no role)", + "System (contains a root directory for the system)", + "User (contains users' home directories)", + "Recovery (contains a recovery system)", + "Virtual memory (used as swap space for virtual memory)", + "Preboot (contains files needed to boot from an encrypted volumes)", + "Installer (used by the OS installer)", + "Data (contains mutable data)", + "Baseband (used by the radio firmware)", + "Update (used by the software update mechanism)", + "xART (used to manage OS access to secure user data", + "Hardware (used for firmware data)", + "Backup (used by Time Machine to store backups)", + "Reserved role 7 (Sidecar?) (role field value 0x1c0)", + "Reserved role 8 (role field value 0x200)", + "Enterprise (used to store enterprise-managed data)", + "Reserved role 10 (role field value 0x280)", + "Pre-login (used to store system data used before login)", }; // Allocate sufficient memory for the result string - size_t max_mem_required = 0; - for (int i = 0; i < NUM_FLAGS; i++) { - max_mem_required += strlen(flag_strings[i]) + 3; - // `+ 3` accounts for prepending "- " and appending "\n" to each string - } - if (max_mem_required < default_string_len) { - max_mem_required = default_string_len; + size_t max_mem_required = strlen(default_string) + 1; // `+1` accounts for format specifier "%#llx" becoming up to 6 characters + for (int i = 0; i < NUM_ROLES; i++) { + size_t role_string_length = strlen(role_strings[i]); + if (max_mem_required < role_string_length) { + max_mem_required = role_string_length; + } } max_mem_required++; // Make room for terminating NULL byte @@ -382,28 +395,22 @@ char* get_apfs_role_string(apfs_superblock_t* apsb) { exit(-1); } - char* cursor = result_string; + // Make `result_string` an empty string so that we can easily test the + // case that no role matches. + *result_string = '\0'; - // Go through possible flags, adding corresponding string to result if - // that flag is set. - for (int i = 0; i < NUM_FLAGS; i++) { - if (apsb->apfs_role & flag_constants[i]) { - *cursor++ = '-'; - *cursor++ = ' '; - memcpy(cursor, flag_strings[i], strlen(flag_strings[i])); - cursor += strlen(flag_strings[i]); - *cursor++ = '\n'; + for (int i = 0; i < NUM_ROLES; i++) { + if (apsb->apfs_role == role_constants[i]) { + memcpy(result_string, role_strings[i], strlen(role_strings[i]) + 1); + break; } } - if (cursor == result_string) { - // No strings were added, so it must be that no flags are set. - memcpy(cursor, default_string, default_string_len); - cursor += default_string_len; + // If no role matches, use the default string. + if (strlen(result_string) == 0) { + snprintf(result_string, max_mem_required, default_string, apsb->apfs_role); } - *cursor = '\0'; - // Free up excess allocated memory. result_string = realloc(result_string, strlen(result_string) + 1); return result_string; @@ -420,7 +427,7 @@ void print_apfs_superblock(apfs_superblock_t* apsb) { printf("\n"); char magic_string[] = { - (char)apsb->apfs_magic, + (char)(apsb->apfs_magic), (char)(apsb->apfs_magic >> 8), (char)(apsb->apfs_magic >> 16), (char)(apsb->apfs_magic >> 24), @@ -431,9 +438,14 @@ void print_apfs_superblock(apfs_superblock_t* apsb) { printf("\n"); printf("Volume name: ### %s ###\n", apsb->apfs_volname); + + char* tmp_string = get_apfs_role_string(apsb); + printf("Role: %s", tmp_string); + free(tmp_string); + printf("\n"); - char* tmp_string = get_apfs_fs_flags_string(apsb); + tmp_string = get_apfs_fs_flags_string(apsb); printf("Flags:\n%s", tmp_string); free(tmp_string); @@ -448,10 +460,6 @@ void print_apfs_superblock(apfs_superblock_t* apsb) { tmp_string = get_apfs_incompatible_features_string(apsb); printf("Backward-incompatible features:\n%s", tmp_string); free(tmp_string); - - tmp_string = get_apfs_role_string(apsb); - printf("Roles:\n%s", tmp_string); - free(tmp_string); printf("\n"); diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index 8a240a5..47be5ad 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -123,13 +123,24 @@ typedef struct { #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 -#define APFS_VOL_ROLE_RESERVED_200 0x0200 +#define APFS_VOLUME_ENUM_SHIFT 6 + +#define APFS_VOL_ROLE_DATA ( 1 << APFS_VOLUME_ENUM_SHIFT) // = 0x0040 --- formerly defined explicitly as `0x0040` +#define APFS_VOL_ROLE_BASEBAND ( 2 << APFS_VOLUME_ENUM_SHIFT) // = 0x0080 --- formerly defined explicitly as `0x0080` + +// Roles supported since revision 2020-05-15 --- macOS 10.15+, iOS 13+ +#define APFS_VOL_ROLE_UPDATE ( 3 << APFS_VOLUME_ENUM_SHIFT) // = 0x00c0 +#define APFS_VOL_ROLE_XART ( 4 << APFS_VOLUME_ENUM_SHIFT) // = 0x0100 +#define APFS_VOL_ROLE_HARDWARE ( 5 << APFS_VOLUME_ENUM_SHIFT) // = 0x0140 +#define APFS_VOL_ROLE_BACKUP ( 6 << APFS_VOLUME_ENUM_SHIFT) // = 0x0180 +#define APFS_VOL_ROLE_RESERVED_7 ( 7 << APFS_VOLUME_ENUM_SHIFT) // = 0x01c0 --- spec also uses the name `APFS_VOL_ROLE_SIDECAR`, but that could be an error +#define APFS_VOL_ROLE_RESERVED_8 ( 8 << APFS_VOLUME_ENUM_SHIFT) // = 0x0200 --- formerly named `APFS_VOL_ROLE_RESERVED_200` +#define APFS_VOL_ROLE_ENTERPRISE ( 9 << APFS_VOLUME_ENUM_SHIFT) // = 0x0240 +#define APFS_VOL_ROLE_RESERVED_10 (10 << APFS_VOLUME_ENUM_SHIFT) // = 0x0280 +#define APFS_VOL_ROLE_PRELOGIN (11 << APFS_VOLUME_ENUM_SHIFT) // = 0x02c0 /** Optional Volume Feature Flags **/ From 124d9e5b5ecd275e9b06ab6969db5d90e9d98a48 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 14:19:43 +0000 Subject: [PATCH 11/20] =?UTF-8?q?Update=20=C2=A77=20Volumes:=20`apfs=5Fsup?= =?UTF-8?q?erblock=5Ft`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 18 +++++++++--------- src/apfs/string/fs.c | 7 +++++++ src/apfs/struct/fs.h | 22 +++++++++++++++++++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/notes.md b/notes.md index 1124b27..ed58173 100644 --- a/notes.md +++ b/notes.md @@ -26,15 +26,15 @@ ## `apfs_superblock_t` - - [ ] apfs_cloneinfo_id_epoch - - [ ] apfs_cloneinfo_xid - - [ ] apfs_snap_meta_ext_oid - - [ ] apfs_volume_group_id - - [ ] apfs_integrity_meta_oid - - [ ] apfs_fext_tree_oid - - [ ] apfs_fext_tree_type - - [ ] reserved_type - - [ ] reserved_oid + - [x] apfs_cloneinfo_id_epoch + - [x] apfs_cloneinfo_xid + - [x] apfs_snap_meta_ext_oid + - [x] apfs_volume_group_id + - [x] apfs_integrity_meta_oid + - [x] apfs_fext_tree_oid + - [x] apfs_fext_tree_type + - [x] reserved_type + - [x] reserved_oid ## Volume Flags diff --git a/src/apfs/string/fs.c b/src/apfs/string/fs.c index 7b18db9..2d9165a 100644 --- a/src/apfs/string/fs.c +++ b/src/apfs/string/fs.c @@ -554,5 +554,12 @@ void print_apfs_superblock(apfs_superblock_t* apsb) { * - apfs_modified_by * - apfs_root_to_xid * - apfs_er_state_oid + * - apfs_cloneinfo_id_epoch + * - apfs_cloneinfo_xid + * - apfs_snap_meta_ext_oid + * - apfs_volume_group_id + * - apfs_integrity_meta_oid + * - apfs_fext_tree_oid + * - apfs_fext_tree_type */ } diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index 47be5ad..c67ef5a 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -80,10 +80,30 @@ typedef struct { uint32_t apfs_next_doc_id; uint16_t apfs_role; - uint16_t apfs_reserved; + uint16_t reserved; xid_t apfs_root_to_xid; oid_t apfs_er_state_oid; + +// Fields introduced in revision 2020-05-15 + + // Fields supported on macOS 10.13.3+ + uint64_t apfs_cloneinfo_id_epoch; + uint64_t apfs_cloneinfo_xid; + + // Fields supported on macOS 10.15+ + oid_t apfs_snap_meta_ext_oid; + uuid_t apfs_volume_group_id; + +// Fields introduced in revision 2020-06-22 + + // Fields supported on macOS 11+ + oid_t apfs_integrity_meta_oid; + oid_t apfs_fext_tree_oid; + uint32_t apfs_fext_tree_type; + + uint32_t reserved_type; + oid_t reserved_oid; } apfs_superblock_t; /** Volume Flags **/ From 9cb74a23469fc3e4bbc360c7d48ee5aa5e0a526f Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 14:53:01 +0000 Subject: [PATCH 12/20] =?UTF-8?q?Update=20=C2=A78/9=20File-System=20Object?= =?UTF-8?q?s/Constants?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 20 +++++++++--------- src/apfs/string/j.c | 40 ++++++++++++++++++++++++++++------- src/apfs/struct/const.h | 47 +++++++++++++++++++++++++++++++---------- src/apfs/struct/j.h | 12 ++++++----- 4 files changed, 85 insertions(+), 34 deletions(-) diff --git a/notes.md b/notes.md index ed58173..66c3f7b 100644 --- a/notes.md +++ b/notes.md @@ -81,22 +81,22 @@ ## `j_inode_flags` - - [ ] INODE_FAST_PROMOTE - - [ ] INODE_HAS_UNCOMPRESSED_SIZE - - [ ] INODE_IS_PURGEABLE - - [ ] INODE_WANTS_TO_BE_PURGEABLE - - [ ] INODE_IS_SYNC_ROOT - - [ ] INODE_SNAPSHOT_COW_EXEMPTION + - [x] INODE_FAST_PROMOTE + - [x] INODE_HAS_UNCOMPRESSED_SIZE + - [x] INODE_IS_PURGEABLE + - [x] INODE_WANTS_TO_BE_PURGEABLE + - [x] INODE_IS_SYNC_ROOT + - [x] INODE_SNAPSHOT_COW_EXEMPTION ## Inode Numbers - - [ ] PURGEABLE_DIR_INO_NUM - - [ ] UNIFIED_ID_SPACE_MARK + - [x] PURGEABLE_DIR_INO_NUM + - [x] UNIFIED_ID_SPACE_MARK ## Extended Attributes Constants - - [ ] FIRMLINK_EA_NAME - - [ ] APFS_COW_EXEMPT_COUNT_NAME + - [x] FIRMLINK_EA_NAME + - [x] APFS_COW_EXEMPT_COUNT_NAME # §11 Extended Fields diff --git a/src/apfs/string/j.c b/src/apfs/string/j.c index 083f21b..b3a1037 100644 --- a/src/apfs/string/j.c +++ b/src/apfs/string/j.c @@ -95,7 +95,7 @@ char* get_j_inode_internal_flags_string(uint64_t internal_flags) { char* default_string = "- No internal flags are set.\n"; size_t default_string_len = strlen(default_string); - const int NUM_FLAGS = 17; + const int NUM_FLAGS = 23; uint64_t flag_constants[] = { INODE_IS_APFS_PRIVATE, @@ -115,6 +115,12 @@ char* get_j_inode_internal_flags_string(uint64_t internal_flags) { INODE_HAS_RSRC_FORK, INODE_NO_RSRC_FORK, INODE_ALLOCATION_SPILLEDOVER, + INODE_FAST_PROMOTE, + INODE_HAS_UNCOMPRESSED_SIZE, + INODE_IS_PURGEABLE, + INODE_WANTS_TO_BE_PURGEABLE, + INODE_IS_SYNC_ROOT, + INODE_SNAPSHOT_COW_EXEMPTION, }; char* flag_strings[] = { @@ -135,6 +141,12 @@ char* get_j_inode_internal_flags_string(uint64_t internal_flags) { "Has a resource fork", "Has no resource fork", "Fusion drive: file content spilled over from preferred storage tier/device", + "Scheduled for promotion from slow storage to fast storage", + "Uncompressed size is stored in the inode", + "Will be deleted at the next purge", + "Should become purgeable when its link count drops to 1", + "Is the root of a sync hierarchy for `fileproviderd`", + "Exempt from copy-on-write behavior if the data is part of a snapshot", }; // Allocate sufficient memory for the result string @@ -261,6 +273,21 @@ void print_j_inode_val(j_inode_val_t* val, bool has_xfields) { printf("Private ID: 0x%llx\n", val->private_id); printf("\n"); + char* tmp_string = NULL; + if (val->internal_flags & INODE_HAS_UNCOMPRESSED_SIZE) { + if (asprintf(tmp_string, "%llu bytes", val->uncompressed_size) < 0) { + fprintf(stderr, "ABORT: %s:%d: call to asprintf() couldn't allocate sufficient memory", __func__, __LINE__); + exit(-1); + } + } else { + if (asprintf(tmp_string, "(unknown)") < 0) { + fprintf(stderr, "ABORT: %s:%d: call to asprintf() couldn't allocate sufficient memory", __func__, __LINE__); + exit(-1); + } + } + printf("Uncompressed size: %s\n", tmp_string); + free(tmp_string); + time_t timestamp = val->create_time / 1000000000; printf("Creation time: %s", ctime(×tamp)); timestamp = val->mod_time / 1000000000; @@ -279,7 +306,7 @@ void print_j_inode_val(j_inode_val_t* val, bool has_xfields) { printf("Mode: %s\n", j_inode_mode_to_string(val->mode)); printf("\n"); - char* tmp_string = get_j_inode_internal_flags_string(val->internal_flags); + tmp_string = get_j_inode_internal_flags_string(val->internal_flags); printf("Internal flags:\n%s", tmp_string); printf("\n"); free(tmp_string); @@ -289,12 +316,9 @@ void print_j_inode_val(j_inode_val_t* val, bool has_xfields) { printf("\n"); free(tmp_string); - printf("No. extended fields: "); - if (!has_xfields) { - printf("0\n"); - return; - } - printf("%u\n", ((xf_blob_t*)(val->xfields))->xf_num_exts); + printf("Number of extended fields: %u\n", + has_xfields ? ((xf_blob_t*)(val->xfields))->xf_num_exts : 0 + ); // TODO: Print actual details of extended fields/attributes } diff --git a/src/apfs/struct/const.h b/src/apfs/struct/const.h index b43ea57..8785787 100644 --- a/src/apfs/struct/const.h +++ b/src/apfs/struct/const.h @@ -25,8 +25,9 @@ typedef enum { APFS_TYPE_DIR_STATS = 10, APFS_TYPE_SNAP_NAME = 11, APFS_TYPE_SIBLING_MAP = 12, + APFS_TYPE_FILE_INFO = 13, - APFS_TYPE_MAX_VALID = 12, + APFS_TYPE_MAX_VALID = 13, APFS_TYPE_MAX = 15, APFS_TYPE_INVALID = 15, @@ -64,17 +65,27 @@ typedef enum { INODE_HAS_RSRC_FORK = 0x00004000, INODE_NO_RSRC_FORK = 0x00008000, INODE_ALLOCATION_SPILLEDOVER = 0x00010000, - - INODE_INHERITED_INTERNAL_FLAGS = INODE_MAINTAIN_DIR_STATS, + INODE_FAST_PROMOTE = 0x00020000, + INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000, + INODE_IS_PURGEABLE = 0x00080000, + INODE_WANTS_TO_BE_PURGEABLE = 0x00100000, + INODE_IS_SYNC_ROOT = 0x00200000, + INODE_SNAPSHOT_COW_EXEMPTION = 0x00400000, + + INODE_INHERITED_INTERNAL_FLAGS = ( \ + INODE_MAINTAIN_DIR_STATS \ + | INODE_SNAPSHOT_COW_EXEMPTION \ + ), INODE_CLONED_INTERNAL_FLAGS = ( \ INODE_HAS_RSRC_FORK \ | INODE_NO_RSRC_FORK \ | INODE_HAS_FINDER_INFO \ + | INODE_SNAPSHOT_COW_EXEMPTION \ ), } j_inode_flags; -#define APFS_VALID_INTERNAL_INODE_FLAGS ( \ +#define APFS_VALID_INTERNAL_INODE_FLAGS ( \ INODE_IS_APFS_PRIVATE \ | INODE_MAINTAIN_DIR_STATS \ | INODE_DIR_STATS_ORIGIN \ @@ -91,9 +102,18 @@ typedef enum { | INODE_HAS_RSRC_FORK \ | INODE_NO_RSRC_FORK \ | INODE_ALLOCATION_SPILLEDOVER \ + | INODE_FAST_PROMOTE \ + | INODE_HAS_UNCOMPRESSED_SIZE \ + | INODE_IS_PURGEABLE \ + | INODE_WANTS_TO_BE_PURGEABLE \ + | INODE_IS_SYNC_ROOT \ + | INODE_SNAPSHOT_COW_EXEMPTION \ ) -#define APFS_INODE_PINNED_MASK (INODE_PINNED_TO_MAIN | INODE_PINNED_TO_TIER2) +#define APFS_INODE_PINNED_MASK ( \ + INODE_PINNED_TO_MAIN \ + | INODE_PINNED_TO_TIER2 \ +) /** `j_xattr_flags` **/ @@ -113,18 +133,23 @@ typedef enum { /** Inode Numbers **/ -#define INVALID_INO_NUM 0 -#define ROOT_DIR_PARENT 1 -#define ROOT_DIR_INO_NUM 2 -#define PRIV_DIR_INO_NUM 3 -#define SNAP_DIR_INO_NUM 6 +#define INVALID_INO_NUM 0 +#define ROOT_DIR_PARENT 1 +#define ROOT_DIR_INO_NUM 2 +#define PRIV_DIR_INO_NUM 3 +#define SNAP_DIR_INO_NUM 6 +#define PURGEABLE_DIR_INO_NUM 7 + +#define MIN_USER_INO_NUM 16 -#define MIN_USER_INO_NUM 16 +#define UNIFIED_ID_SPACE_MARK 0x0800000000000000ULL /** Extended Attributes Constants **/ #define XATTR_MAX_EMBEDDED_SIZE 3804 // = 3 Ki + 732 #define SYMLINK_EA_NAME "com.apple.fs.symlink" +#define FIRMLINK_EA_NAME "com.apple.fs.firmlink" +#define APFS_COW_EXEMPT_COUNT_NAME "com.apple.fs.cow-exempt-file-count" /** File-System Object Constants **/ diff --git a/src/apfs/struct/j.h b/src/apfs/struct/j.h index 943568a..82531d6 100644 --- a/src/apfs/struct/j.h +++ b/src/apfs/struct/j.h @@ -16,9 +16,11 @@ typedef struct { uint64_t obj_id_and_type; } __attribute__((packed)) j_key_t; -#define OBJ_ID_MASK 0x0fffffffffffffffULL -#define OBJ_TYPE_MASK 0xf000000000000000ULL -#define OBJ_TYPE_SHIFT 60 +#define OBJ_ID_MASK 0x0fffffffffffffffULL +#define OBJ_TYPE_MASK 0xf000000000000000ULL +#define OBJ_TYPE_SHIFT 60 + +#define SYSTEM_OBJ_ID_MARK 0x0fffffff00000000ULL /** `j_inode_key_t` **/ @@ -54,7 +56,7 @@ typedef struct { gid_t group; mode_t mode; uint16_t pad1; - uint64_t pad2; + uint64_t uncompressed_size; // formerly `pad2` uint8_t xfields[]; } __attribute__((packed)) j_inode_val_t; @@ -66,7 +68,7 @@ typedef struct { uint8_t name[0]; } __attribute__((packed)) j_drec_key_t; -/* +/** * NOTE: The spec says that if a file-system record is of type * `APFS_TYPE_DIR_REC`, then the record's key is an instance of `j_drec_key_t`. * However, the type `j_drec_hashed_key_t` (seen below) is defined in the spec From 9052b5b380faff4c4b026afa55209fbd184e3021 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 15:06:04 +0000 Subject: [PATCH 13/20] =?UTF-8?q?Update=20=C2=A711=20Extended=20Fields?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/struct/xf.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/notes.md b/notes.md index 66c3f7b..859ca9a 100644 --- a/notes.md +++ b/notes.md @@ -102,8 +102,8 @@ ## Extended-Field Types - - [ ] INO_EXT_TYPE_PURGEABLE_FLAGS - - [ ] INO_EXT_TYPE_ORIG_SYNC_ROOT_ID + - [x] INO_EXT_TYPE_PURGEABLE_FLAGS + - [x] INO_EXT_TYPE_ORIG_SYNC_ROOT_ID # §13 Snapshot Metadata diff --git a/src/apfs/struct/xf.h b/src/apfs/struct/xf.h index 41c8e35..52be0e6 100644 --- a/src/apfs/struct/xf.h +++ b/src/apfs/struct/xf.h @@ -38,7 +38,8 @@ typedef struct { #define INO_EXT_TYPE_RESERVED_12 12 #define INO_EXT_TYPE_SPARSE_BYTES 13 #define INO_EXT_TYPE_RDEV 14 - +#define INO_EXT_TYPE_PURGEABLE_FLAGS 15 +#define INO_EXT_TYPE_ORIG_SYNC_ROOT_ID 16 /** Extended-Field Flags **/ From 2cf51229ee4ba26dfb0be855cf3d37541c363f1b Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 15:11:09 +0000 Subject: [PATCH 14/20] =?UTF-8?q?Update=20=C2=A713=20Snapshot=20Metadata?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 4 ++-- src/apfs/struct/snap.h | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/notes.md b/notes.md index 859ca9a..9eced6d 100644 --- a/notes.md +++ b/notes.md @@ -109,11 +109,11 @@ ## `snap_meta_ext_obj_phys_t` - - [ ] *New datatype* `snap_meta_ext_obj_phys_t` + - [x] *New datatype* `snap_meta_ext_obj_phys_t` ## `snap_meta_ext_t` - - [ ] *New datatype* `snap_meta_ext_t` + - [x] *New datatype* `snap_meta_ext_t` # §14 B-Trees diff --git a/src/apfs/struct/snap.h b/src/apfs/struct/snap.h index 2d31336..3477079 100644 --- a/src/apfs/struct/snap.h +++ b/src/apfs/struct/snap.h @@ -7,6 +7,7 @@ */ #include +#include "general.h" // uuid_t #include "j.h" // j_key_t #include "object.h" // oid_t, xid_t @@ -50,4 +51,23 @@ typedef enum { SNAP_META_PENDING_DATALESS = 0x00000001, } snap_meta_flags; +/** `snap_meta_ext_t` --- forward declared for `snap_meta_ext_obj_phys_t` **/ + +typedef struct { + uint32_t sme_version; + + uint32_t sme_flags; + xid_t sme_snap_xid; + uuid_t sme_uuid; + + uint64_t sme_token; +} __attribute__((packed)) snap_meta_ext_t; + +/** `snap_meta_ext_obj_phys_t` **/ + +typedef struct { + obj_phys_t smeop_o; + snap_meta_ext_t smeop_sme; +} __attribute__((packed)) snap_meta_ext_obj_phys_t; + #endif // APFS_STRUCT_SNAP_H From bf9e422ed1e48d8c98f8ecf65e8cd5db1772955b Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 16:42:43 +0000 Subject: [PATCH 15/20] =?UTF-8?q?Updaet=20=C2=A714=20B-Trees?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 10 +++++----- src/apfs/string/btree.c | 16 +++++++++++----- src/apfs/struct/btree.h | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/notes.md b/notes.md index 9eced6d..d2f217c 100644 --- a/notes.md +++ b/notes.md @@ -119,17 +119,17 @@ ## `btn_index_node_val_t` - - [ ] *New datatype* `btn_index_node_val_t` + - [x] *New datatype* `btn_index_node_val_t` ## B-Tree Flags - - [ ] BTREE_HASHED - - [ ] BTREE_NOHEADER + - [x] BTREE_HASHED + - [x] BTREE_NOHEADER ## B-Tree Node Flags - - [ ] BTNODE_HASHED - - [ ] BTNODE_NOHEADER + - [x] BTNODE_HASHED + - [x] BTNODE_NOHEADER # §15 Encryption diff --git a/src/apfs/string/btree.c b/src/apfs/string/btree.c index e7b2b77..21d656e 100644 --- a/src/apfs/string/btree.c +++ b/src/apfs/string/btree.c @@ -28,20 +28,22 @@ char* get_btn_flags_string(btree_node_phys_t* btn) { char* default_string = "(none)"; size_t default_string_len = strlen(default_string); - uint8_t NUM_FLAGS = 4; - + uint8_t NUM_FLAGS = 6; uint16_t flag_constants[] = { BTNODE_ROOT, BTNODE_LEAF, BTNODE_FIXED_KV_SIZE, + BTNODE_HASHED, + BTNODE_NOHEADER, BTNODE_CHECK_KOFF_INVAL, }; - char* flag_strings[] = { "Root node", "Leaf node", "Fixed size for keys and values", - "In transient state --- should never appear on disk" + "Contains child node hashes", + "Doesn't have an object header", + "In transient state (key offsets are invalid) --- should never appear on disk" }; size_t max_mem_required = 0; @@ -102,7 +104,7 @@ char* get_bt_info_flags_string(btree_info_t* bt_info) { char* default_string = " - No flags are set\n"; size_t default_string_len = strlen(default_string); - uint8_t NUM_FLAGS = 7; + uint8_t NUM_FLAGS = 9; uint16_t flag_constants[] = { BTREE_UINT64_KEYS, @@ -112,6 +114,8 @@ char* get_bt_info_flags_string(btree_info_t* bt_info) { BTREE_PHYSICAL, BTREE_NONPERSISTENT, BTREE_KV_NONALIGNED, + BTREE_HASHED, + BTREE_NOHEADER, }; char* flag_strings[] = { @@ -122,6 +126,8 @@ char* get_bt_info_flags_string(btree_info_t* bt_info) { "Child nodes are referred to using Physical OIDs", "This B-tree does not persist across unmounts", "8-byte alignment of keys and values is not required", + "Non-leaf nodes store a hash of their child nodes", + "Nodes don't have object headers", }; size_t max_mem_required = 0; diff --git a/src/apfs/struct/btree.h b/src/apfs/struct/btree.h index d4e3b8e..d9038ce 100644 --- a/src/apfs/struct/btree.h +++ b/src/apfs/struct/btree.h @@ -49,6 +49,15 @@ typedef struct { uint64_t bt_node_count; } btree_info_t; +/** `btn_index_node_val_t` **/ + +#define BTREE_NODE_HASH_SIZE_MAX 64 + +typedef struct { + oid_t binv_child_oid; + uint8_t binv_child_hash[BTREE_NODE_HASH_SIZE_MAX]; +} btn_index_node_val_t; + /** `kvloc_t` **/ typedef struct { @@ -72,6 +81,8 @@ typedef struct { #define BTREE_PHYSICAL 0x00000010 #define BTREE_NONPERSISTENT 0x00000020 #define BTREE_KV_NONALIGNED 0x00000040 +#define BTREE_HASHED 0x00000080 +#define BTREE_NOHEADER 0x00000100 /** B-Tree Table of Contents Constants **/ @@ -82,7 +93,11 @@ typedef struct { #define BTNODE_ROOT 0x0001 #define BTNODE_LEAF 0x0002 + #define BTNODE_FIXED_KV_SIZE 0x0004 +#define BTNODE_HASHED 0x0008 +#define BTNODE_NOHEADER 0x0010 + #define BTNODE_CHECK_KOFF_INVAL 0x8000 /** B-Tree Node Constants **/ From 9989339132d3abd063d0fa8ea0738cb3e1986dcd Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 16:50:17 +0000 Subject: [PATCH 16/20] =?UTF-8?q?Update=20=C2=A715=20Encryption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 8 ++++---- src/apfs/struct/crypto.h | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/notes.md b/notes.md index d2f217c..000797e 100644 --- a/notes.md +++ b/notes.md @@ -135,16 +135,16 @@ ## Protection Classes - - [ ] PROTECTION_CLASS_M + - [x] PROTECTION_CLASS_M ## Encryption Identifiers - - [ ] APFS_UNASSIGNED_CRYPTO_ID + - [x] APFS_UNASSIGNED_CRYPTO_ID ## Keybag Tags - - [ ] KB_TAG_WRAPPING_M_KEY - - [ ] KB_TAG_VOLUME_M_KEY + - [x] KB_TAG_WRAPPING_M_KEY + - [x] KB_TAG_VOLUME_M_KEY # §16 Sealed Volumes diff --git a/src/apfs/struct/crypto.h b/src/apfs/struct/crypto.h index 3b88fde..256cefb 100644 --- a/src/apfs/struct/crypto.h +++ b/src/apfs/struct/crypto.h @@ -53,19 +53,22 @@ typedef struct { /** Protection Classes **/ -#define PROTECTION_CLASS_DIR_NONE 0 -#define PROTECTION_CLASS_A 1 -#define PROTECTION_CLASS_B 2 -#define PROTECTION_CLASS_C 3 -#define PROTECTION_CLASS_D 4 -#define PROTECTION_CLASS_F 6 +#define PROTECTION_CLASS_DIR_NONE 0 +#define PROTECTION_CLASS_A 1 +#define PROTECTION_CLASS_B 2 +#define PROTECTION_CLASS_C 3 +#define PROTECTION_CLASS_D 4 +#define PROTECTION_CLASS_F 6 +#define PROTECTION_CLASS_M 14 #define CP_EFFECTIVE_CLASSMASK 0x0000001f /** Encryption Identifiers **/ -#define CRYPTO_SW_ID 4 -#define CRYPTO_RESERVED_5 5 +#define CRYPTO_SW_ID 4 +#define CRYPTO_RESERVED_5 5 + +#define APFS_UNASSIGNED_CRYPTO_ID (~0ULL) /** `keybag_entry_t` --- forward declared for `kb_locker_t` **/ @@ -108,6 +111,9 @@ enum { KB_TAG_VOLUME_KEY = 2, KB_TAG_VOLUME_UNLOCK_RECORDS = 3, KB_TAG_VOLUME_PASSPHRASE_HINT = 4, + + KB_TAG_WRAPPING_M_KEY = 5, + KB_TAG_VOLUME_M_KEY = 6, KB_TAG_RESERVED_F8 = 0xf8, }; From 86ec6826c839be66cb310fb1f3c783bf26825d54 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Thu, 4 Feb 2021 16:59:10 +0000 Subject: [PATCH 17/20] =?UTF-8?q?Update=20=C2=A717=20Space=20Manager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 2 +- src/apfs/struct/spaceman.h | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/notes.md b/notes.md index 000797e..cf02d24 100644 --- a/notes.md +++ b/notes.md @@ -154,4 +154,4 @@ ## `spaceman_free_queue_entry_t` - - [ ] *New datatype* `spaceman_free_queue_entry_t` + - [x] *New datatype* `spaceman_free_queue_entry_t` diff --git a/src/apfs/struct/spaceman.h b/src/apfs/struct/spaceman.h index e1bc243..3ca9039 100644 --- a/src/apfs/struct/spaceman.h +++ b/src/apfs/struct/spaceman.h @@ -38,13 +38,24 @@ typedef struct { paddr_t cab_cib_addr[]; } cib_addr_block_t; -/** `spaceman_free_queue_key_t` **/ +/** `spaceman_free_queue_key_t` --- forward declared for `spaceman_free_queue_entry_t` **/ typedef struct { xid_t sfqk_xid; paddr_t sfqk_paddr; } spaceman_free_queue_key_t; +/** `spaceman_free_queue_val_t` --- forward declared for `spaceman_free_queue_entry_t` **/ + +typedef uint64_t spaceman_free_queue_val_t; + +/** `spaceman_free_queue_entry_t` **/ + +typedef struct { + spaceman_free_queue_key_t sfqe_key; + spaceman_free_queue_val_t sfqe_count; +} spaceman_free_queue_entry_t; + /** `spaceman_free_queue_t` **/ typedef struct { From dafaeabef3a6604cf0f9eea548037847fa7e7736 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Fri, 5 Feb 2021 13:57:08 +0000 Subject: [PATCH 18/20] =?UTF-8?q?Add=20=C2=A716=20Sealed=20Volumes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- notes.md | 2 +- src/apfs/struct/sealed.h | 111 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/apfs/struct/sealed.h diff --git a/notes.md b/notes.md index cf02d24..e7a98c5 100644 --- a/notes.md +++ b/notes.md @@ -148,7 +148,7 @@ # §16 Sealed Volumes -- [ ] *New chapter* Sealed Volumes +- [x] *New chapter* Sealed Volumes # §17 Space Manager diff --git a/src/apfs/struct/sealed.h b/src/apfs/struct/sealed.h new file mode 100644 index 0000000..29d0111 --- /dev/null +++ b/src/apfs/struct/sealed.h @@ -0,0 +1,111 @@ +#ifndef APFS_STRUCT_SEALED_H +#define APFS_STRUCT_SEALED_H + +/** + * Structures and related items as defined in + * §16 "Sealed Volumes" + */ + +#include +#include "object.h" +#include "j.h" + +/** `apfs_hash_type_t` --- forward declared for `integrity_meta_phys_t` **/ + +typedef enum { + APFS_HASH_INVALID = 0, + APFS_HASH_SHA256 = 0x1, + APFS_HASH_SHA512_256 = 0x2, + APFS_HASH_SHA384 = 0x3, + APFS_HASH_SHA512 = 0x4, + + APFS_HASH_MIN = APFS_HASH_SHA256, + APFS_HASH_MAX = APFS_HASH_SHA512, + + APFS_HASH_DEFAULT = APFS_HASH_SHA256, +} apfs_hash_type_t; + +#define APFS_HASH_CCSHA256_SIZE 32 +#define APFS_HASH_CCSHA512_256_SIZE 32 +#define APFS_HASH_CCSHA384_SIZE 48 +#define APFS_HASH_CCSHA512_SIZE 64 + +#define APFS_HASH_MAX_SIZE 64 + +/** `integrity_meta_phys_t` **/ + +typedef struct { + obj_phys_t im_o; + uint32_t im_version; + + // Fields supported by `im_version` >= 1 + uint32_t im_flags; + apfs_hash_type_t im_hash_type; + uint32_t im_root_hash_offset; + xid_t im_broken_xid; + + // Fields supported by `im_version` >= 2 + uint64_t im_reserved[9]; +} __attribute__((packed)) integrity_meta_phys_t; + +/** Integrity Metadata Version Constants **/ + +enum { + INTEGRITY_META_VERSION_INVALID = 0, + INTEGRITY_META_VERSION_1 = 1, + INTEGRITY_META_VERSION_2 = 2, + INTEGRITY_META_VERSION_HIGHEST = INTEGRITY_META_VERSION_2, +}; + +/** Integrity Metadata Flags **/ + +#define APFS_SEAL_BROKEN (1U << 0) + +/** `fext_tree_key_t` **/ + +typedef struct { + uint64_t private_id; + uint64_t logical_addr; +} __attribute__((packed)) fext_tree_key_t; + +/** `fext_tree_val_t` **/ + +typedef struct { + uint64_t len_and_flags; + uint64_t phys_block_num; +} __attribute__((packed)) fext_tree_val_t; + +/** `j_file_info_key_t` **/ + +typedef struct { + j_key_t hdr; + uint64_t info_and_lba; +} __attribute__((packed)) j_file_info_key_t; + +#define J_FILE_INFO_LBA_MASK 0x00ffffffffffffffULL +#define J_FILE_INFO_TYPE_MASK 0xff00000000000000ULL +#define J_FILE_INFO_TYPE_SHIFT 56 + +/** `j_file_data_hash_val_t` --- forward declared for `j_file_info_val_t` **/ + +typedef struct { + uint16_t hashed_len; + uint8_t hash_size; + uint8_t hash[0]; +} __attribute__((packed)) j_file_data_hash_val_t; + +/** `j_file_info_val_t` **/ + +typedef struct { + union { + j_file_data_hash_val_t dhash; + }; +} __attribute__((packed)) j_file_info_val_t; + +/** `j_obj_file_info_type` **/ + +typedef enum { + APFS_FILE_INFO_DATA_HASH = 1, +} j_obj_file_info_type; + +#endif // APFS_STRUCT_SEALED_H From 25fa101d604fe2da23cfc86c65ed0e7cc2c2c5e3 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Fri, 5 Feb 2021 13:58:58 +0000 Subject: [PATCH 19/20] Minor: remove quotes from lead comments in struct headers --- src/apfs/struct/btree.h | 2 +- src/apfs/struct/const.h | 2 +- src/apfs/struct/crypto.h | 2 +- src/apfs/struct/cryptorolling.h | 2 +- src/apfs/struct/cryptotypes.h | 8 +++++--- src/apfs/struct/dstream.h | 2 +- src/apfs/struct/fs.h | 2 +- src/apfs/struct/fusion.h | 2 +- src/apfs/struct/general.h | 2 +- src/apfs/struct/j.h | 2 +- src/apfs/struct/jumpstart.h | 2 +- src/apfs/struct/nx.h | 2 +- src/apfs/struct/object.h | 2 +- src/apfs/struct/omap.h | 2 +- src/apfs/struct/reaper.h | 2 +- src/apfs/struct/sealed.h | 2 +- src/apfs/struct/sibling.h | 2 +- src/apfs/struct/snap.h | 2 +- src/apfs/struct/spaceman.h | 2 +- src/apfs/struct/xf.h | 2 +- 20 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/apfs/struct/btree.h b/src/apfs/struct/btree.h index d9038ce..ab8896e 100644 --- a/src/apfs/struct/btree.h +++ b/src/apfs/struct/btree.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §14 "B-Trees" + * §14 B-Trees */ #include diff --git a/src/apfs/struct/const.h b/src/apfs/struct/const.h index 8785787..7db6e8f 100644 --- a/src/apfs/struct/const.h +++ b/src/apfs/struct/const.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §9 "File-System Constants" + * §9 File-System Constants */ #include diff --git a/src/apfs/struct/crypto.h b/src/apfs/struct/crypto.h index 256cefb..44af01c 100644 --- a/src/apfs/struct/crypto.h +++ b/src/apfs/struct/crypto.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §15 "Encryption" + * §15 Encryption */ #include diff --git a/src/apfs/struct/cryptorolling.h b/src/apfs/struct/cryptorolling.h index 7d0f3a4..de22789 100644 --- a/src/apfs/struct/cryptorolling.h +++ b/src/apfs/struct/cryptorolling.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §18 "Encryption Rolling" + * §18 Encryption Rolling */ #include diff --git a/src/apfs/struct/cryptotypes.h b/src/apfs/struct/cryptotypes.h index 069fbee..c1db1cc 100644 --- a/src/apfs/struct/cryptotypes.h +++ b/src/apfs/struct/cryptotypes.h @@ -3,9 +3,11 @@ /** * Definitions of types used for encryption-related structures, as defined in - * §15.6 "Encryption Types" --- These types are defined in their own - * header file rather than being included in `crypto.h`, else there would be - * a dependency cycle (`j.h` ==> `crypto.h` ==> `j.h`). + * §15.6 Encryption Types. + * + * These types are defined in their own header file rather than being included + * in `crypto.h`, else there would be a dependency cycle + * (`j.h` ==> `crypto.h` ==> `j.h`). */ #include diff --git a/src/apfs/struct/dstream.h b/src/apfs/struct/dstream.h index d4e9428..587fbca 100644 --- a/src/apfs/struct/dstream.h +++ b/src/apfs/struct/dstream.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §10 "Data Streams" + * §10 Data Streams */ #include diff --git a/src/apfs/struct/fs.h b/src/apfs/struct/fs.h index c67ef5a..f464506 100644 --- a/src/apfs/struct/fs.h +++ b/src/apfs/struct/fs.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §7 "Volumes" + * §7 Volumes */ #include diff --git a/src/apfs/struct/fusion.h b/src/apfs/struct/fusion.h index 34cebcd..2b77540 100644 --- a/src/apfs/struct/fusion.h +++ b/src/apfs/struct/fusion.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §19 "Fusion" + * §19 Fusion */ #include diff --git a/src/apfs/struct/general.h b/src/apfs/struct/general.h index 497b9d6..8d91c0c 100644 --- a/src/apfs/struct/general.h +++ b/src/apfs/struct/general.h @@ -3,7 +3,7 @@ /** * Structures and related item as defined in - * §2 "General-Purpose Types" + * §2 General-Purpose Types */ #include diff --git a/src/apfs/struct/j.h b/src/apfs/struct/j.h index 82531d6..dd28b1e 100644 --- a/src/apfs/struct/j.h +++ b/src/apfs/struct/j.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §8 "File-System Objects" + * §8 File-System Objects */ #include diff --git a/src/apfs/struct/jumpstart.h b/src/apfs/struct/jumpstart.h index 42bbc1a..ee4ef85 100644 --- a/src/apfs/struct/jumpstart.h +++ b/src/apfs/struct/jumpstart.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §4 "EFI Jumpstart" + * §4 EFI Jumpstart */ #include diff --git a/src/apfs/struct/nx.h b/src/apfs/struct/nx.h index aba95e1..22d16c5 100644 --- a/src/apfs/struct/nx.h +++ b/src/apfs/struct/nx.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §5 "Container" + * §5 Container */ #include diff --git a/src/apfs/struct/object.h b/src/apfs/struct/object.h index 85f6585..75f0aa3 100644 --- a/src/apfs/struct/object.h +++ b/src/apfs/struct/object.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §3 "Objects" + * §3 Objects */ #include diff --git a/src/apfs/struct/omap.h b/src/apfs/struct/omap.h index df9bde2..53c124f 100644 --- a/src/apfs/struct/omap.h +++ b/src/apfs/struct/omap.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §6 "Object Maps" + * §6 Object Maps */ #include diff --git a/src/apfs/struct/reaper.h b/src/apfs/struct/reaper.h index a37d892..43ce62f 100644 --- a/src/apfs/struct/reaper.h +++ b/src/apfs/struct/reaper.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §17 "Reaper" + * §17 Reaper */ #include diff --git a/src/apfs/struct/sealed.h b/src/apfs/struct/sealed.h index 29d0111..79119ea 100644 --- a/src/apfs/struct/sealed.h +++ b/src/apfs/struct/sealed.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §16 "Sealed Volumes" + * §16 Sealed Volumes */ #include diff --git a/src/apfs/struct/sibling.h b/src/apfs/struct/sibling.h index 1b93676..f7e3225 100644 --- a/src/apfs/struct/sibling.h +++ b/src/apfs/struct/sibling.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §12 "Siblings" + * §12 Siblings */ #include diff --git a/src/apfs/struct/snap.h b/src/apfs/struct/snap.h index 3477079..3d40c24 100644 --- a/src/apfs/struct/snap.h +++ b/src/apfs/struct/snap.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §13 "Snapshot Metadata" + * §13 Snapshot Metadata */ #include diff --git a/src/apfs/struct/spaceman.h b/src/apfs/struct/spaceman.h index 3ca9039..7d7b1bc 100644 --- a/src/apfs/struct/spaceman.h +++ b/src/apfs/struct/spaceman.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §17 "Space Manager" + * §17 Space Manager */ #include diff --git a/src/apfs/struct/xf.h b/src/apfs/struct/xf.h index 52be0e6..666a70f 100644 --- a/src/apfs/struct/xf.h +++ b/src/apfs/struct/xf.h @@ -3,7 +3,7 @@ /** * Structures and related items as defined in - * §11 "Extended Fields" + * §11 Extended Fields */ #include From 2cd97437c4f4dfa7c23d8b53869d66e1af423d14 Mon Sep 17 00:00:00 2001 From: Jivan Pal Date: Fri, 5 Feb 2021 14:00:40 +0000 Subject: [PATCH 20/20] Rename struct/const.h to struct/jconst.h --- src/apfs/struct/j.h | 2 +- src/apfs/struct/{const.h => jconst.h} | 0 src/commands/explore-fs-tree.c | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/apfs/struct/{const.h => jconst.h} (100%) diff --git a/src/apfs/struct/j.h b/src/apfs/struct/j.h index dd28b1e..33c591c 100644 --- a/src/apfs/struct/j.h +++ b/src/apfs/struct/j.h @@ -7,7 +7,7 @@ */ #include -#include "const.h" // mode_t +#include "jconst.h" // mode_t #include "cryptotypes.h" // cp_key_class_t /** `j_key_t` **/ diff --git a/src/apfs/struct/const.h b/src/apfs/struct/jconst.h similarity index 100% rename from src/apfs/struct/const.h rename to src/apfs/struct/jconst.h diff --git a/src/commands/explore-fs-tree.c b/src/commands/explore-fs-tree.c index 0a8e3e2..69df15a 100644 --- a/src/commands/explore-fs-tree.c +++ b/src/commands/explore-fs-tree.c @@ -7,7 +7,7 @@ #include "../apfs/io.h" #include "../apfs/struct/general.h" #include "../apfs/struct/j.h" -#include "../apfs/struct/const.h" +#include "../apfs/struct/jconst.h" #include "../apfs/struct/dstream.h" #include "../apfs/struct/sibling.h" #include "../apfs/struct/snap.h"