/src/libfshfs/libfshfs/libfshfs_attributes_btree_file.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * The attributes B-tree file functions |
3 | | * |
4 | | * Copyright (C) 2009-2024, Joachim Metz <joachim.metz@gmail.com> |
5 | | * |
6 | | * Refer to AUTHORS for acknowledgements. |
7 | | * |
8 | | * This program is free software: you can redistribute it and/or modify |
9 | | * it under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation, either version 3 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <common.h> |
23 | | #include <byte_stream.h> |
24 | | #include <types.h> |
25 | | |
26 | | #include "libfshfs_attribute_record.h" |
27 | | #include "libfshfs_attributes_btree_file.h" |
28 | | #include "libfshfs_attributes_btree_key.h" |
29 | | #include "libfshfs_btree_file.h" |
30 | | #include "libfshfs_btree_node_cache.h" |
31 | | #include "libfshfs_definitions.h" |
32 | | #include "libfshfs_file_record.h" |
33 | | #include "libfshfs_libbfio.h" |
34 | | #include "libfshfs_libcdata.h" |
35 | | #include "libfshfs_libcerror.h" |
36 | | #include "libfshfs_libcnotify.h" |
37 | | |
38 | | #include "fshfs_attributes_file.h" |
39 | | |
40 | | /* Retrieves the attributes B-tree key from a specific B-tree node record |
41 | | * Returns 1 if successful or -1 on error |
42 | | */ |
43 | | int libfshfs_attributes_btree_file_get_key_from_node_by_index( |
44 | | libfshfs_btree_node_t *node, |
45 | | uint16_t record_index, |
46 | | libfshfs_attributes_btree_key_t **node_key, |
47 | | libcerror_error_t **error ) |
48 | 9.58k | { |
49 | 9.58k | libfshfs_attributes_btree_key_t *safe_node_key = NULL; |
50 | 9.58k | libfshfs_btree_node_record_t *node_record = NULL; |
51 | 9.58k | static char *function = "libfshfs_attributes_btree_file_get_key_from_node_by_index"; |
52 | | |
53 | 9.58k | if( node_key == NULL ) |
54 | 0 | { |
55 | 0 | libcerror_error_set( |
56 | 0 | error, |
57 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
58 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
59 | 0 | "%s: invalid attributes B-tree key.", |
60 | 0 | function ); |
61 | |
|
62 | 0 | return( -1 ); |
63 | 0 | } |
64 | 9.58k | if( libfshfs_btree_node_get_record_by_index( |
65 | 9.58k | node, |
66 | 9.58k | record_index, |
67 | 9.58k | &node_record, |
68 | 9.58k | error ) == -1 ) |
69 | 7 | { |
70 | 7 | libcerror_error_set( |
71 | 7 | error, |
72 | 7 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
73 | 7 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
74 | 7 | "%s: unable to retrieve node record: %" PRIu16 ".", |
75 | 7 | function, |
76 | 7 | record_index ); |
77 | | |
78 | 7 | goto on_error; |
79 | 7 | } |
80 | 9.58k | if( node_record == NULL ) |
81 | 0 | { |
82 | 0 | libcerror_error_set( |
83 | 0 | error, |
84 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
85 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
86 | 0 | "%s: missing B-tree node record: %" PRIu16 ".", |
87 | 0 | function, |
88 | 0 | record_index ); |
89 | |
|
90 | 0 | goto on_error; |
91 | 0 | } |
92 | 9.58k | if( node_record->key_value == NULL ) |
93 | 6.48k | { |
94 | 6.48k | if( libfshfs_attributes_btree_key_initialize( |
95 | 6.48k | &safe_node_key, |
96 | 6.48k | error ) != 1 ) |
97 | 0 | { |
98 | 0 | libcerror_error_set( |
99 | 0 | error, |
100 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
101 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
102 | 0 | "%s: unable to create attributes B-tree key.", |
103 | 0 | function ); |
104 | |
|
105 | 0 | goto on_error; |
106 | 0 | } |
107 | 6.48k | if( libfshfs_attributes_btree_key_read_data( |
108 | 6.48k | safe_node_key, |
109 | 6.48k | node_record->data, |
110 | 6.48k | node_record->data_size, |
111 | 6.48k | error ) != 1 ) |
112 | 132 | { |
113 | 132 | libcerror_error_set( |
114 | 132 | error, |
115 | 132 | LIBCERROR_ERROR_DOMAIN_IO, |
116 | 132 | LIBCERROR_IO_ERROR_READ_FAILED, |
117 | 132 | "%s: unable to read attributes B-tree key.", |
118 | 132 | function ); |
119 | | |
120 | 132 | goto on_error; |
121 | 132 | } |
122 | 6.35k | node_record->key_value = (intptr_t *) safe_node_key; |
123 | 6.35k | node_record->key_value_free_function = (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attributes_btree_key_free; |
124 | 6.35k | } |
125 | 9.44k | *node_key = (libfshfs_attributes_btree_key_t *) node_record->key_value; |
126 | | |
127 | 9.44k | return( 1 ); |
128 | | |
129 | 139 | on_error: |
130 | 139 | if( safe_node_key != NULL ) |
131 | 132 | { |
132 | 132 | libfshfs_attributes_btree_key_free( |
133 | 132 | &safe_node_key, |
134 | 132 | NULL ); |
135 | 132 | } |
136 | 139 | return( -1 ); |
137 | 9.58k | } |
138 | | |
139 | | /* Retrieves a sub node number for from the attributes B-tree key |
140 | | * Returns 1 if successful or -1 on error |
141 | | */ |
142 | | int libfshfs_attributes_btree_file_get_sub_node_number_from_key( |
143 | | libfshfs_attributes_btree_key_t *node_key, |
144 | | uint32_t *sub_node_number, |
145 | | libcerror_error_t **error ) |
146 | 4.03k | { |
147 | 4.03k | static char *function = "libfshfs_attributes_btree_file_get_sub_node_number_from_key"; |
148 | | |
149 | 4.03k | if( node_key == NULL ) |
150 | 0 | { |
151 | 0 | libcerror_error_set( |
152 | 0 | error, |
153 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
154 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
155 | 0 | "%s: invalid attributes B-tree key.", |
156 | 0 | function ); |
157 | |
|
158 | 0 | return( -1 ); |
159 | 0 | } |
160 | 4.03k | if( node_key->record_data == NULL ) |
161 | 0 | { |
162 | 0 | libcerror_error_set( |
163 | 0 | error, |
164 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
165 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
166 | 0 | "%s: invalid attributes B-tree key - missing record data.", |
167 | 0 | function ); |
168 | |
|
169 | 0 | return( -1 ); |
170 | 0 | } |
171 | 4.03k | if( node_key->record_data_size < 4 ) |
172 | 6 | { |
173 | 6 | libcerror_error_set( |
174 | 6 | error, |
175 | 6 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
176 | 6 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
177 | 6 | "%s: invalid attributes B-tree key - record data size value out of bounds.", |
178 | 6 | function ); |
179 | | |
180 | 6 | return( -1 ); |
181 | 6 | } |
182 | 4.03k | if( sub_node_number == NULL ) |
183 | 0 | { |
184 | 0 | libcerror_error_set( |
185 | 0 | error, |
186 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
187 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
188 | 0 | "%s: invalid sub node number.", |
189 | 0 | function ); |
190 | |
|
191 | 0 | return( -1 ); |
192 | 0 | } |
193 | 4.03k | byte_stream_copy_to_uint32_big_endian( |
194 | 4.03k | node_key->record_data, |
195 | 4.03k | *sub_node_number ); |
196 | | |
197 | 4.03k | return( 1 ); |
198 | 4.03k | } |
199 | | |
200 | | /* Retrieves an attribute for from the attributes B-tree record data |
201 | | * Returns 1 if successful or -1 on error |
202 | | */ |
203 | | int libfshfs_attributes_btree_file_get_attribute_from_record_data( |
204 | | libfshfs_btree_file_t *btree_file, |
205 | | libfshfs_attributes_btree_key_t *node_key, |
206 | | libfshfs_attribute_record_t **attribute_record, |
207 | | libcerror_error_t **error ) |
208 | 681 | { |
209 | 681 | libfshfs_attribute_record_t *safe_attribute_record = NULL; |
210 | 681 | static char *function = "libfshfs_attributes_btree_file_get_attribute_from_record_data"; |
211 | | |
212 | 681 | if( btree_file == NULL ) |
213 | 0 | { |
214 | 0 | libcerror_error_set( |
215 | 0 | error, |
216 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
217 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
218 | 0 | "%s: invalid B-tree file.", |
219 | 0 | function ); |
220 | |
|
221 | 0 | return( -1 ); |
222 | 0 | } |
223 | 681 | if( node_key == NULL ) |
224 | 0 | { |
225 | 0 | libcerror_error_set( |
226 | 0 | error, |
227 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
228 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
229 | 0 | "%s: invalid attributes B-tree key.", |
230 | 0 | function ); |
231 | |
|
232 | 0 | return( -1 ); |
233 | 0 | } |
234 | 681 | if( attribute_record == NULL ) |
235 | 0 | { |
236 | 0 | libcerror_error_set( |
237 | 0 | error, |
238 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
239 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
240 | 0 | "%s: invalid attribute record.", |
241 | 0 | function ); |
242 | |
|
243 | 0 | return( -1 ); |
244 | 0 | } |
245 | 681 | if( *attribute_record != NULL ) |
246 | 0 | { |
247 | 0 | libcerror_error_set( |
248 | 0 | error, |
249 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
250 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
251 | 0 | "%s: invalid attribute record value already set.", |
252 | 0 | function ); |
253 | |
|
254 | 0 | return( -1 ); |
255 | 0 | } |
256 | 681 | if( libfshfs_attribute_record_initialize( |
257 | 681 | &safe_attribute_record, |
258 | 681 | error ) != 1 ) |
259 | 0 | { |
260 | 0 | libcerror_error_set( |
261 | 0 | error, |
262 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
263 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
264 | 0 | "%s: unable to create attribute record.", |
265 | 0 | function ); |
266 | |
|
267 | 0 | goto on_error; |
268 | 0 | } |
269 | 681 | if( libfshfs_attribute_record_set_name( |
270 | 681 | safe_attribute_record, |
271 | 681 | node_key->name_data, |
272 | 681 | node_key->name_size, |
273 | 681 | error ) != 1 ) |
274 | 16 | { |
275 | 16 | libcerror_error_set( |
276 | 16 | error, |
277 | 16 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
278 | 16 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
279 | 16 | "%s: unable to set name of attribute record.", |
280 | 16 | function ); |
281 | | |
282 | 16 | goto on_error; |
283 | 16 | } |
284 | 665 | if( libfshfs_attribute_record_read_data( |
285 | 665 | safe_attribute_record, |
286 | 665 | node_key->record_data, |
287 | 665 | node_key->record_data_size, |
288 | 665 | error ) != 1 ) |
289 | 173 | { |
290 | 173 | libcerror_error_set( |
291 | 173 | error, |
292 | 173 | LIBCERROR_ERROR_DOMAIN_IO, |
293 | 173 | LIBCERROR_IO_ERROR_READ_FAILED, |
294 | 173 | "%s: unable to read attribute record.", |
295 | 173 | function ); |
296 | | |
297 | 173 | goto on_error; |
298 | 173 | } |
299 | 492 | *attribute_record = safe_attribute_record; |
300 | | |
301 | 492 | return( 1 ); |
302 | | |
303 | 189 | on_error: |
304 | 189 | if( safe_attribute_record != NULL ) |
305 | 189 | { |
306 | 189 | libfshfs_attribute_record_free( |
307 | 189 | &safe_attribute_record, |
308 | 189 | NULL ); |
309 | 189 | } |
310 | 189 | return( -1 ); |
311 | 665 | } |
312 | | |
313 | | /* Retrieves the attributes for a specific parent identifier from the attributes B-tree leaf node |
314 | | * Returns 1 if successful or -1 on error |
315 | | */ |
316 | | int libfshfs_attributes_btree_file_get_attributes_from_leaf_node( |
317 | | libfshfs_btree_file_t *btree_file, |
318 | | libfshfs_btree_node_t *node, |
319 | | uint32_t identifier, |
320 | | libcdata_array_t *attributes, |
321 | | libcerror_error_t **error ) |
322 | 2.70k | { |
323 | 2.70k | libfshfs_attribute_record_t *attribute_record = NULL; |
324 | 2.70k | libfshfs_attributes_btree_key_t *node_key = NULL; |
325 | 2.70k | static char *function = "libfshfs_attributes_btree_file_get_attributes_from_leaf_node"; |
326 | 2.70k | uint16_t record_index = 0; |
327 | 2.70k | int entry_index = 0; |
328 | 2.70k | int is_leaf_node = 0; |
329 | | |
330 | 2.70k | if( btree_file == NULL ) |
331 | 0 | { |
332 | 0 | libcerror_error_set( |
333 | 0 | error, |
334 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
335 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
336 | 0 | "%s: invalid B-tree file.", |
337 | 0 | function ); |
338 | |
|
339 | 0 | return( -1 ); |
340 | 0 | } |
341 | 2.70k | if( node == NULL ) |
342 | 0 | { |
343 | 0 | libcerror_error_set( |
344 | 0 | error, |
345 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
346 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
347 | 0 | "%s: invalid B-tree node.", |
348 | 0 | function ); |
349 | |
|
350 | 0 | return( -1 ); |
351 | 0 | } |
352 | 2.70k | if( node->descriptor == NULL ) |
353 | 0 | { |
354 | 0 | libcerror_error_set( |
355 | 0 | error, |
356 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
357 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
358 | 0 | "%s: invalid B-tree node - missing descriptor.", |
359 | 0 | function ); |
360 | |
|
361 | 0 | return( -1 ); |
362 | 0 | } |
363 | 2.70k | is_leaf_node = libfshfs_btree_node_is_leaf_node( |
364 | 2.70k | node, |
365 | 2.70k | error ); |
366 | | |
367 | 2.70k | if( is_leaf_node == -1 ) |
368 | 0 | { |
369 | 0 | libcerror_error_set( |
370 | 0 | error, |
371 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
372 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
373 | 0 | "%s: unable to determine if B-tree node is a leaf node.", |
374 | 0 | function ); |
375 | |
|
376 | 0 | goto on_error; |
377 | 0 | } |
378 | 2.70k | else if( is_leaf_node == 0 ) |
379 | 0 | { |
380 | 0 | libcerror_error_set( |
381 | 0 | error, |
382 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
383 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
384 | 0 | "%s: invalid node - not a leaf node.", |
385 | 0 | function ); |
386 | |
|
387 | 0 | goto on_error; |
388 | 0 | } |
389 | 2.70k | for( record_index = 0; |
390 | 4.43k | record_index < node->descriptor->number_of_records; |
391 | 2.70k | record_index++ ) |
392 | 4.02k | { |
393 | 4.02k | if( libfshfs_attributes_btree_file_get_key_from_node_by_index( |
394 | 4.02k | node, |
395 | 4.02k | record_index, |
396 | 4.02k | &node_key, |
397 | 4.02k | error ) == -1 ) |
398 | 105 | { |
399 | 105 | libcerror_error_set( |
400 | 105 | error, |
401 | 105 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
402 | 105 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
403 | 105 | "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".", |
404 | 105 | function, |
405 | 105 | record_index ); |
406 | | |
407 | 105 | goto on_error; |
408 | 105 | } |
409 | 3.91k | if( node_key == NULL ) |
410 | 0 | { |
411 | 0 | libcerror_error_set( |
412 | 0 | error, |
413 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
414 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
415 | 0 | "%s: missing attributes B-tree key: %" PRIu16 ".", |
416 | 0 | function, |
417 | 0 | record_index ); |
418 | |
|
419 | 0 | goto on_error; |
420 | 0 | } |
421 | 3.91k | if( node_key->identifier == identifier ) |
422 | 681 | { |
423 | 681 | if( libfshfs_attributes_btree_file_get_attribute_from_record_data( |
424 | 681 | btree_file, |
425 | 681 | node_key, |
426 | 681 | &attribute_record, |
427 | 681 | error ) != 1 ) |
428 | 189 | { |
429 | 189 | libcerror_error_set( |
430 | 189 | error, |
431 | 189 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
432 | 189 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
433 | 189 | "%s: unable to retrieve attribute from record data.", |
434 | 189 | function ); |
435 | | |
436 | 189 | goto on_error; |
437 | 189 | } |
438 | 492 | if( libcdata_array_append_entry( |
439 | 492 | attributes, |
440 | 492 | &entry_index, |
441 | 492 | (intptr_t *) attribute_record, |
442 | 492 | error ) != 1 ) |
443 | 0 | { |
444 | 0 | libcerror_error_set( |
445 | 0 | error, |
446 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
447 | 0 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
448 | 0 | "%s: unable to append attribute record to array.", |
449 | 0 | function ); |
450 | |
|
451 | 0 | goto on_error; |
452 | 0 | } |
453 | 492 | attribute_record = NULL; |
454 | 492 | } |
455 | 3.72k | if( node_key->identifier > identifier ) |
456 | 1.99k | { |
457 | 1.99k | break; |
458 | 1.99k | } |
459 | 3.72k | } |
460 | 2.40k | return( 1 ); |
461 | | |
462 | 294 | on_error: |
463 | 294 | if( attribute_record != NULL ) |
464 | 0 | { |
465 | 0 | libfshfs_attribute_record_free( |
466 | 0 | &attribute_record, |
467 | 0 | NULL ); |
468 | 0 | } |
469 | 294 | libcdata_array_empty( |
470 | 294 | attributes, |
471 | 294 | (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free, |
472 | 294 | NULL ); |
473 | | |
474 | 294 | return( -1 ); |
475 | 2.70k | } |
476 | | |
477 | | /* Retrieves the attributes for a specific parent identifier from the attributes B-tree branch node |
478 | | * Returns 1 if successful or -1 on error |
479 | | */ |
480 | | int libfshfs_attributes_btree_file_get_attributes_from_branch_node( |
481 | | libfshfs_btree_file_t *btree_file, |
482 | | libbfio_handle_t *file_io_handle, |
483 | | libfshfs_btree_node_cache_t *node_cache, |
484 | | libfshfs_btree_node_t *node, |
485 | | uint32_t identifier, |
486 | | libcdata_array_t *attributes, |
487 | | int recursion_depth, |
488 | | libcerror_error_t **error ) |
489 | 1.44k | { |
490 | 1.44k | libfshfs_attributes_btree_key_t *last_node_key = NULL; |
491 | 1.44k | libfshfs_attributes_btree_key_t *node_key = NULL; |
492 | 1.44k | libfshfs_btree_node_t *sub_node = NULL; |
493 | 1.44k | static char *function = "libfshfs_attributes_btree_file_get_attributes_from_branch_node"; |
494 | 1.44k | uint32_t sub_node_number = 0; |
495 | 1.44k | uint16_t record_index = 0; |
496 | 1.44k | uint8_t node_type = 0; |
497 | 1.44k | int is_branch_node = 0; |
498 | 1.44k | int result = 0; |
499 | | |
500 | 1.44k | if( btree_file == NULL ) |
501 | 0 | { |
502 | 0 | libcerror_error_set( |
503 | 0 | error, |
504 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
505 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
506 | 0 | "%s: invalid B-tree file.", |
507 | 0 | function ); |
508 | |
|
509 | 0 | return( -1 ); |
510 | 0 | } |
511 | 1.44k | if( node == NULL ) |
512 | 0 | { |
513 | 0 | libcerror_error_set( |
514 | 0 | error, |
515 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
516 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
517 | 0 | "%s: invalid B-tree node.", |
518 | 0 | function ); |
519 | |
|
520 | 0 | return( -1 ); |
521 | 0 | } |
522 | 1.44k | if( node->descriptor == NULL ) |
523 | 0 | { |
524 | 0 | libcerror_error_set( |
525 | 0 | error, |
526 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
527 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
528 | 0 | "%s: invalid B-tree node - missing descriptor.", |
529 | 0 | function ); |
530 | |
|
531 | 0 | return( -1 ); |
532 | 0 | } |
533 | 1.44k | if( ( recursion_depth < 0 ) |
534 | 1.44k | || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) ) |
535 | 0 | { |
536 | 0 | libcerror_error_set( |
537 | 0 | error, |
538 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
539 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
540 | 0 | "%s: invalid recursion depth value out of bounds.", |
541 | 0 | function ); |
542 | |
|
543 | 0 | return( -1 ); |
544 | 0 | } |
545 | 1.44k | is_branch_node = libfshfs_btree_node_is_branch_node( |
546 | 1.44k | node, |
547 | 1.44k | error ); |
548 | | |
549 | 1.44k | if( is_branch_node == -1 ) |
550 | 0 | { |
551 | 0 | libcerror_error_set( |
552 | 0 | error, |
553 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
554 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
555 | 0 | "%s: unable to determine if B-tree node is a branch node.", |
556 | 0 | function ); |
557 | |
|
558 | 0 | goto on_error; |
559 | 0 | } |
560 | 1.44k | else if( is_branch_node == 0 ) |
561 | 0 | { |
562 | 0 | libcerror_error_set( |
563 | 0 | error, |
564 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
565 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
566 | 0 | "%s: invalid node - not a branch node.", |
567 | 0 | function ); |
568 | |
|
569 | 0 | goto on_error; |
570 | 0 | } |
571 | 1.44k | if( libfshfs_attributes_btree_file_get_key_from_node_by_index( |
572 | 1.44k | node, |
573 | 1.44k | 0, |
574 | 1.44k | &last_node_key, |
575 | 1.44k | error ) == -1 ) |
576 | 19 | { |
577 | 19 | libcerror_error_set( |
578 | 19 | error, |
579 | 19 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
580 | 19 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
581 | 19 | "%s: unable to retrieve attributes B-tree key: 0.", |
582 | 19 | function ); |
583 | | |
584 | 19 | goto on_error; |
585 | 19 | } |
586 | 1.42k | node_key = last_node_key; |
587 | | |
588 | 1.42k | for( record_index = 1; |
589 | 5.56k | record_index <= node->descriptor->number_of_records; |
590 | 4.14k | record_index++ ) |
591 | 5.01k | { |
592 | 5.01k | if( record_index < node->descriptor->number_of_records ) |
593 | 4.12k | { |
594 | 4.12k | if( libfshfs_attributes_btree_file_get_key_from_node_by_index( |
595 | 4.12k | node, |
596 | 4.12k | record_index, |
597 | 4.12k | &node_key, |
598 | 4.12k | error ) == -1 ) |
599 | 15 | { |
600 | 15 | libcerror_error_set( |
601 | 15 | error, |
602 | 15 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
603 | 15 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
604 | 15 | "%s: unable to retrieve attributes B-tree key: %" PRIu16 ".", |
605 | 15 | function, |
606 | 15 | record_index ); |
607 | | |
608 | 15 | goto on_error; |
609 | 15 | } |
610 | 4.11k | if( node_key == NULL ) |
611 | 0 | { |
612 | 0 | libcerror_error_set( |
613 | 0 | error, |
614 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
615 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
616 | 0 | "%s: missing attributes B-tree key: %" PRIu16 ".", |
617 | 0 | function, |
618 | 0 | record_index ); |
619 | |
|
620 | 0 | goto on_error; |
621 | 0 | } |
622 | 4.11k | } |
623 | 4.99k | if( ( record_index == node->descriptor->number_of_records ) |
624 | 4.99k | || ( node_key->identifier >= identifier ) ) |
625 | 4.03k | { |
626 | 4.03k | if( libfshfs_attributes_btree_file_get_sub_node_number_from_key( |
627 | 4.03k | last_node_key, |
628 | 4.03k | &sub_node_number, |
629 | 4.03k | error ) != 1 ) |
630 | 6 | { |
631 | 6 | libcerror_error_set( |
632 | 6 | error, |
633 | 6 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
634 | 6 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
635 | 6 | "%s: unable to retrieve sub node number from attributes B-Tree key.", |
636 | 6 | function ); |
637 | | |
638 | 6 | goto on_error; |
639 | 6 | } |
640 | | #if defined( HAVE_DEBUG_OUTPUT ) |
641 | | if( libcnotify_verbose != 0 ) |
642 | | { |
643 | | libcnotify_printf( |
644 | | "%s: B-tree sub node number\t: %" PRIu32 "\n", |
645 | | function, |
646 | | sub_node_number ); |
647 | | |
648 | | libcnotify_printf( |
649 | | "\n" ); |
650 | | } |
651 | | #endif |
652 | 4.03k | if( libfshfs_btree_file_get_node_by_number( |
653 | 4.03k | btree_file, |
654 | 4.03k | file_io_handle, |
655 | 4.03k | node_cache, |
656 | 4.03k | recursion_depth, |
657 | 4.03k | sub_node_number, |
658 | 4.03k | &sub_node, |
659 | 4.03k | error ) == -1 ) |
660 | 108 | { |
661 | 108 | libcerror_error_set( |
662 | 108 | error, |
663 | 108 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
664 | 108 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
665 | 108 | "%s: unable to retrieve B-tree sub node: %" PRIu32 ".", |
666 | 108 | function, |
667 | 108 | sub_node_number ); |
668 | | |
669 | 108 | goto on_error; |
670 | 108 | } |
671 | 3.92k | if( libfshfs_btree_node_get_node_type( |
672 | 3.92k | sub_node, |
673 | 3.92k | &node_type, |
674 | 3.92k | error ) != 1 ) |
675 | 0 | { |
676 | 0 | libcerror_error_set( |
677 | 0 | error, |
678 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
679 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
680 | 0 | "%s: unable to determine if B-tree sub node: %" PRIu32 " type.", |
681 | 0 | function, |
682 | 0 | sub_node_number ); |
683 | |
|
684 | 0 | goto on_error; |
685 | 0 | } |
686 | 3.92k | if( node_type == 0x00 ) |
687 | 1.14k | { |
688 | 1.14k | result = libfshfs_attributes_btree_file_get_attributes_from_branch_node( |
689 | 1.14k | btree_file, |
690 | 1.14k | file_io_handle, |
691 | 1.14k | node_cache, |
692 | 1.14k | sub_node, |
693 | 1.14k | identifier, |
694 | 1.14k | attributes, |
695 | 1.14k | recursion_depth + 1, |
696 | 1.14k | error ); |
697 | 1.14k | } |
698 | 2.77k | else if( node_type == 0xff ) |
699 | 2.23k | { |
700 | 2.23k | result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node( |
701 | 2.23k | btree_file, |
702 | 2.23k | sub_node, |
703 | 2.23k | identifier, |
704 | 2.23k | attributes, |
705 | 2.23k | error ); |
706 | 2.23k | } |
707 | 3.92k | if( result != 1 ) |
708 | 506 | { |
709 | 506 | libcerror_error_set( |
710 | 506 | error, |
711 | 506 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
712 | 506 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
713 | 506 | "%s: unable to retrieve attributes from attributes B-tree node: %" PRIu32 ".", |
714 | 506 | function, |
715 | 506 | sub_node_number ); |
716 | | |
717 | 506 | goto on_error; |
718 | 506 | } |
719 | 3.41k | if( node_key->identifier > identifier ) |
720 | 235 | { |
721 | 235 | break; |
722 | 235 | } |
723 | 3.41k | } |
724 | 4.14k | last_node_key = node_key; |
725 | 4.14k | } |
726 | 786 | return( 1 ); |
727 | | |
728 | 654 | on_error: |
729 | 654 | libcdata_array_empty( |
730 | 654 | attributes, |
731 | 654 | (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free, |
732 | 654 | NULL ); |
733 | | |
734 | 654 | return( -1 ); |
735 | 1.42k | } |
736 | | |
737 | | /* Retrieves the attributes for a specific parent identifier from the attributes B-tree file |
738 | | * Returns 1 if successful or -1 on error |
739 | | */ |
740 | | int libfshfs_attributes_btree_file_get_attributes( |
741 | | libfshfs_btree_file_t *btree_file, |
742 | | libbfio_handle_t *file_io_handle, |
743 | | libfshfs_btree_node_cache_t *node_cache, |
744 | | uint32_t identifier, |
745 | | libcdata_array_t *attributes, |
746 | | libcerror_error_t **error ) |
747 | 1.09k | { |
748 | 1.09k | libfshfs_btree_node_t *root_node = NULL; |
749 | 1.09k | static char *function = "libfshfs_attributes_btree_file_get_attributes"; |
750 | 1.09k | uint8_t node_type = 0; |
751 | 1.09k | int result = 1; |
752 | | |
753 | 1.09k | if( libfshfs_btree_file_get_root_node( |
754 | 1.09k | btree_file, |
755 | 1.09k | file_io_handle, |
756 | 1.09k | node_cache, |
757 | 1.09k | &root_node, |
758 | 1.09k | error ) == -1 ) |
759 | 314 | { |
760 | 314 | libcerror_error_set( |
761 | 314 | error, |
762 | 314 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
763 | 314 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
764 | 314 | "%s: unable to retrieve B-tree root node.", |
765 | 314 | function ); |
766 | | |
767 | 314 | goto on_error; |
768 | 314 | } |
769 | 782 | if( libfshfs_btree_node_get_node_type( |
770 | 782 | root_node, |
771 | 782 | &node_type, |
772 | 782 | error ) != 1 ) |
773 | 0 | { |
774 | 0 | libcerror_error_set( |
775 | 0 | error, |
776 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
777 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
778 | 0 | "%s: unable to determine if B-tree root node type.", |
779 | 0 | function ); |
780 | |
|
781 | 0 | goto on_error; |
782 | 0 | } |
783 | 782 | if( node_type == 0x00 ) |
784 | 292 | { |
785 | 292 | result = libfshfs_attributes_btree_file_get_attributes_from_branch_node( |
786 | 292 | btree_file, |
787 | 292 | file_io_handle, |
788 | 292 | node_cache, |
789 | 292 | root_node, |
790 | 292 | identifier, |
791 | 292 | attributes, |
792 | 292 | 1, |
793 | 292 | error ); |
794 | 292 | } |
795 | 490 | else if( node_type == 0xff ) |
796 | 466 | { |
797 | 466 | result = libfshfs_attributes_btree_file_get_attributes_from_leaf_node( |
798 | 466 | btree_file, |
799 | 466 | root_node, |
800 | 466 | identifier, |
801 | 466 | attributes, |
802 | 466 | error ); |
803 | 466 | } |
804 | 782 | if( result != 1 ) |
805 | 468 | { |
806 | 468 | libcerror_error_set( |
807 | 468 | error, |
808 | 468 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
809 | 468 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
810 | 468 | "%s: unable to retrieve attributes from attributes B-tree root node.", |
811 | 468 | function ); |
812 | | |
813 | 468 | goto on_error; |
814 | 468 | } |
815 | 314 | return( 1 ); |
816 | | |
817 | 782 | on_error: |
818 | 782 | libcdata_array_empty( |
819 | 782 | attributes, |
820 | 782 | (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free, |
821 | 782 | NULL ); |
822 | | |
823 | 782 | return( -1 ); |
824 | 782 | } |
825 | | |