Coverage Report

Created: 2026-10-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libolecf/libolecf/libolecf_directory_tree.c
Line
Count
Source
1
/*
2
 * The directory tree functions
3
 *
4
 * Copyright (C) 2008-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 <types.h>
24
25
#include "libolecf_definitions.h"
26
#include "libolecf_directory_entry.h"
27
#include "libolecf_directory_list.h"
28
#include "libolecf_directory_tree.h"
29
#include "libolecf_libcdata.h"
30
#include "libolecf_libcerror.h"
31
#include "libolecf_libcnotify.h"
32
#include "libolecf_libuna.h"
33
34
#include "olecf_directory.h"
35
36
/* Create the directory tree from the directory entry list
37
 * Returns 1 if successful, 0 if no directory entries or -1 on error
38
 */
39
int libolecf_directory_tree_create(
40
     libcdata_tree_node_t **directory_tree_root_node,
41
     uint32_t *short_sector_stream_start_sector_identifier,
42
     libolecf_directory_entry_t **document_summary_information_directory_entry,
43
     libolecf_directory_entry_t **summary_information_directory_entry,
44
     libcdata_list_t *directory_entry_list,
45
     uint8_t byte_order,
46
     libcerror_error_t **error )
47
817
{
48
817
  libcdata_list_element_t *list_element       = NULL;
49
817
  libolecf_directory_entry_t *directory_entry = NULL;
50
817
  static char *function                       = "libolecf_directory_tree_create";
51
817
  int element_index                           = 0;
52
817
  int number_of_elements                      = 0;
53
54
817
  if( directory_tree_root_node == NULL )
55
0
  {
56
0
    libcerror_error_set(
57
0
     error,
58
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
59
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
60
0
     "%s: invalid directory tree root node.",
61
0
     function );
62
63
0
    return( -1 );
64
0
  }
65
817
  if( *directory_tree_root_node != NULL )
66
0
  {
67
0
    libcerror_error_set(
68
0
     error,
69
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
70
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
71
0
     "%s: directory tree root node already set.",
72
0
     function );
73
74
0
    return( -1 );
75
0
  }
76
817
  if( short_sector_stream_start_sector_identifier == NULL )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
81
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
82
0
     "%s: invalid short sector stream start sector identifier.",
83
0
     function );
84
85
0
    return( -1 );
86
0
  }
87
817
  if( libcdata_list_get_number_of_elements(
88
817
       directory_entry_list,
89
817
       &number_of_elements,
90
817
       error ) != 1 )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
95
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
96
0
     "%s: unable to retrieve number of elements in directory entry list.",
97
0
     function );
98
99
0
    goto on_error;
100
0
  }
101
817
  if( number_of_elements == 0 )
102
55
  {
103
55
    return( 0 );
104
55
  }
105
762
  if( libcdata_list_get_first_element(
106
762
       directory_entry_list,
107
762
       &list_element,
108
762
       error ) != 1 )
109
0
  {
110
0
    libcerror_error_set(
111
0
     error,
112
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
113
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
114
0
     "%s: unable to retrieve first element of directory entry list.",
115
0
     function );
116
117
0
    goto on_error;
118
0
  }
119
762
  for( element_index = 0;
120
7.09k
       element_index < number_of_elements;
121
6.32k
       element_index++ )
122
6.98k
  {
123
6.98k
    if( libcdata_list_element_get_value(
124
6.98k
         list_element,
125
6.98k
         (intptr_t **) &directory_entry,
126
6.98k
         error ) != 1 )
127
0
    {
128
0
      libcerror_error_set(
129
0
       error,
130
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
131
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
132
0
       "%s: unable to retrieve value from element: %d.",
133
0
       function,
134
0
       element_index );
135
136
0
      goto on_error;
137
0
    }
138
6.98k
    if( directory_entry == NULL )
139
0
    {
140
0
      libcerror_error_set(
141
0
       error,
142
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
143
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
144
0
       "%s: missing directory entry: %d.",
145
0
       function,
146
0
       element_index );
147
148
0
      goto on_error;
149
0
    }
150
6.98k
    if( directory_entry->type == LIBOLECF_ITEM_TYPE_ROOT_STORAGE )
151
661
    {
152
661
      break;
153
661
    }
154
6.32k
    if( libcdata_list_element_get_next_element(
155
6.32k
         list_element,
156
6.32k
         &list_element,
157
6.32k
         error ) != 1 )
158
0
    {
159
0
      libcerror_error_set(
160
0
       error,
161
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
162
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
163
0
       "%s: unable to retrieve next element of element: %d.",
164
0
       function,
165
0
       element_index );
166
167
0
      goto on_error;
168
0
    }
169
6.32k
  }
170
762
  if( list_element == NULL )
171
101
  {
172
101
    libcerror_error_set(
173
101
     error,
174
101
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
175
101
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
176
101
     "%s: unable to find root storage directory entry.",
177
101
     function );
178
179
101
    goto on_error;
180
101
  }
181
661
  if( directory_entry == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
187
0
     "%s: missing directory entry: %d.",
188
0
     function,
189
0
     element_index );
190
191
0
    goto on_error;
192
0
  }
193
#if defined( HAVE_VERBOSE_OUTPUT ) || defined( HAVE_DEBUG_OUTPUT )
194
  if( libcnotify_verbose != 0 )
195
  {
196
    if( element_index != 0 )
197
    {
198
      libcnotify_printf(
199
       "%s: root storage is not first directory entry.\n",
200
       function );
201
    }
202
    if( directory_entry->previous_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
203
    {
204
      libcnotify_printf(
205
       "%s: previous directory identifier in root storage is not unused.\n",
206
       function );
207
    }
208
    if( directory_entry->next_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
209
    {
210
      libcnotify_printf(
211
       "%s: next directory identifier in root storage is not unused.\n",
212
       function );
213
    }
214
  }
215
#endif
216
661
  if( directory_entry->sub_directory_identifier == LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
217
27
  {
218
27
    return( 0 );
219
27
  }
220
634
  if( libcdata_tree_node_initialize(
221
634
       directory_tree_root_node,
222
634
       error ) != 1 )
223
0
  {
224
0
    libcerror_error_set(
225
0
     error,
226
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
227
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
228
0
     "%s: unable to create directory root node.",
229
0
     function );
230
231
0
    goto on_error;
232
0
  }
233
634
  if( libcdata_tree_node_set_value(
234
634
       *directory_tree_root_node,
235
634
       (intptr_t *) directory_entry,
236
634
       error ) != 1 )
237
0
  {
238
0
    libcerror_error_set(
239
0
     error,
240
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
241
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
242
0
     "%s: unable to set directory root node value.",
243
0
     function );
244
245
0
    goto on_error;
246
0
  }
247
634
  *short_sector_stream_start_sector_identifier = directory_entry->sector_identifier;
248
249
634
  if( libolecf_directory_tree_create_process_entry(
250
634
       *directory_tree_root_node,
251
634
       directory_entry,
252
634
       document_summary_information_directory_entry,
253
634
       summary_information_directory_entry,
254
634
       directory_entry_list,
255
634
       directory_entry,
256
634
       byte_order,
257
634
       error ) != 1 )
258
565
  {
259
565
    libcerror_error_set(
260
565
     error,
261
565
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
262
565
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
263
565
     "%s: unable to process sub directory entry.",
264
565
     function );
265
266
565
    goto on_error;
267
565
  }
268
69
  directory_entry->set_in_tree = 1;
269
270
69
  return( 1 );
271
272
666
on_error:
273
666
  if( *directory_tree_root_node != NULL )
274
565
  {
275
    /* The directory entry is managed by the list
276
     */
277
565
    libcdata_tree_node_free(
278
565
     directory_tree_root_node,
279
565
     NULL,
280
565
     NULL );
281
565
  }
282
666
  return( -1 );
283
634
}
284
285
/* Process the directory entry and adds it to the directory tree node
286
 * Returns 1 if successful or -1 on error
287
 */
288
int libolecf_directory_tree_create_process_entry(
289
     libcdata_tree_node_t *directory_tree_node,
290
     const libolecf_directory_entry_t *root_directory_entry,
291
     libolecf_directory_entry_t **document_summary_information_directory_entry,
292
     libolecf_directory_entry_t **summary_information_directory_entry,
293
     libcdata_list_t *directory_entry_list,
294
     libolecf_directory_entry_t *directory_entry,
295
     uint8_t byte_order,
296
     libcerror_error_t **error )
297
58.4k
{
298
58.4k
  libcdata_tree_node_t *parent_node               = NULL;
299
58.4k
  libolecf_directory_entry_t *sub_directory_entry = NULL;
300
58.4k
  libcdata_tree_node_t *tree_node                 = NULL;
301
58.4k
  static char *function                           = "libolecf_directory_tree_create_process_entry";
302
58.4k
  int result                                      = 0;
303
304
58.4k
  if( directory_tree_node == NULL )
305
0
  {
306
0
    libcerror_error_set(
307
0
     error,
308
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
309
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
310
0
     "%s: invalid directory tree node.",
311
0
     function );
312
313
0
    return( -1 );
314
0
  }
315
58.4k
  if( root_directory_entry == NULL )
316
0
  {
317
0
    libcerror_error_set(
318
0
     error,
319
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
320
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
321
0
     "%s: invalid root directory entry.",
322
0
     function );
323
324
0
    return( -1 );
325
0
  }
326
58.4k
  if( document_summary_information_directory_entry == NULL )
327
0
  {
328
0
    libcerror_error_set(
329
0
     error,
330
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
331
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
332
0
     "%s: invalid document summary information directory entry.",
333
0
     function );
334
335
0
    return( -1 );
336
0
  }
337
58.4k
  if( summary_information_directory_entry == NULL )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
342
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
343
0
     "%s: invalid summary information directory entry.",
344
0
     function );
345
346
0
    return( -1 );
347
0
  }
348
58.4k
  if( directory_entry->name_size == 28 )
349
309
  {
350
309
    result = libuna_utf8_string_compare_with_utf16_stream(
351
309
              (uint8_t *) "\005DocumentSummaryInformation",
352
309
              28,
353
309
              directory_entry->name,
354
309
              directory_entry->name_size,
355
309
              byte_order,
356
309
              error );
357
358
309
    if( result == -1 )
359
38
    {
360
38
      libcerror_error_set(
361
38
       error,
362
38
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
363
38
       LIBCERROR_RUNTIME_ERROR_GENERIC,
364
38
       "%s: unable to compare directory entry name.",
365
38
       function );
366
367
38
      goto on_error;
368
38
    }
369
271
    else if( result == LIBUNA_COMPARE_EQUAL )
370
0
    {
371
0
      *document_summary_information_directory_entry = directory_entry;
372
0
    }
373
309
  }
374
58.1k
  else if( directory_entry->name_size == 20 )
375
333
  {
376
333
    result = libuna_utf8_string_compare_with_utf16_stream(
377
333
              (uint8_t *) "\005SummaryInformation",
378
333
              20,
379
333
              directory_entry->name,
380
333
              directory_entry->name_size,
381
333
              byte_order,
382
333
              error );
383
384
333
    if( result == -1 )
385
33
    {
386
33
      libcerror_error_set(
387
33
       error,
388
33
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
389
33
       LIBCERROR_RUNTIME_ERROR_GENERIC,
390
33
       "%s: unable to compare directory entry name.",
391
33
       function );
392
393
33
      goto on_error;
394
33
    }
395
300
    else if( result == LIBUNA_COMPARE_EQUAL )
396
0
    {
397
0
      *summary_information_directory_entry = directory_entry;
398
0
    }
399
333
  }
400
  /* Process sub directory identifier
401
   */
402
58.3k
  if( ( directory_entry->sub_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
403
38.2k
   && ( directory_entry->sub_directory_identifier != 0 )
404
37.8k
   && ( root_directory_entry->directory_identifier == 0 ) )
405
37.8k
  {
406
37.8k
    result = libolecf_directory_list_get_element_by_identifier(
407
37.8k
              directory_entry_list,
408
37.8k
              directory_entry->sub_directory_identifier,
409
37.8k
              &sub_directory_entry,
410
37.8k
              error );
411
412
37.8k
    if( result == -1 )
413
0
    {
414
0
      libcerror_error_set(
415
0
       error,
416
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
417
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
418
0
       "%s: unable to retrieve sub directory entry list element: %" PRIu32 ".",
419
0
       function,
420
0
       directory_entry->sub_directory_identifier );
421
422
0
      goto on_error;
423
0
    }
424
37.8k
    else if( result != 0 )
425
1.72k
    {
426
1.72k
      if( sub_directory_entry == NULL )
427
0
      {
428
0
        libcerror_error_set(
429
0
         error,
430
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
431
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
432
0
         "%s: missing sub directory entry: %" PRIu32 ".",
433
0
         function,
434
0
         directory_entry->sub_directory_identifier );
435
436
0
        goto on_error;
437
0
      }
438
1.72k
      if( sub_directory_entry->set_in_tree != 0 )
439
121
      {
440
121
        libcerror_error_set(
441
121
         error,
442
121
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
443
121
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
444
121
         "%s: directory entry tree node already set.",
445
121
         function );
446
447
121
        goto on_error;
448
121
      }
449
1.60k
      if( libcdata_tree_node_initialize(
450
1.60k
           &tree_node,
451
1.60k
           error ) != 1 )
452
0
      {
453
0
        libcerror_error_set(
454
0
         error,
455
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
457
0
         "%s: unable to create directory tree node.",
458
0
         function );
459
460
0
        goto on_error;
461
0
      }
462
1.60k
      if( libcdata_tree_node_set_value(
463
1.60k
           tree_node,
464
1.60k
           (intptr_t *) sub_directory_entry,
465
1.60k
           error ) != 1 )
466
0
      {
467
0
        libcerror_error_set(
468
0
         error,
469
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
470
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
471
0
         "%s: unable to set directory tree node value.",
472
0
         function );
473
474
0
        goto on_error;
475
0
      }
476
1.60k
      if( libcdata_tree_node_insert_node(
477
1.60k
           directory_tree_node,
478
1.60k
           tree_node,
479
1.60k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
480
1.60k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
481
1.60k
           error ) != 1 )
482
0
      {
483
0
        libcerror_error_set(
484
0
         error,
485
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
486
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
487
0
         "%s: unable to insert sub directory tree node.",
488
0
         function );
489
490
0
        goto on_error;
491
0
      }
492
1.60k
      sub_directory_entry->set_in_tree = 1;
493
494
1.60k
      if( libolecf_directory_tree_create_process_entry(
495
1.60k
           tree_node,
496
1.60k
           root_directory_entry,
497
1.60k
           document_summary_information_directory_entry,
498
1.60k
           summary_information_directory_entry,
499
1.60k
           directory_entry_list,
500
1.60k
           sub_directory_entry,
501
1.60k
           byte_order,
502
1.60k
           error ) != 1 )
503
561
      {
504
561
        libcerror_error_set(
505
561
         error,
506
561
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
507
561
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
508
561
         "%s: unable to process sub directory entry.",
509
561
         function );
510
511
561
        tree_node = NULL;
512
513
561
        goto on_error;
514
561
      }
515
1.04k
      tree_node = NULL;
516
1.04k
    }
517
37.8k
  }
518
  /* Process previous directory identifier
519
   */
520
57.7k
  if( directory_entry->previous_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
521
31.4k
  {
522
31.4k
    result = libolecf_directory_list_get_element_by_identifier(
523
31.4k
              directory_entry_list,
524
31.4k
              (int) directory_entry->previous_directory_identifier,
525
31.4k
              &sub_directory_entry,
526
31.4k
              error );
527
528
31.4k
    if( result == -1 )
529
0
    {
530
0
      libcerror_error_set(
531
0
       error,
532
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
534
0
       "%s: unable to retrieve previous directory entry: 0x%08" PRIx32 ".",
535
0
       function,
536
0
       directory_entry->previous_directory_identifier );
537
538
0
      goto on_error;
539
0
    }
540
31.4k
    else if( result != 0 )
541
29.8k
    {
542
29.8k
      if( sub_directory_entry == NULL )
543
0
      {
544
0
        libcerror_error_set(
545
0
         error,
546
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
547
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
548
0
         "%s: missing previous directory entry: %" PRIu32 ".",
549
0
         function,
550
0
         directory_entry->previous_directory_identifier );
551
552
0
        goto on_error;
553
0
      }
554
29.8k
      if( sub_directory_entry->set_in_tree != 0 )
555
20
      {
556
20
        libcerror_error_set(
557
20
         error,
558
20
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
559
20
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
560
20
         "%s: directory entry tree node already set.",
561
20
         function );
562
563
20
        goto on_error;
564
20
      }
565
29.8k
      if( libcdata_tree_node_initialize(
566
29.8k
           &tree_node,
567
29.8k
           error ) != 1 )
568
0
      {
569
0
        libcerror_error_set(
570
0
         error,
571
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
572
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
573
0
         "%s: unable to create directory tree node.",
574
0
         function );
575
576
0
        goto on_error;
577
0
      }
578
29.8k
      if( libcdata_tree_node_set_value(
579
29.8k
           tree_node,
580
29.8k
           (intptr_t *) sub_directory_entry,
581
29.8k
           error ) != 1 )
582
0
      {
583
0
        libcerror_error_set(
584
0
         error,
585
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
586
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
587
0
         "%s: unable to set directory tree node value.",
588
0
         function );
589
590
0
        goto on_error;
591
0
      }
592
29.8k
      if( libcdata_tree_node_get_parent_node(
593
29.8k
           directory_tree_node,
594
29.8k
           &parent_node,
595
29.8k
           error ) != 1 )
596
0
      {
597
0
        libcerror_error_set(
598
0
         error,
599
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
601
0
         "%s: unable to retrieve parent node.",
602
0
         function );
603
604
0
        goto on_error;
605
0
      }
606
29.8k
      if( libcdata_tree_node_insert_node(
607
29.8k
           parent_node,
608
29.8k
           tree_node,
609
29.8k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
610
29.8k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
611
29.8k
           error ) != 1 )
612
9
      {
613
9
        libcerror_error_set(
614
9
         error,
615
9
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
616
9
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
617
9
         "%s: unable to insert previous directory tree node.",
618
9
         function );
619
620
9
        goto on_error;
621
9
      }
622
29.8k
      sub_directory_entry->set_in_tree = 1;
623
624
29.8k
      if( libolecf_directory_tree_create_process_entry(
625
29.8k
           tree_node,
626
29.8k
           root_directory_entry,
627
29.8k
           document_summary_information_directory_entry,
628
29.8k
           summary_information_directory_entry,
629
29.8k
           directory_entry_list,
630
29.8k
           sub_directory_entry,
631
29.8k
           byte_order,
632
29.8k
           error ) != 1 )
633
4.12k
      {
634
4.12k
        libcerror_error_set(
635
4.12k
         error,
636
4.12k
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
637
4.12k
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
638
4.12k
         "%s: unable to process previous directory entry.",
639
4.12k
         function );
640
641
4.12k
        tree_node = NULL;
642
643
4.12k
        goto on_error;
644
4.12k
      }
645
25.7k
      tree_node = NULL;
646
25.7k
    }
647
31.4k
  }
648
  /* Process next directory identifier
649
   */
650
53.5k
  if( directory_entry->next_directory_identifier != LIBOLECF_SECTOR_IDENTIFIER_UNUSED )
651
26.7k
  {
652
26.7k
    result = libolecf_directory_list_get_element_by_identifier(
653
26.7k
              directory_entry_list,
654
26.7k
              (int) directory_entry->next_directory_identifier,
655
26.7k
              &sub_directory_entry,
656
26.7k
              error );
657
658
26.7k
    if( result != 1 )
659
309
    {
660
309
      libcerror_error_set(
661
309
       error,
662
309
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
663
309
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
664
309
       "%s: unable to retrieve next directory entry: 0x%08" PRIx32 ".",
665
309
       function,
666
309
       directory_entry->next_directory_identifier );
667
668
309
      goto on_error;
669
309
    }
670
26.4k
    else if( result != 0 )
671
26.4k
    {
672
26.4k
      if( sub_directory_entry == NULL )
673
0
      {
674
0
        libcerror_error_set(
675
0
         error,
676
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
677
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
678
0
         "%s: missing next directory entry: %" PRIu32 ".",
679
0
         function,
680
0
         directory_entry->sub_directory_identifier );
681
682
0
        goto on_error;
683
0
      }
684
26.4k
      if( sub_directory_entry->set_in_tree != 0 )
685
28
      {
686
28
        libcerror_error_set(
687
28
         error,
688
28
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
689
28
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
690
28
         "%s: directory entry tree node already set.",
691
28
         function );
692
693
28
        goto on_error;
694
28
      }
695
26.4k
      if( libcdata_tree_node_initialize(
696
26.4k
           &tree_node,
697
26.4k
           error ) != 1 )
698
0
      {
699
0
        libcerror_error_set(
700
0
         error,
701
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
703
0
         "%s: unable to create directory tree node.",
704
0
         function );
705
706
0
        goto on_error;
707
0
      }
708
26.4k
      if( libcdata_tree_node_set_value(
709
26.4k
           tree_node,
710
26.4k
           (intptr_t *) sub_directory_entry,
711
26.4k
           error ) != 1 )
712
0
      {
713
0
        libcerror_error_set(
714
0
         error,
715
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
716
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
717
0
         "%s: unable to set directory tree node value.",
718
0
         function );
719
720
0
        goto on_error;
721
0
      }
722
26.4k
      if( libcdata_tree_node_get_parent_node(
723
26.4k
           directory_tree_node,
724
26.4k
           &parent_node,
725
26.4k
           error ) != 1 )
726
0
      {
727
0
        libcerror_error_set(
728
0
         error,
729
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
730
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
731
0
         "%s: unable to retrieve parent node.",
732
0
         function );
733
734
0
        goto on_error;
735
0
      }
736
26.4k
      if( libcdata_tree_node_insert_node(
737
26.4k
           parent_node,
738
26.4k
           tree_node,
739
26.4k
           (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libolecf_directory_entry_compare,
740
26.4k
           LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES,
741
26.4k
           error ) != 1 )
742
7
      {
743
7
        libcerror_error_set(
744
7
         error,
745
7
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
746
7
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
747
7
         "%s: unable to insert next directory tree node.",
748
7
         function );
749
750
7
        goto on_error;
751
7
      }
752
26.3k
      sub_directory_entry->set_in_tree = 1;
753
754
26.3k
      if( libolecf_directory_tree_create_process_entry(
755
26.3k
           tree_node,
756
26.3k
           root_directory_entry,
757
26.3k
           document_summary_information_directory_entry,
758
26.3k
           summary_information_directory_entry,
759
26.3k
           directory_entry_list,
760
26.3k
           sub_directory_entry,
761
26.3k
           byte_order,
762
26.3k
           error ) != 1 )
763
4.01k
      {
764
4.01k
        libcerror_error_set(
765
4.01k
         error,
766
4.01k
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
767
4.01k
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
768
4.01k
         "%s: unable to process next directory entry.",
769
4.01k
         function );
770
771
4.01k
        tree_node = NULL;
772
773
4.01k
        goto on_error;
774
4.01k
      }
775
22.3k
      tree_node = NULL;
776
22.3k
    }
777
26.7k
  }
778
49.2k
  return( 1 );
779
780
9.25k
on_error:
781
9.25k
  if( tree_node != NULL )
782
16
  {
783
16
    libcdata_tree_node_free(
784
16
     &tree_node,
785
16
     NULL,
786
16
     NULL );
787
16
  }
788
9.25k
  return( -1 );
789
53.5k
}
790
791
/* Retrieves the sub node for the specific UTF-8 formatted name
792
 * Returns 1 if successful, 0 if no such sub node or -1 on error
793
 */
794
int libolecf_directory_tree_get_sub_node_by_utf8_name(
795
     libcdata_tree_node_t *directory_tree_node,
796
     const uint8_t *utf8_string,
797
     size_t utf8_string_length,
798
     uint8_t byte_order,
799
     libcdata_tree_node_t **sub_directory_tree_node,
800
     libcerror_error_t **error )
801
0
{
802
0
  libcdata_tree_node_t *safe_sub_directory_tree_node = NULL;
803
0
  libolecf_directory_entry_t *sub_directory_entry    = NULL;
804
0
  static char *function                              = "libolecf_directory_tree_get_sub_node_by_utf8_name";
805
0
  int number_of_sub_nodex                            = 0;
806
0
  int result                                         = 0;
807
0
  int sub_node_index                                 = 0;
808
809
0
  if( directory_tree_node == NULL )
810
0
  {
811
0
    libcerror_error_set(
812
0
     error,
813
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
815
0
     "%s: invalid directory tree node.",
816
0
     function );
817
818
0
    return( -1 );
819
0
  }
820
0
  if( sub_directory_tree_node == NULL )
821
0
  {
822
0
    libcerror_error_set(
823
0
     error,
824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
825
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
826
0
     "%s: invalid sub directory tree node.",
827
0
     function );
828
829
0
    return( -1 );
830
0
  }
831
0
  *sub_directory_tree_node = NULL;
832
833
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
834
0
       directory_tree_node,
835
0
       &number_of_sub_nodex,
836
0
       error ) != 1 )
837
0
  {
838
0
    libcerror_error_set(
839
0
     error,
840
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
841
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
842
0
     "%s: unable to retrieve number of sub nodex.",
843
0
     function );
844
845
0
    return( -1 );
846
0
  }
847
0
  for( sub_node_index = 0;
848
0
       sub_node_index < number_of_sub_nodex;
849
0
       sub_node_index++ )
850
0
        {
851
0
    if( libcdata_tree_node_get_sub_node_by_index(
852
0
         directory_tree_node,
853
0
         sub_node_index,
854
0
         &safe_sub_directory_tree_node,
855
0
         error ) != 1 )
856
0
    {
857
0
      libcerror_error_set(
858
0
       error,
859
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
860
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
861
0
       "%s: unable to retrieve number of sub nodex: %d.",
862
0
       function,
863
0
       sub_node_index );
864
865
0
      return( -1 );
866
0
    }
867
0
    if( libcdata_tree_node_get_value(
868
0
         safe_sub_directory_tree_node,
869
0
         (intptr_t **) &sub_directory_entry,
870
0
         error ) != 1 )
871
0
    {
872
0
      libcerror_error_set(
873
0
       error,
874
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
875
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
876
0
       "%s: unable to retrieve value from sub directory tree node: %d.",
877
0
       function,
878
0
       sub_node_index );
879
880
0
      return( -1 );
881
0
    }
882
0
    if( sub_directory_entry == NULL )
883
0
    {
884
0
      libcerror_error_set(
885
0
       error,
886
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
887
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
888
0
       "%s: missing sub directory entry: %d.",
889
0
       function,
890
0
       sub_node_index );
891
892
0
      return( -1 );
893
0
    }
894
0
    result = libuna_utf8_string_compare_with_utf16_stream(
895
0
              utf8_string,
896
0
              utf8_string_length,
897
0
              sub_directory_entry->name,
898
0
              sub_directory_entry->name_size,
899
0
              byte_order,
900
0
              error );
901
902
0
    if( result == -1 )
903
0
    {
904
0
      libcerror_error_set(
905
0
       error,
906
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
907
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
908
0
       "%s: unable to compare sub directory entry: %d name.",
909
0
       function,
910
0
       sub_node_index );
911
912
0
      return( -1 );
913
0
    }
914
0
    else if( result == LIBUNA_COMPARE_EQUAL )
915
0
    {
916
0
      *sub_directory_tree_node = safe_sub_directory_tree_node;
917
918
0
      return( 1 );
919
0
    }
920
0
  }
921
0
  return( 0 );
922
0
}
923
924
/* Retrieves the sub node for the specific UTF-16 formatted name
925
 * Returns 1 if successful, 0 if no such sub node or -1 on error
926
 */
927
int libolecf_directory_tree_get_sub_node_by_utf16_name(
928
     libcdata_tree_node_t *directory_tree_node,
929
     const uint16_t *utf16_string,
930
     size_t utf16_string_length,
931
     uint8_t byte_order,
932
     libcdata_tree_node_t **sub_directory_tree_node,
933
     libcerror_error_t **error )
934
0
{
935
0
  libcdata_tree_node_t *safe_sub_directory_tree_node = NULL;
936
0
  libolecf_directory_entry_t *sub_directory_entry    = NULL;
937
0
  static char *function                              = "libolecf_directory_tree_get_sub_node_by_utf16_name";
938
0
  int number_of_sub_nodex                            = 0;
939
0
  int result                                         = 0;
940
0
  int sub_node_index                                 = 0;
941
942
0
  if( directory_tree_node == NULL )
943
0
  {
944
0
    libcerror_error_set(
945
0
     error,
946
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
947
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
948
0
     "%s: invalid directory tree node.",
949
0
     function );
950
951
0
    return( -1 );
952
0
  }
953
0
  if( sub_directory_tree_node == NULL )
954
0
  {
955
0
    libcerror_error_set(
956
0
     error,
957
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
958
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
959
0
     "%s: invalid sub directory tree node.",
960
0
     function );
961
962
0
    return( -1 );
963
0
  }
964
0
  *sub_directory_tree_node = NULL;
965
966
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
967
0
       directory_tree_node,
968
0
       &number_of_sub_nodex,
969
0
       error ) != 1 )
970
0
  {
971
0
    libcerror_error_set(
972
0
     error,
973
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
974
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
975
0
     "%s: unable to retrieve number of sub nodex.",
976
0
     function );
977
978
0
    return( -1 );
979
0
  }
980
0
  for( sub_node_index = 0;
981
0
       sub_node_index < number_of_sub_nodex;
982
0
       sub_node_index++ )
983
0
        {
984
0
    if( libcdata_tree_node_get_sub_node_by_index(
985
0
         directory_tree_node,
986
0
         sub_node_index,
987
0
         &safe_sub_directory_tree_node,
988
0
         error ) != 1 )
989
0
    {
990
0
      libcerror_error_set(
991
0
       error,
992
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
993
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
994
0
       "%s: unable to retrieve number of sub nodex: %d.",
995
0
       function,
996
0
       sub_node_index );
997
998
0
      return( -1 );
999
0
    }
1000
0
    if( libcdata_tree_node_get_value(
1001
0
         safe_sub_directory_tree_node,
1002
0
         (intptr_t **) &sub_directory_entry,
1003
0
         error ) != 1 )
1004
0
    {
1005
0
      libcerror_error_set(
1006
0
       error,
1007
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1008
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1009
0
       "%s: unable to retrieve value from sub directory tree node: %d.",
1010
0
       function,
1011
0
       sub_node_index );
1012
1013
0
      return( -1 );
1014
0
    }
1015
0
    if( sub_directory_entry == NULL )
1016
0
    {
1017
0
      libcerror_error_set(
1018
0
       error,
1019
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1020
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1021
0
       "%s: missing sub directory entry: %d.",
1022
0
       function,
1023
0
       sub_node_index );
1024
1025
0
      return( -1 );
1026
0
    }
1027
0
    result = libuna_utf16_string_compare_with_utf16_stream(
1028
0
              utf16_string,
1029
0
              utf16_string_length,
1030
0
              sub_directory_entry->name,
1031
0
              sub_directory_entry->name_size,
1032
0
              byte_order,
1033
0
              error );
1034
1035
0
    if( result == -1 )
1036
0
    {
1037
0
      libcerror_error_set(
1038
0
       error,
1039
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1041
0
       "%s: unable to compare sub directory entry: %d name.",
1042
0
       function,
1043
0
       sub_node_index );
1044
1045
0
      return( -1 );
1046
0
    }
1047
0
    else if( result == LIBUNA_COMPARE_EQUAL )
1048
0
    {
1049
0
      *sub_directory_tree_node = safe_sub_directory_tree_node;
1050
1051
0
      return( 1 );
1052
0
    }
1053
0
  }
1054
0
  return( 0 );
1055
0
}
1056