Coverage Report

Created: 2024-10-02 06:58

/src/libfsntfs/libfsntfs/libfsntfs_mft_attribute.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Master File Table (MFT) attribute functions
3
 *
4
 * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfsntfs_data_run.h"
28
#include "libfsntfs_debug.h"
29
#include "libfsntfs_definitions.h"
30
#include "libfsntfs_extent.h"
31
#include "libfsntfs_libcdata.h"
32
#include "libfsntfs_libcerror.h"
33
#include "libfsntfs_libcnotify.h"
34
#include "libfsntfs_libuna.h"
35
#include "libfsntfs_mft_attribute.h"
36
#include "libfsntfs_name.h"
37
38
#include "fsntfs_mft_attribute.h"
39
40
/* Creates a MFT attribute
41
 * Make sure the value mft_attribute is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libfsntfs_mft_attribute_initialize(
45
     libfsntfs_mft_attribute_t **mft_attribute,
46
     libcerror_error_t **error )
47
52.4k
{
48
52.4k
  static char *function = "libfsntfs_mft_attribute_initialize";
49
50
52.4k
  if( mft_attribute == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid MFT attribute.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
52.4k
  if( *mft_attribute != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid MFT attribute value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
52.4k
  *mft_attribute = memory_allocate_structure(
73
52.4k
                    libfsntfs_mft_attribute_t );
74
75
52.4k
  if( *mft_attribute == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create MFT attribute.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
52.4k
  if( memory_set(
87
52.4k
       *mft_attribute,
88
52.4k
       0,
89
52.4k
       sizeof( libfsntfs_mft_attribute_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear MFT attribute.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
52.4k
  return( 1 );
101
102
0
on_error:
103
0
  if( *mft_attribute != NULL )
104
0
  {
105
0
    memory_free(
106
0
     *mft_attribute );
107
108
0
    *mft_attribute = NULL;
109
0
  }
110
0
  return( -1 );
111
52.4k
}
112
113
/* Frees a MFT attribute
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfsntfs_mft_attribute_free(
117
     libfsntfs_mft_attribute_t **mft_attribute,
118
     libcerror_error_t **error )
119
56.8k
{
120
56.8k
  static char *function = "libfsntfs_mft_attribute_free";
121
56.8k
  int result            = 1;
122
123
56.8k
  if( mft_attribute == NULL )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
129
0
     "%s: invalid MFT attribute.",
130
0
     function );
131
132
0
    return( -1 );
133
0
  }
134
56.8k
  if( *mft_attribute != NULL )
135
56.8k
  {
136
56.8k
    if( ( *mft_attribute )->name != NULL )
137
19.7k
    {
138
19.7k
      memory_free(
139
19.7k
       ( *mft_attribute )->name );
140
19.7k
    }
141
56.8k
    if( ( *mft_attribute )->data != NULL )
142
17.6k
    {
143
17.6k
      memory_free(
144
17.6k
       ( *mft_attribute )->data );
145
17.6k
    }
146
56.8k
    if( ( *mft_attribute )->data_runs_array != NULL )
147
26.9k
    {
148
26.9k
      if( libcdata_array_free(
149
26.9k
           &( ( *mft_attribute )->data_runs_array ),
150
26.9k
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free,
151
26.9k
           error ) != 1 )
152
0
      {
153
0
        libcerror_error_set(
154
0
         error,
155
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
156
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
157
0
         "%s: unable to free data runs array.",
158
0
         function );
159
160
0
        result = -1;
161
0
      }
162
26.9k
    }
163
56.8k
    memory_free(
164
56.8k
     *mft_attribute );
165
166
56.8k
    *mft_attribute = NULL;
167
56.8k
  }
168
56.8k
  return( result );
169
56.8k
}
170
171
/* Clones a MFT attribute
172
 * Returns 1 if successful or -1 on error
173
 */
174
int libfsntfs_mft_attribute_clone(
175
     libfsntfs_mft_attribute_t **destination_mft_attribute,
176
     libfsntfs_mft_attribute_t *source_mft_attribute,
177
     libcerror_error_t **error )
178
4.42k
{
179
4.42k
  static char *function = "libfsntfs_mft_attribute_clone";
180
181
4.42k
  if( destination_mft_attribute == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187
0
     "%s: invalid MFT attribute.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
4.42k
  if( *destination_mft_attribute != NULL )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
198
0
     "%s: invalid destination MFT attribute value already set.",
199
0
     function );
200
201
0
    return( -1 );
202
0
  }
203
4.42k
  if( source_mft_attribute == NULL )
204
0
  {
205
0
    *destination_mft_attribute = source_mft_attribute;
206
207
0
    return( 1 );
208
0
  }
209
4.42k
  *destination_mft_attribute = memory_allocate_structure(
210
4.42k
                                libfsntfs_mft_attribute_t );
211
212
4.42k
  if( *destination_mft_attribute == NULL )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
217
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
218
0
     "%s: unable to create destnation MFT attribute.",
219
0
     function );
220
221
0
    goto on_error;
222
0
  }
223
4.42k
  if( memory_copy(
224
4.42k
       *destination_mft_attribute,
225
4.42k
       source_mft_attribute,
226
4.42k
       sizeof( libfsntfs_mft_attribute_t ) ) == NULL )
227
0
  {
228
0
    libcerror_error_set(
229
0
     error,
230
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
231
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
232
0
     "%s: unable to copy source MFT attribute to destination.",
233
0
     function );
234
235
0
    goto on_error;
236
0
  }
237
4.42k
  ( *destination_mft_attribute )->name            = NULL;
238
4.42k
  ( *destination_mft_attribute )->data            = NULL;
239
4.42k
  ( *destination_mft_attribute )->data_runs_array = NULL;
240
4.42k
  ( *destination_mft_attribute )->next_attribute  = NULL;
241
242
4.42k
  if( source_mft_attribute->name != NULL )
243
2.33k
  {
244
2.33k
    ( *destination_mft_attribute )->name = (uint8_t *) memory_allocate(
245
2.33k
                                                        source_mft_attribute->name_size );
246
247
2.33k
    if( ( *destination_mft_attribute )->name == NULL )
248
0
    {
249
0
      libcerror_error_set(
250
0
       error,
251
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
252
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
253
0
       "%s: unable to create destination name.",
254
0
       function );
255
256
0
      goto on_error;
257
0
    }
258
2.33k
    if( memory_copy(
259
2.33k
         ( *destination_mft_attribute )->name,
260
2.33k
         source_mft_attribute->name,
261
2.33k
         source_mft_attribute->name_size ) == NULL )
262
0
    {
263
0
      libcerror_error_set(
264
0
       error,
265
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
266
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
267
0
       "%s: unable to copy source name to destination.",
268
0
       function );
269
270
0
      goto on_error;
271
0
    }
272
2.33k
    ( *destination_mft_attribute )->name_size = source_mft_attribute->name_size;
273
2.33k
  }
274
4.42k
  if( source_mft_attribute->data != NULL )
275
840
  {
276
840
    ( *destination_mft_attribute )->data = (uint8_t *) memory_allocate(
277
840
                                                        source_mft_attribute->data_size );
278
279
840
    if( ( *destination_mft_attribute )->data == NULL )
280
0
    {
281
0
      libcerror_error_set(
282
0
       error,
283
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
284
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
285
0
       "%s: unable to create destination data.",
286
0
       function );
287
288
0
      goto on_error;
289
0
    }
290
840
    if( memory_copy(
291
840
         ( *destination_mft_attribute )->data,
292
840
         source_mft_attribute->data,
293
840
         source_mft_attribute->data_size ) == NULL )
294
0
    {
295
0
      libcerror_error_set(
296
0
       error,
297
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
298
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
299
0
       "%s: unable to copy source data to destination.",
300
0
       function );
301
302
0
      goto on_error;
303
0
    }
304
840
    ( *destination_mft_attribute )->data_size = source_mft_attribute->data_size;
305
840
  }
306
4.42k
  if( libcdata_array_clone(
307
4.42k
       &( ( *destination_mft_attribute )->data_runs_array ),
308
4.42k
       source_mft_attribute->data_runs_array,
309
4.42k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free,
310
4.42k
       (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfsntfs_data_run_clone,
311
4.42k
       error ) != 1 )
312
0
  {
313
0
    libcerror_error_set(
314
0
     error,
315
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
316
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
317
0
     "%s: unable to clone data runs array.",
318
0
     function );
319
320
0
    goto on_error;
321
0
  }
322
4.42k
  return( 1 );
323
324
0
on_error:
325
0
  if( *destination_mft_attribute != NULL )
326
0
  {
327
0
    if( ( *destination_mft_attribute )->data != NULL )
328
0
    {
329
0
      memory_free(
330
0
       ( *destination_mft_attribute )->data );
331
0
    }
332
0
    if( ( *destination_mft_attribute )->data != NULL )
333
0
    {
334
0
      memory_free(
335
0
       ( *destination_mft_attribute )->data );
336
0
    }
337
0
    memory_free(
338
0
     *destination_mft_attribute );
339
340
0
    *destination_mft_attribute = NULL;
341
0
  }
342
0
  return( -1 );
343
4.42k
}
344
345
/* Reads the MFT attribute
346
 * Returns 1 if successful or -1 on error
347
 */
348
int libfsntfs_mft_attribute_read_data(
349
     libfsntfs_mft_attribute_t *mft_attribute,
350
     libfsntfs_io_handle_t *io_handle,
351
     const uint8_t *data,
352
     size_t data_size,
353
     libcerror_error_t **error )
354
52.4k
{
355
52.4k
  libfsntfs_data_run_t *data_run     = NULL;
356
52.4k
  const uint8_t *non_resident_data   = NULL;
357
52.4k
  const uint8_t *resident_data       = NULL;
358
52.4k
  static char *function              = "libfsntfs_mft_attribute_read_data";
359
52.4k
  size_t data_offset                 = 0;
360
52.4k
  size_t non_resident_data_size      = 0;
361
52.4k
  ssize_t read_count                 = 0;
362
52.4k
  uint64_t last_cluster_block_number = 0;
363
52.4k
  uint16_t compression_unit_size     = 0;
364
52.4k
  uint16_t data_runs_offset          = 0;
365
52.4k
  uint16_t name_offset               = 0;
366
52.4k
  int data_run_index                 = 0;
367
52.4k
  int entry_index                    = 0;
368
369
#if defined( HAVE_DEBUG_OUTPUT )
370
  uint64_t value_64bit               = 0;
371
  uint32_t value_32bit               = 0;
372
#endif
373
374
52.4k
  if( mft_attribute == NULL )
375
0
  {
376
0
    libcerror_error_set(
377
0
     error,
378
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
379
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
380
0
     "%s: invalid MFT attribute.",
381
0
     function );
382
383
0
    return( -1 );
384
0
  }
385
52.4k
  if( mft_attribute->name != NULL )
386
0
  {
387
0
    libcerror_error_set(
388
0
     error,
389
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
390
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
391
0
     "%s: invalid MFT attribute - name value already set.",
392
0
     function );
393
394
0
    return( -1 );
395
0
  }
396
52.4k
  if( mft_attribute->data != NULL )
397
0
  {
398
0
    libcerror_error_set(
399
0
     error,
400
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
401
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
402
0
     "%s: invalid MFT attribute - data value already set.",
403
0
     function );
404
405
0
    return( -1 );
406
0
  }
407
52.4k
  if( mft_attribute->data_runs_array != 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 attribute - data runs array value already set.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
52.4k
  if( io_handle == 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 IO handle.",
425
0
     function );
426
427
0
    return( -1 );
428
0
  }
429
52.4k
  if( data == NULL )
430
0
  {
431
0
    libcerror_error_set(
432
0
     error,
433
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
434
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
435
0
     "%s: invalid data.",
436
0
     function );
437
438
0
    return( -1 );
439
0
  }
440
52.4k
  if( data_size > (size_t) SSIZE_MAX )
441
0
  {
442
0
    libcerror_error_set(
443
0
     error,
444
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
445
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
446
0
     "%s: data size value exceeds maximum.",
447
0
     function );
448
449
0
    return( -1 );
450
0
  }
451
52.4k
  if( data_size < sizeof( fsntfs_mft_attribute_header_t ) )
452
102
  {
453
102
    libcerror_error_set(
454
102
     error,
455
102
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
456
102
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
457
102
     "%s: unsupported data size value too small\n",
458
102
     function );
459
460
102
    return( -1 );
461
102
  }
462
#if defined( HAVE_DEBUG_OUTPUT )
463
  if( libcnotify_verbose != 0 )
464
  {
465
    libcnotify_printf(
466
     "%s: MFT attribute header data:\n",
467
     function );
468
    libcnotify_print_data(
469
     data,
470
     sizeof( fsntfs_mft_attribute_header_t ),
471
     0 );
472
  }
473
#endif
474
52.3k
  byte_stream_copy_to_uint32_little_endian(
475
52.3k
   ( (fsntfs_mft_attribute_header_t *) data )->type,
476
52.3k
   mft_attribute->type );
477
478
52.3k
  byte_stream_copy_to_uint32_little_endian(
479
52.3k
   ( (fsntfs_mft_attribute_header_t *) data )->size,
480
52.3k
   mft_attribute->size );
481
482
52.3k
  mft_attribute->non_resident_flag = ( (fsntfs_mft_attribute_header_t *) data )->non_resident_flag;
483
484
52.3k
  mft_attribute->name_size = (uint16_t) ( (fsntfs_mft_attribute_header_t *) data )->name_size;
485
486
52.3k
  byte_stream_copy_to_uint16_little_endian(
487
52.3k
   ( (fsntfs_mft_attribute_header_t *) data )->name_offset,
488
52.3k
   name_offset );
489
490
52.3k
  byte_stream_copy_to_uint16_little_endian(
491
52.3k
   ( (fsntfs_mft_attribute_header_t *) data )->data_flags,
492
52.3k
   mft_attribute->data_flags );
493
494
52.3k
  byte_stream_copy_to_uint16_little_endian(
495
52.3k
   ( (fsntfs_mft_attribute_header_t *) data )->identifier,
496
52.3k
   mft_attribute->identifier );
497
498
#if defined( HAVE_DEBUG_OUTPUT )
499
  if( libcnotify_verbose != 0 )
500
  {
501
    libcnotify_printf(
502
     "%s: type\t\t\t\t\t: 0x%08" PRIx32 " (%s)\n",
503
     function,
504
     mft_attribute->type,
505
     libfsntfs_debug_print_attribute_type(
506
      mft_attribute->type ) );
507
508
    libcnotify_printf(
509
     "%s: size\t\t\t\t\t: %" PRIu32 "\n",
510
     function,
511
     mft_attribute->size );
512
513
    libcnotify_printf(
514
     "%s: non resident flag\t\t\t: 0x%02" PRIx8 "\n",
515
     function,
516
     mft_attribute->non_resident_flag );
517
518
    libcnotify_printf(
519
     "%s: name size\t\t\t\t: %" PRIu16 "\n",
520
     function,
521
     mft_attribute->name_size );
522
523
    libcnotify_printf(
524
     "%s: name offset\t\t\t\t: %" PRIu16 "\n",
525
     function,
526
     name_offset );
527
528
    libcnotify_printf(
529
     "%s: data flags\t\t\t\t: 0x%04" PRIx16 "\n",
530
     function,
531
     mft_attribute->data_flags );
532
    libfsntfs_debug_print_mft_attribute_data_flags(
533
     mft_attribute->data_flags );
534
    libcnotify_printf(
535
     "\n" );
536
537
    libcnotify_printf(
538
     "%s: identifier\t\t\t\t: %" PRIu16 "\n",
539
     function,
540
     mft_attribute->identifier );
541
542
    libcnotify_printf(
543
     "\n" );
544
  }
545
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
546
547
52.3k
  data_offset = sizeof( fsntfs_mft_attribute_header_t );
548
549
52.3k
  if( ( mft_attribute->size < sizeof( fsntfs_mft_attribute_header_t ) )
550
52.3k
   || ( mft_attribute->size > data_size ) )
551
457
  {
552
457
    libcerror_error_set(
553
457
     error,
554
457
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
555
457
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
556
457
     "%s: size value out of bounds.",
557
457
     function );
558
559
457
    goto on_error;
560
457
  }
561
51.9k
  if( ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0x0000 )
562
51.9k
   && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0x0001 ) )
563
28
  {
564
28
    libcerror_error_set(
565
28
     error,
566
28
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
28
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
568
28
     "%s: unsupported compression flags: 0x%04" PRIx16 ".",
569
28
     function,
570
28
     mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK );
571
572
28
    goto on_error;
573
28
  }
574
51.8k
  if( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 )
575
7.31k
  {
576
7.31k
    if( io_handle->cluster_block_size > 4096 )
577
2
    {
578
2
      libcerror_error_set(
579
2
       error,
580
2
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
581
2
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
582
2
       "%s: unsupported compression flags: 0x%04" PRIx16 " for volume with cluster block size: %" PRIzd ".",
583
2
       function,
584
2
       mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK,
585
2
       io_handle->cluster_block_size );
586
587
2
      goto on_error;
588
2
    }
589
7.31k
  }
590
51.8k
  mft_attribute->name_size *= 2;
591
592
51.8k
  if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 )
593
26.4k
  {
594
26.4k
    if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_resident_t ) ) )
595
11
    {
596
11
      libcerror_error_set(
597
11
       error,
598
11
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
599
11
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
600
11
       "%s: unsupported data size value too small\n",
601
11
       function );
602
603
11
      return( -1 );
604
11
    }
605
26.4k
    resident_data = &( data[ data_offset ] );
606
607
26.4k
    if( mft_attribute->size < ( data_offset + sizeof( fsntfs_mft_attribute_resident_t ) ) )
608
12
    {
609
12
      libcerror_error_set(
610
12
       error,
611
12
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
612
12
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
613
12
       "%s: invalid MFT attribute size value out of bounds.",
614
12
       function );
615
616
12
      goto on_error;
617
12
    }
618
#if defined( HAVE_DEBUG_OUTPUT )
619
    if( libcnotify_verbose != 0 )
620
    {
621
      libcnotify_printf(
622
       "%s: MFT attribute resident data:\n",
623
       function );
624
      libcnotify_print_data(
625
       resident_data,
626
       sizeof( fsntfs_mft_attribute_resident_t ),
627
       0 );
628
    }
629
#endif
630
26.4k
    byte_stream_copy_to_uint32_little_endian(
631
26.4k
     ( (fsntfs_mft_attribute_resident_t *) resident_data )->data_size,
632
26.4k
     mft_attribute->data_size );
633
634
26.4k
    byte_stream_copy_to_uint16_little_endian(
635
26.4k
     ( (fsntfs_mft_attribute_resident_t *) resident_data )->data_offset,
636
26.4k
     mft_attribute->data_offset );
637
638
#if defined( HAVE_DEBUG_OUTPUT )
639
    if( libcnotify_verbose != 0 )
640
    {
641
      libcnotify_printf(
642
       "%s: data size\t\t\t\t: %" PRIu64 "\n",
643
       function,
644
       mft_attribute->data_size );
645
646
      libcnotify_printf(
647
       "%s: data offset\t\t\t\t: %" PRIu16 "\n",
648
       function,
649
       mft_attribute->data_offset );
650
651
      libcnotify_printf(
652
       "%s: indexed flag\t\t\t\t: 0x%02" PRIx8 "\n",
653
       function,
654
       ( (fsntfs_mft_attribute_resident_t *) resident_data )->indexed_flag );
655
656
      libcnotify_printf(
657
       "%s: padding\t\t\t\t: 0x%02" PRIx8 "\n",
658
       function,
659
       ( (fsntfs_mft_attribute_resident_t *) resident_data )->padding );
660
661
      libcnotify_printf(
662
       "\n" );
663
    }
664
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
665
666
26.4k
    data_offset += sizeof( fsntfs_mft_attribute_resident_t );
667
26.4k
  }
668
25.4k
  else
669
25.4k
  {
670
25.4k
    if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_non_resident_t ) ) )
671
19
    {
672
19
      libcerror_error_set(
673
19
       error,
674
19
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
675
19
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
676
19
       "%s: unsupported data size value too small\n",
677
19
       function );
678
679
19
      return( -1 );
680
19
    }
681
25.4k
    non_resident_data      = &( data[ data_offset ] );
682
25.4k
    non_resident_data_size = sizeof( fsntfs_mft_attribute_non_resident_t );
683
684
25.4k
    byte_stream_copy_to_uint16_little_endian(
685
25.4k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->compression_unit_size,
686
25.4k
     compression_unit_size );
687
688
25.4k
    if( compression_unit_size != 0 )
689
12.7k
    {
690
12.7k
      if( data_size < ( data_offset + sizeof( fsntfs_mft_attribute_non_resident_compressed_t ) ) )
691
10
      {
692
10
        libcerror_error_set(
693
10
         error,
694
10
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
695
10
         LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
696
10
         "%s: unsupported data size value too small.",
697
10
         function );
698
699
10
        goto on_error;
700
10
      }
701
12.7k
      non_resident_data_size = sizeof( fsntfs_mft_attribute_non_resident_compressed_t );
702
703
12.7k
      if( compression_unit_size > 31 )
704
47
      {
705
47
        libcerror_error_set(
706
47
         error,
707
47
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
708
47
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
709
47
         "%s: compression unit size value out of bounds.",
710
47
         function );
711
712
47
        goto on_error;
713
47
      }
714
      /* The size is calculated as: 2 ^ value
715
       */
716
12.6k
      mft_attribute->compression_unit_size  = (size_t) 1 << compression_unit_size;
717
12.6k
      mft_attribute->compression_unit_size *= io_handle->cluster_block_size;
718
12.6k
    }
719
12.6k
    else if( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 )
720
1.64k
    {
721
#if defined( HAVE_DEBUG_OUTPUT )
722
      if( libcnotify_verbose != 0 )
723
      {
724
        libcnotify_printf(
725
         "%s: data is flagged as compressed but no compression unit size set.\n",
726
         function );
727
      }
728
#endif
729
1.64k
      mft_attribute->compression_unit_size = 16 * io_handle->cluster_block_size;
730
1.64k
    }
731
25.3k
    if( mft_attribute->size < ( data_offset + non_resident_data_size ) )
732
19
    {
733
19
      libcerror_error_set(
734
19
       error,
735
19
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
19
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
737
19
       "%s: invalid MFT attribute size value out of bounds.",
738
19
       function );
739
740
19
      goto on_error;
741
19
    }
742
#if defined( HAVE_DEBUG_OUTPUT )
743
    if( libcnotify_verbose != 0 )
744
    {
745
      libcnotify_printf(
746
       "%s: MFT attribute non-resident data:\n",
747
       function );
748
      libcnotify_print_data(
749
       non_resident_data,
750
       non_resident_data_size,
751
       0 );
752
    }
753
#endif
754
25.3k
    byte_stream_copy_to_uint64_little_endian(
755
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_first_vcn,
756
25.3k
     mft_attribute->data_first_vcn );
757
758
25.3k
    byte_stream_copy_to_uint64_little_endian(
759
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_last_vcn,
760
25.3k
     mft_attribute->data_last_vcn );
761
762
25.3k
    byte_stream_copy_to_uint16_little_endian(
763
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_runs_offset,
764
25.3k
     data_runs_offset );
765
766
25.3k
    byte_stream_copy_to_uint64_little_endian(
767
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->allocated_data_size,
768
25.3k
     mft_attribute->allocated_data_size );
769
770
25.3k
    byte_stream_copy_to_uint64_little_endian(
771
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->data_size,
772
25.3k
     mft_attribute->data_size );
773
774
25.3k
    byte_stream_copy_to_uint64_little_endian(
775
25.3k
     ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->valid_data_size,
776
25.3k
     mft_attribute->valid_data_size );
777
778
#if defined( HAVE_DEBUG_OUTPUT )
779
    if( libcnotify_verbose != 0 )
780
    {
781
      libcnotify_printf(
782
       "%s: data first VCN\t\t\t: %" PRIi64 "\n",
783
       function,
784
       (int64_t) mft_attribute->data_first_vcn );
785
786
      libcnotify_printf(
787
       "%s: data last VCN\t\t\t: %" PRIi64 "\n",
788
       function,
789
       (int64_t) mft_attribute->data_last_vcn );
790
791
      libcnotify_printf(
792
       "%s: data runs offset\t\t\t: 0x%04" PRIx16 "\n",
793
       function,
794
       data_runs_offset );
795
796
      libcnotify_printf(
797
       "%s: compression unit size\t\t: %" PRIu16 " (%" PRIzd ")\n",
798
       function,
799
       compression_unit_size,
800
       mft_attribute->compression_unit_size );
801
802
      byte_stream_copy_to_uint32_little_endian(
803
       ( (fsntfs_mft_attribute_non_resident_t *) non_resident_data )->padding,
804
       value_32bit );
805
      libcnotify_printf(
806
       "%s: padding\t\t\t\t: 0x%08" PRIx32 "\n",
807
       function,
808
       value_32bit );
809
810
      libcnotify_printf(
811
       "%s: allocated data size\t\t\t: %" PRIu64 "\n",
812
       function,
813
       mft_attribute->allocated_data_size );
814
815
      libcnotify_printf(
816
       "%s: data size\t\t\t\t: %" PRIu64 "\n",
817
       function,
818
       mft_attribute->data_size );
819
820
      libcnotify_printf(
821
       "%s: valid data size\t\t\t: %" PRIu64 " (0x%08" PRIx64 ")\n",
822
       function,
823
       mft_attribute->valid_data_size,
824
       mft_attribute->valid_data_size );
825
826
      if( compression_unit_size > 0 )
827
      {
828
        byte_stream_copy_to_uint64_little_endian(
829
         ( (fsntfs_mft_attribute_non_resident_compressed_t *) non_resident_data )->total_data_size,
830
         value_64bit );
831
        libcnotify_printf(
832
         "%s: total data size\t\t\t: %" PRIu64 "\n",
833
         function,
834
         value_64bit );
835
      }
836
      libcnotify_printf(
837
       "\n" );
838
    }
839
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
840
841
25.3k
    data_offset += sizeof( fsntfs_mft_attribute_non_resident_t );
842
843
25.3k
    if( mft_attribute->valid_data_size > mft_attribute->data_size )
844
12
    {
845
12
      libcerror_error_set(
846
12
       error,
847
12
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
848
12
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
849
12
       "%s: valid data size value out of bounds.",
850
12
       function );
851
852
12
      goto on_error;
853
12
    }
854
25.3k
  }
855
51.7k
  if( mft_attribute->name_size > 0 )
856
17.6k
  {
857
17.6k
    if( ( name_offset < data_offset )
858
17.6k
     || ( name_offset >= mft_attribute->size ) )
859
52
    {
860
52
      libcerror_error_set(
861
52
       error,
862
52
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
863
52
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
864
52
       "%s: name offset value out of bounds.",
865
52
       function );
866
867
52
      goto on_error;
868
52
    }
869
#if defined( HAVE_DEBUG_OUTPUT )
870
    if( libcnotify_verbose != 0 )
871
    {
872
      if( data_offset < name_offset )
873
      {
874
        libcnotify_printf(
875
         "%s: unknown data:\n",
876
         function );
877
        libcnotify_print_data(
878
         &( data[ data_offset ] ),
879
         (size_t) name_offset - data_offset,
880
         0 );
881
      }
882
    }
883
#endif
884
17.5k
    if( mft_attribute->name_size > ( mft_attribute->size - name_offset ) )
885
11
    {
886
11
      libcerror_error_set(
887
11
       error,
888
11
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
889
11
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
890
11
       "%s: name size value out of bounds.",
891
11
       function );
892
893
11
      goto on_error;
894
11
    }
895
17.5k
    data_offset = (size_t) name_offset;
896
897
#if defined( HAVE_DEBUG_OUTPUT )
898
    if( libcnotify_verbose != 0 )
899
    {
900
      libcnotify_printf(
901
       "%s: name data:\n",
902
       function );
903
      libcnotify_print_data(
904
       &( data[ data_offset ] ),
905
       (size_t) mft_attribute->name_size,
906
       0 );
907
    }
908
#endif
909
17.5k
    mft_attribute->name = (uint8_t *) memory_allocate(
910
17.5k
                                       sizeof( uint8_t ) * (size_t) mft_attribute->name_size );
911
912
17.5k
    if( mft_attribute->name == NULL )
913
0
    {
914
0
      libcerror_error_set(
915
0
       error,
916
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
917
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
918
0
       "%s: unable to create name.",
919
0
       function );
920
921
0
      goto on_error;
922
0
    }
923
17.5k
    if( memory_copy(
924
17.5k
         mft_attribute->name,
925
17.5k
         &( data[ data_offset ] ),
926
17.5k
         (size_t) mft_attribute->name_size ) == NULL )
927
0
    {
928
0
      libcerror_error_set(
929
0
       error,
930
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
931
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
932
0
       "%s: unable to copy name.",
933
0
       function );
934
935
0
      goto on_error;
936
0
    }
937
17.5k
    data_offset += (size_t) mft_attribute->name_size;
938
939
#if defined( HAVE_DEBUG_OUTPUT )
940
    if( libcnotify_verbose != 0 )
941
    {
942
      if( libfsntfs_debug_print_utf16_string_value(
943
           function,
944
           "name\t\t\t\t\t",
945
           mft_attribute->name,
946
           (size_t) mft_attribute->name_size,
947
           LIBUNA_ENDIAN_LITTLE,
948
           error ) != 1 )
949
      {
950
        libcerror_error_set(
951
         error,
952
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
953
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
954
         "%s: unable to print UTF-16 string value.",
955
         function );
956
957
        goto on_error;
958
      }
959
      libcnotify_printf(
960
       "\n" );
961
    }
962
#endif
963
17.5k
  }
964
51.6k
  if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 )
965
26.3k
  {
966
26.3k
    if( mft_attribute->data_size > 0 )
967
17.0k
    {
968
17.0k
      if( ( mft_attribute->data_offset < data_offset )
969
17.0k
       || ( mft_attribute->data_offset >= mft_attribute->size ) )
970
103
      {
971
103
        libcerror_error_set(
972
103
         error,
973
103
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
974
103
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
975
103
         "%s: resident data offset value out of bounds.",
976
103
         function );
977
978
103
        goto on_error;
979
103
      }
980
16.9k
      if( mft_attribute->data_size > ( mft_attribute->size - mft_attribute->data_offset ) )
981
148
      {
982
148
        libcerror_error_set(
983
148
         error,
984
148
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
985
148
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
986
148
         "%s: resident data size value out of bounds.",
987
148
         function );
988
989
148
        goto on_error;
990
148
      }
991
#if defined( HAVE_DEBUG_OUTPUT )
992
      if( libcnotify_verbose != 0 )
993
      {
994
        libcnotify_printf(
995
         "%s: resident data:\n",
996
         function );
997
        libcnotify_print_data(
998
         &( data[ mft_attribute->data_offset ] ),
999
         (size_t) mft_attribute->data_size,
1000
         0 );
1001
      }
1002
#endif
1003
16.8k
      mft_attribute->data = (uint8_t *) memory_allocate(
1004
16.8k
                                         sizeof( uint8_t ) * (size_t) mft_attribute->data_size );
1005
1006
16.8k
      if( mft_attribute->data == NULL )
1007
0
      {
1008
0
        libcerror_error_set(
1009
0
         error,
1010
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1011
0
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1012
0
         "%s: unable to create resident data.",
1013
0
         function );
1014
1015
0
        goto on_error;
1016
0
      }
1017
16.8k
      if( memory_copy(
1018
16.8k
           mft_attribute->data,
1019
16.8k
           &( data[ mft_attribute->data_offset ] ),
1020
16.8k
           (size_t) mft_attribute->data_size ) == NULL )
1021
0
      {
1022
0
        libcerror_error_set(
1023
0
         error,
1024
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1025
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1026
0
         "%s: unable to copy resident data.",
1027
0
         function );
1028
1029
0
        goto on_error;
1030
0
      }
1031
16.8k
      data_offset = (size_t) mft_attribute->data_offset + (size_t) mft_attribute->data_size;
1032
16.8k
    }
1033
26.3k
  }
1034
25.3k
  else
1035
25.3k
  {
1036
    /* Note that data size is set in the first attribute of a chain
1037
     * and successive elements contain a size of 0
1038
     */
1039
25.3k
    if( ( data_runs_offset < data_offset )
1040
25.3k
     || ( data_runs_offset >= mft_attribute->size ) )
1041
82
    {
1042
82
      libcerror_error_set(
1043
82
       error,
1044
82
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1045
82
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1046
82
       "%s: data runs offset value out of bounds.",
1047
82
       function );
1048
1049
82
      goto on_error;
1050
82
    }
1051
#if defined( HAVE_DEBUG_OUTPUT )
1052
    if( libcnotify_verbose != 0 )
1053
    {
1054
      if( data_offset < name_offset )
1055
      {
1056
        libcnotify_printf(
1057
         "%s: unknown data:\n",
1058
         function );
1059
        libcnotify_print_data(
1060
         &( data[ data_offset ] ),
1061
         (size_t) data_runs_offset - data_offset,
1062
         0 );
1063
      }
1064
    }
1065
#endif
1066
25.2k
    data_offset = (size_t) data_runs_offset;
1067
1068
25.2k
    if( libcdata_array_initialize(
1069
25.2k
         &( mft_attribute->data_runs_array ),
1070
25.2k
         0,
1071
25.2k
         error ) != 1 )
1072
0
    {
1073
0
      libcerror_error_set(
1074
0
       error,
1075
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1076
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1077
0
       "%s: unable to create data runs array.",
1078
0
       function );
1079
1080
0
      goto on_error;
1081
0
    }
1082
866k
    while( data_offset < data_size )
1083
866k
    {
1084
866k
      if( libfsntfs_data_run_initialize(
1085
866k
           &data_run,
1086
866k
           error ) != 1 )
1087
0
      {
1088
0
        libcerror_error_set(
1089
0
         error,
1090
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1091
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1092
0
         "%s: unable to create data run: %d.",
1093
0
         function,
1094
0
         data_run_index );
1095
1096
0
        goto on_error;
1097
0
      }
1098
#if defined( HAVE_DEBUG_OUTPUT )
1099
      if( libcnotify_verbose != 0 )
1100
      {
1101
        libcnotify_printf(
1102
         "%s: reading data run: %d.\n",
1103
         function,
1104
         data_run_index );
1105
      }
1106
#endif
1107
866k
      read_count = libfsntfs_data_run_read_data(
1108
866k
                    data_run,
1109
866k
                    io_handle,
1110
866k
                    &( data[ data_offset ] ),
1111
866k
                    data_size - data_offset,
1112
866k
                    last_cluster_block_number,
1113
866k
                    error );
1114
1115
866k
      if( read_count <= -1 )
1116
21
      {
1117
21
        libcerror_error_set(
1118
21
         error,
1119
21
         LIBCERROR_ERROR_DOMAIN_IO,
1120
21
         LIBCERROR_IO_ERROR_READ_FAILED,
1121
21
         "%s: unable to read data run: %d.",
1122
21
         function,
1123
21
         data_run_index );
1124
1125
21
        goto on_error;
1126
21
      }
1127
866k
      else if( read_count == 1 )
1128
24.5k
      {
1129
24.5k
        if( libfsntfs_data_run_free(
1130
24.5k
             &data_run,
1131
24.5k
             error ) != 1 )
1132
0
        {
1133
0
          libcerror_error_set(
1134
0
           error,
1135
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1136
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1137
0
           "%s: unable to free data run: %d.",
1138
0
           function,
1139
0
           data_run_index );
1140
1141
0
          goto on_error;
1142
0
        }
1143
24.5k
        break;
1144
24.5k
      }
1145
841k
      data_offset += read_count;
1146
1147
#if defined( HAVE_DEBUG_OUTPUT )
1148
      if( libcnotify_verbose != 0 )
1149
      {
1150
        if( ( data_run->start_offset == 0 )
1151
         && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) == 0 )
1152
         && ( ( mft_attribute->data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_SPARSE ) == 0 ) )
1153
        {
1154
          libcnotify_printf(
1155
           "%s: data run is sparse but no attribute data flags set.\n\n",
1156
           function );
1157
        }
1158
      }
1159
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1160
1161
841k
      if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) == 0 )
1162
58.3k
      {
1163
58.3k
        last_cluster_block_number = data_run->cluster_block_number;
1164
58.3k
      }
1165
841k
      if( libcdata_array_append_entry(
1166
841k
           mft_attribute->data_runs_array,
1167
841k
           &entry_index,
1168
841k
           (intptr_t *) data_run,
1169
841k
           error ) != 1 )
1170
0
      {
1171
0
        libcerror_error_set(
1172
0
         error,
1173
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1174
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1175
0
         "%s: unable to append data run: %d to array.",
1176
0
         function,
1177
0
         data_run_index );
1178
1179
0
        goto on_error;
1180
0
      }
1181
841k
      data_run = NULL;
1182
1183
841k
      data_run_index++;
1184
841k
    }
1185
25.2k
  }
1186
#if defined( HAVE_DEBUG_OUTPUT )
1187
  if( libcnotify_verbose != 0 )
1188
  {
1189
    if( data_offset < mft_attribute->size )
1190
    {
1191
      libcnotify_printf(
1192
       "%s: trailing data:\n",
1193
       function );
1194
      libcnotify_print_data(
1195
       &( data[ data_offset ] ),
1196
       (size_t) mft_attribute->size - data_offset,
1197
       0 );
1198
    }
1199
  }
1200
#endif
1201
51.3k
  return( 1 );
1202
1203
1.00k
on_error:
1204
1.00k
  if( data_run != NULL )
1205
21
  {
1206
21
    libfsntfs_data_run_free(
1207
21
     &data_run,
1208
21
     NULL );
1209
21
  }
1210
1.00k
  if( mft_attribute->data_runs_array != NULL )
1211
21
  {
1212
21
    libcdata_array_free(
1213
21
     &( mft_attribute->data_runs_array ),
1214
21
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_data_run_free,
1215
21
     NULL );
1216
21
  }
1217
1.00k
  if( mft_attribute->data != NULL )
1218
0
  {
1219
0
    memory_free(
1220
0
     mft_attribute->data );
1221
1222
0
    mft_attribute->data = NULL;
1223
0
  }
1224
1.00k
  if( mft_attribute->name != NULL )
1225
149
  {
1226
149
    memory_free(
1227
149
     mft_attribute->name );
1228
1229
149
    mft_attribute->name = NULL;
1230
149
  }
1231
1.00k
  mft_attribute->name_size = 0;
1232
1233
1.00k
  return( -1 );
1234
51.6k
}
1235
1236
/* Determines if the attribute data is resident
1237
 * Returns 1 if the attribute data is resident, 0 if not or -1 on error
1238
 */
1239
int libfsntfs_mft_attribute_data_is_resident(
1240
     libfsntfs_mft_attribute_t *mft_attribute,
1241
     libcerror_error_t **error )
1242
12.3k
{
1243
12.3k
  static char *function = "libfsntfs_mft_attribute_data_is_resident";
1244
1245
12.3k
  if( mft_attribute == NULL )
1246
0
  {
1247
0
    libcerror_error_set(
1248
0
     error,
1249
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1250
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1251
0
     "%s: invalid MFT attribute.",
1252
0
     function );
1253
1254
0
    return( -1 );
1255
0
  }
1256
12.3k
  if( ( mft_attribute->non_resident_flag & 0x01 ) == 0 )
1257
8.29k
  {
1258
8.29k
    return( 1 );
1259
8.29k
  }
1260
4.04k
  return( 0 );
1261
12.3k
}
1262
1263
/* Retrieves the type
1264
 * Returns 1 if successful or -1 on error
1265
 */
1266
int libfsntfs_mft_attribute_get_type(
1267
     libfsntfs_mft_attribute_t *mft_attribute,
1268
     uint32_t *type,
1269
     libcerror_error_t **error )
1270
63.8k
{
1271
63.8k
  static char *function = "libfsntfs_mft_attribute_get_type";
1272
1273
63.8k
  if( mft_attribute == NULL )
1274
0
  {
1275
0
    libcerror_error_set(
1276
0
     error,
1277
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1278
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1279
0
     "%s: invalid MFT attribute.",
1280
0
     function );
1281
1282
0
    return( -1 );
1283
0
  }
1284
63.8k
  if( type == NULL )
1285
0
  {
1286
0
    libcerror_error_set(
1287
0
     error,
1288
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1289
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1290
0
     "%s: invalid type.",
1291
0
     function );
1292
1293
0
    return( -1 );
1294
0
  }
1295
63.8k
  *type = mft_attribute->type;
1296
1297
63.8k
  return( 1 );
1298
63.8k
}
1299
1300
/* Retrieves the data flags
1301
 * Returns 1 if successful or -1 on error
1302
 */
1303
int libfsntfs_mft_attribute_get_data_flags(
1304
     libfsntfs_mft_attribute_t *mft_attribute,
1305
     uint16_t *data_flags,
1306
     libcerror_error_t **error )
1307
17.0k
{
1308
17.0k
  static char *function = "libfsntfs_mft_attribute_get_data_flags";
1309
1310
17.0k
  if( mft_attribute == NULL )
1311
356
  {
1312
356
    libcerror_error_set(
1313
356
     error,
1314
356
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1315
356
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1316
356
     "%s: invalid MFT attribute.",
1317
356
     function );
1318
1319
356
    return( -1 );
1320
356
  }
1321
16.6k
  if( data_flags == NULL )
1322
0
  {
1323
0
    libcerror_error_set(
1324
0
     error,
1325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1326
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1327
0
     "%s: invalid data flags.",
1328
0
     function );
1329
1330
0
    return( -1 );
1331
0
  }
1332
16.6k
  *data_flags = mft_attribute->data_flags;
1333
1334
16.6k
  return( 1 );
1335
16.6k
}
1336
1337
/* Retrieves the data size
1338
 * Returns 1 if successful or -1 on error
1339
 */
1340
int libfsntfs_mft_attribute_get_data_size(
1341
     libfsntfs_mft_attribute_t *mft_attribute,
1342
     uint64_t *data_size,
1343
     libcerror_error_t **error )
1344
11.7k
{
1345
11.7k
  static char *function = "libfsntfs_mft_attribute_get_data_size";
1346
1347
11.7k
  if( mft_attribute == NULL )
1348
0
  {
1349
0
    libcerror_error_set(
1350
0
     error,
1351
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1352
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1353
0
     "%s: invalid MFT attribute.",
1354
0
     function );
1355
1356
0
    return( -1 );
1357
0
  }
1358
11.7k
  if( data_size == NULL )
1359
0
  {
1360
0
    libcerror_error_set(
1361
0
     error,
1362
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1363
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1364
0
     "%s: invalid data size.",
1365
0
     function );
1366
1367
0
    return( -1 );
1368
0
  }
1369
11.7k
  *data_size = mft_attribute->data_size;
1370
1371
11.7k
  return( 1 );
1372
11.7k
}
1373
1374
/* Retrieves the data VCN range
1375
 * Returns 1 if successful, 0 if not available or -1 on error
1376
 */
1377
int libfsntfs_mft_attribute_get_data_vcn_range(
1378
     libfsntfs_mft_attribute_t *mft_attribute,
1379
     uint64_t *data_first_vcn,
1380
     uint64_t *data_last_vcn,
1381
     libcerror_error_t **error )
1382
4.99k
{
1383
4.99k
  static char *function = "libfsntfs_mft_attribute_get_data_vcn_range";
1384
1385
4.99k
  if( mft_attribute == NULL )
1386
0
  {
1387
0
    libcerror_error_set(
1388
0
     error,
1389
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1390
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1391
0
     "%s: invalid MFT attribute.",
1392
0
     function );
1393
1394
0
    return( -1 );
1395
0
  }
1396
4.99k
  if( data_first_vcn == NULL )
1397
0
  {
1398
0
    libcerror_error_set(
1399
0
     error,
1400
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1401
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1402
0
     "%s: invalid data first VCN.",
1403
0
     function );
1404
1405
0
    return( -1 );
1406
0
  }
1407
4.99k
  if( data_last_vcn == NULL )
1408
0
  {
1409
0
    libcerror_error_set(
1410
0
     error,
1411
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1412
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1413
0
     "%s: invalid data last VCN.",
1414
0
     function );
1415
1416
0
    return( -1 );
1417
0
  }
1418
4.99k
  if( ( mft_attribute->non_resident_flag & 0x01 ) != 0 )
1419
4.95k
  {
1420
4.95k
    *data_first_vcn = mft_attribute->data_first_vcn;
1421
4.95k
    *data_last_vcn  = mft_attribute->data_last_vcn;
1422
1423
4.95k
    return( 1 );
1424
4.95k
  }
1425
41
  return( 0 );
1426
4.99k
}
1427
1428
/* Retrieves the allocated data size
1429
 * Returns 1 if successful or -1 on error
1430
 */
1431
int libfsntfs_mft_attribute_get_allocated_data_size(
1432
     libfsntfs_mft_attribute_t *mft_attribute,
1433
     uint64_t *allocated_data_size,
1434
     libcerror_error_t **error )
1435
5.72k
{
1436
5.72k
  static char *function = "libfsntfs_mft_attribute_get_allocated_data_size";
1437
1438
5.72k
  if( mft_attribute == NULL )
1439
0
  {
1440
0
    libcerror_error_set(
1441
0
     error,
1442
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1443
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1444
0
     "%s: invalid MFT attribute.",
1445
0
     function );
1446
1447
0
    return( -1 );
1448
0
  }
1449
5.72k
  if( allocated_data_size == NULL )
1450
0
  {
1451
0
    libcerror_error_set(
1452
0
     error,
1453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1455
0
     "%s: invalid allocated data size.",
1456
0
     function );
1457
1458
0
    return( -1 );
1459
0
  }
1460
5.72k
  *allocated_data_size = mft_attribute->allocated_data_size;
1461
1462
5.72k
  return( 1 );
1463
5.72k
}
1464
1465
/* Retrieves the valid data size
1466
 * Returns 1 if successful or -1 on error
1467
 */
1468
int libfsntfs_mft_attribute_get_valid_data_size(
1469
     libfsntfs_mft_attribute_t *mft_attribute,
1470
     uint64_t *valid_data_size,
1471
     libcerror_error_t **error )
1472
3.31k
{
1473
3.31k
  static char *function = "libfsntfs_mft_attribute_get_valid_data_size";
1474
1475
3.31k
  if( mft_attribute == NULL )
1476
0
  {
1477
0
    libcerror_error_set(
1478
0
     error,
1479
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1480
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1481
0
     "%s: invalid MFT attribute.",
1482
0
     function );
1483
1484
0
    return( -1 );
1485
0
  }
1486
3.31k
  if( valid_data_size == NULL )
1487
0
  {
1488
0
    libcerror_error_set(
1489
0
     error,
1490
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1491
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1492
0
     "%s: invalid valid data size.",
1493
0
     function );
1494
1495
0
    return( -1 );
1496
0
  }
1497
3.31k
  *valid_data_size = mft_attribute->valid_data_size;
1498
1499
3.31k
  return( 1 );
1500
3.31k
}
1501
1502
/* Retrieves the size of the UTF-8 encoded name
1503
 * The returned size includes the end of string character
1504
 * Returns 1 if successful or -1 on error
1505
 */
1506
int libfsntfs_mft_attribute_get_utf8_name_size(
1507
     libfsntfs_mft_attribute_t *mft_attribute,
1508
     size_t *utf8_string_size,
1509
     libcerror_error_t **error )
1510
75.7k
{
1511
75.7k
  static char *function = "libfsntfs_mft_attribute_get_utf8_name_size";
1512
1513
75.7k
  if( mft_attribute == NULL )
1514
0
  {
1515
0
    libcerror_error_set(
1516
0
     error,
1517
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1518
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1519
0
     "%s: invalid MFT attribute.",
1520
0
     function );
1521
1522
0
    return( -1 );
1523
0
  }
1524
75.7k
  if( ( mft_attribute->name == NULL )
1525
75.7k
   || ( mft_attribute->name_size == 0 ) )
1526
49.4k
  {
1527
49.4k
    if( utf8_string_size == NULL )
1528
0
    {
1529
0
      libcerror_error_set(
1530
0
       error,
1531
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1532
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1533
0
       "%s: invalid UTF-8 string size.",
1534
0
       function );
1535
1536
0
      return( -1 );
1537
0
    }
1538
49.4k
    *utf8_string_size = 0;
1539
49.4k
  }
1540
26.2k
  else
1541
26.2k
  {
1542
26.2k
    if( libuna_utf8_string_size_from_utf16_stream(
1543
26.2k
         mft_attribute->name,
1544
26.2k
         (size_t) mft_attribute->name_size,
1545
26.2k
         LIBUNA_ENDIAN_LITTLE,
1546
26.2k
         utf8_string_size,
1547
26.2k
         error ) != 1 )
1548
95
    {
1549
95
      libcerror_error_set(
1550
95
       error,
1551
95
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1552
95
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1553
95
       "%s: unable to retrieve UTF-8 string size.",
1554
95
       function );
1555
1556
95
      return( -1 );
1557
95
    }
1558
26.2k
  }
1559
75.6k
  return( 1 );
1560
75.7k
}
1561
1562
/* Retrieves the UTF-8 encoded name
1563
 * The size should include the end of string character
1564
 * Returns 1 if successful or -1 on error
1565
 */
1566
int libfsntfs_mft_attribute_get_utf8_name(
1567
     libfsntfs_mft_attribute_t *mft_attribute,
1568
     uint8_t *utf8_string,
1569
     size_t utf8_string_size,
1570
     libcerror_error_t **error )
1571
11.7k
{
1572
11.7k
  static char *function = "libfsntfs_mft_attribute_get_utf8_name";
1573
1574
11.7k
  if( mft_attribute == NULL )
1575
0
  {
1576
0
    libcerror_error_set(
1577
0
     error,
1578
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1579
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1580
0
     "%s: invalid MFT attribute.",
1581
0
     function );
1582
1583
0
    return( -1 );
1584
0
  }
1585
11.7k
  if( mft_attribute->name == NULL )
1586
0
  {
1587
0
    libcerror_error_set(
1588
0
     error,
1589
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1590
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1591
0
     "%s: invalid MFT attribute - missing name.",
1592
0
     function );
1593
1594
0
    return( -1 );
1595
0
  }
1596
11.7k
  if( libuna_utf8_string_copy_from_utf16_stream(
1597
11.7k
       utf8_string,
1598
11.7k
       utf8_string_size,
1599
11.7k
       mft_attribute->name,
1600
11.7k
       (size_t) mft_attribute->name_size,
1601
11.7k
       LIBUNA_ENDIAN_LITTLE,
1602
11.7k
       error ) != 1 )
1603
0
  {
1604
0
    libcerror_error_set(
1605
0
     error,
1606
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1607
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1608
0
     "%s: unable to retrieve UTF-8 string.",
1609
0
     function );
1610
1611
0
    return( -1 );
1612
0
  }
1613
11.7k
  return( 1 );
1614
11.7k
}
1615
1616
/* Retrieves the size of the UTF-16 encoded name
1617
 * The returned size includes the end of string character
1618
 * Returns 1 if successful or -1 on error
1619
 */
1620
int libfsntfs_mft_attribute_get_utf16_name_size(
1621
     libfsntfs_mft_attribute_t *mft_attribute,
1622
     size_t *utf16_string_size,
1623
     libcerror_error_t **error )
1624
0
{
1625
0
  static char *function = "libfsntfs_mft_attribute_get_utf16_name_size";
1626
1627
0
  if( mft_attribute == NULL )
1628
0
  {
1629
0
    libcerror_error_set(
1630
0
     error,
1631
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1632
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1633
0
     "%s: invalid MFT attribute.",
1634
0
     function );
1635
1636
0
    return( -1 );
1637
0
  }
1638
0
  if( ( mft_attribute->name == NULL )
1639
0
   || ( mft_attribute->name_size == 0 ) )
1640
0
  {
1641
0
    if( utf16_string_size == NULL )
1642
0
    {
1643
0
      libcerror_error_set(
1644
0
       error,
1645
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1646
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1647
0
       "%s: invalid UTF-16 string size.",
1648
0
       function );
1649
1650
0
      return( -1 );
1651
0
    }
1652
0
    *utf16_string_size = 0;
1653
0
  }
1654
0
  else
1655
0
  {
1656
0
    if( libuna_utf16_string_size_from_utf16_stream(
1657
0
         mft_attribute->name,
1658
0
         (size_t) mft_attribute->name_size,
1659
0
         LIBUNA_ENDIAN_LITTLE,
1660
0
         utf16_string_size,
1661
0
         error ) != 1 )
1662
0
    {
1663
0
      libcerror_error_set(
1664
0
       error,
1665
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1666
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1667
0
       "%s: unable to retrieve UTF-16 string size.",
1668
0
       function );
1669
1670
0
      return( -1 );
1671
0
    }
1672
0
  }
1673
0
  return( 1 );
1674
0
}
1675
1676
/* Retrieves the UTF-16 encoded name
1677
 * The size should include the end of string character
1678
 * Returns 1 if successful or -1 on error
1679
 */
1680
int libfsntfs_mft_attribute_get_utf16_name(
1681
     libfsntfs_mft_attribute_t *mft_attribute,
1682
     uint16_t *utf16_string,
1683
     size_t utf16_string_size,
1684
     libcerror_error_t **error )
1685
0
{
1686
0
  static char *function = "libfsntfs_mft_attribute_get_utf16_name";
1687
1688
0
  if( mft_attribute == NULL )
1689
0
  {
1690
0
    libcerror_error_set(
1691
0
     error,
1692
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1693
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1694
0
     "%s: invalid MFT attribute.",
1695
0
     function );
1696
1697
0
    return( -1 );
1698
0
  }
1699
0
  if( mft_attribute->name == NULL )
1700
0
  {
1701
0
    libcerror_error_set(
1702
0
     error,
1703
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1704
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1705
0
     "%s: invalid MFT attribute - missing name.",
1706
0
     function );
1707
1708
0
    return( -1 );
1709
0
  }
1710
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1711
0
       utf16_string,
1712
0
       utf16_string_size,
1713
0
       mft_attribute->name,
1714
0
       (size_t) mft_attribute->name_size,
1715
0
       LIBUNA_ENDIAN_LITTLE,
1716
0
       error ) != 1 )
1717
0
  {
1718
0
    libcerror_error_set(
1719
0
     error,
1720
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1721
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1722
0
     "%s: unable to retrieve UTF-16 string.",
1723
0
     function );
1724
1725
0
    return( -1 );
1726
0
  }
1727
0
  return( 1 );
1728
0
}
1729
1730
/* Compares the name with an UTF-8 encoded string
1731
 * Returns 1 if the strings are equal, 0 if not or -1 on error
1732
 */
1733
int libfsntfs_mft_attribute_compare_name_with_utf8_string(
1734
     libfsntfs_mft_attribute_t *mft_attribute,
1735
     const uint8_t *utf8_string,
1736
     size_t utf8_string_length,
1737
     libcerror_error_t **error )
1738
34.1k
{
1739
34.1k
  static char *function = "libfsntfs_mft_attribute_compare_name_with_utf8_string";
1740
34.1k
  int result            = 0;
1741
1742
34.1k
  if( mft_attribute == NULL )
1743
0
  {
1744
0
    libcerror_error_set(
1745
0
     error,
1746
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1747
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1748
0
     "%s: invalid MFT attribute.",
1749
0
     function );
1750
1751
0
    return( -1 );
1752
0
  }
1753
34.1k
  if( mft_attribute->name == NULL )
1754
5.18k
  {
1755
5.18k
    return( 0 );
1756
5.18k
  }
1757
29.0k
  result = libfsntfs_name_compare_with_utf8_string(
1758
29.0k
            mft_attribute->name,
1759
29.0k
            mft_attribute->name_size,
1760
29.0k
            utf8_string,
1761
29.0k
            utf8_string_length,
1762
29.0k
            0,
1763
29.0k
            error );
1764
1765
29.0k
  if( result == -1 )
1766
0
  {
1767
0
    libcerror_error_set(
1768
0
     error,
1769
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
1771
0
     "%s: unable to compare UTF-8 string with name.",
1772
0
     function );
1773
1774
0
    return( -1 );
1775
0
  }
1776
29.0k
  else if( result == LIBUNA_COMPARE_EQUAL )
1777
6.79k
  {
1778
6.79k
    return( 1 );
1779
6.79k
  }
1780
22.2k
  return( 0 );
1781
29.0k
}
1782
1783
/* Compares the name with an UTF-16 encoded string
1784
 * Returns 1 if the strings are equal, 0 if not or -1 on error
1785
 */
1786
int libfsntfs_mft_attribute_compare_name_with_utf16_string(
1787
     libfsntfs_mft_attribute_t *mft_attribute,
1788
     const uint16_t *utf16_string,
1789
     size_t utf16_string_length,
1790
     libcerror_error_t **error )
1791
0
{
1792
0
  static char *function = "libfsntfs_mft_attribute_compare_name_with_utf16_string";
1793
0
  int result            = 0;
1794
1795
0
  if( mft_attribute == NULL )
1796
0
  {
1797
0
    libcerror_error_set(
1798
0
     error,
1799
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1800
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1801
0
     "%s: invalid MFT attribute.",
1802
0
     function );
1803
1804
0
    return( -1 );
1805
0
  }
1806
0
  if( mft_attribute->name == NULL )
1807
0
  {
1808
0
    return( 0 );
1809
0
  }
1810
0
  result = libfsntfs_name_compare_with_utf16_string(
1811
0
            mft_attribute->name,
1812
0
            mft_attribute->name_size,
1813
0
            utf16_string,
1814
0
            utf16_string_length,
1815
0
            0,
1816
0
            error );
1817
1818
0
  if( result == -1 )
1819
0
  {
1820
0
    libcerror_error_set(
1821
0
     error,
1822
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1823
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
1824
0
     "%s: unable to compare UTF-16 string with name.",
1825
0
     function );
1826
1827
0
    return( -1 );
1828
0
  }
1829
0
  else if( result == LIBUNA_COMPARE_EQUAL )
1830
0
  {
1831
0
    return( 1 );
1832
0
  }
1833
0
  return( 0 );
1834
0
}
1835
1836
/* Retrieves the compression unit size
1837
 * Returns 1 if successful or -1 on error
1838
 */
1839
int libfsntfs_mft_attribute_get_compression_unit_size(
1840
     libfsntfs_mft_attribute_t *mft_attribute,
1841
     size_t *compression_unit_size,
1842
     libcerror_error_t **error )
1843
2.15k
{
1844
2.15k
  static char *function = "libfsntfs_mft_attribute_get_compression_unit_size";
1845
1846
2.15k
  if( mft_attribute == NULL )
1847
0
  {
1848
0
    libcerror_error_set(
1849
0
     error,
1850
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1851
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1852
0
     "%s: invalid MFT attribute.",
1853
0
     function );
1854
1855
0
    return( -1 );
1856
0
  }
1857
2.15k
  if( compression_unit_size == NULL )
1858
0
  {
1859
0
    libcerror_error_set(
1860
0
     error,
1861
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1862
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1863
0
     "%s: invalid compression unit size.",
1864
0
     function );
1865
1866
0
    return( -1 );
1867
0
  }
1868
2.15k
  *compression_unit_size = mft_attribute->compression_unit_size;
1869
1870
2.15k
  return( 1 );
1871
2.15k
}
1872
1873
/* Retrieves the resident data
1874
 * Returns 1 if successful or -1 on error
1875
 */
1876
int libfsntfs_mft_attribute_get_resident_data(
1877
     libfsntfs_mft_attribute_t *mft_attribute,
1878
     uint8_t **resident_data,
1879
     size_t *resident_data_size,
1880
     libcerror_error_t **error )
1881
8.29k
{
1882
8.29k
  static char *function = "libfsntfs_mft_attribute_get_resident_data";
1883
1884
8.29k
  if( mft_attribute == NULL )
1885
0
  {
1886
0
    libcerror_error_set(
1887
0
     error,
1888
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1889
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1890
0
     "%s: invalid MFT attribute.",
1891
0
     function );
1892
1893
0
    return( -1 );
1894
0
  }
1895
8.29k
  if( ( mft_attribute->non_resident_flag & 0x01 ) != 0 )
1896
0
  {
1897
0
    libcerror_error_set(
1898
0
     error,
1899
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1900
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1901
0
     "%s: invalid MFT attribute - non-resident flag is set.",
1902
0
     function );
1903
1904
0
    return( -1 );
1905
0
  }
1906
8.29k
  if( mft_attribute->data_size > (uint64_t) SSIZE_MAX )
1907
0
  {
1908
0
    libcerror_error_set(
1909
0
     error,
1910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1911
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1912
0
     "%s: invalid MFT attribute - data size value out of bounds.",
1913
0
     function );
1914
1915
0
    return( -1 );
1916
0
  }
1917
8.29k
  if( resident_data == NULL )
1918
0
  {
1919
0
    libcerror_error_set(
1920
0
     error,
1921
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1922
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1923
0
     "%s: invalid resident data.",
1924
0
     function );
1925
1926
0
    return( -1 );
1927
0
  }
1928
8.29k
  if( resident_data_size == NULL )
1929
0
  {
1930
0
    libcerror_error_set(
1931
0
     error,
1932
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1933
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1934
0
     "%s: invalid resident data size.",
1935
0
     function );
1936
1937
0
    return( -1 );
1938
0
  }
1939
8.29k
  *resident_data      = mft_attribute->data;
1940
8.29k
  *resident_data_size = (size_t) mft_attribute->data_size;
1941
1942
8.29k
  return( 1 );
1943
8.29k
}
1944
1945
/* Retrieves the number of data runs
1946
 * Returns 1 if successful or -1 on error
1947
 */
1948
int libfsntfs_mft_attribute_get_number_of_data_runs(
1949
     libfsntfs_mft_attribute_t *mft_attribute,
1950
     int *number_of_data_runs,
1951
     libcerror_error_t **error )
1952
12.6k
{
1953
12.6k
  static char *function = "libfsntfs_mft_attribute_get_number_of_data_runs";
1954
1955
12.6k
  if( mft_attribute == NULL )
1956
0
  {
1957
0
    libcerror_error_set(
1958
0
     error,
1959
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1960
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1961
0
     "%s: invalid MFT attribute.",
1962
0
     function );
1963
1964
0
    return( -1 );
1965
0
  }
1966
12.6k
  if( mft_attribute->data_runs_array == NULL )
1967
968
  {
1968
968
    if( number_of_data_runs == NULL )
1969
0
    {
1970
0
      libcerror_error_set(
1971
0
       error,
1972
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1973
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1974
0
       "%s: invalid number of data runs.",
1975
0
       function );
1976
1977
0
      return( -1 );
1978
0
    }
1979
968
    *number_of_data_runs = 0;
1980
968
  }
1981
11.7k
  else
1982
11.7k
  {
1983
11.7k
    if( libcdata_array_get_number_of_entries(
1984
11.7k
         mft_attribute->data_runs_array,
1985
11.7k
         number_of_data_runs,
1986
11.7k
         error ) != 1 )
1987
0
    {
1988
0
      libcerror_error_set(
1989
0
       error,
1990
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1991
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1992
0
       "%s: unable to retrieve number of data runs.",
1993
0
       function );
1994
1995
0
      return( -1 );
1996
0
    }
1997
11.7k
  }
1998
12.6k
  return( 1 );
1999
12.6k
}
2000
2001
/* Retrieves a specific data run
2002
 * Returns 1 if successful or -1 on error
2003
 */
2004
int libfsntfs_mft_attribute_get_data_run_by_index(
2005
     libfsntfs_mft_attribute_t *mft_attribute,
2006
     int data_run_index,
2007
     libfsntfs_data_run_t **data_run,
2008
     libcerror_error_t **error )
2009
337k
{
2010
337k
  static char *function = "libfsntfs_mft_attribute_get_data_run_by_index";
2011
2012
337k
  if( mft_attribute == NULL )
2013
0
  {
2014
0
    libcerror_error_set(
2015
0
     error,
2016
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2017
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2018
0
     "%s: invalid MFT attribute.",
2019
0
     function );
2020
2021
0
    return( -1 );
2022
0
  }
2023
337k
  if( libcdata_array_get_entry_by_index(
2024
337k
       mft_attribute->data_runs_array,
2025
337k
       data_run_index,
2026
337k
       (intptr_t **) data_run,
2027
337k
       error ) != 1 )
2028
0
  {
2029
0
    libcerror_error_set(
2030
0
     error,
2031
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2032
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2033
0
     "%s: unable to retrieve data run: %d.",
2034
0
     function,
2035
0
     data_run_index );
2036
2037
0
    return( -1 );
2038
0
  }
2039
337k
  return( 1 );
2040
337k
}
2041
2042
/* Retrieves the data extents array
2043
 * Returns 1 if successful or -1 on error
2044
 */
2045
int libfsntfs_mft_attribute_get_data_extents_array(
2046
     libfsntfs_mft_attribute_t *mft_attribute,
2047
     libfsntfs_io_handle_t *io_handle,
2048
     libcdata_array_t **data_extents_array,
2049
     libcerror_error_t **error )
2050
1.19k
{
2051
1.19k
  libcdata_array_t *safe_data_extents_array    = NULL;
2052
1.19k
  libfsntfs_data_run_t *data_run               = NULL;
2053
1.19k
  libfsntfs_extent_t *data_extent              = NULL;
2054
1.19k
  static char *function                        = "libfsntfs_mft_attribute_get_data_extents_array";
2055
1.19k
  size64_t attribute_data_vcn_size             = 0;
2056
1.19k
  size64_t calculated_allocated_data_size      = 0;
2057
1.19k
  size64_t stored_allocated_data_size          = 0;
2058
1.19k
  off64_t attribute_data_vcn_offset            = 0;
2059
1.19k
  off64_t calculated_attribute_data_vcn_offset = 0;
2060
1.19k
  int attribute_index                          = 0;
2061
1.19k
  int data_run_index                           = 0;
2062
1.19k
  int entry_index                              = 0;
2063
1.19k
  int number_of_data_runs                      = 0;
2064
2065
1.19k
  if( mft_attribute == NULL )
2066
0
  {
2067
0
    libcerror_error_set(
2068
0
     error,
2069
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2070
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2071
0
     "%s: invalid MFT attribute.",
2072
0
     function );
2073
2074
0
    return( -1 );
2075
0
  }
2076
1.19k
  if( io_handle == NULL )
2077
0
  {
2078
0
    libcerror_error_set(
2079
0
     error,
2080
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2081
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2082
0
     "%s: invalid IO handle.",
2083
0
     function );
2084
2085
0
    return( -1 );
2086
0
  }
2087
1.19k
  if( io_handle->cluster_block_size == 0 )
2088
0
  {
2089
0
    libcerror_error_set(
2090
0
     error,
2091
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2092
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2093
0
     "%s: invalid IO handle - cluster block size value out of bounds.",
2094
0
     function );
2095
2096
0
    return( -1 );
2097
0
  }
2098
1.19k
  if( data_extents_array == NULL )
2099
0
  {
2100
0
    libcerror_error_set(
2101
0
     error,
2102
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2103
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2104
0
     "%s: invalid data extents array.",
2105
0
     function );
2106
2107
0
    return( -1 );
2108
0
  }
2109
1.19k
  if( libfsntfs_mft_attribute_get_allocated_data_size(
2110
1.19k
       mft_attribute,
2111
1.19k
       &stored_allocated_data_size,
2112
1.19k
       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 attribute allocated data size.",
2119
0
     function );
2120
2121
0
    goto on_error;
2122
0
  }
2123
1.19k
  if( libcdata_array_initialize(
2124
1.19k
       &safe_data_extents_array,
2125
1.19k
       0,
2126
1.19k
       error ) != 1 )
2127
0
  {
2128
0
    libcerror_error_set(
2129
0
     error,
2130
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2131
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2132
0
     "%s: unable to create extents array.",
2133
0
     function );
2134
2135
0
    goto on_error;
2136
0
  }
2137
2.59k
  while( mft_attribute != NULL )
2138
1.84k
  {
2139
1.84k
    if( mft_attribute->data_runs_array != NULL )
2140
1.34k
    {
2141
1.34k
      attribute_data_vcn_offset = mft_attribute->data_first_vcn;
2142
1.34k
      attribute_data_vcn_size   = mft_attribute->data_last_vcn;
2143
2144
1.34k
      if( attribute_data_vcn_size != 0xffffffffffffffffULL )
2145
996
      {
2146
996
        if( (uint64_t) attribute_data_vcn_offset > (uint64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) )
2147
125
        {
2148
125
          libcerror_error_set(
2149
125
           error,
2150
125
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2151
125
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2152
125
           "%s: invalid attribute data first VCN value out of bounds.",
2153
125
           function );
2154
2155
125
          goto on_error;
2156
125
        }
2157
871
        if( attribute_data_vcn_size > (size64_t) ( ( INT64_MAX / io_handle->cluster_block_size ) - 1 ) )
2158
165
        {
2159
165
          libcerror_error_set(
2160
165
           error,
2161
165
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2162
165
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2163
165
           "%s: invalid attribute data last VCN value out of bounds.",
2164
165
           function );
2165
2166
165
          goto on_error;
2167
165
        }
2168
706
        if( attribute_data_vcn_offset > (off64_t) attribute_data_vcn_size )
2169
17
        {
2170
17
          libcerror_error_set(
2171
17
           error,
2172
17
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2173
17
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2174
17
           "%s: invalid attribute data first VCN value out of bounds.",
2175
17
           function );
2176
2177
17
          goto on_error;
2178
17
        }
2179
689
        attribute_data_vcn_size   += 1;
2180
689
        attribute_data_vcn_size   -= attribute_data_vcn_offset;
2181
689
        attribute_data_vcn_offset *= io_handle->cluster_block_size;
2182
689
        attribute_data_vcn_size   *= io_handle->cluster_block_size;
2183
2184
689
        if( ( calculated_attribute_data_vcn_offset != 0 )
2185
689
         && ( calculated_attribute_data_vcn_offset != attribute_data_vcn_offset ) )
2186
140
        {
2187
140
          libcerror_error_set(
2188
140
           error,
2189
140
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2190
140
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2191
140
           "%s: invalid attribute data VCN offset value out of bounds.",
2192
140
           function );
2193
2194
140
          goto on_error;
2195
140
        }
2196
549
        calculated_attribute_data_vcn_offset = attribute_data_vcn_offset + (off64_t) attribute_data_vcn_size;
2197
549
      }
2198
896
      if( libcdata_array_get_number_of_entries(
2199
896
           mft_attribute->data_runs_array,
2200
896
           &number_of_data_runs,
2201
896
           error ) != 1 )
2202
0
      {
2203
0
        libcerror_error_set(
2204
0
         error,
2205
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2206
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2207
0
         "%s: unable to retrieve attribute: %d number of data runs.",
2208
0
         function,
2209
0
         attribute_index );
2210
2211
0
        goto on_error;
2212
0
      }
2213
896
      for( data_run_index = 0;
2214
6.84k
           data_run_index < number_of_data_runs;
2215
5.94k
           data_run_index++ )
2216
5.94k
      {
2217
5.94k
        if( libcdata_array_get_entry_by_index(
2218
5.94k
             mft_attribute->data_runs_array,
2219
5.94k
             data_run_index,
2220
5.94k
             (intptr_t **) &data_run,
2221
5.94k
             error ) != 1 )
2222
0
        {
2223
0
          libcerror_error_set(
2224
0
           error,
2225
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2226
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2227
0
           "%s: unable to retrieve attribute: %d data run: %d.",
2228
0
           function,
2229
0
           attribute_index,
2230
0
           data_run_index );
2231
2232
0
          goto on_error;
2233
0
        }
2234
5.94k
        if( data_run == NULL )
2235
0
        {
2236
0
          libcerror_error_set(
2237
0
           error,
2238
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2239
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2240
0
           "%s: missing attribute: %d data run: %d.",
2241
0
           function,
2242
0
           attribute_index,
2243
0
           data_run_index );
2244
2245
0
          goto on_error;
2246
0
        }
2247
5.94k
        if( libfsntfs_extent_initialize(
2248
5.94k
             &data_extent,
2249
5.94k
             error ) != 1 )
2250
0
        {
2251
0
          libcerror_error_set(
2252
0
           error,
2253
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2254
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2255
0
           "%s: unable to create data extent: %d.",
2256
0
           function,
2257
0
           data_run_index );
2258
2259
0
          goto on_error;
2260
0
        }
2261
5.94k
        data_extent->start_offset = data_run->start_offset;
2262
5.94k
        data_extent->size         = data_run->size;
2263
5.94k
        data_extent->range_flags  = 0;
2264
2265
5.94k
        if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_SPARSE ) != 0 )
2266
3.55k
        {
2267
3.55k
          data_extent->range_flags |= LIBFSNTFS_EXTENT_FLAG_IS_SPARSE;
2268
3.55k
        }
2269
5.94k
        if( ( data_run->range_flags & LIBFDATA_RANGE_FLAG_IS_COMPRESSED ) != 0 )
2270
0
        {
2271
0
          data_extent->range_flags |= LIBFSNTFS_EXTENT_FLAG_IS_COMPRESSED;
2272
0
        }
2273
5.94k
        if( libcdata_array_append_entry(
2274
5.94k
             safe_data_extents_array,
2275
5.94k
             &entry_index,
2276
5.94k
             (intptr_t *) data_extent,
2277
5.94k
             error ) != 1 )
2278
0
        {
2279
0
          libcerror_error_set(
2280
0
           error,
2281
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
2282
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2283
0
           "%s: unable to append data extent: %d to array.",
2284
0
           function,
2285
0
           data_run_index );
2286
2287
0
          goto on_error;
2288
0
        }
2289
5.94k
        calculated_allocated_data_size += data_run->size;
2290
2291
5.94k
        data_extent = NULL;
2292
5.94k
      }
2293
896
    }
2294
1.39k
    attribute_index++;
2295
2296
1.39k
    if( libfsntfs_mft_attribute_get_next_attribute(
2297
1.39k
         mft_attribute,
2298
1.39k
         &mft_attribute,
2299
1.39k
         error ) != 1 )
2300
0
    {
2301
0
      libcerror_error_set(
2302
0
       error,
2303
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2304
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2305
0
       "%s: unable to retrieve next MFT attribute: %d.",
2306
0
       function,
2307
0
       attribute_index );
2308
2309
0
      goto on_error;
2310
0
    }
2311
1.39k
  }
2312
750
  if( calculated_allocated_data_size != stored_allocated_data_size )
2313
144
  {
2314
144
    libcerror_error_set(
2315
144
     error,
2316
144
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2317
144
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2318
144
     "%s: size of data runs: %" PRIu64 " does not match allocated data size: %" PRIu64 ".",
2319
144
     function,
2320
144
     calculated_allocated_data_size,
2321
144
     stored_allocated_data_size );
2322
2323
144
    goto on_error;
2324
144
  }
2325
606
  *data_extents_array = safe_data_extents_array;
2326
2327
606
  return( 1 );
2328
2329
591
on_error:
2330
591
  if( data_extent != NULL )
2331
0
  {
2332
0
    libfsntfs_extent_free(
2333
0
     &data_extent,
2334
0
     NULL );
2335
0
  }
2336
591
  if( safe_data_extents_array != NULL )
2337
591
  {
2338
591
    libcdata_array_free(
2339
591
     &safe_data_extents_array,
2340
591
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_extent_free,
2341
591
     NULL );
2342
591
  }
2343
591
  return( -1 );
2344
750
}
2345
2346
/* Retrieves the next attribute
2347
 * Returns 1 if successful or -1 on error
2348
 */
2349
int libfsntfs_mft_attribute_get_next_attribute(
2350
     libfsntfs_mft_attribute_t *mft_attribute,
2351
     libfsntfs_mft_attribute_t **next_attribute,
2352
     libcerror_error_t **error )
2353
7.10k
{
2354
7.10k
  static char *function = "libfsntfs_mft_attribute_get_next_attribute";
2355
2356
7.10k
  if( mft_attribute == NULL )
2357
0
  {
2358
0
    libcerror_error_set(
2359
0
     error,
2360
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2361
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2362
0
     "%s: invalid MFT attribute.",
2363
0
     function );
2364
2365
0
    return( -1 );
2366
0
  }
2367
7.10k
  if( next_attribute == NULL )
2368
0
  {
2369
0
    libcerror_error_set(
2370
0
     error,
2371
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2372
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2373
0
     "%s: invalid next attribute.",
2374
0
     function );
2375
2376
0
    return( -1 );
2377
0
  }
2378
7.10k
  *next_attribute = mft_attribute->next_attribute;
2379
2380
7.10k
  return( 1 );
2381
7.10k
}
2382
2383
/* Appends the attribute to the attribute chain
2384
 * Returns 1 if successful or -1 on error
2385
 */
2386
int libfsntfs_mft_attribute_append_to_chain(
2387
     libfsntfs_mft_attribute_t **first_attribute,
2388
     libfsntfs_mft_attribute_t *additional_attribute,
2389
     libcerror_error_t **error )
2390
17.5k
{
2391
17.5k
  libfsntfs_mft_attribute_t *mft_attribute      = NULL;
2392
17.5k
  libfsntfs_mft_attribute_t *previous_attribute = NULL;
2393
17.5k
  static char *function                         = "libfsntfs_mft_attribute_append_to_chain";
2394
2395
17.5k
  if( first_attribute == NULL )
2396
0
  {
2397
0
    libcerror_error_set(
2398
0
     error,
2399
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2400
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2401
0
     "%s: invalid first attribute.",
2402
0
     function );
2403
2404
0
    return( -1 );
2405
0
  }
2406
17.5k
  if( additional_attribute == NULL )
2407
0
  {
2408
0
    libcerror_error_set(
2409
0
     error,
2410
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2411
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2412
0
     "%s: invalid additional attribute.",
2413
0
     function );
2414
2415
0
    return( -1 );
2416
0
  }
2417
17.5k
  mft_attribute = *first_attribute;
2418
2419
17.5k
  if( mft_attribute != NULL )
2420
4.86k
  {
2421
4.86k
    if( mft_attribute->type != additional_attribute->type )
2422
0
    {
2423
0
      libcerror_error_set(
2424
0
       error,
2425
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2426
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2427
0
       "%s: unable to chain attributes of different types.",
2428
0
       function );
2429
2430
0
      return( -1 );
2431
0
    }
2432
4.86k
  }
2433
31.6k
  while( mft_attribute != NULL )
2434
15.9k
  {
2435
15.9k
    if( mft_attribute == additional_attribute )
2436
0
    {
2437
0
      libcerror_error_set(
2438
0
       error,
2439
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2440
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2441
0
       "%s: invalid chained attribute value out of bounds.",
2442
0
       function );
2443
2444
0
      return( -1 );
2445
0
    }
2446
15.9k
    if( mft_attribute->data_first_vcn > additional_attribute->data_first_vcn )
2447
1.82k
    {
2448
1.82k
      break;
2449
1.82k
    }
2450
14.1k
    previous_attribute = mft_attribute;
2451
14.1k
    mft_attribute      = mft_attribute->next_attribute;
2452
14.1k
  }
2453
17.5k
  if( previous_attribute == NULL )
2454
13.4k
  {
2455
13.4k
    additional_attribute->next_attribute = mft_attribute;
2456
2457
13.4k
    *first_attribute = additional_attribute;
2458
13.4k
  }
2459
4.08k
  else
2460
4.08k
  {
2461
4.08k
    if( previous_attribute->next_attribute != NULL )
2462
1.05k
    {
2463
1.05k
      additional_attribute->next_attribute = previous_attribute->next_attribute;
2464
1.05k
    }
2465
4.08k
    previous_attribute->next_attribute = additional_attribute;
2466
4.08k
  }
2467
17.5k
  return( 1 );
2468
17.5k
}
2469