Coverage Report

Created: 2026-08-31 07:43

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