On Sat, 2025-04-26 at 06:17 +0000, 李扬韬 wrote: > Hi Slava and Adrian, > I plan on looking at a few hfsplus failures first, or if there is something else planned I'll go for that too. > Sounds good! I think I can share some resources [1, 2] if you need to take a deeper look into HFS/HFS+ on-disk layout. I already started to take a look into HFS issues. Currently, I am investigating generic/001 case. fsck.hfs -d -n ./test-image.bin ** ./test-image.bin (NO WRITE) Using cacheBlockSize=32K cacheTotalBlock=1024 cacheSize=32768K. Executing fsck_hfs (version 540.1-Linux). ** Checking HFS volume. The volume name is untitled ** Checking extents overflow file. ** Checking catalog file. Unused node is not erased (node = 2) Unused node is not erased (node = 4) Unused node is not erased (node = 5) Unused node is not erased (node = 6) Unused node is not erased (node = 7) Unused node is not erased (node = 8) Unused node is not erased (node = 9) Unused node is not erased (node = 10) Unused node is not erased (node = 11) Unused node is not erased (node = 12) Unused node is not erased (node = 13) Unused node is not erased (node = 14) Unused node is not erased (node = 16) Unused node is not erased (node = 17) Unused node is not erased (node = 18) Unused node is not erased (node = 19) Unused node is not erased (node = 20) Unused node is not erased (node = 21) Unused node is not erased (node = 22) Unused node is not erased (node = 23) Unused node is not erased (node = 24) Unused node is not erased (node = 25) Unused node is not erased (node = 26) Unused node is not erased (node = 27) Unused node is not erased (node = 28) Unused node is not erased (node = 29) Unused node is not erased (node = 30) Unused node is not erased (node = 31) Unused node is not erased (node = 32) Unused node is not erased (node = 33) Unused node is not erased (node = 34) Unused node is not erased (node = 35) Unused node is not erased (node = 36) Unused node is not erased (node = 37) Unused node is not erased (node = 38) Unused node is not erased (node = 39) Unused node is not erased (node = 40) Unused node is not erased (node = 41) Unused node is not erased (node = 42) Unused node is not erased (node = 43) Unused node is not erased (node = 44) Unused node is not erased (node = 45) Unused node is not erased (node = 46) Unused node is not erased (node = 47) Unused node is not erased (node = 48) Unused node is not erased (node = 49) Unused node is not erased (node = 50) Unused node is not erased (node = 51) Unused node is not erased (node = 52) Unused node is not erased (node = 53) Unused node is not erased (node = 54) Unused node is not erased (node = 55) Unused node is not erased (node = 56) Unused node is not erased (node = 57) Unused node is not erased (node = 58) Unused node is not erased (node = 59) Unused node is not erased (node = 60) Unused node is not erased (node = 61) Unused node is not erased (node = 62) Unused node is not erased (node = 63) Unused node is not erased (node = 64) Unused node is not erased (node = 65) Unused node is not erased (node = 66) Unused node is not erased (node = 67) Unused node is not erased (node = 68) Unused node is not erased (node = 69) Unused node is not erased (node = 70) Unused node is not erased (node = 71) Unused node is not erased (node = 72) Unused node is not erased (node = 73) Unused node is not erased (node = 74) Unused node is not erased (node = 75) Unused node is not erased (node = 76) Unused node is not erased (node = 77) Unused node is not erased (node = 78) Unused node is not erased (node = 79) Unused node is not erased (node = 80) Unused node is not erased (node = 81) Unused node is not erased (node = 82) Unused node is not erased (node = 83) Unused node is not erased (node = 84) Unused node is not erased (node = 85) Unused node is not erased (node = 86) Unused node is not erased (node = 87) Unused node is not erased (node = 88) Unused node is not erased (node = 89) Unused node is not erased (node = 90) Unused node is not erased (node = 91) Unused node is not erased (node = 92) Unused node is not erased (node = 93) Unused node is not erased (node = 95) Unused node is not erased (node = 96) Unused node is not erased (node = 97) Unused node is not erased (node = 98) Unused node is not erased (node = 99) Unused node is not erased (node = 100) Unused node is not erased (node = 101) Unused node is not erased (node = 102) Unused node is not erased (node = 103) Unused node is not erased (node = 104) Unused node is not erased (node = 105) Unused node is not erased (node = 106) Unused node is not erased (node = 107) Unused node is not erased (node = 108) Unused node is not erased (node = 109) Unused node is not erased (node = 110) Unused node is not erased (node = 111) Unused node is not erased (node = 112) Unused node is not erased (node = 113) Unused node is not erased (node = 114) Unused node is not erased (node = 115) Unused node is not erased (node = 116) Unused node is not erased (node = 117) Unused node is not erased (node = 118) Unused node is not erased (node = 119) Unused node is not erased (node = 120) Unused node is not erased (node = 121) Unused node is not erased (node = 122) Unused node is not erased (node = 123) Unused node is not erased (node = 124) Unused node is not erased (node = 125) Unused node is not erased (node = 126) Unused node is not erased (node = 127) Unused node is not erased (node = 128) Unused node is not erased (node = 129) Unused node is not erased (node = 130) Unused node is not erased (node = 131) Unused node is not erased (node = 132) Unused node is not erased (node = 133) Unused node is not erased (node = 134) Unused node is not erased (node = 135) Unused node is not erased (node = 136) Unused node is not erased (node = 137) Unused node is not erased (node = 138) Unused node is not erased (node = 139) Unused node is not erased (node = 140) Unused node is not erased (node = 141) Unused node is not erased (node = 142) Unused node is not erased (node = 143) Unused node is not erased (node = 144) Unused node is not erased (node = 145) Unused node is not erased (node = 146) Unused node is not erased (node = 147) Unused node is not erased (node = 148) Unused node is not erased (node = 149) Unused node is not erased (node = 150) Unused node is not erased (node = 151) Unused node is not erased (node = 152) Unused node is not erased (node = 153) Unused node is not erased (node = 154) Unused node is not erased (node = 155) Unused node is not erased (node = 156) Unused node is not erased (node = 157) Unused node is not erased (node = 158) Unused node is not erased (node = 159) Unused node is not erased (node = 160) Unused node is not erased (node = 161) Unused node is not erased (node = 162) Unused node is not erased (node = 163) Unused node is not erased (node = 164) Unused node is not erased (node = 165) Unused node is not erased (node = 166) Unused node is not erased (node = 167) Unused node is not erased (node = 168) Unused node is not erased (node = 169) Unused node is not erased (node = 170) Unused node is not erased (node = 171) Unused node is not erased (node = 172) Unused node is not erased (node = 173) Unused node is not erased (node = 174) Unused node is not erased (node = 175) Unused node is not erased (node = 176) Unused node is not erased (node = 177) Unused node is not erased (node = 178) Unused node is not erased (node = 179) Unused node is not erased (node = 180) Unused node is not erased (node = 181) Unused node is not erased (node = 182) Unused node is not erased (node = 183) Unused node is not erased (node = 184) Unused node is not erased (node = 185) Unused node is not erased (node = 186) Unused node is not erased (node = 187) Unused node is not erased (node = 188) Unused node is not erased (node = 189) Unused node is not erased (node = 190) Unused node is not erased (node = 191) Unused node is not erased (node = 192) Unused node is not erased (node = 193) Unused node is not erased (node = 194) Unused node is not erased (node = 195) Unused node is not erased (node = 196) Unused node is not erased (node = 197) Unused node is not erased (node = 198) Unused node is not erased (node = 199) Unused node is not erased (node = 200) Unused node is not erased (node = 201) Unused node is not erased (node = 202) Unused node is not erased (node = 203) Unused node is not erased (node = 204) Unused node is not erased (node = 205) Unused node is not erased (node = 206) Unused node is not erased (node = 207) Unused node is not erased (node = 208) Unused node is not erased (node = 209) Unused node is not erased (node = 210) Unused node is not erased (node = 211) Unused node is not erased (node = 212) Unused node is not erased (node = 213) Unused node is not erased (node = 214) Unused node is not erased (node = 215) Unused node is not erased (node = 216) Unused node is not erased (node = 217) Unused node is not erased (node = 218) Unused node is not erased (node = 219) Unused node is not erased (node = 220) Unused node is not erased (node = 221) Unused node is not erased (node = 222) Unused node is not erased (node = 223) Unused node is not erased (node = 224) Unused node is not erased (node = 225) Unused node is not erased (node = 226) Unused node is not erased (node = 227) Unused node is not erased (node = 228) Unused node is not erased (node = 229) Unused node is not erased (node = 230) Unused node is not erased (node = 231) Unused node is not erased (node = 232) Unused node is not erased (node = 233) Unused node is not erased (node = 234) Unused node is not erased (node = 235) Unused node is not erased (node = 236) Unused node is not erased (node = 237) Unused node is not erased (node = 238) Unused node is not erased (node = 239) Unused node is not erased (node = 240) Unused node is not erased (node = 241) Unused node is not erased (node = 242) Unused node is not erased (node = 243) Unused node is not erased (node = 244) Unused node is not erased (node = 245) Unused node is not erased (node = 246) Unused node is not erased (node = 247) Unused node is not erased (node = 248) Unused node is not erased (node = 249) Unused node is not erased (node = 250) Unused node is not erased (node = 251) Unused node is not erased (node = 252) Unused node is not erased (node = 253) Unused node is not erased (node = 254) Unused node is not erased (node = 255) Unused node is not erased (node = 256) ** Checking catalog hierarchy. ** Checking volume bitmap. ** Checking volume information. Verify Status: VIStat = 0x0000, ABTStat = 0x0000 EBTStat = 0x0000 CBTStat = 0x0004 CatStat = 0x00000000 ** The volume untitled was found corrupt and needs to be repaired. volume type is HFS primary MDB is at block 2 0x02 alternate MDB is at block 20971518 0x13ffffe primary VHB is at block 0 0x00 alternate VHB is at block 0 0x00 sector size = 512 0x200 VolumeObject flags = 0x19 total sectors for volume = 20971520 0x1400000 total sectors for embedded volume = 0 0x00 It looks like that HFS driver doesn't erase deleted nodes of catalog file. So, I need to refresh my knowledge of HFS on-disk layout. Somehow, scratch volume becomes corrupted too. But I don't quite follow yet which operation makes it happened. We lost magic signature in the first MDB. 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000400 00 00 e4 31 b7 03 e4 31 b7 03 01 00 00 00 00 03 |...1...1........| 00000410 00 00 ff 33 00 02 82 00 00 0a 08 00 00 13 00 00 |...3............| 00000420 00 10 ff 27 08 75 6e 74 69 74 6c 65 64 00 00 00 |...'.untitled...| 00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000440 00 00 00 00 00 00 00 00 00 03 00 0f 0c 00 00 0f |................| 00000450 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 63 6e 65 |.............cne| 00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000480 00 00 00 0f 0c 00 00 00 00 06 00 00 00 00 00 00 |................| 00000490 00 00 00 0f 0c 00 00 06 00 06 00 00 00 00 00 00 |................| 000004a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000600 ff f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00002600 00 00 00 00 00 00 00 00 01 00 00 03 00 00 00 00 |................| 00002610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00002620 02 00 00 07 00 00 07 86 00 00 07 85 00 00 00 0f |................| 00002630 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00002640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000026f0 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 |................| 00002700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000027f0 00 00 00 00 00 00 00 00 01 f8 00 f8 00 78 00 0e |.............x..| 00002800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000f3200 00 00 00 00 00 00 00 00 01 00 00 03 00 00 00 01 |................| 000f3210 00 00 00 01 00 00 00 02 00 00 00 01 00 00 00 01 |................| 000f3220 02 00 00 25 00 00 07 86 00 00 07 84 00 00 00 0f |...%............| 000f3230 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000f3240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000f32f0 00 00 00 00 00 00 00 00 c0 00 00 00 00 00 00 00 |................| 000f3300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000f33f0 00 00 00 00 00 00 00 00 01 f8 00 f8 00 78 00 0e |.............x..| 000f3400 00 00 00 00 00 00 00 00 ff 01 00 02 00 00 0f 00 |................| 000f3410 00 00 00 01 08 75 6e 74 69 74 6c 65 64 00 01 00 |.....untitled...| 000f3420 00 00 00 00 00 00 00 02 e4 31 b7 03 e4 31 b7 03 |.........1...1..| 000f3430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000f3460 00 00 00 00 06 00 00 00 00 02 00 00 03 00 00 00 |................| 000f3470 00 00 00 00 00 00 00 00 00 01 08 75 6e 74 69 74 |...........untit| 000f3480 6c 65 64 00 00 00 00 00 00 00 00 00 00 00 00 00 |led.............| 000f3490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000f35f0 00 00 00 00 00 00 00 00 00 00 00 9a 00 64 00 0e |.............d..| 000f3600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 27ffffc00 42 44 e4 31 b7 03 e4 31 b7 03 01 00 00 00 00 03 |BD.1...1........| 27ffffc10 00 00 ff 33 00 02 82 00 00 0a 08 00 00 13 00 00 |...3............| 27ffffc20 00 10 ff 27 08 75 6e 74 69 74 6c 65 64 00 00 00 |...'.untitled...| 27ffffc30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 27ffffc40 00 00 00 00 00 00 00 00 00 02 00 0f 0c 00 00 0f |................| 27ffffc50 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 27ffffc60 00 00 00 00 00 00 00 00 00 00 00 00 00 63 6e 65 |.............cne| 27ffffc70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 27ffffc80 00 00 00 0f 0c 00 00 00 00 06 00 00 00 00 00 00 |................| 27ffffc90 00 00 00 0f 0c 00 00 06 00 06 00 00 00 00 00 00 |................| 27ffffca0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 280000000 And it looks like that mkfs.hfs simply ignores the -v option. I requested the test volume label, but it's untitled, finally. mkfs.hfs -v test ./scratch-image.bin Initialized ./scratch-image.bin as a 10240 MB HFS volume hexdump -C ./scratch-image.bin 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000400 42 44 e4 34 41 f8 e4 34 41 f8 01 00 00 00 00 03 |BD.4A..4A.......| 00000410 00 00 ff 33 00 02 82 00 00 0a 08 00 00 13 00 00 |...3............| 00000420 00 10 ff 27 08 75 6e 74 69 74 6c 65 64 00 00 00 |...'.untitled...| 00000430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000440 00 00 00 00 00 00 00 00 00 02 00 0f 0c 00 00 0f |................| 00000450 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000460 00 00 00 00 00 00 00 00 00 00 00 00 00 63 6e 65 |.............cne| 00000470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000480 00 00 00 0f 0c 00 00 00 00 06 00 00 00 00 00 00 |................| 00000490 00 00 00 0f 0c 00 00 06 00 06 00 00 00 00 00 00 |................| 000004a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| mkfs.hfs -h usage: mkfs.hfs [-N [partition-size]] [hfsplus-options] special-device options: -h create an HFS format filesystem (HFS Plus is the default) -N do not create file system, just print out parameters -s use case-sensitive filenames (default is case-insensitive) -w add a HFS wrapper (i.e. Native Mac OS 9 bootable) where hfsplus-options are: -J [journal-size] make this HFS+ volume journaled -D journal-dev use 'journal-dev' for an external journal -G group-id (for root directory) -U user-id (for root directory) -M octal access-mask (for root directory) -b allocation block size (4096 optimal) -c clump size list (comma separated) a=blocks (attributes file) b=blocks (bitmap file) c=blocks (catalog file) d=blocks (user data fork) e=blocks (extents file) r=blocks (user resource fork) -i starting catalog node id -n b-tree node size list (comma separated) e=size (extents b-tree) c=size (catalog b-tree) a=size (attributes b-tree) -v volume name (in ascii or UTF-8) examples: mkfs.hfs -v Untitled /dev/rdisk0s7 mkfs.hfs -v Untitled -n c=4096,e=1024 /dev/rdisk0s7 mkfs.hfs -v Untitled -c b=64,c=1024 /dev/rdisk0s Thanks, Slava. [1] https://dubeyko.com/development/FileSystems/hfs.html [2] https://dubeyko.com/development/FileSystems/hfsplus.html