-
Notifications
You must be signed in to change notification settings - Fork 206
/
Copy pathds_store.ksy
223 lines (223 loc) · 6.32 KB
/
ds_store.ksy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
meta:
id: ds_store
title: macOS '.DS_Store' format
file-extension: DS_Store
xref:
justsolve: Desktop_Services_Store
pronom: fmt/394
wikidata: Q307271
license: MIT
ks-version: 0.9
encoding: UTF-8
endian: be
doc: |
Apple macOS '.DS_Store' file format.
doc-ref:
- https://en.wikipedia.org/wiki/.DS_Store
- https://metacpan.org/dist/Mac-Finder-DSStore/view/DSStoreFormat.pod
- https://0day.work/parsing-the-ds_store-file-format/
seq:
- id: alignment_header
contents: [0x00, 0x00, 0x00, 0x01]
- id: buddy_allocator_header
type: buddy_allocator_header
instances:
buddy_allocator_body:
pos: buddy_allocator_header.ofs_bookkeeping_info_block + 4
size: buddy_allocator_header.len_bookkeeping_info_block
type: buddy_allocator_body
block_address_mask:
value: 0x1f
doc: |
Bitmask used to calculate the position and the size of each block
of the B-tree from the block addresses.
types:
buddy_allocator_header:
seq:
- id: magic
contents: ["Bud1"]
doc: Magic number 'Bud1'.
- id: ofs_bookkeeping_info_block
type: u4
- id: len_bookkeeping_info_block
type: u4
- id: copy_ofs_bookkeeping_info_block
type: u4
doc: Needs to match 'offset_bookkeeping_info_block'.
- size: 16
doc: |
Unused field which might simply be the unused space at the end of the block,
since the minimum allocation size is 32 bytes.
buddy_allocator_body:
seq:
- id: num_blocks
type: u4
doc: Number of blocks in the allocated-blocks list.
- size: 4
doc: Unknown field which appears to always be 0.
- id: block_addresses
type: block_descriptor
repeat: expr
repeat-expr: num_block_addresses
doc: Addresses of the different blocks.
- id: num_directories
type: u4
doc: Indicates the number of directory entries.
- id: directory_entries
type: directory_entry
repeat: expr
repeat-expr: num_directories
doc: Each directory is an independent B-tree.
- id: free_lists
type: free_list
repeat: expr
repeat-expr: num_free_lists
types:
block_descriptor:
seq:
- id: address_raw
type: u4
instances:
offset:
value: (address_raw & ~_root.block_address_mask) + 4
size:
value: 1 << (address_raw & _root.block_address_mask)
directory_entry:
seq:
- id: len_name
type: u1
- id: name
size: len_name
type: str
- id: block_id
type: u4
free_list:
seq:
- id: counter
type: u4
- id: offsets
type: u4
repeat: expr
repeat-expr: counter
instances:
num_block_addresses:
value: 256
num_free_lists:
value: 32
directories:
io: _root._io
type: master_block_ref(_index)
repeat: expr
repeat-expr: num_directories
doc: Master blocks of the different B-trees.
master_block_ref:
params:
- id: idx
type: u8
instances:
master_block:
pos: _parent.block_addresses[_parent.directory_entries[idx].block_id].offset
size: _parent.block_addresses[_parent.directory_entries[idx].block_id].size
type: master_block
types:
master_block:
seq:
- id: block_id
type: u4
doc: Block number of the B-tree's root node.
- id: num_internal_nodes
type: u4
doc: Number of internal node levels.
- id: num_records
type: u4
doc: Number of records in the tree.
- id: num_nodes
type: u4
doc: Number of nodes in the tree.
- type: u4
doc: Always 0x1000, probably the B-tree node page size.
instances:
root_block:
io: _root._io
pos: _root.buddy_allocator_body.block_addresses[block_id].offset
type: block
block:
seq:
- id: mode
type: u4
doc: If mode is 0, this is a leaf node, otherwise it is an internal node.
- id: counter
type: u4
doc: Number of records or number of block id + record pairs.
- id: data
type: block_data(mode)
repeat: expr
repeat-expr: counter
types:
block_data:
params:
- id: mode
type: u4
seq:
- id: block_id
type: u4
if: mode > 0
- id: record
type: record
instances:
block:
io: _root._io
pos: _root.buddy_allocator_body.block_addresses[block_id.as<u4>].offset
type: block
if: mode > 0
types:
record:
seq:
- id: filename
type: ustr
- id: structure_type
type: four_char_code
doc: Description of the entry's property.
- id: data_type
size: 4
type: str
doc: Data type of the value.
- id: value
type:
switch-on: data_type
cases:
'"long"': u4
'"shor"': u4
'"bool"': u1
'"blob"': record_blob
'"type"': four_char_code
'"ustr"': ustr
'"comp"': u8
'"dutc"': u8
types:
record_blob:
seq:
- id: length
type: u4
- id: value
size: length
ustr:
seq:
- id: length
type: u4
- id: value
size: 2 * length
type: str
encoding: UTF-16BE
four_char_code:
seq:
- id: value
size: 4
type: str
instances:
rightmost_block:
io: _root._io
pos: _root.buddy_allocator_body.block_addresses[mode].offset
type: block
if: mode > 0
doc: Rightmost child block pointer.