1 /*
2 * Master File Table (MFT) entry 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_debug.h"
28 #include "libfsntfs_definitions.h"
29 #include "libfsntfs_directory_entry.h"
30 #include "libfsntfs_fixup_values.h"
31 #include "libfsntfs_io_handle.h"
32 #include "libfsntfs_libbfio.h"
33 #include "libfsntfs_libcdata.h"
34 #include "libfsntfs_libcerror.h"
35 #include "libfsntfs_libcnotify.h"
36 #include "libfsntfs_libfcache.h"
37 #include "libfsntfs_libfdata.h"
38 #include "libfsntfs_libuna.h"
39 #include "libfsntfs_mft_attribute.h"
40 #include "libfsntfs_mft_attribute_list.h"
41 #include "libfsntfs_mft_attribute_list_entry.h"
42 #include "libfsntfs_mft_entry.h"
43 #include "libfsntfs_mft_entry_header.h"
44 #include "libfsntfs_standard_information_values.h"
45 #include "libfsntfs_types.h"
46 #include "libfsntfs_unused.h"
47
48 #include "fsntfs_mft_entry.h"
49
50 const char fsntfs_mft_entry_signature[ 4 ] = { 'F', 'I', 'L', 'E' };
51
52 /* Checks if a buffer containing the MFT entry is filled with 0-byte values (empty-block)
53 * Returns 1 if empty, 0 if not or -1 on error
54 */
libfsntfs_mft_entry_check_for_empty_block(const uint8_t * data,size_t data_size,libcerror_error_t ** error)55 int libfsntfs_mft_entry_check_for_empty_block(
56 const uint8_t *data,
57 size_t data_size,
58 libcerror_error_t **error )
59 {
60 libfsntfs_aligned_t *aligned_data_index = NULL;
61 libfsntfs_aligned_t *aligned_data_start = NULL;
62 uint8_t *data_index = NULL;
63 uint8_t *data_start = NULL;
64 static char *function = "libfsntfs_mft_entry_check_for_empty_block";
65
66 if( data == NULL )
67 {
68 libcerror_error_set(
69 error,
70 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72 "%s: invalid data.",
73 function );
74
75 return( -1 );
76 }
77 if( data_size > (size_t) SSIZE_MAX )
78 {
79 libcerror_error_set(
80 error,
81 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
83 "%s: invalid data size value exceeds maximum.",
84 function );
85
86 return( -1 );
87 }
88 data_start = (uint8_t *) data;
89 data_index = (uint8_t *) data + 1;
90 data_size -= 1;
91
92 /* Only optimize for data larger than the alignment
93 */
94 if( data_size > ( 2 * sizeof( libfsntfs_aligned_t ) ) )
95 {
96 /* Align the data start
97 */
98 while( ( (intptr_t) data_start % sizeof( libfsntfs_aligned_t ) ) != 0 )
99 {
100 if( *data_start != *data_index )
101 {
102 return( 0 );
103 }
104 data_start += 1;
105 data_index += 1;
106 data_size -= 1;
107 }
108 /* Align the data index
109 */
110 while( ( (intptr_t) data_index % sizeof( libfsntfs_aligned_t ) ) != 0 )
111 {
112 if( *data_start != *data_index )
113 {
114 return( 0 );
115 }
116 data_index += 1;
117 data_size -= 1;
118 }
119 aligned_data_start = (libfsntfs_aligned_t *) data_start;
120 aligned_data_index = (libfsntfs_aligned_t *) data_index;
121
122 while( data_size > sizeof( libfsntfs_aligned_t ) )
123 {
124 if( *aligned_data_start != *aligned_data_index )
125 {
126 return( 0 );
127 }
128 aligned_data_index += 1;
129 data_size -= sizeof( libfsntfs_aligned_t );
130 }
131 data_index = (uint8_t *) aligned_data_index;
132 }
133 while( data_size != 0 )
134 {
135 if( *data_start != *data_index )
136 {
137 return( 0 );
138 }
139 data_index += 1;
140 data_size -= 1;
141 }
142 return( 1 );
143 }
144
145 /* Creates a MFT entry
146 * Make sure the value mft_entry is referencing, is set to NULL
147 * Returns 1 if successful or -1 on error
148 */
libfsntfs_mft_entry_initialize(libfsntfs_mft_entry_t ** mft_entry,libcerror_error_t ** error)149 int libfsntfs_mft_entry_initialize(
150 libfsntfs_mft_entry_t **mft_entry,
151 libcerror_error_t **error )
152 {
153 static char *function = "libfsntfs_mft_entry_initialize";
154
155 if( mft_entry == NULL )
156 {
157 libcerror_error_set(
158 error,
159 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161 "%s: invalid MFT entry.",
162 function );
163
164 return( -1 );
165 }
166 if( *mft_entry != NULL )
167 {
168 libcerror_error_set(
169 error,
170 LIBCERROR_ERROR_DOMAIN_RUNTIME,
171 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
172 "%s: invalid MFT entry value already set.",
173 function );
174
175 return( -1 );
176 }
177 *mft_entry = memory_allocate_structure(
178 libfsntfs_mft_entry_t );
179
180 if( *mft_entry == NULL )
181 {
182 libcerror_error_set(
183 error,
184 LIBCERROR_ERROR_DOMAIN_MEMORY,
185 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
186 "%s: unable to create MFT entry.",
187 function );
188
189 goto on_error;
190 }
191 if( memory_set(
192 *mft_entry,
193 0,
194 sizeof( libfsntfs_mft_entry_t ) ) == NULL )
195 {
196 libcerror_error_set(
197 error,
198 LIBCERROR_ERROR_DOMAIN_MEMORY,
199 LIBCERROR_MEMORY_ERROR_SET_FAILED,
200 "%s: unable to clear MFT entry.",
201 function );
202
203 memory_free(
204 *mft_entry );
205
206 *mft_entry = NULL;
207
208 return( -1 );
209 }
210 if( libcdata_array_initialize(
211 &( ( *mft_entry )->attributes_array ),
212 0,
213 error ) != 1 )
214 {
215 libcerror_error_set(
216 error,
217 LIBCERROR_ERROR_DOMAIN_RUNTIME,
218 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
219 "%s: unable to create attributes array.",
220 function );
221
222 goto on_error;
223 }
224 if( libcdata_array_initialize(
225 &( ( *mft_entry )->alternate_data_attributes_array ),
226 0,
227 error ) != 1 )
228 {
229 libcerror_error_set(
230 error,
231 LIBCERROR_ERROR_DOMAIN_RUNTIME,
232 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
233 "%s: unable to create alternate data attributes array.",
234 function );
235
236 goto on_error;
237 }
238 ( *mft_entry )->file_name_attribute_index = -1;
239 ( *mft_entry )->reparse_point_attribute_index = -1;
240 ( *mft_entry )->security_descriptor_attribute_index = -1;
241 ( *mft_entry )->standard_information_attribute_index = -1;
242 ( *mft_entry )->volume_information_attribute_index = -1;
243 ( *mft_entry )->volume_name_attribute_index = -1;
244
245 return( 1 );
246
247 on_error:
248 if( *mft_entry != NULL )
249 {
250 if( ( *mft_entry )->alternate_data_attributes_array != NULL )
251 {
252 libcdata_array_free(
253 &( ( *mft_entry )->alternate_data_attributes_array ),
254 NULL,
255 NULL );
256 }
257 if( ( *mft_entry )->attributes_array != NULL )
258 {
259 libcdata_array_free(
260 &( ( *mft_entry )->attributes_array ),
261 NULL,
262 NULL );
263 }
264 memory_free(
265 *mft_entry );
266
267 *mft_entry = NULL;
268 }
269 return( -1 );
270 }
271
272 /* Frees a MFT entry
273 * Returns 1 if successful or -1 on error
274 */
libfsntfs_mft_entry_free(libfsntfs_mft_entry_t ** mft_entry,libcerror_error_t ** error)275 int libfsntfs_mft_entry_free(
276 libfsntfs_mft_entry_t **mft_entry,
277 libcerror_error_t **error )
278 {
279 static char *function = "libfsntfs_mft_entry_free";
280 int result = 1;
281
282 if( mft_entry == NULL )
283 {
284 libcerror_error_set(
285 error,
286 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288 "%s: invalid MFT entry.",
289 function );
290
291 return( -1 );
292 }
293 if( *mft_entry != NULL )
294 {
295 if( ( *mft_entry )->header != NULL )
296 {
297 if( libfsntfs_mft_entry_header_free(
298 &( ( *mft_entry )->header ),
299 error ) != 1 )
300 {
301 libcerror_error_set(
302 error,
303 LIBCERROR_ERROR_DOMAIN_RUNTIME,
304 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
305 "%s: unable to free MFT entry header.",
306 function );
307
308 result = -1;
309 }
310 }
311 if( ( *mft_entry )->data != NULL )
312 {
313 memory_free(
314 ( *mft_entry )->data );
315 }
316 /* The specific attribute references point to attributes in the array
317 * and are freed by freeing the array and its values
318 */
319 if( libcdata_array_free(
320 &( ( *mft_entry )->attributes_array ),
321 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
322 error ) != 1 )
323 {
324 libcerror_error_set(
325 error,
326 LIBCERROR_ERROR_DOMAIN_RUNTIME,
327 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
328 "%s: unable to free attributes array.",
329 function );
330
331 result = -1;
332 }
333 if( ( *mft_entry )->attribute_list != NULL )
334 {
335 if( libfsntfs_mft_attribute_list_free(
336 &( ( *mft_entry )->attribute_list ),
337 error ) != 1 )
338 {
339 libcerror_error_set(
340 error,
341 LIBCERROR_ERROR_DOMAIN_RUNTIME,
342 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
343 "%s: unable to free attribute list.",
344 function );
345
346 result = -1;
347 }
348 }
349 /* The alternate_data_attributes_array only contains references that are managed
350 * by the attributes_array
351 */
352 if( libcdata_array_free(
353 &( ( *mft_entry )->alternate_data_attributes_array ),
354 NULL,
355 error ) != 1 )
356 {
357 libcerror_error_set(
358 error,
359 LIBCERROR_ERROR_DOMAIN_RUNTIME,
360 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
361 "%s: unable to free alternate data attributes array.",
362 function );
363
364 result = -1;
365 }
366 memory_free(
367 *mft_entry );
368
369 *mft_entry = NULL;
370 }
371 return( result );
372 }
373
374 /* Reads the MFT entry
375 * Returns 1 if successful, 0 if empty or marked as bad, or -1 on error
376 */
libfsntfs_mft_entry_read_data(libfsntfs_mft_entry_t * mft_entry,uint8_t * data,size_t data_size,uint32_t mft_entry_index,libcerror_error_t ** error)377 int libfsntfs_mft_entry_read_data(
378 libfsntfs_mft_entry_t *mft_entry,
379 uint8_t *data,
380 size_t data_size,
381 uint32_t mft_entry_index,
382 libcerror_error_t **error )
383 {
384 static char *function = "libfsntfs_mft_entry_read_data";
385 size_t data_offset = 0;
386 size_t unknown_data_size = 0;
387 uint16_t attributes_offset = 0;
388 uint16_t fixup_values_offset = 0;
389 uint16_t number_of_fixup_values = 0;
390 int result = 0;
391
392 #if defined( HAVE_DEBUG_OUTPUT )
393 uint16_t total_entry_size = 0;
394 #endif
395
396 if( mft_entry == NULL )
397 {
398 libcerror_error_set(
399 error,
400 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
401 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
402 "%s: invalid MFT entry.",
403 function );
404
405 return( -1 );
406 }
407 if( mft_entry->header != NULL )
408 {
409 libcerror_error_set(
410 error,
411 LIBCERROR_ERROR_DOMAIN_RUNTIME,
412 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
413 "%s: invalid MFT entry - header value already set.",
414 function );
415
416 return( -1 );
417 }
418 if( data == NULL )
419 {
420 libcerror_error_set(
421 error,
422 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
423 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
424 "%s: invalid data.",
425 function );
426
427 return( -1 );
428 }
429 if( data_size > (size_t) SSIZE_MAX )
430 {
431 libcerror_error_set(
432 error,
433 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
434 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
435 "%s: invalid data size value exceeds maximum.",
436 function );
437
438 return( -1 );
439 }
440 result = libfsntfs_mft_entry_check_for_empty_block(
441 data,
442 data_size,
443 error );
444
445 if( result == -1 )
446 {
447 libcerror_error_set(
448 error,
449 LIBCERROR_ERROR_DOMAIN_RUNTIME,
450 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
451 "%s: unable to determine if MFT entry is empty.",
452 function );
453
454 goto on_error;
455 }
456 else if( result != 0 )
457 {
458 #if defined( HAVE_DEBUG_OUTPUT )
459 if( libcnotify_verbose != 0 )
460 {
461 libcnotify_printf(
462 "%s: MFT entry: %" PRIu32 " is empty.\n",
463 function,
464 mft_entry_index );
465 }
466 #endif
467 mft_entry->is_empty = 1;
468
469 return( 0 );
470 }
471 if( libfsntfs_mft_entry_header_initialize(
472 &( mft_entry->header ),
473 error ) != 1 )
474 {
475 libcerror_error_set(
476 error,
477 LIBCERROR_ERROR_DOMAIN_RUNTIME,
478 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
479 "%s: unable to create MFT entry header.",
480 function );
481
482 goto on_error;
483 }
484 result = libfsntfs_mft_entry_header_read_data(
485 mft_entry->header,
486 data,
487 data_size,
488 error );
489
490 if( result == -1 )
491 {
492 libcerror_error_set(
493 error,
494 LIBCERROR_ERROR_DOMAIN_IO,
495 LIBCERROR_IO_ERROR_READ_FAILED,
496 "%s: unable to read MFT entry header.",
497 function );
498
499 goto on_error;
500 }
501 else if( result == 0 )
502 {
503 /* Note that an empty MFT data can contain arbitrary data
504 */
505 mft_entry->is_empty = 1;
506
507 return( 0 );
508 }
509 #if defined( HAVE_DEBUG_OUTPUT )
510 if( libcnotify_verbose != 0 )
511 {
512 if( libfsntfs_mft_entry_header_get_total_entry_size(
513 mft_entry->header,
514 &total_entry_size,
515 error ) != 1 )
516 {
517 libcerror_error_set(
518 error,
519 LIBCERROR_ERROR_DOMAIN_RUNTIME,
520 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
521 "%s: unable to retrieve total entry size.",
522 function );
523
524 goto on_error;
525 }
526 if( data_size != (size_t) total_entry_size )
527 {
528 libcnotify_printf(
529 "%s: mismatch in total MFT entry size (calculated: %" PRIzd ", stored: %" PRIu16 ").\n",
530 function,
531 data_size,
532 total_entry_size );
533 }
534 }
535 #endif
536 if( libfsntfs_mft_entry_header_get_attributes_offset(
537 mft_entry->header,
538 &attributes_offset,
539 error ) != 1 )
540 {
541 libcerror_error_set(
542 error,
543 LIBCERROR_ERROR_DOMAIN_RUNTIME,
544 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
545 "%s: unable to retrieve attributes offset.",
546 function );
547
548 goto on_error;
549 }
550 if( attributes_offset >= data_size )
551 {
552 libcerror_error_set(
553 error,
554 LIBCERROR_ERROR_DOMAIN_RUNTIME,
555 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
556 "%s: invalid attributes offset value out of bounds.",
557 function );
558
559 goto on_error;
560 }
561 if( libfsntfs_mft_entry_header_get_fixup_values_offset(
562 mft_entry->header,
563 &fixup_values_offset,
564 error ) != 1 )
565 {
566 libcerror_error_set(
567 error,
568 LIBCERROR_ERROR_DOMAIN_RUNTIME,
569 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
570 "%s: unable to retrieve fix-up values offset.",
571 function );
572
573 goto on_error;
574 }
575 if( fixup_values_offset > attributes_offset )
576 {
577 libcerror_error_set(
578 error,
579 LIBCERROR_ERROR_DOMAIN_RUNTIME,
580 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
581 "%s: fix-up values offset exceeds attributes offset.",
582 function );
583
584 goto on_error;
585 }
586 if( fixup_values_offset > 42 )
587 {
588 data_offset = sizeof( fsntfs_mft_entry_header_t );
589 }
590 else
591 {
592 /* In NTFS 1.2 the fix-up values offset can point to wfixupPattern
593 */
594 data_offset = 42;
595 }
596 if( data_offset < fixup_values_offset )
597 {
598 unknown_data_size = (size_t) fixup_values_offset - data_offset;
599
600 #if defined( HAVE_DEBUG_OUTPUT )
601 if( libcnotify_verbose != 0 )
602 {
603 libcnotify_printf(
604 "%s: unknown data:\n",
605 function );
606 libcnotify_print_data(
607 &( data[ data_offset ] ),
608 unknown_data_size,
609 0 );
610 }
611 #endif
612 data_offset += unknown_data_size;
613 }
614 if( libfsntfs_mft_entry_header_get_number_of_fixup_values(
615 mft_entry->header,
616 &number_of_fixup_values,
617 error ) != 1 )
618 {
619 libcerror_error_set(
620 error,
621 LIBCERROR_ERROR_DOMAIN_RUNTIME,
622 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
623 "%s: unable to retrieve number of fix-up values.",
624 function );
625
626 goto on_error;
627 }
628 if( number_of_fixup_values > 0 )
629 {
630 if( libfsntfs_fixup_values_apply(
631 data,
632 data_size,
633 fixup_values_offset,
634 number_of_fixup_values,
635 error ) != 1 )
636 {
637 libcerror_error_set(
638 error,
639 LIBCERROR_ERROR_DOMAIN_RUNTIME,
640 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
641 "%s: unable to apply fix-up values.",
642 function );
643
644 goto on_error;
645 }
646 data_offset += 2 + ( (size_t) number_of_fixup_values * 2 );
647 }
648 #if defined( HAVE_DEBUG_OUTPUT )
649 if( libcnotify_verbose != 0 )
650 {
651 if( data_offset < attributes_offset )
652 {
653 libcnotify_printf(
654 "%s: unknown data:\n",
655 function );
656 libcnotify_print_data(
657 &( data[ data_offset ] ),
658 (size_t) attributes_offset - data_offset,
659 0 );
660 }
661 }
662 #endif
663 mft_entry->is_empty = 0;
664
665 mft_entry->index = mft_entry->header->index;
666
667 if( mft_entry->index != mft_entry_index )
668 {
669 mft_entry->index = mft_entry_index;
670 }
671 mft_entry->file_reference = ( (uint64_t) mft_entry->header->sequence << 48 ) | mft_entry->index;
672
673 return( 1 );
674
675 on_error:
676 if( mft_entry->header != NULL )
677 {
678 libfsntfs_mft_entry_header_free(
679 &( mft_entry->header ),
680 NULL );
681 }
682 return( -1 );
683 }
684
685 /* Reads the MFT entry
686 * Returns 1 if successful or -1 on error
687 */
libfsntfs_mft_entry_read_file_io_handle(libfsntfs_mft_entry_t * mft_entry,libbfio_handle_t * file_io_handle,off64_t file_offset,uint32_t mft_entry_size,uint32_t mft_entry_index,libcerror_error_t ** error)688 int libfsntfs_mft_entry_read_file_io_handle(
689 libfsntfs_mft_entry_t *mft_entry,
690 libbfio_handle_t *file_io_handle,
691 off64_t file_offset,
692 uint32_t mft_entry_size,
693 uint32_t mft_entry_index,
694 libcerror_error_t **error )
695 {
696 static char *function = "libfsntfs_mft_entry_read_file_io_handle";
697 ssize_t read_count = 0;
698 int result = 0;
699
700 if( mft_entry == NULL )
701 {
702 libcerror_error_set(
703 error,
704 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
705 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
706 "%s: invalid MFT entry.",
707 function );
708
709 return( -1 );
710 }
711 if( mft_entry->data != NULL )
712 {
713 libcerror_error_set(
714 error,
715 LIBCERROR_ERROR_DOMAIN_RUNTIME,
716 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
717 "%s: invalid MFT entry - data value already set.",
718 function );
719
720 return( -1 );
721 }
722 if( ( (size_t) mft_entry_size <= 42 )
723 || ( (size_t) mft_entry_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
724 {
725 libcerror_error_set(
726 error,
727 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
728 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
729 "%s: invalid MFT entry size value out of bounds.",
730 function );
731
732 goto on_error;
733 }
734 mft_entry->data = (uint8_t *) memory_allocate(
735 (size_t) mft_entry_size );
736
737 if( mft_entry->data == NULL )
738 {
739 libcerror_error_set(
740 error,
741 LIBCERROR_ERROR_DOMAIN_MEMORY,
742 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
743 "%s: unable to create MFT entry data.",
744 function );
745
746 goto on_error;
747 }
748 mft_entry->data_size = (size_t) mft_entry_size;
749
750 #if defined( HAVE_DEBUG_OUTPUT )
751 if( libcnotify_verbose != 0 )
752 {
753 libcnotify_printf(
754 "%s: reading MFT entry at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
755 function,
756 file_offset,
757 file_offset );
758 }
759 #endif
760 read_count = libbfio_handle_read_buffer_at_offset(
761 file_io_handle,
762 mft_entry->data,
763 mft_entry->data_size,
764 file_offset,
765 error );
766
767 if( read_count != (ssize_t) mft_entry->data_size )
768 {
769 libcerror_error_set(
770 error,
771 LIBCERROR_ERROR_DOMAIN_IO,
772 LIBCERROR_IO_ERROR_READ_FAILED,
773 "%s: unable to read MFT entry data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
774 function,
775 file_offset,
776 file_offset );
777
778 goto on_error;
779 }
780 result = libfsntfs_mft_entry_read_data(
781 mft_entry,
782 mft_entry->data,
783 mft_entry->data_size,
784 mft_entry_index,
785 error );
786
787 if( result == -1 )
788 {
789 libcerror_error_set(
790 error,
791 LIBCERROR_ERROR_DOMAIN_IO,
792 LIBCERROR_IO_ERROR_READ_FAILED,
793 "%s: unable to read MFT entry data.",
794 function );
795
796 goto on_error;
797 }
798 else if( result == 0 )
799 {
800 memory_free(
801 mft_entry->data );
802
803 mft_entry->data = NULL;
804 mft_entry->data_size = 0;
805 }
806 return( 1 );
807
808 on_error:
809 if( mft_entry->header != NULL )
810 {
811 libfsntfs_mft_entry_header_free(
812 &( mft_entry->header ),
813 NULL );
814 }
815 if( mft_entry->data != NULL )
816 {
817 memory_free(
818 mft_entry->data );
819
820 mft_entry->data = NULL;
821 }
822 mft_entry->data_size = 0;
823
824 return( -1 );
825 }
826
827 /* Reads the MFT attributes
828 * Returns 1 if successful or -1 on error
829 */
libfsntfs_mft_entry_read_attributes_data(libfsntfs_mft_entry_t * mft_entry,libfsntfs_io_handle_t * io_handle,const uint8_t * data,size_t data_size,libcerror_error_t ** error)830 int libfsntfs_mft_entry_read_attributes_data(
831 libfsntfs_mft_entry_t *mft_entry,
832 libfsntfs_io_handle_t *io_handle,
833 const uint8_t *data,
834 size_t data_size,
835 libcerror_error_t **error )
836 {
837 libfsntfs_mft_attribute_t *mft_attribute = NULL;
838 static char *function = "libfsntfs_mft_entry_read_attributes_data";
839 size_t data_offset = 0;
840 uint32_t attribute_type = 0;
841 uint16_t attributes_offset = 0;
842 int attribute_index = 0;
843 int entry_index = 0;
844
845 #if defined( HAVE_DEBUG_OUTPUT )
846 uint16_t used_entry_size = 0;
847 #endif
848
849 if( mft_entry == NULL )
850 {
851 libcerror_error_set(
852 error,
853 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
854 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
855 "%s: invalid MFT entry.",
856 function );
857
858 return( -1 );
859 }
860 if( data == NULL )
861 {
862 libcerror_error_set(
863 error,
864 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
865 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
866 "%s: invalid data.",
867 function );
868
869 return( -1 );
870 }
871 if( data_size > (size_t) SSIZE_MAX )
872 {
873 libcerror_error_set(
874 error,
875 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
876 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
877 "%s: invalid data size value exceeds maximum.",
878 function );
879
880 return( -1 );
881 }
882 if( data_size < 4 )
883 {
884 libcerror_error_set(
885 error,
886 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
887 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
888 "%s: unsupported data size value too small\n",
889 function );
890
891 return( -1 );
892 }
893 if( libfsntfs_mft_entry_header_get_attributes_offset(
894 mft_entry->header,
895 &attributes_offset,
896 error ) != 1 )
897 {
898 libcerror_error_set(
899 error,
900 LIBCERROR_ERROR_DOMAIN_RUNTIME,
901 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
902 "%s: unable to retrieve attributes offset.",
903 function );
904
905 goto on_error;
906 }
907 data_offset = (size_t) attributes_offset;
908
909 do
910 {
911 if( data_offset > ( data_size - 4 ) )
912 {
913 libcerror_error_set(
914 error,
915 LIBCERROR_ERROR_DOMAIN_RUNTIME,
916 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
917 "%s: invalid MFT entry - attribute offset: %d value out of bounds.",
918 function,
919 attribute_index );
920
921 goto on_error;
922 }
923 byte_stream_copy_to_uint32_little_endian(
924 &( data[ data_offset ] ),
925 attribute_type );
926
927 if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES )
928 {
929 break;
930 }
931 if( libfsntfs_mft_attribute_initialize(
932 &mft_attribute,
933 error ) != 1 )
934 {
935 libcerror_error_set(
936 error,
937 LIBCERROR_ERROR_DOMAIN_RUNTIME,
938 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
939 "%s: unable to create MFT attribute: %d.",
940 function,
941 attribute_index );
942
943 goto on_error;
944 }
945 if( libfsntfs_mft_attribute_read_data(
946 mft_attribute,
947 io_handle,
948 &( data[ data_offset ] ),
949 data_size - data_offset,
950 error ) != 1 )
951 {
952 libcerror_error_set(
953 error,
954 LIBCERROR_ERROR_DOMAIN_IO,
955 LIBCERROR_IO_ERROR_READ_FAILED,
956 "%s: unable to read MFT attribute: %d of type: 0x%08" PRIx32 ".",
957 function,
958 attribute_index,
959 attribute_type );
960
961 goto on_error;
962 }
963 data_offset += mft_attribute->size;
964
965 if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST )
966 {
967 if( mft_entry->list_attribute != NULL )
968 {
969 libcerror_error_set(
970 error,
971 LIBCERROR_ERROR_DOMAIN_RUNTIME,
972 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
973 "%s: invalid MFT entry - list attribute value already set.",
974 function );
975
976 goto on_error;
977 }
978 mft_entry->list_attribute = mft_attribute;
979 }
980 /* mft_entry->attributes_array takes over management of mft_attribute
981 */
982 if( libcdata_array_append_entry(
983 mft_entry->attributes_array,
984 &entry_index,
985 (intptr_t *) mft_attribute,
986 error ) != 1 )
987 {
988 libcerror_error_set(
989 error,
990 LIBCERROR_ERROR_DOMAIN_RUNTIME,
991 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
992 "%s: unable to append attribute to array.",
993 function );
994
995 goto on_error;
996 }
997 if( libfsntfs_mft_entry_set_attribute_helper_values(
998 mft_entry,
999 entry_index,
1000 mft_attribute,
1001 error ) != 1 )
1002 {
1003 libcerror_error_set(
1004 error,
1005 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1006 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1007 "%s: unable to set helper values for attribute: %d.",
1008 function,
1009 attribute_index );
1010
1011 mft_attribute = NULL;
1012
1013 goto on_error;
1014 }
1015 mft_attribute = NULL;
1016
1017 attribute_index++;
1018 }
1019 while( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES );
1020
1021 data_offset += 4;
1022
1023 #if defined( HAVE_DEBUG_OUTPUT )
1024 if( libcnotify_verbose != 0 )
1025 {
1026 if( libfsntfs_mft_entry_header_get_used_entry_size(
1027 mft_entry->header,
1028 &used_entry_size,
1029 error ) != 1 )
1030 {
1031 libcerror_error_set(
1032 error,
1033 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1034 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1035 "%s: unable to retrieve used entry size.",
1036 function );
1037
1038 goto on_error;
1039 }
1040 if( data_offset != (size_t) used_entry_size )
1041 {
1042 libcnotify_printf(
1043 "%s: mismatch in used MFT entry size (calculated: %" PRIzd ", stored: %" PRIu16 ").\n",
1044 function,
1045 data_offset,
1046 used_entry_size );
1047 }
1048 }
1049 #endif
1050 return( 1 );
1051
1052 on_error:
1053 if( mft_attribute != NULL )
1054 {
1055 libfsntfs_mft_attribute_free(
1056 &mft_attribute,
1057 NULL );
1058 }
1059 libcdata_array_empty(
1060 mft_entry->attributes_array,
1061 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
1062 NULL );
1063
1064 mft_entry->file_name_attribute_index = -1;
1065 mft_entry->reparse_point_attribute_index = -1;
1066 mft_entry->security_descriptor_attribute_index = -1;
1067 mft_entry->standard_information_attribute_index = -1;
1068 mft_entry->volume_information_attribute_index = -1;
1069 mft_entry->volume_name_attribute_index = -1;
1070 mft_entry->list_attribute = NULL;
1071 mft_entry->data_attribute = NULL;
1072 mft_entry->wof_compressed_data_attribute = NULL;
1073
1074 return( -1 );
1075 }
1076
1077 /* Reads the MFT attributes
1078 * Returns 1 if successful or -1 on error
1079 */
libfsntfs_mft_entry_read_attributes(libfsntfs_mft_entry_t * mft_entry,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfdata_vector_t * mft_entry_vector,libcdata_btree_t * attribute_list_tree,uint8_t flags,libcerror_error_t ** error)1080 int libfsntfs_mft_entry_read_attributes(
1081 libfsntfs_mft_entry_t *mft_entry,
1082 libfsntfs_io_handle_t *io_handle,
1083 libbfio_handle_t *file_io_handle,
1084 libfdata_vector_t *mft_entry_vector,
1085 libcdata_btree_t *attribute_list_tree,
1086 uint8_t flags,
1087 libcerror_error_t **error )
1088 {
1089 libcdata_tree_node_t *upper_node = NULL;
1090 libfsntfs_mft_attribute_list_t *attribute_list = NULL;
1091 libfsntfs_mft_attribute_list_t *lookup_attribute_list = NULL;
1092 static char *function = "libfsntfs_mft_entry_read_attributes";
1093 int result = 0;
1094
1095 if( mft_entry == NULL )
1096 {
1097 libcerror_error_set(
1098 error,
1099 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1100 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1101 "%s: invalid MFT entry.",
1102 function );
1103
1104 return( -1 );
1105 }
1106 if( mft_entry->attributes_read != 0 )
1107 {
1108 return( 1 );
1109 }
1110 if( mft_entry->is_empty == 0 )
1111 {
1112 if( libfsntfs_mft_entry_read_attributes_data(
1113 mft_entry,
1114 io_handle,
1115 mft_entry->data,
1116 mft_entry->data_size,
1117 error ) != 1 )
1118 {
1119 libcerror_error_set(
1120 error,
1121 LIBCERROR_ERROR_DOMAIN_IO,
1122 LIBCERROR_IO_ERROR_READ_FAILED,
1123 "%s: unable to read attributes of MFT entry: %d.",
1124 function,
1125 mft_entry->index );
1126
1127 goto on_error;
1128 }
1129 if( mft_entry->list_attribute != NULL )
1130 {
1131 if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 )
1132 {
1133 if( libfsntfs_mft_attribute_list_initialize(
1134 &lookup_attribute_list,
1135 mft_entry->file_reference,
1136 error ) != 1 )
1137 {
1138 libcerror_error_set(
1139 error,
1140 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1141 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1142 "%s: unable to create lookup attribute list.",
1143 function );
1144
1145 goto on_error;
1146 }
1147 result = libcdata_btree_get_value_by_value(
1148 attribute_list_tree,
1149 (intptr_t *) lookup_attribute_list,
1150 (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference,
1151 &upper_node,
1152 (intptr_t **) &attribute_list,
1153 error );
1154
1155 if( result == -1 )
1156 {
1157 libcerror_error_set(
1158 error,
1159 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1160 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1161 "%s: unable to retrieve path hint from tree.",
1162 function );
1163
1164 goto on_error;
1165 }
1166 if( libfsntfs_mft_attribute_list_free(
1167 &lookup_attribute_list,
1168 error ) != 1 )
1169 {
1170 libcerror_error_set(
1171 error,
1172 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1173 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1174 "%s: unable to free lookup attribute list.",
1175 function );
1176
1177 goto on_error;
1178 }
1179 }
1180 else
1181 {
1182 if( libfsntfs_mft_entry_read_attribute_list(
1183 mft_entry,
1184 io_handle,
1185 file_io_handle,
1186 error ) != 1 )
1187 {
1188 libcerror_error_set(
1189 error,
1190 LIBCERROR_ERROR_DOMAIN_IO,
1191 LIBCERROR_IO_ERROR_READ_FAILED,
1192 "%s: unable to read attribute list.",
1193 function );
1194
1195 goto on_error;
1196 }
1197 attribute_list = mft_entry->attribute_list;
1198 }
1199 if( attribute_list != NULL )
1200 {
1201 if( libfsntfs_mft_entry_read_attribute_list_data_mft_entries(
1202 mft_entry,
1203 attribute_list,
1204 io_handle,
1205 file_io_handle,
1206 mft_entry_vector,
1207 error ) != 1 )
1208 {
1209 libcerror_error_set(
1210 error,
1211 LIBCERROR_ERROR_DOMAIN_IO,
1212 LIBCERROR_IO_ERROR_READ_FAILED,
1213 "%s: unable to read attribute list data MFT entries.",
1214 function );
1215
1216 goto on_error;
1217 }
1218 }
1219 else
1220 {
1221 mft_entry->is_corrupted = 1;
1222 }
1223 }
1224 }
1225 mft_entry->attributes_read = 1;
1226
1227 return( 1 );
1228
1229 on_error:
1230 if( lookup_attribute_list != NULL )
1231 {
1232 libfsntfs_mft_attribute_list_free(
1233 &lookup_attribute_list,
1234 NULL );
1235 }
1236 if( mft_entry->attribute_list != NULL )
1237 {
1238 libfsntfs_mft_attribute_list_free(
1239 &( mft_entry->attribute_list ),
1240 NULL );
1241 }
1242 libcdata_array_empty(
1243 mft_entry->alternate_data_attributes_array,
1244 NULL,
1245 NULL );
1246
1247 libcdata_array_empty(
1248 mft_entry->attributes_array,
1249 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
1250 NULL );
1251
1252 return( -1 );
1253 }
1254
1255 /* Reads the attribute list
1256 * Returns 1 if successful or -1 on error
1257 */
libfsntfs_mft_entry_read_attribute_list(libfsntfs_mft_entry_t * mft_entry,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)1258 int libfsntfs_mft_entry_read_attribute_list(
1259 libfsntfs_mft_entry_t *mft_entry,
1260 libfsntfs_io_handle_t *io_handle,
1261 libbfio_handle_t *file_io_handle,
1262 libcerror_error_t **error )
1263 {
1264 libfsntfs_mft_attribute_list_entry_t *attribute_list_entry = NULL;
1265 static char *function = "libfsntfs_mft_entry_read_attribute_list";
1266 uint64_t attribute_list_data_mft_entry_index = 0;
1267 uint64_t file_reference = 0;
1268 int attribute_list_entry_index = 0;
1269 int number_of_attribute_list_entries = 0;
1270
1271 if( mft_entry == NULL )
1272 {
1273 libcerror_error_set(
1274 error,
1275 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1276 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1277 "%s: invalid MFT entry.",
1278 function );
1279
1280 return( -1 );
1281 }
1282 if( mft_entry->list_attribute == NULL )
1283 {
1284 libcerror_error_set(
1285 error,
1286 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1287 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1288 "%s: invalid MFT entry - missing list attribute.",
1289 function );
1290
1291 return( -1 );
1292 }
1293 if( mft_entry->attribute_list != NULL )
1294 {
1295 libcerror_error_set(
1296 error,
1297 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1299 "%s: invalid MFT entry - attribute list value already set.",
1300 function );
1301
1302 return( -1 );
1303 }
1304 if( libfsntfs_mft_attribute_list_initialize(
1305 &( mft_entry->attribute_list ),
1306 mft_entry->file_reference,
1307 error ) != 1 )
1308 {
1309 libcerror_error_set(
1310 error,
1311 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1312 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1313 "%s: unable to create attribute list.",
1314 function );
1315
1316 goto on_error;
1317 }
1318 if( libfsntfs_mft_attribute_list_read_from_attribute(
1319 mft_entry->attribute_list,
1320 io_handle,
1321 file_io_handle,
1322 mft_entry->list_attribute,
1323 error ) != 1 )
1324 {
1325 libcerror_error_set(
1326 error,
1327 LIBCERROR_ERROR_DOMAIN_IO,
1328 LIBCERROR_IO_ERROR_READ_FAILED,
1329 "%s: unable to read attribute list.",
1330 function );
1331
1332 goto on_error;
1333 }
1334 if( libfsntfs_mft_attribute_list_get_number_of_entries(
1335 mft_entry->attribute_list,
1336 &number_of_attribute_list_entries,
1337 error ) != 1 )
1338 {
1339 libcerror_error_set(
1340 error,
1341 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1342 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1343 "%s: unable to retrieve number of attribute list entries.",
1344 function );
1345
1346 goto on_error;
1347 }
1348 for( attribute_list_entry_index = 0;
1349 attribute_list_entry_index < number_of_attribute_list_entries;
1350 attribute_list_entry_index++ )
1351 {
1352 if( libfsntfs_mft_attribute_list_get_entry_by_index(
1353 mft_entry->attribute_list,
1354 attribute_list_entry_index,
1355 &attribute_list_entry,
1356 error ) != 1 )
1357 {
1358 libcerror_error_set(
1359 error,
1360 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1361 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1362 "%s: unable to retrieve attribute list entry: %d.",
1363 function,
1364 attribute_list_entry_index );
1365
1366 goto on_error;
1367 }
1368 if( libfsntfs_mft_attribute_list_entry_get_file_reference(
1369 attribute_list_entry,
1370 &file_reference,
1371 error ) != 1 )
1372 {
1373 libcerror_error_set(
1374 error,
1375 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1376 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1377 "%s: unable to retrieve attribute list entry: %d file reference.",
1378 function,
1379 attribute_list_entry_index );
1380
1381 goto on_error;
1382 }
1383 attribute_list_data_mft_entry_index = file_reference & 0xffffffffffffUL;
1384
1385 if( attribute_list_data_mft_entry_index > (uint64_t) INT_MAX )
1386 {
1387 libcerror_error_set(
1388 error,
1389 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1390 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1391 "%s: attribute list data MFT entry reference value out of bounds.",
1392 function );
1393
1394 goto on_error;
1395 }
1396 /* Ignore the current MFT entry
1397 */
1398 if( attribute_list_data_mft_entry_index == (uint64_t) mft_entry->index )
1399 {
1400 continue;
1401 }
1402 if( libfsntfs_mft_attribute_list_insert_file_reference(
1403 mft_entry->attribute_list,
1404 file_reference,
1405 error ) == -1 )
1406 {
1407 libcerror_error_set(
1408 error,
1409 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1410 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1411 "%s: unable to insert attribute list data file reference in attribute list.",
1412 function );
1413
1414 goto on_error;
1415 }
1416 }
1417 return( 1 );
1418
1419 on_error:
1420 if( mft_entry->attribute_list != NULL )
1421 {
1422 libfsntfs_mft_attribute_list_free(
1423 &( mft_entry->attribute_list ),
1424 NULL );
1425 }
1426 return( -1 );
1427 }
1428
1429 /* Reads a specific attribute list data MFT entry
1430 * Returns 1 if successful, 0 if not available or -1 on error
1431 */
libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(libfsntfs_mft_entry_t * mft_entry,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfdata_vector_t * mft_entry_vector,libfcache_cache_t * mft_entry_cache,uint64_t file_reference,libcerror_error_t ** error)1432 int libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(
1433 libfsntfs_mft_entry_t *mft_entry,
1434 libfsntfs_io_handle_t *io_handle,
1435 libbfio_handle_t *file_io_handle,
1436 libfdata_vector_t *mft_entry_vector,
1437 libfcache_cache_t *mft_entry_cache,
1438 uint64_t file_reference,
1439 libcerror_error_t **error )
1440 {
1441 libfsntfs_mft_attribute_t *data_mft_attribute = NULL;
1442 libfsntfs_mft_attribute_t *mft_attribute = NULL;
1443 libfsntfs_mft_entry_t *data_mft_entry = NULL;
1444 static char *function = "libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index";
1445 uint64_t attribute_list_data_mft_entry = 0;
1446 uint64_t base_record_file_reference = 0;
1447 int attribute_index = 0;
1448 int entry_index = 0;
1449 int number_of_attributes = 0;
1450
1451 if( mft_entry == NULL )
1452 {
1453 libcerror_error_set(
1454 error,
1455 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1456 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1457 "%s: invalid MFT entry.",
1458 function );
1459
1460 return( -1 );
1461 }
1462 attribute_list_data_mft_entry = file_reference & 0xffffffffffffUL;
1463
1464 #if defined( HAVE_DEBUG_OUTPUT )
1465 if( libcnotify_verbose != 0 )
1466 {
1467 libcnotify_printf(
1468 "%s: reading data file reference: %" PRIu64 "-%" PRIu16 "\n",
1469 function,
1470 attribute_list_data_mft_entry,
1471 (uint16_t) ( file_reference >> 48 ) );
1472 libcnotify_printf(
1473 "\n" );
1474 }
1475 #endif
1476 if( libfdata_vector_get_element_value_by_index(
1477 mft_entry_vector,
1478 (intptr_t *) file_io_handle,
1479 (libfdata_cache_t *) mft_entry_cache,
1480 (int) attribute_list_data_mft_entry,
1481 (intptr_t **) &data_mft_entry,
1482 0,
1483 error ) != 1 )
1484 {
1485 libcerror_error_set(
1486 error,
1487 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1488 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1489 "%s: unable to retrieve MFT entry: %" PRIu64 ".",
1490 function,
1491 attribute_list_data_mft_entry );
1492
1493 return( -1 );
1494 }
1495 if( data_mft_entry->header == NULL )
1496 {
1497 return( 0 );
1498 }
1499 if( libfsntfs_mft_entry_header_get_base_record_file_reference(
1500 data_mft_entry->header,
1501 &base_record_file_reference,
1502 error ) != 1 )
1503 {
1504 libcerror_error_set(
1505 error,
1506 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1507 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1508 "%s: unable to retrieve base record file reference.",
1509 function );
1510
1511 return( -1 );
1512 }
1513 if( mft_entry->file_reference != base_record_file_reference )
1514 {
1515 return( 0 );
1516 }
1517 if( libfsntfs_mft_entry_read_attributes_data(
1518 data_mft_entry,
1519 io_handle,
1520 data_mft_entry->data,
1521 data_mft_entry->data_size,
1522 error ) != 1 )
1523 {
1524 libcerror_error_set(
1525 error,
1526 LIBCERROR_ERROR_DOMAIN_IO,
1527 LIBCERROR_IO_ERROR_READ_FAILED,
1528 "%s: unable to read attributes.",
1529 function );
1530
1531 return( -1 );
1532 }
1533 if( libcdata_array_get_number_of_entries(
1534 data_mft_entry->attributes_array,
1535 &number_of_attributes,
1536 error ) != 1 )
1537 {
1538 libcerror_error_set(
1539 error,
1540 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1541 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1542 "%s: unable to retrieve number of attributes.",
1543 function );
1544
1545 return( -1 );
1546 }
1547 for( attribute_index = 0;
1548 attribute_index < number_of_attributes;
1549 attribute_index++ )
1550 {
1551 if( libcdata_array_get_entry_by_index(
1552 data_mft_entry->attributes_array,
1553 attribute_index,
1554 (intptr_t **) &mft_attribute,
1555 error ) != 1 )
1556 {
1557 libcerror_error_set(
1558 error,
1559 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1560 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1561 "%s: unable to retrieve attribute: %d from list MFT entry.",
1562 function,
1563 attribute_index );
1564
1565 return( -1 );
1566 }
1567 if( libfsntfs_mft_attribute_clone(
1568 &data_mft_attribute,
1569 mft_attribute,
1570 error ) != 1 )
1571 {
1572 libcerror_error_set(
1573 error,
1574 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1575 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1576 "%s: unable to clone MFT attribute: %d.",
1577 function,
1578 attribute_index );
1579
1580 return( -1 );
1581 }
1582 /* mft_entry->attributes_array takes over management of data_mft_attribute
1583 */
1584 if( libcdata_array_append_entry(
1585 mft_entry->attributes_array,
1586 &entry_index,
1587 (intptr_t *) data_mft_attribute,
1588 error ) != 1 )
1589 {
1590 libcerror_error_set(
1591 error,
1592 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1593 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1594 "%s: unable to append MFT attribute to array.",
1595 function );
1596
1597 libfsntfs_mft_attribute_free(
1598 &data_mft_attribute,
1599 NULL );
1600
1601 return( -1 );
1602 }
1603 if( libfsntfs_mft_entry_set_attribute_helper_values(
1604 mft_entry,
1605 entry_index,
1606 data_mft_attribute,
1607 error ) != 1 )
1608 {
1609 libcerror_error_set(
1610 error,
1611 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1612 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1613 "%s: unable to set helper values for attribute: %d.",
1614 function,
1615 entry_index );
1616
1617 return( -1 );
1618 }
1619 data_mft_attribute = NULL;
1620 }
1621 return( 1 );
1622 }
1623
1624 /* Reads the attribute list data MFT entries
1625 * Returns 1 if successful or -1 on error
1626 */
libfsntfs_mft_entry_read_attribute_list_data_mft_entries(libfsntfs_mft_entry_t * mft_entry,libfsntfs_mft_attribute_list_t * attribute_list,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfdata_vector_t * mft_entry_vector,libcerror_error_t ** error)1627 int libfsntfs_mft_entry_read_attribute_list_data_mft_entries(
1628 libfsntfs_mft_entry_t *mft_entry,
1629 libfsntfs_mft_attribute_list_t *attribute_list,
1630 libfsntfs_io_handle_t *io_handle,
1631 libbfio_handle_t *file_io_handle,
1632 libfdata_vector_t *mft_entry_vector,
1633 libcerror_error_t **error )
1634 {
1635 libfcache_cache_t *mft_entry_cache = NULL;
1636 static char *function = "libfsntfs_mft_entry_read_attribute_list_data_mft_entries";
1637 uint64_t file_reference = 0;
1638 int file_reference_index = 0;
1639 int number_of_file_entries = 0;
1640 int result = 0;
1641
1642 if( mft_entry == NULL )
1643 {
1644 libcerror_error_set(
1645 error,
1646 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1647 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1648 "%s: invalid MFT entry.",
1649 function );
1650
1651 return( -1 );
1652 }
1653 /* Read the list data MFT entries
1654 * Use a local cache to prevent cache outs
1655 */
1656 if( libfcache_cache_initialize(
1657 &mft_entry_cache,
1658 1,
1659 error ) != 1 )
1660 {
1661 libcerror_error_set(
1662 error,
1663 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1664 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1665 "%s: unable to create MFT entry cache.",
1666 function );
1667
1668 goto on_error;
1669 }
1670 if( libfsntfs_mft_attribute_list_get_number_of_file_references(
1671 attribute_list,
1672 &number_of_file_entries,
1673 error ) != 1 )
1674 {
1675 libcerror_error_set(
1676 error,
1677 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1678 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1679 "%s: unable to retrieve number of attribute list data MFT entries.",
1680 function );
1681
1682 goto on_error;
1683 }
1684 for( file_reference_index = 0;
1685 file_reference_index < number_of_file_entries;
1686 file_reference_index++ )
1687 {
1688 if( libfsntfs_mft_attribute_list_get_file_reference_by_index(
1689 attribute_list,
1690 file_reference_index,
1691 &file_reference,
1692 error ) != 1 )
1693 {
1694 libcerror_error_set(
1695 error,
1696 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1697 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1698 "%s: unable to retrieve attribute list data MFT entry: %d.",
1699 function,
1700 file_reference_index );
1701
1702 goto on_error;
1703 }
1704 result = libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(
1705 mft_entry,
1706 io_handle,
1707 file_io_handle,
1708 mft_entry_vector,
1709 mft_entry_cache,
1710 file_reference,
1711 error );
1712
1713 if( result == -1 )
1714 {
1715 libcerror_error_set(
1716 error,
1717 LIBCERROR_ERROR_DOMAIN_IO,
1718 LIBCERROR_IO_ERROR_READ_FAILED,
1719 "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".",
1720 function,
1721 file_reference & 0xffffffffffffUL,
1722 file_reference >> 48 );
1723
1724 goto on_error;
1725 }
1726 else if( result == 0 )
1727 {
1728 mft_entry->is_corrupted = 1;
1729 }
1730 }
1731 if( libfcache_cache_free(
1732 &mft_entry_cache,
1733 error ) != 1 )
1734 {
1735 libcerror_error_set(
1736 error,
1737 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1738 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1739 "%s: unable to free MFT entry cache.",
1740 function );
1741
1742 goto on_error;
1743 }
1744 return( 1 );
1745
1746 on_error:
1747 if( mft_entry_cache != NULL )
1748 {
1749 libfcache_cache_free(
1750 &mft_entry_cache,
1751 NULL );
1752 }
1753 return( -1 );
1754 }
1755
1756 /* Determines if the MFT entry is empty
1757 * Returns 1 if empty, 0 if not or -1 on error
1758 */
libfsntfs_mft_entry_is_empty(libfsntfs_mft_entry_t * mft_entry,libcerror_error_t ** error)1759 int libfsntfs_mft_entry_is_empty(
1760 libfsntfs_mft_entry_t *mft_entry,
1761 libcerror_error_t **error )
1762 {
1763 static char *function = "libfsntfs_mft_entry_is_empty";
1764
1765 if( mft_entry == NULL )
1766 {
1767 libcerror_error_set(
1768 error,
1769 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1770 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1771 "%s: invalid MFT entry.",
1772 function );
1773
1774 return( -1 );
1775 }
1776 return( (int) mft_entry->is_empty );
1777 }
1778
1779 /* Determines if the MFT entry is allocated (in use)
1780 * Returns 1 if allocated, 0 if not or -1 on error
1781 */
libfsntfs_mft_entry_is_allocated(libfsntfs_mft_entry_t * mft_entry,libcerror_error_t ** error)1782 int libfsntfs_mft_entry_is_allocated(
1783 libfsntfs_mft_entry_t *mft_entry,
1784 libcerror_error_t **error )
1785 {
1786 static char *function = "libfsntfs_mft_entry_is_allocated";
1787
1788 if( mft_entry == NULL )
1789 {
1790 libcerror_error_set(
1791 error,
1792 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1793 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1794 "%s: invalid MFT entry.",
1795 function );
1796
1797 return( -1 );
1798 }
1799 if( mft_entry->header == NULL )
1800 {
1801 libcerror_error_set(
1802 error,
1803 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1804 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1805 "%s: invalid MFT entry - missing header.",
1806 function );
1807
1808 return( -1 );
1809 }
1810 if( ( mft_entry->header->flags & LIBFSNTFS_MFT_ENTRY_FLAG_IN_USE ) != 0 )
1811 {
1812 return( 1 );
1813 }
1814 return( 0 );
1815 }
1816
1817 /* Determines if the MFT entry is corrupted
1818 * Returns 1 if corrupted, 0 if not or -1 on error
1819 */
libfsntfs_mft_entry_is_corrupted(libfsntfs_mft_entry_t * mft_entry,libcerror_error_t ** error)1820 int libfsntfs_mft_entry_is_corrupted(
1821 libfsntfs_mft_entry_t *mft_entry,
1822 libcerror_error_t **error )
1823 {
1824 static char *function = "libfsntfs_mft_entry_is_corrupted";
1825
1826 if( mft_entry == NULL )
1827 {
1828 libcerror_error_set(
1829 error,
1830 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1831 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1832 "%s: invalid MFT entry.",
1833 function );
1834
1835 return( -1 );
1836 }
1837 return( (int) mft_entry->is_corrupted );
1838 }
1839
1840 /* Retrieves the file reference
1841 * Returns 1 if successful or -1 on error
1842 */
libfsntfs_mft_entry_get_file_reference(libfsntfs_mft_entry_t * mft_entry,uint64_t * file_reference,libcerror_error_t ** error)1843 int libfsntfs_mft_entry_get_file_reference(
1844 libfsntfs_mft_entry_t *mft_entry,
1845 uint64_t *file_reference,
1846 libcerror_error_t **error )
1847 {
1848 static char *function = "libfsntfs_mft_entry_get_file_reference";
1849
1850 if( mft_entry == NULL )
1851 {
1852 libcerror_error_set(
1853 error,
1854 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1855 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1856 "%s: invalid MFT entry.",
1857 function );
1858
1859 return( -1 );
1860 }
1861 if( file_reference == NULL )
1862 {
1863 libcerror_error_set(
1864 error,
1865 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1866 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1867 "%s: invalid file reference.",
1868 function );
1869
1870 return( -1 );
1871 }
1872 *file_reference = mft_entry->file_reference;
1873
1874 return( 1 );
1875 }
1876
1877 /* Retrieves the base record file reference
1878 * Returns 1 if successful, 0 if not available or -1 on error
1879 */
libfsntfs_mft_entry_get_base_record_file_reference(libfsntfs_mft_entry_t * mft_entry,uint64_t * file_reference,libcerror_error_t ** error)1880 int libfsntfs_mft_entry_get_base_record_file_reference(
1881 libfsntfs_mft_entry_t *mft_entry,
1882 uint64_t *file_reference,
1883 libcerror_error_t **error )
1884 {
1885 static char *function = "libfsntfs_mft_entry_get_base_record_file_reference";
1886
1887 if( mft_entry == NULL )
1888 {
1889 libcerror_error_set(
1890 error,
1891 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1892 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1893 "%s: invalid MFT entry.",
1894 function );
1895
1896 return( -1 );
1897 }
1898 if( mft_entry->header == NULL )
1899 {
1900 return( 0 );
1901 }
1902 if( libfsntfs_mft_entry_header_get_base_record_file_reference(
1903 mft_entry->header,
1904 file_reference,
1905 error ) != 1 )
1906 {
1907 libcerror_error_set(
1908 error,
1909 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1910 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1911 "%s: unable to retrieve base record file reference.",
1912 function );
1913
1914 return( -1 );
1915 }
1916 return( 1 );
1917 }
1918
1919 /* Retrieves the journal sequence number
1920 * Returns 1 if successful or -1 on error
1921 */
libfsntfs_mft_entry_get_journal_sequence_number(libfsntfs_mft_entry_t * mft_entry,uint64_t * journal_sequence_number,libcerror_error_t ** error)1922 int libfsntfs_mft_entry_get_journal_sequence_number(
1923 libfsntfs_mft_entry_t *mft_entry,
1924 uint64_t *journal_sequence_number,
1925 libcerror_error_t **error )
1926 {
1927 static char *function = "libfsntfs_mft_entry_get_journal_sequence_number";
1928
1929 if( mft_entry == NULL )
1930 {
1931 libcerror_error_set(
1932 error,
1933 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1934 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1935 "%s: invalid MFT entry.",
1936 function );
1937
1938 return( -1 );
1939 }
1940 if( libfsntfs_mft_entry_header_get_journal_sequence_number(
1941 mft_entry->header,
1942 journal_sequence_number,
1943 error ) != 1 )
1944 {
1945 libcerror_error_set(
1946 error,
1947 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1948 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1949 "%s: unable to retrieve journal sequence number.",
1950 function );
1951
1952 return( -1 );
1953 }
1954 return( 1 );
1955 }
1956
1957 /* Retrieves the number of attributes
1958 * Returns 1 if successful or -1 on error
1959 */
libfsntfs_mft_entry_get_number_of_attributes(libfsntfs_mft_entry_t * mft_entry,int * number_of_attributes,libcerror_error_t ** error)1960 int libfsntfs_mft_entry_get_number_of_attributes(
1961 libfsntfs_mft_entry_t *mft_entry,
1962 int *number_of_attributes,
1963 libcerror_error_t **error )
1964 {
1965 static char *function = "libfsntfs_mft_entry_get_number_of_attributes";
1966
1967 if( mft_entry == NULL )
1968 {
1969 libcerror_error_set(
1970 error,
1971 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1972 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1973 "%s: invalid MFT entry.",
1974 function );
1975
1976 return( -1 );
1977 }
1978 if( libcdata_array_get_number_of_entries(
1979 mft_entry->attributes_array,
1980 number_of_attributes,
1981 error ) != 1 )
1982 {
1983 libcerror_error_set(
1984 error,
1985 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1986 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1987 "%s: unable to retrieve number of entries from attributes array.",
1988 function );
1989
1990 return( -1 );
1991 }
1992 return( 1 );
1993 }
1994
1995 /* Retrieves a specific attribute
1996 * Returns 1 if successful or -1 on error
1997 */
libfsntfs_mft_entry_get_attribute_by_index(libfsntfs_mft_entry_t * mft_entry,int attribute_index,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)1998 int libfsntfs_mft_entry_get_attribute_by_index(
1999 libfsntfs_mft_entry_t *mft_entry,
2000 int attribute_index,
2001 libfsntfs_mft_attribute_t **attribute,
2002 libcerror_error_t **error )
2003 {
2004 static char *function = "libfsntfs_mft_entry_get_attribute_by_index";
2005
2006 if( mft_entry == NULL )
2007 {
2008 libcerror_error_set(
2009 error,
2010 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2011 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2012 "%s: invalid MFT entry.",
2013 function );
2014
2015 return( -1 );
2016 }
2017 if( libcdata_array_get_entry_by_index(
2018 mft_entry->attributes_array,
2019 attribute_index,
2020 (intptr_t **) attribute,
2021 error ) != 1 )
2022 {
2023 libcerror_error_set(
2024 error,
2025 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2026 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2027 "%s: unable to retrieve entry: %d from attributes array.",
2028 function,
2029 attribute_index );
2030
2031 return( -1 );
2032 }
2033 return( 1 );
2034 }
2035
2036 /* Retrieves the $STANDARD_INFORMATION attribute
2037 * Returns 1 if successful, 0 if not available or -1 on error
2038 */
libfsntfs_mft_entry_get_standard_information_attribute(libfsntfs_mft_entry_t * mft_entry,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2039 int libfsntfs_mft_entry_get_standard_information_attribute(
2040 libfsntfs_mft_entry_t *mft_entry,
2041 libfsntfs_mft_attribute_t **attribute,
2042 libcerror_error_t **error )
2043 {
2044 static char *function = "libfsntfs_mft_entry_get_standard_information_attribute";
2045
2046 if( mft_entry == NULL )
2047 {
2048 libcerror_error_set(
2049 error,
2050 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2051 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2052 "%s: invalid MFT entry.",
2053 function );
2054
2055 return( -1 );
2056 }
2057 if( mft_entry->standard_information_attribute_index == -1 )
2058 {
2059 return( 0 );
2060 }
2061 if( libcdata_array_get_entry_by_index(
2062 mft_entry->attributes_array,
2063 mft_entry->standard_information_attribute_index,
2064 (intptr_t **) attribute,
2065 error ) != 1 )
2066 {
2067 libcerror_error_set(
2068 error,
2069 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2070 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2071 "%s: unable to retrieve entry: %d from attributes array.",
2072 function,
2073 mft_entry->standard_information_attribute_index );
2074
2075 return( -1 );
2076 }
2077 return( 1 );
2078 }
2079
2080 /* Retrieves the $VOLUME_INFORMATION attribute
2081 * Returns 1 if successful, 0 if not available or -1 on error
2082 */
libfsntfs_mft_entry_get_volume_information_attribute(libfsntfs_mft_entry_t * mft_entry,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2083 int libfsntfs_mft_entry_get_volume_information_attribute(
2084 libfsntfs_mft_entry_t *mft_entry,
2085 libfsntfs_mft_attribute_t **attribute,
2086 libcerror_error_t **error )
2087 {
2088 static char *function = "libfsntfs_mft_entry_get_volume_information_attribute";
2089
2090 if( mft_entry == NULL )
2091 {
2092 libcerror_error_set(
2093 error,
2094 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2095 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2096 "%s: invalid MFT entry.",
2097 function );
2098
2099 return( -1 );
2100 }
2101 if( mft_entry->volume_information_attribute_index == -1 )
2102 {
2103 return( 0 );
2104 }
2105 if( libcdata_array_get_entry_by_index(
2106 mft_entry->attributes_array,
2107 mft_entry->volume_information_attribute_index,
2108 (intptr_t **) attribute,
2109 error ) != 1 )
2110 {
2111 libcerror_error_set(
2112 error,
2113 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2114 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2115 "%s: unable to retrieve entry: %d from attributes array.",
2116 function,
2117 mft_entry->volume_information_attribute_index );
2118
2119 return( -1 );
2120 }
2121 return( 1 );
2122 }
2123
2124 /* Retrieves the $VOLUME_NAME attribute
2125 * Returns 1 if successful, 0 if not available or -1 on error
2126 */
libfsntfs_mft_entry_get_volume_name_attribute(libfsntfs_mft_entry_t * mft_entry,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2127 int libfsntfs_mft_entry_get_volume_name_attribute(
2128 libfsntfs_mft_entry_t *mft_entry,
2129 libfsntfs_mft_attribute_t **attribute,
2130 libcerror_error_t **error )
2131 {
2132 static char *function = "libfsntfs_mft_entry_get_volume_name_attribute";
2133
2134 if( mft_entry == NULL )
2135 {
2136 libcerror_error_set(
2137 error,
2138 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2139 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2140 "%s: invalid MFT entry.",
2141 function );
2142
2143 return( -1 );
2144 }
2145 if( mft_entry->volume_name_attribute_index == -1 )
2146 {
2147 return( 0 );
2148 }
2149 if( libcdata_array_get_entry_by_index(
2150 mft_entry->attributes_array,
2151 mft_entry->volume_name_attribute_index,
2152 (intptr_t **) attribute,
2153 error ) != 1 )
2154 {
2155 libcerror_error_set(
2156 error,
2157 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2158 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2159 "%s: unable to retrieve entry: %d from attributes array.",
2160 function,
2161 mft_entry->volume_name_attribute_index );
2162
2163 return( -1 );
2164 }
2165 return( 1 );
2166 }
2167
2168 /* Retrieves the number of alternate data attributes
2169 * Returns 1 if successful or -1 on error
2170 */
libfsntfs_mft_entry_get_number_of_alternate_data_attributes(libfsntfs_mft_entry_t * mft_entry,int * number_of_attributes,libcerror_error_t ** error)2171 int libfsntfs_mft_entry_get_number_of_alternate_data_attributes(
2172 libfsntfs_mft_entry_t *mft_entry,
2173 int *number_of_attributes,
2174 libcerror_error_t **error )
2175 {
2176 static char *function = "libfsntfs_mft_entry_get_number_of_alternate_data_attributes";
2177
2178 if( mft_entry == NULL )
2179 {
2180 libcerror_error_set(
2181 error,
2182 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2183 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2184 "%s: invalid MFT entry.",
2185 function );
2186
2187 return( -1 );
2188 }
2189 if( libcdata_array_get_number_of_entries(
2190 mft_entry->alternate_data_attributes_array,
2191 number_of_attributes,
2192 error ) != 1 )
2193 {
2194 libcerror_error_set(
2195 error,
2196 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2197 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2198 "%s: unable to retrieve number of entries from alternate data attributes array.",
2199 function );
2200
2201 return( -1 );
2202 }
2203 return( 1 );
2204 }
2205
2206 /* Retrieves a specific alternate data attribute
2207 * Returns 1 if successful or -1 on error
2208 */
libfsntfs_mft_entry_get_alternate_data_attribute_by_index(libfsntfs_mft_entry_t * mft_entry,int attribute_index,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2209 int libfsntfs_mft_entry_get_alternate_data_attribute_by_index(
2210 libfsntfs_mft_entry_t *mft_entry,
2211 int attribute_index,
2212 libfsntfs_mft_attribute_t **attribute,
2213 libcerror_error_t **error )
2214 {
2215 static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_index";
2216
2217 if( mft_entry == NULL )
2218 {
2219 libcerror_error_set(
2220 error,
2221 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2222 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2223 "%s: invalid MFT entry.",
2224 function );
2225
2226 return( -1 );
2227 }
2228 if( libcdata_array_get_entry_by_index(
2229 mft_entry->alternate_data_attributes_array,
2230 attribute_index,
2231 (intptr_t **) attribute,
2232 error ) != 1 )
2233 {
2234 libcerror_error_set(
2235 error,
2236 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2237 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2238 "%s: unable to retrieve entry: %d from alternate data attributes array.",
2239 function,
2240 attribute_index );
2241
2242 return( -1 );
2243 }
2244 return( 1 );
2245 }
2246
2247 /* Retrieves a specific alternate data attribute for an UTF-8 encoded name
2248 * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error
2249 */
libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name(libfsntfs_mft_entry_t * mft_entry,const uint8_t * utf8_string,size_t utf8_string_length,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2250 int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name(
2251 libfsntfs_mft_entry_t *mft_entry,
2252 const uint8_t *utf8_string,
2253 size_t utf8_string_length,
2254 libfsntfs_mft_attribute_t **attribute,
2255 libcerror_error_t **error )
2256 {
2257 static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name";
2258 int attribute_index = 0;
2259 int number_of_attributes = 0;
2260 int result = 0;
2261
2262 if( mft_entry == NULL )
2263 {
2264 libcerror_error_set(
2265 error,
2266 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2267 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2268 "%s: invalid MFT entry.",
2269 function );
2270
2271 return( -1 );
2272 }
2273 if( attribute == NULL )
2274 {
2275 libcerror_error_set(
2276 error,
2277 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2278 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2279 "%s: invalid attribute.",
2280 function );
2281
2282 return( -1 );
2283 }
2284 if( libcdata_array_get_number_of_entries(
2285 mft_entry->alternate_data_attributes_array,
2286 &number_of_attributes,
2287 error ) != 1 )
2288 {
2289 libcerror_error_set(
2290 error,
2291 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2292 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2293 "%s: unable to retrieve number of entries from alternate data attributes array.",
2294 function );
2295
2296 return( -1 );
2297 }
2298 for( attribute_index = 0;
2299 attribute_index < number_of_attributes;
2300 attribute_index++ )
2301 {
2302 if( libcdata_array_get_entry_by_index(
2303 mft_entry->alternate_data_attributes_array,
2304 attribute_index,
2305 (intptr_t **) attribute,
2306 error ) != 1 )
2307 {
2308 libcerror_error_set(
2309 error,
2310 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2311 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2312 "%s: unable to retrieve entry: %d from alternative data attributes array.",
2313 function,
2314 attribute_index );
2315
2316 return( -1 );
2317 }
2318 result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
2319 *attribute,
2320 utf8_string,
2321 utf8_string_length,
2322 error );
2323
2324 if( result == -1 )
2325 {
2326 libcerror_error_set(
2327 error,
2328 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2329 LIBCERROR_RUNTIME_ERROR_GENERIC,
2330 "%s: unable to compare UTF-8 string with alternative data attribute name.",
2331 function );
2332
2333 goto on_error;
2334 }
2335 else if( result == 1 )
2336 {
2337 return( 1 );
2338 }
2339 }
2340 *attribute = NULL;
2341
2342 return( 0 );
2343
2344 on_error:
2345 *attribute = NULL;
2346
2347 return( -1 );
2348 }
2349
2350 /* Retrieves a specific alternate data attribute for an UTF-16 encoded name
2351 * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error
2352 */
libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name(libfsntfs_mft_entry_t * mft_entry,const uint16_t * utf16_string,size_t utf16_string_length,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2353 int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name(
2354 libfsntfs_mft_entry_t *mft_entry,
2355 const uint16_t *utf16_string,
2356 size_t utf16_string_length,
2357 libfsntfs_mft_attribute_t **attribute,
2358 libcerror_error_t **error )
2359 {
2360 static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name";
2361 int attribute_index = 0;
2362 int number_of_attributes = 0;
2363 int result = 0;
2364
2365 if( mft_entry == NULL )
2366 {
2367 libcerror_error_set(
2368 error,
2369 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2370 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2371 "%s: invalid MFT entry.",
2372 function );
2373
2374 return( -1 );
2375 }
2376 if( attribute == NULL )
2377 {
2378 libcerror_error_set(
2379 error,
2380 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2381 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2382 "%s: invalid attribute.",
2383 function );
2384
2385 return( -1 );
2386 }
2387 if( libcdata_array_get_number_of_entries(
2388 mft_entry->alternate_data_attributes_array,
2389 &number_of_attributes,
2390 error ) != 1 )
2391 {
2392 libcerror_error_set(
2393 error,
2394 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2395 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2396 "%s: unable to retrieve number of entries from alternate data attributes array.",
2397 function );
2398
2399 return( -1 );
2400 }
2401 for( attribute_index = 0;
2402 attribute_index < number_of_attributes;
2403 attribute_index++ )
2404 {
2405 if( libcdata_array_get_entry_by_index(
2406 mft_entry->alternate_data_attributes_array,
2407 attribute_index,
2408 (intptr_t **) attribute,
2409 error ) != 1 )
2410 {
2411 libcerror_error_set(
2412 error,
2413 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2414 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2415 "%s: unable to retrieve entry: %d from alternative data attributes array.",
2416 function,
2417 attribute_index );
2418
2419 return( -1 );
2420 }
2421 result = libfsntfs_mft_attribute_compare_name_with_utf16_string(
2422 *attribute,
2423 utf16_string,
2424 utf16_string_length,
2425 error );
2426
2427 if( result == -1 )
2428 {
2429 libcerror_error_set(
2430 error,
2431 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2432 LIBCERROR_RUNTIME_ERROR_GENERIC,
2433 "%s: unable to compare UTF-16 string with alternative data attribute name.",
2434 function );
2435
2436 goto on_error;
2437 }
2438 else if( result == 1 )
2439 {
2440 return( 1 );
2441 }
2442 }
2443 *attribute = NULL;
2444
2445 return( 0 );
2446
2447 on_error:
2448 *attribute = NULL;
2449
2450 return( -1 );
2451 }
2452
2453 /* Sets the attribute helper values for an attribute
2454 * Returns 1 if successful or -1 on error
2455 */
libfsntfs_mft_entry_set_attribute_helper_values(libfsntfs_mft_entry_t * mft_entry,int attribute_index,libfsntfs_mft_attribute_t * attribute,libcerror_error_t ** error)2456 int libfsntfs_mft_entry_set_attribute_helper_values(
2457 libfsntfs_mft_entry_t *mft_entry,
2458 int attribute_index,
2459 libfsntfs_mft_attribute_t *attribute,
2460 libcerror_error_t **error )
2461 {
2462 uint8_t utf8_attribute_name[ 64 ];
2463
2464 static char *function = "libfsntfs_mft_entry_set_attribute_helper_values";
2465 size_t utf8_attribute_name_size = 0;
2466 uint32_t attribute_type = 0;
2467 int result = 0;
2468
2469 #if defined( HAVE_DEBUG_OUTPUT )
2470 libfsntfs_standard_information_values_t *standard_information_values = NULL;
2471 #endif
2472
2473 if( mft_entry == NULL )
2474 {
2475 libcerror_error_set(
2476 error,
2477 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2478 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2479 "%s: invalid MFT entry.",
2480 function );
2481
2482 return( -1 );
2483 }
2484 if( libfsntfs_mft_attribute_get_utf8_name_size(
2485 attribute,
2486 &utf8_attribute_name_size,
2487 error ) != 1 )
2488 {
2489 libcerror_error_set(
2490 error,
2491 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2492 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2493 "%s: unable to retrieve UTF-8 attribute name size.",
2494 function );
2495
2496 return( -1 );
2497 }
2498 if( libfsntfs_mft_attribute_get_type(
2499 attribute,
2500 &attribute_type,
2501 error ) != 1 )
2502 {
2503 libcerror_error_set(
2504 error,
2505 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2506 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2507 "%s: unable to retrieve attribute type.",
2508 function );
2509
2510 return( -1 );
2511 }
2512 switch( attribute_type )
2513 {
2514 case LIBFSNTFS_ATTRIBUTE_TYPE_DATA:
2515 if( libfsntfs_mft_entry_set_data_attribute_helper_values(
2516 mft_entry,
2517 attribute,
2518 error ) != 1 )
2519 {
2520 libcerror_error_set(
2521 error,
2522 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2523 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2524 "%s: unable to set data attribute helper values.",
2525 function );
2526
2527 return( -1 );
2528 }
2529 break;
2530
2531 case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME:
2532 if( mft_entry->file_name_attribute_index == -1 )
2533 {
2534 mft_entry->file_name_attribute_index = attribute_index;
2535 }
2536 break;
2537
2538 case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT:
2539 if( libfsntfs_mft_attribute_get_utf8_name(
2540 attribute,
2541 utf8_attribute_name,
2542 64,
2543 error ) != 1 )
2544 {
2545 libcerror_error_set(
2546 error,
2547 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2548 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2549 "%s: unable to retrieve UTF-8 attribute name.",
2550 function );
2551
2552 return( -1 );
2553 }
2554 result = libuna_utf8_string_compare_with_utf8_stream(
2555 utf8_attribute_name,
2556 utf8_attribute_name_size,
2557 (uint8_t *) "$I30",
2558 4,
2559 error );
2560
2561 if( result == -1 )
2562 {
2563 libcerror_error_set(
2564 error,
2565 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2566 LIBCERROR_RUNTIME_ERROR_GENERIC,
2567 "%s: unable to compare UTF-8 string with $I30.",
2568 function );
2569
2570 return( -1 );
2571 }
2572 else if( result == LIBUNA_COMPARE_EQUAL )
2573 {
2574 mft_entry->has_i30_index = 1;
2575 }
2576 break;
2577
2578 case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT:
2579 /* Assume only one reparse point attribute per MFT entry is allowed
2580 */
2581 if( mft_entry->reparse_point_attribute_index != -1 )
2582 {
2583 libcerror_error_set(
2584 error,
2585 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2586 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2587 "%s: invalid MFT entry - reparse point attribute index value already set.",
2588 function );
2589
2590 return( -1 );
2591 }
2592 mft_entry->reparse_point_attribute_index = attribute_index;
2593
2594 break;
2595
2596 case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR:
2597 /* Assume only one security descriptor attribute per MFT entry is allowed
2598 */
2599 if( mft_entry->security_descriptor_attribute_index != -1 )
2600 {
2601 libcerror_error_set(
2602 error,
2603 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2604 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2605 "%s: invalid MFT entry - security descriptor attribute index value already set.",
2606 function );
2607
2608 return( -1 );
2609 }
2610 mft_entry->security_descriptor_attribute_index = attribute_index;
2611
2612 break;
2613
2614 case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION:
2615 #if defined( HAVE_DEBUG_OUTPUT )
2616 if( libfsntfs_standard_information_values_initialize(
2617 &standard_information_values,
2618 error ) != 1 )
2619 {
2620 libcerror_error_set(
2621 error,
2622 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2623 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2624 "%s: unable to create standard information values.",
2625 function );
2626
2627 return( -1 );
2628 }
2629 if( libfsntfs_standard_information_values_read_from_mft_attribute(
2630 standard_information_values,
2631 attribute,
2632 error ) != 1 )
2633 {
2634 libcerror_error_set(
2635 error,
2636 LIBCERROR_ERROR_DOMAIN_IO,
2637 LIBCERROR_IO_ERROR_READ_FAILED,
2638 "%s: unable to read standard information values from MFT attribute.",
2639 function );
2640
2641 libfsntfs_standard_information_values_free(
2642 &standard_information_values,
2643 NULL );
2644
2645 return( -1 );
2646 }
2647 if( libfsntfs_standard_information_values_free(
2648 &standard_information_values,
2649 error ) != 1 )
2650 {
2651 libcerror_error_set(
2652 error,
2653 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2654 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2655 "%s: unable to free standard information values.",
2656 function );
2657
2658 return( -1 );
2659 }
2660 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
2661
2662 /* Assume only one standard information attribute per MFT entry is allowed
2663 */
2664 if( mft_entry->standard_information_attribute_index != -1 )
2665 {
2666 libcerror_error_set(
2667 error,
2668 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2669 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2670 "%s: invalid MFT entry - standard information attribute index value already set.",
2671 function );
2672
2673 return( -1 );
2674 }
2675 mft_entry->standard_information_attribute_index = attribute_index;
2676
2677 break;
2678
2679 case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION:
2680 /* Assume only one volume information attribute per MFT entry is allowed
2681 */
2682 if( mft_entry->volume_information_attribute_index != -1 )
2683 {
2684 libcerror_error_set(
2685 error,
2686 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2687 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2688 "%s: invalid MFT entry - volume information attribute index value already set.",
2689 function );
2690
2691 return( -1 );
2692 }
2693 mft_entry->volume_information_attribute_index = attribute_index;
2694
2695 break;
2696
2697 case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME:
2698 /* Assume only one volume name attribute per MFT entry is allowed
2699 */
2700 if( mft_entry->volume_name_attribute_index != -1 )
2701 {
2702 libcerror_error_set(
2703 error,
2704 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2705 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2706 "%s: invalid MFT entry - volume name attribute index value already set.",
2707 function );
2708
2709 return( -1 );
2710 }
2711 mft_entry->volume_name_attribute_index = attribute_index;
2712
2713 break;
2714
2715 default:
2716 break;
2717 }
2718 return( 1 );
2719 }
2720
2721 /* Sets the attribute helper values for a $DATA attribute
2722 * Returns 1 if successful or -1 on error
2723 */
libfsntfs_mft_entry_set_data_attribute_helper_values(libfsntfs_mft_entry_t * mft_entry,libfsntfs_mft_attribute_t * data_attribute,libcerror_error_t ** error)2724 int libfsntfs_mft_entry_set_data_attribute_helper_values(
2725 libfsntfs_mft_entry_t *mft_entry,
2726 libfsntfs_mft_attribute_t *data_attribute,
2727 libcerror_error_t **error )
2728 {
2729 uint8_t utf8_attribute_name[ 64 ];
2730
2731 libfsntfs_mft_attribute_t *existing_data_attribute = NULL;
2732 static char *function = "libfsntfs_mft_entry_set_data_attribute_helper_values";
2733 size_t utf8_attribute_name_size = 0;
2734 int attribute_index = 0;
2735 int entry_index = 0;
2736 int result = 0;
2737
2738 if( mft_entry == NULL )
2739 {
2740 libcerror_error_set(
2741 error,
2742 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2743 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2744 "%s: invalid MFT entry.",
2745 function );
2746
2747 return( -1 );
2748 }
2749 if( libfsntfs_mft_attribute_get_utf8_name_size(
2750 data_attribute,
2751 &utf8_attribute_name_size,
2752 error ) != 1 )
2753 {
2754 libcerror_error_set(
2755 error,
2756 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2757 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2758 "%s: unable to retrieve UTF-8 attribute name size.",
2759 function );
2760
2761 return( -1 );
2762 }
2763 if( utf8_attribute_name_size <= 1 )
2764 {
2765 if( libfsntfs_mft_attribute_append_to_chain(
2766 &( mft_entry->data_attribute ),
2767 data_attribute,
2768 error ) != 1 )
2769 {
2770 libcerror_error_set(
2771 error,
2772 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2773 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2774 "%s: unable to chain attribute.",
2775 function );
2776
2777 return( -1 );
2778 }
2779 }
2780 else
2781 {
2782 if( libfsntfs_mft_attribute_get_utf8_name(
2783 data_attribute,
2784 utf8_attribute_name,
2785 64,
2786 error ) != 1 )
2787 {
2788 libcerror_error_set(
2789 error,
2790 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2791 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2792 "%s: unable to retrieve UTF-8 attribute name.",
2793 function );
2794
2795 return( -1 );
2796 }
2797 result = libfsntfs_mft_entry_get_data_attribute_by_utf8_name(
2798 mft_entry,
2799 utf8_attribute_name,
2800 utf8_attribute_name_size,
2801 &attribute_index,
2802 &existing_data_attribute,
2803 error );
2804
2805 if( result == -1 )
2806 {
2807 libcerror_error_set(
2808 error,
2809 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2810 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2811 "%s: unable to retrieve data attribute.",
2812 function );
2813
2814 return( -1 );
2815 }
2816 else if( result == 0 )
2817 {
2818 if( libcdata_array_append_entry(
2819 mft_entry->alternate_data_attributes_array,
2820 &entry_index,
2821 (intptr_t *) data_attribute,
2822 error ) != 1 )
2823 {
2824 libcerror_error_set(
2825 error,
2826 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2827 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2828 "%s: unable to append alternate data attribute to array.",
2829 function );
2830
2831 return( -1 );
2832 }
2833 existing_data_attribute = data_attribute;
2834 }
2835 else
2836 {
2837 if( libfsntfs_mft_attribute_append_to_chain(
2838 &existing_data_attribute,
2839 data_attribute,
2840 error ) != 1 )
2841 {
2842 libcerror_error_set(
2843 error,
2844 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2845 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2846 "%s: unable to chain alternate data attribute.",
2847 function );
2848
2849 return( -1 );
2850 }
2851 if( libcdata_array_set_entry_by_index(
2852 mft_entry->alternate_data_attributes_array,
2853 attribute_index,
2854 (intptr_t *) existing_data_attribute,
2855 error ) != 1 )
2856 {
2857 libcerror_error_set(
2858 error,
2859 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2860 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2861 "%s: unable to append set data attribute: %d in array.",
2862 function,
2863 attribute_index );
2864
2865 return( -1 );
2866 }
2867 }
2868 result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
2869 data_attribute,
2870 (uint8_t *) "WofCompressedData",
2871 17,
2872 error );
2873
2874 if( result == -1 )
2875 {
2876 libcerror_error_set(
2877 error,
2878 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2879 LIBCERROR_RUNTIME_ERROR_GENERIC,
2880 "%s: unable to compare UTF-8 string with alternative data attribute name.",
2881 function );
2882
2883 return( -1 );
2884 }
2885 else if( result == 1 )
2886 {
2887 mft_entry->wof_compressed_data_attribute = existing_data_attribute;
2888 }
2889 }
2890 return( 1 );
2891 }
2892
2893 /* Retrieves a data attribute with the specified name
2894 * Returns 1 if successful, 0 if no attribute was found or -1 on error
2895 */
libfsntfs_mft_entry_get_data_attribute_by_utf8_name(libfsntfs_mft_entry_t * mft_entry,const uint8_t * utf8_string,size_t utf8_string_length,int * attribute_index,libfsntfs_mft_attribute_t ** attribute,libcerror_error_t ** error)2896 int libfsntfs_mft_entry_get_data_attribute_by_utf8_name(
2897 libfsntfs_mft_entry_t *mft_entry,
2898 const uint8_t *utf8_string,
2899 size_t utf8_string_length,
2900 int *attribute_index,
2901 libfsntfs_mft_attribute_t **attribute,
2902 libcerror_error_t **error )
2903 {
2904 libfsntfs_mft_attribute_t *safe_attribute = NULL;
2905 static char *function = "libfsntfs_mft_entry_get_data_attribute_by_utf8_name";
2906 int number_of_attributes = 0;
2907 int result = 0;
2908 int safe_attribute_index = 0;
2909
2910 if( mft_entry == NULL )
2911 {
2912 libcerror_error_set(
2913 error,
2914 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2915 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2916 "%s: invalid MFT entry.",
2917 function );
2918
2919 return( -1 );
2920 }
2921 if( utf8_string == NULL )
2922 {
2923 libcerror_error_set(
2924 error,
2925 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2926 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2927 "%s: invalid UTF-8 string.",
2928 function );
2929
2930 return( -1 );
2931 }
2932 if( utf8_string_length > (size_t) ( SSIZE_MAX - 1 ) )
2933 {
2934 libcerror_error_set(
2935 error,
2936 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2937 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2938 "%s: invalid UTF-8 string length value exceeds maximum.",
2939 function );
2940
2941 return( -1 );
2942 }
2943 if( attribute_index == NULL )
2944 {
2945 libcerror_error_set(
2946 error,
2947 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2948 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2949 "%s: invalid attribute index.",
2950 function );
2951
2952 return( -1 );
2953 }
2954 if( attribute == NULL )
2955 {
2956 libcerror_error_set(
2957 error,
2958 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2959 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2960 "%s: invalid attribute.",
2961 function );
2962
2963 return( -1 );
2964 }
2965 if( libcdata_array_get_number_of_entries(
2966 mft_entry->alternate_data_attributes_array,
2967 &number_of_attributes,
2968 error ) != 1 )
2969 {
2970 libcerror_error_set(
2971 error,
2972 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2973 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2974 "%s: unable to retrieve number of alternate data attributes.",
2975 function );
2976
2977 return( -1 );
2978 }
2979 for( safe_attribute_index = 0;
2980 safe_attribute_index < number_of_attributes;
2981 safe_attribute_index++ )
2982 {
2983 if( libcdata_array_get_entry_by_index(
2984 mft_entry->alternate_data_attributes_array,
2985 safe_attribute_index,
2986 (intptr_t **) &safe_attribute,
2987 error ) != 1 )
2988 {
2989 libcerror_error_set(
2990 error,
2991 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2992 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2993 "%s: unable to retrieve alternate data attribute: %d.",
2994 function,
2995 safe_attribute_index );
2996
2997 return( -1 );
2998 }
2999 result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
3000 safe_attribute,
3001 utf8_string,
3002 utf8_string_length,
3003 error );
3004
3005 if( result == -1 )
3006 {
3007 libcerror_error_set(
3008 error,
3009 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3010 LIBCERROR_RUNTIME_ERROR_GENERIC,
3011 "%s: unable to compare UTF-8 string with alternative data attribute: %d name.",
3012 function,
3013 safe_attribute_index );
3014
3015 return( -1 );
3016 }
3017 else if( result != 0 )
3018 {
3019 break;
3020 }
3021 }
3022 if( result != 0 )
3023 {
3024 *attribute_index = safe_attribute_index;
3025 *attribute = safe_attribute;
3026 }
3027 else
3028 {
3029 *attribute_index = 0;
3030 *attribute = NULL;
3031 }
3032 return( result );
3033 }
3034
3035 /* Determines if the file entry has the directory entries ($I30) index
3036 * Returns 1 if the default data stream, 0 if not or -1 on error
3037 */
libfsntfs_mft_entry_has_directory_entries_index(libfsntfs_mft_entry_t * mft_entry,libcerror_error_t ** error)3038 int libfsntfs_mft_entry_has_directory_entries_index(
3039 libfsntfs_mft_entry_t *mft_entry,
3040 libcerror_error_t **error )
3041 {
3042 static char *function = "libfsntfs_mft_entry_has_directory_entries_index";
3043
3044 if( mft_entry == NULL )
3045 {
3046 libcerror_error_set(
3047 error,
3048 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3049 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3050 "%s: invalid MFT entry.",
3051 function );
3052
3053 return( -1 );
3054 }
3055 return( (int) mft_entry->has_i30_index );
3056 }
3057
3058 /* Reads the MFT entry
3059 * Callback function for the MFT entry vector
3060 * Returns 1 if successful or -1 on error
3061 */
libfsntfs_mft_entry_read_element_data(intptr_t * data_handle LIBFSNTFS_ATTRIBUTE_UNUSED,libbfio_handle_t * file_io_handle,libfdata_vector_t * vector,libfdata_cache_t * cache,int element_index,int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED,off64_t element_data_offset,size64_t element_data_size,uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED,uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED,libcerror_error_t ** error)3062 int libfsntfs_mft_entry_read_element_data(
3063 intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED,
3064 libbfio_handle_t *file_io_handle,
3065 libfdata_vector_t *vector,
3066 libfdata_cache_t *cache,
3067 int element_index,
3068 int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED,
3069 off64_t element_data_offset,
3070 size64_t element_data_size,
3071 uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
3072 uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
3073 libcerror_error_t **error )
3074 {
3075 libfsntfs_mft_entry_t *mft_entry = NULL;
3076 static char *function = "libfsntfs_mft_entry_read_element_data";
3077
3078 LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle )
3079 LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index )
3080 LIBFSNTFS_UNREFERENCED_PARAMETER( element_flags )
3081 LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags )
3082
3083 #if ( SIZEOF_INT <= 4 )
3084 if( element_index < 0 )
3085 #else
3086 if( ( element_index < 0 )
3087 || ( (int64_t) element_index > (int64_t) UINT32_MAX ) )
3088 #endif
3089 {
3090 libcerror_error_set(
3091 error,
3092 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3093 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3094 "%s: invalid element index value out of bounds.",
3095 function );
3096
3097 return( -1 );
3098 }
3099 if( element_data_size > (size64_t) UINT32_MAX )
3100 {
3101 libcerror_error_set(
3102 error,
3103 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3104 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3105 "%s: invalid element data size value out of bounds.",
3106 function );
3107
3108 return( -1 );
3109 }
3110 if( libfsntfs_mft_entry_initialize(
3111 &mft_entry,
3112 error ) != 1 )
3113 {
3114 libcerror_error_set(
3115 error,
3116 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3117 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3118 "%s: unable to create MFT entry.",
3119 function );
3120
3121 goto on_error;
3122 }
3123 if( libfsntfs_mft_entry_read_file_io_handle(
3124 mft_entry,
3125 file_io_handle,
3126 element_data_offset,
3127 (uint32_t) element_data_size,
3128 (uint32_t) element_index,
3129 error ) != 1 )
3130 {
3131 libcerror_error_set(
3132 error,
3133 LIBCERROR_ERROR_DOMAIN_IO,
3134 LIBCERROR_IO_ERROR_READ_FAILED,
3135 "%s: unable to read MFT entry: %d.",
3136 function,
3137 element_index );
3138
3139 goto on_error;
3140 }
3141 if( libfdata_vector_set_element_value_by_index(
3142 vector,
3143 (intptr_t *) file_io_handle,
3144 cache,
3145 element_index,
3146 (intptr_t *) mft_entry,
3147 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_entry_free,
3148 LIBFDATA_VECTOR_ELEMENT_VALUE_FLAG_MANAGED,
3149 error ) != 1 )
3150 {
3151 libcerror_error_set(
3152 error,
3153 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3154 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3155 "%s: unable to set MFT entry as element value.",
3156 function );
3157
3158 goto on_error;
3159 }
3160 return( 1 );
3161
3162 on_error:
3163 if( mft_entry != NULL )
3164 {
3165 libfsntfs_mft_entry_free(
3166 &mft_entry,
3167 NULL );
3168 }
3169 return( -1 );
3170 }
3171
3172