Coverage Report

Created: 2024-02-25 07:20

/src/libluksde/libcdata/libcdata_list.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * List functions
3
 *
4
 * Copyright (C) 2006-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libcdata_definitions.h"
27
#include "libcdata_libcerror.h"
28
#include "libcdata_libcthreads.h"
29
#include "libcdata_list.h"
30
#include "libcdata_list_element.h"
31
#include "libcdata_types.h"
32
33
/* Creates a list
34
 * Make sure the value list is referencing, is set to NULL
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libcdata_list_initialize(
38
     libcdata_list_t **list,
39
     libcerror_error_t **error )
40
323k
{
41
323k
  libcdata_internal_list_t *internal_list = NULL;
42
323k
  static char *function                   = "libcdata_list_initialize";
43
44
323k
  if( list == 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 list.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
323k
  if( *list != 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 list value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
323k
  internal_list = memory_allocate_structure(
67
323k
                   libcdata_internal_list_t );
68
69
323k
  if( internal_list == 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 list.",
76
0
     function );
77
78
0
    goto on_error;
79
0
  }
80
323k
  if( memory_set(
81
323k
       internal_list,
82
323k
       0,
83
323k
       sizeof( libcdata_internal_list_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 list.",
90
0
     function );
91
92
0
    memory_free(
93
0
     internal_list );
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_list->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
323k
  *list = (libcdata_list_t *) internal_list;
113
114
323k
  return( 1 );
115
116
0
on_error:
117
0
  if( internal_list != NULL )
118
0
  {
119
0
    memory_free(
120
0
     internal_list );
121
0
  }
122
0
  return( -1 );
123
323k
}
124
125
/* Frees a list including the elements
126
 * Uses the value_free_function to free the element value
127
 * Returns 1 if successful or -1 on error
128
 */
129
int libcdata_list_free(
130
     libcdata_list_t **list,
131
     int (*value_free_function)(
132
            intptr_t **value,
133
            libcerror_error_t **error ),
134
     libcerror_error_t **error )
135
323k
{
136
323k
  libcdata_internal_list_t *internal_list = NULL;
137
323k
  static char *function                   = "libcdata_list_free";
138
323k
  int result                              = 1;
139
140
323k
  if( list == 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 list.",
147
0
     function );
148
149
0
    return( -1 );
150
0
  }
151
323k
  if( *list != NULL )
152
323k
  {
153
323k
    internal_list = (libcdata_internal_list_t *) *list;
154
323k
    *list         = NULL;
155
156
323k
    if( libcdata_list_empty(
157
323k
         (libcdata_list_t*) internal_list,
158
323k
         value_free_function,
159
323k
         error ) != 1 )
160
0
    {
161
0
      libcerror_error_set(
162
0
       error,
163
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
164
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
165
0
       "%s: unable to empty list.",
166
0
       function );
167
168
0
      result = -1;
169
0
    }
170
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
171
    if( libcthreads_read_write_lock_free(
172
         &( internal_list->read_write_lock ),
173
         error ) != 1 )
174
    {
175
      libcerror_error_set(
176
       error,
177
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
178
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
179
       "%s: unable to free read/write lock.",
180
       function );
181
182
      result = -1;
183
    }
184
#endif
185
323k
    memory_free(
186
323k
     internal_list );
187
323k
  }
188
323k
  return( result );
189
323k
}
190
191
/* Empties a list and frees the elements
192
 * Uses the value_free_function to free the element value
193
 * Returns 1 if successful or -1 on error
194
 */
195
int libcdata_list_empty(
196
     libcdata_list_t *list,
197
     int (*value_free_function)(
198
            intptr_t **value,
199
            libcerror_error_t **error ),
200
     libcerror_error_t **error )
201
337k
{
202
337k
  libcdata_internal_list_t *internal_list = NULL;
203
337k
  libcdata_list_element_t *list_element   = NULL;
204
337k
  libcdata_list_element_t *next_element   = NULL;
205
337k
  static char *function                   = "libcdata_list_empty";
206
337k
  int element_index                       = 0;
207
337k
  int number_of_elements                  = 0;
208
337k
  int result                              = 1;
209
210
337k
  if( list == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
216
0
     "%s: invalid list.",
217
0
     function );
218
219
0
    return( -1 );
220
0
  }
221
337k
  internal_list = (libcdata_internal_list_t *) list;
222
223
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
224
  if( libcthreads_read_write_lock_grab_for_write(
225
       internal_list->read_write_lock,
226
       error ) != 1 )
227
  {
228
    libcerror_error_set(
229
     error,
230
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
231
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
232
     "%s: unable to grab read/write lock for writing.",
233
     function );
234
235
    return( -1 );
236
  }
237
#endif
238
337k
  if( internal_list->number_of_elements > 0 )
239
94.4k
  {
240
94.4k
    number_of_elements = internal_list->number_of_elements;
241
242
94.4k
    list_element = internal_list->first_element;
243
244
94.4k
    for( element_index = 0;
245
1.37M
         element_index < number_of_elements;
246
1.27M
         element_index++ )
247
1.27M
    {
248
1.27M
      if( libcdata_list_element_get_next_element(
249
1.27M
           list_element,
250
1.27M
           &next_element,
251
1.27M
           error ) != 1 )
252
0
      {
253
0
        libcerror_error_set(
254
0
         error,
255
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
257
0
         "%s: unable to retrieve next element from list element: %d.",
258
0
         function,
259
0
         element_index );
260
261
0
        result = -1;
262
263
0
        break;
264
0
      }
265
1.27M
      internal_list->first_element = next_element;
266
267
1.27M
      if( internal_list->last_element == list_element )
268
94.4k
      {
269
94.4k
        internal_list->last_element = next_element;
270
94.4k
      }
271
1.27M
      internal_list->number_of_elements -= 1;
272
273
1.27M
      if( next_element != NULL )
274
1.18M
      {
275
1.18M
        if( libcdata_list_element_set_previous_element(
276
1.18M
             next_element,
277
1.18M
             NULL,
278
1.18M
             error ) != 1 )
279
0
        {
280
0
          libcerror_error_set(
281
0
           error,
282
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
283
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
284
0
           "%s: unable to set previous element of list element: %d.",
285
0
           function,
286
0
           element_index + 1 );
287
288
0
          result = -1;
289
0
        }
290
1.18M
      }
291
1.27M
      if( libcdata_list_element_set_next_element(
292
1.27M
           list_element,
293
1.27M
           NULL,
294
1.27M
           error ) != 1 )
295
0
      {
296
0
        libcerror_error_set(
297
0
         error,
298
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
299
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
300
0
         "%s: unable to set next element of list element: %d.",
301
0
         function,
302
0
         element_index );
303
304
0
        result = -1;
305
0
      }
306
1.27M
      if( libcdata_list_element_free(
307
1.27M
           &list_element,
308
1.27M
           value_free_function,
309
1.27M
           error ) != 1 )
310
0
      {
311
0
        libcerror_error_set(
312
0
         error,
313
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
314
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
315
0
         "%s: unable to free list element: %d.",
316
0
         function,
317
0
         element_index );
318
319
0
        result = -1;
320
0
      }
321
1.27M
      list_element = next_element;
322
1.27M
    }
323
94.4k
  }
324
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
325
  if( libcthreads_read_write_lock_release_for_write(
326
       internal_list->read_write_lock,
327
       error ) != 1 )
328
  {
329
    libcerror_error_set(
330
     error,
331
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
332
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
333
     "%s: unable to release read/write lock for writing.",
334
     function );
335
336
    result = -1;
337
  }
338
#endif
339
337k
  return( result );
340
337k
}
341
342
/* Clones the list and its elements
343
 *
344
 * The values are cloned using the value_clone_function
345
 * On error the values are freed using the value_free_function
346
 *
347
 * Returns 1 if successful or -1 on error
348
 */
349
int libcdata_list_clone(
350
     libcdata_list_t **destination_list,
351
     libcdata_list_t *source_list,
352
     int (*value_free_function)(
353
            intptr_t **value,
354
            libcerror_error_t **error ),
355
     int (*value_clone_function)(
356
            intptr_t **destination_value,
357
            intptr_t *source_value,
358
            libcerror_error_t **error ),
359
     libcerror_error_t **error )
360
0
{
361
0
  libcdata_internal_list_t *internal_destination_list            = NULL;
362
0
  libcdata_internal_list_t *internal_source_list                 = NULL;
363
0
  libcdata_internal_list_element_t *internal_source_list_element = NULL;
364
0
  intptr_t *destination_value                                    = NULL;
365
0
  static char *function                                          = "libcdata_list_clone";
366
0
  int element_index                                              = 0;
367
368
0
  if( destination_list == NULL )
369
0
  {
370
0
    libcerror_error_set(
371
0
     error,
372
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
373
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
374
0
     "%s: invalid destination list.",
375
0
     function );
376
377
0
    return( -1 );
378
0
  }
379
0
  if( *destination_list != NULL )
380
0
  {
381
0
    libcerror_error_set(
382
0
     error,
383
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
384
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
385
0
     "%s: invalid destination list already set.",
386
0
     function );
387
388
0
    return( -1 );
389
0
  }
390
0
  if( value_free_function == NULL )
391
0
  {
392
0
    libcerror_error_set(
393
0
     error,
394
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
395
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
396
0
     "%s: invalid value free function.",
397
0
     function );
398
399
0
    return( -1 );
400
0
  }
401
0
  if( value_clone_function == NULL )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
406
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
407
0
     "%s: invalid value clone function.",
408
0
     function );
409
410
0
    return( -1 );
411
0
  }
412
0
  if( source_list == NULL )
413
0
  {
414
0
    *destination_list = NULL;
415
416
0
    return( 1 );
417
0
  }
418
0
  internal_source_list = (libcdata_internal_list_t *) source_list;
419
420
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
421
  if( libcthreads_read_write_lock_grab_for_read(
422
       internal_source_list->read_write_lock,
423
       error ) != 1 )
424
  {
425
    libcerror_error_set(
426
     error,
427
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
428
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
429
     "%s: unable to grab read/write lock for reading.",
430
     function );
431
432
    return( -1 );
433
  }
434
#endif
435
0
  if( libcdata_list_initialize(
436
0
       (libcdata_list_t **) &internal_destination_list,
437
0
       error ) != 1 )
438
0
  {
439
0
    libcerror_error_set(
440
0
     error,
441
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
442
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
443
0
     "%s: unable to create destination list.",
444
0
     function );
445
446
0
    goto on_error;
447
0
  }
448
0
  if( internal_destination_list == NULL )
449
0
  {
450
0
    libcerror_error_set(
451
0
     error,
452
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
453
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
454
0
     "%s: missing destination list.",
455
0
     function );
456
457
0
    goto on_error;
458
0
  }
459
0
  if( internal_source_list->first_element != NULL )
460
0
  {
461
0
    internal_source_list_element = (libcdata_internal_list_element_t *) internal_source_list->first_element;
462
463
0
    for( element_index = 0;
464
0
         element_index < internal_source_list->number_of_elements;
465
0
         element_index++ )
466
0
    {
467
0
      if( internal_source_list_element == NULL )
468
0
      {
469
0
        libcerror_error_set(
470
0
         error,
471
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
472
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
473
0
         "%s: missing source list element: %d.",
474
0
         function,
475
0
         element_index );
476
477
0
        goto on_error;
478
0
      }
479
0
      if( value_clone_function(
480
0
           &destination_value,
481
0
           internal_source_list_element->value,
482
0
           error ) != 1 )
483
0
      {
484
0
        libcerror_error_set(
485
0
         error,
486
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
487
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
488
0
         "%s: unable to create destination value: %d.",
489
0
         function,
490
0
         element_index );
491
492
0
        goto on_error;
493
0
      }
494
0
      if( libcdata_list_append_value(
495
0
           (libcdata_list_t *) internal_destination_list,
496
0
           destination_value,
497
0
           error ) != 1 )
498
0
      {
499
0
        libcerror_error_set(
500
0
         error,
501
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
502
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
503
0
         "%s: unable to append value: %d to destination list.",
504
0
         function,
505
0
         element_index );
506
507
0
        goto on_error;
508
0
      }
509
0
      destination_value = NULL;
510
511
0
      internal_source_list_element = (libcdata_internal_list_element_t *) internal_source_list_element->next_element;
512
0
    }
513
0
  }
514
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
515
  if( libcthreads_read_write_lock_release_for_read(
516
       internal_source_list->read_write_lock,
517
       error ) != 1 )
518
  {
519
    libcerror_error_set(
520
     error,
521
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
523
     "%s: unable to release read/write lock for reading.",
524
     function );
525
526
    libcdata_list_free(
527
     (libcdata_list_t **) &internal_destination_list,
528
     value_free_function,
529
     error );
530
531
    return( -1 );
532
  }
533
#endif
534
0
  *destination_list = (libcdata_list_t *) internal_destination_list;
535
536
0
  return( 1 );
537
538
0
on_error:
539
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
540
  libcthreads_read_write_lock_release_for_read(
541
   internal_source_list->read_write_lock,
542
   NULL );
543
#endif
544
0
  if( destination_value != NULL )
545
0
  {
546
0
    value_free_function(
547
0
     &destination_value,
548
0
     NULL );
549
0
  }
550
0
  if( internal_destination_list != NULL )
551
0
  {
552
0
    libcdata_list_free(
553
0
     (libcdata_list_t **) &internal_destination_list,
554
0
     value_free_function,
555
0
     error );
556
0
  }
557
0
  return( -1 );
558
0
}
559
560
/* Retrieves the number of elements in the list
561
 * Returns 1 if successful or -1 on error
562
 */
563
int libcdata_list_get_number_of_elements(
564
     libcdata_list_t *list,
565
     int *number_of_elements,
566
     libcerror_error_t **error )
567
4.33M
{
568
4.33M
  libcdata_internal_list_t *internal_list = NULL;
569
4.33M
  static char *function                   = "libcdata_list_get_number_of_elements";
570
571
4.33M
  if( list == NULL )
572
0
  {
573
0
    libcerror_error_set(
574
0
     error,
575
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
576
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
577
0
     "%s: invalid list.",
578
0
     function );
579
580
0
    return( -1 );
581
0
  }
582
4.33M
  internal_list = (libcdata_internal_list_t *) list;
583
584
4.33M
  if( number_of_elements == NULL )
585
0
  {
586
0
    libcerror_error_set(
587
0
     error,
588
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
589
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
590
0
     "%s: invalid number of elements.",
591
0
     function );
592
593
0
    return( -1 );
594
0
  }
595
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
596
  if( libcthreads_read_write_lock_grab_for_read(
597
       internal_list->read_write_lock,
598
       error ) != 1 )
599
  {
600
    libcerror_error_set(
601
     error,
602
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
603
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
604
     "%s: unable to grab read/write lock for reading.",
605
     function );
606
607
    return( -1 );
608
  }
609
#endif
610
4.33M
  *number_of_elements = internal_list->number_of_elements;
611
612
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
613
  if( libcthreads_read_write_lock_release_for_read(
614
       internal_list->read_write_lock,
615
       error ) != 1 )
616
  {
617
    libcerror_error_set(
618
     error,
619
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
620
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
621
     "%s: unable to release read/write lock for reading.",
622
     function );
623
624
    return( -1 );
625
  }
626
#endif
627
4.33M
  return( 1 );
628
4.33M
}
629
630
/* Retrieves the first elements in the list
631
 * Returns 1 if successful or -1 on error
632
 */
633
int libcdata_list_get_first_element(
634
     libcdata_list_t *list,
635
     libcdata_list_element_t **element,
636
     libcerror_error_t **error )
637
4.10M
{
638
4.10M
  libcdata_internal_list_t *internal_list = NULL;
639
4.10M
  static char *function                   = "libcdata_list_get_first_element";
640
641
4.10M
  if( list == NULL )
642
0
  {
643
0
    libcerror_error_set(
644
0
     error,
645
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
646
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
647
0
     "%s: invalid list.",
648
0
     function );
649
650
0
    return( -1 );
651
0
  }
652
4.10M
  internal_list = (libcdata_internal_list_t *) list;
653
654
4.10M
  if( element == NULL )
655
0
  {
656
0
    libcerror_error_set(
657
0
     error,
658
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660
0
     "%s: invalid element.",
661
0
     function );
662
663
0
    return( -1 );
664
0
  }
665
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
666
  if( libcthreads_read_write_lock_grab_for_read(
667
       internal_list->read_write_lock,
668
       error ) != 1 )
669
  {
670
    libcerror_error_set(
671
     error,
672
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
673
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
674
     "%s: unable to grab read/write lock for reading.",
675
     function );
676
677
    return( -1 );
678
  }
679
#endif
680
4.10M
  *element = internal_list->first_element;
681
682
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
683
  if( libcthreads_read_write_lock_release_for_read(
684
       internal_list->read_write_lock,
685
       error ) != 1 )
686
  {
687
    libcerror_error_set(
688
     error,
689
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
690
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
691
     "%s: unable to release read/write lock for reading.",
692
     function );
693
694
    return( -1 );
695
  }
696
#endif
697
4.10M
  return( 1 );
698
4.10M
}
699
700
/* Sets the first element in the list
701
 * Returns 1 if successful or -1 on error
702
 */
703
int libcdata_internal_list_set_first_element(
704
     libcdata_internal_list_t *internal_list,
705
     libcdata_list_element_t *element,
706
     libcerror_error_t **error )
707
0
{
708
0
  libcdata_list_element_t *backup_first_element = NULL;
709
0
  static char *function                         = "libcdata_internal_list_set_first_element";
710
711
0
  if( internal_list == NULL )
712
0
  {
713
0
    libcerror_error_set(
714
0
     error,
715
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
716
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
717
0
     "%s: invalid list.",
718
0
     function );
719
720
0
    return( -1 );
721
0
  }
722
0
  backup_first_element = internal_list->first_element;
723
724
0
  if( element != NULL )
725
0
  {
726
0
    if( libcdata_list_element_set_next_element(
727
0
         element,
728
0
         internal_list->first_element,
729
0
         error ) != 1 )
730
0
    {
731
0
      libcerror_error_set(
732
0
       error,
733
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
734
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
735
0
       "%s: unable to set next element of element.",
736
0
       function );
737
738
0
      goto on_error;
739
0
    }
740
0
  }
741
0
  if( internal_list->first_element != NULL )
742
0
  {
743
0
    if( libcdata_list_element_set_previous_element(
744
0
         internal_list->first_element,
745
0
         element,
746
0
         error ) != 1 )
747
0
    {
748
0
      libcerror_error_set(
749
0
       error,
750
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
751
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
752
0
       "%s: unable to set previous element of first element.",
753
0
       function );
754
755
0
      goto on_error;
756
0
    }
757
0
  }
758
0
  internal_list->first_element = element;
759
760
0
  return( 1 );
761
762
0
on_error:
763
0
  if( element != NULL )
764
0
  {
765
0
    libcdata_list_element_set_next_element(
766
0
     element,
767
0
     NULL,
768
0
     NULL );
769
0
  }
770
0
  if( backup_first_element != NULL )
771
0
  {
772
0
    libcdata_list_element_set_next_element(
773
0
     backup_first_element,
774
0
     NULL,
775
0
     NULL );
776
0
  }
777
0
  internal_list->first_element = backup_first_element;
778
779
0
  return( -1 );
780
0
}
781
782
/* Retrieves the last elements in the list
783
 * Returns 1 if successful or -1 on error
784
 */
785
int libcdata_list_get_last_element(
786
     libcdata_list_t *list,
787
     libcdata_list_element_t **element,
788
     libcerror_error_t **error )
789
86.9k
{
790
86.9k
  libcdata_internal_list_t *internal_list = NULL;
791
86.9k
  static char *function                   = "libcdata_list_get_last_element";
792
793
86.9k
  if( list == NULL )
794
0
  {
795
0
    libcerror_error_set(
796
0
     error,
797
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
798
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
799
0
     "%s: invalid list.",
800
0
     function );
801
802
0
    return( -1 );
803
0
  }
804
86.9k
  internal_list = (libcdata_internal_list_t *) list;
805
806
86.9k
  if( element == NULL )
807
0
  {
808
0
    libcerror_error_set(
809
0
     error,
810
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
811
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
812
0
     "%s: invalid element.",
813
0
     function );
814
815
0
    return( -1 );
816
0
  }
817
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
818
  if( libcthreads_read_write_lock_grab_for_read(
819
       internal_list->read_write_lock,
820
       error ) != 1 )
821
  {
822
    libcerror_error_set(
823
     error,
824
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
825
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
826
     "%s: unable to grab read/write lock for reading.",
827
     function );
828
829
    return( -1 );
830
  }
831
#endif
832
86.9k
  *element = internal_list->last_element;
833
834
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
835
  if( libcthreads_read_write_lock_release_for_read(
836
       internal_list->read_write_lock,
837
       error ) != 1 )
838
  {
839
    libcerror_error_set(
840
     error,
841
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
842
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
843
     "%s: unable to release read/write lock for reading.",
844
     function );
845
846
    return( -1 );
847
  }
848
#endif
849
86.9k
  return( 1 );
850
86.9k
}
851
852
/* Sets the last element in the list
853
 * Returns 1 if successful or -1 on error
854
 */
855
int libcdata_internal_list_set_last_element(
856
     libcdata_internal_list_t *internal_list,
857
     libcdata_list_element_t *element,
858
     libcerror_error_t **error )
859
87.2k
{
860
87.2k
  libcdata_list_element_t *backup_last_element = NULL;
861
87.2k
  static char *function                        = "libcdata_internal_list_set_last_element";
862
863
87.2k
  if( internal_list == NULL )
864
0
  {
865
0
    libcerror_error_set(
866
0
     error,
867
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
868
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
869
0
     "%s: invalid list.",
870
0
     function );
871
872
0
    return( -1 );
873
0
  }
874
87.2k
  backup_last_element = internal_list->last_element;
875
876
87.2k
  if( element != NULL )
877
87.2k
  {
878
87.2k
    if( libcdata_list_element_set_previous_element(
879
87.2k
         element,
880
87.2k
         internal_list->last_element,
881
87.2k
         error ) != 1 )
882
0
    {
883
0
      libcerror_error_set(
884
0
       error,
885
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
886
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
887
0
       "%s: unable to set previous element of element.",
888
0
       function );
889
890
0
      goto on_error;
891
0
    }
892
87.2k
  }
893
87.2k
  if( internal_list->last_element != NULL )
894
87.2k
  {
895
87.2k
    if( libcdata_list_element_set_next_element(
896
87.2k
         internal_list->last_element,
897
87.2k
         element,
898
87.2k
         error ) != 1 )
899
0
    {
900
0
      libcerror_error_set(
901
0
       error,
902
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
903
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
904
0
       "%s: unable to set next element of last element.",
905
0
       function );
906
907
0
      goto on_error;
908
0
    }
909
87.2k
  }
910
87.2k
  internal_list->last_element = element;
911
912
87.2k
  return( 1 );
913
914
0
on_error:
915
0
  if( element != NULL )
916
0
  {
917
0
    libcdata_list_element_set_previous_element(
918
0
     element,
919
0
     NULL,
920
0
     NULL );
921
0
  }
922
0
  if( backup_last_element != NULL )
923
0
  {
924
0
    libcdata_list_element_set_next_element(
925
0
     backup_last_element,
926
0
     NULL,
927
0
     NULL );
928
0
  }
929
0
  internal_list->last_element = backup_last_element;
930
931
0
  return( -1 );
932
87.2k
}
933
934
/* Retrieves a specific element from the list
935
 * Returns 1 if successful or -1 on error
936
 */
937
int libcdata_list_get_element_by_index(
938
     libcdata_list_t *list,
939
     int element_index,
940
     libcdata_list_element_t **element,
941
     libcerror_error_t **error )
942
0
{
943
0
  libcdata_internal_list_t *internal_list = NULL;
944
0
  libcdata_list_element_t *list_element   = NULL;
945
0
  static char *function                   = "libcdata_list_get_element_by_index";
946
0
  int element_iterator                    = 0;
947
948
0
  if( list == NULL )
949
0
  {
950
0
    libcerror_error_set(
951
0
     error,
952
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
953
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
954
0
     "%s: invalid list.",
955
0
     function );
956
957
0
    return( -1 );
958
0
  }
959
0
  internal_list = (libcdata_internal_list_t *) list;
960
961
0
  if( ( element_index < 0 )
962
0
   || ( element_index >= internal_list->number_of_elements ) )
963
0
  {
964
0
    libcerror_error_set(
965
0
     error,
966
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
967
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
968
0
     "%s: invalid element index value out of bounds.",
969
0
     function );
970
971
0
    return( -1 );
972
0
  }
973
0
  if( element == NULL )
974
0
  {
975
0
    libcerror_error_set(
976
0
     error,
977
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
978
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
979
0
     "%s: invalid list element.",
980
0
     function );
981
982
0
    return( -1 );
983
0
  }
984
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
985
  if( libcthreads_read_write_lock_grab_for_read(
986
       internal_list->read_write_lock,
987
       error ) != 1 )
988
  {
989
    libcerror_error_set(
990
     error,
991
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
992
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
993
     "%s: unable to grab read/write lock for reading.",
994
     function );
995
996
    return( -1 );
997
  }
998
#endif
999
0
  if( element_index < ( internal_list->number_of_elements / 2 ) )
1000
0
  {
1001
0
    list_element = internal_list->first_element;
1002
1003
0
    for( element_iterator = 0;
1004
0
         element_iterator < element_index;
1005
0
         element_iterator++ )
1006
0
    {
1007
0
      if( list_element == NULL )
1008
0
      {
1009
0
        libcerror_error_set(
1010
0
         error,
1011
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1012
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1013
0
         "%s: corruption detected in element: %d.",
1014
0
         function,
1015
0
         element_iterator );
1016
1017
0
        goto on_error;
1018
0
      }
1019
0
      if( libcdata_list_element_get_next_element(
1020
0
           list_element,
1021
0
           &list_element,
1022
0
           error ) != 1 )
1023
0
      {
1024
0
        libcerror_error_set(
1025
0
         error,
1026
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1027
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1028
0
         "%s: unable to retrieve next element from list element: %d.",
1029
0
         function,
1030
0
         element_index );
1031
1032
0
        goto on_error;
1033
0
      }
1034
0
    }
1035
0
  }
1036
0
  else
1037
0
  {
1038
0
    list_element = internal_list->last_element;
1039
1040
0
    for( element_iterator = ( internal_list->number_of_elements - 1 );
1041
0
         element_iterator > element_index;
1042
0
         element_iterator-- )
1043
0
    {
1044
0
      if( list_element == NULL )
1045
0
      {
1046
0
        libcerror_error_set(
1047
0
         error,
1048
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1049
0
         LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1050
0
         "%s: corruption detected in element: %d.",
1051
0
         function,
1052
0
         element_iterator );
1053
1054
0
        goto on_error;
1055
0
      }
1056
0
      if( libcdata_list_element_get_previous_element(
1057
0
           list_element,
1058
0
           &list_element,
1059
0
           error ) != 1 )
1060
0
      {
1061
0
        libcerror_error_set(
1062
0
         error,
1063
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1064
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1065
0
         "%s: unable to retrieve previous element from list element: %d.",
1066
0
         function,
1067
0
         element_index );
1068
1069
0
        goto on_error;
1070
0
      }
1071
0
    }
1072
0
  }
1073
0
  if( list_element == NULL )
1074
0
  {
1075
0
    libcerror_error_set(
1076
0
     error,
1077
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1078
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1079
0
     "%s: corruption detected - missing list element.",
1080
0
     function );
1081
1082
0
    goto on_error;
1083
0
  }
1084
0
  *element = list_element;
1085
1086
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1087
  if( libcthreads_read_write_lock_release_for_read(
1088
       internal_list->read_write_lock,
1089
       error ) != 1 )
1090
  {
1091
    libcerror_error_set(
1092
     error,
1093
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1095
     "%s: unable to release read/write lock for reading.",
1096
     function );
1097
1098
    return( -1 );
1099
  }
1100
#endif
1101
0
  return( 1 );
1102
1103
0
on_error:
1104
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1105
  libcthreads_read_write_lock_release_for_read(
1106
   internal_list->read_write_lock,
1107
   NULL );
1108
#endif
1109
0
  return( -1 );
1110
0
}
1111
1112
/* Retrieves a specific value from the list
1113
 * Returns 1 if successful or -1 on error
1114
 */
1115
int libcdata_list_get_value_by_index(
1116
     libcdata_list_t *list,
1117
     int element_index,
1118
     intptr_t **value,
1119
     libcerror_error_t **error )
1120
0
{
1121
0
  libcdata_list_element_t *list_element = NULL;
1122
0
  static char *function                 = "libcdata_list_get_value_by_index";
1123
1124
0
  if( libcdata_list_get_element_by_index(
1125
0
       list,
1126
0
       element_index,
1127
0
       &list_element,
1128
0
       error ) != 1 )
1129
0
  {
1130
0
    libcerror_error_set(
1131
0
     error,
1132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1133
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1134
0
     "%s: unable to retrieve list element: %d from list.",
1135
0
     function,
1136
0
     element_index );
1137
1138
0
    return( -1 );
1139
0
  }
1140
0
  if( libcdata_list_element_get_value(
1141
0
       list_element,
1142
0
       value,
1143
0
       error ) != 1 )
1144
0
  {
1145
0
    libcerror_error_set(
1146
0
     error,
1147
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1148
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1149
0
     "%s: unable to retrieve value from list element: %d.",
1150
0
     function,
1151
0
     element_index );
1152
1153
0
    return( -1 );
1154
0
  }
1155
0
  return( 1 );
1156
0
}
1157
1158
/* Prepends a list element to the list
1159
 * Returns 1 if successful or -1 on error
1160
 */
1161
int libcdata_list_prepend_element(
1162
     libcdata_list_t *list,
1163
     libcdata_list_element_t *element,
1164
     libcerror_error_t **error )
1165
1.23M
{
1166
1.23M
  libcdata_internal_list_t *internal_list       = NULL;
1167
1.23M
  libcdata_list_element_t *next_element         = NULL;
1168
1.23M
  libcdata_list_element_t *previous_element     = NULL;
1169
1.23M
  static char *function                         = "libcdata_list_prepend_element";
1170
1.23M
  int result                                    = 1;
1171
1172
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1173
  libcdata_list_element_t *backup_first_element = NULL;
1174
  libcdata_list_element_t *backup_last_element  = NULL;
1175
#endif
1176
1177
1.23M
  if( list == NULL )
1178
0
  {
1179
0
    libcerror_error_set(
1180
0
     error,
1181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1183
0
     "%s: invalid list.",
1184
0
     function );
1185
1186
0
    return( -1 );
1187
0
  }
1188
1.23M
  internal_list = (libcdata_internal_list_t *) list;
1189
1190
1.23M
  if( internal_list->number_of_elements == 0 )
1191
490k
  {
1192
490k
    if( internal_list->first_element != NULL )
1193
0
    {
1194
0
      libcerror_error_set(
1195
0
       error,
1196
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1197
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1198
0
       "%s: corruption detected - first element already set.",
1199
0
       function );
1200
1201
0
      return( -1 );
1202
0
    }
1203
490k
    if( internal_list->last_element != NULL )
1204
0
    {
1205
0
      libcerror_error_set(
1206
0
       error,
1207
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1208
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1209
0
       "%s: corruption detected - last element already set.",
1210
0
       function );
1211
1212
0
      return( -1 );
1213
0
    }
1214
490k
  }
1215
748k
  else
1216
748k
  {
1217
748k
    if( internal_list->first_element == NULL )
1218
0
    {
1219
0
      libcerror_error_set(
1220
0
       error,
1221
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1222
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1223
0
       "%s: corruption detected - missing first element.",
1224
0
       function );
1225
1226
0
      return( -1 );
1227
0
    }
1228
748k
    if( internal_list->last_element == NULL )
1229
0
    {
1230
0
      libcerror_error_set(
1231
0
       error,
1232
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1233
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1234
0
       "%s: corruption detected - missing last element.",
1235
0
       function );
1236
1237
0
      return( -1 );
1238
0
    }
1239
748k
  }
1240
1.23M
  if( element == NULL )
1241
0
  {
1242
0
    libcerror_error_set(
1243
0
     error,
1244
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1245
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1246
0
     "%s: invalid list element.",
1247
0
     function );
1248
1249
0
    return( -1 );
1250
0
  }
1251
1.23M
  if( libcdata_list_element_get_elements(
1252
1.23M
       element,
1253
1.23M
       &previous_element,
1254
1.23M
       &next_element,
1255
1.23M
       error ) != 1 )
1256
0
  {
1257
0
    libcerror_error_set(
1258
0
     error,
1259
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1260
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1261
0
     "%s: unable to retrieve previous and next element from list element.",
1262
0
     function );
1263
1264
0
    return( -1 );
1265
0
  }
1266
1.23M
  if( ( previous_element != NULL )
1267
1.23M
   || ( next_element != NULL ) )
1268
0
  {
1269
0
    libcerror_error_set(
1270
0
     error,
1271
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1272
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1273
0
     "%s: list element already part of a list.",
1274
0
     function );
1275
1276
0
    return( -1 );
1277
0
  }
1278
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1279
  if( libcthreads_read_write_lock_grab_for_write(
1280
       internal_list->read_write_lock,
1281
       error ) != 1 )
1282
  {
1283
    libcerror_error_set(
1284
     error,
1285
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1286
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1287
     "%s: unable to grab read/write lock for writing.",
1288
     function );
1289
1290
    return( -1 );
1291
  }
1292
  backup_first_element = internal_list->first_element;
1293
  backup_last_element  = internal_list->last_element;
1294
1295
#endif
1296
1.23M
  result = libcdata_list_element_set_next_element(
1297
1.23M
            element,
1298
1.23M
            internal_list->first_element,
1299
1.23M
            error );
1300
1301
1.23M
  if( result != 1 )
1302
0
  {
1303
0
    libcerror_error_set(
1304
0
     error,
1305
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1307
0
     "%s: unable to set next element of list element.",
1308
0
     function );
1309
1310
0
    result = -1;
1311
0
  }
1312
1.23M
  if( result == 1 )
1313
1.23M
  {
1314
1.23M
    if( internal_list->first_element != NULL )
1315
748k
    {
1316
748k
      result = libcdata_list_element_set_previous_element(
1317
748k
                internal_list->first_element,
1318
748k
                element,
1319
748k
                error );
1320
1321
748k
      if( result != 1 )
1322
0
      {
1323
0
        libcerror_error_set(
1324
0
         error,
1325
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1326
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1327
0
         "%s: unable to set previous element of first element.",
1328
0
         function );
1329
1330
0
        libcdata_list_element_set_next_element(
1331
0
         element,
1332
0
         NULL,
1333
0
         NULL );
1334
1335
0
        result = -1;
1336
0
      }
1337
748k
    }
1338
1.23M
  }
1339
1.23M
  if( result == 1 )
1340
1.23M
  {
1341
1.23M
    internal_list->first_element = element;
1342
1343
1.23M
    if( internal_list->last_element == NULL )
1344
490k
    {
1345
490k
      internal_list->last_element = element;
1346
490k
    }
1347
1.23M
    internal_list->number_of_elements += 1;
1348
1.23M
  }
1349
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1350
  if( libcthreads_read_write_lock_release_for_write(
1351
       internal_list->read_write_lock,
1352
       error ) != 1 )
1353
  {
1354
    libcerror_error_set(
1355
     error,
1356
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1357
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1358
     "%s: unable to release read/write lock for writing.",
1359
     function );
1360
1361
    goto on_error;
1362
  }
1363
#endif
1364
1.23M
  return( result );
1365
1366
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1367
on_error:
1368
  if( result == 1 )
1369
  {
1370
    libcdata_list_element_set_next_element(
1371
     element,
1372
     NULL,
1373
     NULL );
1374
1375
    libcdata_list_element_set_previous_element(
1376
     backup_first_element,
1377
     NULL,
1378
     NULL );
1379
1380
    internal_list->first_element = backup_first_element;
1381
    internal_list->last_element  = backup_last_element;
1382
1383
    internal_list->number_of_elements -= 1;
1384
  }
1385
  return( -1 );
1386
#endif
1387
1.23M
}
1388
1389
/* Prepends a value to the list
1390
 * Creates a new list element
1391
 * Returns 1 if successful or -1 on error
1392
 */
1393
int libcdata_list_prepend_value(
1394
     libcdata_list_t *list,
1395
     intptr_t *value,
1396
     libcerror_error_t **error )
1397
125k
{
1398
125k
  libcdata_list_element_t *list_element = NULL;
1399
125k
  static char *function                 = "libcdata_list_prepend_value";
1400
1401
125k
  if( libcdata_list_element_initialize(
1402
125k
       &list_element,
1403
125k
       error ) != 1 )
1404
0
  {
1405
0
    libcerror_error_set(
1406
0
     error,
1407
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1408
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1409
0
     "%s: unable to create list element.",
1410
0
     function );
1411
1412
0
    goto on_error;
1413
0
  }
1414
125k
  if( libcdata_list_prepend_element(
1415
125k
       list,
1416
125k
       list_element,
1417
125k
       error ) != 1 )
1418
0
  {
1419
0
    libcerror_error_set(
1420
0
     error,
1421
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1422
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1423
0
     "%s: unable to prepend element to list.",
1424
0
     function );
1425
1426
0
    goto on_error;
1427
0
  }
1428
125k
  if( libcdata_list_element_set_value(
1429
125k
       list_element,
1430
125k
       value,
1431
125k
       error ) != 1 )
1432
0
  {
1433
0
    libcerror_error_set(
1434
0
     error,
1435
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1436
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1437
0
     "%s: unable to set value of list element.",
1438
0
     function );
1439
1440
0
    goto on_error;
1441
0
  }
1442
125k
  return( 1 );
1443
1444
0
on_error:
1445
0
  if( list_element != NULL )
1446
0
  {
1447
0
    libcdata_list_element_free(
1448
0
     &list_element,
1449
0
     NULL,
1450
0
     NULL );
1451
0
  }
1452
0
  return( -1 );
1453
125k
}
1454
1455
/* Appends a list element to the list
1456
 * Returns 1 if successful or -1 on error
1457
 */
1458
int libcdata_list_append_element(
1459
     libcdata_list_t *list,
1460
     libcdata_list_element_t *element,
1461
     libcerror_error_t **error )
1462
1.06M
{
1463
1.06M
  libcdata_internal_list_t *internal_list       = NULL;
1464
1.06M
  libcdata_list_element_t *next_element         = NULL;
1465
1.06M
  libcdata_list_element_t *previous_element     = NULL;
1466
1.06M
  static char *function                         = "libcdata_list_append_element";
1467
1.06M
  int result                                    = 1;
1468
1469
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1470
  libcdata_list_element_t *backup_first_element = NULL;
1471
  libcdata_list_element_t *backup_last_element  = NULL;
1472
#endif
1473
1474
1.06M
  if( list == NULL )
1475
0
  {
1476
0
    libcerror_error_set(
1477
0
     error,
1478
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1479
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1480
0
     "%s: invalid list.",
1481
0
     function );
1482
1483
0
    return( -1 );
1484
0
  }
1485
1.06M
  internal_list = (libcdata_internal_list_t *) list;
1486
1487
1.06M
  if( internal_list->number_of_elements == 0 )
1488
12.2k
  {
1489
12.2k
    if( internal_list->first_element != NULL )
1490
0
    {
1491
0
      libcerror_error_set(
1492
0
       error,
1493
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1494
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1495
0
       "%s: corruption detected - first element already set.",
1496
0
       function );
1497
1498
0
      return( -1 );
1499
0
    }
1500
12.2k
    if( internal_list->last_element != NULL )
1501
0
    {
1502
0
      libcerror_error_set(
1503
0
       error,
1504
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1505
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1506
0
       "%s: corruption detected - last element already set.",
1507
0
       function );
1508
1509
0
      return( -1 );
1510
0
    }
1511
12.2k
  }
1512
1.04M
  else
1513
1.04M
  {
1514
1.04M
    if( internal_list->first_element == NULL )
1515
0
    {
1516
0
      libcerror_error_set(
1517
0
       error,
1518
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1519
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1520
0
       "%s: corruption detected - missing first element.",
1521
0
       function );
1522
1523
0
      return( -1 );
1524
0
    }
1525
1.04M
    if( internal_list->last_element == NULL )
1526
0
    {
1527
0
      libcerror_error_set(
1528
0
       error,
1529
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1530
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1531
0
       "%s: corruption detected - missing last element.",
1532
0
       function );
1533
1534
0
      return( -1 );
1535
0
    }
1536
1.04M
  }
1537
1.06M
  if( libcdata_list_element_get_elements(
1538
1.06M
       element,
1539
1.06M
       &previous_element,
1540
1.06M
       &next_element,
1541
1.06M
       error ) != 1 )
1542
0
  {
1543
0
    libcerror_error_set(
1544
0
     error,
1545
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1546
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1547
0
     "%s: unable to retrieve previous and next element from list element.",
1548
0
     function );
1549
1550
0
    return( -1 );
1551
0
  }
1552
1.06M
  if( ( previous_element != NULL )
1553
1.06M
   || ( next_element != NULL ) )
1554
0
  {
1555
0
    libcerror_error_set(
1556
0
     error,
1557
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1558
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1559
0
     "%s: list element already part of a list.",
1560
0
     function );
1561
1562
0
    return( -1 );
1563
0
  }
1564
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1565
  if( libcthreads_read_write_lock_grab_for_write(
1566
       internal_list->read_write_lock,
1567
       error ) != 1 )
1568
  {
1569
    libcerror_error_set(
1570
     error,
1571
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1572
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1573
     "%s: unable to grab read/write lock for writing.",
1574
     function );
1575
1576
    return( -1 );
1577
  }
1578
  backup_first_element = internal_list->first_element;
1579
  backup_last_element  = internal_list->last_element;
1580
1581
#endif
1582
1.06M
  result = libcdata_list_element_set_previous_element(
1583
1.06M
            element,
1584
1.06M
            internal_list->last_element,
1585
1.06M
            error );
1586
1587
1.06M
  if( result != 1 )
1588
0
  {
1589
0
    libcerror_error_set(
1590
0
     error,
1591
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1592
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1593
0
     "%s: unable to set previous element of list element.",
1594
0
     function );
1595
1596
0
    result = -1;
1597
0
  }
1598
1.06M
  if( result == 1 )
1599
1.06M
  {
1600
1.06M
    if( internal_list->last_element != NULL )
1601
1.04M
    {
1602
1.04M
      result = libcdata_list_element_set_next_element(
1603
1.04M
                internal_list->last_element,
1604
1.04M
                element,
1605
1.04M
                error );
1606
1607
1.04M
      if( result != 1 )
1608
0
      {
1609
0
        libcerror_error_set(
1610
0
         error,
1611
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1612
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1613
0
         "%s: unable to set next element of last element.",
1614
0
         function );
1615
1616
0
        libcdata_list_element_set_previous_element(
1617
0
         element,
1618
0
         NULL,
1619
0
         NULL );
1620
1621
0
        result = -1;
1622
0
      }
1623
1.04M
    }
1624
1.06M
  }
1625
1.06M
  if( result == 1 )
1626
1.06M
  {
1627
1.06M
    if( internal_list->first_element == NULL )
1628
12.2k
    {
1629
12.2k
      internal_list->first_element = element;
1630
12.2k
    }
1631
1.06M
    internal_list->last_element = element;
1632
1633
1.06M
    internal_list->number_of_elements += 1;
1634
1.06M
  }
1635
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1636
  if( libcthreads_read_write_lock_release_for_write(
1637
       internal_list->read_write_lock,
1638
       error ) != 1 )
1639
  {
1640
    libcerror_error_set(
1641
     error,
1642
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1643
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1644
     "%s: unable to release read/write lock for writing.",
1645
     function );
1646
1647
    goto on_error;
1648
  }
1649
#endif
1650
1.06M
  return( result );
1651
1652
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1653
on_error:
1654
  if( result == 1 )
1655
  {
1656
    libcdata_list_element_set_previous_element(
1657
     element,
1658
     NULL,
1659
     NULL );
1660
1661
    libcdata_list_element_set_next_element(
1662
     backup_last_element,
1663
     NULL,
1664
     NULL );
1665
1666
    internal_list->first_element = backup_first_element;
1667
    internal_list->last_element  = backup_last_element;
1668
1669
    internal_list->number_of_elements -= 1;
1670
  }
1671
  return( -1 );
1672
#endif
1673
1.06M
}
1674
1675
/* Appends a value to the list
1676
 * Creates a new list element
1677
 * Returns 1 if successful or -1 on error
1678
 */
1679
int libcdata_list_append_value(
1680
     libcdata_list_t *list,
1681
     intptr_t *value,
1682
     libcerror_error_t **error )
1683
1.06M
{
1684
1.06M
  libcdata_list_element_t *element = NULL;
1685
1.06M
  static char *function            = "libcdata_list_append_value";
1686
1687
1.06M
  if( libcdata_list_element_initialize(
1688
1.06M
       &element,
1689
1.06M
       error ) != 1 )
1690
0
  {
1691
0
    libcerror_error_set(
1692
0
     error,
1693
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1694
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1695
0
     "%s: unable to create list element.",
1696
0
     function );
1697
1698
0
    goto on_error;
1699
0
  }
1700
1.06M
  if( libcdata_list_element_set_value(
1701
1.06M
       element,
1702
1.06M
       value,
1703
1.06M
       error ) != 1 )
1704
0
  {
1705
0
    libcerror_error_set(
1706
0
     error,
1707
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1708
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1709
0
     "%s: unable to set value of list element.",
1710
0
     function );
1711
1712
0
    goto on_error;
1713
0
  }
1714
1.06M
  if( libcdata_list_append_element(
1715
1.06M
       list,
1716
1.06M
       element,
1717
1.06M
       error ) != 1 )
1718
0
  {
1719
0
    libcerror_error_set(
1720
0
     error,
1721
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1722
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1723
0
     "%s: unable to append element to list.",
1724
0
     function );
1725
1726
0
    goto on_error;
1727
0
  }
1728
1.06M
  return( 1 );
1729
1730
0
on_error:
1731
0
  if( element != NULL )
1732
0
  {
1733
0
    libcdata_list_element_free(
1734
0
     &element,
1735
0
     NULL,
1736
0
     NULL );
1737
0
  }
1738
0
  return( -1 );
1739
1.06M
}
1740
1741
/* Retrieves the element which the element should be inserted before
1742
 *
1743
 * Uses the value_compare_function to determine the order of the entries
1744
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
1745
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
1746
 *
1747
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
1748
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
1749
 *
1750
 * On return element will be set to NULL if the element should be inserted at the end of the list.
1751
 *
1752
 * Returns 1 if successful, 0 if a list element containing the value already exists or -1 on error
1753
 */
1754
int libcdata_internal_list_insert_element_find_element(
1755
     libcdata_internal_list_t *internal_list,
1756
     intptr_t *value_to_insert,
1757
     int (*value_compare_function)(
1758
            intptr_t *first_value,
1759
            intptr_t *second_value,
1760
            libcerror_error_t **error ),
1761
     uint8_t insert_flags,
1762
     int *element_index,
1763
     libcdata_list_element_t **element,
1764
     libcerror_error_t **error )
1765
90.7k
{
1766
90.7k
  libcdata_list_element_t *list_element = NULL;
1767
90.7k
  intptr_t *list_element_value          = NULL;
1768
90.7k
  static char *function                 = "libcdata_internal_list_insert_element_find_element";
1769
90.7k
  int compare_result                    = 0;
1770
90.7k
  int result                            = 1;
1771
90.7k
  int safe_element_index                = 0;
1772
1773
90.7k
  if( internal_list == NULL )
1774
0
  {
1775
0
    libcerror_error_set(
1776
0
     error,
1777
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1778
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1779
0
     "%s: invalid list.",
1780
0
     function );
1781
1782
0
    return( -1 );
1783
0
  }
1784
90.7k
  if( value_compare_function == NULL )
1785
0
  {
1786
0
    libcerror_error_set(
1787
0
     error,
1788
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1789
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1790
0
     "%s: invalid value compare function.",
1791
0
     function );
1792
1793
0
    return( -1 );
1794
0
  }
1795
90.7k
  if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
1796
0
  {
1797
0
    libcerror_error_set(
1798
0
     error,
1799
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1800
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1801
0
     "%s: unsupported insert flags: 0x%02" PRIx8 ".",
1802
0
     function,
1803
0
     insert_flags );
1804
1805
0
    return( -1 );
1806
0
  }
1807
90.7k
  if( element_index == NULL )
1808
0
  {
1809
0
    libcerror_error_set(
1810
0
     error,
1811
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1812
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1813
0
     "%s: invalid element index.",
1814
0
     function );
1815
1816
0
    return( -1 );
1817
0
  }
1818
90.7k
  if( element == NULL )
1819
0
  {
1820
0
    libcerror_error_set(
1821
0
     error,
1822
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1823
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1824
0
     "%s: invalid element.",
1825
0
     function );
1826
1827
0
    return( -1 );
1828
0
  }
1829
90.7k
  list_element   = internal_list->first_element;
1830
90.7k
  compare_result = LIBCDATA_COMPARE_GREATER;
1831
1832
90.7k
  for( safe_element_index = 0;
1833
11.4M
       safe_element_index < internal_list->number_of_elements;
1834
11.3M
       safe_element_index++ )
1835
11.4M
  {
1836
11.4M
    if( libcdata_list_element_get_value(
1837
11.4M
         list_element,
1838
11.4M
         &list_element_value,
1839
11.4M
         error ) != 1 )
1840
0
    {
1841
0
      libcerror_error_set(
1842
0
       error,
1843
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1844
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1845
0
       "%s: unable to retrieve value from list element: %d.",
1846
0
       function,
1847
0
       safe_element_index );
1848
1849
0
      return( -1 );
1850
0
    }
1851
11.4M
    compare_result = value_compare_function(
1852
11.4M
                      value_to_insert,
1853
11.4M
                      list_element_value,
1854
11.4M
                      error );
1855
1856
11.4M
    if( compare_result == -1 )
1857
0
    {
1858
0
      libcerror_error_set(
1859
0
       error,
1860
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1861
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1862
0
       "%s: unable to compare list element: %d.",
1863
0
       function,
1864
0
       safe_element_index );
1865
1866
0
      return( -1 );
1867
0
    }
1868
11.4M
    else if( compare_result == LIBCDATA_COMPARE_EQUAL )
1869
0
    {
1870
0
      if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 )
1871
0
      {
1872
0
        result = 0;
1873
1874
0
        break;
1875
0
      }
1876
0
    }
1877
11.4M
    else if( compare_result == LIBCDATA_COMPARE_LESS )
1878
2.61k
    {
1879
2.61k
      break;
1880
2.61k
    }
1881
11.3M
    else if( compare_result != LIBCDATA_COMPARE_GREATER )
1882
0
    {
1883
0
      libcerror_error_set(
1884
0
       error,
1885
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1886
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1887
0
       "%s: unsupported value compare function return value: %d.",
1888
0
       function,
1889
0
       compare_result );
1890
1891
0
      return( -1 );
1892
0
    }
1893
11.3M
    if( libcdata_list_element_get_next_element(
1894
11.3M
         list_element,
1895
11.3M
         &list_element,
1896
11.3M
         error ) != 1 )
1897
0
    {
1898
0
      libcerror_error_set(
1899
0
       error,
1900
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1901
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1902
0
       "%s: unable to retrieve next element from list element: %d.",
1903
0
       function,
1904
0
       safe_element_index );
1905
1906
0
      return( -1 );
1907
0
    }
1908
11.3M
  }
1909
90.7k
  if( ( compare_result == LIBCDATA_COMPARE_EQUAL )
1910
90.7k
   || ( compare_result == LIBCDATA_COMPARE_LESS ) )
1911
2.61k
  {
1912
2.61k
    *element_index = safe_element_index;
1913
2.61k
    *element       = list_element;
1914
2.61k
  }
1915
88.1k
  else
1916
88.1k
  {
1917
88.1k
    *element_index = internal_list->number_of_elements;
1918
88.1k
    *element       = NULL;
1919
88.1k
  }
1920
90.7k
  return( result );
1921
90.7k
}
1922
1923
/* Inserts the element before the list element
1924
 * If list_element is NULL the element is inserted before or as the first element in the list
1925
 * Returns 1 if successful, or -1 on error
1926
 */
1927
int libcdata_internal_list_insert_element_before_element(
1928
     libcdata_internal_list_t *internal_list,
1929
     libcdata_list_element_t *list_element,
1930
     libcdata_list_element_t *element_to_insert,
1931
     libcerror_error_t **error )
1932
90.7k
{
1933
90.7k
  libcdata_list_element_t *backup_first_element = NULL;
1934
90.7k
  libcdata_list_element_t *backup_last_element  = NULL;
1935
90.7k
  libcdata_list_element_t *previous_element     = NULL;
1936
90.7k
  static char *function                         = "libcdata_internal_list_insert_element_before_element";
1937
1938
90.7k
  if( internal_list == NULL )
1939
0
  {
1940
0
    libcerror_error_set(
1941
0
     error,
1942
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1943
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1944
0
     "%s: invalid list.",
1945
0
     function );
1946
1947
0
    return( -1 );
1948
0
  }
1949
90.7k
  if( element_to_insert == NULL )
1950
0
  {
1951
0
    libcerror_error_set(
1952
0
     error,
1953
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1954
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1955
0
     "%s: invalid element to insert.",
1956
0
     function );
1957
1958
0
    return( -1 );
1959
0
  }
1960
90.7k
  backup_first_element = internal_list->first_element;
1961
90.7k
  backup_last_element  = internal_list->last_element;
1962
1963
90.7k
  if( list_element != NULL )
1964
2.61k
  {
1965
2.61k
    if( libcdata_list_element_get_previous_element(
1966
2.61k
         list_element,
1967
2.61k
         &previous_element,
1968
2.61k
         error ) != 1 )
1969
0
    {
1970
0
      libcerror_error_set(
1971
0
       error,
1972
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1973
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1974
0
       "%s: unable to retrieve previous element from list element.",
1975
0
       function );
1976
1977
0
      return( -1 );
1978
0
    }
1979
2.61k
  }
1980
90.7k
  if( internal_list->number_of_elements == 0 )
1981
892
  {
1982
892
    internal_list->first_element = element_to_insert;
1983
892
    internal_list->last_element  = element_to_insert;
1984
892
  }
1985
89.8k
  else if( list_element == NULL )
1986
87.2k
  {
1987
87.2k
    if( libcdata_internal_list_set_last_element(
1988
87.2k
         internal_list,
1989
87.2k
         element_to_insert,
1990
87.2k
         error ) != 1 )
1991
0
    {
1992
0
      libcerror_error_set(
1993
0
       error,
1994
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1995
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1996
0
       "%s: unable to set last list element.",
1997
0
       function );
1998
1999
0
      goto on_error;
2000
0
    }
2001
87.2k
  }
2002
2.61k
  else
2003
2.61k
  {
2004
2.61k
    if( libcdata_list_element_set_elements(
2005
2.61k
         element_to_insert,
2006
2.61k
         previous_element,
2007
2.61k
         list_element,
2008
2.61k
         error ) != 1 )
2009
0
    {
2010
0
      libcerror_error_set(
2011
0
       error,
2012
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2013
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2014
0
       "%s: unable to set previous and next element of element to insert.",
2015
0
       function );
2016
2017
0
      goto on_error;
2018
0
    }
2019
2.61k
    if( internal_list->first_element == list_element )
2020
607
    {
2021
607
      internal_list->first_element = element_to_insert;
2022
607
    }
2023
2.00k
    else
2024
2.00k
    {
2025
2.00k
      if( libcdata_list_element_set_next_element(
2026
2.00k
           previous_element,
2027
2.00k
           element_to_insert,
2028
2.00k
           error ) != 1 )
2029
0
      {
2030
0
        libcerror_error_set(
2031
0
         error,
2032
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2033
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2034
0
         "%s: unable to set next element of previous list element.",
2035
0
         function );
2036
2037
0
        goto on_error;
2038
0
      }
2039
2.00k
    }
2040
2.61k
    if( libcdata_list_element_set_previous_element(
2041
2.61k
         list_element,
2042
2.61k
         element_to_insert,
2043
2.61k
         error ) != 1 )
2044
0
    {
2045
0
      libcerror_error_set(
2046
0
       error,
2047
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2048
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2049
0
       "%s: unable to set previous element of list element.",
2050
0
       function );
2051
2052
0
      goto on_error;
2053
0
    }
2054
2.61k
  }
2055
90.7k
  internal_list->number_of_elements += 1;
2056
2057
90.7k
  return( 1 );
2058
2059
0
on_error:
2060
0
  if( element_to_insert != NULL )
2061
0
  {
2062
0
    libcdata_list_element_set_elements(
2063
0
     element_to_insert,
2064
0
     NULL,
2065
0
     NULL,
2066
0
     NULL );
2067
0
  }
2068
0
  if( previous_element != NULL )
2069
0
  {
2070
0
    libcdata_list_element_set_next_element(
2071
0
     previous_element,
2072
0
     list_element,
2073
0
     NULL );
2074
0
  }
2075
0
  if( list_element != NULL )
2076
0
  {
2077
0
    libcdata_list_element_set_previous_element(
2078
0
     list_element,
2079
0
     previous_element,
2080
0
     NULL );
2081
0
  }
2082
0
  internal_list->first_element = backup_first_element;
2083
0
  internal_list->last_element  = backup_last_element;
2084
2085
0
  return( -1 );
2086
90.7k
}
2087
2088
/* Inserts a list element into the list
2089
 *
2090
 * Uses the value_compare_function to determine the order of the entries
2091
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2092
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2093
 *
2094
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2095
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2096
 *
2097
 * Returns 1 if successful, 0 if the list element already exists or -1 on error
2098
 */
2099
int libcdata_list_insert_element(
2100
     libcdata_list_t *list,
2101
     libcdata_list_element_t *element_to_insert,
2102
     int (*value_compare_function)(
2103
            intptr_t *first_value,
2104
            intptr_t *second_value,
2105
            libcerror_error_t **error ),
2106
     uint8_t insert_flags,
2107
     libcerror_error_t **error )
2108
0
{
2109
0
  libcdata_list_element_t *existing_element = NULL;
2110
0
  static char *function                     = "libcdata_list_insert_element";
2111
0
  int result                                = 0;
2112
2113
0
  result = libcdata_list_insert_element_with_existing(
2114
0
            list,
2115
0
            element_to_insert,
2116
0
            value_compare_function,
2117
0
            insert_flags,
2118
0
            &existing_element,
2119
0
            error );
2120
2121
0
  if( result == -1 )
2122
0
  {
2123
0
    libcerror_error_set(
2124
0
     error,
2125
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2126
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2127
0
     "%s: unable to insert element into list.",
2128
0
     function );
2129
2130
0
    return( -1 );
2131
0
  }
2132
0
  return( result );
2133
0
}
2134
2135
/* Inserts a list element into the list
2136
 *
2137
 * Uses the value_compare_function to determine the order of the entries
2138
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2139
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2140
 *
2141
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2142
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2143
 *
2144
 * Returns 1 if successful, 0 if the list element already exists or -1 on error
2145
 */
2146
int libcdata_list_insert_element_with_existing(
2147
     libcdata_list_t *list,
2148
     libcdata_list_element_t *element_to_insert,
2149
     int (*value_compare_function)(
2150
            intptr_t *first_value,
2151
            intptr_t *second_value,
2152
            libcerror_error_t **error ),
2153
     uint8_t insert_flags,
2154
     libcdata_list_element_t **existing_element,
2155
     libcerror_error_t **error )
2156
90.7k
{
2157
90.7k
  libcdata_internal_list_t *internal_list        = NULL;
2158
90.7k
  libcdata_list_element_t *next_element          = NULL;
2159
90.7k
  libcdata_list_element_t *previous_element      = NULL;
2160
90.7k
  libcdata_list_element_t *safe_existing_element = NULL;
2161
90.7k
  intptr_t *value_to_insert                      = NULL;
2162
90.7k
  static char *function                          = "libcdata_list_insert_element_with_existing";
2163
90.7k
  int element_index                              = 0;
2164
90.7k
  int result                                     = 1;
2165
2166
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2167
  libcdata_list_element_t *backup_first_element  = NULL;
2168
  libcdata_list_element_t *backup_last_element   = NULL;
2169
#endif
2170
2171
90.7k
  if( list == NULL )
2172
0
  {
2173
0
    libcerror_error_set(
2174
0
     error,
2175
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2176
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2177
0
     "%s: invalid list.",
2178
0
     function );
2179
2180
0
    return( -1 );
2181
0
  }
2182
90.7k
  internal_list = (libcdata_internal_list_t *) list;
2183
2184
90.7k
  if( internal_list->number_of_elements == 0 )
2185
892
  {
2186
892
    if( internal_list->first_element != NULL )
2187
0
    {
2188
0
      libcerror_error_set(
2189
0
       error,
2190
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2191
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2192
0
       "%s: corruption detected - first element already set.",
2193
0
       function );
2194
2195
0
      return( -1 );
2196
0
    }
2197
892
    if( internal_list->last_element != NULL )
2198
0
    {
2199
0
      libcerror_error_set(
2200
0
       error,
2201
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2202
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2203
0
       "%s: corruption detected - last element already set.",
2204
0
       function );
2205
2206
0
      return( -1 );
2207
0
    }
2208
892
  }
2209
89.8k
  else
2210
89.8k
  {
2211
89.8k
    if( internal_list->first_element == NULL )
2212
0
    {
2213
0
      libcerror_error_set(
2214
0
       error,
2215
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2216
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2217
0
       "%s: corruption detected - missing first element.",
2218
0
       function );
2219
2220
0
      return( -1 );
2221
0
    }
2222
89.8k
    if( internal_list->last_element == NULL )
2223
0
    {
2224
0
      libcerror_error_set(
2225
0
       error,
2226
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2227
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2228
0
       "%s: corruption detected - missing last element.",
2229
0
       function );
2230
2231
0
      return( -1 );
2232
0
    }
2233
89.8k
  }
2234
90.7k
  if( element_to_insert == NULL )
2235
0
  {
2236
0
    libcerror_error_set(
2237
0
     error,
2238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2239
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2240
0
     "%s: invalid element to insert.",
2241
0
     function );
2242
2243
0
    return( -1 );
2244
0
  }
2245
90.7k
  if( value_compare_function == NULL )
2246
0
  {
2247
0
    libcerror_error_set(
2248
0
     error,
2249
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2250
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2251
0
     "%s: invalid value compare function.",
2252
0
     function );
2253
2254
0
    return( -1 );
2255
0
  }
2256
90.7k
  if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
2257
0
  {
2258
0
    libcerror_error_set(
2259
0
     error,
2260
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2261
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2262
0
     "%s: unsupported insert flags: 0x%02" PRIx8 ".",
2263
0
     function,
2264
0
     insert_flags );
2265
2266
0
    return( -1 );
2267
0
  }
2268
90.7k
  if( existing_element == NULL )
2269
0
  {
2270
0
    libcerror_error_set(
2271
0
     error,
2272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2274
0
     "%s: invalid existing element.",
2275
0
     function );
2276
2277
0
    return( -1 );
2278
0
  }
2279
90.7k
  *existing_element = NULL;
2280
2281
90.7k
  if( libcdata_list_element_get_elements(
2282
90.7k
       element_to_insert,
2283
90.7k
       &previous_element,
2284
90.7k
       &next_element,
2285
90.7k
       error ) != 1 )
2286
0
  {
2287
0
    libcerror_error_set(
2288
0
     error,
2289
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2290
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2291
0
     "%s: unable to retrieve previous and next element from element to insert.",
2292
0
     function );
2293
2294
0
    return( -1 );
2295
0
  }
2296
90.7k
  if( ( previous_element != NULL )
2297
90.7k
   || ( next_element != NULL ) )
2298
0
  {
2299
0
    libcerror_error_set(
2300
0
     error,
2301
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2302
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2303
0
     "%s: invalid element to insert - already part of a list.",
2304
0
     function );
2305
2306
0
    return( -1 );
2307
0
  }
2308
90.7k
  if( libcdata_list_element_get_value(
2309
90.7k
       element_to_insert,
2310
90.7k
       &value_to_insert,
2311
90.7k
       error ) != 1 )
2312
0
  {
2313
0
    libcerror_error_set(
2314
0
     error,
2315
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2316
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2317
0
     "%s: unable to retrieve value from element to insert.",
2318
0
     function );
2319
2320
0
    return( -1 );
2321
0
  }
2322
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2323
  if( libcthreads_read_write_lock_grab_for_write(
2324
       internal_list->read_write_lock,
2325
       error ) != 1 )
2326
  {
2327
    libcerror_error_set(
2328
     error,
2329
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2330
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2331
     "%s: unable to grab read/write lock for writing.",
2332
     function );
2333
2334
    return( -1 );
2335
  }
2336
  backup_first_element = internal_list->first_element;
2337
  backup_last_element  = internal_list->last_element;
2338
2339
#endif /* defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) */
2340
2341
90.7k
  result = libcdata_internal_list_insert_element_find_element(
2342
90.7k
            internal_list,
2343
90.7k
            value_to_insert,
2344
90.7k
            value_compare_function,
2345
90.7k
            insert_flags,
2346
90.7k
            &element_index,
2347
90.7k
            &safe_existing_element,
2348
90.7k
            error );
2349
2350
90.7k
  if( result == -1 )
2351
0
  {
2352
0
    libcerror_error_set(
2353
0
     error,
2354
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2355
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2356
0
     "%s: unable to find element in list.",
2357
0
     function );
2358
2359
0
    result = -1;
2360
0
  }
2361
90.7k
  else if( result == 0 )
2362
0
  {
2363
0
    *existing_element = safe_existing_element;
2364
0
  }
2365
90.7k
  else
2366
90.7k
  {
2367
90.7k
    if( safe_existing_element != NULL )
2368
2.61k
    {
2369
2.61k
      if( libcdata_list_element_get_elements(
2370
2.61k
           safe_existing_element,
2371
2.61k
           &previous_element,
2372
2.61k
           &next_element,
2373
2.61k
           error ) != 1 )
2374
0
      {
2375
0
        libcerror_error_set(
2376
0
         error,
2377
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2378
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2379
0
         "%s: unable to retrieve previous and next element from list element: %d.",
2380
0
         function,
2381
0
         element_index );
2382
2383
0
        result = -1;
2384
0
      }
2385
2.61k
    }
2386
90.7k
    if( result == 1 )
2387
90.7k
    {
2388
90.7k
      if( libcdata_internal_list_insert_element_before_element(
2389
90.7k
           internal_list,
2390
90.7k
           safe_existing_element,
2391
90.7k
           element_to_insert,
2392
90.7k
           error ) != 1 )
2393
0
      {
2394
0
        libcerror_error_set(
2395
0
         error,
2396
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2397
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2398
0
         "%s: unable to insert element before list element.",
2399
0
         function );
2400
2401
0
        result = -1;
2402
0
      }
2403
90.7k
    }
2404
90.7k
  }
2405
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2406
  if( libcthreads_read_write_lock_release_for_write(
2407
       internal_list->read_write_lock,
2408
       error ) != 1 )
2409
  {
2410
    libcerror_error_set(
2411
     error,
2412
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2413
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2414
     "%s: unable to release read/write lock for writing.",
2415
     function );
2416
2417
    goto on_error;
2418
  }
2419
#endif
2420
90.7k
  return( result );
2421
2422
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2423
2424
on_error:
2425
  if( result == 1 )
2426
  {
2427
    libcdata_list_element_set_elements(
2428
     element_to_insert,
2429
     NULL,
2430
     NULL,
2431
     NULL );
2432
2433
    if( safe_existing_element != NULL )
2434
    {
2435
      libcdata_list_element_set_elements(
2436
       safe_existing_element,
2437
       previous_element,
2438
       next_element,
2439
       NULL );
2440
    }
2441
    else if( backup_last_element != NULL )
2442
    {
2443
      libcdata_list_element_set_next_element(
2444
       backup_last_element,
2445
       NULL,
2446
       NULL );
2447
    }
2448
    internal_list->first_element = backup_first_element;
2449
    internal_list->last_element  = backup_last_element;
2450
2451
    internal_list->number_of_elements -= 1;
2452
  }
2453
  return( -1 );
2454
2455
#endif /* defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA ) */
2456
90.7k
}
2457
2458
/* Inserts a value to the list
2459
 *
2460
 * Creates a new list element
2461
 *
2462
 * Uses the value_compare_function to determine the order of the entries
2463
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2464
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2465
 *
2466
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2467
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2468
 *
2469
 * Returns 1 if successful, 0 if the list element already exists or -1 on error
2470
 */
2471
int libcdata_list_insert_value(
2472
     libcdata_list_t *list,
2473
     intptr_t *value,
2474
     int (*value_compare_function)(
2475
            intptr_t *first_value,
2476
            intptr_t *second_value,
2477
            libcerror_error_t **error ),
2478
     uint8_t insert_flags,
2479
     libcerror_error_t **error )
2480
90.7k
{
2481
90.7k
  intptr_t *existing_value = NULL;
2482
90.7k
  static char *function    = "libcdata_list_insert_value";
2483
90.7k
  int result               = 0;
2484
2485
90.7k
  result = libcdata_list_insert_value_with_existing(
2486
90.7k
            list,
2487
90.7k
            value,
2488
90.7k
            value_compare_function,
2489
90.7k
            insert_flags,
2490
90.7k
            &existing_value,
2491
90.7k
            error );
2492
2493
90.7k
  if( result == -1 )
2494
0
  {
2495
0
    libcerror_error_set(
2496
0
     error,
2497
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2498
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2499
0
     "%s: unable to insert value into list.",
2500
0
     function );
2501
2502
0
    return( -1 );
2503
0
  }
2504
90.7k
  return( result );
2505
90.7k
}
2506
2507
/* Inserts a value to the list
2508
 *
2509
 * Creates a new list element
2510
 *
2511
 * Uses the value_compare_function to determine the order of the entries
2512
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
2513
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
2514
 *
2515
 * Duplicate entries are allowed by default and inserted after the last duplicate value.
2516
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
2517
 *
2518
 * Returns 1 if successful, 0 if the list element already exists or -1 on error
2519
 */
2520
int libcdata_list_insert_value_with_existing(
2521
     libcdata_list_t *list,
2522
     intptr_t *value,
2523
     int (*value_compare_function)(
2524
            intptr_t *first_value,
2525
            intptr_t *second_value,
2526
            libcerror_error_t **error ),
2527
     uint8_t insert_flags,
2528
     intptr_t **existing_value,
2529
     libcerror_error_t **error )
2530
90.7k
{
2531
90.7k
  libcdata_list_element_t *element          = NULL;
2532
90.7k
  libcdata_list_element_t *existing_element = NULL;
2533
90.7k
  static char *function                     = "libcdata_list_insert_value_with_existing";
2534
90.7k
  int result                                = 1;
2535
2536
90.7k
  if( existing_value == NULL )
2537
0
  {
2538
0
    libcerror_error_set(
2539
0
     error,
2540
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2541
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2542
0
     "%s: invalid existing value.",
2543
0
     function );
2544
2545
0
    return( -1 );
2546
0
  }
2547
90.7k
  *existing_value = NULL;
2548
2549
90.7k
  if( libcdata_list_element_initialize(
2550
90.7k
       &element,
2551
90.7k
       error ) != 1 )
2552
0
  {
2553
0
    libcerror_error_set(
2554
0
     error,
2555
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2556
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2557
0
     "%s: unable to create list element.",
2558
0
     function );
2559
2560
0
    return( -1 );
2561
0
  }
2562
90.7k
  if( libcdata_list_element_set_value(
2563
90.7k
       element,
2564
90.7k
       value,
2565
90.7k
       error ) != 1 )
2566
0
  {
2567
0
    libcerror_error_set(
2568
0
     error,
2569
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2570
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2571
0
     "%s: unable to set value of list element.",
2572
0
     function );
2573
2574
0
    goto on_error;
2575
0
  }
2576
90.7k
  result = libcdata_list_insert_element_with_existing(
2577
90.7k
            list,
2578
90.7k
            element,
2579
90.7k
            value_compare_function,
2580
90.7k
            insert_flags,
2581
90.7k
            &existing_element,
2582
90.7k
            error );
2583
2584
90.7k
  if( result == -1 )
2585
0
  {
2586
0
    libcerror_error_set(
2587
0
     error,
2588
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2589
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2590
0
     "%s: unable to insert element to list.",
2591
0
     function );
2592
2593
0
    goto on_error;
2594
0
  }
2595
90.7k
  else if( result == 0 )
2596
0
  {
2597
0
    if( libcdata_list_element_free(
2598
0
         &element,
2599
0
         NULL,
2600
0
         error ) != 1 )
2601
0
    {
2602
0
      libcerror_error_set(
2603
0
       error,
2604
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2605
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2606
0
       "%s: unable to free list element.",
2607
0
       function );
2608
2609
0
      goto on_error;
2610
0
    }
2611
0
    if( libcdata_list_element_get_value(
2612
0
         existing_element,
2613
0
         existing_value,
2614
0
         error ) != 1 )
2615
0
    {
2616
0
      libcerror_error_set(
2617
0
       error,
2618
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2619
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2620
0
       "%s: unable to retrieve value from existing list element.",
2621
0
       function );
2622
2623
0
      goto on_error;
2624
0
    }
2625
0
  }
2626
90.7k
  return( result );
2627
2628
0
on_error:
2629
0
  if( element != NULL )
2630
0
  {
2631
0
    libcdata_list_element_free(
2632
0
     &element,
2633
0
     NULL,
2634
0
     NULL );
2635
0
  }
2636
0
  return( -1 );
2637
90.7k
}
2638
2639
/* Removes a list element from the list
2640
 * Returns 1 if successful or -1 on error
2641
 */
2642
int libcdata_list_remove_element(
2643
     libcdata_list_t *list,
2644
     libcdata_list_element_t *element_to_remove,
2645
     libcerror_error_t **error )
2646
1.11M
{
2647
1.11M
  libcdata_internal_list_t *internal_list       = NULL;
2648
1.11M
  libcdata_list_element_t *next_element         = NULL;
2649
1.11M
  libcdata_list_element_t *previous_element     = NULL;
2650
1.11M
  static char *function                         = "libcdata_list_remove_element";
2651
1.11M
  int result                                    = 1;
2652
2653
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2654
  libcdata_list_element_t *backup_first_element = NULL;
2655
  libcdata_list_element_t *backup_last_element  = NULL;
2656
#endif
2657
2658
1.11M
  if( list == NULL )
2659
0
  {
2660
0
    libcerror_error_set(
2661
0
     error,
2662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2664
0
     "%s: invalid list.",
2665
0
     function );
2666
2667
0
    return( -1 );
2668
0
  }
2669
1.11M
  internal_list = (libcdata_internal_list_t *) list;
2670
2671
1.11M
  if( internal_list->number_of_elements == 0 )
2672
0
  {
2673
0
    if( internal_list->first_element != NULL )
2674
0
    {
2675
0
      libcerror_error_set(
2676
0
       error,
2677
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2678
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2679
0
       "%s: corruption detected - first element already set.",
2680
0
       function );
2681
2682
0
      return( -1 );
2683
0
    }
2684
0
    if( internal_list->last_element != NULL )
2685
0
    {
2686
0
      libcerror_error_set(
2687
0
       error,
2688
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2689
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2690
0
       "%s: corruption detected - last element already set.",
2691
0
       function );
2692
2693
0
      return( -1 );
2694
0
    }
2695
0
  }
2696
1.11M
  else
2697
1.11M
  {
2698
1.11M
    if( internal_list->first_element == NULL )
2699
0
    {
2700
0
      libcerror_error_set(
2701
0
       error,
2702
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2703
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2704
0
       "%s: corruption detected - missing first element.",
2705
0
       function );
2706
2707
0
      return( -1 );
2708
0
    }
2709
1.11M
    if( internal_list->last_element == NULL )
2710
0
    {
2711
0
      libcerror_error_set(
2712
0
       error,
2713
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2714
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2715
0
       "%s: corruption detected - missing last element.",
2716
0
       function );
2717
2718
0
      return( -1 );
2719
0
    }
2720
1.11M
  }
2721
1.11M
  if( element_to_remove == NULL )
2722
0
  {
2723
0
    libcerror_error_set(
2724
0
     error,
2725
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2726
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2727
0
     "%s: invalid element to remove.",
2728
0
     function );
2729
2730
0
    return( -1 );
2731
0
  }
2732
1.11M
  if( libcdata_list_element_get_elements(
2733
1.11M
       element_to_remove,
2734
1.11M
       &previous_element,
2735
1.11M
       &next_element,
2736
1.11M
       error ) != 1 )
2737
0
  {
2738
0
    libcerror_error_set(
2739
0
     error,
2740
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2741
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2742
0
     "%s: unable to retrieve previous and next element from element to remove.",
2743
0
     function );
2744
2745
0
    return( -1 );
2746
0
  }
2747
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2748
  if( libcthreads_read_write_lock_grab_for_write(
2749
       internal_list->read_write_lock,
2750
       error ) != 1 )
2751
  {
2752
    libcerror_error_set(
2753
     error,
2754
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2755
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2756
     "%s: unable to grab read/write lock for writing.",
2757
     function );
2758
2759
    return( -1 );
2760
  }
2761
  backup_first_element = internal_list->first_element;
2762
  backup_last_element  = internal_list->last_element;
2763
2764
#endif
2765
1.11M
  result = libcdata_list_element_set_elements(
2766
1.11M
            element_to_remove,
2767
1.11M
            NULL,
2768
1.11M
            NULL,
2769
1.11M
            error );
2770
2771
1.11M
  if( result != 1 )
2772
0
  {
2773
0
    libcerror_error_set(
2774
0
     error,
2775
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2776
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2777
0
     "%s: unable to set previous and next element of element to remove.",
2778
0
     function );
2779
2780
0
    result = -1;
2781
0
  }
2782
1.11M
  if( result == 1 )
2783
1.11M
  {
2784
1.11M
    if( next_element != NULL )
2785
631k
    {
2786
631k
      result = libcdata_list_element_set_previous_element(
2787
631k
                next_element,
2788
631k
                previous_element,
2789
631k
                error );
2790
2791
631k
      if( result != 1 )
2792
0
      {
2793
0
        libcerror_error_set(
2794
0
         error,
2795
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2796
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2797
0
         "%s: unable to set previous element of next element.",
2798
0
         function );
2799
2800
0
        libcdata_list_element_set_elements(
2801
0
         element_to_remove,
2802
0
         previous_element,
2803
0
         next_element,
2804
0
         NULL );
2805
2806
0
        result = -1;
2807
0
      }
2808
631k
    }
2809
1.11M
  }
2810
1.11M
  if( result == 1 )
2811
1.11M
  {
2812
1.11M
    if( previous_element != NULL )
2813
79.6k
    {
2814
79.6k
      result = libcdata_list_element_set_next_element(
2815
79.6k
                previous_element,
2816
79.6k
                next_element,
2817
79.6k
                error );
2818
2819
79.6k
      if( result != 1 )
2820
0
      {
2821
0
        libcerror_error_set(
2822
0
         error,
2823
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2824
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2825
0
         "%s: unable to set next element of previous element.",
2826
0
         function );
2827
2828
0
        if( next_element != NULL )
2829
0
        {
2830
0
          libcdata_list_element_set_previous_element(
2831
0
           next_element,
2832
0
           element_to_remove,
2833
0
           NULL );
2834
0
        }
2835
0
        libcdata_list_element_set_elements(
2836
0
         element_to_remove,
2837
0
         previous_element,
2838
0
         next_element,
2839
0
         NULL );
2840
2841
0
        result = -1;
2842
0
      }
2843
79.6k
    }
2844
1.11M
  }
2845
1.11M
  if( result == 1 )
2846
1.11M
  {
2847
1.11M
    if( element_to_remove == internal_list->first_element )
2848
1.03M
    {
2849
1.03M
      internal_list->first_element = next_element;
2850
1.03M
    }
2851
1.11M
    if( element_to_remove == internal_list->last_element )
2852
482k
    {
2853
482k
      internal_list->last_element = previous_element;
2854
482k
    }
2855
1.11M
    internal_list->number_of_elements -= 1;
2856
1.11M
  }
2857
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2858
  if( libcthreads_read_write_lock_release_for_write(
2859
       internal_list->read_write_lock,
2860
       error ) != 1 )
2861
  {
2862
    libcerror_error_set(
2863
     error,
2864
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2865
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2866
     "%s: unable to release read/write lock for writing.",
2867
     function );
2868
2869
    goto on_error;
2870
  }
2871
#endif
2872
1.11M
  return( result );
2873
2874
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2875
on_error:
2876
  if( result == 1 )
2877
  {
2878
    libcdata_list_element_set_elements(
2879
     element_to_remove,
2880
     previous_element,
2881
     next_element,
2882
     NULL );
2883
2884
    if( next_element != NULL )
2885
    {
2886
      libcdata_list_element_set_previous_element(
2887
       next_element,
2888
       element_to_remove,
2889
       NULL );
2890
    }
2891
    if( previous_element != NULL )
2892
    {
2893
      libcdata_list_element_set_next_element(
2894
       previous_element,
2895
       element_to_remove,
2896
       NULL );
2897
    }
2898
    internal_list->first_element = backup_first_element;
2899
    internal_list->last_element  = backup_last_element;
2900
2901
    internal_list->number_of_elements += 1;
2902
  }
2903
  return( -1 );
2904
#endif
2905
1.11M
}
2906