Coverage Report

Created: 2024-02-25 07:20

/src/libewf/libcdata/libcdata_tree_node.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Tree functions
3
 *
4
 * Copyright (C) 2006-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libcdata_definitions.h"
27
#include "libcdata_libcerror.h"
28
#include "libcdata_libcthreads.h"
29
#include "libcdata_list.h"
30
#include "libcdata_tree_node.h"
31
#include "libcdata_types.h"
32
33
/* Creates a tree node
34
 * Make sure the value node is referencing, is set to NULL
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libcdata_tree_node_initialize(
38
     libcdata_tree_node_t **node,
39
     libcerror_error_t **error )
40
1.44M
{
41
1.44M
  libcdata_internal_tree_node_t *internal_node = NULL;
42
1.44M
  static char *function                        = "libcdata_tree_node_initialize";
43
44
1.44M
  if( node == NULL )
45
0
  {
46
0
    libcerror_error_set(
47
0
     error,
48
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50
0
     "%s: invalid node.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
1.44M
  if( *node != NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61
0
     "%s: invalid node value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
1.44M
  internal_node = memory_allocate_structure(
67
1.44M
                   libcdata_internal_tree_node_t );
68
69
1.44M
  if( internal_node == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
74
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
75
0
     "%s: unable to create node.",
76
0
     function );
77
78
0
    goto on_error;
79
0
  }
80
1.44M
  if( memory_set(
81
1.44M
       internal_node,
82
1.44M
       0,
83
1.44M
       sizeof( libcdata_internal_tree_node_t ) ) == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
88
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
89
0
     "%s: unable to clear node.",
90
0
     function );
91
92
0
    memory_free(
93
0
     internal_node );
94
95
0
    return( -1 );
96
0
  }
97
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
98
  if( libcthreads_read_write_lock_initialize(
99
       &( internal_node->read_write_lock ),
100
       error ) != 1 )
101
  {
102
    libcerror_error_set(
103
     error,
104
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
105
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
106
     "%s: unable to initialize read/write lock.",
107
     function );
108
109
    goto on_error;
110
  }
111
#endif
112
1.44M
  *node = (libcdata_tree_node_t *) internal_node;
113
114
1.44M
  return( 1 );
115
116
0
on_error:
117
0
  if( internal_node != NULL )
118
0
  {
119
0
    memory_free(
120
0
     internal_node );
121
0
  }
122
0
  return( -1 );
123
1.44M
}
124
125
/* Frees a tree node, its sub nodes
126
 * Uses the value_free_function to free the value
127
 * Returns 1 if successful or -1 on error
128
 */
129
int libcdata_tree_node_free(
130
     libcdata_tree_node_t **node,
131
     int (*value_free_function)(
132
            intptr_t **value,
133
            libcerror_error_t **error ),
134
     libcerror_error_t **error )
135
1.44M
{
136
1.44M
  libcdata_internal_tree_node_t *internal_node = NULL;
137
1.44M
  static char *function                        = "libcdata_tree_node_free";
138
1.44M
  int result                                   = 1;
139
140
1.44M
  if( node == NULL )
141
0
  {
142
0
    libcerror_error_set(
143
0
     error,
144
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
145
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
146
0
     "%s: invalid node.",
147
0
     function );
148
149
0
    return( -1 );
150
0
  }
151
1.44M
  if( *node != NULL )
152
1.44M
  {
153
1.44M
    internal_node = (libcdata_internal_tree_node_t *) *node;
154
155
1.44M
    if( ( internal_node->parent_node != NULL )
156
1.44M
     || ( internal_node->previous_node != NULL )
157
1.44M
     || ( internal_node->next_node != NULL ) )
158
2.28k
    {
159
2.28k
      libcerror_error_set(
160
2.28k
       error,
161
2.28k
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
162
2.28k
       LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
163
2.28k
       "%s: invalid node - connected to other nodes.",
164
2.28k
       function );
165
166
2.28k
      return( -1 );
167
2.28k
    }
168
1.44M
    *node = NULL;
169
170
1.44M
    if( libcdata_tree_node_empty(
171
1.44M
         (libcdata_tree_node_t *) internal_node,
172
1.44M
         value_free_function,
173
1.44M
         error ) != 1 )
174
0
    {
175
0
      libcerror_error_set(
176
0
       error,
177
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
178
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
179
0
       "%s: unable to empty node.",
180
0
       function );
181
182
0
      result = -1;
183
0
    }
184
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
185
    if( libcthreads_read_write_lock_free(
186
         &( internal_node->read_write_lock ),
187
         error ) != 1 )
188
    {
189
      libcerror_error_set(
190
       error,
191
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
192
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
193
       "%s: unable to free read/write lock.",
194
       function );
195
196
      result = -1;
197
    }
198
#endif
199
1.44M
    if( internal_node->value != NULL )
200
1.41M
    {
201
1.41M
      if( value_free_function != NULL )
202
1.01M
      {
203
1.01M
        if( value_free_function(
204
1.01M
             &( internal_node->value ),
205
1.01M
             error ) != 1 )
206
0
        {
207
0
          libcerror_error_set(
208
0
           error,
209
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
211
0
           "%s: unable to free value.",
212
0
          function );
213
214
0
          result = -1;
215
0
        }
216
1.01M
        internal_node->value = NULL;
217
1.01M
      }
218
1.41M
    }
219
1.44M
    memory_free(
220
1.44M
     internal_node );
221
1.44M
  }
222
1.44M
  return( result );
223
1.44M
}
224
225
/* Empties a tree node and frees its sub nodes
226
 * Uses the value_free_function to free the value of the sub nodes
227
 * Returns 1 if successful or -1 on error
228
 */
229
int libcdata_tree_node_empty(
230
     libcdata_tree_node_t *tree_node,
231
     int (*value_free_function)(
232
            intptr_t **value,
233
            libcerror_error_t **error ),
234
     libcerror_error_t **error )
235
1.44M
{
236
1.44M
  libcdata_internal_tree_node_t *internal_node = NULL;
237
1.44M
  libcdata_tree_node_t *next_node              = NULL;
238
1.44M
  libcdata_tree_node_t *parent_node            = NULL;
239
1.44M
  libcdata_tree_node_t *previous_node          = NULL;
240
1.44M
  libcdata_tree_node_t *sub_node               = NULL;
241
1.44M
  static char *function                        = "libcdata_tree_node_empty";
242
1.44M
  int number_of_sub_nodes                      = 0;
243
1.44M
  int result                                   = 1;
244
1.44M
  int sub_node_index                           = 0;
245
246
1.44M
  if( tree_node == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252
0
     "%s: invalid tree node.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
1.44M
  internal_node = (libcdata_internal_tree_node_t *) tree_node;
258
259
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
260
  if( libcthreads_read_write_lock_grab_for_write(
261
       internal_node->read_write_lock,
262
       error ) != 1 )
263
  {
264
    libcerror_error_set(
265
     error,
266
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
267
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
268
     "%s: unable to grab read/write lock for writing.",
269
     function );
270
271
    return( -1 );
272
  }
273
#endif
274
1.44M
  number_of_sub_nodes = internal_node->number_of_sub_nodes;
275
276
1.44M
  sub_node = internal_node->first_sub_node;
277
278
1.44M
  for( sub_node_index = 0;
279
1.57M
       sub_node_index < number_of_sub_nodes;
280
1.44M
       sub_node_index++ )
281
124k
  {
282
124k
    if( libcdata_tree_node_get_nodes(
283
124k
         sub_node,
284
124k
         &parent_node,
285
124k
         &previous_node,
286
124k
         &next_node,
287
124k
         error ) != 1 )
288
0
    {
289
0
      libcerror_error_set(
290
0
       error,
291
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
292
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
293
0
       "%s: unable to retrieve nodes of sub node: %d.",
294
0
       function,
295
0
       sub_node_index );
296
297
0
      goto on_error;
298
0
    }
299
124k
    if( previous_node != NULL )
300
0
    {
301
0
      libcerror_error_set(
302
0
       error,
303
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
304
0
       LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
305
0
       "%s: invalid sub node: %d - previous node is set.",
306
0
       function,
307
0
       sub_node_index );
308
309
0
      goto on_error;
310
0
    }
311
124k
    internal_node->first_sub_node = next_node;
312
313
124k
    if( internal_node->last_sub_node == sub_node )
314
15.0k
    {
315
15.0k
      internal_node->last_sub_node = next_node;
316
15.0k
    }
317
124k
    internal_node->number_of_sub_nodes -= 1;
318
319
124k
    if( next_node != NULL )
320
109k
    {
321
109k
      if( libcdata_tree_node_set_previous_node(
322
109k
           next_node,
323
109k
           NULL,
324
109k
           error ) != 1 )
325
0
      {
326
0
        libcerror_error_set(
327
0
         error,
328
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
329
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
330
0
         "%s: unable to set previous node of sub node: %d.",
331
0
         function,
332
0
         sub_node_index + 1 );
333
334
0
        goto on_error;
335
0
      }
336
109k
    }
337
124k
    if( libcdata_tree_node_set_nodes(
338
124k
         sub_node,
339
124k
         NULL,
340
124k
         NULL,
341
124k
         NULL,
342
124k
         error ) != 1 )
343
0
    {
344
0
      libcerror_error_set(
345
0
       error,
346
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
347
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
348
0
       "%s: unable to set nodes of sub node: %d.",
349
0
       function,
350
0
       sub_node_index );
351
352
0
      goto on_error;
353
0
    }
354
124k
    if( libcdata_tree_node_free(
355
124k
         &sub_node,
356
124k
         value_free_function,
357
124k
         error ) != 1 )
358
0
    {
359
0
      libcerror_error_set(
360
0
       error,
361
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
362
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
363
0
       "%s: unable to free sub node: %d.",
364
0
       function,
365
0
       sub_node_index );
366
367
0
      result = -1;
368
0
    }
369
124k
    sub_node = next_node;
370
124k
  }
371
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
372
  if( libcthreads_read_write_lock_release_for_write(
373
       internal_node->read_write_lock,
374
       error ) != 1 )
375
  {
376
    libcerror_error_set(
377
     error,
378
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
379
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
380
     "%s: unable to release read/write lock for writing.",
381
     function );
382
383
    return( -1 );
384
  }
385
#endif
386
1.44M
  return( result );
387
388
0
on_error:
389
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
390
  libcthreads_read_write_lock_release_for_write(
391
   internal_node->read_write_lock,
392
   NULL );
393
#endif
394
0
  return( -1 );
395
1.44M
}
396
397
/* Clones the tree node and its sub nodes
398
 *
399
 * The values are cloned using the value_clone_function
400
 * On error the values are freed using the value_free_function
401
 *
402
 * Returns 1 if successful or -1 on error
403
 */
404
int libcdata_tree_node_clone(
405
     libcdata_tree_node_t **destination_node,
406
     libcdata_tree_node_t *source_node,
407
     int (*value_free_function)(
408
            intptr_t **value,
409
            libcerror_error_t **error ),
410
     int (*value_clone_function)(
411
            intptr_t **destination_value,
412
            intptr_t *source_value,
413
            libcerror_error_t **error ),
414
     libcerror_error_t **error )
415
0
{
416
0
  libcdata_internal_tree_node_t *internal_destination_node = NULL;
417
0
  libcdata_internal_tree_node_t *internal_source_node      = NULL;
418
0
  libcdata_tree_node_t *destination_sub_node               = NULL;
419
0
  libcdata_tree_node_t *sub_node                           = NULL;
420
0
  static char *function                                    = "libcdata_tree_node_clone";
421
0
  int sub_node_index                                       = 0;
422
423
0
  if( destination_node == NULL )
424
0
  {
425
0
    libcerror_error_set(
426
0
     error,
427
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
428
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
429
0
     "%s: invalid destination tree node.",
430
0
     function );
431
432
0
    return( -1 );
433
0
  }
434
0
  if( *destination_node != NULL )
435
0
  {
436
0
    libcerror_error_set(
437
0
     error,
438
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
439
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
440
0
     "%s: invalid destination tree node already set.",
441
0
     function );
442
443
0
    return( -1 );
444
0
  }
445
0
  if( value_free_function == NULL )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
450
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
451
0
     "%s: invalid value free function.",
452
0
     function );
453
454
0
    return( -1 );
455
0
  }
456
0
  if( value_clone_function == NULL )
457
0
  {
458
0
    libcerror_error_set(
459
0
     error,
460
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
461
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
462
0
     "%s: invalid value clone function.",
463
0
     function );
464
465
0
    return( -1 );
466
0
  }
467
0
  if( source_node == NULL )
468
0
  {
469
0
    *destination_node = NULL;
470
471
0
    return( 1 );
472
0
  }
473
0
  internal_source_node = (libcdata_internal_tree_node_t *) source_node;
474
475
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
476
  if( libcthreads_read_write_lock_grab_for_read(
477
       internal_source_node->read_write_lock,
478
       error ) != 1 )
479
  {
480
    libcerror_error_set(
481
     error,
482
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
483
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
484
     "%s: unable to grab read/write lock for reading.",
485
     function );
486
487
    return( -1 );
488
  }
489
#endif
490
0
  if( libcdata_tree_node_initialize(
491
0
       (libcdata_tree_node_t **) &internal_destination_node,
492
0
       error ) != 1 )
493
0
  {
494
0
    libcerror_error_set(
495
0
     error,
496
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
497
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
498
0
     "%s: unable to create destination tree node.",
499
0
     function );
500
501
0
    goto on_error;
502
0
  }
503
0
  if( internal_destination_node == NULL )
504
0
  {
505
0
    libcerror_error_set(
506
0
     error,
507
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
508
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
509
0
     "%s: missing destination tree node.",
510
0
     function );
511
512
0
    goto on_error;
513
0
  }
514
0
  if( value_clone_function(
515
0
       &( internal_destination_node->value ),
516
0
       internal_source_node->value,
517
0
       error ) != 1 )
518
0
  {
519
0
    libcerror_error_set(
520
0
     error,
521
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
523
0
     "%s: unable to create destination tree node value.",
524
0
     function );
525
526
0
    goto on_error;
527
0
  }
528
  /* Clone the sub nodes
529
   */
530
0
  sub_node = internal_source_node->first_sub_node;
531
532
0
  for( sub_node_index = 0;
533
0
       sub_node_index < internal_source_node->number_of_sub_nodes;
534
0
       sub_node_index++ )
535
0
  {
536
0
    if( sub_node == NULL )
537
0
    {
538
0
      libcerror_error_set(
539
0
       error,
540
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
541
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
542
0
       "%s: corruption detected in source sub node: %d.",
543
0
       function,
544
0
       sub_node_index );
545
546
0
      goto on_error;
547
0
    }
548
0
    if( libcdata_tree_node_clone(
549
0
         &destination_sub_node,
550
0
         sub_node,
551
0
         value_free_function,
552
0
         value_clone_function,
553
0
         error ) != 1 )
554
0
    {
555
0
      libcerror_error_set(
556
0
       error,
557
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
558
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
559
0
       "%s: unable to create destination sub node: %d.",
560
0
       function,
561
0
       sub_node_index );
562
563
0
      goto on_error;
564
0
    }
565
0
    if( libcdata_internal_tree_node_append_node(
566
0
         internal_destination_node,
567
0
         destination_sub_node,
568
0
         error ) != 1 )
569
0
    {
570
0
      libcerror_error_set(
571
0
       error,
572
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
574
0
       "%s: unable to append sub node: %d to destination tree node.",
575
0
       function,
576
0
       sub_node_index );
577
578
0
      goto on_error;
579
0
    }
580
0
    destination_sub_node = NULL;
581
582
0
    if( libcdata_tree_node_get_next_node(
583
0
         sub_node,
584
0
         &sub_node,
585
0
         error ) != 1 )
586
0
    {
587
0
      libcerror_error_set(
588
0
       error,
589
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
590
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
591
0
       "%s: unable to retrieve next node of sub node: %d.",
592
0
       function,
593
0
       sub_node_index );
594
595
0
      goto on_error;
596
0
    }
597
0
  }
598
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
599
  if( libcthreads_read_write_lock_release_for_read(
600
       internal_source_node->read_write_lock,
601
       error ) != 1 )
602
  {
603
    libcerror_error_set(
604
     error,
605
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
606
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
607
     "%s: unable to release read/write lock for reading.",
608
     function );
609
610
    libcdata_tree_node_free(
611
     &destination_sub_node,
612
     value_free_function,
613
     NULL );
614
615
    return( -1 );
616
  }
617
#endif
618
0
  *destination_node = (libcdata_tree_node_t *) internal_destination_node;
619
620
0
  return( 1 );
621
622
0
on_error:
623
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
624
  libcthreads_read_write_lock_release_for_read(
625
   internal_source_node->read_write_lock,
626
   NULL );
627
#endif
628
0
  if( destination_sub_node != NULL )
629
0
  {
630
0
    libcdata_tree_node_free(
631
0
     &destination_sub_node,
632
0
     value_free_function,
633
0
     NULL );
634
0
  }
635
0
  if( internal_destination_node != NULL )
636
0
  {
637
0
    libcdata_tree_node_free(
638
0
     (libcdata_tree_node_t **) &internal_destination_node,
639
0
     value_free_function,
640
0
     NULL );
641
0
  }
642
0
  return( -1 );
643
0
}
644
645
/* Retrieves the value from the tree node
646
 * Returns 1 if successful or -1 on error
647
 */
648
int libcdata_tree_node_get_value(
649
     libcdata_tree_node_t *node,
650
     intptr_t **value,
651
     libcerror_error_t **error )
652
20.4M
{
653
20.4M
  libcdata_internal_tree_node_t *internal_node = NULL;
654
20.4M
  static char *function                        = "libcdata_tree_node_get_value";
655
656
20.4M
  if( node == NULL )
657
0
  {
658
0
    libcerror_error_set(
659
0
     error,
660
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
661
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
662
0
     "%s: invalid node.",
663
0
     function );
664
665
0
    return( -1 );
666
0
  }
667
20.4M
  internal_node = (libcdata_internal_tree_node_t *) node;
668
669
20.4M
  if( value == NULL )
670
0
  {
671
0
    libcerror_error_set(
672
0
     error,
673
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
674
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
675
0
     "%s: invalid value.",
676
0
     function );
677
678
0
    return( -1 );
679
0
  }
680
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
681
  if( libcthreads_read_write_lock_grab_for_read(
682
       internal_node->read_write_lock,
683
       error ) != 1 )
684
  {
685
    libcerror_error_set(
686
     error,
687
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
688
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
689
     "%s: unable to grab read/write lock for reading.",
690
     function );
691
692
    return( -1 );
693
  }
694
#endif
695
20.4M
  *value = internal_node->value;
696
697
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
698
  if( libcthreads_read_write_lock_release_for_read(
699
       internal_node->read_write_lock,
700
       error ) != 1 )
701
  {
702
    libcerror_error_set(
703
     error,
704
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
705
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
706
     "%s: unable to release read/write lock for reading.",
707
     function );
708
709
    return( -1 );
710
  }
711
#endif
712
20.4M
  return( 1 );
713
20.4M
}
714
715
/* Sets the value in the tree node
716
 * Returns 1 if successful or -1 on error
717
 */
718
int libcdata_tree_node_set_value(
719
     libcdata_tree_node_t *node,
720
     intptr_t *value,
721
     libcerror_error_t **error )
722
1.41M
{
723
1.41M
  libcdata_internal_tree_node_t *internal_node = NULL;
724
1.41M
  static char *function                        = "libcdata_tree_node_set_value";
725
726
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
727
  intptr_t *backup_value                       = NULL;
728
#endif
729
730
1.41M
  if( node == NULL )
731
0
  {
732
0
    libcerror_error_set(
733
0
     error,
734
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
735
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
736
0
     "%s: invalid node.",
737
0
     function );
738
739
0
    return( -1 );
740
0
  }
741
1.41M
  internal_node = (libcdata_internal_tree_node_t *) node;
742
743
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
744
  if( libcthreads_read_write_lock_grab_for_write(
745
       internal_node->read_write_lock,
746
       error ) != 1 )
747
  {
748
    libcerror_error_set(
749
     error,
750
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
751
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
752
     "%s: unable to grab read/write lock for writing.",
753
     function );
754
755
    return( -1 );
756
  }
757
  backup_value = internal_node->value;
758
#endif
759
760
1.41M
  internal_node->value = value;
761
762
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
763
  if( libcthreads_read_write_lock_release_for_write(
764
       internal_node->read_write_lock,
765
       error ) != 1 )
766
  {
767
    libcerror_error_set(
768
     error,
769
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
770
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
771
     "%s: unable to release read/write lock for writing.",
772
     function );
773
774
    goto on_error;
775
  }
776
#endif
777
1.41M
  return( 1 );
778
779
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
780
on_error:
781
  internal_node->value = backup_value;
782
783
  return( -1 );
784
#endif
785
1.41M
}
786
787
/* Retrieves the parent node from the tree node
788
 * Returns 1 if successful or -1 on error
789
 */
790
int libcdata_tree_node_get_parent_node(
791
     libcdata_tree_node_t *node,
792
     libcdata_tree_node_t **parent_node,
793
     libcerror_error_t **error )
794
23.6k
{
795
23.6k
  libcdata_internal_tree_node_t *internal_node = NULL;
796
23.6k
  static char *function                        = "libcdata_tree_node_get_parent_node";
797
798
23.6k
  if( node == NULL )
799
0
  {
800
0
    libcerror_error_set(
801
0
     error,
802
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
803
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
804
0
     "%s: invalid node.",
805
0
     function );
806
807
0
    return( -1 );
808
0
  }
809
23.6k
  internal_node = (libcdata_internal_tree_node_t *) node;
810
811
23.6k
  if( parent_node == NULL )
812
0
  {
813
0
    libcerror_error_set(
814
0
     error,
815
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
816
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
817
0
     "%s: invalid parent node.",
818
0
     function );
819
820
0
    return( -1 );
821
0
  }
822
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
823
  if( libcthreads_read_write_lock_grab_for_read(
824
       internal_node->read_write_lock,
825
       error ) != 1 )
826
  {
827
    libcerror_error_set(
828
     error,
829
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
830
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
831
     "%s: unable to grab read/write lock for reading.",
832
     function );
833
834
    return( -1 );
835
  }
836
#endif
837
23.6k
  *parent_node = internal_node->parent_node;
838
839
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
840
  if( libcthreads_read_write_lock_release_for_read(
841
       internal_node->read_write_lock,
842
       error ) != 1 )
843
  {
844
    libcerror_error_set(
845
     error,
846
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
847
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
848
     "%s: unable to release read/write lock for reading.",
849
     function );
850
851
    return( -1 );
852
  }
853
#endif
854
23.6k
  return( 1 );
855
23.6k
}
856
857
/* Sets the parent node in the tree node
858
 * Returns 1 if successful or -1 on error
859
 */
860
int libcdata_tree_node_set_parent_node(
861
     libcdata_tree_node_t *node,
862
     libcdata_tree_node_t *parent_node,
863
     libcerror_error_t **error )
864
124k
{
865
124k
  libcdata_internal_tree_node_t *internal_node = NULL;
866
124k
  static char *function                        = "libcdata_tree_node_set_parent_node";
867
868
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
869
  libcdata_tree_node_t *backup_parent_node     = NULL;
870
#endif
871
872
124k
  if( node == NULL )
873
0
  {
874
0
    libcerror_error_set(
875
0
     error,
876
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
877
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
878
0
     "%s: invalid node.",
879
0
     function );
880
881
0
    return( -1 );
882
0
  }
883
124k
  internal_node = (libcdata_internal_tree_node_t *) node;
884
885
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
886
  if( libcthreads_read_write_lock_grab_for_write(
887
       internal_node->read_write_lock,
888
       error ) != 1 )
889
  {
890
    libcerror_error_set(
891
     error,
892
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
893
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
894
     "%s: unable to grab read/write lock for writing.",
895
     function );
896
897
    return( -1 );
898
  }
899
  backup_parent_node = internal_node->parent_node;
900
#endif
901
902
124k
  internal_node->parent_node = parent_node;
903
904
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
905
  if( libcthreads_read_write_lock_release_for_write(
906
       internal_node->read_write_lock,
907
       error ) != 1 )
908
  {
909
    libcerror_error_set(
910
     error,
911
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
912
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
913
     "%s: unable to release read/write lock for writing.",
914
     function );
915
916
    goto on_error;
917
  }
918
#endif
919
124k
  return( 1 );
920
921
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
922
on_error:
923
  internal_node->parent_node = backup_parent_node;
924
925
  return( -1 );
926
#endif
927
124k
}
928
929
/* Retrieves the previous node from the tree node
930
 * Returns 1 if successful or -1 on error
931
 */
932
int libcdata_tree_node_get_previous_node(
933
     libcdata_tree_node_t *node,
934
     libcdata_tree_node_t **previous_node,
935
     libcerror_error_t **error )
936
105k
{
937
105k
  libcdata_internal_tree_node_t *internal_node = NULL;
938
105k
  static char *function                        = "libcdata_tree_node_get_previous_node";
939
940
105k
  if( node == NULL )
941
0
  {
942
0
    libcerror_error_set(
943
0
     error,
944
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
945
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
946
0
     "%s: invalid node.",
947
0
     function );
948
949
0
    return( -1 );
950
0
  }
951
105k
  internal_node = (libcdata_internal_tree_node_t *) node;
952
953
105k
  if( previous_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 previous node.",
960
0
     function );
961
962
0
    return( -1 );
963
0
  }
964
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
965
  if( libcthreads_read_write_lock_grab_for_read(
966
       internal_node->read_write_lock,
967
       error ) != 1 )
968
  {
969
    libcerror_error_set(
970
     error,
971
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
972
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
973
     "%s: unable to grab read/write lock for reading.",
974
     function );
975
976
    return( -1 );
977
  }
978
#endif
979
105k
  *previous_node = internal_node->previous_node;
980
981
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
982
  if( libcthreads_read_write_lock_release_for_read(
983
       internal_node->read_write_lock,
984
       error ) != 1 )
985
  {
986
    libcerror_error_set(
987
     error,
988
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
989
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
990
     "%s: unable to release read/write lock for reading.",
991
     function );
992
993
    return( -1 );
994
  }
995
#endif
996
105k
  return( 1 );
997
105k
}
998
999
/* Sets the previous node in the tree node
1000
 * Returns 1 if successful or -1 on error
1001
 */
1002
int libcdata_tree_node_set_previous_node(
1003
     libcdata_tree_node_t *node,
1004
     libcdata_tree_node_t *previous_node,
1005
     libcerror_error_t **error )
1006
218k
{
1007
218k
  libcdata_internal_tree_node_t *internal_node = NULL;
1008
218k
  static char *function                        = "libcdata_tree_node_set_previous_node";
1009
1010
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1011
  libcdata_tree_node_t *backup_previous_node   = NULL;
1012
#endif
1013
1014
218k
  if( node == NULL )
1015
0
  {
1016
0
    libcerror_error_set(
1017
0
     error,
1018
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1019
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1020
0
     "%s: invalid node.",
1021
0
     function );
1022
1023
0
    return( -1 );
1024
0
  }
1025
218k
  internal_node = (libcdata_internal_tree_node_t *) node;
1026
1027
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1028
  if( libcthreads_read_write_lock_grab_for_write(
1029
       internal_node->read_write_lock,
1030
       error ) != 1 )
1031
  {
1032
    libcerror_error_set(
1033
     error,
1034
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1035
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1036
     "%s: unable to grab read/write lock for writing.",
1037
     function );
1038
1039
    return( -1 );
1040
  }
1041
  backup_previous_node = internal_node->previous_node;
1042
#endif
1043
1044
218k
  internal_node->previous_node = previous_node;
1045
1046
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1047
  if( libcthreads_read_write_lock_release_for_write(
1048
       internal_node->read_write_lock,
1049
       error ) != 1 )
1050
  {
1051
    libcerror_error_set(
1052
     error,
1053
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1054
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1055
     "%s: unable to release read/write lock for writing.",
1056
     function );
1057
1058
    goto on_error;
1059
  }
1060
#endif
1061
218k
  return( 1 );
1062
1063
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1064
on_error:
1065
  internal_node->previous_node = backup_previous_node;
1066
1067
  return( -1 );
1068
#endif
1069
218k
}
1070
1071
/* Retrieves the next node from the tree node
1072
 * Returns 1 if successful or -1 on error
1073
 */
1074
int libcdata_tree_node_get_next_node(
1075
     libcdata_tree_node_t *node,
1076
     libcdata_tree_node_t **next_node,
1077
     libcerror_error_t **error )
1078
43.9M
{
1079
43.9M
  libcdata_internal_tree_node_t *internal_node = NULL;
1080
43.9M
  static char *function                        = "libcdata_tree_node_get_next_node";
1081
1082
43.9M
  if( node == NULL )
1083
0
  {
1084
0
    libcerror_error_set(
1085
0
     error,
1086
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1087
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1088
0
     "%s: invalid node.",
1089
0
     function );
1090
1091
0
    return( -1 );
1092
0
  }
1093
43.9M
  internal_node = (libcdata_internal_tree_node_t *) node;
1094
1095
43.9M
  if( next_node == NULL )
1096
0
  {
1097
0
    libcerror_error_set(
1098
0
     error,
1099
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1100
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1101
0
     "%s: invalid next node.",
1102
0
     function );
1103
1104
0
    return( -1 );
1105
0
  }
1106
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1107
  if( libcthreads_read_write_lock_grab_for_read(
1108
       internal_node->read_write_lock,
1109
       error ) != 1 )
1110
  {
1111
    libcerror_error_set(
1112
     error,
1113
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1114
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1115
     "%s: unable to grab read/write lock for reading.",
1116
     function );
1117
1118
    return( -1 );
1119
  }
1120
#endif
1121
43.9M
  *next_node = internal_node->next_node;
1122
1123
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1124
  if( libcthreads_read_write_lock_release_for_read(
1125
       internal_node->read_write_lock,
1126
       error ) != 1 )
1127
  {
1128
    libcerror_error_set(
1129
     error,
1130
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1131
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1132
     "%s: unable to release read/write lock for reading.",
1133
     function );
1134
1135
    return( -1 );
1136
  }
1137
#endif
1138
43.9M
  return( 1 );
1139
43.9M
}
1140
1141
/* Sets the next node in the tree node
1142
 * Returns 1 if successful or -1 on error
1143
 */
1144
int libcdata_tree_node_set_next_node(
1145
     libcdata_tree_node_t *node,
1146
     libcdata_tree_node_t *next_node,
1147
     libcerror_error_t **error )
1148
103k
{
1149
103k
  libcdata_internal_tree_node_t *internal_node = NULL;
1150
103k
  static char *function                        = "libcdata_tree_node_set_next_node";
1151
1152
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1153
  libcdata_tree_node_t *backup_next_node       = NULL;
1154
#endif
1155
1156
103k
  if( node == NULL )
1157
0
  {
1158
0
    libcerror_error_set(
1159
0
     error,
1160
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1161
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1162
0
     "%s: invalid node.",
1163
0
     function );
1164
1165
0
    return( -1 );
1166
0
  }
1167
103k
  internal_node = (libcdata_internal_tree_node_t *) node;
1168
1169
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1170
  if( libcthreads_read_write_lock_grab_for_write(
1171
       internal_node->read_write_lock,
1172
       error ) != 1 )
1173
  {
1174
    libcerror_error_set(
1175
     error,
1176
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1177
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1178
     "%s: unable to grab read/write lock for writing.",
1179
     function );
1180
1181
    return( -1 );
1182
  }
1183
  backup_next_node = internal_node->next_node ;
1184
#endif
1185
1186
103k
  internal_node->next_node = next_node;
1187
1188
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1189
  if( libcthreads_read_write_lock_release_for_write(
1190
       internal_node->read_write_lock,
1191
       error ) != 1 )
1192
  {
1193
    libcerror_error_set(
1194
     error,
1195
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1196
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1197
     "%s: unable to release read/write lock for writing.",
1198
     function );
1199
1200
    goto on_error;
1201
  }
1202
#endif
1203
103k
  return( 1 );
1204
1205
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1206
on_error:
1207
  internal_node->next_node = backup_next_node;
1208
1209
  return( -1 );
1210
#endif
1211
103k
}
1212
1213
/* Retrieves the nodes from the tree node
1214
 * Returns 1 if successful or -1 on error
1215
 */
1216
int libcdata_tree_node_get_nodes(
1217
     libcdata_tree_node_t *node,
1218
     libcdata_tree_node_t **parent_node,
1219
     libcdata_tree_node_t **previous_node,
1220
     libcdata_tree_node_t **next_node,
1221
     libcerror_error_t **error )
1222
699k
{
1223
699k
  libcdata_internal_tree_node_t *internal_node = NULL;
1224
699k
  static char *function                        = "libcdata_tree_node_get_nodes";
1225
1226
699k
  if( node == NULL )
1227
0
  {
1228
0
    libcerror_error_set(
1229
0
     error,
1230
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1231
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1232
0
     "%s: invalid node.",
1233
0
     function );
1234
1235
0
    return( -1 );
1236
0
  }
1237
699k
  internal_node = (libcdata_internal_tree_node_t *) node;
1238
1239
699k
  if( parent_node == NULL )
1240
0
  {
1241
0
    libcerror_error_set(
1242
0
     error,
1243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1244
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1245
0
     "%s: invalid parent node.",
1246
0
     function );
1247
1248
0
    return( -1 );
1249
0
  }
1250
699k
  if( previous_node == NULL )
1251
0
  {
1252
0
    libcerror_error_set(
1253
0
     error,
1254
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1255
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1256
0
     "%s: invalid previous node.",
1257
0
     function );
1258
1259
0
    return( -1 );
1260
0
  }
1261
699k
  if( next_node == NULL )
1262
0
  {
1263
0
    libcerror_error_set(
1264
0
     error,
1265
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1266
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1267
0
     "%s: invalid next node.",
1268
0
     function );
1269
1270
0
    return( -1 );
1271
0
  }
1272
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1273
  if( libcthreads_read_write_lock_grab_for_read(
1274
       internal_node->read_write_lock,
1275
       error ) != 1 )
1276
  {
1277
    libcerror_error_set(
1278
     error,
1279
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1280
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1281
     "%s: unable to grab read/write lock for reading.",
1282
     function );
1283
1284
    return( -1 );
1285
  }
1286
#endif
1287
699k
  *parent_node   = internal_node->parent_node;
1288
699k
  *previous_node = internal_node->previous_node;
1289
699k
  *next_node     = internal_node->next_node;
1290
1291
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1292
  if( libcthreads_read_write_lock_release_for_read(
1293
       internal_node->read_write_lock,
1294
       error ) != 1 )
1295
  {
1296
    libcerror_error_set(
1297
     error,
1298
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1299
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1300
     "%s: unable to release read/write lock for reading.",
1301
     function );
1302
1303
    return( -1 );
1304
  }
1305
#endif
1306
699k
  return( 1 );
1307
699k
}
1308
1309
/* Sets the nodes in the tree node
1310
 * Returns 1 if successful or -1 on error
1311
 */
1312
int libcdata_tree_node_set_nodes(
1313
     libcdata_tree_node_t *node,
1314
     libcdata_tree_node_t *parent_node,
1315
     libcdata_tree_node_t *previous_node,
1316
     libcdata_tree_node_t *next_node,
1317
     libcerror_error_t **error )
1318
174k
{
1319
174k
  libcdata_internal_tree_node_t *internal_node = NULL;
1320
174k
  static char *function                        = "libcdata_tree_node_set_nodes";
1321
1322
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1323
  libcdata_tree_node_t *backup_next_node       = NULL;
1324
  libcdata_tree_node_t *backup_parent_node     = NULL;
1325
  libcdata_tree_node_t *backup_previous_node   = NULL;
1326
#endif
1327
1328
174k
  if( node == NULL )
1329
0
  {
1330
0
    libcerror_error_set(
1331
0
     error,
1332
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1333
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1334
0
     "%s: invalid node.",
1335
0
     function );
1336
1337
0
    return( -1 );
1338
0
  }
1339
174k
  internal_node = (libcdata_internal_tree_node_t *) node;
1340
1341
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1342
  if( libcthreads_read_write_lock_grab_for_write(
1343
       internal_node->read_write_lock,
1344
       error ) != 1 )
1345
  {
1346
    libcerror_error_set(
1347
     error,
1348
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1349
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1350
     "%s: unable to grab read/write lock for writing.",
1351
     function );
1352
1353
    return( -1 );
1354
  }
1355
  backup_parent_node   = internal_node->parent_node;
1356
  backup_previous_node = internal_node->previous_node;
1357
  backup_next_node     = internal_node->next_node;
1358
#endif
1359
1360
174k
  internal_node->parent_node   = parent_node;
1361
174k
  internal_node->previous_node = previous_node;
1362
174k
  internal_node->next_node     = next_node;
1363
1364
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1365
  if( libcthreads_read_write_lock_release_for_write(
1366
       internal_node->read_write_lock,
1367
       error ) != 1 )
1368
  {
1369
    libcerror_error_set(
1370
     error,
1371
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1372
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1373
     "%s: unable to release read/write lock for writing.",
1374
     function );
1375
1376
    goto on_error;
1377
  }
1378
#endif
1379
174k
  return( 1 );
1380
1381
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1382
on_error:
1383
  internal_node->parent_node   = backup_parent_node;
1384
  internal_node->previous_node = backup_previous_node;
1385
  internal_node->next_node     = backup_next_node;
1386
1387
  return( -1 );
1388
#endif
1389
174k
}
1390
1391
/* Retrieves the first sub node from the tree node
1392
 * Returns 1 if successful or -1 on error
1393
 */
1394
int libcdata_tree_node_get_first_sub_node(
1395
     libcdata_tree_node_t *node,
1396
     libcdata_tree_node_t **first_sub_node,
1397
     libcerror_error_t **error )
1398
0
{
1399
0
  libcdata_internal_tree_node_t *internal_node = NULL;
1400
0
  static char *function                        = "libcdata_tree_node_get_first_sub_node";
1401
1402
0
  if( node == NULL )
1403
0
  {
1404
0
    libcerror_error_set(
1405
0
     error,
1406
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1407
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1408
0
     "%s: invalid node.",
1409
0
     function );
1410
1411
0
    return( -1 );
1412
0
  }
1413
0
  internal_node = (libcdata_internal_tree_node_t *) node;
1414
1415
0
  if( first_sub_node == NULL )
1416
0
  {
1417
0
    libcerror_error_set(
1418
0
     error,
1419
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1420
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1421
0
     "%s: invalid first sub node.",
1422
0
     function );
1423
1424
0
    return( -1 );
1425
0
  }
1426
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1427
  if( libcthreads_read_write_lock_grab_for_read(
1428
       internal_node->read_write_lock,
1429
       error ) != 1 )
1430
  {
1431
    libcerror_error_set(
1432
     error,
1433
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1434
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1435
     "%s: unable to grab read/write lock for reading.",
1436
     function );
1437
1438
    return( -1 );
1439
  }
1440
#endif
1441
0
  *first_sub_node = internal_node->first_sub_node;
1442
1443
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1444
  if( libcthreads_read_write_lock_release_for_read(
1445
       internal_node->read_write_lock,
1446
       error ) != 1 )
1447
  {
1448
    libcerror_error_set(
1449
     error,
1450
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1451
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1452
     "%s: unable to release read/write lock for reading.",
1453
     function );
1454
1455
    return( -1 );
1456
  }
1457
#endif
1458
0
  return( 1 );
1459
0
}
1460
1461
/* Sets the first sub node in the tree node
1462
 * Returns 1 if successful or -1 on error
1463
 */
1464
int libcdata_internal_tree_node_set_first_sub_node(
1465
     libcdata_internal_tree_node_t *internal_node,
1466
     libcdata_tree_node_t *first_sub_node,
1467
     libcerror_error_t **error )
1468
0
{
1469
0
  libcdata_tree_node_t *backup_first_sub_node = NULL;
1470
0
  libcdata_tree_node_t *backup_previous_node  = NULL;
1471
0
  static char *function                       = "libcdata_internal_tree_node_set_first_sub_node";
1472
1473
0
  if( internal_node == NULL )
1474
0
  {
1475
0
    libcerror_error_set(
1476
0
     error,
1477
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1478
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1479
0
     "%s: invalid node.",
1480
0
     function );
1481
1482
0
    return( -1 );
1483
0
  }
1484
0
  if( first_sub_node != NULL )
1485
0
  {
1486
0
    if( libcdata_tree_node_get_previous_node(
1487
0
         first_sub_node,
1488
0
         &backup_previous_node,
1489
0
         error ) != 1 )
1490
0
    {
1491
0
      libcerror_error_set(
1492
0
       error,
1493
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1494
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1495
0
       "%s: unable to retrieve previous node of sub node.",
1496
0
       function );
1497
1498
0
      return( -1 );
1499
0
    }
1500
0
  }
1501
0
  backup_first_sub_node = internal_node->first_sub_node;
1502
1503
0
  if( first_sub_node != NULL )
1504
0
  {
1505
0
    if( libcdata_tree_node_set_previous_node(
1506
0
         first_sub_node,
1507
0
         internal_node->first_sub_node,
1508
0
         error ) != 1 )
1509
0
    {
1510
0
      libcerror_error_set(
1511
0
       error,
1512
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1513
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1514
0
       "%s: unable to set previous node of sub node.",
1515
0
       function );
1516
1517
0
      goto on_error;
1518
0
    }
1519
0
  }
1520
0
  if( internal_node->first_sub_node != NULL )
1521
0
  {
1522
0
    if( libcdata_tree_node_set_next_node(
1523
0
         internal_node->first_sub_node,
1524
0
         first_sub_node,
1525
0
         error ) != 1 )
1526
0
    {
1527
0
      libcerror_error_set(
1528
0
       error,
1529
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1530
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1531
0
       "%s: unable to set next node of first sub node.",
1532
0
       function );
1533
1534
0
      goto on_error;
1535
0
    }
1536
0
  }
1537
0
  internal_node->first_sub_node = first_sub_node;
1538
1539
0
  return( 1 );
1540
1541
0
on_error:
1542
0
  if( first_sub_node != NULL )
1543
0
  {
1544
0
    libcdata_tree_node_set_previous_node(
1545
0
     first_sub_node,
1546
0
     backup_previous_node,
1547
0
     NULL );
1548
0
  }
1549
0
  if( backup_first_sub_node != NULL )
1550
0
  {
1551
0
    libcdata_tree_node_set_next_node(
1552
0
     backup_first_sub_node,
1553
0
     NULL,
1554
0
     NULL );
1555
0
  }
1556
0
  internal_node->first_sub_node = backup_first_sub_node;
1557
1558
0
  return( -1 );
1559
0
}
1560
1561
/* Retrieves the last sub node from the tree node
1562
 * Returns 1 if successful or -1 on error
1563
 */
1564
int libcdata_tree_node_get_last_sub_node(
1565
     libcdata_tree_node_t *node,
1566
     libcdata_tree_node_t **last_sub_node,
1567
     libcerror_error_t **error )
1568
0
{
1569
0
  libcdata_internal_tree_node_t *internal_node = NULL;
1570
0
  static char *function                        = "libcdata_tree_node_get_last_sub_node";
1571
1572
0
  if( node == NULL )
1573
0
  {
1574
0
    libcerror_error_set(
1575
0
     error,
1576
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1577
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1578
0
     "%s: invalid node.",
1579
0
     function );
1580
1581
0
    return( -1 );
1582
0
  }
1583
0
  internal_node = (libcdata_internal_tree_node_t *) node;
1584
1585
0
  if( last_sub_node == 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 last sub node.",
1592
0
     function );
1593
1594
0
    return( -1 );
1595
0
  }
1596
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1597
  if( libcthreads_read_write_lock_grab_for_read(
1598
       internal_node->read_write_lock,
1599
       error ) != 1 )
1600
  {
1601
    libcerror_error_set(
1602
     error,
1603
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1604
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1605
     "%s: unable to grab read/write lock for reading.",
1606
     function );
1607
1608
    return( -1 );
1609
  }
1610
#endif
1611
0
  *last_sub_node = internal_node->last_sub_node;
1612
1613
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1614
  if( libcthreads_read_write_lock_release_for_read(
1615
       internal_node->read_write_lock,
1616
       error ) != 1 )
1617
  {
1618
    libcerror_error_set(
1619
     error,
1620
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1621
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1622
     "%s: unable to release read/write lock for reading.",
1623
     function );
1624
1625
    return( -1 );
1626
  }
1627
#endif
1628
0
  return( 1 );
1629
0
}
1630
1631
/* Sets the last sub node in the tree node
1632
 * Returns 1 if successful or -1 on error
1633
 */
1634
int libcdata_internal_tree_node_set_last_sub_node(
1635
     libcdata_internal_tree_node_t *internal_node,
1636
     libcdata_tree_node_t *last_sub_node,
1637
     libcerror_error_t **error )
1638
55.0k
{
1639
55.0k
  libcdata_tree_node_t *backup_last_sub_node = NULL;
1640
55.0k
  libcdata_tree_node_t *backup_previous_node = NULL;
1641
55.0k
  static char *function                      = "libcdata_internal_tree_node_set_last_sub_node";
1642
1643
55.0k
  if( internal_node == NULL )
1644
0
  {
1645
0
    libcerror_error_set(
1646
0
     error,
1647
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1648
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1649
0
     "%s: invalid node.",
1650
0
     function );
1651
1652
0
    return( -1 );
1653
0
  }
1654
55.0k
  if( last_sub_node != NULL )
1655
55.0k
  {
1656
55.0k
    if( libcdata_tree_node_get_previous_node(
1657
55.0k
         last_sub_node,
1658
55.0k
         &backup_previous_node,
1659
55.0k
         error ) != 1 )
1660
0
    {
1661
0
      libcerror_error_set(
1662
0
       error,
1663
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1664
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1665
0
       "%s: unable to retrieve previous node of sub node.",
1666
0
       function );
1667
1668
0
      return( -1 );
1669
0
    }
1670
55.0k
  }
1671
55.0k
  backup_last_sub_node = internal_node->last_sub_node;
1672
1673
55.0k
  if( last_sub_node != NULL )
1674
55.0k
  {
1675
55.0k
    if( libcdata_tree_node_set_previous_node(
1676
55.0k
         last_sub_node,
1677
55.0k
         internal_node->last_sub_node,
1678
55.0k
         error ) != 1 )
1679
0
    {
1680
0
      libcerror_error_set(
1681
0
       error,
1682
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1683
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1684
0
       "%s: unable to set previous node of sub node.",
1685
0
       function );
1686
1687
0
      goto on_error;
1688
0
    }
1689
55.0k
  }
1690
55.0k
  if( internal_node->last_sub_node != NULL )
1691
55.0k
  {
1692
55.0k
    if( libcdata_tree_node_set_next_node(
1693
55.0k
         internal_node->last_sub_node,
1694
55.0k
         last_sub_node,
1695
55.0k
         error ) != 1 )
1696
0
    {
1697
0
      libcerror_error_set(
1698
0
       error,
1699
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1700
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1701
0
       "%s: unable to set next node of last sub node.",
1702
0
       function );
1703
1704
0
      goto on_error;
1705
0
    }
1706
55.0k
  }
1707
55.0k
  internal_node->last_sub_node = last_sub_node;
1708
1709
55.0k
  return( 1 );
1710
1711
0
on_error:
1712
0
  if( last_sub_node != NULL )
1713
0
  {
1714
0
    libcdata_tree_node_set_previous_node(
1715
0
     last_sub_node,
1716
0
     backup_previous_node,
1717
0
     NULL );
1718
0
  }
1719
0
  if( backup_last_sub_node != NULL )
1720
0
  {
1721
0
    libcdata_tree_node_set_next_node(
1722
0
     backup_last_sub_node,
1723
0
     NULL,
1724
0
     NULL );
1725
0
  }
1726
0
  internal_node->last_sub_node = backup_last_sub_node;
1727
1728
0
  return( -1 );
1729
55.0k
}
1730
1731
/* Retrieves the sub nodes from the tree node
1732
 * Returns 1 if successful or -1 on error
1733
 */
1734
int libcdata_tree_node_get_sub_nodes(
1735
     libcdata_tree_node_t *node,
1736
     libcdata_tree_node_t **first_sub_node,
1737
     libcdata_tree_node_t **last_sub_node,
1738
     libcerror_error_t **error )
1739
0
{
1740
0
  libcdata_internal_tree_node_t *internal_node = NULL;
1741
0
  static char *function                        = "libcdata_tree_node_sub_get_nodes";
1742
1743
0
  if( node == NULL )
1744
0
  {
1745
0
    libcerror_error_set(
1746
0
     error,
1747
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1748
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1749
0
     "%s: invalid node.",
1750
0
     function );
1751
1752
0
    return( -1 );
1753
0
  }
1754
0
  internal_node = (libcdata_internal_tree_node_t *) node;
1755
1756
0
  if( first_sub_node == NULL )
1757
0
  {
1758
0
    libcerror_error_set(
1759
0
     error,
1760
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1761
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1762
0
     "%s: invalid first sub node.",
1763
0
     function );
1764
1765
0
    return( -1 );
1766
0
  }
1767
0
  if( last_sub_node == NULL )
1768
0
  {
1769
0
    libcerror_error_set(
1770
0
     error,
1771
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1772
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1773
0
     "%s: invalid last sub node.",
1774
0
     function );
1775
1776
0
    return( -1 );
1777
0
  }
1778
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1779
  if( libcthreads_read_write_lock_grab_for_read(
1780
       internal_node->read_write_lock,
1781
       error ) != 1 )
1782
  {
1783
    libcerror_error_set(
1784
     error,
1785
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1786
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1787
     "%s: unable to grab read/write lock for reading.",
1788
     function );
1789
1790
    return( -1 );
1791
  }
1792
#endif
1793
0
  *first_sub_node = internal_node->first_sub_node;
1794
0
  *last_sub_node  = internal_node->last_sub_node;
1795
1796
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1797
  if( libcthreads_read_write_lock_release_for_read(
1798
       internal_node->read_write_lock,
1799
       error ) != 1 )
1800
  {
1801
    libcerror_error_set(
1802
     error,
1803
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1804
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1805
     "%s: unable to release read/write lock for reading.",
1806
     function );
1807
1808
    return( -1 );
1809
  }
1810
#endif
1811
0
  return( 1 );
1812
0
}
1813
1814
/* Sets the sub nodes in the tree node
1815
 * Returns 1 if successful or -1 on error
1816
 */
1817
int libcdata_tree_node_set_sub_nodes(
1818
     libcdata_tree_node_t *node,
1819
     libcdata_tree_node_t *first_sub_node,
1820
     libcdata_tree_node_t *last_sub_node,
1821
     libcerror_error_t **error )
1822
0
{
1823
0
  libcdata_internal_tree_node_t *internal_node = NULL;
1824
0
  static char *function                        = "libcdata_tree_node_set_sub_nodes";
1825
1826
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1827
  libcdata_tree_node_t *backup_first_sub_node  = NULL;
1828
  libcdata_tree_node_t *backup_last_sub_node   = NULL;
1829
#endif
1830
1831
0
  if( node == NULL )
1832
0
  {
1833
0
    libcerror_error_set(
1834
0
     error,
1835
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1836
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1837
0
     "%s: invalid node.",
1838
0
     function );
1839
1840
0
    return( -1 );
1841
0
  }
1842
0
  internal_node = (libcdata_internal_tree_node_t *) node;
1843
1844
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1845
  if( libcthreads_read_write_lock_grab_for_write(
1846
       internal_node->read_write_lock,
1847
       error ) != 1 )
1848
  {
1849
    libcerror_error_set(
1850
     error,
1851
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1852
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1853
     "%s: unable to grab read/write lock for writing.",
1854
     function );
1855
1856
    return( -1 );
1857
  }
1858
  backup_first_sub_node = internal_node->first_sub_node;
1859
  backup_last_sub_node  = internal_node->last_sub_node;
1860
#endif
1861
1862
0
  internal_node->first_sub_node = first_sub_node;
1863
0
  internal_node->last_sub_node  = last_sub_node;
1864
1865
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1866
  if( libcthreads_read_write_lock_release_for_write(
1867
       internal_node->read_write_lock,
1868
       error ) != 1 )
1869
  {
1870
    libcerror_error_set(
1871
     error,
1872
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1873
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1874
     "%s: unable to release read/write lock for writing.",
1875
     function );
1876
1877
    goto on_error;
1878
  }
1879
#endif
1880
0
  return( 1 );
1881
1882
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1883
on_error:
1884
  internal_node->first_sub_node = backup_first_sub_node;
1885
  internal_node->last_sub_node  = backup_last_sub_node;
1886
1887
  return( -1 );
1888
#endif
1889
0
}
1890
1891
/* Appends a sub tree node to the node
1892
 * Returns 1 if successful or -1 on error
1893
 */
1894
int libcdata_internal_tree_node_append_node(
1895
     libcdata_internal_tree_node_t *internal_node,
1896
     libcdata_tree_node_t *node_to_append,
1897
     libcerror_error_t **error )
1898
0
{
1899
0
  libcdata_tree_node_t *to_append_next_node     = NULL;
1900
0
  libcdata_tree_node_t *to_append_parent_node   = NULL;
1901
0
  libcdata_tree_node_t *to_append_previous_node = NULL;
1902
0
  static char *function                         = "libcdata_internal_tree_node_append_node";
1903
1904
0
  if( internal_node == NULL )
1905
0
  {
1906
0
    libcerror_error_set(
1907
0
     error,
1908
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1909
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1910
0
     "%s: invalid node.",
1911
0
     function );
1912
1913
0
    return( -1 );
1914
0
  }
1915
0
  if( node_to_append == NULL )
1916
0
  {
1917
0
    libcerror_error_set(
1918
0
     error,
1919
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1920
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1921
0
     "%s: invalid node to append.",
1922
0
     function );
1923
1924
0
    return( -1 );
1925
0
  }
1926
0
  if( libcdata_tree_node_get_nodes(
1927
0
       node_to_append,
1928
0
       &to_append_parent_node,
1929
0
       &to_append_previous_node,
1930
0
       &to_append_next_node,
1931
0
       error ) != 1 )
1932
0
  {
1933
0
    libcerror_error_set(
1934
0
     error,
1935
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1936
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1937
0
     "%s: unable to retrieve nodes of node to append.",
1938
0
     function );
1939
1940
0
    return( -1 );
1941
0
  }
1942
0
  if( ( to_append_parent_node != NULL )
1943
0
   || ( to_append_previous_node != NULL )
1944
0
   || ( to_append_next_node != NULL ) )
1945
0
  {
1946
0
    libcerror_error_set(
1947
0
     error,
1948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1949
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1950
0
     "%s: invalid node to append - node is already part of a tree.",
1951
0
     function );
1952
1953
0
    return( -1 );
1954
0
  }
1955
0
  if( internal_node->number_of_sub_nodes == 0 )
1956
0
  {
1957
0
    if( internal_node->first_sub_node != NULL )
1958
0
    {
1959
0
      libcerror_error_set(
1960
0
       error,
1961
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1962
0
       LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1963
0
       "%s: corruption detected - first sub node already set.",
1964
0
       function );
1965
1966
0
      return( -1 );
1967
0
    }
1968
0
    if( internal_node->last_sub_node != NULL )
1969
0
    {
1970
0
      libcerror_error_set(
1971
0
       error,
1972
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1973
0
       LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1974
0
       "%s: corruption detected - last sub node already set.",
1975
0
       function );
1976
1977
0
      return( -1 );
1978
0
    }
1979
0
    internal_node->first_sub_node = node_to_append;
1980
0
    internal_node->last_sub_node  = node_to_append;
1981
0
  }
1982
0
  else
1983
0
  {
1984
0
    if( internal_node->first_sub_node == NULL )
1985
0
    {
1986
0
      libcerror_error_set(
1987
0
       error,
1988
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1989
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1990
0
       "%s: corruption detected - missing first sub node.",
1991
0
       function );
1992
1993
0
      return( -1 );
1994
0
    }
1995
0
    if( internal_node->last_sub_node == NULL )
1996
0
    {
1997
0
      libcerror_error_set(
1998
0
       error,
1999
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2000
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2001
0
       "%s: corruption detected - missing last sub node.",
2002
0
       function );
2003
2004
0
      return( -1 );
2005
0
    }
2006
0
    if( libcdata_tree_node_set_next_node(
2007
0
         internal_node->last_sub_node,
2008
0
         node_to_append,
2009
0
         error ) != 1 )
2010
0
    {
2011
0
      libcerror_error_set(
2012
0
       error,
2013
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2014
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2015
0
       "%s: unable to set next node of last sub node.",
2016
0
       function );
2017
2018
0
      return( -1 );
2019
0
    }
2020
0
    if( libcdata_tree_node_set_previous_node(
2021
0
         node_to_append,
2022
0
         internal_node->last_sub_node,
2023
0
         error ) != 1 )
2024
0
    {
2025
0
      libcerror_error_set(
2026
0
       error,
2027
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2028
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2029
0
       "%s: unable to set previous node of node to append.",
2030
0
       function );
2031
2032
0
      return( -1 );
2033
0
    }
2034
0
    internal_node->last_sub_node = node_to_append;
2035
0
  }
2036
0
  if( libcdata_tree_node_set_parent_node(
2037
0
       node_to_append,
2038
0
       (libcdata_tree_node_t *) internal_node,
2039
0
       error ) != 1 )
2040
0
  {
2041
0
    libcerror_error_set(
2042
0
     error,
2043
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2044
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2045
0
     "%s: unable to set parent node of node to append.",
2046
0
     function );
2047
2048
0
    return( -1 );
2049
0
  }
2050
0
  internal_node->number_of_sub_nodes += 1;
2051
2052
0
  return( 1 );
2053
0
}
2054
2055
/* Appends a tree node to the node
2056
 * Returns 1 if successful or -1 on error
2057
 */
2058
int libcdata_tree_node_append_node(
2059
     libcdata_tree_node_t *node,
2060
     libcdata_tree_node_t *node_to_append,
2061
     libcerror_error_t **error )
2062
4.17k
{
2063
4.17k
  libcdata_internal_tree_node_t *internal_node  = NULL;
2064
4.17k
  libcdata_tree_node_t *to_append_next_node     = NULL;
2065
4.17k
  libcdata_tree_node_t *to_append_parent_node   = NULL;
2066
4.17k
  libcdata_tree_node_t *to_append_previous_node = NULL;
2067
4.17k
  static char *function                         = "libcdata_tree_node_append_node";
2068
4.17k
  int result                                    = 1;
2069
2070
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2071
  libcdata_tree_node_t *backup_first_sub_node   = NULL;
2072
  libcdata_tree_node_t *backup_last_sub_node    = NULL;
2073
#endif
2074
2075
4.17k
  if( node == NULL )
2076
0
  {
2077
0
    libcerror_error_set(
2078
0
     error,
2079
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2080
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2081
0
     "%s: invalid node.",
2082
0
     function );
2083
2084
0
    return( -1 );
2085
0
  }
2086
4.17k
  internal_node = (libcdata_internal_tree_node_t *) node;
2087
2088
4.17k
  if( internal_node->number_of_sub_nodes == 0 )
2089
348
  {
2090
348
    if( internal_node->first_sub_node != NULL )
2091
0
    {
2092
0
      libcerror_error_set(
2093
0
       error,
2094
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2095
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2096
0
       "%s: corruption detected - first sub node already set.",
2097
0
       function );
2098
2099
0
      return( -1 );
2100
0
    }
2101
348
    if( internal_node->last_sub_node != NULL )
2102
0
    {
2103
0
      libcerror_error_set(
2104
0
       error,
2105
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2106
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2107
0
       "%s: corruption detected - last sub node already set.",
2108
0
       function );
2109
2110
0
      return( -1 );
2111
0
    }
2112
348
  }
2113
3.82k
  else
2114
3.82k
  {
2115
3.82k
    if( internal_node->first_sub_node == NULL )
2116
0
    {
2117
0
      libcerror_error_set(
2118
0
       error,
2119
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2120
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2121
0
       "%s: corruption detected - missing first sub node.",
2122
0
       function );
2123
2124
0
      return( -1 );
2125
0
    }
2126
3.82k
    if( internal_node->last_sub_node == NULL )
2127
0
    {
2128
0
      libcerror_error_set(
2129
0
       error,
2130
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2131
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2132
0
       "%s: corruption detected - missing last sub node.",
2133
0
       function );
2134
2135
0
      return( -1 );
2136
0
    }
2137
3.82k
  }
2138
4.17k
  if( libcdata_tree_node_get_nodes(
2139
4.17k
       node_to_append,
2140
4.17k
       &to_append_parent_node,
2141
4.17k
       &to_append_previous_node,
2142
4.17k
       &to_append_next_node,
2143
4.17k
       error ) != 1 )
2144
0
  {
2145
0
    libcerror_error_set(
2146
0
     error,
2147
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2148
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2149
0
     "%s: unable to retrieve nodes of node to append.",
2150
0
     function );
2151
2152
0
    return( -1 );
2153
0
  }
2154
4.17k
  if( ( to_append_parent_node != NULL )
2155
4.17k
   || ( to_append_previous_node != NULL )
2156
4.17k
   || ( to_append_next_node != NULL ) )
2157
0
  {
2158
0
    libcerror_error_set(
2159
0
     error,
2160
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2161
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2162
0
     "%s: invalid node to append - node is already part of a tree.",
2163
0
     function );
2164
2165
0
    return( -1 );
2166
0
  }
2167
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2168
  if( libcthreads_read_write_lock_grab_for_write(
2169
       internal_node->read_write_lock,
2170
       error ) != 1 )
2171
  {
2172
    libcerror_error_set(
2173
     error,
2174
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2175
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2176
     "%s: unable to grab read/write lock for writing.",
2177
     function );
2178
2179
    return( -1 );
2180
  }
2181
  backup_first_sub_node = internal_node->first_sub_node;
2182
  backup_last_sub_node  = internal_node->last_sub_node;
2183
#endif
2184
2185
4.17k
  result = libcdata_tree_node_set_parent_node(
2186
4.17k
            node_to_append,
2187
4.17k
            node,
2188
4.17k
            error );
2189
2190
4.17k
  if( result != 1 )
2191
0
  {
2192
0
    libcerror_error_set(
2193
0
     error,
2194
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2195
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2196
0
     "%s: unable to set parent node of node to append.",
2197
0
     function );
2198
2199
0
    result = -1;
2200
0
  }
2201
4.17k
  if( result == 1 )
2202
4.17k
  {
2203
4.17k
    result = libcdata_tree_node_set_previous_node(
2204
4.17k
              node_to_append,
2205
4.17k
              internal_node->last_sub_node,
2206
4.17k
              error );
2207
2208
4.17k
    if( result != 1 )
2209
0
    {
2210
0
      libcerror_error_set(
2211
0
       error,
2212
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2213
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2214
0
       "%s: unable to set previous node of node to append.",
2215
0
       function );
2216
2217
0
      libcdata_tree_node_set_parent_node(
2218
0
       node_to_append,
2219
0
       NULL,
2220
0
       NULL );
2221
2222
0
      result = -1;
2223
0
    }
2224
4.17k
  }
2225
4.17k
  if( result == 1 )
2226
4.17k
  {
2227
4.17k
    if( internal_node->last_sub_node != NULL )
2228
3.82k
    {
2229
3.82k
      result = libcdata_tree_node_set_next_node(
2230
3.82k
                internal_node->last_sub_node,
2231
3.82k
                node_to_append,
2232
3.82k
                error );
2233
2234
3.82k
      if( result != 1 )
2235
0
      {
2236
0
        libcerror_error_set(
2237
0
         error,
2238
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2239
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2240
0
         "%s: unable to set next node of last sub node.",
2241
0
         function );
2242
2243
0
        libcdata_tree_node_set_parent_node(
2244
0
         node_to_append,
2245
0
         NULL,
2246
0
         NULL );
2247
2248
0
        libcdata_tree_node_set_previous_node(
2249
0
         node_to_append,
2250
0
         NULL,
2251
0
         NULL );
2252
2253
0
        result = -1;
2254
0
      }
2255
3.82k
    }
2256
4.17k
  }
2257
4.17k
  if( result == 1 )
2258
4.17k
  {
2259
4.17k
    if( internal_node->first_sub_node == NULL )
2260
348
    {
2261
348
      internal_node->first_sub_node = node_to_append;
2262
348
    }
2263
4.17k
    internal_node->last_sub_node = node_to_append;
2264
2265
4.17k
    internal_node->number_of_sub_nodes += 1;
2266
4.17k
  }
2267
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2268
  if( libcthreads_read_write_lock_release_for_write(
2269
       internal_node->read_write_lock,
2270
       error ) != 1 )
2271
  {
2272
    libcerror_error_set(
2273
     error,
2274
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2275
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2276
     "%s: unable to release read/write lock for writing.",
2277
     function );
2278
2279
    goto on_error;
2280
  }
2281
#endif
2282
4.17k
  return( result );
2283
2284
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2285
on_error:
2286
  libcdata_tree_node_set_parent_node(
2287
   node_to_append,
2288
   NULL,
2289
   NULL );
2290
2291
  libcdata_tree_node_set_previous_node(
2292
   node_to_append,
2293
   NULL,
2294
   NULL );
2295
2296
  internal_node->first_sub_node = backup_first_sub_node;
2297
  internal_node->last_sub_node  = backup_last_sub_node;
2298
2299
  internal_node->number_of_sub_nodes -= 1;
2300
2301
  return( -1 );
2302
#endif
2303
4.17k
}
2304
2305
/* Appends a value to the node
2306
 * Creates a new sub tree node
2307
 * Returns 1 if successful or -1 on error
2308
 */
2309
int libcdata_tree_node_append_value(
2310
     libcdata_tree_node_t *node,
2311
     intptr_t *value,
2312
     libcerror_error_t **error )
2313
0
{
2314
0
  libcdata_tree_node_t *sub_node = NULL;
2315
0
  static char *function          = "libcdata_tree_node_append_value";
2316
2317
0
  if( node == NULL )
2318
0
  {
2319
0
    libcerror_error_set(
2320
0
     error,
2321
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2322
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2323
0
     "%s: invalid node.",
2324
0
     function );
2325
2326
0
    return( -1 );
2327
0
  }
2328
0
  if( libcdata_tree_node_initialize(
2329
0
       &sub_node,
2330
0
       error ) != 1 )
2331
0
  {
2332
0
    libcerror_error_set(
2333
0
     error,
2334
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2335
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2336
0
     "%s: unable to create sub node.",
2337
0
     function );
2338
2339
0
    goto on_error;
2340
0
  }
2341
0
  if( libcdata_tree_node_set_value(
2342
0
       sub_node,
2343
0
       value,
2344
0
       error ) != 1 )
2345
0
  {
2346
0
    libcerror_error_set(
2347
0
     error,
2348
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
2349
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
2350
0
     "%s: unable to set value in sub node.",
2351
0
     function );
2352
2353
0
    goto on_error;
2354
0
  }
2355
0
  if( libcdata_tree_node_append_node(
2356
0
       node,
2357
0
       sub_node,
2358
0
       error ) != 1 )
2359
0
  {
2360
0
    libcerror_error_set(
2361
0
     error,
2362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2363
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2364
0
     "%s: unable to append sub node to node.",
2365
0
     function );
2366
2367
0
    goto on_error;
2368
0
  }
2369
0
  return( 1 );
2370
2371
0
on_error:
2372
0
  if( sub_node != NULL )
2373
0
  {
2374
0
    libcdata_tree_node_free(
2375
0
     &sub_node,
2376
0
     NULL,
2377
0
     NULL );
2378
0
  }
2379
0
  return( -1 );
2380
0
}
2381
2382
2383
/* Retrieves the node which the sub node should be inserted before
2384
 *
2385
 * Uses the value_compare_function to determine the order of the entries
2386
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2387
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2388
 *
2389
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2390
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2391
 *
2392
 * On return sub_node will be set to NULL if the sub node should be inserted at the end of the list.
2393
 *
2394
 * Returns 1 if successful, 0 if a sub node containing the value already exists or -1 on error
2395
 */
2396
int libcdata_internal_tree_node_insert_node_find_sub_node(
2397
     libcdata_internal_tree_node_t *internal_node,
2398
     intptr_t *value_to_insert,
2399
     int (*value_compare_function)(
2400
            intptr_t *first_value,
2401
            intptr_t *second_value,
2402
            libcerror_error_t **error ),
2403
     uint8_t insert_flags,
2404
     int *sub_node_index,
2405
     libcdata_tree_node_t **sub_node,
2406
     libcerror_error_t **error )
2407
520k
{
2408
520k
  libcdata_tree_node_t *sub_tree_node = NULL;
2409
520k
  intptr_t *sub_node_value            = NULL;
2410
520k
  static char *function               = "libcdata_internal_tree_node_insert_node_find_sub_node";
2411
520k
  int compare_result                  = 0;
2412
520k
  int result                          = 1;
2413
520k
  int safe_sub_node_index             = 0;
2414
2415
520k
  if( internal_node == NULL )
2416
0
  {
2417
0
    libcerror_error_set(
2418
0
     error,
2419
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2420
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2421
0
     "%s: invalid node.",
2422
0
     function );
2423
2424
0
    return( -1 );
2425
0
  }
2426
520k
  if( value_compare_function == NULL )
2427
0
  {
2428
0
    libcerror_error_set(
2429
0
     error,
2430
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2431
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2432
0
     "%s: invalid value compare function.",
2433
0
     function );
2434
2435
0
    return( -1 );
2436
0
  }
2437
520k
  if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
2438
0
  {
2439
0
    libcerror_error_set(
2440
0
     error,
2441
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2442
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2443
0
     "%s: unsupported insert flags: 0x%02" PRIx8 ".",
2444
0
     function,
2445
0
     insert_flags );
2446
2447
0
    return( -1 );
2448
0
  }
2449
520k
  if( sub_node_index == NULL )
2450
0
  {
2451
0
    libcerror_error_set(
2452
0
     error,
2453
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2454
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2455
0
     "%s: invalid sub node index.",
2456
0
     function );
2457
2458
0
    return( -1 );
2459
0
  }
2460
520k
  if( sub_node == NULL )
2461
0
  {
2462
0
    libcerror_error_set(
2463
0
     error,
2464
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2465
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2466
0
     "%s: invalid sub node.",
2467
0
     function );
2468
2469
0
    return( -1 );
2470
0
  }
2471
520k
  sub_tree_node = internal_node->first_sub_node;
2472
2473
520k
  for( safe_sub_node_index = 0;
2474
11.0M
       safe_sub_node_index < internal_node->number_of_sub_nodes;
2475
10.5M
       safe_sub_node_index++ )
2476
11.0M
  {
2477
11.0M
    if( libcdata_tree_node_get_value(
2478
11.0M
         sub_tree_node,
2479
11.0M
         &sub_node_value,
2480
11.0M
         error ) != 1 )
2481
0
    {
2482
0
      libcerror_error_set(
2483
0
       error,
2484
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2485
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2486
0
       "%s: unable to retrieve value of sub node: %d.",
2487
0
       function,
2488
0
       safe_sub_node_index );
2489
2490
0
      return( -1 );
2491
0
    }
2492
11.0M
    compare_result = value_compare_function(
2493
11.0M
                      value_to_insert,
2494
11.0M
                      sub_node_value,
2495
11.0M
                      error );
2496
2497
11.0M
    if( compare_result == -1 )
2498
0
    {
2499
0
      libcerror_error_set(
2500
0
       error,
2501
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2502
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2503
0
       "%s: unable to compare sub node: %d.",
2504
0
       function,
2505
0
       safe_sub_node_index );
2506
2507
0
      return( -1 );
2508
0
    }
2509
11.0M
    else if( compare_result == LIBCDATA_COMPARE_EQUAL )
2510
407k
    {
2511
407k
      if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 )
2512
400k
      {
2513
400k
        result = 0;
2514
2515
400k
        break;
2516
400k
      }
2517
407k
    }
2518
10.6M
    else if( compare_result == LIBCDATA_COMPARE_LESS )
2519
50.1k
    {
2520
50.1k
      break;
2521
50.1k
    }
2522
10.5M
    else if( compare_result != LIBCDATA_COMPARE_GREATER )
2523
0
    {
2524
0
      libcerror_error_set(
2525
0
       error,
2526
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2527
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2528
0
       "%s: unsupported value compare function return value: %d.",
2529
0
       function,
2530
0
       result );
2531
2532
0
      return( -1 );
2533
0
    }
2534
10.5M
    if( libcdata_tree_node_get_next_node(
2535
10.5M
         sub_tree_node,
2536
10.5M
         &sub_tree_node,
2537
10.5M
         error ) != 1 )
2538
0
    {
2539
0
      libcerror_error_set(
2540
0
       error,
2541
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2542
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2543
0
       "%s: unable to retrieve next node of sub node: %d.",
2544
0
       function,
2545
0
       safe_sub_node_index );
2546
2547
0
      return( -1 );
2548
0
    }
2549
10.5M
  }
2550
520k
  if( ( compare_result == LIBCDATA_COMPARE_EQUAL )
2551
520k
   || ( compare_result == LIBCDATA_COMPARE_LESS ) )
2552
466k
  {
2553
466k
    *sub_node_index = safe_sub_node_index;
2554
466k
    *sub_node       = sub_tree_node;
2555
466k
  }
2556
54.3k
  else
2557
54.3k
  {
2558
54.3k
    *sub_node_index = internal_node->number_of_sub_nodes;
2559
54.3k
    *sub_node       = NULL;
2560
54.3k
  }
2561
520k
  return( result );
2562
520k
}
2563
2564
/* Inserts the node before the sub node
2565
 * If sub_node is NULL the node is inserted before or as the first sub node in the list
2566
 * Returns 1 if successful, or -1 on error
2567
 */
2568
int libcdata_internal_tree_node_insert_node_before_sub_node(
2569
     libcdata_internal_tree_node_t *internal_node,
2570
     libcdata_tree_node_t *sub_node,
2571
     libcdata_tree_node_t *node_to_insert,
2572
     libcerror_error_t **error )
2573
119k
{
2574
119k
  libcdata_tree_node_t *backup_first_sub_node = NULL;
2575
119k
  libcdata_tree_node_t *backup_last_sub_node  = NULL;
2576
119k
  libcdata_tree_node_t *previous_node         = NULL;
2577
119k
  static char *function                       = "libcdata_internal_tree_node_insert_node_before_sub_node";
2578
2579
119k
  if( internal_node == NULL )
2580
0
  {
2581
0
    libcerror_error_set(
2582
0
     error,
2583
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2584
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2585
0
     "%s: invalid node.",
2586
0
     function );
2587
2588
0
    return( -1 );
2589
0
  }
2590
119k
  if( node_to_insert == NULL )
2591
0
  {
2592
0
    libcerror_error_set(
2593
0
     error,
2594
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2595
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2596
0
     "%s: invalid node to insert.",
2597
0
     function );
2598
2599
0
    return( -1 );
2600
0
  }
2601
119k
  backup_first_sub_node = internal_node->first_sub_node;
2602
119k
  backup_last_sub_node  = internal_node->last_sub_node;
2603
2604
119k
  if( sub_node != NULL )
2605
50.1k
  {
2606
50.1k
    if( libcdata_tree_node_get_previous_node(
2607
50.1k
         sub_node,
2608
50.1k
         &previous_node,
2609
50.1k
         error ) != 1 )
2610
0
    {
2611
0
      libcerror_error_set(
2612
0
       error,
2613
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2614
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2615
0
       "%s: unable to retrieve previous node from sub node.",
2616
0
       function );
2617
2618
0
      return( -1 );
2619
0
    }
2620
50.1k
  }
2621
119k
  if( internal_node->number_of_sub_nodes == 0 )
2622
14.6k
  {
2623
14.6k
    internal_node->first_sub_node = node_to_insert;
2624
14.6k
    internal_node->last_sub_node  = node_to_insert;
2625
14.6k
  }
2626
105k
  else if( sub_node == NULL )
2627
55.0k
  {
2628
55.0k
    if( libcdata_internal_tree_node_set_last_sub_node(
2629
55.0k
         internal_node,
2630
55.0k
         node_to_insert,
2631
55.0k
         error ) != 1 )
2632
0
    {
2633
0
      libcerror_error_set(
2634
0
       error,
2635
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2636
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2637
0
       "%s: unable to set last sub node.",
2638
0
       function );
2639
2640
0
      goto on_error;
2641
0
    }
2642
55.0k
  }
2643
50.1k
  else
2644
50.1k
  {
2645
50.1k
    if( libcdata_tree_node_set_nodes(
2646
50.1k
         node_to_insert,
2647
50.1k
         (libcdata_tree_node_t *) internal_node,
2648
50.1k
         previous_node,
2649
50.1k
         sub_node,
2650
50.1k
         error ) != 1 )
2651
0
    {
2652
0
      libcerror_error_set(
2653
0
       error,
2654
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2655
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2656
0
       "%s: unable to set parent, previous and next node of node to insert.",
2657
0
       function );
2658
2659
0
      goto on_error;
2660
0
    }
2661
50.1k
    if( internal_node->first_sub_node == sub_node )
2662
5.18k
    {
2663
5.18k
      internal_node->first_sub_node = node_to_insert;
2664
5.18k
    }
2665
45.0k
    else
2666
45.0k
    {
2667
45.0k
      if( libcdata_tree_node_set_next_node(
2668
45.0k
           previous_node,
2669
45.0k
           node_to_insert,
2670
45.0k
           error ) != 1 )
2671
0
      {
2672
0
        libcerror_error_set(
2673
0
         error,
2674
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2675
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2676
0
         "%s: unable to set next node of previous node.",
2677
0
         function );
2678
2679
0
        goto on_error;
2680
0
      }
2681
45.0k
    }
2682
50.1k
    if( libcdata_tree_node_set_previous_node(
2683
50.1k
         sub_node,
2684
50.1k
         node_to_insert,
2685
50.1k
         error ) != 1 )
2686
0
    {
2687
0
      libcerror_error_set(
2688
0
       error,
2689
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2690
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2691
0
       "%s: unable to set previous node of sub node.",
2692
0
       function );
2693
2694
0
      goto on_error;
2695
0
    }
2696
50.1k
  }
2697
119k
  if( libcdata_tree_node_set_parent_node(
2698
119k
       node_to_insert,
2699
119k
       (libcdata_tree_node_t *) internal_node,
2700
119k
       error ) != 1 )
2701
0
  {
2702
0
    libcerror_error_set(
2703
0
     error,
2704
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2705
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2706
0
     "%s: unable to set parent node of node to insert.",
2707
0
     function );
2708
2709
0
    goto on_error;
2710
0
  }
2711
119k
  internal_node->number_of_sub_nodes += 1;
2712
2713
119k
  return( 1 );
2714
2715
0
on_error:
2716
0
  if( node_to_insert != NULL )
2717
0
  {
2718
0
    libcdata_tree_node_set_nodes(
2719
0
     node_to_insert,
2720
0
     NULL,
2721
0
     NULL,
2722
0
     NULL,
2723
0
     NULL );
2724
0
  }
2725
0
  if( previous_node != NULL )
2726
0
  {
2727
0
    libcdata_tree_node_set_next_node(
2728
0
     previous_node,
2729
0
     sub_node,
2730
0
     NULL );
2731
0
  }
2732
0
  if( sub_node != NULL )
2733
0
  {
2734
0
    libcdata_tree_node_set_previous_node(
2735
0
     sub_node,
2736
0
     previous_node,
2737
0
     NULL );
2738
0
  }
2739
0
  internal_node->first_sub_node = backup_first_sub_node;
2740
0
  internal_node->last_sub_node  = backup_last_sub_node;
2741
2742
0
  return( -1 );
2743
119k
}
2744
2745
/* Inserts a sub node in the node
2746
 *
2747
 * Uses the value_compare_function to determine the order of the entries
2748
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2749
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2750
 *
2751
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2752
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2753
 *
2754
 * Returns 1 if successful, 0 if the node already exists or -1 on error
2755
 */
2756
int libcdata_tree_node_insert_node(
2757
     libcdata_tree_node_t *node,
2758
     libcdata_tree_node_t *node_to_insert,
2759
     int (*value_compare_function)(
2760
            intptr_t *first_value,
2761
            intptr_t *second_value,
2762
            libcerror_error_t **error ),
2763
     uint8_t insert_flags,
2764
     libcerror_error_t **error )
2765
520k
{
2766
520k
  libcdata_internal_tree_node_t *internal_node = NULL;
2767
520k
  libcdata_tree_node_t *next_node              = NULL;
2768
520k
  libcdata_tree_node_t *parent_node            = NULL;
2769
520k
  libcdata_tree_node_t *previous_node          = NULL;
2770
520k
  libcdata_tree_node_t *sub_node               = NULL;
2771
520k
  intptr_t *value_to_insert                    = NULL;
2772
520k
  static char *function                        = "libcdata_tree_node_insert_node";
2773
520k
  int result                                   = 1;
2774
520k
  int sub_node_index                           = 0;
2775
2776
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2777
  libcdata_tree_node_t *backup_first_sub_node  = NULL;
2778
  libcdata_tree_node_t *backup_last_sub_node   = NULL;
2779
#endif
2780
2781
520k
  if( node == NULL )
2782
20
  {
2783
20
    libcerror_error_set(
2784
20
     error,
2785
20
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2786
20
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2787
20
     "%s: invalid node.",
2788
20
     function );
2789
2790
20
    return( -1 );
2791
20
  }
2792
520k
  internal_node = (libcdata_internal_tree_node_t *) node;
2793
2794
520k
  if( internal_node->number_of_sub_nodes == 0 )
2795
14.6k
  {
2796
14.6k
    if( internal_node->first_sub_node != NULL )
2797
0
    {
2798
0
      libcerror_error_set(
2799
0
       error,
2800
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2801
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2802
0
       "%s: corruption detected - first sub node already set.",
2803
0
       function );
2804
2805
0
      return( -1 );
2806
0
    }
2807
14.6k
    if( internal_node->last_sub_node != NULL )
2808
0
    {
2809
0
      libcerror_error_set(
2810
0
       error,
2811
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2812
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2813
0
       "%s: corruption detected - last sub node already set.",
2814
0
       function );
2815
2816
0
      return( -1 );
2817
0
    }
2818
14.6k
  }
2819
506k
  else
2820
506k
  {
2821
506k
    if( internal_node->first_sub_node == NULL )
2822
0
    {
2823
0
      libcerror_error_set(
2824
0
       error,
2825
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2826
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2827
0
       "%s: corruption detected - missing first sub node.",
2828
0
       function );
2829
2830
0
      return( -1 );
2831
0
    }
2832
506k
    if( internal_node->last_sub_node == NULL )
2833
0
    {
2834
0
      libcerror_error_set(
2835
0
       error,
2836
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2837
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2838
0
       "%s: corruption detected - missing last sub node.",
2839
0
       function );
2840
2841
0
      return( -1 );
2842
0
    }
2843
506k
  }
2844
520k
  if( node_to_insert == NULL )
2845
0
  {
2846
0
    libcerror_error_set(
2847
0
     error,
2848
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2849
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2850
0
     "%s: invalid node to insert.",
2851
0
     function );
2852
2853
0
    return( -1 );
2854
0
  }
2855
520k
  if( value_compare_function == NULL )
2856
0
  {
2857
0
    libcerror_error_set(
2858
0
     error,
2859
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2860
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2861
0
     "%s: invalid value compare function.",
2862
0
     function );
2863
2864
0
    return( -1 );
2865
0
  }
2866
520k
  if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
2867
0
  {
2868
0
    libcerror_error_set(
2869
0
     error,
2870
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2871
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2872
0
     "%s: unsupported insert flags: 0x%02" PRIx8 ".",
2873
0
     function,
2874
0
     insert_flags );
2875
2876
0
    return( -1 );
2877
0
  }
2878
520k
  if( libcdata_tree_node_get_nodes(
2879
520k
       node_to_insert,
2880
520k
       &parent_node,
2881
520k
       &previous_node,
2882
520k
       &next_node,
2883
520k
       error ) != 1 )
2884
0
  {
2885
0
    libcerror_error_set(
2886
0
     error,
2887
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2888
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2889
0
     "%s: unable to retrieve nodes of node to insert.",
2890
0
     function );
2891
2892
0
    return( -1 );
2893
0
  }
2894
520k
  if( ( parent_node != NULL )
2895
520k
   || ( previous_node != NULL )
2896
520k
   || ( next_node != NULL ) )
2897
0
  {
2898
0
    libcerror_error_set(
2899
0
     error,
2900
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2901
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2902
0
     "%s: invalid node to insert - node is already part of a tree.",
2903
0
     function );
2904
2905
0
    return( -1 );
2906
0
  }
2907
520k
  if( libcdata_tree_node_get_value(
2908
520k
       node_to_insert,
2909
520k
       &value_to_insert,
2910
520k
       error ) != 1 )
2911
0
  {
2912
0
    libcerror_error_set(
2913
0
     error,
2914
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2915
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2916
0
     "%s: unable to retrieve value from node to insert.",
2917
0
     function );
2918
2919
0
    return( -1 );
2920
0
  }
2921
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2922
  if( libcthreads_read_write_lock_grab_for_write(
2923
       internal_node->read_write_lock,
2924
       error ) != 1 )
2925
  {
2926
    libcerror_error_set(
2927
     error,
2928
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2929
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2930
     "%s: unable to grab read/write lock for writing.",
2931
     function );
2932
2933
    return( -1 );
2934
  }
2935
  backup_first_sub_node = internal_node->first_sub_node;
2936
  backup_last_sub_node  = internal_node->last_sub_node;
2937
#endif
2938
2939
520k
  result = libcdata_internal_tree_node_insert_node_find_sub_node(
2940
520k
            internal_node,
2941
520k
            value_to_insert,
2942
520k
            value_compare_function,
2943
520k
            insert_flags,
2944
520k
            &sub_node_index,
2945
520k
            &sub_node,
2946
520k
            error );
2947
2948
520k
  if( result == -1 )
2949
0
  {
2950
0
    libcerror_error_set(
2951
0
     error,
2952
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2953
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2954
0
     "%s: unable to find sub node in tree node.",
2955
0
     function );
2956
2957
0
    result = -1;
2958
0
  }
2959
520k
  else if( result == 1 )
2960
119k
  {
2961
119k
    if( sub_node != NULL )
2962
50.1k
    {
2963
50.1k
      if( libcdata_tree_node_get_nodes(
2964
50.1k
           sub_node,
2965
50.1k
           &parent_node,
2966
50.1k
           &previous_node,
2967
50.1k
           &next_node,
2968
50.1k
           error ) != 1 )
2969
0
      {
2970
0
        libcerror_error_set(
2971
0
         error,
2972
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2973
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2974
0
         "%s: unable to retrieve nodes of sub node: %d.",
2975
0
         function,
2976
0
         sub_node_index );
2977
2978
0
        result = -1;
2979
0
      }
2980
50.1k
    }
2981
119k
    if( result == 1 )
2982
119k
    {
2983
119k
      if( libcdata_internal_tree_node_insert_node_before_sub_node(
2984
119k
           internal_node,
2985
119k
           sub_node,
2986
119k
           node_to_insert,
2987
119k
           error ) != 1 )
2988
0
      {
2989
0
        libcerror_error_set(
2990
0
         error,
2991
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2992
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2993
0
         "%s: unable to insert node before tree sub node.",
2994
0
         function );
2995
2996
0
        result = -1;
2997
0
      }
2998
119k
    }
2999
119k
  }
3000
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3001
  if( libcthreads_read_write_lock_release_for_write(
3002
       internal_node->read_write_lock,
3003
       error ) != 1 )
3004
  {
3005
    libcerror_error_set(
3006
     error,
3007
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3008
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3009
     "%s: unable to release read/write lock for writing.",
3010
     function );
3011
3012
    goto on_error;
3013
  }
3014
#endif
3015
520k
  return( result );
3016
3017
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3018
on_error:
3019
  if( result == 1 )
3020
  {
3021
    if( node_to_insert != NULL )
3022
    {
3023
      libcdata_tree_node_set_nodes(
3024
       node_to_insert,
3025
       NULL,
3026
       NULL,
3027
       NULL,
3028
       NULL );
3029
    }
3030
    if( previous_node != NULL )
3031
    {
3032
      libcdata_tree_node_set_next_node(
3033
       previous_node,
3034
       sub_node,
3035
       NULL );
3036
    }
3037
    if( sub_node != NULL )
3038
    {
3039
      libcdata_tree_node_set_previous_node(
3040
       sub_node,
3041
       previous_node,
3042
       NULL );
3043
    }
3044
    internal_node->first_sub_node = backup_first_sub_node;
3045
    internal_node->last_sub_node  = backup_last_sub_node;
3046
3047
    internal_node->number_of_sub_nodes -= 1;
3048
  }
3049
  return( -1 );
3050
#endif
3051
520k
}
3052
3053
/* Inserts a value in the node
3054
 *
3055
 * Creates a new sub tree node
3056
 *
3057
 * Uses the value_compare_function to determine the order of the entries
3058
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
3059
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
3060
 *
3061
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
3062
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
3063
 *
3064
 * Returns 1 if successful, 0 if the node already exists or -1 on error
3065
 */
3066
int libcdata_tree_node_insert_value(
3067
     libcdata_tree_node_t *node,
3068
     intptr_t *value,
3069
     int (*value_compare_function)(
3070
            intptr_t *first_value,
3071
            intptr_t *second_value,
3072
            libcerror_error_t **error ),
3073
     uint8_t insert_flags,
3074
     libcerror_error_t **error )
3075
481k
{
3076
481k
  libcdata_tree_node_t *sub_node = NULL;
3077
481k
  static char *function          = "libcdata_tree_node_insert_value";
3078
481k
  int result                     = 0;
3079
3080
481k
  if( node == NULL )
3081
0
  {
3082
0
    libcerror_error_set(
3083
0
     error,
3084
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3085
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3086
0
     "%s: invalid node.",
3087
0
     function );
3088
3089
0
    return( -1 );
3090
0
  }
3091
481k
  if( libcdata_tree_node_initialize(
3092
481k
       &sub_node,
3093
481k
       error ) != 1 )
3094
0
  {
3095
0
    libcerror_error_set(
3096
0
     error,
3097
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3098
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3099
0
     "%s: unable to create sub node.",
3100
0
     function );
3101
3102
0
    goto on_error;
3103
0
  }
3104
481k
  if( libcdata_tree_node_set_value(
3105
481k
       sub_node,
3106
481k
       value,
3107
481k
       error ) != 1 )
3108
0
  {
3109
0
    libcerror_error_set(
3110
0
     error,
3111
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
3112
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
3113
0
     "%s: unable to set value in sub node.",
3114
0
     function );
3115
3116
0
    goto on_error;
3117
0
  }
3118
481k
  result = libcdata_tree_node_insert_node(
3119
481k
            node,
3120
481k
            sub_node,
3121
481k
            value_compare_function,
3122
481k
            insert_flags,
3123
481k
            error );
3124
3125
481k
  if( result == -1 )
3126
0
  {
3127
0
    libcerror_error_set(
3128
0
     error,
3129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3130
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
3131
0
     "%s: unable to insert node.",
3132
0
     function );
3133
3134
0
    goto on_error;
3135
0
  }
3136
481k
  else if( result == 0 )
3137
390k
  {
3138
390k
    if( libcdata_tree_node_free(
3139
390k
         &sub_node,
3140
390k
         NULL,
3141
390k
         error ) != 1 )
3142
0
    {
3143
0
      libcerror_error_set(
3144
0
       error,
3145
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3146
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3147
0
       "%s: unable to free sub node.",
3148
0
       function );
3149
3150
0
      goto on_error;
3151
0
    }
3152
390k
  }
3153
481k
  return( result );
3154
3155
0
on_error:
3156
0
  if( sub_node != NULL )
3157
0
  {
3158
0
    libcdata_tree_node_free(
3159
0
     &sub_node,
3160
0
     NULL,
3161
0
     NULL );
3162
0
  }
3163
0
  return( -1 );
3164
481k
}
3165
3166
/* Replaces a tree node with another tree node
3167
 * Returns 1 if successful or -1 on error
3168
 */
3169
int libcdata_tree_node_replace_node(
3170
     libcdata_tree_node_t *node,
3171
     libcdata_tree_node_t *replacement_node,
3172
     libcerror_error_t **error )
3173
0
{
3174
0
  libcdata_internal_tree_node_t *internal_node       = NULL;
3175
0
  libcdata_tree_node_t *backup_parent_first_sub_node = NULL;
3176
0
  libcdata_tree_node_t *backup_parent_last_sub_node  = NULL;
3177
0
  libcdata_tree_node_t *next_node                    = NULL;
3178
0
  libcdata_tree_node_t *parent_first_sub_node        = NULL;
3179
0
  libcdata_tree_node_t *parent_last_sub_node         = NULL;
3180
0
  libcdata_tree_node_t *parent_node                  = NULL;
3181
0
  libcdata_tree_node_t *previous_node                = NULL;
3182
0
  libcdata_tree_node_t *replacement_next_node        = NULL;
3183
0
  libcdata_tree_node_t *replacement_parent_node      = NULL;
3184
0
  libcdata_tree_node_t *replacement_previous_node    = NULL;
3185
0
  static char *function                              = "libcdata_tree_node_replace_node";
3186
0
  int result                                         = 1;
3187
3188
0
  if( node == NULL )
3189
0
  {
3190
0
    libcerror_error_set(
3191
0
     error,
3192
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3193
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3194
0
     "%s: invalid node.",
3195
0
     function );
3196
3197
0
    return( -1 );
3198
0
  }
3199
0
  internal_node = (libcdata_internal_tree_node_t *) node;
3200
3201
0
  if( replacement_node == NULL )
3202
0
  {
3203
0
    libcerror_error_set(
3204
0
     error,
3205
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3206
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3207
0
     "%s: invalid replacement node.",
3208
0
     function );
3209
3210
0
    return( -1 );
3211
0
  }
3212
0
  if( replacement_node == node )
3213
0
  {
3214
0
    libcerror_error_set(
3215
0
     error,
3216
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3217
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3218
0
     "%s: cannot replace node with itself.",
3219
0
     function );
3220
3221
0
    return( -1 );
3222
0
  }
3223
0
  if( libcdata_tree_node_get_nodes(
3224
0
       replacement_node,
3225
0
       &replacement_parent_node,
3226
0
       &replacement_previous_node,
3227
0
       &replacement_next_node,
3228
0
       error ) != 1 )
3229
0
  {
3230
0
    libcerror_error_set(
3231
0
     error,
3232
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3233
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3234
0
     "%s: unable to retrieve nodes of replacement node.",
3235
0
     function );
3236
3237
0
    return( -1 );
3238
0
  }
3239
0
  if( ( replacement_parent_node != NULL )
3240
0
   || ( replacement_previous_node != NULL )
3241
0
   || ( replacement_next_node != NULL ) )
3242
0
  {
3243
0
    libcerror_error_set(
3244
0
     error,
3245
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3246
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3247
0
     "%s: invalid replacement node - already part of a tree.",
3248
0
     function );
3249
3250
0
    return( -1 );
3251
0
  }
3252
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3253
  if( libcthreads_read_write_lock_grab_for_write(
3254
       internal_node->read_write_lock,
3255
       error ) != 1 )
3256
  {
3257
    libcerror_error_set(
3258
     error,
3259
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3260
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3261
     "%s: unable to grab read/write lock for writing.",
3262
     function );
3263
3264
    return( -1 );
3265
  }
3266
#endif
3267
0
  parent_node   = internal_node->parent_node;
3268
0
  previous_node = internal_node->previous_node;
3269
0
  next_node     = internal_node->next_node;
3270
3271
0
  if( parent_node != NULL )
3272
0
  {
3273
0
    if( libcdata_tree_node_get_sub_nodes(
3274
0
         parent_node,
3275
0
         &parent_first_sub_node,
3276
0
         &parent_last_sub_node,
3277
0
         error ) != 1 )
3278
0
    {
3279
0
      libcerror_error_set(
3280
0
       error,
3281
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3282
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3283
0
       "%s: unable to retrieve sub nodes of parent node.",
3284
0
       function );
3285
3286
0
      result = -1;
3287
0
    }
3288
0
  }
3289
0
  if( result == 1 )
3290
0
  {
3291
0
    if( libcdata_tree_node_set_nodes(
3292
0
         replacement_node,
3293
0
         parent_node,
3294
0
         previous_node,
3295
0
         next_node,
3296
0
         error ) != 1 )
3297
0
    {
3298
0
      libcerror_error_set(
3299
0
       error,
3300
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3301
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3302
0
       "%s: unable to set nodes of replacement node.",
3303
0
       function );
3304
3305
0
      result = -1;
3306
0
    }
3307
0
  }
3308
0
  if( result == 1 )
3309
0
  {
3310
0
    if( parent_node != NULL )
3311
0
    {
3312
0
      backup_parent_first_sub_node = parent_first_sub_node;
3313
0
      backup_parent_last_sub_node  = parent_last_sub_node;
3314
3315
0
      if( parent_first_sub_node == node )
3316
0
      {
3317
0
        parent_first_sub_node = replacement_node;
3318
0
      }
3319
0
      if( parent_last_sub_node == node )
3320
0
      {
3321
0
        parent_last_sub_node = replacement_node;
3322
0
      }
3323
0
      if( libcdata_tree_node_set_sub_nodes(
3324
0
           parent_node,
3325
0
           parent_first_sub_node,
3326
0
           parent_last_sub_node,
3327
0
           error ) != 1 )
3328
0
      {
3329
0
        libcerror_error_set(
3330
0
         error,
3331
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3332
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3333
0
         "%s: unable to set sub nodes of parent node.",
3334
0
         function );
3335
3336
0
        libcdata_tree_node_set_nodes(
3337
0
         replacement_node,
3338
0
         NULL,
3339
0
         NULL,
3340
0
         NULL,
3341
0
         NULL );
3342
3343
0
        result = -1;
3344
0
      }
3345
0
    }
3346
0
  }
3347
0
  if( result == 1 )
3348
0
  {
3349
0
    if( previous_node != NULL )
3350
0
    {
3351
0
      if( libcdata_tree_node_set_next_node(
3352
0
           previous_node,
3353
0
           replacement_node,
3354
0
           error ) != 1 )
3355
0
      {
3356
0
        libcerror_error_set(
3357
0
         error,
3358
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3359
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3360
0
         "%s: unable to set next node of previous node.",
3361
0
         function );
3362
3363
0
        libcdata_tree_node_set_nodes(
3364
0
         replacement_node,
3365
0
         NULL,
3366
0
         NULL,
3367
0
         NULL,
3368
0
         NULL );
3369
3370
0
        if( parent_node != NULL )
3371
0
        {
3372
0
          libcdata_tree_node_set_sub_nodes(
3373
0
           parent_node,
3374
0
           backup_parent_first_sub_node,
3375
0
           backup_parent_last_sub_node,
3376
0
           NULL );
3377
0
        }
3378
0
        result = -1;
3379
0
      }
3380
0
    }
3381
0
  }
3382
0
  if( result == 1 )
3383
0
  {
3384
0
    if( next_node != NULL )
3385
0
    {
3386
0
      if( libcdata_tree_node_set_previous_node(
3387
0
           next_node,
3388
0
           replacement_node,
3389
0
           error ) != 1 )
3390
0
      {
3391
0
        libcerror_error_set(
3392
0
         error,
3393
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3394
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3395
0
         "%s: unable to set previous node of next node.",
3396
0
         function );
3397
3398
0
        libcdata_tree_node_set_nodes(
3399
0
         replacement_node,
3400
0
         NULL,
3401
0
         NULL,
3402
0
         NULL,
3403
0
         NULL );
3404
3405
0
        if( parent_node != NULL )
3406
0
        {
3407
0
          libcdata_tree_node_set_sub_nodes(
3408
0
           parent_node,
3409
0
           backup_parent_first_sub_node,
3410
0
           backup_parent_last_sub_node,
3411
0
           NULL );
3412
0
        }
3413
0
        if( previous_node != NULL )
3414
0
        {
3415
0
          libcdata_tree_node_set_next_node(
3416
0
           previous_node,
3417
0
           node,
3418
0
           NULL );
3419
0
        }
3420
0
        result = -1;
3421
0
      }
3422
0
    }
3423
0
  }
3424
0
  if( result == 1 )
3425
0
  {
3426
0
    internal_node->parent_node   = NULL;
3427
0
    internal_node->previous_node = NULL;
3428
0
    internal_node->next_node     = NULL;
3429
0
  }
3430
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3431
  if( libcthreads_read_write_lock_release_for_write(
3432
       internal_node->read_write_lock,
3433
       error ) != 1 )
3434
  {
3435
    libcerror_error_set(
3436
     error,
3437
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3438
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3439
     "%s: unable to release read/write lock for writing.",
3440
     function );
3441
3442
    goto on_error;
3443
  }
3444
#endif
3445
0
  return( result );
3446
3447
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3448
on_error:
3449
  if( result == 1 )
3450
  {
3451
    libcdata_tree_node_set_nodes(
3452
     replacement_node,
3453
     NULL,
3454
     NULL,
3455
     NULL,
3456
     NULL );
3457
3458
    if( parent_node != NULL )
3459
    {
3460
      libcdata_tree_node_set_sub_nodes(
3461
       parent_node,
3462
       backup_parent_first_sub_node,
3463
       backup_parent_last_sub_node,
3464
       NULL );
3465
    }
3466
    if( previous_node != NULL )
3467
    {
3468
      libcdata_tree_node_set_next_node(
3469
       previous_node,
3470
       node,
3471
       NULL );
3472
    }
3473
    if( next_node != NULL )
3474
    {
3475
      libcdata_tree_node_set_previous_node(
3476
       next_node,
3477
       node,
3478
       NULL );
3479
    }
3480
    internal_node->parent_node   = parent_node;
3481
    internal_node->previous_node = previous_node;
3482
    internal_node->next_node     = next_node;
3483
  }
3484
  return( -1 );
3485
#endif
3486
0
}
3487
3488
/* Removes a sub tree node from the tree node
3489
 * Returns 1 if successful or -1 on error
3490
 */
3491
int libcdata_tree_node_remove_node(
3492
     libcdata_tree_node_t *node,
3493
     libcdata_tree_node_t *sub_node_to_remove,
3494
     libcerror_error_t **error )
3495
0
{
3496
0
  libcdata_internal_tree_node_t *internal_node = NULL;
3497
0
  libcdata_tree_node_t *next_node              = NULL;
3498
0
  libcdata_tree_node_t *parent_node            = NULL;
3499
0
  libcdata_tree_node_t *previous_node          = NULL;
3500
0
  static char *function                        = "libcdata_tree_node_remove_node";
3501
0
  int result                                   = 1;
3502
3503
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3504
  libcdata_tree_node_t *backup_first_sub_node  = NULL;
3505
  libcdata_tree_node_t *backup_last_sub_node   = NULL;
3506
#endif
3507
3508
0
  if( node == NULL )
3509
0
  {
3510
0
    libcerror_error_set(
3511
0
     error,
3512
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3513
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3514
0
     "%s: invalid node.",
3515
0
     function );
3516
3517
0
    return( -1 );
3518
0
  }
3519
0
  internal_node = (libcdata_internal_tree_node_t *) node;
3520
3521
0
  if( internal_node->number_of_sub_nodes == 0 )
3522
0
  {
3523
0
    if( internal_node->first_sub_node != NULL )
3524
0
    {
3525
0
      libcerror_error_set(
3526
0
       error,
3527
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3528
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3529
0
       "%s: corruption detected - first sub node already set.",
3530
0
       function );
3531
3532
0
      return( -1 );
3533
0
    }
3534
0
    if( internal_node->last_sub_node != NULL )
3535
0
    {
3536
0
      libcerror_error_set(
3537
0
       error,
3538
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3539
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3540
0
       "%s: corruption detected - last sub node already set.",
3541
0
       function );
3542
3543
0
      return( -1 );
3544
0
    }
3545
0
  }
3546
0
  else
3547
0
  {
3548
0
    if( internal_node->first_sub_node == NULL )
3549
0
    {
3550
0
      libcerror_error_set(
3551
0
       error,
3552
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3553
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3554
0
       "%s: corruption detected - missing first sub node.",
3555
0
       function );
3556
3557
0
      return( -1 );
3558
0
    }
3559
0
    if( internal_node->last_sub_node == NULL )
3560
0
    {
3561
0
      libcerror_error_set(
3562
0
       error,
3563
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3564
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3565
0
       "%s: corruption detected - missing last sub node.",
3566
0
       function );
3567
3568
0
      return( -1 );
3569
0
    }
3570
0
  }
3571
0
  if( sub_node_to_remove == NULL )
3572
0
  {
3573
0
    libcerror_error_set(
3574
0
     error,
3575
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3576
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3577
0
     "%s: invalid sub node to remove.",
3578
0
     function );
3579
3580
0
    return( -1 );
3581
0
  }
3582
0
  if( internal_node->number_of_sub_nodes == 0 )
3583
0
  {
3584
0
    libcerror_error_set(
3585
0
     error,
3586
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3587
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3588
0
     "%s: invalid node - missing number of sub nodes.",
3589
0
     function );
3590
3591
0
    return( -1 );
3592
0
  }
3593
0
  if( internal_node->first_sub_node == NULL )
3594
0
  {
3595
0
    libcerror_error_set(
3596
0
     error,
3597
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3598
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3599
0
     "%s: invalid node - missing first sub node.",
3600
0
     function );
3601
3602
0
    return( -1 );
3603
0
  }
3604
0
  if( internal_node->last_sub_node == NULL )
3605
0
  {
3606
0
    libcerror_error_set(
3607
0
     error,
3608
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3609
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3610
0
     "%s: invalid node - missing last sub node.",
3611
0
     function );
3612
3613
0
    return( -1 );
3614
0
  }
3615
0
  if( libcdata_tree_node_get_nodes(
3616
0
       sub_node_to_remove,
3617
0
       &parent_node,
3618
0
       &previous_node,
3619
0
       &next_node,
3620
0
       error ) != 1 )
3621
0
  {
3622
0
    libcerror_error_set(
3623
0
     error,
3624
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3625
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3626
0
     "%s: unable to retrieve nodes of node to remove.",
3627
0
     function );
3628
3629
0
    return( -1 );
3630
0
  }
3631
0
  if( parent_node != node )
3632
0
  {
3633
0
    libcerror_error_set(
3634
0
     error,
3635
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3636
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3637
0
     "%s: invalid node to remove - parent node mismatch.",
3638
0
     function );
3639
3640
0
    return( -1 );
3641
0
  }
3642
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3643
  if( libcthreads_read_write_lock_grab_for_write(
3644
       internal_node->read_write_lock,
3645
       error ) != 1 )
3646
  {
3647
    libcerror_error_set(
3648
     error,
3649
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3650
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3651
     "%s: unable to grab read/write lock for writing.",
3652
     function );
3653
3654
    return( -1 );
3655
  }
3656
  backup_first_sub_node = internal_node->first_sub_node;
3657
  backup_last_sub_node  = internal_node->last_sub_node;
3658
#endif
3659
0
  result = libcdata_tree_node_set_nodes(
3660
0
            sub_node_to_remove,
3661
0
            NULL,
3662
0
            NULL,
3663
0
            NULL,
3664
0
            error );
3665
3666
0
  if( result != 1 )
3667
0
  {
3668
0
    libcerror_error_set(
3669
0
     error,
3670
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3671
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3672
0
     "%s: unable to set nodes of node to remove.",
3673
0
     function );
3674
3675
0
    result = -1;
3676
0
  }
3677
0
  if( result == 1 )
3678
0
  {
3679
0
    if( next_node != NULL )
3680
0
    {
3681
0
      if( libcdata_tree_node_set_previous_node(
3682
0
           next_node,
3683
0
           previous_node,
3684
0
           error ) != 1 )
3685
0
      {
3686
0
        libcerror_error_set(
3687
0
         error,
3688
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3689
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3690
0
         "%s: unable to set previous node of next node.",
3691
0
         function );
3692
3693
0
        libcdata_tree_node_set_nodes(
3694
0
         sub_node_to_remove,
3695
0
         parent_node,
3696
0
         previous_node,
3697
0
         next_node,
3698
0
         NULL );
3699
3700
0
        result = -1;
3701
0
      }
3702
0
    }
3703
0
  }
3704
0
  if( result == 1 )
3705
0
  {
3706
0
    if( previous_node != NULL )
3707
0
    {
3708
0
      if( libcdata_tree_node_set_next_node(
3709
0
           previous_node,
3710
0
           next_node,
3711
0
           error ) != 1 )
3712
0
      {
3713
0
        libcerror_error_set(
3714
0
         error,
3715
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3716
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3717
0
         "%s: unable to set next node of previous node.",
3718
0
         function );
3719
3720
0
        libcdata_tree_node_set_nodes(
3721
0
         sub_node_to_remove,
3722
0
         parent_node,
3723
0
         previous_node,
3724
0
         next_node,
3725
0
         NULL );
3726
3727
0
        if( next_node != NULL )
3728
0
        {
3729
0
          libcdata_tree_node_set_previous_node(
3730
0
           next_node,
3731
0
           sub_node_to_remove,
3732
0
           NULL );
3733
0
        }
3734
0
        result = -1;
3735
0
      }
3736
0
    }
3737
0
  }
3738
0
  if( result == 1 )
3739
0
  {
3740
0
    if( internal_node->first_sub_node == sub_node_to_remove )
3741
0
    {
3742
0
      internal_node->first_sub_node = next_node;
3743
0
    }
3744
0
    if( internal_node->last_sub_node == sub_node_to_remove )
3745
0
    {
3746
0
      internal_node->last_sub_node = previous_node;
3747
0
    }
3748
0
    internal_node->number_of_sub_nodes -= 1;
3749
0
  }
3750
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3751
  if( libcthreads_read_write_lock_release_for_write(
3752
       internal_node->read_write_lock,
3753
       error ) != 1 )
3754
  {
3755
    libcerror_error_set(
3756
     error,
3757
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3758
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3759
     "%s: unable to release read/write lock for writing.",
3760
     function );
3761
3762
    goto on_error;
3763
  }
3764
#endif
3765
0
  return( 1 );
3766
3767
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3768
on_error:
3769
  if( result == 1 )
3770
  {
3771
    libcdata_tree_node_set_nodes(
3772
     sub_node_to_remove,
3773
     parent_node,
3774
     previous_node,
3775
     next_node,
3776
     NULL );
3777
3778
    if( next_node != NULL )
3779
    {
3780
      libcdata_tree_node_set_previous_node(
3781
       next_node,
3782
       sub_node_to_remove,
3783
       NULL );
3784
    }
3785
    if( previous_node != NULL )
3786
    {
3787
      libcdata_tree_node_set_next_node(
3788
       previous_node,
3789
       sub_node_to_remove,
3790
       NULL );
3791
    }
3792
    internal_node->first_sub_node = backup_first_sub_node;
3793
    internal_node->last_sub_node  = backup_last_sub_node;
3794
3795
    internal_node->number_of_sub_nodes += 1;
3796
  }
3797
  return( -1 );
3798
#endif
3799
0
}
3800
3801
/* Retrieves the number of sub nodes in the tree node
3802
 * Returns 1 if successful or -1 on error
3803
 */
3804
int libcdata_tree_node_get_number_of_sub_nodes(
3805
     libcdata_tree_node_t *node,
3806
     int *number_of_sub_nodes,
3807
     libcerror_error_t **error )
3808
8.25M
{
3809
8.25M
  libcdata_internal_tree_node_t *internal_node = NULL;
3810
8.25M
  static char *function                        = "libcdata_tree_node_get_number_of_sub_nodes";
3811
3812
8.25M
  if( node == NULL )
3813
0
  {
3814
0
    libcerror_error_set(
3815
0
     error,
3816
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3817
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3818
0
     "%s: invalid node.",
3819
0
     function );
3820
3821
0
    return( -1 );
3822
0
  }
3823
8.25M
  internal_node = (libcdata_internal_tree_node_t *) node;
3824
3825
8.25M
  if( number_of_sub_nodes == NULL )
3826
0
  {
3827
0
    libcerror_error_set(
3828
0
     error,
3829
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3830
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3831
0
     "%s: invalid number of sub nodes.",
3832
0
     function );
3833
3834
0
    return( -1 );
3835
0
  }
3836
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3837
  if( libcthreads_read_write_lock_grab_for_read(
3838
       internal_node->read_write_lock,
3839
       error ) != 1 )
3840
  {
3841
    libcerror_error_set(
3842
     error,
3843
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3844
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3845
     "%s: unable to grab read/write lock for reading.",
3846
     function );
3847
3848
    return( -1 );
3849
  }
3850
#endif
3851
8.25M
  *number_of_sub_nodes = internal_node->number_of_sub_nodes;
3852
3853
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3854
  if( libcthreads_read_write_lock_release_for_read(
3855
       internal_node->read_write_lock,
3856
       error ) != 1 )
3857
  {
3858
    libcerror_error_set(
3859
     error,
3860
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3861
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3862
     "%s: unable to release read/write lock for reading.",
3863
     function );
3864
3865
    return( -1 );
3866
  }
3867
#endif
3868
8.25M
  return( 1 );
3869
8.25M
}
3870
3871
/* Retrieves a specific sub node from the tree node
3872
 * Returns 1 if successful or -1 on error
3873
 */
3874
int libcdata_tree_node_get_sub_node_by_index(
3875
     libcdata_tree_node_t *node,
3876
     int sub_node_index,
3877
     libcdata_tree_node_t **sub_node,
3878
     libcerror_error_t **error )
3879
4.21M
{
3880
4.21M
  libcdata_internal_tree_node_t *internal_node = NULL;
3881
4.21M
  libcdata_tree_node_t *safe_sub_node          = NULL;
3882
4.21M
  static char *function                        = "libcdata_tree_node_get_sub_node_by_index";
3883
4.21M
  int result                                   = -1;
3884
4.21M
  int sub_node_iterator                        = 0;
3885
3886
4.21M
  if( node == NULL )
3887
0
  {
3888
0
    libcerror_error_set(
3889
0
     error,
3890
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3891
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3892
0
     "%s: invalid node.",
3893
0
     function );
3894
3895
0
    return( -1 );
3896
0
  }
3897
4.21M
  internal_node = (libcdata_internal_tree_node_t *) node;
3898
3899
4.21M
  if( ( sub_node_index < 0 )
3900
4.21M
   || ( sub_node_index >= internal_node->number_of_sub_nodes ) )
3901
30
  {
3902
30
    libcerror_error_set(
3903
30
     error,
3904
30
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3905
30
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3906
30
     "%s: invalid sub node index value out of bounds.",
3907
30
     function );
3908
3909
30
    return( -1 );
3910
30
  }
3911
4.21M
  if( sub_node == NULL )
3912
0
  {
3913
0
    libcerror_error_set(
3914
0
     error,
3915
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3916
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3917
0
     "%s: invalid sub node.",
3918
0
     function );
3919
3920
0
    return( -1 );
3921
0
  }
3922
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
3923
  if( libcthreads_read_write_lock_grab_for_read(
3924
       internal_node->read_write_lock,
3925
       error ) != 1 )
3926
  {
3927
    libcerror_error_set(
3928
     error,
3929
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3930
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3931
     "%s: unable to grab read/write lock for reading.",
3932
     function );
3933
3934
    return( -1 );
3935
  }
3936
#endif
3937
  /* Check if the sub nodes should be searched front to back
3938
   * or back to front
3939
   */
3940
4.21M
  if( sub_node_index < ( internal_node->number_of_sub_nodes / 2 ) )
3941
3.38M
  {
3942
3.38M
    safe_sub_node = internal_node->first_sub_node;
3943
3944
3.38M
    for( sub_node_iterator = 0;
3945
3.38M
         sub_node_iterator < internal_node->number_of_sub_nodes;
3946
3.38M
         sub_node_iterator++ )
3947
3.38M
    {
3948
3.38M
      if( sub_node_iterator == sub_node_index )
3949
3.38M
      {
3950
3.38M
        result = 1;
3951
3952
3.38M
        break;
3953
3.38M
      }
3954
0
      if( libcdata_tree_node_get_next_node(
3955
0
           safe_sub_node,
3956
0
           &safe_sub_node,
3957
0
           error ) != 1 )
3958
0
      {
3959
0
        libcerror_error_set(
3960
0
         error,
3961
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3962
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3963
0
         "%s: unable to retrieve next node of sub node: %d.",
3964
0
         function,
3965
0
         sub_node_iterator );
3966
3967
0
        goto on_error;
3968
0
      }
3969
0
    }
3970
3.38M
  }
3971
832k
  else
3972
832k
  {
3973
832k
    safe_sub_node = internal_node->last_sub_node;
3974
3975
832k
    for( sub_node_iterator = ( internal_node->number_of_sub_nodes - 1 );
3976
832k
         sub_node_iterator >= 0;
3977
832k
         sub_node_iterator-- )
3978
832k
    {
3979
832k
      if( sub_node_iterator == sub_node_index )
3980
832k
      {
3981
832k
        result = 1;
3982
3983
832k
        break;
3984
832k
      }
3985
0
      if( libcdata_tree_node_get_previous_node(
3986
0
           safe_sub_node,
3987
0
           &safe_sub_node,
3988
0
           error ) != 1 )
3989
0
      {
3990
0
        libcerror_error_set(
3991
0
         error,
3992
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
3993
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3994
0
         "%s: unable to retrieve previous node of sub node: %d.",
3995
0
         function,
3996
0
         sub_node_iterator );
3997
3998
0
        goto on_error;
3999
0
      }
4000
0
    }
4001
832k
  }
4002
4.21M
  *sub_node = safe_sub_node;
4003
4004
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
4005
  if( libcthreads_read_write_lock_release_for_read(
4006
       internal_node->read_write_lock,
4007
       error ) != 1 )
4008
  {
4009
    libcerror_error_set(
4010
     error,
4011
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4012
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4013
     "%s: unable to release read/write lock for reading.",
4014
     function );
4015
4016
    return( -1 );
4017
  }
4018
#endif
4019
4.21M
  return( result );
4020
4021
0
on_error:
4022
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
4023
  libcthreads_read_write_lock_release_for_read(
4024
   internal_node->read_write_lock,
4025
   NULL );
4026
#endif
4027
0
  return( -1 );
4028
4.21M
}
4029
4030
/* Retrieves a list of all the leaf nodes
4031
 * Returns 1 if successful or -1 on error
4032
 */
4033
int libcdata_tree_node_get_leaf_node_list(
4034
     libcdata_tree_node_t *node,
4035
     libcdata_list_t **leaf_node_list,
4036
     libcerror_error_t **error )
4037
0
{
4038
0
  libcdata_internal_tree_node_t *internal_node = NULL;
4039
0
  libcdata_tree_node_t *sub_node               = NULL;
4040
0
  static char *function                        = "libcdata_tree_node_get_leaf_node_list";
4041
0
  int leaf_node_list_created_in_node           = 0;
4042
0
  int sub_node_index                           = 0;
4043
4044
0
  if( node == NULL )
4045
0
  {
4046
0
    libcerror_error_set(
4047
0
     error,
4048
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4049
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4050
0
     "%s: invalid node.",
4051
0
     function );
4052
4053
0
    return( -1 );
4054
0
  }
4055
0
  internal_node = (libcdata_internal_tree_node_t *) node;
4056
4057
0
  if( leaf_node_list == NULL )
4058
0
  {
4059
0
    libcerror_error_set(
4060
0
     error,
4061
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4062
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4063
0
     "%s: invalid leaf node list.",
4064
0
     function );
4065
4066
0
    return( -1 );
4067
0
  }
4068
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
4069
  if( libcthreads_read_write_lock_grab_for_read(
4070
       internal_node->read_write_lock,
4071
       error ) != 1 )
4072
  {
4073
    libcerror_error_set(
4074
     error,
4075
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4076
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4077
     "%s: unable to grab read/write lock for reading.",
4078
     function );
4079
4080
    return( -1 );
4081
  }
4082
#endif
4083
0
  if( *leaf_node_list == NULL )
4084
0
  {
4085
0
    if( libcdata_list_initialize(
4086
0
         leaf_node_list,
4087
0
         error ) != 1 )
4088
0
    {
4089
0
      libcerror_error_set(
4090
0
       error,
4091
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4092
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4093
0
       "%s: unable to create leaf node list.",
4094
0
       function );
4095
4096
0
      goto on_error;
4097
0
    }
4098
0
    leaf_node_list_created_in_node = 1;
4099
0
  }
4100
  /* Traverse the sub nodes
4101
   */
4102
0
  if( internal_node->number_of_sub_nodes == 0 )
4103
0
  {
4104
0
    if( internal_node->value == NULL )
4105
0
    {
4106
0
      libcerror_error_set(
4107
0
       error,
4108
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4109
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4110
0
       "%s: invalid node - missing value.",
4111
0
       function );
4112
4113
0
      goto on_error;
4114
0
    }
4115
0
    if( libcdata_list_append_value(
4116
0
         *leaf_node_list,
4117
0
         internal_node->value,
4118
0
         error ) != 1 )
4119
0
    {
4120
0
      libcerror_error_set(
4121
0
       error,
4122
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
4123
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
4124
0
       "%s: unable to append tree node to leaf node list.",
4125
0
       function );
4126
4127
0
      goto on_error;
4128
0
    }
4129
0
  }
4130
0
  else
4131
0
  {
4132
0
    sub_node = internal_node->first_sub_node;
4133
4134
0
    for( sub_node_index = 0;
4135
0
         sub_node_index < internal_node->number_of_sub_nodes;
4136
0
         sub_node_index++ )
4137
0
    {
4138
0
      if( sub_node == NULL )
4139
0
      {
4140
0
        libcerror_error_set(
4141
0
         error,
4142
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4143
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4144
0
         "%s: corruption detected for sub node: %d.",
4145
0
         function,
4146
0
         sub_node_index );
4147
4148
0
        goto on_error;
4149
0
      }
4150
0
      if( libcdata_tree_node_get_leaf_node_list(
4151
0
           sub_node,
4152
0
           leaf_node_list,
4153
0
           error ) != 1 )
4154
0
      {
4155
0
        libcerror_error_set(
4156
0
         error,
4157
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4158
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4159
0
         "%s: unable to traverse sub node: %d.",
4160
0
         function,
4161
0
         sub_node_index );
4162
4163
0
        goto on_error;
4164
0
      }
4165
0
      if( libcdata_tree_node_get_next_node(
4166
0
           sub_node,
4167
0
           &sub_node,
4168
0
           error ) != 1 )
4169
0
      {
4170
0
        libcerror_error_set(
4171
0
         error,
4172
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
4173
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4174
0
         "%s: unable to retrieve next node of sub node: %d.",
4175
0
         function,
4176
0
         sub_node_index );
4177
4178
0
        goto on_error;
4179
0
      }
4180
0
    }
4181
0
  }
4182
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
4183
  if( libcthreads_read_write_lock_release_for_read(
4184
       internal_node->read_write_lock,
4185
       error ) != 1 )
4186
  {
4187
    libcerror_error_set(
4188
     error,
4189
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
4190
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4191
     "%s: unable to release read/write lock for reading.",
4192
     function );
4193
4194
    return( -1 );
4195
  }
4196
#endif
4197
0
  return( 1 );
4198
4199
0
on_error:
4200
0
  if( leaf_node_list_created_in_node != 0 )
4201
0
  {
4202
0
    if( *leaf_node_list == NULL )
4203
0
    {
4204
0
      libcdata_list_initialize(
4205
0
       leaf_node_list,
4206
0
       NULL );
4207
0
    }
4208
0
  }
4209
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
4210
  libcthreads_read_write_lock_release_for_read(
4211
   internal_node->read_write_lock,
4212
   NULL );
4213
#endif
4214
0
  return( -1 );
4215
0
}
4216