/src/libfsntfs/libfsntfs/libfsntfs_file_system.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * File system 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 <byte_stream.h> |
24 | | #include <memory.h> |
25 | | #include <types.h> |
26 | | |
27 | | #include "libfsntfs_cluster_block.h" |
28 | | #include "libfsntfs_cluster_block_vector.h" |
29 | | #include "libfsntfs_definitions.h" |
30 | | #include "libfsntfs_file_system.h" |
31 | | #include "libfsntfs_libbfio.h" |
32 | | #include "libfsntfs_libcdata.h" |
33 | | #include "libfsntfs_libcerror.h" |
34 | | #include "libfsntfs_libcnotify.h" |
35 | | #include "libfsntfs_libcthreads.h" |
36 | | #include "libfsntfs_libuna.h" |
37 | | #include "libfsntfs_mft.h" |
38 | | #include "libfsntfs_mft_attribute_list.h" |
39 | | #include "libfsntfs_mft_entry.h" |
40 | | #include "libfsntfs_name.h" |
41 | | #include "libfsntfs_path_hint.h" |
42 | | #include "libfsntfs_security_descriptor_index.h" |
43 | | #include "libfsntfs_security_descriptor_values.h" |
44 | | |
45 | | /* Creates a file system |
46 | | * Make sure the value file_system is referencing, is set to NULL |
47 | | * Returns 1 if successful or -1 on error |
48 | | */ |
49 | | int libfsntfs_file_system_initialize( |
50 | | libfsntfs_file_system_t **file_system, |
51 | | libcerror_error_t **error ) |
52 | 9.76k | { |
53 | 9.76k | static char *function = "libfsntfs_file_system_initialize"; |
54 | | |
55 | 9.76k | if( file_system == NULL ) |
56 | 0 | { |
57 | 0 | libcerror_error_set( |
58 | 0 | error, |
59 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
60 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
61 | 0 | "%s: invalid file system.", |
62 | 0 | function ); |
63 | |
|
64 | 0 | return( -1 ); |
65 | 0 | } |
66 | 9.76k | if( *file_system != NULL ) |
67 | 0 | { |
68 | 0 | libcerror_error_set( |
69 | 0 | error, |
70 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
71 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
72 | 0 | "%s: invalid file system value already set.", |
73 | 0 | function ); |
74 | |
|
75 | 0 | return( -1 ); |
76 | 0 | } |
77 | 9.76k | *file_system = memory_allocate_structure( |
78 | 9.76k | libfsntfs_file_system_t ); |
79 | | |
80 | 9.76k | if( *file_system == NULL ) |
81 | 0 | { |
82 | 0 | libcerror_error_set( |
83 | 0 | error, |
84 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
85 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
86 | 0 | "%s: unable to create file system.", |
87 | 0 | function ); |
88 | |
|
89 | 0 | goto on_error; |
90 | 0 | } |
91 | 9.76k | if( memory_set( |
92 | 9.76k | *file_system, |
93 | 9.76k | 0, |
94 | 9.76k | sizeof( libfsntfs_file_system_t ) ) == NULL ) |
95 | 0 | { |
96 | 0 | libcerror_error_set( |
97 | 0 | error, |
98 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
99 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
100 | 0 | "%s: unable to clear file system.", |
101 | 0 | function ); |
102 | |
|
103 | 0 | memory_free( |
104 | 0 | *file_system ); |
105 | |
|
106 | 0 | *file_system = NULL; |
107 | |
|
108 | 0 | return( -1 ); |
109 | 0 | } |
110 | 9.76k | #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) |
111 | 9.76k | if( libcthreads_read_write_lock_initialize( |
112 | 9.76k | &( ( *file_system )->read_write_lock ), |
113 | 9.76k | error ) != 1 ) |
114 | 0 | { |
115 | 0 | libcerror_error_set( |
116 | 0 | error, |
117 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
118 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
119 | 0 | "%s: unable to initialize read/write lock.", |
120 | 0 | function ); |
121 | |
|
122 | 0 | goto on_error; |
123 | 0 | } |
124 | 9.76k | #endif |
125 | 9.76k | return( 1 ); |
126 | | |
127 | 0 | on_error: |
128 | 0 | if( *file_system != NULL ) |
129 | 0 | { |
130 | 0 | memory_free( |
131 | 0 | *file_system ); |
132 | |
|
133 | 0 | *file_system = NULL; |
134 | 0 | } |
135 | 0 | return( -1 ); |
136 | 9.76k | } |
137 | | |
138 | | /* Frees a file system |
139 | | * Returns 1 if successful or -1 on error |
140 | | */ |
141 | | int libfsntfs_file_system_free( |
142 | | libfsntfs_file_system_t **file_system, |
143 | | libcerror_error_t **error ) |
144 | 9.76k | { |
145 | 9.76k | static char *function = "libfsntfs_file_system_free"; |
146 | 9.76k | int result = 1; |
147 | | |
148 | 9.76k | if( file_system == NULL ) |
149 | 0 | { |
150 | 0 | libcerror_error_set( |
151 | 0 | error, |
152 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
153 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
154 | 0 | "%s: invalid file system.", |
155 | 0 | function ); |
156 | |
|
157 | 0 | return( -1 ); |
158 | 0 | } |
159 | 9.76k | if( *file_system != NULL ) |
160 | 9.76k | { |
161 | 9.76k | #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT ) |
162 | 9.76k | if( libcthreads_read_write_lock_free( |
163 | 9.76k | &( ( *file_system )->read_write_lock ), |
164 | 9.76k | error ) != 1 ) |
165 | 0 | { |
166 | 0 | libcerror_error_set( |
167 | 0 | error, |
168 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
169 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
170 | 0 | "%s: unable to free read/write lock.", |
171 | 0 | function ); |
172 | |
|
173 | 0 | result = -1; |
174 | 0 | } |
175 | 9.76k | #endif |
176 | 9.76k | if( ( *file_system )->path_hints_tree != NULL ) |
177 | 3.93k | { |
178 | 3.93k | if( libcdata_btree_free( |
179 | 3.93k | &( ( *file_system )->path_hints_tree ), |
180 | 3.93k | (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free, |
181 | 3.93k | error ) != 1 ) |
182 | 0 | { |
183 | 0 | libcerror_error_set( |
184 | 0 | error, |
185 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
186 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
187 | 0 | "%s: unable to free path hints tree.", |
188 | 0 | function ); |
189 | |
|
190 | 0 | result = -1; |
191 | 0 | } |
192 | 3.93k | } |
193 | 9.76k | if( ( *file_system )->security_descriptor_index != NULL ) |
194 | 165 | { |
195 | 165 | if( libfsntfs_security_descriptor_index_free( |
196 | 165 | &( ( *file_system )->security_descriptor_index ), |
197 | 165 | error ) != 1 ) |
198 | 0 | { |
199 | 0 | libcerror_error_set( |
200 | 0 | error, |
201 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
202 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
203 | 0 | "%s: unable to free security descriptor index.", |
204 | 0 | function ); |
205 | |
|
206 | 0 | result = -1; |
207 | 0 | } |
208 | 165 | } |
209 | 9.76k | if( ( *file_system )->mft != NULL ) |
210 | 7.52k | { |
211 | 7.52k | if( libfsntfs_mft_free( |
212 | 7.52k | &( ( *file_system )->mft ), |
213 | 7.52k | error ) != 1 ) |
214 | 0 | { |
215 | 0 | libcerror_error_set( |
216 | 0 | error, |
217 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
218 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
219 | 0 | "%s: unable to free MFT.", |
220 | 0 | function ); |
221 | |
|
222 | 0 | result = -1; |
223 | 0 | } |
224 | 7.52k | } |
225 | 9.76k | memory_free( |
226 | 9.76k | *file_system ); |
227 | | |
228 | 9.76k | *file_system = NULL; |
229 | 9.76k | } |
230 | 9.76k | return( result ); |
231 | 9.76k | } |
232 | | |
233 | | /* Reads the MFT |
234 | | * Returns 1 if successful or -1 on error |
235 | | */ |
236 | | int libfsntfs_file_system_read_mft( |
237 | | libfsntfs_file_system_t *file_system, |
238 | | libfsntfs_io_handle_t *io_handle, |
239 | | libbfio_handle_t *file_io_handle, |
240 | | off64_t mft_offset, |
241 | | uint8_t flags, |
242 | | libcerror_error_t **error ) |
243 | 9.65k | { |
244 | 9.65k | libfsntfs_data_run_t *data_run = NULL; |
245 | 9.65k | libfsntfs_mft_attribute_t *data_attribute = NULL; |
246 | 9.65k | libfsntfs_mft_attribute_t *last_data_attribute = NULL; |
247 | 9.65k | libfsntfs_mft_entry_t *mft_entry = NULL; |
248 | 9.65k | static char *function = "libfsntfs_file_system_read_mft"; |
249 | 9.65k | size64_t mft_size = 0; |
250 | 9.65k | uint64_t file_reference = 0; |
251 | 9.65k | uint64_t number_of_mft_entries = 0; |
252 | 9.65k | uint16_t attribute_data_flags = 0; |
253 | 9.65k | int attribute_index = 0; |
254 | 9.65k | int data_run_index = 0; |
255 | 9.65k | int file_reference_index = 0; |
256 | 9.65k | int number_of_data_runs = 0; |
257 | 9.65k | int number_of_file_entries = 0; |
258 | 9.65k | int segment_index = 0; |
259 | | |
260 | 9.65k | if( file_system == NULL ) |
261 | 0 | { |
262 | 0 | libcerror_error_set( |
263 | 0 | error, |
264 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
265 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
266 | 0 | "%s: invalid file system.", |
267 | 0 | function ); |
268 | |
|
269 | 0 | return( -1 ); |
270 | 0 | } |
271 | 9.65k | if( file_system->mft != NULL ) |
272 | 0 | { |
273 | 0 | libcerror_error_set( |
274 | 0 | error, |
275 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
276 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
277 | 0 | "%s: invalid file system - MFT value already set.", |
278 | 0 | function ); |
279 | |
|
280 | 0 | return( -1 ); |
281 | 0 | } |
282 | 9.65k | if( io_handle == NULL ) |
283 | 0 | { |
284 | 0 | libcerror_error_set( |
285 | 0 | error, |
286 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
287 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
288 | 0 | "%s: invalid IO handle.", |
289 | 0 | function ); |
290 | |
|
291 | 0 | return( -1 ); |
292 | 0 | } |
293 | 9.65k | if( mft_offset < 0 ) |
294 | 0 | { |
295 | 0 | libcerror_error_set( |
296 | 0 | error, |
297 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
298 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
299 | 0 | "%s: invalid MFT offset value out of bounds.", |
300 | 0 | function ); |
301 | |
|
302 | 0 | goto on_error; |
303 | 0 | } |
304 | 9.65k | if( mft_size > (size64_t) INT64_MAX ) |
305 | 0 | { |
306 | 0 | libcerror_error_set( |
307 | 0 | error, |
308 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
309 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM, |
310 | 0 | "%s: invalid MFT size value exceeds maximum.", |
311 | 0 | function ); |
312 | |
|
313 | 0 | return( -1 ); |
314 | 0 | } |
315 | 9.65k | if( libfsntfs_mft_entry_initialize( |
316 | 9.65k | &mft_entry, |
317 | 9.65k | error ) != 1 ) |
318 | 0 | { |
319 | 0 | libcerror_error_set( |
320 | 0 | error, |
321 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
322 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
323 | 0 | "%s: unable to create MFT entry.", |
324 | 0 | function ); |
325 | |
|
326 | 0 | goto on_error; |
327 | 0 | } |
328 | 9.65k | if( libfsntfs_mft_entry_read_file_io_handle( |
329 | 9.65k | mft_entry, |
330 | 9.65k | file_io_handle, |
331 | 9.65k | mft_offset, |
332 | 9.65k | io_handle->mft_entry_size, |
333 | 9.65k | LIBFSNTFS_MFT_ENTRY_INDEX_MFT, |
334 | 9.65k | error ) != 1 ) |
335 | 419 | { |
336 | 419 | libcerror_error_set( |
337 | 419 | error, |
338 | 419 | LIBCERROR_ERROR_DOMAIN_IO, |
339 | 419 | LIBCERROR_IO_ERROR_READ_FAILED, |
340 | 419 | "%s: unable to read MFT entry: %d.", |
341 | 419 | function, |
342 | 419 | LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); |
343 | | |
344 | 419 | goto on_error; |
345 | 419 | } |
346 | 9.23k | if( mft_entry->is_empty == 0 ) |
347 | 8.90k | { |
348 | 8.90k | if( libfsntfs_mft_entry_read_attributes_data( |
349 | 8.90k | mft_entry, |
350 | 8.90k | io_handle, |
351 | 8.90k | mft_entry->data, |
352 | 8.90k | mft_entry->data_size, |
353 | 8.90k | error ) != 1 ) |
354 | 1.34k | { |
355 | 1.34k | libcerror_error_set( |
356 | 1.34k | error, |
357 | 1.34k | LIBCERROR_ERROR_DOMAIN_IO, |
358 | 1.34k | LIBCERROR_IO_ERROR_READ_FAILED, |
359 | 1.34k | "%s: unable to read attributes of MFT entry: %d.", |
360 | 1.34k | function, |
361 | 1.34k | LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); |
362 | | |
363 | 1.34k | goto on_error; |
364 | 1.34k | } |
365 | 8.90k | } |
366 | 7.89k | if( libfsntfs_mft_attribute_get_data_flags( |
367 | 7.89k | mft_entry->data_attribute, |
368 | 7.89k | &attribute_data_flags, |
369 | 7.89k | error ) != 1 ) |
370 | 356 | { |
371 | 356 | libcerror_error_set( |
372 | 356 | error, |
373 | 356 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
374 | 356 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
375 | 356 | "%s: unable to retrieve attribute data flags.", |
376 | 356 | function ); |
377 | | |
378 | 356 | goto on_error; |
379 | 356 | } |
380 | 7.53k | if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 ) |
381 | 7 | { |
382 | 7 | libcerror_error_set( |
383 | 7 | error, |
384 | 7 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
385 | 7 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
386 | 7 | "%s: unsupported compressed attribute data.", |
387 | 7 | function ); |
388 | | |
389 | 7 | goto on_error; |
390 | 7 | } |
391 | 7.52k | if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) |
392 | 381 | { |
393 | 381 | if( libbfio_handle_get_size( |
394 | 381 | file_io_handle, |
395 | 381 | &mft_size, |
396 | 381 | error ) != 1 ) |
397 | 0 | { |
398 | 0 | libcerror_error_set( |
399 | 0 | error, |
400 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
401 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
402 | 0 | "%s: unable to retrieve $MFT metadata file size.", |
403 | 0 | function ); |
404 | |
|
405 | 0 | goto on_error; |
406 | 0 | } |
407 | 381 | } |
408 | 7.14k | else |
409 | 7.14k | { |
410 | 7.14k | if( libfsntfs_mft_attribute_get_data_size( |
411 | 7.14k | mft_entry->data_attribute, |
412 | 7.14k | &mft_size, |
413 | 7.14k | error ) != 1 ) |
414 | 0 | { |
415 | 0 | libcerror_error_set( |
416 | 0 | error, |
417 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
418 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
419 | 0 | "%s: unable to retrieve data size of MFT entry: %d.", |
420 | 0 | function, |
421 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_MFT ); |
422 | |
|
423 | 0 | goto on_error; |
424 | 0 | } |
425 | 7.14k | } |
426 | 7.52k | if( libfsntfs_mft_initialize( |
427 | 7.52k | &( file_system->mft ), |
428 | 7.52k | io_handle, |
429 | 7.52k | (size64_t) io_handle->mft_entry_size, |
430 | 7.52k | flags, |
431 | 7.52k | error ) != 1 ) |
432 | 0 | { |
433 | 0 | libcerror_error_set( |
434 | 0 | error, |
435 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
436 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
437 | 0 | "%s: unable to create MFT.", |
438 | 0 | function ); |
439 | |
|
440 | 0 | goto on_error; |
441 | 0 | } |
442 | 7.52k | if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 ) |
443 | 381 | { |
444 | 381 | if( libfdata_vector_append_segment( |
445 | 381 | file_system->mft->mft_entry_vector, |
446 | 381 | &segment_index, |
447 | 381 | 0, |
448 | 381 | 0, |
449 | 381 | mft_size, |
450 | 381 | 0, |
451 | 381 | error ) != 1 ) |
452 | 0 | { |
453 | 0 | libcerror_error_set( |
454 | 0 | error, |
455 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
456 | 0 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
457 | 0 | "%s: unable to append $MFT metadata file range to MFT entry vector.", |
458 | 0 | function ); |
459 | |
|
460 | 0 | goto on_error; |
461 | 0 | } |
462 | 381 | } |
463 | 7.14k | else |
464 | 7.14k | { |
465 | 7.14k | if( libfsntfs_mft_attribute_get_number_of_data_runs( |
466 | 7.14k | mft_entry->data_attribute, |
467 | 7.14k | &number_of_data_runs, |
468 | 7.14k | error ) != 1 ) |
469 | 0 | { |
470 | 0 | libcerror_error_set( |
471 | 0 | error, |
472 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
473 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
474 | 0 | "%s: unable to retrieve number of data runs.", |
475 | 0 | function ); |
476 | |
|
477 | 0 | goto on_error; |
478 | 0 | } |
479 | 7.14k | for( data_run_index = 0; |
480 | 247k | data_run_index < number_of_data_runs; |
481 | 240k | data_run_index++ ) |
482 | 240k | { |
483 | 240k | if( libfsntfs_mft_attribute_get_data_run_by_index( |
484 | 240k | mft_entry->data_attribute, |
485 | 240k | data_run_index, |
486 | 240k | &data_run, |
487 | 240k | error ) != 1 ) |
488 | 0 | { |
489 | 0 | libcerror_error_set( |
490 | 0 | error, |
491 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
492 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
493 | 0 | "%s: unable to data run: %d.", |
494 | 0 | function, |
495 | 0 | data_run_index ); |
496 | |
|
497 | 0 | goto on_error; |
498 | 0 | } |
499 | 240k | if( data_run == NULL ) |
500 | 0 | { |
501 | 0 | libcerror_error_set( |
502 | 0 | error, |
503 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
504 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
505 | 0 | "%s: missing data run: %d.", |
506 | 0 | data_run_index ); |
507 | |
|
508 | 0 | goto on_error; |
509 | 0 | } |
510 | 240k | if( libfdata_vector_append_segment( |
511 | 240k | file_system->mft->mft_entry_vector, |
512 | 240k | &segment_index, |
513 | 240k | 0, |
514 | 240k | data_run->start_offset, |
515 | 240k | data_run->size, |
516 | 240k | 0, |
517 | 240k | error ) != 1 ) |
518 | 127 | { |
519 | 127 | libcerror_error_set( |
520 | 127 | error, |
521 | 127 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
522 | 127 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
523 | 127 | "%s: unable to append data run: %d to MFT entry vector.", |
524 | 127 | function, |
525 | 127 | data_run_index ); |
526 | | |
527 | 127 | goto on_error; |
528 | 127 | } |
529 | 240k | } |
530 | 7.01k | last_data_attribute = mft_entry->data_attribute; |
531 | 7.01k | } |
532 | 7.40k | if( ( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) |
533 | 7.40k | && ( mft_entry->list_attribute != NULL ) ) |
534 | 3.97k | { |
535 | 3.97k | if( libfsntfs_mft_entry_read_attribute_list( |
536 | 3.97k | mft_entry, |
537 | 3.97k | io_handle, |
538 | 3.97k | file_io_handle, |
539 | 3.97k | error ) != 1 ) |
540 | 2.85k | { |
541 | 2.85k | libcerror_error_set( |
542 | 2.85k | error, |
543 | 2.85k | LIBCERROR_ERROR_DOMAIN_IO, |
544 | 2.85k | LIBCERROR_IO_ERROR_READ_FAILED, |
545 | 2.85k | "%s: unable to read attribute list.", |
546 | 2.85k | function ); |
547 | | |
548 | 2.85k | goto on_error; |
549 | 2.85k | } |
550 | 1.12k | if( libfsntfs_mft_attribute_list_get_number_of_file_references( |
551 | 1.12k | mft_entry->attribute_list, |
552 | 1.12k | &number_of_file_entries, |
553 | 1.12k | error ) != 1 ) |
554 | 0 | { |
555 | 0 | libcerror_error_set( |
556 | 0 | error, |
557 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
558 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
559 | 0 | "%s: unable to retrieve number of attribute list data MFT entries.", |
560 | 0 | function ); |
561 | |
|
562 | 0 | goto on_error; |
563 | 0 | } |
564 | 1.12k | for( file_reference_index = 0; |
565 | 1.64k | file_reference_index < number_of_file_entries; |
566 | 1.12k | file_reference_index++ ) |
567 | 1.05k | { |
568 | 1.05k | if( libfsntfs_mft_attribute_list_get_file_reference_by_index( |
569 | 1.05k | mft_entry->attribute_list, |
570 | 1.05k | file_reference_index, |
571 | 1.05k | &file_reference, |
572 | 1.05k | error ) != 1 ) |
573 | 0 | { |
574 | 0 | libcerror_error_set( |
575 | 0 | error, |
576 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
577 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
578 | 0 | "%s: unable to retrieve attribute list data MFT entry: %d.", |
579 | 0 | function, |
580 | 0 | file_reference_index ); |
581 | |
|
582 | 0 | goto on_error; |
583 | 0 | } |
584 | 1.05k | if( libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index( |
585 | 1.05k | mft_entry, |
586 | 1.05k | io_handle, |
587 | 1.05k | file_io_handle, |
588 | 1.05k | file_system->mft->mft_entry_vector, |
589 | 1.05k | file_system->mft->mft_entry_cache, |
590 | 1.05k | file_reference, |
591 | 1.05k | error ) != 1 ) |
592 | 526 | { |
593 | 526 | libcerror_error_set( |
594 | 526 | error, |
595 | 526 | LIBCERROR_ERROR_DOMAIN_IO, |
596 | 526 | LIBCERROR_IO_ERROR_READ_FAILED, |
597 | 526 | "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".", |
598 | 526 | function, |
599 | 526 | file_reference & 0xffffffffffffUL, |
600 | 526 | file_reference >> 48 ); |
601 | | |
602 | 526 | goto on_error; |
603 | 526 | } |
604 | 531 | if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 ) |
605 | 531 | { |
606 | 531 | if( libfsntfs_mft_attribute_get_next_attribute( |
607 | 531 | last_data_attribute, |
608 | 531 | &data_attribute, |
609 | 531 | error ) != 1 ) |
610 | 0 | { |
611 | 0 | libcerror_error_set( |
612 | 0 | error, |
613 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
614 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
615 | 0 | "%s: unable to retrieve next data attribute: %d.", |
616 | 0 | function, |
617 | 0 | attribute_index ); |
618 | |
|
619 | 0 | goto on_error; |
620 | 0 | } |
621 | 531 | if( data_attribute != NULL ) |
622 | 398 | { |
623 | 398 | attribute_index++; |
624 | | |
625 | 398 | if( libfsntfs_mft_attribute_get_number_of_data_runs( |
626 | 398 | data_attribute, |
627 | 398 | &number_of_data_runs, |
628 | 398 | error ) != 1 ) |
629 | 0 | { |
630 | 0 | libcerror_error_set( |
631 | 0 | error, |
632 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
633 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
634 | 0 | "%s: unable to retrieve number of data runs.", |
635 | 0 | function ); |
636 | |
|
637 | 0 | goto on_error; |
638 | 0 | } |
639 | 398 | for( data_run_index = 0; |
640 | 115k | data_run_index < number_of_data_runs; |
641 | 115k | data_run_index++ ) |
642 | 115k | { |
643 | 115k | if( libfsntfs_mft_attribute_get_data_run_by_index( |
644 | 115k | data_attribute, |
645 | 115k | data_run_index, |
646 | 115k | &data_run, |
647 | 115k | error ) != 1 ) |
648 | 0 | { |
649 | 0 | libcerror_error_set( |
650 | 0 | error, |
651 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
652 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
653 | 0 | "%s: unable to retrieve data run: %d.", |
654 | 0 | function, |
655 | 0 | data_run_index ); |
656 | |
|
657 | 0 | goto on_error; |
658 | 0 | } |
659 | 115k | if( data_run == NULL ) |
660 | 0 | { |
661 | 0 | libcerror_error_set( |
662 | 0 | error, |
663 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
664 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
665 | 0 | "%s: missing data run: %d.", |
666 | 0 | data_run_index ); |
667 | |
|
668 | 0 | goto on_error; |
669 | 0 | } |
670 | 115k | if( libfdata_vector_append_segment( |
671 | 115k | file_system->mft->mft_entry_vector, |
672 | 115k | &segment_index, |
673 | 115k | 0, |
674 | 115k | data_run->start_offset, |
675 | 115k | data_run->size, |
676 | 115k | 0, |
677 | 115k | error ) != 1 ) |
678 | 11 | { |
679 | 11 | libcerror_error_set( |
680 | 11 | error, |
681 | 11 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
682 | 11 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
683 | 11 | "%s: unable to append data run: %d to MFT entry vector.", |
684 | 11 | function, |
685 | 11 | data_run_index ); |
686 | | |
687 | 11 | goto on_error; |
688 | 11 | } |
689 | 115k | } |
690 | 387 | last_data_attribute = data_attribute; |
691 | 387 | } |
692 | 531 | } |
693 | 531 | } |
694 | 1.12k | } |
695 | 4.01k | number_of_mft_entries = (uint64_t) ( mft_size / io_handle->mft_entry_size ); |
696 | | |
697 | 4.01k | if( number_of_mft_entries > (uint64_t) INT_MAX ) |
698 | 74 | { |
699 | 74 | libcerror_error_set( |
700 | 74 | error, |
701 | 74 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
702 | 74 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
703 | 74 | "%s: invalid number of MFT entries value out of bounds.", |
704 | 74 | function ); |
705 | | |
706 | 74 | goto on_error; |
707 | 74 | } |
708 | 3.93k | file_system->mft->number_of_mft_entries = number_of_mft_entries; |
709 | | |
710 | 3.93k | if( libfsntfs_mft_entry_free( |
711 | 3.93k | &mft_entry, |
712 | 3.93k | error ) != 1 ) |
713 | 0 | { |
714 | 0 | libcerror_error_set( |
715 | 0 | error, |
716 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
717 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
718 | 0 | "%s: unable to free MFT entry.", |
719 | 0 | function ); |
720 | |
|
721 | 0 | goto on_error; |
722 | 0 | } |
723 | 3.93k | if( libcdata_btree_initialize( |
724 | 3.93k | &( file_system->path_hints_tree ), |
725 | 3.93k | LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES, |
726 | 3.93k | error ) != 1 ) |
727 | 0 | { |
728 | 0 | libcerror_error_set( |
729 | 0 | error, |
730 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
731 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
732 | 0 | "%s: unable to create path hints B-tree.", |
733 | 0 | function ); |
734 | |
|
735 | 0 | goto on_error; |
736 | 0 | } |
737 | 3.93k | return( 1 ); |
738 | | |
739 | 5.72k | on_error: |
740 | 5.72k | if( file_system->path_hints_tree != NULL ) |
741 | 0 | { |
742 | 0 | libcdata_btree_free( |
743 | 0 | &( file_system->path_hints_tree ), |
744 | 0 | (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free, |
745 | 0 | NULL ); |
746 | 0 | } |
747 | 5.72k | if( mft_entry != NULL ) |
748 | 5.72k | { |
749 | 5.72k | libfsntfs_mft_entry_free( |
750 | 5.72k | &mft_entry, |
751 | 5.72k | NULL ); |
752 | 5.72k | } |
753 | 5.72k | return( -1 ); |
754 | 3.93k | } |
755 | | |
756 | | /* Reads the bitmap file entry |
757 | | * Returns 1 if successful or -1 on error |
758 | | */ |
759 | | int libfsntfs_file_system_read_bitmap( |
760 | | libfsntfs_file_system_t *file_system, |
761 | | libfsntfs_io_handle_t *io_handle, |
762 | | libbfio_handle_t *file_io_handle, |
763 | | libcerror_error_t **error ) |
764 | 0 | { |
765 | 0 | libfcache_cache_t *cluster_block_cache = NULL; |
766 | 0 | libfdata_vector_t *cluster_block_vector = NULL; |
767 | 0 | libfsntfs_cluster_block_t *cluster_block = NULL; |
768 | 0 | libfsntfs_mft_entry_t *mft_entry = NULL; |
769 | 0 | static char *function = "libfsntfs_file_system_read_bitmap"; |
770 | 0 | size_t cluster_block_data_offset = 0; |
771 | 0 | off64_t bitmap_offset = 0; |
772 | 0 | off64_t start_offset = 0; |
773 | 0 | uint32_t value_32bit = 0; |
774 | 0 | uint8_t bit_index = 0; |
775 | 0 | int cluster_block_index = 0; |
776 | 0 | int number_of_cluster_blocks = 0; |
777 | |
|
778 | 0 | if( file_system == NULL ) |
779 | 0 | { |
780 | 0 | libcerror_error_set( |
781 | 0 | error, |
782 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
783 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
784 | 0 | "%s: invalid file system.", |
785 | 0 | function ); |
786 | |
|
787 | 0 | return( -1 ); |
788 | 0 | } |
789 | 0 | if( io_handle == NULL ) |
790 | 0 | { |
791 | 0 | libcerror_error_set( |
792 | 0 | error, |
793 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
794 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
795 | 0 | "%s: invalid IO handle.", |
796 | 0 | function ); |
797 | |
|
798 | 0 | return( -1 ); |
799 | 0 | } |
800 | 0 | if( libfsntfs_mft_get_mft_entry_by_index( |
801 | 0 | file_system->mft, |
802 | 0 | file_io_handle, |
803 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP, |
804 | 0 | &mft_entry, |
805 | 0 | error ) != 1 ) |
806 | 0 | { |
807 | 0 | libcerror_error_set( |
808 | 0 | error, |
809 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
810 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
811 | 0 | "%s: unable to retrieve MFT entry: %d.", |
812 | 0 | function, |
813 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); |
814 | |
|
815 | 0 | goto on_error; |
816 | 0 | } |
817 | 0 | if( mft_entry == NULL ) |
818 | 0 | { |
819 | 0 | libcerror_error_set( |
820 | 0 | error, |
821 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
822 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
823 | 0 | "%s: missing MFT entry: %d.", |
824 | 0 | function, |
825 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); |
826 | |
|
827 | 0 | goto on_error; |
828 | 0 | } |
829 | 0 | if( mft_entry->data_attribute == NULL ) |
830 | 0 | { |
831 | 0 | libcerror_error_set( |
832 | 0 | error, |
833 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
834 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
835 | 0 | "%s: invalid MFT entry: %d - missing data attribute.", |
836 | 0 | function, |
837 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP ); |
838 | |
|
839 | 0 | goto on_error; |
840 | 0 | } |
841 | 0 | if( libfsntfs_cluster_block_vector_initialize( |
842 | 0 | &cluster_block_vector, |
843 | 0 | io_handle, |
844 | 0 | mft_entry->data_attribute, |
845 | 0 | error ) != 1 ) |
846 | 0 | { |
847 | 0 | libcerror_error_set( |
848 | 0 | error, |
849 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
850 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
851 | 0 | "%s: unable to create cluster block vector.", |
852 | 0 | function ); |
853 | |
|
854 | 0 | goto on_error; |
855 | 0 | } |
856 | 0 | if( libfcache_cache_initialize( |
857 | 0 | &cluster_block_cache, |
858 | 0 | 1, |
859 | 0 | error ) != 1 ) |
860 | 0 | { |
861 | 0 | libcerror_error_set( |
862 | 0 | error, |
863 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
864 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
865 | 0 | "%s: unable to create cluster block cache.", |
866 | 0 | function ); |
867 | |
|
868 | 0 | goto on_error; |
869 | 0 | } |
870 | 0 | if( libfdata_vector_get_number_of_elements( |
871 | 0 | cluster_block_vector, |
872 | 0 | &number_of_cluster_blocks, |
873 | 0 | error ) != 1 ) |
874 | 0 | { |
875 | 0 | libcerror_error_set( |
876 | 0 | error, |
877 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
878 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
879 | 0 | "%s: unable to retrieve number of cluster blocks.", |
880 | 0 | function ); |
881 | |
|
882 | 0 | goto on_error; |
883 | 0 | } |
884 | 0 | for( cluster_block_index = 0; |
885 | 0 | cluster_block_index < number_of_cluster_blocks; |
886 | 0 | cluster_block_index++ ) |
887 | 0 | { |
888 | 0 | if( libfdata_vector_get_element_value_by_index( |
889 | 0 | cluster_block_vector, |
890 | 0 | (intptr_t *) file_io_handle, |
891 | 0 | (libfdata_cache_t *) cluster_block_cache, |
892 | 0 | cluster_block_index, |
893 | 0 | (intptr_t **) &cluster_block, |
894 | 0 | 0, |
895 | 0 | error ) != 1 ) |
896 | 0 | { |
897 | 0 | libcerror_error_set( |
898 | 0 | error, |
899 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
900 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
901 | 0 | "%s: unable to retrieve cluster block: %d from vector.", |
902 | 0 | function, |
903 | 0 | cluster_block_index ); |
904 | |
|
905 | 0 | goto on_error; |
906 | 0 | } |
907 | 0 | if( cluster_block == NULL ) |
908 | 0 | { |
909 | 0 | libcerror_error_set( |
910 | 0 | error, |
911 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
912 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
913 | 0 | "%s: missing cluster block: %d.", |
914 | 0 | function, |
915 | 0 | cluster_block_index ); |
916 | |
|
917 | 0 | goto on_error; |
918 | 0 | } |
919 | 0 | if( cluster_block->data == NULL ) |
920 | 0 | { |
921 | 0 | libcerror_error_set( |
922 | 0 | error, |
923 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
924 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
925 | 0 | "%s: invalid cluster block: %d - missing data.", |
926 | 0 | function, |
927 | 0 | cluster_block_index ); |
928 | |
|
929 | 0 | goto on_error; |
930 | 0 | } |
931 | 0 | if( ( ( cluster_block->data_size % 4 ) != 0 ) |
932 | 0 | || ( cluster_block->data_size > (size_t) SSIZE_MAX ) ) |
933 | 0 | { |
934 | 0 | libcerror_error_set( |
935 | 0 | error, |
936 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
937 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
938 | 0 | "%s: cluster block: %d data size value out of bounds.", |
939 | 0 | function, |
940 | 0 | cluster_block_index ); |
941 | |
|
942 | 0 | goto on_error; |
943 | 0 | } |
944 | | #if defined( HAVE_DEBUG_OUTPUT ) |
945 | | if( libcnotify_verbose != 0 ) |
946 | | { |
947 | | libcnotify_printf( |
948 | | "%s: bitmap segment: %d data:\n", |
949 | | function, |
950 | | cluster_block_index ); |
951 | | libcnotify_print_data( |
952 | | cluster_block->data, |
953 | | cluster_block->data_size, |
954 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
955 | | } |
956 | | #endif |
957 | 0 | cluster_block_data_offset = 0; |
958 | 0 | start_offset = -1; |
959 | |
|
960 | 0 | while( cluster_block_data_offset < cluster_block->data_size ) |
961 | 0 | { |
962 | 0 | byte_stream_copy_to_uint32_little_endian( |
963 | 0 | &( cluster_block->data[ cluster_block_data_offset ] ), |
964 | 0 | value_32bit ); |
965 | |
|
966 | 0 | for( bit_index = 0; |
967 | 0 | bit_index < 32; |
968 | 0 | bit_index++ ) |
969 | 0 | { |
970 | 0 | if( ( value_32bit & 0x00000001UL ) == 0 ) |
971 | 0 | { |
972 | 0 | if( start_offset >= 0 ) |
973 | 0 | { |
974 | | #if defined( HAVE_DEBUG_OUTPUT ) |
975 | | if( libcnotify_verbose != 0 ) |
976 | | { |
977 | | libcnotify_printf( |
978 | | "%s: offset range\t\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n", |
979 | | function, |
980 | | start_offset, |
981 | | bitmap_offset, |
982 | | bitmap_offset - start_offset ); |
983 | | } |
984 | | #endif |
985 | | /* |
986 | | if( libfsntfs_offset_list_append_offset( |
987 | | offset_list, |
988 | | start_offset, |
989 | | bitmap_offset - start_offset, |
990 | | 1, |
991 | | error ) != 1 ) |
992 | | { |
993 | | libcerror_error_set( |
994 | | error, |
995 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
996 | | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
997 | | "%s: unable to append offset range to offset list.", |
998 | | function ); |
999 | | |
1000 | | goto on_error; |
1001 | | } |
1002 | | */ |
1003 | 0 | start_offset = -1; |
1004 | 0 | } |
1005 | 0 | } |
1006 | 0 | else |
1007 | 0 | { |
1008 | 0 | if( start_offset < 0 ) |
1009 | 0 | { |
1010 | 0 | start_offset = bitmap_offset; |
1011 | 0 | } |
1012 | 0 | } |
1013 | 0 | bitmap_offset += io_handle->cluster_block_size; |
1014 | |
|
1015 | 0 | value_32bit >>= 1; |
1016 | 0 | } |
1017 | 0 | cluster_block_data_offset += 4; |
1018 | 0 | } |
1019 | 0 | if( start_offset >= 0 ) |
1020 | 0 | { |
1021 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1022 | | if( libcnotify_verbose != 0 ) |
1023 | | { |
1024 | | libcnotify_printf( |
1025 | | "%s: offset range\t\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n", |
1026 | | function, |
1027 | | start_offset, |
1028 | | bitmap_offset, |
1029 | | bitmap_offset - start_offset ); |
1030 | | } |
1031 | | #endif |
1032 | | /* TODO |
1033 | | if( libfsntfs_offset_list_append_offset( |
1034 | | offset_list, |
1035 | | start_offset, |
1036 | | bitmap_offset - start_offset, |
1037 | | 1, |
1038 | | error ) != 1 ) |
1039 | | { |
1040 | | libcerror_error_set( |
1041 | | error, |
1042 | | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1043 | | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
1044 | | "%s: unable to append offset range to offset list.", |
1045 | | function ); |
1046 | | |
1047 | | goto on_error; |
1048 | | } |
1049 | | */ |
1050 | 0 | } |
1051 | | #if defined( HAVE_DEBUG_OUTPUT ) |
1052 | | if( libcnotify_verbose != 0 ) |
1053 | | { |
1054 | | libcnotify_printf( |
1055 | | "\n" ); |
1056 | | } |
1057 | | #endif |
1058 | 0 | } |
1059 | 0 | if( libfdata_vector_free( |
1060 | 0 | &cluster_block_vector, |
1061 | 0 | error ) != 1 ) |
1062 | 0 | { |
1063 | 0 | libcerror_error_set( |
1064 | 0 | error, |
1065 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1066 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1067 | 0 | "%s: unable to free cluster block vector.", |
1068 | 0 | function ); |
1069 | |
|
1070 | 0 | goto on_error; |
1071 | 0 | } |
1072 | 0 | if( libfcache_cache_free( |
1073 | 0 | &cluster_block_cache, |
1074 | 0 | error ) != 1 ) |
1075 | 0 | { |
1076 | 0 | libcerror_error_set( |
1077 | 0 | error, |
1078 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1079 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1080 | 0 | "%s: unable to free cluster block cache.", |
1081 | 0 | function ); |
1082 | |
|
1083 | 0 | goto on_error; |
1084 | 0 | } |
1085 | 0 | return( 1 ); |
1086 | | |
1087 | 0 | on_error: |
1088 | 0 | if( cluster_block_cache != NULL ) |
1089 | 0 | { |
1090 | 0 | libfcache_cache_free( |
1091 | 0 | &cluster_block_cache, |
1092 | 0 | NULL ); |
1093 | 0 | } |
1094 | 0 | if( cluster_block_vector != NULL ) |
1095 | 0 | { |
1096 | 0 | libfdata_vector_free( |
1097 | 0 | &cluster_block_vector, |
1098 | 0 | NULL ); |
1099 | 0 | } |
1100 | 0 | return( -1 ); |
1101 | 0 | } |
1102 | | |
1103 | | /* Reads the security descriptors |
1104 | | * Returns 1 if successful or -1 on error |
1105 | | */ |
1106 | | int libfsntfs_file_system_read_security_descriptors( |
1107 | | libfsntfs_file_system_t *file_system, |
1108 | | libfsntfs_io_handle_t *io_handle, |
1109 | | libbfio_handle_t *file_io_handle, |
1110 | | libcerror_error_t **error ) |
1111 | 3.55k | { |
1112 | 3.55k | libfsntfs_file_name_values_t *file_name_values = NULL; |
1113 | 3.55k | libfsntfs_mft_attribute_t *data_attribute = NULL; |
1114 | 3.55k | libfsntfs_mft_attribute_t *mft_attribute = NULL; |
1115 | 3.55k | libfsntfs_mft_entry_t *mft_entry = NULL; |
1116 | 3.55k | static char *function = "libfsntfs_file_system_read_security_descriptors"; |
1117 | 3.55k | int result = 0; |
1118 | | |
1119 | 3.55k | if( file_system == NULL ) |
1120 | 0 | { |
1121 | 0 | libcerror_error_set( |
1122 | 0 | error, |
1123 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1124 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1125 | 0 | "%s: invalid file system.", |
1126 | 0 | function ); |
1127 | |
|
1128 | 0 | return( -1 ); |
1129 | 0 | } |
1130 | 3.55k | if( file_system->security_descriptor_index != NULL ) |
1131 | 0 | { |
1132 | 0 | libcerror_error_set( |
1133 | 0 | error, |
1134 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1135 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
1136 | 0 | "%s: invalid file system - security descriptor index value already set.", |
1137 | 0 | function ); |
1138 | |
|
1139 | 0 | return( -1 ); |
1140 | 0 | } |
1141 | 3.55k | if( libfsntfs_mft_get_mft_entry_by_index( |
1142 | 3.55k | file_system->mft, |
1143 | 3.55k | file_io_handle, |
1144 | 3.55k | LIBFSNTFS_MFT_ENTRY_INDEX_SECURE, |
1145 | 3.55k | &mft_entry, |
1146 | 3.55k | error ) != 1 ) |
1147 | 446 | { |
1148 | 446 | libcerror_error_set( |
1149 | 446 | error, |
1150 | 446 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1151 | 446 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1152 | 446 | "%s: unable to retrieve MFT entry: %d.", |
1153 | 446 | function, |
1154 | 446 | LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); |
1155 | | |
1156 | 446 | goto on_error; |
1157 | 446 | } |
1158 | 3.10k | if( mft_entry == NULL ) |
1159 | 0 | { |
1160 | 0 | libcerror_error_set( |
1161 | 0 | error, |
1162 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1163 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
1164 | 0 | "%s: missing MFT entry: %d.", |
1165 | 0 | function, |
1166 | 0 | LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); |
1167 | |
|
1168 | 0 | goto on_error; |
1169 | 0 | } |
1170 | 3.10k | if( libfsntfs_mft_entry_get_attribute_by_index( |
1171 | 3.10k | mft_entry, |
1172 | 3.10k | mft_entry->file_name_attribute_index, |
1173 | 3.10k | &mft_attribute, |
1174 | 3.10k | error ) != 1 ) |
1175 | 208 | { |
1176 | 208 | libcerror_error_set( |
1177 | 208 | error, |
1178 | 208 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1179 | 208 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1180 | 208 | "%s: unable to retrieve attribute: %d from MFT entry: %d.", |
1181 | 208 | function, |
1182 | 208 | mft_entry->file_name_attribute_index, |
1183 | 208 | LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); |
1184 | | |
1185 | 208 | goto on_error; |
1186 | 208 | } |
1187 | 2.90k | if( libfsntfs_file_name_values_initialize( |
1188 | 2.90k | &file_name_values, |
1189 | 2.90k | error ) != 1 ) |
1190 | 0 | { |
1191 | 0 | libcerror_error_set( |
1192 | 0 | error, |
1193 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1194 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
1195 | 0 | "%s: unable to create file name values.", |
1196 | 0 | function ); |
1197 | |
|
1198 | 0 | goto on_error; |
1199 | 0 | } |
1200 | 2.90k | if( libfsntfs_file_name_values_read_from_mft_attribute( |
1201 | 2.90k | file_name_values, |
1202 | 2.90k | mft_attribute, |
1203 | 2.90k | error ) != 1 ) |
1204 | 49 | { |
1205 | 49 | libcerror_error_set( |
1206 | 49 | error, |
1207 | 49 | LIBCERROR_ERROR_DOMAIN_IO, |
1208 | 49 | LIBCERROR_IO_ERROR_READ_FAILED, |
1209 | 49 | "%s: unable to read file name values from attribute: %d from MFT entry: %d.", |
1210 | 49 | function, |
1211 | 49 | mft_entry->file_name_attribute_index, |
1212 | 49 | LIBFSNTFS_MFT_ENTRY_INDEX_SECURE ); |
1213 | | |
1214 | 49 | goto on_error; |
1215 | 49 | } |
1216 | 2.85k | result = libfsntfs_name_compare_with_utf8_string( |
1217 | 2.85k | file_name_values->name, |
1218 | 2.85k | file_name_values->name_size, |
1219 | 2.85k | (uint8_t *) "$Secure", |
1220 | 2.85k | 7, |
1221 | 2.85k | 1, |
1222 | 2.85k | error ); |
1223 | | |
1224 | 2.85k | if( result == -1 ) |
1225 | 13 | { |
1226 | 13 | libcerror_error_set( |
1227 | 13 | error, |
1228 | 13 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1229 | 13 | LIBCERROR_RUNTIME_ERROR_GENERIC, |
1230 | 13 | "%s: unable to compare UTF-8 string with data attribute name.", |
1231 | 13 | function ); |
1232 | | |
1233 | 13 | goto on_error; |
1234 | 13 | } |
1235 | 2.83k | else if( result == LIBUNA_COMPARE_EQUAL ) |
1236 | 953 | { |
1237 | 953 | if( libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name( |
1238 | 953 | mft_entry, |
1239 | 953 | (uint8_t *) "$SDS", |
1240 | 953 | 4, |
1241 | 953 | &data_attribute, |
1242 | 953 | error ) != 1 ) |
1243 | 12 | { |
1244 | 12 | libcerror_error_set( |
1245 | 12 | error, |
1246 | 12 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1247 | 12 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1248 | 12 | "%s: unable to retrieve $SDS data attribute.", |
1249 | 12 | function ); |
1250 | | |
1251 | 12 | goto on_error; |
1252 | 12 | } |
1253 | 941 | if( libfsntfs_security_descriptor_index_initialize( |
1254 | 941 | &( file_system->security_descriptor_index ), |
1255 | 941 | io_handle, |
1256 | 941 | file_io_handle, |
1257 | 941 | data_attribute, |
1258 | 941 | error ) != 1 ) |
1259 | 441 | { |
1260 | 441 | libcerror_error_set( |
1261 | 441 | error, |
1262 | 441 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1263 | 441 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
1264 | 441 | "%s: unable to create security descriptor index.", |
1265 | 441 | function ); |
1266 | | |
1267 | 441 | goto on_error; |
1268 | 441 | } |
1269 | 500 | if( libfsntfs_security_descriptor_index_read_sii_index( |
1270 | 500 | file_system->security_descriptor_index, |
1271 | 500 | io_handle, |
1272 | 500 | file_io_handle, |
1273 | 500 | mft_entry, |
1274 | 500 | error ) != 1 ) |
1275 | 335 | { |
1276 | 335 | libcerror_error_set( |
1277 | 335 | error, |
1278 | 335 | LIBCERROR_ERROR_DOMAIN_IO, |
1279 | 335 | LIBCERROR_IO_ERROR_READ_FAILED, |
1280 | 335 | "%s: unable to read security descriptor identifier ($SII) index.", |
1281 | 335 | function ); |
1282 | | |
1283 | 335 | goto on_error; |
1284 | 335 | } |
1285 | 500 | } |
1286 | 2.05k | if( libfsntfs_file_name_values_free( |
1287 | 2.05k | &file_name_values, |
1288 | 2.05k | error ) != 1 ) |
1289 | 0 | { |
1290 | 0 | libcerror_error_set( |
1291 | 0 | error, |
1292 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1293 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1294 | 0 | "%s: unable to free file name values.", |
1295 | 0 | function ); |
1296 | |
|
1297 | 0 | goto on_error; |
1298 | 0 | } |
1299 | 2.05k | return( 1 ); |
1300 | | |
1301 | 1.50k | on_error: |
1302 | 1.50k | if( file_system->security_descriptor_index != NULL ) |
1303 | 335 | { |
1304 | 335 | libfsntfs_security_descriptor_index_free( |
1305 | 335 | &( file_system->security_descriptor_index ), |
1306 | 335 | NULL ); |
1307 | 335 | } |
1308 | 1.50k | if( file_name_values != NULL ) |
1309 | 850 | { |
1310 | 850 | libfsntfs_file_name_values_free( |
1311 | 850 | &file_name_values, |
1312 | 850 | NULL ); |
1313 | 850 | } |
1314 | 1.50k | return( -1 ); |
1315 | 2.05k | } |
1316 | | |
1317 | | /* Retrieves the number of MFT entries |
1318 | | * Returns 1 if successful or -1 on error |
1319 | | */ |
1320 | | int libfsntfs_file_system_get_number_of_mft_entries( |
1321 | | libfsntfs_file_system_t *file_system, |
1322 | | uint64_t *number_of_mft_entries, |
1323 | | libcerror_error_t **error ) |
1324 | 0 | { |
1325 | 0 | static char *function = "libfsntfs_file_system_get_number_of_mft_entries"; |
1326 | |
|
1327 | 0 | if( file_system == NULL ) |
1328 | 0 | { |
1329 | 0 | libcerror_error_set( |
1330 | 0 | error, |
1331 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1332 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1333 | 0 | "%s: invalid file system.", |
1334 | 0 | function ); |
1335 | |
|
1336 | 0 | return( -1 ); |
1337 | 0 | } |
1338 | 0 | if( libfsntfs_mft_get_number_of_entries( |
1339 | 0 | file_system->mft, |
1340 | 0 | number_of_mft_entries, |
1341 | 0 | error ) != 1 ) |
1342 | 0 | { |
1343 | 0 | libcerror_error_set( |
1344 | 0 | error, |
1345 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1346 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1347 | 0 | "%s: unable to retrieve number of MFT entries.", |
1348 | 0 | function ); |
1349 | |
|
1350 | 0 | return( -1 ); |
1351 | 0 | } |
1352 | 0 | return( 1 ); |
1353 | 0 | } |
1354 | | |
1355 | | /* Retrieves the MFT entry for a specific index |
1356 | | * Returns 1 if successful or -1 on error |
1357 | | */ |
1358 | | int libfsntfs_file_system_get_mft_entry_by_index( |
1359 | | libfsntfs_file_system_t *file_system, |
1360 | | libbfio_handle_t *file_io_handle, |
1361 | | uint64_t mft_entry_index, |
1362 | | libfsntfs_mft_entry_t **mft_entry, |
1363 | | libcerror_error_t **error ) |
1364 | 0 | { |
1365 | 0 | static char *function = "libfsntfs_file_system_get_mft_entry_by_index"; |
1366 | |
|
1367 | 0 | if( file_system == NULL ) |
1368 | 0 | { |
1369 | 0 | libcerror_error_set( |
1370 | 0 | error, |
1371 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1372 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1373 | 0 | "%s: invalid file system.", |
1374 | 0 | function ); |
1375 | |
|
1376 | 0 | return( -1 ); |
1377 | 0 | } |
1378 | 0 | if( libfsntfs_mft_get_mft_entry_by_index( |
1379 | 0 | file_system->mft, |
1380 | 0 | file_io_handle, |
1381 | 0 | mft_entry_index, |
1382 | 0 | mft_entry, |
1383 | 0 | error ) != 1 ) |
1384 | 0 | { |
1385 | 0 | libcerror_error_set( |
1386 | 0 | error, |
1387 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1388 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1389 | 0 | "%s: unable to retrieve MFT entry: %" PRIi64 ".", |
1390 | 0 | function, |
1391 | 0 | mft_entry_index ); |
1392 | |
|
1393 | 0 | return( -1 ); |
1394 | 0 | } |
1395 | 0 | return( 1 ); |
1396 | 0 | } |
1397 | | |
1398 | | /* Retrieves the MFT entry for a specific index |
1399 | | * This function creates new MFT entry |
1400 | | * Returns 1 if successful or -1 on error |
1401 | | */ |
1402 | | int libfsntfs_file_system_get_mft_entry_by_index_no_cache( |
1403 | | libfsntfs_file_system_t *file_system, |
1404 | | libbfio_handle_t *file_io_handle, |
1405 | | uint64_t mft_entry_index, |
1406 | | libfsntfs_mft_entry_t **mft_entry, |
1407 | | libcerror_error_t **error ) |
1408 | 2.03k | { |
1409 | 2.03k | static char *function = "libfsntfs_file_system_get_mft_entry_by_index_no_cache"; |
1410 | | |
1411 | 2.03k | if( file_system == NULL ) |
1412 | 0 | { |
1413 | 0 | libcerror_error_set( |
1414 | 0 | error, |
1415 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1416 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1417 | 0 | "%s: invalid file system.", |
1418 | 0 | function ); |
1419 | |
|
1420 | 0 | return( -1 ); |
1421 | 0 | } |
1422 | 2.03k | if( libfsntfs_mft_get_mft_entry_by_index_no_cache( |
1423 | 2.03k | file_system->mft, |
1424 | 2.03k | file_io_handle, |
1425 | 2.03k | mft_entry_index, |
1426 | 2.03k | mft_entry, |
1427 | 2.03k | error ) != 1 ) |
1428 | 29 | { |
1429 | 29 | libcerror_error_set( |
1430 | 29 | error, |
1431 | 29 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1432 | 29 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1433 | 29 | "%s: unable to retrieve MFT entry: %" PRIi64 ".", |
1434 | 29 | function, |
1435 | 29 | mft_entry_index ); |
1436 | | |
1437 | 29 | return( -1 ); |
1438 | 29 | } |
1439 | 2.00k | return( 1 ); |
1440 | 2.03k | } |
1441 | | |
1442 | | /* Retrieves the security descriptor for a specific identifier |
1443 | | * This function creates new security descriptor values |
1444 | | * Returns 1 if successful, 0 if not available or -1 on error |
1445 | | */ |
1446 | | int libfsntfs_file_system_get_security_descriptor_values_by_identifier( |
1447 | | libfsntfs_file_system_t *file_system, |
1448 | | libbfio_handle_t *file_io_handle, |
1449 | | uint32_t security_descriptor_identifier, |
1450 | | libfsntfs_security_descriptor_values_t **security_descriptor_values, |
1451 | | libcerror_error_t **error ) |
1452 | 0 | { |
1453 | 0 | static char *function = "libfsntfs_file_system_get_security_descriptor_values_by_identifier"; |
1454 | 0 | int result = 0; |
1455 | |
|
1456 | 0 | if( file_system == NULL ) |
1457 | 0 | { |
1458 | 0 | libcerror_error_set( |
1459 | 0 | error, |
1460 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1461 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1462 | 0 | "%s: invalid file system.", |
1463 | 0 | function ); |
1464 | |
|
1465 | 0 | return( -1 ); |
1466 | 0 | } |
1467 | 0 | if( file_system->security_descriptor_index != NULL ) |
1468 | 0 | { |
1469 | 0 | result = libfsntfs_security_descriptor_index_get_entry_by_identifier( |
1470 | 0 | file_system->security_descriptor_index, |
1471 | 0 | file_io_handle, |
1472 | 0 | security_descriptor_identifier, |
1473 | 0 | security_descriptor_values, |
1474 | 0 | error ); |
1475 | |
|
1476 | 0 | if( result == -1 ) |
1477 | 0 | { |
1478 | 0 | libcerror_error_set( |
1479 | 0 | error, |
1480 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1481 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1482 | 0 | "%s: unable to retrieve security descriptor from index for identifier: %" PRIu32 ".", |
1483 | 0 | function, |
1484 | 0 | security_descriptor_identifier ); |
1485 | |
|
1486 | 0 | return( -1 ); |
1487 | 0 | } |
1488 | 0 | } |
1489 | 0 | return( result ); |
1490 | 0 | } |
1491 | | |
1492 | | /* Retrieves the path hint of a specific file reference |
1493 | | * Returns 1 if successful, 0 if not available or -1 on error |
1494 | | */ |
1495 | | int libfsntfs_file_system_get_path_hint( |
1496 | | libfsntfs_file_system_t *file_system, |
1497 | | libbfio_handle_t *file_io_handle, |
1498 | | uint64_t file_reference, |
1499 | | libfsntfs_path_hint_t **path_hint, |
1500 | | int recursion_depth, |
1501 | | libcerror_error_t **error ) |
1502 | 0 | { |
1503 | 0 | libcdata_tree_node_t *upper_node = NULL; |
1504 | 0 | libfsntfs_file_name_values_t *file_name_values = NULL; |
1505 | 0 | libfsntfs_mft_attribute_t *mft_attribute = NULL; |
1506 | 0 | libfsntfs_mft_entry_t *mft_entry = NULL; |
1507 | 0 | libfsntfs_path_hint_t *existing_path_hint = NULL; |
1508 | 0 | libfsntfs_path_hint_t *lookup_path_hint = NULL; |
1509 | 0 | libfsntfs_path_hint_t *parent_path_hint = NULL; |
1510 | 0 | libfsntfs_path_hint_t *safe_path_hint = NULL; |
1511 | 0 | uint8_t *parent_path = NULL; |
1512 | 0 | static char *function = "libfsntfs_file_system_get_path_hint"; |
1513 | 0 | size_t name_size = 0; |
1514 | 0 | size_t parent_path_size = 0; |
1515 | 0 | uint64_t mft_entry_index = 0; |
1516 | 0 | uint64_t mft_entry_file_reference = 0; |
1517 | 0 | uint64_t parent_file_reference = 0; |
1518 | 0 | uint64_t parent_mft_entry_index = 0; |
1519 | 0 | uint32_t attribute_type = 0; |
1520 | 0 | uint16_t mft_entry_sequence_number = 0; |
1521 | 0 | uint16_t sequence_number = 0; |
1522 | 0 | int attribute_index = 0; |
1523 | 0 | int number_of_attributes = 0; |
1524 | 0 | int result = 0; |
1525 | 0 | int value_index = 0; |
1526 | |
|
1527 | 0 | if( file_system == NULL ) |
1528 | 0 | { |
1529 | 0 | libcerror_error_set( |
1530 | 0 | error, |
1531 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1532 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1533 | 0 | "%s: invalid file system.", |
1534 | 0 | function ); |
1535 | |
|
1536 | 0 | return( -1 ); |
1537 | 0 | } |
1538 | 0 | if( path_hint == NULL ) |
1539 | 0 | { |
1540 | 0 | libcerror_error_set( |
1541 | 0 | error, |
1542 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
1543 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
1544 | 0 | "%s: invalid path hint.", |
1545 | 0 | function ); |
1546 | |
|
1547 | 0 | return( -1 ); |
1548 | 0 | } |
1549 | 0 | if( ( recursion_depth < 0 ) |
1550 | 0 | || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) ) |
1551 | 0 | { |
1552 | 0 | libcerror_error_set( |
1553 | 0 | error, |
1554 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1555 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
1556 | 0 | "%s: invalid recursion depth value out of bounds.", |
1557 | 0 | function ); |
1558 | |
|
1559 | 0 | return( -1 ); |
1560 | 0 | } |
1561 | 0 | mft_entry_index = file_reference & 0xffffffffffffUL; |
1562 | |
|
1563 | 0 | if( libfsntfs_file_system_get_mft_entry_by_index( |
1564 | 0 | file_system, |
1565 | 0 | file_io_handle, |
1566 | 0 | mft_entry_index, |
1567 | 0 | &mft_entry, |
1568 | 0 | error ) != 1 ) |
1569 | 0 | { |
1570 | 0 | libcerror_error_set( |
1571 | 0 | error, |
1572 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1573 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1574 | 0 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
1575 | 0 | function, |
1576 | 0 | mft_entry_index ); |
1577 | |
|
1578 | 0 | goto on_error; |
1579 | 0 | } |
1580 | 0 | if( libfsntfs_mft_entry_get_file_reference( |
1581 | 0 | mft_entry, |
1582 | 0 | &mft_entry_file_reference, |
1583 | 0 | error ) != 1 ) |
1584 | 0 | { |
1585 | 0 | libcerror_error_set( |
1586 | 0 | error, |
1587 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1588 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1589 | 0 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
1590 | 0 | function, |
1591 | 0 | mft_entry_index ); |
1592 | |
|
1593 | 0 | goto on_error; |
1594 | 0 | } |
1595 | 0 | if( mft_entry_file_reference != file_reference ) |
1596 | 0 | { |
1597 | 0 | result = libfsntfs_mft_entry_is_allocated( |
1598 | 0 | mft_entry, |
1599 | 0 | error ); |
1600 | |
|
1601 | 0 | if( result == -1 ) |
1602 | 0 | { |
1603 | 0 | libcerror_error_set( |
1604 | 0 | error, |
1605 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1606 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1607 | 0 | "%s: unable to retrieve MFT entry: %" PRIu64 ".", |
1608 | 0 | function, |
1609 | 0 | mft_entry_index ); |
1610 | |
|
1611 | 0 | goto on_error; |
1612 | 0 | } |
1613 | 0 | else if( result != 0 ) |
1614 | 0 | { |
1615 | 0 | return( 0 ); |
1616 | 0 | } |
1617 | | /* The sequence number is updated when the MFT entry is deleted |
1618 | | */ |
1619 | 0 | sequence_number = (uint16_t) ( file_reference >> 48 ); |
1620 | 0 | mft_entry_sequence_number = (uint16_t) ( mft_entry_file_reference >> 48 ); |
1621 | |
|
1622 | 0 | if( sequence_number != ( mft_entry_sequence_number - 1 ) ) |
1623 | 0 | { |
1624 | 0 | return( 0 ); |
1625 | 0 | } |
1626 | 0 | } |
1627 | 0 | if( libfsntfs_path_hint_initialize( |
1628 | 0 | &lookup_path_hint, |
1629 | 0 | error ) != 1 ) |
1630 | 0 | { |
1631 | 0 | libcerror_error_set( |
1632 | 0 | error, |
1633 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1634 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
1635 | 0 | "%s: unable to create path hint.", |
1636 | 0 | function ); |
1637 | |
|
1638 | 0 | goto on_error; |
1639 | 0 | } |
1640 | 0 | lookup_path_hint->file_reference = mft_entry_file_reference; |
1641 | |
|
1642 | 0 | result = libcdata_btree_get_value_by_value( |
1643 | 0 | file_system->path_hints_tree, |
1644 | 0 | (intptr_t *) lookup_path_hint, |
1645 | 0 | (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference, |
1646 | 0 | &upper_node, |
1647 | 0 | (intptr_t **) path_hint, |
1648 | 0 | error ); |
1649 | |
|
1650 | 0 | if( result == -1 ) |
1651 | 0 | { |
1652 | 0 | libcerror_error_set( |
1653 | 0 | error, |
1654 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1655 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1656 | 0 | "%s: unable to retrieve path hint from tree.", |
1657 | 0 | function ); |
1658 | |
|
1659 | 0 | goto on_error; |
1660 | 0 | } |
1661 | 0 | else if( result == 0 ) |
1662 | 0 | { |
1663 | 0 | if( libfsntfs_mft_entry_get_number_of_attributes( |
1664 | 0 | mft_entry, |
1665 | 0 | &number_of_attributes, |
1666 | 0 | error ) != 1 ) |
1667 | 0 | { |
1668 | 0 | libcerror_error_set( |
1669 | 0 | error, |
1670 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1671 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1672 | 0 | "%s: unable to retrieve number of attributes.", |
1673 | 0 | function ); |
1674 | |
|
1675 | 0 | goto on_error; |
1676 | 0 | } |
1677 | 0 | for( attribute_index = 0; |
1678 | 0 | attribute_index < number_of_attributes; |
1679 | 0 | attribute_index++ ) |
1680 | 0 | { |
1681 | 0 | if( libfsntfs_mft_entry_get_attribute_by_index( |
1682 | 0 | mft_entry, |
1683 | 0 | attribute_index, |
1684 | 0 | &mft_attribute, |
1685 | 0 | error ) != 1 ) |
1686 | 0 | { |
1687 | 0 | libcerror_error_set( |
1688 | 0 | error, |
1689 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1690 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1691 | 0 | "%s: unable to retrieve attribute: %d.", |
1692 | 0 | function, |
1693 | 0 | attribute_index ); |
1694 | |
|
1695 | 0 | goto on_error; |
1696 | 0 | } |
1697 | 0 | if( libfsntfs_mft_attribute_get_type( |
1698 | 0 | mft_attribute, |
1699 | 0 | &attribute_type, |
1700 | 0 | error ) != 1 ) |
1701 | 0 | { |
1702 | 0 | libcerror_error_set( |
1703 | 0 | error, |
1704 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1705 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1706 | 0 | "%s: unable to retrieve attribute: %d type.", |
1707 | 0 | function, |
1708 | 0 | attribute_index ); |
1709 | |
|
1710 | 0 | goto on_error; |
1711 | 0 | } |
1712 | 0 | if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME ) |
1713 | 0 | { |
1714 | 0 | continue; |
1715 | 0 | } |
1716 | 0 | if( libfsntfs_file_name_values_initialize( |
1717 | 0 | &file_name_values, |
1718 | 0 | error ) != 1 ) |
1719 | 0 | { |
1720 | 0 | libcerror_error_set( |
1721 | 0 | error, |
1722 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1723 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
1724 | 0 | "%s: unable to create file name values.", |
1725 | 0 | function ); |
1726 | |
|
1727 | 0 | goto on_error; |
1728 | 0 | } |
1729 | 0 | if( libfsntfs_file_name_values_read_from_mft_attribute( |
1730 | 0 | file_name_values, |
1731 | 0 | mft_attribute, |
1732 | 0 | error ) != 1 ) |
1733 | 0 | { |
1734 | 0 | libcerror_error_set( |
1735 | 0 | error, |
1736 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
1737 | 0 | LIBCERROR_IO_ERROR_READ_FAILED, |
1738 | 0 | "%s: unable to read file name values.", |
1739 | 0 | function ); |
1740 | |
|
1741 | 0 | goto on_error; |
1742 | 0 | } |
1743 | 0 | if( libfsntfs_file_name_values_get_parent_file_reference( |
1744 | 0 | file_name_values, |
1745 | 0 | &parent_file_reference, |
1746 | 0 | error ) != 1 ) |
1747 | 0 | { |
1748 | 0 | libcerror_error_set( |
1749 | 0 | error, |
1750 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1751 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1752 | 0 | "%s: unable to retrieve parent file reference.", |
1753 | 0 | function ); |
1754 | |
|
1755 | 0 | goto on_error; |
1756 | 0 | } |
1757 | 0 | parent_mft_entry_index = parent_file_reference & 0xffffffffffffUL; |
1758 | |
|
1759 | 0 | if( file_name_values->name_space != LIBFSNTFS_FILE_NAME_SPACE_DOS ) |
1760 | 0 | { |
1761 | 0 | parent_path = NULL; |
1762 | 0 | parent_path_size = 0; |
1763 | |
|
1764 | 0 | if( ( mft_entry_index != LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) |
1765 | 0 | && ( parent_mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) ) |
1766 | 0 | { |
1767 | 0 | parent_path = (uint8_t *) ""; |
1768 | 0 | parent_path_size = 1; |
1769 | 0 | } |
1770 | 0 | else if( ( parent_mft_entry_index != 0 ) |
1771 | 0 | && ( parent_mft_entry_index != mft_entry_index ) ) |
1772 | 0 | { |
1773 | 0 | result = libfsntfs_file_system_get_path_hint( |
1774 | 0 | file_system, |
1775 | 0 | file_io_handle, |
1776 | 0 | parent_file_reference, |
1777 | 0 | &parent_path_hint, |
1778 | 0 | recursion_depth + 1, |
1779 | 0 | error ); |
1780 | |
|
1781 | 0 | if( result == -1 ) |
1782 | 0 | { |
1783 | 0 | libcerror_error_set( |
1784 | 0 | error, |
1785 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1786 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1787 | 0 | "%s: unable to retrieve path hint for MFT entry: %" PRIu64 ".", |
1788 | 0 | function, |
1789 | 0 | parent_mft_entry_index ); |
1790 | |
|
1791 | 0 | goto on_error; |
1792 | 0 | } |
1793 | 0 | else if( result == 0 ) |
1794 | 0 | { |
1795 | 0 | parent_path = (uint8_t *) "$Orphan"; |
1796 | 0 | parent_path_size = 8; |
1797 | 0 | } |
1798 | 0 | else |
1799 | 0 | { |
1800 | 0 | parent_path = parent_path_hint->path; |
1801 | 0 | parent_path_size = parent_path_hint->path_size; |
1802 | 0 | } |
1803 | 0 | } |
1804 | 0 | if( libfsntfs_file_name_values_get_utf8_name_size( |
1805 | 0 | file_name_values, |
1806 | 0 | &name_size, |
1807 | 0 | error ) != 1 ) |
1808 | 0 | { |
1809 | 0 | libcerror_error_set( |
1810 | 0 | error, |
1811 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1812 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1813 | 0 | "%s: unable to retrieve size of UTF-8 name.", |
1814 | 0 | function ); |
1815 | |
|
1816 | 0 | goto on_error; |
1817 | 0 | } |
1818 | 0 | if( libfsntfs_path_hint_initialize( |
1819 | 0 | &safe_path_hint, |
1820 | 0 | error ) != 1 ) |
1821 | 0 | { |
1822 | 0 | libcerror_error_set( |
1823 | 0 | error, |
1824 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1825 | 0 | LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED, |
1826 | 0 | "%s: unable to create path hint.", |
1827 | 0 | function ); |
1828 | |
|
1829 | 0 | goto on_error; |
1830 | 0 | } |
1831 | 0 | safe_path_hint->file_reference = file_reference; |
1832 | 0 | safe_path_hint->path_size = parent_path_size + name_size; |
1833 | |
|
1834 | 0 | safe_path_hint->path = (uint8_t *) memory_allocate( |
1835 | 0 | sizeof( uint8_t ) * safe_path_hint->path_size ); |
1836 | |
|
1837 | 0 | if( safe_path_hint->path == NULL ) |
1838 | 0 | { |
1839 | 0 | libcerror_error_set( |
1840 | 0 | error, |
1841 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
1842 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
1843 | 0 | "%s: unable to create path.", |
1844 | 0 | function ); |
1845 | |
|
1846 | 0 | goto on_error; |
1847 | 0 | } |
1848 | 0 | if( ( parent_path != NULL ) |
1849 | 0 | && ( parent_path_size > 0 ) ) |
1850 | 0 | { |
1851 | 0 | if( memory_copy( |
1852 | 0 | safe_path_hint->path, |
1853 | 0 | parent_path, |
1854 | 0 | parent_path_size ) == NULL ) |
1855 | 0 | { |
1856 | 0 | libcerror_error_set( |
1857 | 0 | error, |
1858 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
1859 | 0 | LIBCERROR_MEMORY_ERROR_COPY_FAILED, |
1860 | 0 | "%s: unable to copy parent path to path.", |
1861 | 0 | function ); |
1862 | |
|
1863 | 0 | goto on_error; |
1864 | 0 | } |
1865 | 0 | safe_path_hint->path[ parent_path_size - 1 ] = '\\'; |
1866 | 0 | } |
1867 | 0 | if( name_size > 0 ) |
1868 | 0 | { |
1869 | 0 | if( libfsntfs_file_name_values_get_utf8_name( |
1870 | 0 | file_name_values, |
1871 | 0 | &( safe_path_hint->path[ parent_path_size ] ), |
1872 | 0 | name_size, |
1873 | 0 | error ) != 1 ) |
1874 | 0 | { |
1875 | 0 | libcerror_error_set( |
1876 | 0 | error, |
1877 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1878 | 0 | LIBCERROR_RUNTIME_ERROR_GET_FAILED, |
1879 | 0 | "%s: unable to retrieve UTF-8 name.", |
1880 | 0 | function ); |
1881 | |
|
1882 | 0 | goto on_error; |
1883 | 0 | } |
1884 | 0 | } |
1885 | 0 | if( mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) |
1886 | 0 | { |
1887 | 0 | safe_path_hint->path[ 0 ] = '\\'; |
1888 | 0 | } |
1889 | 0 | result = libcdata_btree_insert_value( |
1890 | 0 | file_system->path_hints_tree, |
1891 | 0 | &value_index, |
1892 | 0 | (intptr_t *) safe_path_hint, |
1893 | 0 | (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference, |
1894 | 0 | &upper_node, |
1895 | 0 | (intptr_t **) &existing_path_hint, |
1896 | 0 | error ); |
1897 | |
|
1898 | 0 | if( result == -1 ) |
1899 | 0 | { |
1900 | 0 | libcerror_error_set( |
1901 | 0 | error, |
1902 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1903 | 0 | LIBCERROR_RUNTIME_ERROR_APPEND_FAILED, |
1904 | 0 | "%s: unable to insert path hint into tree.", |
1905 | 0 | function ); |
1906 | |
|
1907 | 0 | goto on_error; |
1908 | 0 | } |
1909 | 0 | else if( result == 0 ) |
1910 | 0 | { |
1911 | 0 | if( libfsntfs_path_hint_free( |
1912 | 0 | &safe_path_hint, |
1913 | 0 | error ) != 1 ) |
1914 | 0 | { |
1915 | 0 | libcerror_error_set( |
1916 | 0 | error, |
1917 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1918 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1919 | 0 | "%s: unable to free path hint.", |
1920 | 0 | function ); |
1921 | |
|
1922 | 0 | goto on_error; |
1923 | 0 | } |
1924 | 0 | *path_hint = existing_path_hint; |
1925 | 0 | } |
1926 | 0 | else |
1927 | 0 | { |
1928 | 0 | *path_hint = safe_path_hint; |
1929 | |
|
1930 | 0 | safe_path_hint = NULL; |
1931 | 0 | } |
1932 | 0 | result = 1; |
1933 | 0 | } |
1934 | 0 | if( libfsntfs_file_name_values_free( |
1935 | 0 | &file_name_values, |
1936 | 0 | error ) != 1 ) |
1937 | 0 | { |
1938 | 0 | libcerror_error_set( |
1939 | 0 | error, |
1940 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1941 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1942 | 0 | "%s: unable to free file name values.", |
1943 | 0 | function ); |
1944 | |
|
1945 | 0 | goto on_error; |
1946 | 0 | } |
1947 | 0 | } |
1948 | 0 | } |
1949 | 0 | if( libfsntfs_path_hint_free( |
1950 | 0 | &lookup_path_hint, |
1951 | 0 | error ) != 1 ) |
1952 | 0 | { |
1953 | 0 | libcerror_error_set( |
1954 | 0 | error, |
1955 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
1956 | 0 | LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED, |
1957 | 0 | "%s: unable to free path hint.", |
1958 | 0 | function ); |
1959 | |
|
1960 | 0 | goto on_error; |
1961 | 0 | } |
1962 | 0 | return( result ); |
1963 | | |
1964 | 0 | on_error: |
1965 | 0 | if( safe_path_hint != NULL ) |
1966 | 0 | { |
1967 | 0 | libfsntfs_path_hint_free( |
1968 | 0 | &safe_path_hint, |
1969 | 0 | NULL ); |
1970 | 0 | } |
1971 | 0 | if( file_name_values != NULL ) |
1972 | 0 | { |
1973 | 0 | libfsntfs_file_name_values_free( |
1974 | 0 | &file_name_values, |
1975 | 0 | NULL ); |
1976 | 0 | } |
1977 | 0 | if( lookup_path_hint != NULL ) |
1978 | 0 | { |
1979 | 0 | libfsntfs_path_hint_free( |
1980 | 0 | &lookup_path_hint, |
1981 | 0 | NULL ); |
1982 | 0 | } |
1983 | 0 | return( -1 ); |
1984 | 0 | } |
1985 | | |