1 /*
2 * Attribute list attribute ($ATTRIBUTE_LIST) 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 <memory.h>
24 #include <types.h>
25
26 #include "libfsntfs_cluster_block.h"
27 #include "libfsntfs_cluster_block_stream.h"
28 #include "libfsntfs_definitions.h"
29 #include "libfsntfs_io_handle.h"
30 #include "libfsntfs_libbfio.h"
31 #include "libfsntfs_libcdata.h"
32 #include "libfsntfs_libcerror.h"
33 #include "libfsntfs_libcnotify.h"
34 #include "libfsntfs_libfcache.h"
35 #include "libfsntfs_libfdata.h"
36 #include "libfsntfs_mft_attribute.h"
37 #include "libfsntfs_mft_attribute_list.h"
38 #include "libfsntfs_mft_attribute_list_entry.h"
39
40 #include "fsntfs_mft_attribute_list.h"
41
42 /* Creates attribute list
43 * Make sure the value attribute_list is referencing, is set to NULL
44 * Returns 1 if successful or -1 on error
45 */
libfsntfs_mft_attribute_list_initialize(libfsntfs_mft_attribute_list_t ** attribute_list,uint64_t base_record_file_reference,libcerror_error_t ** error)46 int libfsntfs_mft_attribute_list_initialize(
47 libfsntfs_mft_attribute_list_t **attribute_list,
48 uint64_t base_record_file_reference,
49 libcerror_error_t **error )
50 {
51 static char *function = "libfsntfs_mft_attribute_list_initialize";
52
53 if( attribute_list == NULL )
54 {
55 libcerror_error_set(
56 error,
57 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59 "%s: invalid attribute list.",
60 function );
61
62 return( -1 );
63 }
64 if( *attribute_list != NULL )
65 {
66 libcerror_error_set(
67 error,
68 LIBCERROR_ERROR_DOMAIN_RUNTIME,
69 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70 "%s: invalid attribute list value already set.",
71 function );
72
73 return( -1 );
74 }
75 *attribute_list = memory_allocate_structure(
76 libfsntfs_mft_attribute_list_t );
77
78 if( *attribute_list == NULL )
79 {
80 libcerror_error_set(
81 error,
82 LIBCERROR_ERROR_DOMAIN_MEMORY,
83 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84 "%s: unable to create attribute list.",
85 function );
86
87 goto on_error;
88 }
89 if( memory_set(
90 *attribute_list,
91 0,
92 sizeof( libfsntfs_mft_attribute_list_t ) ) == NULL )
93 {
94 libcerror_error_set(
95 error,
96 LIBCERROR_ERROR_DOMAIN_MEMORY,
97 LIBCERROR_MEMORY_ERROR_SET_FAILED,
98 "%s: unable to clear attribute list.",
99 function );
100
101 memory_free(
102 *attribute_list );
103
104 *attribute_list = NULL;
105
106 return( -1 );
107 }
108 if( libcdata_array_initialize(
109 &( ( *attribute_list )->entries_array ),
110 0,
111 error ) != 1 )
112 {
113 libcerror_error_set(
114 error,
115 LIBCERROR_ERROR_DOMAIN_RUNTIME,
116 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117 "%s: unable to create entries array.",
118 function );
119
120 goto on_error;
121 }
122 if( libcdata_array_initialize(
123 &( ( *attribute_list )->file_references_array ),
124 0,
125 error ) != 1 )
126 {
127 libcerror_error_set(
128 error,
129 LIBCERROR_ERROR_DOMAIN_RUNTIME,
130 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
131 "%s: unable to create file references array.",
132 function );
133
134 goto on_error;
135 }
136 ( *attribute_list )->base_record_file_reference = base_record_file_reference;
137
138 return( 1 );
139
140 on_error:
141 if( *attribute_list != NULL )
142 {
143 if( ( *attribute_list )->entries_array != NULL )
144 {
145 libcdata_array_free(
146 &( ( *attribute_list )->entries_array ),
147 NULL,
148 NULL );
149 }
150 memory_free(
151 *attribute_list );
152
153 *attribute_list = NULL;
154 }
155 return( -1 );
156 }
157
158 /* Frees attribute list
159 * Returns 1 if successful or -1 on error
160 */
libfsntfs_mft_attribute_list_free(libfsntfs_mft_attribute_list_t ** attribute_list,libcerror_error_t ** error)161 int libfsntfs_mft_attribute_list_free(
162 libfsntfs_mft_attribute_list_t **attribute_list,
163 libcerror_error_t **error )
164 {
165 static char *function = "libfsntfs_mft_attribute_list_free";
166 int result = 1;
167
168 if( attribute_list == NULL )
169 {
170 libcerror_error_set(
171 error,
172 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
173 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
174 "%s: invalid attribute list.",
175 function );
176
177 return( -1 );
178 }
179 if( *attribute_list != NULL )
180 {
181 if( libcdata_array_free(
182 &( ( *attribute_list )->entries_array ),
183 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_entry_free,
184 error ) != 1 )
185 {
186 libcerror_error_set(
187 error,
188 LIBCERROR_ERROR_DOMAIN_RUNTIME,
189 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
190 "%s: unable to free entries array.",
191 function );
192
193 result = -1;
194 }
195 if( libcdata_array_free(
196 &( ( *attribute_list )->file_references_array ),
197 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_file_reference_free,
198 error ) != 1 )
199 {
200 libcerror_error_set(
201 error,
202 LIBCERROR_ERROR_DOMAIN_RUNTIME,
203 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
204 "%s: unable to free file references array.",
205 function );
206
207 result = -1;
208 }
209 memory_free(
210 *attribute_list );
211
212 *attribute_list = NULL;
213 }
214 return( result );
215 }
216
217 /* Frees attribute list file reference
218 * Returns 1 if successful or -1 on error
219 */
libfsntfs_mft_attribute_list_file_reference_free(uint64_t ** file_reference,libcerror_error_t ** error)220 int libfsntfs_mft_attribute_list_file_reference_free(
221 uint64_t **file_reference,
222 libcerror_error_t **error )
223 {
224 static char *function = "libfsntfs_mft_attribute_list_file_reference_free";
225
226 if( file_reference == NULL )
227 {
228 libcerror_error_set(
229 error,
230 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
231 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
232 "%s: invalid file reference.",
233 function );
234
235 return( -1 );
236 }
237 if( *file_reference != NULL )
238 {
239 memory_free(
240 *file_reference );
241
242 *file_reference = NULL;
243 }
244 return( 1 );
245 }
246
247 /* Reads the attribute list
248 * Returns 1 if successful or -1 on error
249 */
libfsntfs_mft_attribute_list_read_data(libfsntfs_mft_attribute_list_t * attribute_list,const uint8_t * data,size_t data_size,libcerror_error_t ** error)250 int libfsntfs_mft_attribute_list_read_data(
251 libfsntfs_mft_attribute_list_t *attribute_list,
252 const uint8_t *data,
253 size_t data_size,
254 libcerror_error_t **error )
255 {
256 libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL;
257 static char *function = "libfsntfs_mft_attribute_list_read_data";
258 size_t data_offset = 0;
259 int attribute_index = 0;
260 int entry_index = 0;
261
262 if( attribute_list == NULL )
263 {
264 libcerror_error_set(
265 error,
266 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
267 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
268 "%s: invalid attribute list.",
269 function );
270
271 return( -1 );
272 }
273 if( data == NULL )
274 {
275 libcerror_error_set(
276 error,
277 LIBCERROR_ERROR_DOMAIN_RUNTIME,
278 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
279 "%s: invalid data.",
280 function );
281
282 return( -1 );
283 }
284 if( data_size > (size_t) SSIZE_MAX )
285 {
286 libcerror_error_set(
287 error,
288 LIBCERROR_ERROR_DOMAIN_RUNTIME,
289 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
290 "%s: invalid data size value out of bounds.",
291 function );
292
293 return( -1 );
294 }
295 #if defined( HAVE_DEBUG_OUTPUT )
296 if( libcnotify_verbose != 0 )
297 {
298 libcnotify_printf(
299 "%s: attribute list data:\n",
300 function );
301 libcnotify_print_data(
302 data,
303 data_size,
304 0 );
305 }
306 #endif
307 while( data_offset < data_size )
308 {
309 if( libfsntfs_mft_attribute_list_entry_initialize(
310 &mft_attribute_list_entry,
311 error ) != 1 )
312 {
313 libcerror_error_set(
314 error,
315 LIBCERROR_ERROR_DOMAIN_RUNTIME,
316 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
317 "%s: unable to create MFT attribute list entry.",
318 function );
319
320 goto on_error;
321 }
322 if( libfsntfs_mft_attribute_list_entry_read_data(
323 mft_attribute_list_entry,
324 &( data[ data_offset ] ),
325 data_size,
326 error ) != 1 )
327 {
328 libcerror_error_set(
329 error,
330 LIBCERROR_ERROR_DOMAIN_IO,
331 LIBCERROR_IO_ERROR_READ_FAILED,
332 "%s: unable to read MFT attribute list entry: %d.",
333 function,
334 attribute_index );
335
336 goto on_error;
337 }
338 data_offset += mft_attribute_list_entry->size;
339
340 if( libcdata_array_append_entry(
341 attribute_list->entries_array,
342 &entry_index,
343 (intptr_t *) mft_attribute_list_entry,
344 error ) != 1 )
345 {
346 libcerror_error_set(
347 error,
348 LIBCERROR_ERROR_DOMAIN_RUNTIME,
349 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
350 "%s: unable to append MFT attribute list entry: %d to array.",
351 function,
352 attribute_index );
353
354 goto on_error;
355 }
356 mft_attribute_list_entry = NULL;
357
358 attribute_index++;
359 }
360 #if defined( HAVE_DEBUG_OUTPUT )
361 if( libcnotify_verbose != 0 )
362 {
363 if( data_offset < data_size )
364 {
365 libcnotify_printf(
366 "%s: alignment padding:\n",
367 function );
368 libcnotify_print_data(
369 &( data[ data_offset ] ),
370 data_size - data_offset,
371 0 );
372 }
373 }
374 #endif
375 return( 1 );
376
377 on_error:
378 if( mft_attribute_list_entry != NULL )
379 {
380 libfsntfs_mft_attribute_list_entry_free(
381 &mft_attribute_list_entry,
382 NULL );
383 }
384 return( -1 );
385 }
386
387 /* Reads the attribute list
388 * Returns 1 if successful or -1 on error
389 */
libfsntfs_mft_attribute_list_read_from_attribute(libfsntfs_mft_attribute_list_t * attribute_list,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfsntfs_mft_attribute_t * list_attribute,libcerror_error_t ** error)390 int libfsntfs_mft_attribute_list_read_from_attribute(
391 libfsntfs_mft_attribute_list_t *attribute_list,
392 libfsntfs_io_handle_t *io_handle,
393 libbfio_handle_t *file_io_handle,
394 libfsntfs_mft_attribute_t *list_attribute,
395 libcerror_error_t **error )
396 {
397 uint8_t data[ sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256 ];
398
399 libfdata_stream_t *cluster_block_stream = NULL;
400 libfsntfs_mft_attribute_list_entry_t *mft_attribute_list_entry = NULL;
401 static char *function = "libfsntfs_mft_attribute_list_read_from_attribute";
402 size64_t data_size = 0;
403 ssize_t read_count = 0;
404 off64_t data_offset = 0;
405 int attribute_index = 0;
406 int entry_index = 0;
407
408 if( attribute_list == NULL )
409 {
410 libcerror_error_set(
411 error,
412 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
414 "%s: invalid attribute list.",
415 function );
416
417 return( -1 );
418 }
419 if( libfsntfs_cluster_block_stream_initialize(
420 &cluster_block_stream,
421 io_handle,
422 list_attribute,
423 NULL,
424 0,
425 error ) != 1 )
426 {
427 libcerror_error_set(
428 error,
429 LIBCERROR_ERROR_DOMAIN_RUNTIME,
430 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
431 "%s: unable to create cluster block stream.",
432 function );
433
434 goto on_error;
435 }
436 if( libfdata_stream_get_size(
437 cluster_block_stream,
438 &data_size,
439 error ) != 1 )
440 {
441 libcerror_error_set(
442 error,
443 LIBCERROR_ERROR_DOMAIN_RUNTIME,
444 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
445 "%s: unable to retrieve size from cluster block stream.",
446 function );
447
448 goto on_error;
449 }
450 while( (size64_t) data_offset < data_size )
451 {
452 if( memory_set(
453 data,
454 0,
455 sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256 ) == NULL )
456 {
457 libcerror_error_set(
458 error,
459 LIBCERROR_ERROR_DOMAIN_MEMORY,
460 LIBCERROR_MEMORY_ERROR_SET_FAILED,
461 "%s: unable to clear data.",
462 function );
463
464 goto on_error;
465 }
466 read_count = libfdata_stream_read_buffer_at_offset(
467 cluster_block_stream,
468 (intptr_t *) file_io_handle,
469 data,
470 sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256,
471 data_offset,
472 0,
473 error );
474
475 if( read_count < 0 )
476 {
477 libcerror_error_set(
478 error,
479 LIBCERROR_ERROR_DOMAIN_IO,
480 LIBCERROR_IO_ERROR_READ_FAILED,
481 "%s: unable to read attribute list entry: %d from cluster block stream at offset: %" PRIi64 " (0x%08" PRIx64 ").",
482 function,
483 attribute_index,
484 data_offset,
485 data_offset );
486
487 goto on_error;
488 }
489 if( libfsntfs_mft_attribute_list_entry_initialize(
490 &mft_attribute_list_entry,
491 error ) != 1 )
492 {
493 libcerror_error_set(
494 error,
495 LIBCERROR_ERROR_DOMAIN_RUNTIME,
496 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
497 "%s: unable to create attribute list entry: %d.",
498 function,
499 attribute_index );
500
501 goto on_error;
502 }
503 if( libfsntfs_mft_attribute_list_entry_read_data(
504 mft_attribute_list_entry,
505 data,
506 sizeof( fsntfs_mft_attribute_list_entry_header_t ) + 256,
507 error ) != 1 )
508 {
509 libcerror_error_set(
510 error,
511 LIBCERROR_ERROR_DOMAIN_IO,
512 LIBCERROR_IO_ERROR_READ_FAILED,
513 "%s: unable to read attribute list entry: %d.",
514 function,
515 attribute_index );
516
517 goto on_error;
518 }
519 data_offset += mft_attribute_list_entry->size;
520
521 if( libcdata_array_append_entry(
522 attribute_list->entries_array,
523 &entry_index,
524 (intptr_t *) mft_attribute_list_entry,
525 error ) != 1 )
526 {
527 libcerror_error_set(
528 error,
529 LIBCERROR_ERROR_DOMAIN_RUNTIME,
530 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
531 "%s: unable to append attribute list entry: %d to array.",
532 function,
533 attribute_index );
534
535 goto on_error;
536 }
537 mft_attribute_list_entry = NULL;
538
539 attribute_index++;
540 }
541 if( libfdata_stream_free(
542 &cluster_block_stream,
543 error ) != 1 )
544 {
545 libcerror_error_set(
546 error,
547 LIBCERROR_ERROR_DOMAIN_RUNTIME,
548 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
549 "%s: unable to free cluster block stream.",
550 function );
551
552 goto on_error;
553 }
554 return( 1 );
555
556 on_error:
557 if( mft_attribute_list_entry != NULL )
558 {
559 libfsntfs_mft_attribute_list_entry_free(
560 &mft_attribute_list_entry,
561 NULL );
562 }
563 if( cluster_block_stream != NULL )
564 {
565 libfdata_stream_free(
566 &cluster_block_stream,
567 NULL );
568 }
569 return( -1 );
570 }
571
572 /* Retrieves the number of attribute list entries
573 * Returns 1 if successful or -1 on error
574 */
libfsntfs_mft_attribute_list_get_number_of_entries(libfsntfs_mft_attribute_list_t * attribute_list,int * number_of_entries,libcerror_error_t ** error)575 int libfsntfs_mft_attribute_list_get_number_of_entries(
576 libfsntfs_mft_attribute_list_t *attribute_list,
577 int *number_of_entries,
578 libcerror_error_t **error )
579 {
580 static char *function = "libfsntfs_mft_attribute_list_get_number_of_entries";
581
582 if( attribute_list == NULL )
583 {
584 libcerror_error_set(
585 error,
586 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
587 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
588 "%s: invalid attribute list.",
589 function );
590
591 return( -1 );
592 }
593 if( libcdata_array_get_number_of_entries(
594 attribute_list->entries_array,
595 number_of_entries,
596 error ) != 1 )
597 {
598 libcerror_error_set(
599 error,
600 LIBCERROR_ERROR_DOMAIN_RUNTIME,
601 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
602 "%s: unable to retrieve number of entries from array.",
603 function );
604
605 return( -1 );
606 }
607 return( 1 );
608 }
609
610 /* Retrieves a specific attribute list entry
611 * Returns 1 if successful or -1 on error
612 */
libfsntfs_mft_attribute_list_get_entry_by_index(libfsntfs_mft_attribute_list_t * attribute_list,int entry_index,libfsntfs_mft_attribute_list_entry_t ** mft_attribute_list_entry,libcerror_error_t ** error)613 int libfsntfs_mft_attribute_list_get_entry_by_index(
614 libfsntfs_mft_attribute_list_t *attribute_list,
615 int entry_index,
616 libfsntfs_mft_attribute_list_entry_t **mft_attribute_list_entry,
617 libcerror_error_t **error )
618 {
619 static char *function = "libfsntfs_mft_entry_get_attribute_by_index";
620
621 if( attribute_list == NULL )
622 {
623 libcerror_error_set(
624 error,
625 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
626 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
627 "%s: invalid attribute list.",
628 function );
629
630 return( -1 );
631 }
632 if( libcdata_array_get_entry_by_index(
633 attribute_list->entries_array,
634 entry_index,
635 (intptr_t **) mft_attribute_list_entry,
636 error ) != 1 )
637 {
638 libcerror_error_set(
639 error,
640 LIBCERROR_ERROR_DOMAIN_RUNTIME,
641 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
642 "%s: unable to retrieve entry: %d from array.",
643 function,
644 entry_index );
645
646 return( -1 );
647 }
648 return( 1 );
649 }
650
651 /* Compares attribute lists by their base record file reference
652 * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
653 */
libfsntfs_mft_attribute_list_compare_by_base_record_file_reference(libfsntfs_mft_attribute_list_t * first_attribute_list,libfsntfs_mft_attribute_list_t * second_attribute_list,libcerror_error_t ** error)654 int libfsntfs_mft_attribute_list_compare_by_base_record_file_reference(
655 libfsntfs_mft_attribute_list_t *first_attribute_list,
656 libfsntfs_mft_attribute_list_t *second_attribute_list,
657 libcerror_error_t **error )
658 {
659 static char *function = "libfsntfs_mft_attribute_list_compare_by_base_record_file_reference";
660 uint64_t first_mft_entry_index = 0;
661 uint64_t second_mft_entry_index = 0;
662
663 if( first_attribute_list == NULL )
664 {
665 libcerror_error_set(
666 error,
667 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
668 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
669 "%s: invalid first attribute list.",
670 function );
671
672 return( -1 );
673 }
674 if( second_attribute_list == NULL )
675 {
676 libcerror_error_set(
677 error,
678 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
680 "%s: invalid second attribute list.",
681 function );
682
683 return( -1 );
684 }
685 first_mft_entry_index = first_attribute_list->base_record_file_reference & 0xffffffffffffUL;
686 second_mft_entry_index = second_attribute_list->base_record_file_reference & 0xffffffffffffUL;
687
688 if( first_mft_entry_index < second_mft_entry_index )
689 {
690 return( LIBCDATA_COMPARE_LESS );
691 }
692 else if( first_mft_entry_index > second_mft_entry_index )
693 {
694 return( LIBCDATA_COMPARE_GREATER );
695 }
696 return( LIBCDATA_COMPARE_EQUAL );
697 }
698
699 /* Retrieves the number of attribute list data file references
700 * Returns 1 if successful or -1 on error
701 */
libfsntfs_mft_attribute_list_get_number_of_file_references(libfsntfs_mft_attribute_list_t * attribute_list,int * number_of_file_references,libcerror_error_t ** error)702 int libfsntfs_mft_attribute_list_get_number_of_file_references(
703 libfsntfs_mft_attribute_list_t *attribute_list,
704 int *number_of_file_references,
705 libcerror_error_t **error )
706 {
707 static char *function = "libfsntfs_mft_attribute_list_get_number_of_file_references";
708
709 if( attribute_list == NULL )
710 {
711 libcerror_error_set(
712 error,
713 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
714 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
715 "%s: invalid attribute list.",
716 function );
717
718 return( -1 );
719 }
720 if( libcdata_array_get_number_of_entries(
721 attribute_list->file_references_array,
722 number_of_file_references,
723 error ) != 1 )
724 {
725 libcerror_error_set(
726 error,
727 LIBCERROR_ERROR_DOMAIN_RUNTIME,
728 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
729 "%s: unable to retrieve number of entries from array.",
730 function );
731
732 return( -1 );
733 }
734 return( 1 );
735 }
736
737 /* Retrieves a specific attribute list data file reference
738 * Returns 1 if successful or -1 on error
739 */
libfsntfs_mft_attribute_list_get_file_reference_by_index(libfsntfs_mft_attribute_list_t * attribute_list,int file_reference_index,uint64_t * file_reference,libcerror_error_t ** error)740 int libfsntfs_mft_attribute_list_get_file_reference_by_index(
741 libfsntfs_mft_attribute_list_t *attribute_list,
742 int file_reference_index,
743 uint64_t *file_reference,
744 libcerror_error_t **error )
745 {
746 uint64_t *safe_file_reference = NULL;
747 static char *function = "libfsntfs_mft_attribute_list_get_file_reference_by_index";
748
749 if( attribute_list == NULL )
750 {
751 libcerror_error_set(
752 error,
753 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
754 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
755 "%s: invalid attribute list.",
756 function );
757
758 return( -1 );
759 }
760 if( file_reference == NULL )
761 {
762 libcerror_error_set(
763 error,
764 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
765 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
766 "%s: invalid file reference.",
767 function );
768
769 return( -1 );
770 }
771 if( libcdata_array_get_entry_by_index(
772 attribute_list->file_references_array,
773 file_reference_index,
774 (intptr_t **) &safe_file_reference,
775 error ) != 1 )
776 {
777 libcerror_error_set(
778 error,
779 LIBCERROR_ERROR_DOMAIN_RUNTIME,
780 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
781 "%s: unable to retrieve entry: %d from array.",
782 function,
783 file_reference_index );
784
785 return( -1 );
786 }
787 *file_reference = *safe_file_reference;
788
789 return( 1 );
790 }
791
792 /* Compares attribute list data file references
793 * Returns LIBCDATA_COMPARE_LESS, LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
794 */
libfsntfs_mft_attribute_list_compare_file_reference(uint64_t * first_file_reference,uint64_t * second_file_reference,libcerror_error_t ** error)795 int libfsntfs_mft_attribute_list_compare_file_reference(
796 uint64_t *first_file_reference,
797 uint64_t *second_file_reference,
798 libcerror_error_t **error )
799 {
800 static char *function = "libfsntfs_mft_attribute_list_compare_file_reference";
801 uint64_t first_mft_entry_index = 0;
802 uint64_t second_mft_entry_index = 0;
803
804 if( first_file_reference == NULL )
805 {
806 libcerror_error_set(
807 error,
808 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
809 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
810 "%s: invalid first file reference.",
811 function );
812
813 return( -1 );
814 }
815 if( second_file_reference == NULL )
816 {
817 libcerror_error_set(
818 error,
819 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
820 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
821 "%s: invalid second file reference.",
822 function );
823
824 return( -1 );
825 }
826 first_mft_entry_index = *first_file_reference & 0xffffffffffffUL;
827 second_mft_entry_index = *second_file_reference & 0xffffffffffffUL;
828
829 if( first_mft_entry_index < second_mft_entry_index )
830 {
831 return( LIBCDATA_COMPARE_LESS );
832 }
833 else if( first_mft_entry_index > second_mft_entry_index )
834 {
835 return( LIBCDATA_COMPARE_GREATER );
836 }
837 return( LIBCDATA_COMPARE_EQUAL );
838 }
839
840 /* Insert an attribute list data file reference
841 * Returns 1 if successful or -1 on error
842 */
libfsntfs_mft_attribute_list_insert_file_reference(libfsntfs_mft_attribute_list_t * attribute_list,uint64_t file_reference,libcerror_error_t ** error)843 int libfsntfs_mft_attribute_list_insert_file_reference(
844 libfsntfs_mft_attribute_list_t *attribute_list,
845 uint64_t file_reference,
846 libcerror_error_t **error )
847 {
848 uint64_t *safe_file_reference = NULL;
849 static char *function = "libfsntfs_mft_attribute_list_insert_file_reference";
850 int entry_index = 0;
851 int result = 0;
852
853 if( attribute_list == NULL )
854 {
855 libcerror_error_set(
856 error,
857 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
858 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
859 "%s: invalid attribute list.",
860 function );
861
862 return( -1 );
863 }
864 safe_file_reference = (uint64_t *) memory_allocate(
865 sizeof( uint64_t ) );
866
867 if( safe_file_reference == NULL )
868 {
869 libcerror_error_set(
870 error,
871 LIBCERROR_ERROR_DOMAIN_MEMORY,
872 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
873 "%s: unable to create file reference.",
874 function );
875
876 goto on_error;
877 }
878 *safe_file_reference = file_reference;
879
880 result = libcdata_array_insert_entry(
881 attribute_list->file_references_array,
882 &entry_index,
883 (intptr_t *) safe_file_reference,
884 (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_file_reference,
885 LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
886 error );
887
888 if( result == -1 )
889 {
890 libcerror_error_set(
891 error,
892 LIBCERROR_ERROR_DOMAIN_RUNTIME,
893 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
894 "%s: unable to insert file reference in array.",
895 function );
896
897 goto on_error;
898 }
899 else if( result == 0 )
900 {
901 memory_free(
902 safe_file_reference );
903 }
904 return( 1 );
905
906 on_error:
907 if( safe_file_reference != NULL )
908 {
909 memory_free(
910 safe_file_reference );
911 }
912 return( -1 );
913 }
914
915