Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsntfs/libfsntfs/libfsntfs_directory_entries_tree.c
Line
Count
Source
1
/*
2
 * Directory entries tree 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 <memory.h>
24
#include <types.h>
25
26
#include "libfsntfs_definitions.h"
27
#include "libfsntfs_directory_entries_tree.h"
28
#include "libfsntfs_directory_entry.h"
29
#include "libfsntfs_file_name_values.h"
30
#include "libfsntfs_index.h"
31
#include "libfsntfs_index_value.h"
32
#include "libfsntfs_libcdata.h"
33
#include "libfsntfs_libcerror.h"
34
#include "libfsntfs_libcnotify.h"
35
#include "libfsntfs_libfcache.h"
36
#include "libfsntfs_libfdata.h"
37
#include "libfsntfs_mft_attribute.h"
38
#include "libfsntfs_mft_entry.h"
39
#include "libfsntfs_name.h"
40
#include "libfsntfs_standard_information_values.h"
41
#include "libfsntfs_unused.h"
42
43
/* Creates a directory entries tree
44
 * Make sure the value directory_entries_tree is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfsntfs_directory_entries_tree_initialize(
48
     libfsntfs_directory_entries_tree_t **directory_entries_tree,
49
     libcerror_error_t **error )
50
1.59k
{
51
1.59k
  static char *function = "libfsntfs_directory_entries_tree_initialize";
52
53
1.59k
  if( directory_entries_tree == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid directory entries tree.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
1.59k
  if( *directory_entries_tree != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid directory entries tree value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
1.59k
  *directory_entries_tree = memory_allocate_structure(
76
1.59k
                             libfsntfs_directory_entries_tree_t );
77
78
1.59k
  if( *directory_entries_tree == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create directory entries tree.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
1.59k
  if( memory_set(
90
1.59k
       *directory_entries_tree,
91
1.59k
       0,
92
1.59k
       sizeof( libfsntfs_directory_entries_tree_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear directory entries tree.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
1.59k
  return( 1 );
104
105
0
on_error:
106
0
  if( *directory_entries_tree != NULL )
107
0
  {
108
0
    memory_free(
109
0
     *directory_entries_tree );
110
111
0
    *directory_entries_tree = NULL;
112
0
  }
113
0
  return( -1 );
114
1.59k
}
115
116
/* Frees a directory entries tree
117
 * Returns 1 if successful or -1 on error
118
 */
119
int libfsntfs_directory_entries_tree_free(
120
     libfsntfs_directory_entries_tree_t **directory_entries_tree,
121
     libcerror_error_t **error )
122
1.59k
{
123
1.59k
  static char *function = "libfsntfs_directory_entries_tree_free";
124
1.59k
  int result            = 1;
125
126
1.59k
  if( directory_entries_tree == NULL )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
131
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
132
0
     "%s: invalid directory entries tree.",
133
0
     function );
134
135
0
    return( -1 );
136
0
  }
137
1.59k
  if( *directory_entries_tree != NULL )
138
1.59k
  {
139
1.59k
    if( ( *directory_entries_tree )->i30_index != NULL )
140
171
    {
141
171
      if( libfsntfs_index_free(
142
171
           &( ( *directory_entries_tree )->i30_index ),
143
171
           error ) != 1 )
144
0
      {
145
0
        libcerror_error_set(
146
0
         error,
147
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
148
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
149
0
         "%s: unable to free $I30 index.",
150
0
         function );
151
152
0
        result = -1;
153
0
      }
154
171
    }
155
1.59k
    if( ( *directory_entries_tree )->short_names_tree != NULL )
156
168
    {
157
168
      if( libcdata_btree_free(
158
168
           &( ( *directory_entries_tree )->short_names_tree ),
159
168
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free,
160
168
           error ) != 1 )
161
0
      {
162
0
        libcerror_error_set(
163
0
         error,
164
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
165
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
166
0
         "%s: unable to free short names tree.",
167
0
         function );
168
169
0
        result = -1;
170
0
      }
171
168
    }
172
1.59k
    if( ( *directory_entries_tree )->entries_list != NULL )
173
168
    {
174
168
      if( libfdata_list_free(
175
168
           &( ( *directory_entries_tree )->entries_list ),
176
168
           error ) != 1 )
177
0
      {
178
0
        libcerror_error_set(
179
0
         error,
180
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
181
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
182
0
         "%s: unable to free entries list.",
183
0
         function );
184
185
0
        result = -1;
186
0
      }
187
168
    }
188
1.59k
    if( ( *directory_entries_tree )->entries_cache != NULL )
189
168
    {
190
168
      if( libfcache_cache_free(
191
168
           &( ( *directory_entries_tree )->entries_cache ),
192
168
           error ) != 1 )
193
0
      {
194
0
        libcerror_error_set(
195
0
         error,
196
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
197
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
198
0
         "%s: unable to free entries cache.",
199
0
         function );
200
201
0
        result = -1;
202
0
      }
203
168
    }
204
1.59k
    memory_free(
205
1.59k
     *directory_entries_tree );
206
207
1.59k
    *directory_entries_tree = NULL;
208
1.59k
  }
209
1.59k
  return( result );
210
1.59k
}
211
212
/* Inserts an index value into the directory entries tree
213
 * Returns 1 if a directory entry was inserted, 0 if not or -1 on error
214
 */
215
int libfsntfs_directory_entries_tree_insert_index_value(
216
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
217
     int index_value_entry,
218
     libfsntfs_index_value_t *index_value,
219
     uint32_t index_value_flags,
220
     libcerror_error_t **error )
221
3.58k
{
222
3.58k
  libcdata_tree_node_t *upper_node                      = NULL;
223
3.58k
  libfsntfs_directory_entry_t *directory_entry          = NULL;
224
3.58k
  libfsntfs_directory_entry_t *existing_directory_entry = NULL;
225
3.58k
  libfsntfs_file_name_values_t *file_name_values        = NULL;
226
3.58k
  static char *function                                 = "libfsntfs_directory_entries_tree_insert_index_value";
227
3.58k
  uint8_t name_space                                    = 0;
228
3.58k
  int element_file_index                                = 0;
229
3.58k
  int element_index                                     = 0;
230
3.58k
  int result                                            = 0;
231
3.58k
  int value_index                                       = 0;
232
233
3.58k
  if( directory_entries_tree == NULL )
234
0
  {
235
0
    libcerror_error_set(
236
0
     error,
237
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
238
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
239
0
     "%s: invalid directory entries tree.",
240
0
     function );
241
242
0
    return( -1 );
243
0
  }
244
3.58k
  if( index_value == NULL )
245
0
  {
246
0
    libcerror_error_set(
247
0
     error,
248
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
249
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
250
0
     "%s: invalid index value.",
251
0
     function );
252
253
0
    return( -1 );
254
0
  }
255
3.58k
  if( libfsntfs_file_name_values_initialize(
256
3.58k
       &file_name_values,
257
3.58k
       error ) != 1 )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
262
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
263
0
     "%s: unable to create file name values.",
264
0
     function );
265
266
0
    goto on_error;
267
0
  }
268
3.58k
  if( libfsntfs_file_name_values_read_data(
269
3.58k
       file_name_values,
270
3.58k
       index_value->key_data,
271
3.58k
       (size_t) index_value->key_data_size,
272
3.58k
       error ) != 1 )
273
19
  {
274
19
    libcerror_error_set(
275
19
     error,
276
19
     LIBCERROR_ERROR_DOMAIN_IO,
277
19
     LIBCERROR_IO_ERROR_READ_FAILED,
278
19
     "%s: unable to read file name values.",
279
19
     function );
280
281
19
    goto on_error;
282
19
  }
283
3.56k
  if( file_name_values->name == NULL )
284
6
  {
285
6
    libcerror_error_set(
286
6
     error,
287
6
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
288
6
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
289
6
     "%s: invalid file name values - missing name.",
290
6
     function );
291
292
6
    goto on_error;
293
6
  }
294
  /* Ignore the file name with the . as its name
295
   */
296
3.56k
  if( ( file_name_values->name_size == 2 )
297
688
   && ( file_name_values->name[ 0 ] == 0x2e )
298
13
   && ( file_name_values->name[ 1 ] == 0x00 ) )
299
7
  {
300
7
    if( libfsntfs_file_name_values_free(
301
7
         &file_name_values,
302
7
         error ) != 1 )
303
0
    {
304
0
      libcerror_error_set(
305
0
       error,
306
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
307
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
308
0
       "%s: unable to free file name values.",
309
0
       function );
310
311
0
      goto on_error;
312
0
    }
313
7
    return( 0 );
314
7
  }
315
3.55k
  name_space = file_name_values->name_space;
316
317
3.55k
  if( name_space == LIBFSNTFS_FILE_NAME_SPACE_DOS )
318
388
  {
319
388
    if( libfsntfs_directory_entry_initialize(
320
388
         &directory_entry,
321
388
         error ) != 1 )
322
0
    {
323
0
      libcerror_error_set(
324
0
       error,
325
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
326
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
327
0
       "%s: unable to create directory entry.",
328
0
       function );
329
330
0
      goto on_error;
331
0
    }
332
388
    directory_entry->file_reference         = index_value->file_reference;
333
388
    directory_entry->short_file_name_values = file_name_values;
334
335
388
    file_name_values = NULL;
336
337
388
    result = libcdata_btree_insert_value(
338
388
              directory_entries_tree->short_names_tree,
339
388
              &value_index,
340
388
              (intptr_t *) directory_entry,
341
388
              (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference,
342
388
              &upper_node,
343
388
              (intptr_t **) &existing_directory_entry,
344
388
              error ) ;
345
346
388
    if( result == -1 )
347
0
    {
348
0
      libcerror_error_set(
349
0
       error,
350
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
351
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
352
0
       "%s: unable to insert directory entry into tree.",
353
0
       function );
354
355
0
      goto on_error;
356
0
    }
357
388
    else if( result == 0 )
358
9
    {
359
9
      if( existing_directory_entry == NULL )
360
0
      {
361
0
        libcerror_error_set(
362
0
         error,
363
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
364
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
365
0
         "%s: missing existing directory entry.",
366
0
         function );
367
368
0
        goto on_error;
369
0
      }
370
9
      if( name_space == LIBFSNTFS_FILE_NAME_SPACE_DOS )
371
9
      {
372
9
        if( existing_directory_entry->short_file_name_values != NULL )
373
9
        {
374
9
          libcerror_error_set(
375
9
           error,
376
9
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
9
           LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
378
9
           "%s: short file name of existing directory entry already set.",
379
9
           function );
380
381
9
          goto on_error;
382
9
        }
383
0
        existing_directory_entry->short_file_name_values = directory_entry->short_file_name_values;
384
0
        directory_entry->short_file_name_values          = NULL;
385
0
      }
386
0
      else
387
0
      {
388
0
        if( existing_directory_entry->file_name_values != NULL )
389
0
        {
390
0
          libcerror_error_set(
391
0
           error,
392
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
393
0
           LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
394
0
           "%s: file name of existing directory entry already set.",
395
0
           function );
396
397
0
          goto on_error;
398
0
        }
399
0
        existing_directory_entry->file_name_values = directory_entry->file_name_values;
400
0
        directory_entry->file_name_values          = NULL;
401
0
      }
402
0
      if( libfsntfs_directory_entry_free(
403
0
           &directory_entry,
404
0
           error ) != 1 )
405
0
      {
406
0
        libcerror_error_set(
407
0
         error,
408
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
409
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
410
0
         "%s: unable to free directory entry.",
411
0
         function );
412
413
0
        goto on_error;
414
0
      }
415
0
    }
416
388
  }
417
3.54k
  if( name_space != LIBFSNTFS_FILE_NAME_SPACE_DOS )
418
3.16k
  {
419
    /* The element file index value contains the index value entry + 1
420
     */
421
3.16k
    element_file_index = index_value_entry + 1;
422
423
3.16k
    if( libfdata_list_append_element(
424
3.16k
         directory_entries_tree->entries_list,
425
3.16k
         &element_index,
426
3.16k
         element_file_index,
427
3.16k
         index_value->offset,
428
3.16k
         (size64_t) index_value->size,
429
3.16k
         index_value_flags,
430
3.16k
         error ) != 1 )
431
0
    {
432
0
      libcerror_error_set(
433
0
       error,
434
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
436
0
       "%s: unable to append index value to entries list.",
437
0
       function );
438
439
0
      goto on_error;
440
0
    }
441
3.16k
  }
442
3.54k
  if( file_name_values != NULL )
443
3.16k
  {
444
3.16k
    if( libfsntfs_file_name_values_free(
445
3.16k
         &file_name_values,
446
3.16k
         error ) != 1 )
447
0
    {
448
0
      libcerror_error_set(
449
0
       error,
450
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
451
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
452
0
       "%s: unable to free file name values.",
453
0
       function );
454
455
0
      goto on_error;
456
0
    }
457
3.16k
  }
458
3.54k
  return( result );
459
460
34
on_error:
461
34
  if( directory_entry != NULL )
462
9
  {
463
9
    libfsntfs_directory_entry_free(
464
9
     &directory_entry,
465
9
     NULL );
466
9
  }
467
34
  if( file_name_values != NULL )
468
25
  {
469
25
    libfsntfs_file_name_values_free(
470
25
     &file_name_values,
471
25
     NULL );
472
25
  }
473
34
  return( -1 );
474
3.54k
}
475
476
/* Reads the directory entries tree from an index node
477
 * Returns 1 if successful or -1 on error
478
 */
479
int libfsntfs_directory_entries_tree_read_from_index_node(
480
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
481
     libbfio_handle_t *file_io_handle,
482
     libfsntfs_index_node_t *index_node,
483
     int recursion_depth,
484
     libcerror_error_t **error )
485
938
{
486
938
  libfcache_cache_t *sub_node_cache    = NULL;
487
938
  libfsntfs_index_node_t *sub_node     = NULL;
488
938
  libfsntfs_index_value_t *index_value = NULL;
489
938
  static char *function                = "libfsntfs_directory_entries_tree_read_from_index_node";
490
938
  off64_t index_entry_offset           = 0;
491
938
  uint32_t index_value_flags           = 0;
492
938
  int index_value_entry                = 0;
493
938
  int is_allocated                     = 0;
494
938
  int number_of_index_values           = 0;
495
938
  int result                           = 0;
496
497
938
  if( directory_entries_tree == NULL )
498
0
  {
499
0
    libcerror_error_set(
500
0
     error,
501
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
502
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
503
0
     "%s: invalid directory entries tree.",
504
0
     function );
505
506
0
    return( -1 );
507
0
  }
508
938
  if( directory_entries_tree->i30_index == NULL )
509
0
  {
510
0
    libcerror_error_set(
511
0
     error,
512
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
513
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
514
0
     "%s: invalid directory entries tree - missing $I30 index.",
515
0
     function );
516
517
0
    return( -1 );
518
0
  }
519
938
  if( directory_entries_tree->i30_index->io_handle == NULL )
520
0
  {
521
0
    libcerror_error_set(
522
0
     error,
523
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
524
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
525
0
     "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.",
526
0
     function );
527
528
0
    return( -1 );
529
0
  }
530
938
  if( ( recursion_depth < 0 )
531
938
   || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) )
532
2
  {
533
2
    libcerror_error_set(
534
2
     error,
535
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
536
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
537
2
     "%s: invalid recursion depth value out of bounds.",
538
2
     function );
539
540
2
    return( -1 );
541
2
  }
542
936
  if( libfsntfs_index_node_get_number_of_values(
543
936
       index_node,
544
936
       &number_of_index_values,
545
936
       error ) != 1 )
546
0
  {
547
0
    libcerror_error_set(
548
0
     error,
549
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
550
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
551
0
     "%s: unable to retrieve number of values from index node.",
552
0
     function );
553
554
0
    goto on_error;
555
0
  }
556
  /* Use a local cache to prevent cache invalidation of index node
557
   * when reading sub nodes.
558
   */
559
936
  if( libfcache_cache_initialize(
560
936
       &sub_node_cache,
561
936
       1,
562
936
       error ) != 1 )
563
0
  {
564
0
    libcerror_error_set(
565
0
     error,
566
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
567
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
568
0
     "%s: unable to create sub node cache.",
569
0
     function );
570
571
0
    goto on_error;
572
0
  }
573
936
  for( index_value_entry = 0;
574
4.56k
       index_value_entry < number_of_index_values;
575
3.62k
       index_value_entry++ )
576
4.41k
  {
577
4.41k
    if( libfsntfs_index_node_get_value_by_index(
578
4.41k
         index_node,
579
4.41k
         index_value_entry,
580
4.41k
         &index_value,
581
4.41k
         error ) != 1 )
582
0
    {
583
0
      libcerror_error_set(
584
0
       error,
585
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
587
0
       "%s: unable to retrieve value: %d from index node.",
588
0
       function,
589
0
       index_value_entry );
590
591
0
      goto on_error;
592
0
    }
593
#if defined( HAVE_DEBUG_OUTPUT )
594
    if( libcnotify_verbose != 0 )
595
    {
596
      libcnotify_printf(
597
       "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n",
598
       function,
599
       index_value_entry,
600
       index_value->file_reference & 0xffffffffffffUL,
601
       index_value->file_reference >> 48 );
602
603
      libcnotify_printf(
604
       "\n" );
605
    }
606
#endif
607
4.41k
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
608
791
    {
609
791
      if( index_value->sub_node_vcn > (uint64_t) INT_MAX )
610
62
      {
611
62
        libcerror_error_set(
612
62
         error,
613
62
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
614
62
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
615
62
         "%s: node index value: %d sub node VCN value out of bounds.",
616
62
         function,
617
62
         index_value_entry );
618
619
62
        goto on_error;
620
62
      }
621
729
      is_allocated = libfsntfs_index_sub_node_is_allocated(
622
729
                      directory_entries_tree->i30_index,
623
729
                      (int) index_value->sub_node_vcn,
624
729
                      error );
625
626
729
      if( is_allocated == -1 )
627
18
      {
628
18
        libcerror_error_set(
629
18
         error,
630
18
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
631
18
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
632
18
         "%s: unable to determine if sub node with VCN: %d is allocated.",
633
18
         function,
634
18
         (int) index_value->sub_node_vcn );
635
636
18
        goto on_error;
637
18
      }
638
#if defined( HAVE_DEBUG_OUTPUT )
639
      if( libcnotify_verbose != 0 )
640
      {
641
        libcnotify_printf(
642
         "%s: index value: %03d sub node VCN: %" PRIu64 " (%s).\n",
643
         function,
644
         index_value_entry,
645
         index_value->sub_node_vcn,
646
         is_allocated != 0 ? "allocated" : "unallocated" );
647
648
        libcnotify_printf(
649
         "\n" );
650
      }
651
#endif
652
711
      if( is_allocated == 0 )
653
70
      {
654
70
        continue;
655
70
      }
656
641
      index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size );
657
658
641
      if( libfsntfs_index_get_sub_node(
659
641
           directory_entries_tree->i30_index,
660
641
           file_io_handle,
661
641
           sub_node_cache,
662
641
           index_entry_offset,
663
641
           (int) index_value->sub_node_vcn,
664
641
           &sub_node,
665
641
           error ) != 1 )
666
44
      {
667
44
        libcerror_error_set(
668
44
         error,
669
44
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
670
44
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
671
44
         "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
672
44
         function,
673
44
         (int) index_value->sub_node_vcn,
674
44
         index_entry_offset,
675
44
         index_entry_offset );
676
677
44
        goto on_error;
678
44
      }
679
597
      if( libfsntfs_directory_entries_tree_read_from_index_node(
680
597
           directory_entries_tree,
681
597
           file_io_handle,
682
597
           sub_node,
683
597
           recursion_depth + 1,
684
597
           error ) != 1 )
685
562
      {
686
562
        libcerror_error_set(
687
562
         error,
688
562
         LIBCERROR_ERROR_DOMAIN_IO,
689
562
         LIBCERROR_IO_ERROR_READ_FAILED,
690
562
         "%s: unable to read directory entries tree from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
691
562
         function,
692
562
         (int) index_value->sub_node_vcn,
693
562
         index_entry_offset,
694
562
         index_entry_offset );
695
696
562
        goto on_error;
697
562
      }
698
597
    }
699
3.65k
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 )
700
66
    {
701
66
      break;
702
66
    }
703
3.58k
    index_value_flags = 0;
704
705
3.58k
    if( index_node == directory_entries_tree->i30_index->root_node )
706
47
    {
707
47
      index_value_flags = LIBFSNTFS_INDEX_VALUE_LIST_FLAG_STORED_IN_ROOT;
708
47
    }
709
    /* Add the index values containing data in a depth first manner since
710
     * this will preserve the sorted by file name order of the directory entries
711
     */
712
3.58k
    result = libfsntfs_directory_entries_tree_insert_index_value(
713
3.58k
              directory_entries_tree,
714
3.58k
              index_value_entry,
715
3.58k
              index_value,
716
3.58k
              index_value_flags,
717
3.58k
              error );
718
719
3.58k
    if( result == -1 )
720
34
    {
721
34
      libcerror_error_set(
722
34
       error,
723
34
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
724
34
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
725
34
       "%s: unable to insert index value into directory entries tree.",
726
34
       function );
727
728
34
      goto on_error;
729
34
    }
730
3.58k
  }
731
216
  if( libfcache_cache_free(
732
216
       &sub_node_cache,
733
216
       error ) != 1 )
734
0
  {
735
0
    libcerror_error_set(
736
0
     error,
737
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
738
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
739
0
     "%s: unable to free sub node cache.",
740
0
     function );
741
742
0
    goto on_error;
743
0
  }
744
216
  return( 1 );
745
746
720
on_error:
747
720
  if( sub_node_cache != NULL )
748
720
  {
749
720
    libfcache_cache_free(
750
720
     &sub_node_cache,
751
720
     NULL );
752
720
  }
753
720
  return( -1 );
754
216
}
755
756
/* Reads the directory entries tree from the $I30 index
757
 * Returns 1 if successful or -1 on error
758
 */
759
int libfsntfs_directory_entries_tree_read_from_i30_index(
760
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
761
     libfsntfs_io_handle_t *io_handle,
762
     libbfio_handle_t *file_io_handle,
763
     libfsntfs_mft_entry_t *mft_entry,
764
     uint8_t flags,
765
     libcerror_error_t **error )
766
1.59k
{
767
1.59k
  libfsntfs_mft_attribute_t *mft_attribute                             = NULL;
768
1.59k
  libfsntfs_standard_information_values_t *standard_information_values = NULL;
769
1.59k
  static char *function                                                = "libfsntfs_directory_entries_tree_read_from_i30_index";
770
1.59k
  uint32_t attribute_type                                              = 0;
771
1.59k
  uint32_t collation_type                                              = 0;
772
1.59k
  int result                                                           = 0;
773
774
1.59k
  if( directory_entries_tree == NULL )
775
0
  {
776
0
    libcerror_error_set(
777
0
     error,
778
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
779
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
780
0
     "%s: invalid directory entries tree.",
781
0
     function );
782
783
0
    return( -1 );
784
0
  }
785
1.59k
  if( directory_entries_tree->i30_index != NULL )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
790
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
791
0
     "%s: invalid directory entries tree - $I30 index value already set.",
792
0
     function );
793
794
0
    return( -1 );
795
0
  }
796
1.59k
  if( directory_entries_tree->short_names_tree != NULL )
797
0
  {
798
0
    libcerror_error_set(
799
0
     error,
800
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
801
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
802
0
     "%s: invalid directory entries tree - short names tree value already set.",
803
0
     function );
804
805
0
    return( -1 );
806
0
  }
807
1.59k
  if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 )
808
0
  {
809
0
    return( 1 );
810
0
  }
811
1.59k
  if( libfsntfs_index_initialize(
812
1.59k
       &( directory_entries_tree->i30_index ),
813
1.59k
       io_handle,
814
1.59k
       (uint8_t *) "$I30",
815
1.59k
       5,
816
1.59k
       error ) != 1 )
817
0
  {
818
0
    libcerror_error_set(
819
0
     error,
820
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
821
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
822
0
     "%s: unable to create $I30 index.",
823
0
     function );
824
825
0
    goto on_error;
826
0
  }
827
1.59k
  result = libfsntfs_index_read(
828
1.59k
            directory_entries_tree->i30_index,
829
1.59k
            file_io_handle,
830
1.59k
            mft_entry,
831
1.59k
            flags,
832
1.59k
            error );
833
834
1.59k
  if( result == -1 )
835
1.16k
  {
836
1.16k
    libcerror_error_set(
837
1.16k
     error,
838
1.16k
     LIBCERROR_ERROR_DOMAIN_IO,
839
1.16k
     LIBCERROR_IO_ERROR_READ_FAILED,
840
1.16k
     "%s: unable to read $I30 index.",
841
1.16k
     function );
842
843
1.16k
    goto on_error;
844
1.16k
  }
845
432
  else if( result != 0 )
846
429
  {
847
429
    if( libfsntfs_index_get_attribute_type(
848
429
         directory_entries_tree->i30_index,
849
429
         &attribute_type,
850
429
         error ) != 1 )
851
1
    {
852
1
      libcerror_error_set(
853
1
       error,
854
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
855
1
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
856
1
       "%s: unable to retrieve attribute type from index.",
857
1
       function );
858
859
1
      goto on_error;
860
1
    }
861
428
    if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME )
862
41
    {
863
41
      libcerror_error_set(
864
41
       error,
865
41
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
866
41
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
867
41
       "%s: unsupported index attribute type.",
868
41
       function );
869
870
41
      goto on_error;
871
41
    }
872
387
    if( libfsntfs_index_get_collation_type(
873
387
         directory_entries_tree->i30_index,
874
387
         &collation_type,
875
387
         error ) != 1 )
876
0
    {
877
0
      libcerror_error_set(
878
0
       error,
879
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
880
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
881
0
       "%s: unable to retrieve collation type from index.",
882
0
       function );
883
884
0
      goto on_error;
885
0
    }
886
387
    if( collation_type != 1 )
887
46
    {
888
46
      libcerror_error_set(
889
46
       error,
890
46
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
891
46
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
892
46
       "%s: unsupported index collation type.",
893
46
       function );
894
895
46
      goto on_error;
896
46
    }
897
341
    if( libfdata_list_initialize(
898
341
         &( directory_entries_tree->entries_list ),
899
341
         (intptr_t *) directory_entries_tree,
900
341
         NULL,
901
341
         NULL,
902
341
         (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_directory_entries_tree_read_element_data,
903
341
         NULL,
904
341
         LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
905
341
         error ) != 1 )
906
0
    {
907
0
      libcerror_error_set(
908
0
       error,
909
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
910
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
911
0
       "%s: unable to create entries list.",
912
0
       function );
913
914
0
      goto on_error;
915
0
    }
916
341
    if( libfcache_cache_initialize(
917
341
         &( directory_entries_tree->entries_cache ),
918
341
         1,
919
341
         error ) != 1 )
920
0
    {
921
0
      libcerror_error_set(
922
0
       error,
923
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
924
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
925
0
       "%s: unable to create entries cache.",
926
0
       function );
927
928
0
      goto on_error;
929
0
    }
930
341
    if( libcdata_btree_initialize(
931
341
         &( directory_entries_tree->short_names_tree ),
932
341
         LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES,
933
341
         error ) != 1 )
934
0
    {
935
0
      libcerror_error_set(
936
0
       error,
937
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
938
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
939
0
       "%s: unable to create short names B-tree.",
940
0
       function );
941
942
0
      goto on_error;
943
0
    }
944
341
    if( libfsntfs_directory_entries_tree_read_from_index_node(
945
341
         directory_entries_tree,
946
341
         file_io_handle,
947
341
         directory_entries_tree->i30_index->root_node,
948
341
         0,
949
341
         error ) != 1 )
950
160
    {
951
160
      libcerror_error_set(
952
160
       error,
953
160
       LIBCERROR_ERROR_DOMAIN_IO,
954
160
       LIBCERROR_IO_ERROR_READ_FAILED,
955
160
       "%s: unable to read directory entries tree from root node.",
956
160
       function );
957
958
160
      goto on_error;
959
160
    }
960
181
    directory_entries_tree->use_case_folding = 0;
961
962
181
    result = libfsntfs_mft_entry_get_standard_information_attribute(
963
181
              mft_entry,
964
181
              &mft_attribute,
965
181
              error );
966
967
181
    if( result == -1 )
968
0
    {
969
0
      libcerror_error_set(
970
0
       error,
971
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
972
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
973
0
       "%s: unable to retrieve $STANDARD_INFORMATION attribute from MFT entry.",
974
0
       function );
975
976
0
      goto on_error;
977
0
    }
978
181
    else if( result != 0 )
979
111
    {
980
111
      if( libfsntfs_standard_information_values_initialize(
981
111
           &standard_information_values,
982
111
           error ) != 1 )
983
0
      {
984
0
        libcerror_error_set(
985
0
         error,
986
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
987
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
988
0
         "%s: unable to create standard information values.",
989
0
         function );
990
991
0
        goto on_error;
992
0
      }
993
111
      if( libfsntfs_standard_information_values_read_from_mft_attribute(
994
111
           standard_information_values,
995
111
           mft_attribute,
996
111
           error ) != 1 )
997
13
      {
998
13
        libcerror_error_set(
999
13
         error,
1000
13
         LIBCERROR_ERROR_DOMAIN_IO,
1001
13
         LIBCERROR_IO_ERROR_READ_FAILED,
1002
13
         "%s: unable to read standard information values from MFT attribute.",
1003
13
         function );
1004
1005
13
        goto on_error;
1006
13
      }
1007
98
      if( standard_information_values->is_case_sensitive == 0 )
1008
95
      {
1009
95
        directory_entries_tree->use_case_folding = 1;
1010
95
      }
1011
98
      if( libfsntfs_standard_information_values_free(
1012
98
           &standard_information_values,
1013
98
           error ) != 1 )
1014
0
      {
1015
0
        libcerror_error_set(
1016
0
         error,
1017
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1019
0
         "%s: unable to free standard information values.",
1020
0
         function );
1021
1022
0
        goto on_error;
1023
0
      }
1024
98
    }
1025
181
  }
1026
171
  return( 1 );
1027
1028
1.42k
on_error:
1029
1.42k
  if( standard_information_values != NULL )
1030
13
  {
1031
13
    libfsntfs_standard_information_values_free(
1032
13
     &standard_information_values,
1033
13
     NULL );
1034
13
  }
1035
1.42k
  if( directory_entries_tree->short_names_tree != NULL )
1036
173
  {
1037
173
    libcdata_btree_free(
1038
173
     &( directory_entries_tree->short_names_tree ),
1039
173
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free,
1040
173
     NULL );
1041
173
  }
1042
1.42k
  if( directory_entries_tree->entries_cache != NULL )
1043
173
  {
1044
173
    libfcache_cache_free(
1045
173
     &( directory_entries_tree->entries_cache ),
1046
173
     NULL );
1047
173
  }
1048
1.42k
  if( directory_entries_tree->entries_list != NULL )
1049
173
  {
1050
173
    libfdata_list_free(
1051
173
     &( directory_entries_tree->entries_list ),
1052
173
     NULL );
1053
173
  }
1054
1.42k
  if( directory_entries_tree->i30_index != NULL )
1055
1.42k
  {
1056
1.42k
    libfsntfs_index_free(
1057
1.42k
     &( directory_entries_tree->i30_index ),
1058
1.42k
     NULL );
1059
1.42k
  }
1060
1.42k
  return( -1 );
1061
1.59k
}
1062
1063
/* Retrieves the number of entries
1064
 * Returns 1 if successful or -1 on error
1065
 */
1066
int libfsntfs_directory_entries_tree_get_number_of_entries(
1067
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
1068
     int *number_of_entries,
1069
     libcerror_error_t **error )
1070
151
{
1071
151
  static char *function = "libfsntfs_directory_entries_tree_get_number_of_entries";
1072
1073
151
  if( directory_entries_tree == NULL )
1074
0
  {
1075
0
    libcerror_error_set(
1076
0
     error,
1077
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1078
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1079
0
     "%s: invalid directory entries tree.",
1080
0
     function );
1081
1082
0
    return( -1 );
1083
0
  }
1084
151
  if( directory_entries_tree->entries_list == NULL )
1085
2
  {
1086
2
    if( number_of_entries == NULL )
1087
0
    {
1088
0
      libcerror_error_set(
1089
0
       error,
1090
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1091
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1092
0
       "%s: invalid number of entries.",
1093
0
       function );
1094
1095
0
      return( -1 );
1096
0
    }
1097
2
    *number_of_entries = 0;
1098
2
  }
1099
149
  else
1100
149
  {
1101
149
    if( libfdata_list_get_number_of_elements(
1102
149
         directory_entries_tree->entries_list,
1103
149
         number_of_entries,
1104
149
         error ) != 1 )
1105
0
    {
1106
0
      libcerror_error_set(
1107
0
       error,
1108
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1109
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1110
0
       "%s: unable to retrieve number of elements from entries list.",
1111
0
       function );
1112
1113
0
      return( -1 );
1114
0
    }
1115
149
  }
1116
151
  return( 1 );
1117
151
}
1118
1119
/* Retrieves a specific entry
1120
 * This function creates a new directory entry
1121
 * Returns 1 if successful or -1 on error
1122
 */
1123
int libfsntfs_directory_entries_tree_get_entry_by_index(
1124
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
1125
     libbfio_handle_t *file_io_handle,
1126
     int entry_index,
1127
     libfsntfs_directory_entry_t **directory_entry,
1128
     libcerror_error_t **error )
1129
37
{
1130
37
  libfsntfs_directory_entry_t *safe_directory_entry = NULL;
1131
37
  static char *function                             = "libfsntfs_directory_entries_tree_get_entry_by_index";
1132
1133
37
  if( directory_entries_tree == NULL )
1134
0
  {
1135
0
    libcerror_error_set(
1136
0
     error,
1137
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1138
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1139
0
     "%s: invalid directory entries tree.",
1140
0
     function );
1141
1142
0
    return( -1 );
1143
0
  }
1144
37
  if( libfdata_list_get_element_value_by_index(
1145
37
       directory_entries_tree->entries_list,
1146
37
       (intptr_t *) file_io_handle,
1147
37
       (libfdata_cache_t *) directory_entries_tree->entries_cache,
1148
37
       entry_index,
1149
37
       (intptr_t **) &safe_directory_entry,
1150
37
       LIBFDATA_READ_FLAG_IGNORE_CACHE,
1151
37
       error ) != 1 )
1152
0
  {
1153
0
    libcerror_error_set(
1154
0
     error,
1155
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1156
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1157
0
     "%s: unable to retrieve element: %d from entries list.",
1158
0
     function,
1159
0
     entry_index );
1160
1161
0
    return( -1 );
1162
0
  }
1163
37
  if( libfsntfs_directory_entry_clone(
1164
37
       directory_entry,
1165
37
       safe_directory_entry,
1166
37
       error ) != 1 )
1167
0
  {
1168
0
    libcerror_error_set(
1169
0
     error,
1170
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1171
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1172
0
     "%s: unable to create directory entry.",
1173
0
     function );
1174
1175
0
    return( -1 );
1176
0
  }
1177
37
  return( 1 );
1178
37
}
1179
1180
/* Retrieves the directory entry from an index node for an UTF-8 encoded name
1181
 * This function creates a new directory entry
1182
 * Returns 1 if successful, 0 if no such directory entry or -1 on error
1183
 */
1184
int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name(
1185
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
1186
     libbfio_handle_t *file_io_handle,
1187
     libfsntfs_index_node_t *index_node,
1188
     const uint8_t *utf8_string,
1189
     size_t utf8_string_length,
1190
     libfsntfs_directory_entry_t **directory_entry,
1191
     int recursion_depth,
1192
     libcerror_error_t **error )
1193
0
{
1194
0
  libcdata_tree_node_t *upper_node                      = NULL;
1195
0
  libfsntfs_directory_entry_t *existing_directory_entry = NULL;
1196
0
  libfsntfs_directory_entry_t *safe_directory_entry     = NULL;
1197
0
  libfsntfs_file_name_values_t *file_name_values        = NULL;
1198
0
  libfsntfs_index_node_t *sub_node                      = NULL;
1199
0
  libfsntfs_index_value_t *index_value                  = NULL;
1200
0
  static char *function                                 = "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name";
1201
0
  off64_t index_entry_offset                            = 0;
1202
0
  int compare_result                                    = 0;
1203
0
  int index_value_entry                                 = 0;
1204
0
  int is_allocated                                      = 0;
1205
0
  int number_of_index_values                            = 0;
1206
0
  int result                                            = 0;
1207
1208
0
  if( directory_entries_tree == NULL )
1209
0
  {
1210
0
    libcerror_error_set(
1211
0
     error,
1212
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1213
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1214
0
     "%s: invalid directory entries tree.",
1215
0
     function );
1216
1217
0
    return( -1 );
1218
0
  }
1219
0
  if( directory_entries_tree->i30_index == NULL )
1220
0
  {
1221
0
    libcerror_error_set(
1222
0
     error,
1223
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1224
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1225
0
     "%s: invalid directory entries tree - missing $I30 index.",
1226
0
     function );
1227
1228
0
    return( -1 );
1229
0
  }
1230
0
  if( directory_entries_tree->i30_index->io_handle == NULL )
1231
0
  {
1232
0
    libcerror_error_set(
1233
0
     error,
1234
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1235
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1236
0
     "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.",
1237
0
     function );
1238
1239
0
    return( -1 );
1240
0
  }
1241
0
  if( directory_entry == NULL )
1242
0
  {
1243
0
    libcerror_error_set(
1244
0
     error,
1245
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1246
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1247
0
     "%s: invalid directory entry.",
1248
0
     function );
1249
1250
0
    return( -1 );
1251
0
  }
1252
0
  if( ( recursion_depth < 0 )
1253
0
   || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) )
1254
0
  {
1255
0
    libcerror_error_set(
1256
0
     error,
1257
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1258
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1259
0
     "%s: invalid recursion depth value out of bounds.",
1260
0
     function );
1261
1262
0
    return( -1 );
1263
0
  }
1264
0
  if( libfsntfs_index_node_get_number_of_values(
1265
0
       index_node,
1266
0
       &number_of_index_values,
1267
0
       error ) != 1 )
1268
0
  {
1269
0
    libcerror_error_set(
1270
0
     error,
1271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1272
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1273
0
     "%s: unable to retrieve number of values from index node.",
1274
0
     function );
1275
1276
0
    goto on_error;
1277
0
  }
1278
0
  for( index_value_entry = 0;
1279
0
       index_value_entry < number_of_index_values;
1280
0
       index_value_entry++ )
1281
0
  {
1282
0
    if( libfsntfs_index_node_get_value_by_index(
1283
0
         index_node,
1284
0
         index_value_entry,
1285
0
         &index_value,
1286
0
         error ) != 1 )
1287
0
    {
1288
0
      libcerror_error_set(
1289
0
       error,
1290
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292
0
       "%s: unable to retrieve value: %d from index node.",
1293
0
       function,
1294
0
       index_value_entry );
1295
1296
0
      goto on_error;
1297
0
    }
1298
#if defined( HAVE_DEBUG_OUTPUT )
1299
    if( libcnotify_verbose != 0 )
1300
    {
1301
      libcnotify_printf(
1302
       "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n",
1303
       function,
1304
       index_value_entry,
1305
       index_value->file_reference & 0xffffffffffffUL,
1306
       index_value->file_reference >> 48 );
1307
1308
      libcnotify_printf(
1309
       "\n" );
1310
    }
1311
#endif
1312
0
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1313
0
    {
1314
0
      if( index_value->sub_node_vcn > (uint64_t) INT_MAX )
1315
0
      {
1316
0
        libcerror_error_set(
1317
0
         error,
1318
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1319
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1320
0
         "%s: node index value: %d sub node VCN value out of bounds.",
1321
0
         function,
1322
0
         index_value_entry );
1323
1324
0
        goto on_error;
1325
0
      }
1326
0
      is_allocated = libfsntfs_index_sub_node_is_allocated(
1327
0
                      directory_entries_tree->i30_index,
1328
0
                      (int) index_value->sub_node_vcn,
1329
0
                      error );
1330
1331
0
      if( is_allocated == -1 )
1332
0
      {
1333
0
        libcerror_error_set(
1334
0
         error,
1335
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1337
0
         "%s: unable to determine if sub node with VCN: %d is allocated.",
1338
0
         function,
1339
0
         (int) index_value->sub_node_vcn );
1340
1341
0
        goto on_error;
1342
0
      }
1343
0
      else if( is_allocated == 0 )
1344
0
      {
1345
0
        continue;
1346
0
      }
1347
0
    }
1348
0
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 )
1349
0
    {
1350
0
      break;
1351
0
    }
1352
0
    if( libfsntfs_file_name_values_initialize(
1353
0
         &file_name_values,
1354
0
         error ) != 1 )
1355
0
    {
1356
0
      libcerror_error_set(
1357
0
       error,
1358
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1359
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1360
0
       "%s: unable to create file name values.",
1361
0
       function );
1362
1363
0
      goto on_error;
1364
0
    }
1365
0
    if( libfsntfs_file_name_values_read_data(
1366
0
         file_name_values,
1367
0
         index_value->key_data,
1368
0
         (size_t) index_value->key_data_size,
1369
0
         error ) != 1 )
1370
0
    {
1371
0
      libcerror_error_set(
1372
0
       error,
1373
0
       LIBCERROR_ERROR_DOMAIN_IO,
1374
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1375
0
       "%s: unable to read file name values.",
1376
0
       function );
1377
1378
0
      goto on_error;
1379
0
    }
1380
0
    compare_result = libfsntfs_name_compare_with_utf8_string(
1381
0
                      file_name_values->name,
1382
0
                      file_name_values->name_size,
1383
0
                      utf8_string,
1384
0
                      utf8_string_length,
1385
0
                      directory_entries_tree->use_case_folding,
1386
0
                      error );
1387
1388
0
    if( compare_result == -1 )
1389
0
    {
1390
0
      libcerror_error_set(
1391
0
       error,
1392
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1393
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1394
0
       "%s: unable to compare file name values with UTF-8 string.",
1395
0
       function );
1396
1397
0
      goto on_error;
1398
0
    }
1399
0
    if( compare_result != LIBUNA_COMPARE_EQUAL )
1400
0
    {
1401
0
      if( libfsntfs_file_name_values_free(
1402
0
           &file_name_values,
1403
0
           error ) != 1 )
1404
0
      {
1405
0
        libcerror_error_set(
1406
0
         error,
1407
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1408
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1409
0
         "%s: unable to free file name values.",
1410
0
         function );
1411
1412
0
        goto on_error;
1413
0
      }
1414
0
    }
1415
0
    if( compare_result == LIBUNA_COMPARE_LESS )
1416
0
    {
1417
0
      if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1418
0
      {
1419
0
        break;
1420
0
      }
1421
0
    }
1422
0
    else if( compare_result == LIBUNA_COMPARE_EQUAL )
1423
0
    {
1424
0
      break;
1425
0
    }
1426
0
  }
1427
0
  if( compare_result == LIBUNA_COMPARE_EQUAL )
1428
0
  {
1429
0
    if( libfsntfs_directory_entry_initialize(
1430
0
         &safe_directory_entry,
1431
0
         error ) != 1 )
1432
0
    {
1433
0
      libcerror_error_set(
1434
0
       error,
1435
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1436
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1437
0
       "%s: unable to create directory entry.",
1438
0
       function );
1439
1440
0
      goto on_error;
1441
0
    }
1442
0
    safe_directory_entry->file_reference   = index_value->file_reference;
1443
0
    safe_directory_entry->file_name_values = file_name_values;
1444
1445
0
    file_name_values = NULL;
1446
1447
0
    if( safe_directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS )
1448
0
    {
1449
0
      result = libcdata_btree_get_value_by_value(
1450
0
                directory_entries_tree->short_names_tree,
1451
0
                (intptr_t *) directory_entry,
1452
0
                (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference,
1453
0
                &upper_node,
1454
0
                (intptr_t **) &existing_directory_entry,
1455
0
                error );
1456
1457
0
      if( result == -1 )
1458
0
      {
1459
0
        libcerror_error_set(
1460
0
         error,
1461
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1462
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1463
0
         "%s: unable to retrieve directory entry from tree.",
1464
0
         function );
1465
1466
0
        goto on_error;
1467
0
      }
1468
0
      else if( result != 0 )
1469
0
      {
1470
/* TODO add debug compare of long and short names */
1471
0
        if( existing_directory_entry == NULL )
1472
0
        {
1473
0
          libcerror_error_set(
1474
0
           error,
1475
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1476
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1477
0
           "%s: missing existing directory entry.",
1478
0
           function );
1479
1480
0
          goto on_error;
1481
0
        }
1482
0
        if( libfsntfs_file_name_values_clone(
1483
0
             &( safe_directory_entry->short_file_name_values ),
1484
0
             existing_directory_entry->short_file_name_values,
1485
0
             error ) != 1 )
1486
0
        {
1487
0
          libcerror_error_set(
1488
0
           error,
1489
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1490
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1491
0
           "%s: unable to clone short file name values.",
1492
0
           function );
1493
1494
0
          goto on_error;
1495
0
        }
1496
0
      }
1497
0
    }
1498
0
    *directory_entry = safe_directory_entry;
1499
1500
0
    result = 1;
1501
0
  }
1502
0
  else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1503
0
  {
1504
0
    index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size );
1505
1506
0
    if( libfsntfs_index_get_sub_node(
1507
0
         directory_entries_tree->i30_index,
1508
0
         file_io_handle,
1509
0
         directory_entries_tree->i30_index->index_node_cache,
1510
0
         index_entry_offset,
1511
0
         (int) index_value->sub_node_vcn,
1512
0
         &sub_node,
1513
0
         error ) != 1 )
1514
0
    {
1515
0
      libcerror_error_set(
1516
0
       error,
1517
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1518
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1519
0
       "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1520
0
       function,
1521
0
       (int) index_value->sub_node_vcn,
1522
0
       index_entry_offset,
1523
0
       index_entry_offset );
1524
1525
0
      goto on_error;
1526
0
    }
1527
0
    result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name(
1528
0
              directory_entries_tree,
1529
0
              file_io_handle,
1530
0
              sub_node,
1531
0
              utf8_string,
1532
0
              utf8_string_length,
1533
0
              directory_entry,
1534
0
              recursion_depth + 1,
1535
0
              error );
1536
1537
0
    if( result == -1 )
1538
0
    {
1539
0
      libcerror_error_set(
1540
0
       error,
1541
0
       LIBCERROR_ERROR_DOMAIN_IO,
1542
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1543
0
       "%s: unable to retrieve directory entry by UTF-8 string from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1544
0
       function,
1545
0
       (int) index_value->sub_node_vcn,
1546
0
       index_entry_offset,
1547
0
       index_entry_offset );
1548
1549
0
      goto on_error;
1550
0
    }
1551
0
  }
1552
0
  return( result );
1553
1554
0
on_error:
1555
0
  if( safe_directory_entry != NULL )
1556
0
  {
1557
0
    libfsntfs_directory_entry_free(
1558
0
     &safe_directory_entry,
1559
0
     NULL );
1560
0
  }
1561
0
  if( file_name_values != NULL )
1562
0
  {
1563
0
    libfsntfs_file_name_values_free(
1564
0
     &file_name_values,
1565
0
     NULL );
1566
0
  }
1567
0
  return( -1 );
1568
0
}
1569
1570
/* Retrieves the directory entry for an UTF-8 encoded name
1571
 * This function creates a new directory entry
1572
 * Returns 1 if successful, 0 if no such directory entry or -1 on error
1573
 */
1574
int libfsntfs_directory_entries_tree_get_entry_by_utf8_name(
1575
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
1576
     libbfio_handle_t *file_io_handle,
1577
     const uint8_t *utf8_string,
1578
     size_t utf8_string_length,
1579
     libfsntfs_directory_entry_t **directory_entry,
1580
     libcerror_error_t **error )
1581
0
{
1582
0
  static char *function = "libfsntfs_directory_entries_tree_get_entry_by_utf8_name";
1583
0
  int result            = 0;
1584
1585
0
  if( directory_entries_tree == NULL )
1586
0
  {
1587
0
    libcerror_error_set(
1588
0
     error,
1589
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1590
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1591
0
     "%s: invalid directory entries tree.",
1592
0
     function );
1593
1594
0
    return( -1 );
1595
0
  }
1596
0
  if( directory_entries_tree->i30_index == NULL )
1597
0
  {
1598
0
    libcerror_error_set(
1599
0
     error,
1600
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1601
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1602
0
     "%s: invalid directory entries tree - missing $I30 index.",
1603
0
     function );
1604
1605
0
    return( -1 );
1606
0
  }
1607
0
  result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf8_name(
1608
0
            directory_entries_tree,
1609
0
            file_io_handle,
1610
0
            directory_entries_tree->i30_index->root_node,
1611
0
            utf8_string,
1612
0
            utf8_string_length,
1613
0
            directory_entry,
1614
0
            0,
1615
0
            error );
1616
1617
0
  if( result == -1 )
1618
0
  {
1619
0
    libcerror_error_set(
1620
0
     error,
1621
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1622
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1623
0
     "%s: unable to retrieve directory entry by UTF-8 string.",
1624
0
     function );
1625
1626
0
    return( -1 );
1627
0
  }
1628
0
  return( result );
1629
0
}
1630
1631
/* Retrieves the directory entry from an index node for an UTF-16 encoded name
1632
 * This function creates a new directory entry
1633
 * Returns 1 if successful, 0 if no such directory entry or -1 on error
1634
 */
1635
int libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name(
1636
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
1637
     libbfio_handle_t *file_io_handle,
1638
     libfsntfs_index_node_t *index_node,
1639
     const uint16_t *utf16_string,
1640
     size_t utf16_string_length,
1641
     libfsntfs_directory_entry_t **directory_entry,
1642
     int recursion_depth,
1643
     libcerror_error_t **error )
1644
0
{
1645
0
  libcdata_tree_node_t *upper_node                      = NULL;
1646
0
  libfsntfs_directory_entry_t *existing_directory_entry = NULL;
1647
0
  libfsntfs_directory_entry_t *safe_directory_entry     = NULL;
1648
0
  libfsntfs_file_name_values_t *file_name_values        = NULL;
1649
0
  libfsntfs_index_node_t *sub_node                      = NULL;
1650
0
  libfsntfs_index_value_t *index_value                  = NULL;
1651
0
  static char *function                                 = "libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name";
1652
0
  off64_t index_entry_offset                            = 0;
1653
0
  int compare_result                                    = 0;
1654
0
  int index_value_entry                                 = 0;
1655
0
  int is_allocated                                      = 0;
1656
0
  int number_of_index_values                            = 0;
1657
0
  int result                                            = 0;
1658
1659
0
  if( directory_entries_tree == NULL )
1660
0
  {
1661
0
    libcerror_error_set(
1662
0
     error,
1663
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1664
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1665
0
     "%s: invalid directory entries tree.",
1666
0
     function );
1667
1668
0
    return( -1 );
1669
0
  }
1670
0
  if( directory_entries_tree->i30_index == NULL )
1671
0
  {
1672
0
    libcerror_error_set(
1673
0
     error,
1674
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1675
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1676
0
     "%s: invalid directory entries tree - missing $I30 index.",
1677
0
     function );
1678
1679
0
    return( -1 );
1680
0
  }
1681
0
  if( directory_entries_tree->i30_index->io_handle == NULL )
1682
0
  {
1683
0
    libcerror_error_set(
1684
0
     error,
1685
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1686
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1687
0
     "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.",
1688
0
     function );
1689
1690
0
    return( -1 );
1691
0
  }
1692
0
  if( directory_entry == NULL )
1693
0
  {
1694
0
    libcerror_error_set(
1695
0
     error,
1696
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1697
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1698
0
     "%s: invalid directory entry.",
1699
0
     function );
1700
1701
0
    return( -1 );
1702
0
  }
1703
0
  if( ( recursion_depth < 0 )
1704
0
   || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) )
1705
0
  {
1706
0
    libcerror_error_set(
1707
0
     error,
1708
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1709
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1710
0
     "%s: invalid recursion depth value out of bounds.",
1711
0
     function );
1712
1713
0
    return( -1 );
1714
0
  }
1715
0
  if( libfsntfs_index_node_get_number_of_values(
1716
0
       index_node,
1717
0
       &number_of_index_values,
1718
0
       error ) != 1 )
1719
0
  {
1720
0
    libcerror_error_set(
1721
0
     error,
1722
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1723
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1724
0
     "%s: unable to retrieve number of values from index node.",
1725
0
     function );
1726
1727
0
    goto on_error;
1728
0
  }
1729
0
  for( index_value_entry = 0;
1730
0
       index_value_entry < number_of_index_values;
1731
0
       index_value_entry++ )
1732
0
  {
1733
0
    if( libfsntfs_index_node_get_value_by_index(
1734
0
         index_node,
1735
0
         index_value_entry,
1736
0
         &index_value,
1737
0
         error ) != 1 )
1738
0
    {
1739
0
      libcerror_error_set(
1740
0
       error,
1741
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1742
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1743
0
       "%s: unable to retrieve value: %d from index node.",
1744
0
       function,
1745
0
       index_value_entry );
1746
1747
0
      goto on_error;
1748
0
    }
1749
#if defined( HAVE_DEBUG_OUTPUT )
1750
    if( libcnotify_verbose != 0 )
1751
    {
1752
      libcnotify_printf(
1753
       "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n",
1754
       function,
1755
       index_value_entry,
1756
       index_value->file_reference & 0xffffffffffffUL,
1757
       index_value->file_reference >> 48 );
1758
1759
      libcnotify_printf(
1760
       "\n" );
1761
    }
1762
#endif
1763
0
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1764
0
    {
1765
0
      if( index_value->sub_node_vcn > (uint64_t) INT_MAX )
1766
0
      {
1767
0
        libcerror_error_set(
1768
0
         error,
1769
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770
0
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1771
0
         "%s: node index value: %d sub node VCN value out of bounds.",
1772
0
         function,
1773
0
         index_value_entry );
1774
1775
0
        goto on_error;
1776
0
      }
1777
0
      is_allocated = libfsntfs_index_sub_node_is_allocated(
1778
0
                      directory_entries_tree->i30_index,
1779
0
                      (int) index_value->sub_node_vcn,
1780
0
                      error );
1781
1782
0
      if( is_allocated == -1 )
1783
0
      {
1784
0
        libcerror_error_set(
1785
0
         error,
1786
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1787
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1788
0
         "%s: unable to determine if sub node with VCN: %d is allocated.",
1789
0
         function,
1790
0
         (int) index_value->sub_node_vcn );
1791
1792
0
        goto on_error;
1793
0
      }
1794
0
      else if( is_allocated == 0 )
1795
0
      {
1796
0
        continue;
1797
0
      }
1798
0
    }
1799
0
    if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_LAST ) != 0 )
1800
0
    {
1801
0
      break;
1802
0
    }
1803
0
    if( libfsntfs_file_name_values_initialize(
1804
0
         &file_name_values,
1805
0
         error ) != 1 )
1806
0
    {
1807
0
      libcerror_error_set(
1808
0
       error,
1809
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1810
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1811
0
       "%s: unable to create file name values.",
1812
0
       function );
1813
1814
0
      goto on_error;
1815
0
    }
1816
0
    if( libfsntfs_file_name_values_read_data(
1817
0
         file_name_values,
1818
0
         index_value->key_data,
1819
0
         (size_t) index_value->key_data_size,
1820
0
         error ) != 1 )
1821
0
    {
1822
0
      libcerror_error_set(
1823
0
       error,
1824
0
       LIBCERROR_ERROR_DOMAIN_IO,
1825
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1826
0
       "%s: unable to read file name values.",
1827
0
       function );
1828
1829
0
      goto on_error;
1830
0
    }
1831
0
    compare_result = libfsntfs_name_compare_with_utf16_string(
1832
0
                      file_name_values->name,
1833
0
                      file_name_values->name_size,
1834
0
                      utf16_string,
1835
0
                      utf16_string_length,
1836
0
                      directory_entries_tree->use_case_folding,
1837
0
                      error );
1838
1839
0
    if( compare_result == -1 )
1840
0
    {
1841
0
      libcerror_error_set(
1842
0
       error,
1843
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1844
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1845
0
       "%s: unable to compare file name values with UTF-16 string.",
1846
0
       function );
1847
1848
0
      goto on_error;
1849
0
    }
1850
0
    if( compare_result != LIBUNA_COMPARE_EQUAL )
1851
0
    {
1852
0
      if( libfsntfs_file_name_values_free(
1853
0
           &file_name_values,
1854
0
           error ) != 1 )
1855
0
      {
1856
0
        libcerror_error_set(
1857
0
         error,
1858
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1859
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1860
0
         "%s: unable to free file name values.",
1861
0
         function );
1862
1863
0
        goto on_error;
1864
0
      }
1865
0
    }
1866
0
    if( compare_result == LIBUNA_COMPARE_LESS )
1867
0
    {
1868
0
      if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1869
0
      {
1870
0
        break;
1871
0
      }
1872
0
    }
1873
0
    else if( compare_result == LIBUNA_COMPARE_EQUAL )
1874
0
    {
1875
0
      break;
1876
0
    }
1877
0
  }
1878
0
  if( compare_result == LIBUNA_COMPARE_EQUAL )
1879
0
  {
1880
0
    if( libfsntfs_directory_entry_initialize(
1881
0
         &safe_directory_entry,
1882
0
         error ) != 1 )
1883
0
    {
1884
0
      libcerror_error_set(
1885
0
       error,
1886
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1887
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1888
0
       "%s: unable to create directory entry.",
1889
0
       function );
1890
1891
0
      goto on_error;
1892
0
    }
1893
0
    safe_directory_entry->file_reference   = index_value->file_reference;
1894
0
    safe_directory_entry->file_name_values = file_name_values;
1895
1896
0
    file_name_values = NULL;
1897
1898
0
    if( safe_directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS )
1899
0
    {
1900
0
      result = libcdata_btree_get_value_by_value(
1901
0
                directory_entries_tree->short_names_tree,
1902
0
                (intptr_t *) directory_entry,
1903
0
                (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference,
1904
0
                &upper_node,
1905
0
                (intptr_t **) &existing_directory_entry,
1906
0
                error );
1907
1908
0
      if( result == -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 directory entry from tree.",
1915
0
         function );
1916
1917
0
        goto on_error;
1918
0
      }
1919
0
      else if( result != 0 )
1920
0
      {
1921
/* TODO add debug compare of long and short names */
1922
0
        if( existing_directory_entry == NULL )
1923
0
        {
1924
0
          libcerror_error_set(
1925
0
           error,
1926
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1927
0
           LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1928
0
           "%s: missing existing directory entry.",
1929
0
           function );
1930
1931
0
          goto on_error;
1932
0
        }
1933
0
        if( libfsntfs_file_name_values_clone(
1934
0
             &( safe_directory_entry->short_file_name_values ),
1935
0
             existing_directory_entry->short_file_name_values,
1936
0
             error ) != 1 )
1937
0
        {
1938
0
          libcerror_error_set(
1939
0
           error,
1940
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1941
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1942
0
           "%s: unable to clone short file name values.",
1943
0
           function );
1944
1945
0
          goto on_error;
1946
0
        }
1947
0
      }
1948
0
    }
1949
0
    *directory_entry = safe_directory_entry;
1950
1951
0
    result = 1;
1952
0
  }
1953
0
  else if( ( index_value->flags & LIBFSNTFS_INDEX_VALUE_FLAG_IS_BRANCH_NODE ) != 0 )
1954
0
  {
1955
0
    index_entry_offset = (off64_t) ( index_value->sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size );
1956
1957
0
    if( libfsntfs_index_get_sub_node(
1958
0
         directory_entries_tree->i30_index,
1959
0
         file_io_handle,
1960
0
         directory_entries_tree->i30_index->index_node_cache,
1961
0
         index_entry_offset,
1962
0
         (int) index_value->sub_node_vcn,
1963
0
         &sub_node,
1964
0
         error ) != 1 )
1965
0
    {
1966
0
      libcerror_error_set(
1967
0
       error,
1968
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1969
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1970
0
       "%s: unable to retrieve sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1971
0
       function,
1972
0
       (int) index_value->sub_node_vcn,
1973
0
       index_entry_offset,
1974
0
       index_entry_offset );
1975
1976
0
      goto on_error;
1977
0
    }
1978
0
    result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name(
1979
0
              directory_entries_tree,
1980
0
              file_io_handle,
1981
0
              sub_node,
1982
0
              utf16_string,
1983
0
              utf16_string_length,
1984
0
              directory_entry,
1985
0
              recursion_depth + 1,
1986
0
              error );
1987
1988
0
    if( result == -1 )
1989
0
    {
1990
0
      libcerror_error_set(
1991
0
       error,
1992
0
       LIBCERROR_ERROR_DOMAIN_IO,
1993
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1994
0
       "%s: unable to retrieve directory entry by UTF-16 string from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1995
0
       function,
1996
0
       (int) index_value->sub_node_vcn,
1997
0
       index_entry_offset,
1998
0
       index_entry_offset );
1999
2000
0
      goto on_error;
2001
0
    }
2002
0
  }
2003
0
  return( result );
2004
2005
0
on_error:
2006
0
  if( safe_directory_entry != NULL )
2007
0
  {
2008
0
    libfsntfs_directory_entry_free(
2009
0
     &safe_directory_entry,
2010
0
     NULL );
2011
0
  }
2012
0
  if( file_name_values != NULL )
2013
0
  {
2014
0
    libfsntfs_file_name_values_free(
2015
0
     &file_name_values,
2016
0
     NULL );
2017
0
  }
2018
0
  return( -1 );
2019
0
}
2020
2021
/* Retrieves the directory entry for an UTF-16 encoded name
2022
 * This function creates a new directory entry
2023
 * Returns 1 if successful, 0 if no such directory entry or -1 on error
2024
 */
2025
int libfsntfs_directory_entries_tree_get_entry_by_utf16_name(
2026
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
2027
     libbfio_handle_t *file_io_handle,
2028
     const uint16_t *utf16_string,
2029
     size_t utf16_string_length,
2030
     libfsntfs_directory_entry_t **directory_entry,
2031
     libcerror_error_t **error )
2032
0
{
2033
0
  static char *function = "libfsntfs_directory_entries_tree_get_entry_by_utf16_name";
2034
0
  int result            = 0;
2035
2036
0
  if( directory_entries_tree == NULL )
2037
0
  {
2038
0
    libcerror_error_set(
2039
0
     error,
2040
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2041
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2042
0
     "%s: invalid directory entries tree.",
2043
0
     function );
2044
2045
0
    return( -1 );
2046
0
  }
2047
0
  if( directory_entries_tree->i30_index == NULL )
2048
0
  {
2049
0
    libcerror_error_set(
2050
0
     error,
2051
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2052
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2053
0
     "%s: invalid directory entries tree - missing $I30 index.",
2054
0
     function );
2055
2056
0
    return( -1 );
2057
0
  }
2058
0
  result = libfsntfs_directory_entries_tree_get_entry_from_index_node_by_utf16_name(
2059
0
            directory_entries_tree,
2060
0
            file_io_handle,
2061
0
            directory_entries_tree->i30_index->root_node,
2062
0
            utf16_string,
2063
0
            utf16_string_length,
2064
0
            directory_entry,
2065
0
            0,
2066
0
            error );
2067
2068
0
  if( result == -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 directory entry by UTF-16 string.",
2075
0
     function );
2076
2077
0
    return( -1 );
2078
0
  }
2079
0
  return( result );
2080
0
}
2081
2082
/* Reads a directory entry
2083
 * Callback function for the entries list
2084
 * Returns 1 if successful or -1 on error
2085
 */
2086
int libfsntfs_directory_entries_tree_read_element_data(
2087
     libfsntfs_directory_entries_tree_t *directory_entries_tree,
2088
     libbfio_handle_t *file_io_handle,
2089
     libfdata_list_element_t *element,
2090
     libfdata_cache_t *cache,
2091
     int element_file_index,
2092
     off64_t index_value_offset,
2093
     size64_t element_size LIBFSNTFS_ATTRIBUTE_UNUSED,
2094
     uint32_t index_value_flags,
2095
     uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
2096
     libcerror_error_t **error )
2097
37
{
2098
37
  libcdata_tree_node_t *upper_node                      = NULL;
2099
37
  libfsntfs_directory_entry_t *directory_entry          = NULL;
2100
37
  libfsntfs_directory_entry_t *existing_directory_entry = NULL;
2101
37
  libfsntfs_index_node_t *sub_node                      = NULL;
2102
37
  libfsntfs_index_value_t *index_value                  = NULL;
2103
37
  static char *function                                 = "libfsntfs_directory_entries_tree_read_element_data";
2104
37
  off64_t index_entry_offset                            = 0;
2105
37
  off64_t sub_node_vcn                                  = 0;
2106
37
  int index_value_entry                                 = 0;
2107
37
  int is_allocated                                      = 0;
2108
37
  int result                                            = 0;
2109
2110
37
  LIBFSNTFS_UNREFERENCED_PARAMETER( element_size )
2111
37
  LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags )
2112
2113
37
  if( directory_entries_tree == NULL )
2114
0
  {
2115
0
    libcerror_error_set(
2116
0
     error,
2117
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2118
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2119
0
     "%s: invalid directory entries tree.",
2120
0
     function );
2121
2122
0
    return( -1 );
2123
0
  }
2124
37
  if( directory_entries_tree->i30_index == NULL )
2125
0
  {
2126
0
    libcerror_error_set(
2127
0
     error,
2128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2130
0
     "%s: invalid directory entries tree - missing $I30 index.",
2131
0
     function );
2132
2133
0
    return( -1 );
2134
0
  }
2135
37
  if( directory_entries_tree->i30_index->io_handle == NULL )
2136
0
  {
2137
0
    libcerror_error_set(
2138
0
     error,
2139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2141
0
     "%s: invalid directory entries tree - invalid $I30 index - missing IO handle.",
2142
0
     function );
2143
2144
0
    return( -1 );
2145
0
  }
2146
37
  if( libfdata_list_element_get_element_index(
2147
37
       element,
2148
37
       &index_value_entry,
2149
37
       error ) != 1 )
2150
0
  {
2151
0
    libcerror_error_set(
2152
0
     error,
2153
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2154
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2155
0
     "%s: unable to retrieve element index.",
2156
0
     function );
2157
2158
0
    goto on_error;
2159
0
  }
2160
#if defined( HAVE_DEBUG_OUTPUT )
2161
  if( libcnotify_verbose != 0 )
2162
  {
2163
    libcnotify_printf(
2164
     "%s: reading index value: %03d at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
2165
     function,
2166
     index_value_entry,
2167
     index_value_offset,
2168
     index_value_offset );
2169
  }
2170
#endif
2171
  /* The element file index value contains the index value entry + 1
2172
   */
2173
37
  element_file_index -= 1;
2174
2175
37
  if( ( index_value_flags & LIBFSNTFS_INDEX_VALUE_LIST_FLAG_STORED_IN_ROOT ) != 0 )
2176
16
  {
2177
16
    if( libfsntfs_index_node_get_value_by_index(
2178
16
         directory_entries_tree->i30_index->root_node,
2179
16
         element_file_index,
2180
16
         &index_value,
2181
16
         error ) != 1 )
2182
0
    {
2183
0
      libcerror_error_set(
2184
0
       error,
2185
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2186
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2187
0
       "%s: unable to retrieve index value: %d from root node.",
2188
0
       function,
2189
0
       element_file_index );
2190
2191
0
      goto on_error;
2192
0
    }
2193
16
  }
2194
21
  else
2195
21
  {
2196
21
    sub_node_vcn       = index_value_offset / directory_entries_tree->i30_index->io_handle->cluster_block_size;
2197
21
    index_entry_offset = (off64_t) ( sub_node_vcn * directory_entries_tree->i30_index->io_handle->cluster_block_size );
2198
2199
21
    is_allocated = libfsntfs_index_sub_node_is_allocated(
2200
21
                    directory_entries_tree->i30_index,
2201
21
                    (int) sub_node_vcn,
2202
21
                    error );
2203
2204
21
    if( is_allocated == -1 )
2205
0
    {
2206
0
      libcerror_error_set(
2207
0
       error,
2208
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2209
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2210
0
       "%s: unable to determine if sub node with VCN: %d is allocated.",
2211
0
       function,
2212
0
       (int) sub_node_vcn );
2213
2214
0
      goto on_error;
2215
0
    }
2216
21
    else if( is_allocated == 0 )
2217
0
    {
2218
0
      libcerror_error_set(
2219
0
       error,
2220
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2221
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2222
0
       "%s: unsupported unallocated sub node with VCN: %d.",
2223
0
       function,
2224
0
       (int) sub_node_vcn );
2225
2226
0
      goto on_error;
2227
0
    }
2228
21
    if( libfsntfs_index_get_sub_node(
2229
21
         directory_entries_tree->i30_index,
2230
21
         file_io_handle,
2231
21
         directory_entries_tree->i30_index->index_node_cache,
2232
21
         index_entry_offset,
2233
21
         (int) sub_node_vcn,
2234
21
         &sub_node,
2235
21
         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 sub node with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
2242
0
       function,
2243
0
       (int) sub_node_vcn,
2244
0
       index_entry_offset,
2245
0
       index_entry_offset );
2246
2247
0
      goto on_error;
2248
0
    }
2249
21
    if( libfsntfs_index_node_get_value_by_index(
2250
21
         sub_node,
2251
21
         element_file_index,
2252
21
         &index_value,
2253
21
         error ) != 1 )
2254
0
    {
2255
0
      libcerror_error_set(
2256
0
       error,
2257
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2258
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2259
0
       "%s: unable to retrieve index value: %d from sub node.",
2260
0
       function,
2261
0
       element_file_index );
2262
2263
0
      goto on_error;
2264
0
    }
2265
21
  }
2266
37
  if( libfsntfs_directory_entry_initialize(
2267
37
       &directory_entry,
2268
37
       error ) != 1 )
2269
0
  {
2270
0
    libcerror_error_set(
2271
0
     error,
2272
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2273
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2274
0
     "%s: unable to create directory entry.",
2275
0
     function );
2276
2277
0
    goto on_error;
2278
0
  }
2279
37
  if( libfsntfs_file_name_values_initialize(
2280
37
       &( directory_entry->file_name_values ),
2281
37
       error ) != 1 )
2282
0
  {
2283
0
    libcerror_error_set(
2284
0
     error,
2285
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2286
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2287
0
     "%s: unable to create file name values.",
2288
0
     function );
2289
2290
0
    goto on_error;
2291
0
  }
2292
#if defined( HAVE_DEBUG_OUTPUT )
2293
  if( libcnotify_verbose != 0 )
2294
  {
2295
    libcnotify_printf(
2296
     "%s: index value: %03d file reference: %" PRIu64 "-%" PRIu64 "\n",
2297
     function,
2298
     index_value_entry,
2299
     index_value->file_reference & 0xffffffffffffUL,
2300
     index_value->file_reference >> 48 );
2301
2302
    libcnotify_printf(
2303
     "\n" );
2304
  }
2305
#endif
2306
37
  directory_entry->file_reference = index_value->file_reference;
2307
2308
37
  if( libfsntfs_file_name_values_read_data(
2309
37
       directory_entry->file_name_values,
2310
37
       index_value->key_data,
2311
37
       (size_t) index_value->key_data_size,
2312
37
       error ) != 1 )
2313
0
  {
2314
0
    libcerror_error_set(
2315
0
     error,
2316
0
     LIBCERROR_ERROR_DOMAIN_IO,
2317
0
     LIBCERROR_IO_ERROR_READ_FAILED,
2318
0
     "%s: unable to read file name values.",
2319
0
     function );
2320
2321
0
    goto on_error;
2322
0
  }
2323
37
  if( directory_entry->file_name_values->name_space == LIBFSNTFS_FILE_NAME_SPACE_WINDOWS )
2324
9
  {
2325
9
    result = libcdata_btree_get_value_by_value(
2326
9
              directory_entries_tree->short_names_tree,
2327
9
              (intptr_t *) directory_entry,
2328
9
              (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_directory_entry_compare_by_file_reference,
2329
9
              &upper_node,
2330
9
              (intptr_t **) &existing_directory_entry,
2331
9
              error ) ;
2332
2333
9
    if( result == -1 )
2334
0
    {
2335
0
      libcerror_error_set(
2336
0
       error,
2337
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2338
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2339
0
       "%s: unable to retrieve directory entry from tree.",
2340
0
       function );
2341
2342
0
      goto on_error;
2343
0
    }
2344
9
    else if( result != 0 )
2345
1
    {
2346
/* TODO add debug compare of long and short names */
2347
1
      if( existing_directory_entry == NULL )
2348
0
      {
2349
0
        libcerror_error_set(
2350
0
         error,
2351
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2352
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2353
0
         "%s: missing existing directory entry.",
2354
0
         function );
2355
2356
0
        goto on_error;
2357
0
      }
2358
1
      if( libfsntfs_file_name_values_clone(
2359
1
           &( directory_entry->short_file_name_values ),
2360
1
           existing_directory_entry->short_file_name_values,
2361
1
           error ) != 1 )
2362
0
      {
2363
0
        libcerror_error_set(
2364
0
         error,
2365
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2366
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2367
0
         "%s: unable to clone short file name values.",
2368
0
         function );
2369
2370
0
        goto on_error;
2371
0
      }
2372
1
    }
2373
9
  }
2374
37
  if( libfdata_list_element_set_element_value(
2375
37
       element,
2376
37
       (intptr_t *) file_io_handle,
2377
37
       cache,
2378
37
       (intptr_t *) directory_entry,
2379
37
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_directory_entry_free,
2380
37
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
2381
37
       error ) != 1 )
2382
0
  {
2383
0
    libcerror_error_set(
2384
0
     error,
2385
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2386
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2387
0
     "%s: unable to set index value as element value.",
2388
0
     function );
2389
2390
0
    goto on_error;
2391
0
  }
2392
37
  return( 1 );
2393
2394
0
on_error:
2395
0
  if( directory_entry != NULL )
2396
0
  {
2397
0
    libfsntfs_directory_entry_free(
2398
0
     &directory_entry,
2399
     NULL );
2400
0
  }
2401
0
  return( -1 );
2402
37
}
2403