/src/libfsntfs/libfsntfs/libfsntfs_mft.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * MFT functions |
3 | | * |
4 | | * Copyright (C) 2010-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 <memory.h> |
24 | | #include <types.h> |
25 | | |
26 | | #include "libfsntfs_definitions.h" |
27 | | #include "libfsntfs_io_handle.h" |
28 | | #include "libfsntfs_libbfio.h" |
29 | | #include "libfsntfs_libcerror.h" |
30 | | #include "libfsntfs_libfcache.h" |
31 | | #include "libfsntfs_libfdata.h" |
32 | | #include "libfsntfs_mft.h" |
33 | | #include "libfsntfs_mft_attribute_list.h" |
34 | | #include "libfsntfs_mft_entry.h" |
35 | | #include "libfsntfs_types.h" |
36 | | |
37 | | /* Creates a MFT |
38 | | * Make sure the value mft is referencing, is set to NULL |
39 | | * Returns 1 if successful or -1 on error |
40 | | */ |
41 | | int libfsntfs_mft_initialize( |
42 | | libfsntfs_mft_t **mft, |
43 | | libfsntfs_io_handle_t *io_handle, |
44 | | size64_t mft_entry_size, |
45 | | uint8_t flags, |
46 | | libcerror_error_t **error ) |
47 | 7.66k | { |
48 | 7.66k | static char *function = "libfsntfs_mft_initialize"; |
49 | | |
50 | 7.66k | if( mft == NULL ) |
51 | 0 | { |
52 | 0 | libcerror_error_set( |
53 | 0 | error, |
54 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
55 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
56 | 0 | "%s: invalid MFT.", |
57 | 0 | function ); |
58 | |
|
59 | 0 | return( -1 ); |
60 | 0 | } |
61 | 7.66k | if( *mft != NULL ) |
62 | 0 | { |
63 | 0 | libcerror_error_set( |
64 | 0 | error, |
65 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
66 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
67 | 0 | "%s: invalid MFT value already set.", |
68 | 0 | function ); |
69 | |
|
70 | 0 | return( -1 ); |
71 | 0 | } |
72 | 7.66k | if( io_handle == NULL ) |
73 | 0 | { |
74 | 0 | libcerror_error_set( |
75 | 0 | error, |
76 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
77 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
78 | 0 | "%s: invalid IO handle.", |
79 | 0 | function ); |
80 | |
|
81 | 0 | return( -1 ); |
82 | 0 | } |
83 | 7.66k | *mft = memory_allocate_structure( |
84 | 7.66k | libfsntfs_mft_t ); |
85 | | |
86 | 7.66k | if( *mft == NULL ) |
87 | 0 | { |
88 | 0 | libcerror_error_set( |
89 | 0 | error, |
90 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
91 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
92 | 0 | "%s: unable to create MFT.", |
93 | 0 | function ); |
94 | |
|
95 | 0 | goto on_error; |
96 | 0 | } |
97 | 7.66k | if( memory_set( |
98 | 7.66k | *mft, |
99 | 7.66k | 0, |
100 | 7.66k | sizeof( libfsntfs_mft_t ) ) == NULL ) |
101 | 0 | { |
102 | 0 | libcerror_error_set( |
103 | 0 | error, |
104 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
105 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
106 | 0 | "%s: unable to clear MFT.", |
107 | 0 | function ); |
108 | |
|
109 | 0 | memory_free( |
110 | 0 | *mft ); |
111 | |
|
112 | 0 | *mft = NULL; |
113 | |
|
114 | 0 | return( -1 ); |
115 | 0 | } |
116 | 7.66k | if( libfdata_vector_initialize( |
117 | 7.66k | &( ( *mft )->mft_entry_vector ), |
118 | 7.66k | mft_entry_size, |
119 | 7.66k | (intptr_t *) io_handle, |
120 | 7.66k | NULL, |
121 | 7.66k | NULL, |
122 | 7.66k | (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_mft_entry_read_element_data, |
123 | 7.66k | NULL, |
124 | 7.66k | LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED, |
125 | 7.66k | error ) != 1 ) |
126 | 0 | { |
127 | 0 | libcerror_error_set( |
128 | 0 | error, |
129 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
130 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
131 | 0 | "%s: unable to create MFT entry vector.", |
132 | 0 | function ); |
133 | |
|
134 | 0 | goto on_error; |
135 | 0 | } |
136 | 7.66k | if( libfcache_cache_initialize( |
137 | 7.66k | &( ( *mft )->mft_entry_cache ), |
138 | 7.66k | LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_MFT_ENTRIES, |
139 | 7.66k | error ) != 1 ) |
140 | 0 | { |
141 | 0 | libcerror_error_set( |
142 | 0 | error, |
143 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
144 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
145 | 0 | "%s: unable to create MFT entry cache.", |
146 | 0 | function ); |
147 | |
|
148 | 0 | goto on_error; |
149 | 0 | } |
150 | 7.66k | if( libfcache_cache_initialize( |
151 | 7.66k | &( ( *mft )->single_mft_entry_cache ), |
152 | 7.66k | 1, |
153 | 7.66k | error ) != 1 ) |
154 | 0 | { |
155 | 0 | libcerror_error_set( |
156 | 0 | error, |
157 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
158 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
159 | 0 | "%s: unable to create signle MFT entry cache.", |
160 | 0 | function ); |
161 | |
|
162 | 0 | goto on_error; |
163 | 0 | } |
164 | 7.66k | ( *mft )->io_handle = io_handle; |
165 | 7.66k | ( *mft )->flags = flags; |
166 | | |
167 | 7.66k | return( 1 ); |
168 | | |
169 | 0 | on_error: |
170 | 0 | if( *mft != NULL ) |
171 | 0 | { |
172 | 0 | if( ( *mft )->mft_entry_cache != NULL ) |
173 | 0 | { |
174 | 0 | libfcache_cache_free( |
175 | 0 | &( ( *mft )->mft_entry_cache ), |
176 | 0 | NULL ); |
177 | 0 | } |
178 | 0 | if( ( *mft )->mft_entry_vector != NULL ) |
179 | 0 | { |
180 | 0 | libfdata_vector_free( |
181 | 0 | &( ( *mft )->mft_entry_vector ), |
182 | 0 | NULL ); |
183 | 0 | } |
184 | 0 | memory_free( |
185 | 0 | *mft ); |
186 | |
|
187 | 0 | *mft = NULL; |
188 | 0 | } |
189 | 0 | return( -1 ); |
190 | 7.66k | } |
191 | | |
192 | | /* Frees a MFT |
193 | | * Returns 1 if successful or -1 on error |
194 | | */ |
195 | | int libfsntfs_mft_free( |
196 | | libfsntfs_mft_t **mft, |
197 | | libcerror_error_t **error ) |
198 | 7.66k | { |
199 | 7.66k | static char *function = "libfsntfs_mft_free"; |
200 | 7.66k | int result = 1; |
201 | | |
202 | 7.66k | if( mft == NULL ) |
203 | 0 | { |
204 | 0 | libcerror_error_set( |
205 | 0 | error, |
206 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
207 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
208 | 0 | "%s: invalid MFT.", |
209 | 0 | function ); |
210 | |
|
211 | 0 | return( -1 ); |
212 | 0 | } |
213 | 7.66k | if( *mft != NULL ) |
214 | 7.66k | { |
215 | 7.66k | if( libfdata_vector_free( |
216 | 7.66k | &( ( *mft )->mft_entry_vector ), |
217 | 7.66k | error ) != 1 ) |
218 | 0 | { |
219 | 0 | libcerror_error_set( |
220 | 0 | error, |
221 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
222 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
223 | 0 | "%s: unable to free MFT entry vector.", |
224 | 0 | function ); |
225 | |
|
226 | 0 | result = -1; |
227 | 0 | } |
228 | 7.66k | if( libfcache_cache_free( |
229 | 7.66k | &( ( *mft )->mft_entry_cache ), |
230 | 7.66k | error ) != 1 ) |
231 | 0 | { |
232 | 0 | libcerror_error_set( |
233 | 0 | error, |
234 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
235 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
236 | 0 | "%s: unable to free MFT entry cache.", |
237 | 0 | function ); |
238 | |
|
239 | 0 | result = -1; |
240 | 0 | } |
241 | 7.66k | if( libfcache_cache_free( |
242 | 7.66k | &( ( *mft )->single_mft_entry_cache ), |
243 | 7.66k | error ) != 1 ) |
244 | 0 | { |
245 | 0 | libcerror_error_set( |
246 | 0 | error, |
247 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
248 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
249 | 0 | "%s: unable to free single MFT entry cache.", |
250 | 0 | function ); |
251 | |
|
252 | 0 | result = -1; |
253 | 0 | } |
254 | 7.66k | if( ( *mft )->attribute_list_tree != NULL ) |
255 | 365 | { |
256 | 365 | if( libcdata_btree_free( |
257 | 365 | &( ( *mft )->attribute_list_tree ), |
258 | 365 | (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free, |
259 | 365 | error ) != 1 ) |
260 | 0 | { |
261 | 0 | libcerror_error_set( |
262 | 0 | error, |
263 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
264 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
265 | 0 | "%s: unable to free attribute list tree.", |
266 | 0 | function ); |
267 | |
|
268 | 0 | result = -1; |
269 | 0 | } |
270 | 365 | } |
271 | 7.66k | memory_free( |
272 | 7.66k | *mft ); |
273 | | |
274 | 7.66k | *mft = NULL; |
275 | 7.66k | } |
276 | 7.66k | return( result ); |
277 | 7.66k | } |
278 | | |
279 | | /* Reads the attribute list data MFT entries |
280 | | * Returns 1 if successful or -1 on error |
281 | | */ |
282 | | int libfsntfs_mft_read_list_data_mft_entries( |
283 | | libfsntfs_mft_t *mft, |
284 | | libbfio_handle_t *file_io_handle, |
285 | | libcerror_error_t **error ) |
286 | 369 | { |
287 | 369 | libcdata_tree_node_t *upper_node = NULL; |
288 | 369 | libfsntfs_mft_attribute_list_t *attribute_list = NULL; |
289 | 369 | libfsntfs_mft_attribute_list_t *existing_attribute_list = NULL; |
290 | 369 | libfsntfs_mft_entry_t *mft_entry = NULL; |
291 | 369 | static char *function = "libfsntfs_mft_read_list_data_mft_entries"; |
292 | 369 | uint64_t base_record_file_reference = 0; |
293 | 369 | uint64_t file_reference = 0; |
294 | 369 | uint64_t mft_entry_index = 0; |
295 | 369 | int result = 0; |
296 | 369 | int value_index = 0; |
297 | | |
298 | 369 | if( mft == NULL ) |
299 | 0 | { |
300 | 0 | libcerror_error_set( |
301 | 0 | error, |
302 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
303 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
304 | 0 | "%s: invalid MFT.", |
305 | 0 | function ); |
306 | |
|
307 | 0 | return( -1 ); |
308 | 0 | } |
309 | 369 | if( mft->attribute_list_tree != NULL ) |
310 | 0 | { |
311 | 0 | libcerror_error_set( |
312 | 0 | error, |
313 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
314 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
315 | 0 | "%s: invalid MFT - attribute list tree value already set.", |
316 | 0 | function ); |
317 | |
|
318 | 0 | return( -1 ); |
319 | 0 | } |
320 | 369 | if( libcdata_btree_initialize( |
321 | 369 | &( mft->attribute_list_tree ), |
322 | 369 | LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES, |
323 | 369 | error ) != 1 ) |
324 | 0 | { |
325 | 0 | libcerror_error_set( |
326 | 0 | error, |
327 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
328 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
329 | 0 | "%s: unable to create attribute list B-tree.", |
330 | 0 | function ); |
331 | |
|
332 | 0 | goto on_error; |
333 | 0 | } |
334 | 369 | for( mft_entry_index = 0; |
335 | 22.5k | mft_entry_index < mft->number_of_mft_entries; |
336 | 22.1k | mft_entry_index++ ) |
337 | 22.1k | { |
338 | 22.1k | if( libfdata_vector_get_element_value_by_index( |
339 | 22.1k | mft->mft_entry_vector, |
340 | 22.1k | (intptr_t *) file_io_handle, |
341 | 22.1k | (libfdata_cache_t *) mft->mft_entry_cache, |
342 | 22.1k | (int) mft_entry_index, |
343 | 22.1k | (intptr_t **) &mft_entry, |
344 | 22.1k | 0, |
345 | 22.1k | error ) != 1 ) |
346 | 4 | { |
347 | 4 | libcerror_error_set( |
348 | 4 | error, |
349 | 4 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
350 | 4 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
351 | 4 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
352 | 4 | function, |
353 | 4 | mft_entry_index ); |
354 | | |
355 | 4 | goto on_error; |
356 | 4 | } |
357 | 22.1k | result = libfsntfs_mft_entry_get_base_record_file_reference( |
358 | 22.1k | mft_entry, |
359 | 22.1k | &base_record_file_reference, |
360 | 22.1k | error ); |
361 | | |
362 | 22.1k | if( result == -1 ) |
363 | 0 | { |
364 | 0 | libcerror_error_set( |
365 | 0 | error, |
366 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
367 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
368 | 0 | "%s: unable to retrieve base record file reference from MFT entry: %" PRIu64 ".", |
369 | 0 | function, |
370 | 0 | mft_entry_index ); |
371 | |
|
372 | 0 | goto on_error; |
373 | 0 | } |
374 | 22.1k | if( ( result == 0 ) |
375 | 22.1k | || ( base_record_file_reference == 0 ) ) |
376 | 15.1k | { |
377 | 15.1k | continue; |
378 | 15.1k | } |
379 | 6.96k | if( libfsntfs_mft_attribute_list_initialize( |
380 | 6.96k | &attribute_list, |
381 | 6.96k | base_record_file_reference, |
382 | 6.96k | error ) != 1 ) |
383 | 0 | { |
384 | 0 | libcerror_error_set( |
385 | 0 | error, |
386 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
387 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
388 | 0 | "%s: unable to create attribute list.", |
389 | 0 | function ); |
390 | |
|
391 | 0 | goto on_error; |
392 | 0 | } |
393 | 6.96k | result = libcdata_btree_insert_value( |
394 | 6.96k | mft->attribute_list_tree, |
395 | 6.96k | &value_index, |
396 | 6.96k | (intptr_t *) attribute_list, |
397 | 6.96k | (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference, |
398 | 6.96k | &upper_node, |
399 | 6.96k | (intptr_t **) &existing_attribute_list, |
400 | 6.96k | error ); |
401 | | |
402 | 6.96k | if( result == -1 ) |
403 | 0 | { |
404 | 0 | libcerror_error_set( |
405 | 0 | error, |
406 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
407 | 0 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
408 | 0 | "%s: unable to insert attribute list into tree.", |
409 | 0 | function ); |
410 | |
|
411 | 0 | goto on_error; |
412 | 0 | } |
413 | 6.96k | else if( result == 0 ) |
414 | 5.18k | { |
415 | 5.18k | if( libfsntfs_mft_attribute_list_free( |
416 | 5.18k | &attribute_list, |
417 | 5.18k | error ) != 1 ) |
418 | 0 | { |
419 | 0 | libcerror_error_set( |
420 | 0 | error, |
421 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
422 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
423 | 0 | "%s: unable to free attribute list.", |
424 | 0 | function ); |
425 | |
|
426 | 0 | goto on_error; |
427 | 0 | } |
428 | 5.18k | } |
429 | 1.77k | else |
430 | 1.77k | { |
431 | 1.77k | existing_attribute_list = attribute_list; |
432 | | |
433 | 1.77k | attribute_list = NULL; |
434 | 1.77k | } |
435 | 6.96k | if( libfsntfs_mft_entry_get_file_reference( |
436 | 6.96k | mft_entry, |
437 | 6.96k | &file_reference, |
438 | 6.96k | error ) != 1 ) |
439 | 0 | { |
440 | 0 | libcerror_error_set( |
441 | 0 | error, |
442 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
443 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
444 | 0 | "%s: unable to retrieve file reference from MFT entry: %" PRIu64 ".", |
445 | 0 | function, |
446 | 0 | mft_entry_index ); |
447 | |
|
448 | 0 | goto on_error; |
449 | 0 | } |
450 | 6.96k | if( libfsntfs_mft_attribute_list_insert_file_reference( |
451 | 6.96k | existing_attribute_list, |
452 | 6.96k | file_reference, |
453 | 6.96k | error ) == -1 ) |
454 | 0 | { |
455 | 0 | libcerror_error_set( |
456 | 0 | error, |
457 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
458 | 0 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
459 | 0 | "%s: unable to insert attribute list data file reference in attribute list.", |
460 | 0 | function ); |
461 | |
|
462 | 0 | goto on_error; |
463 | 0 | } |
464 | 6.96k | } |
465 | 365 | return( 1 ); |
466 | | |
467 | 4 | on_error: |
468 | 4 | if( attribute_list != NULL ) |
469 | 0 | { |
470 | 0 | libfsntfs_mft_attribute_list_free( |
471 | 0 | &attribute_list, |
472 | 0 | NULL ); |
473 | 0 | } |
474 | 4 | if( mft->attribute_list_tree != NULL ) |
475 | 4 | { |
476 | 4 | libcdata_btree_free( |
477 | 4 | &( mft->attribute_list_tree ), |
478 | 4 | (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free, |
479 | 4 | NULL ); |
480 | 4 | } |
481 | 4 | return( -1 ); |
482 | 369 | } |
483 | | |
484 | | /* Retrieves the number of MFT entries |
485 | | * Returns 1 if successful or -1 on error |
486 | | */ |
487 | | int libfsntfs_mft_get_number_of_entries( |
488 | | libfsntfs_mft_t *mft, |
489 | | uint64_t *number_of_entries, |
490 | | libcerror_error_t **error ) |
491 | 0 | { |
492 | 0 | static char *function = "libfsntfs_mft_get_number_of_entries"; |
493 | |
|
494 | 0 | if( mft == NULL ) |
495 | 0 | { |
496 | 0 | libcerror_error_set( |
497 | 0 | error, |
498 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
499 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
500 | 0 | "%s: invalid MFT.", |
501 | 0 | function ); |
502 | |
|
503 | 0 | return( -1 ); |
504 | 0 | } |
505 | 0 | if( number_of_entries == NULL ) |
506 | 0 | { |
507 | 0 | libcerror_error_set( |
508 | 0 | error, |
509 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
510 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
511 | 0 | "%s: invalid number of entries.", |
512 | 0 | function ); |
513 | |
|
514 | 0 | return( -1 ); |
515 | 0 | } |
516 | 0 | *number_of_entries = mft->number_of_mft_entries; |
517 | |
|
518 | 0 | return( 1 ); |
519 | 0 | } |
520 | | |
521 | | /* Retrieves the MFT entry for a specific index |
522 | | * Returns 1 if successful or -1 on error |
523 | | */ |
524 | | int libfsntfs_mft_get_mft_entry_by_index( |
525 | | libfsntfs_mft_t *mft, |
526 | | libbfio_handle_t *file_io_handle, |
527 | | uint64_t mft_entry_index, |
528 | | libfsntfs_mft_entry_t **mft_entry, |
529 | | libcerror_error_t **error ) |
530 | 3.67k | { |
531 | 3.67k | libfsntfs_mft_entry_t *safe_mft_entry = NULL; |
532 | 3.67k | static char *function = "libfsntfs_mft_get_mft_entry_by_index"; |
533 | | |
534 | 3.67k | if( mft == NULL ) |
535 | 0 | { |
536 | 0 | libcerror_error_set( |
537 | 0 | error, |
538 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
539 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
540 | 0 | "%s: invalid MFT.", |
541 | 0 | function ); |
542 | |
|
543 | 0 | return( -1 ); |
544 | 0 | } |
545 | 3.67k | if( mft_entry_index > mft->number_of_mft_entries ) |
546 | 47 | { |
547 | 47 | libcerror_error_set( |
548 | 47 | error, |
549 | 47 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
550 | 47 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
551 | 47 | "%s: invalid MFT entry index value out of bounds.", |
552 | 47 | function ); |
553 | | |
554 | 47 | return( -1 ); |
555 | 47 | } |
556 | 3.62k | if( mft_entry == NULL ) |
557 | 0 | { |
558 | 0 | libcerror_error_set( |
559 | 0 | error, |
560 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
561 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
562 | 0 | "%s: invalid MFT entry.", |
563 | 0 | function ); |
564 | |
|
565 | 0 | return( -1 ); |
566 | 0 | } |
567 | 3.62k | if( libfdata_vector_get_element_value_by_index( |
568 | 3.62k | mft->mft_entry_vector, |
569 | 3.62k | (intptr_t *) file_io_handle, |
570 | 3.62k | (libfdata_cache_t *) mft->mft_entry_cache, |
571 | 3.62k | (int) mft_entry_index, |
572 | 3.62k | (intptr_t **) &safe_mft_entry, |
573 | 3.62k | 0, |
574 | 3.62k | error ) != 1 ) |
575 | 272 | { |
576 | 272 | libcerror_error_set( |
577 | 272 | error, |
578 | 272 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
579 | 272 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
580 | 272 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
581 | 272 | function, |
582 | 272 | mft_entry_index ); |
583 | | |
584 | 272 | return( -1 ); |
585 | 272 | } |
586 | 3.35k | if( libfsntfs_mft_entry_read_attributes( |
587 | 3.35k | safe_mft_entry, |
588 | 3.35k | mft->io_handle, |
589 | 3.35k | file_io_handle, |
590 | 3.35k | mft->mft_entry_vector, |
591 | 3.35k | mft->attribute_list_tree, |
592 | 3.35k | mft->flags, |
593 | 3.35k | error ) != 1 ) |
594 | 148 | { |
595 | 148 | libcerror_error_set( |
596 | 148 | error, |
597 | 148 | LIBCERROR_ERROR_DOMAIN_IO, |
598 | 148 | LIBCERROR_IO_ERROR_READ_FAILED, |
599 | 148 | "%s: unable to read MFT entry: %d attributes.", |
600 | 148 | function, |
601 | 148 | mft_entry_index ); |
602 | | |
603 | 148 | return( -1 ); |
604 | 148 | } |
605 | 3.20k | *mft_entry = safe_mft_entry; |
606 | | |
607 | 3.20k | return( 1 ); |
608 | 3.35k | } |
609 | | |
610 | | /* Retrieves the MFT entry for a specific index |
611 | | * Returns 1 if successful or -1 on error |
612 | | */ |
613 | | int libfsntfs_mft_get_mft_entry_by_index_no_cache( |
614 | | libfsntfs_mft_t *mft, |
615 | | libbfio_handle_t *file_io_handle, |
616 | | uint64_t mft_entry_index, |
617 | | libfsntfs_mft_entry_t **mft_entry, |
618 | | libcerror_error_t **error ) |
619 | 2.14k | { |
620 | 2.14k | libfsntfs_mft_entry_t *safe_mft_entry = NULL; |
621 | 2.14k | static char *function = "libfsntfs_mft_get_mft_entry_by_index_no_cache"; |
622 | | |
623 | 2.14k | if( mft == NULL ) |
624 | 0 | { |
625 | 0 | libcerror_error_set( |
626 | 0 | error, |
627 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
628 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
629 | 0 | "%s: invalid MFT.", |
630 | 0 | function ); |
631 | |
|
632 | 0 | return( -1 ); |
633 | 0 | } |
634 | 2.14k | if( mft_entry_index > mft->number_of_mft_entries ) |
635 | 3 | { |
636 | 3 | libcerror_error_set( |
637 | 3 | error, |
638 | 3 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
639 | 3 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
640 | 3 | "%s: invalid MFT entry index value out of bounds.", |
641 | 3 | function ); |
642 | | |
643 | 3 | return( -1 ); |
644 | 3 | } |
645 | 2.13k | if( mft_entry == NULL ) |
646 | 0 | { |
647 | 0 | libcerror_error_set( |
648 | 0 | error, |
649 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
650 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
651 | 0 | "%s: invalid MFT entry.", |
652 | 0 | function ); |
653 | |
|
654 | 0 | return( -1 ); |
655 | 0 | } |
656 | 2.13k | if( libfdata_vector_get_element_value_by_index( |
657 | 2.13k | mft->mft_entry_vector, |
658 | 2.13k | (intptr_t *) file_io_handle, |
659 | 2.13k | (libfdata_cache_t *) mft->single_mft_entry_cache, |
660 | 2.13k | (int) mft_entry_index, |
661 | 2.13k | (intptr_t **) &safe_mft_entry, |
662 | 2.13k | LIBFDATA_READ_FLAG_IGNORE_CACHE, |
663 | 2.13k | error ) != 1 ) |
664 | 8 | { |
665 | 8 | libcerror_error_set( |
666 | 8 | error, |
667 | 8 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
668 | 8 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
669 | 8 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
670 | 8 | function, |
671 | 8 | mft_entry_index ); |
672 | | |
673 | 8 | return( -1 ); |
674 | 8 | } |
675 | 2.12k | if( libfsntfs_mft_entry_read_attributes( |
676 | 2.12k | safe_mft_entry, |
677 | 2.12k | mft->io_handle, |
678 | 2.12k | file_io_handle, |
679 | 2.12k | mft->mft_entry_vector, |
680 | 2.12k | mft->attribute_list_tree, |
681 | 2.12k | mft->flags, |
682 | 2.12k | error ) != 1 ) |
683 | 9 | { |
684 | 9 | libcerror_error_set( |
685 | 9 | error, |
686 | 9 | LIBCERROR_ERROR_DOMAIN_IO, |
687 | 9 | LIBCERROR_IO_ERROR_READ_FAILED, |
688 | 9 | "%s: unable to read MFT entry: %d attributes.", |
689 | 9 | function, |
690 | 9 | mft_entry_index ); |
691 | | |
692 | 9 | return( -1 ); |
693 | 9 | } |
694 | 2.12k | if( libfcache_cache_clear_value_by_index( |
695 | 2.12k | mft->single_mft_entry_cache, |
696 | 2.12k | 0, |
697 | 2.12k | error ) != 1 ) |
698 | 0 | { |
699 | 0 | libcerror_error_set( |
700 | 0 | error, |
701 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
702 | 0 | LIBCERROR_RUNTIME_ERROR_SET_FAILED, |
703 | 0 | "%s: unable to clear single MFT entry cache entry: 0.", |
704 | 0 | function ); |
705 | |
|
706 | 0 | return( -1 ); |
707 | 0 | } |
708 | 2.12k | *mft_entry = safe_mft_entry; |
709 | | |
710 | 2.12k | return( 1 ); |
711 | 2.12k | } |
712 | | |