Coverage Report

Created: 2026-07-10 07:32

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