Coverage Report

Created: 2025-09-05 06:58

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