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