Coverage Report

Created: 2024-02-25 07:19

/src/libluksde/libcdata/libcdata_array.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Array 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_array.h"
27
#include "libcdata_definitions.h"
28
#include "libcdata_libcerror.h"
29
#include "libcdata_libcthreads.h"
30
#include "libcdata_types.h"
31
32
/* Creates an array
33
 * Make sure the value array is referencing, is set to NULL
34
 * Returns 1 if successful or -1 on error
35
 */
36
int libcdata_array_initialize(
37
     libcdata_array_t **array,
38
     int number_of_entries,
39
     libcerror_error_t **error )
40
1.09k
{
41
1.09k
  libcdata_internal_array_t *internal_array = NULL;
42
1.09k
  static char *function                     = "libcdata_array_initialize";
43
1.09k
  size_t entries_size                       = 0;
44
1.09k
  int number_of_allocated_entries           = 0;
45
46
1.09k
  if( array == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid array.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
1.09k
  if( *array != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid array value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
1.09k
  if( number_of_entries < 0 )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
74
0
     "%s: invalid number of entries value less than zero.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
1.09k
  internal_array = memory_allocate_structure(
80
1.09k
                    libcdata_internal_array_t );
81
82
1.09k
  if( internal_array == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create array.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
1.09k
  if( memory_set(
94
1.09k
       internal_array,
95
1.09k
       0,
96
1.09k
       sizeof( libcdata_internal_array_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear array.",
103
0
     function );
104
105
0
    memory_free(
106
0
     internal_array );
107
108
0
    return( -1 );
109
0
  }
110
  /* Pre-allocate in blocks of 16 entries
111
   */
112
1.09k
  if( number_of_entries >= (int) ( INT_MAX - 16 ) )
113
0
  {
114
0
    number_of_allocated_entries = INT_MAX;
115
0
  }
116
1.09k
  else
117
1.09k
  {
118
1.09k
    number_of_allocated_entries = ( number_of_entries & ~( 15 ) ) + 16;
119
1.09k
  }
120
1.09k
#if SIZEOF_INT <= SIZEOF_SIZE_T
121
1.09k
  if( (size_t) number_of_allocated_entries > (size_t) ( SSIZE_MAX / sizeof( intptr_t * ) ) )
122
#else
123
  if( number_of_allocated_entries > (int) ( SSIZE_MAX / sizeof( intptr_t * ) ) )
124
#endif
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
129
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
130
0
     "%s: invalid number of allocated entries value exceeds maximum.",
131
0
     function );
132
133
0
    goto on_error;
134
0
  }
135
1.09k
  entries_size = sizeof( intptr_t * ) * number_of_allocated_entries;
136
137
1.09k
  if( entries_size > (size_t) LIBCDATA_ARRAY_ENTRIES_MEMORY_LIMIT )
138
0
  {
139
0
    libcerror_error_set(
140
0
     error,
141
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
142
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
143
0
     "%s: invalid entries size value exceeds maximum.",
144
0
     function );
145
146
0
    goto on_error;
147
0
  }
148
1.09k
  internal_array->entries = (intptr_t **) memory_allocate(
149
1.09k
                                           entries_size );
150
151
1.09k
  if( internal_array->entries == NULL )
152
0
  {
153
0
    libcerror_error_set(
154
0
     error,
155
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
156
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
157
0
     "%s: unable to create array entries.",
158
0
     function );
159
160
0
    goto on_error;
161
0
  }
162
1.09k
  if( memory_set(
163
1.09k
       internal_array->entries,
164
1.09k
       0,
165
1.09k
       entries_size ) == NULL )
166
0
  {
167
0
    libcerror_error_set(
168
0
     error,
169
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
170
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
171
0
     "%s: unable to clear array entries.",
172
0
     function );
173
174
0
    goto on_error;
175
0
  }
176
1.09k
  internal_array->number_of_allocated_entries = number_of_allocated_entries;
177
1.09k
  internal_array->number_of_entries           = number_of_entries;
178
179
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
180
  if( libcthreads_read_write_lock_initialize(
181
       &( internal_array->read_write_lock ),
182
       error ) != 1 )
183
  {
184
    libcerror_error_set(
185
     error,
186
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
187
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
188
     "%s: unable to initialize read/write lock.",
189
     function );
190
191
    goto on_error;
192
  }
193
#endif
194
1.09k
  *array = (libcdata_array_t *) internal_array;
195
196
1.09k
  return( 1 );
197
198
0
on_error:
199
0
  if( internal_array != NULL )
200
0
  {
201
0
    if( internal_array->entries != NULL )
202
0
    {
203
0
      memory_free(
204
0
       internal_array->entries );
205
0
    }
206
0
    memory_free(
207
0
     internal_array );
208
0
  }
209
0
  return( -1 );
210
1.09k
}
211
212
/* Frees an array
213
 * The entries are freed using the entry_free_function
214
 * Returns 1 if successful or -1 on error
215
 */
216
int libcdata_array_free(
217
     libcdata_array_t **array,
218
     int (*entry_free_function)(
219
            intptr_t **entry,
220
            libcerror_error_t **error ),
221
     libcerror_error_t **error )
222
1.09k
{
223
1.09k
  libcdata_internal_array_t *internal_array = NULL;
224
1.09k
  static char *function                     = "libcdata_array_free";
225
1.09k
  int result                                = 1;
226
227
1.09k
  if( array == NULL )
228
0
  {
229
0
    libcerror_error_set(
230
0
     error,
231
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
233
0
     "%s: invalid array.",
234
0
     function );
235
236
0
    return( -1 );
237
0
  }
238
1.09k
  if( *array != NULL )
239
1.09k
  {
240
1.09k
    internal_array = (libcdata_internal_array_t *) *array;
241
1.09k
    *array         = NULL;
242
243
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
244
    if( libcthreads_read_write_lock_free(
245
         &( internal_array->read_write_lock ),
246
         error ) != 1 )
247
    {
248
      libcerror_error_set(
249
       error,
250
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
251
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
252
       "%s: unable to free read/write lock.",
253
       function );
254
255
      result = -1;
256
    }
257
#endif
258
1.09k
    if( internal_array->entries != NULL )
259
1.09k
    {
260
1.09k
      if( libcdata_internal_array_clear(
261
1.09k
           internal_array,
262
1.09k
           entry_free_function,
263
1.09k
           error ) != 1 )
264
0
      {
265
0
        libcerror_error_set(
266
0
         error,
267
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
268
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
269
0
         "%s: unable to clear array.",
270
0
         function );
271
272
0
        result = -1;
273
0
      }
274
1.09k
      memory_free(
275
1.09k
       internal_array->entries );
276
1.09k
    }
277
1.09k
    memory_free(
278
1.09k
     internal_array );
279
1.09k
  }
280
1.09k
  return( result );
281
1.09k
}
282
283
/* Empties an array and frees its entries
284
 * The entries are freed using the entry_free_function
285
 * If the entry_free_function fails for a specific entry it is not freed and kept in the array
286
 *
287
 * Returns 1 if successful or -1 on error
288
 */
289
int libcdata_array_empty(
290
     libcdata_array_t *array,
291
     int (*entry_free_function)(
292
            intptr_t **entry,
293
            libcerror_error_t **error ),
294
     libcerror_error_t **error )
295
248
{
296
248
  libcdata_internal_array_t *internal_array = NULL;
297
248
  static char *function                     = "libcdata_array_empty";
298
248
  int result                                = 1;
299
300
248
  if( array == NULL )
301
0
  {
302
0
    libcerror_error_set(
303
0
     error,
304
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
305
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
306
0
     "%s: invalid array.",
307
0
     function );
308
309
0
    return( -1 );
310
0
  }
311
248
  internal_array = (libcdata_internal_array_t *) array;
312
313
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
314
  if( libcthreads_read_write_lock_grab_for_write(
315
       internal_array->read_write_lock,
316
       error ) != 1 )
317
  {
318
    libcerror_error_set(
319
     error,
320
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
321
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
322
     "%s: unable to grab read/write lock for writing.",
323
     function );
324
325
    return( -1 );
326
  }
327
#endif
328
248
  if( libcdata_internal_array_clear(
329
248
       internal_array,
330
248
       entry_free_function,
331
248
       error ) != 1 )
332
0
  {
333
0
    libcerror_error_set(
334
0
     error,
335
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
336
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
337
0
     "%s: unable to clear array.",
338
0
     function );
339
340
0
    result = -1;
341
0
  }
342
248
  else
343
248
  {
344
248
    internal_array->number_of_entries = 0;
345
248
  }
346
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
347
  if( libcthreads_read_write_lock_release_for_write(
348
       internal_array->read_write_lock,
349
       error ) != 1 )
350
  {
351
    libcerror_error_set(
352
     error,
353
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
354
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
355
     "%s: unable to release read/write lock for writing.",
356
     function );
357
358
    return( -1 );
359
  }
360
#endif
361
248
  return( result );
362
248
}
363
364
/* Clears an array and frees its entries
365
 * The entries are freed using the entry_free_function
366
 * If the entry_free_function fails for a specific entry it is not freed and kept in the array
367
 *
368
 * This function is not multi-thread safe acquire write lock before call
369
 * Returns 1 if successful or -1 on error
370
 */
371
int libcdata_internal_array_clear(
372
     libcdata_internal_array_t *internal_array,
373
     int (*entry_free_function)(
374
            intptr_t **entry,
375
            libcerror_error_t **error ),
376
     libcerror_error_t **error )
377
1.34k
{
378
1.34k
  static char *function = "libcdata_internal_array_clear";
379
1.34k
  int entry_free_result = 0;
380
1.34k
  int entry_iterator    = 0;
381
1.34k
  int result            = 1;
382
383
1.34k
  if( internal_array == NULL )
384
0
  {
385
0
    libcerror_error_set(
386
0
     error,
387
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
389
0
     "%s: invalid array.",
390
0
     function );
391
392
0
    return( -1 );
393
0
  }
394
1.34k
  if( internal_array->entries == NULL )
395
0
  {
396
0
    libcerror_error_set(
397
0
     error,
398
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
399
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
400
0
     "%s: invalid array - missing entries.",
401
0
     function );
402
403
0
    return( -1 );
404
0
  }
405
1.34k
  for( entry_iterator = 0;
406
8.19k
       entry_iterator < internal_array->number_of_entries;
407
6.84k
       entry_iterator++ )
408
6.84k
  {
409
6.84k
    if( internal_array->entries[ entry_iterator ] != NULL )
410
6.19k
    {
411
6.19k
      if( entry_free_function == NULL )
412
0
      {
413
0
        entry_free_result = 1;
414
0
      }
415
6.19k
      else
416
6.19k
      {
417
6.19k
        entry_free_result = entry_free_function(
418
6.19k
                             &( internal_array->entries[ entry_iterator ] ),
419
6.19k
                             error );
420
6.19k
      }
421
6.19k
      if( entry_free_result != 1 )
422
0
      {
423
0
        libcerror_error_set(
424
0
         error,
425
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
426
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
427
0
         "%s: unable to free array entry: %d.",
428
0
         function,
429
0
         entry_iterator );
430
431
0
        result = -1;
432
0
      }
433
6.19k
      else
434
6.19k
      {
435
6.19k
        internal_array->entries[ entry_iterator ] = NULL;
436
6.19k
      }
437
6.19k
    }
438
6.84k
  }
439
1.34k
  return( result );
440
1.34k
}
441
442
/* Clears an array and frees its entries
443
 * The entries are freed using the entry_free_function
444
 * If the entry_free_function fails for a specific entry it is not freed and kept in the array
445
 *
446
 * Returns 1 if successful or -1 on error
447
 */
448
int libcdata_array_clear(
449
     libcdata_array_t *array,
450
     int (*entry_free_function)(
451
            intptr_t **entry,
452
            libcerror_error_t **error ),
453
     libcerror_error_t **error )
454
0
{
455
0
  libcdata_internal_array_t *internal_array = NULL;
456
0
  static char *function                     = "libcdata_array_clear";
457
0
  int result                                = 1;
458
459
0
  if( array == NULL )
460
0
  {
461
0
    libcerror_error_set(
462
0
     error,
463
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
464
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
465
0
     "%s: invalid array.",
466
0
     function );
467
468
0
    return( -1 );
469
0
  }
470
0
  internal_array = (libcdata_internal_array_t *) array;
471
472
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
473
  if( libcthreads_read_write_lock_grab_for_write(
474
       internal_array->read_write_lock,
475
       error ) != 1 )
476
  {
477
    libcerror_error_set(
478
     error,
479
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
480
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
481
     "%s: unable to grab read/write lock for writing.",
482
     function );
483
484
    return( -1 );
485
  }
486
#endif
487
0
  if( libcdata_internal_array_clear(
488
0
       internal_array,
489
0
       entry_free_function,
490
0
       error ) != 1 )
491
0
  {
492
0
    libcerror_error_set(
493
0
     error,
494
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
496
0
     "%s: unable to clear array.",
497
0
     function );
498
499
0
    result = -1;
500
0
  }
501
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
502
  if( libcthreads_read_write_lock_release_for_write(
503
       internal_array->read_write_lock,
504
       error ) != 1 )
505
  {
506
    libcerror_error_set(
507
     error,
508
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
509
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
510
     "%s: unable to release read/write lock for writing.",
511
     function );
512
513
    return( -1 );
514
  }
515
#endif
516
0
  return( result );
517
0
}
518
519
/* Clones the array and its entries
520
 *
521
 * The entries are cloned using the entry_clone_function
522
 * On error the entries are freed using the entry_free_function
523
 *
524
 * Returns 1 if successful or -1 on error
525
 */
526
int libcdata_array_clone(
527
     libcdata_array_t **destination_array,
528
     libcdata_array_t *source_array,
529
     int (*entry_free_function)(
530
            intptr_t **entry,
531
            libcerror_error_t **error ),
532
     int (*entry_clone_function)(
533
            intptr_t **destination_entry,
534
            intptr_t *source_entry,
535
            libcerror_error_t **error ),
536
     libcerror_error_t **error )
537
0
{
538
0
  libcdata_internal_array_t *internal_destination_array = NULL;
539
0
  libcdata_internal_array_t *internal_source_array      = NULL;
540
0
  static char *function                                 = "libcdata_array_clone";
541
0
  int entry_iterator                                    = 0;
542
543
0
  if( destination_array == NULL )
544
0
  {
545
0
    libcerror_error_set(
546
0
     error,
547
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
548
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
549
0
     "%s: invalid destination array.",
550
0
     function );
551
552
0
    return( -1 );
553
0
  }
554
0
  if( *destination_array != NULL )
555
0
  {
556
0
    libcerror_error_set(
557
0
     error,
558
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
559
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
560
0
     "%s: invalid destination array already set.",
561
0
     function );
562
563
0
    return( -1 );
564
0
  }
565
0
  if( entry_free_function == NULL )
566
0
  {
567
0
    libcerror_error_set(
568
0
     error,
569
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
571
0
     "%s: invalid entry free function.",
572
0
     function );
573
574
0
    return( -1 );
575
0
  }
576
0
  if( entry_clone_function == NULL )
577
0
  {
578
0
    libcerror_error_set(
579
0
     error,
580
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
581
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
582
0
     "%s: invalid entry clone function.",
583
0
     function );
584
585
0
    return( -1 );
586
0
  }
587
0
  if( source_array == NULL )
588
0
  {
589
0
    *destination_array = NULL;
590
591
0
    return( 1 );
592
0
  }
593
0
  internal_source_array = (libcdata_internal_array_t *) source_array;
594
595
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
596
  if( libcthreads_read_write_lock_grab_for_read(
597
       internal_source_array->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
0
  if( libcdata_array_initialize(
611
0
       (libcdata_array_t **) &internal_destination_array,
612
0
       internal_source_array->number_of_entries,
613
0
       error ) != 1 )
614
0
  {
615
0
    libcerror_error_set(
616
0
     error,
617
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
618
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
619
0
     "%s: unable to create destination array.",
620
0
     function );
621
622
0
    goto on_error;
623
0
  }
624
0
  if( internal_destination_array == NULL )
625
0
  {
626
0
    libcerror_error_set(
627
0
     error,
628
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
629
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
630
0
     "%s: missing destination array.",
631
0
     function );
632
633
0
    goto on_error;
634
0
  }
635
0
  if( internal_source_array->entries != NULL )
636
0
  {
637
0
    for( entry_iterator = 0;
638
0
         entry_iterator < internal_source_array->number_of_entries;
639
0
         entry_iterator++ )
640
0
    {
641
0
      if( internal_source_array->entries[ entry_iterator ] != NULL )
642
0
      {
643
0
        if( entry_clone_function(
644
0
             &( internal_destination_array->entries[ entry_iterator ] ),
645
0
             internal_source_array->entries[ entry_iterator ],
646
0
             error ) != 1 )
647
0
        {
648
0
          libcerror_error_set(
649
0
           error,
650
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
651
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
652
0
           "%s: unable to create destination array entry: %d.",
653
0
           function,
654
0
           entry_iterator );
655
656
0
          goto on_error;
657
0
        }
658
0
      }
659
0
    }
660
0
  }
661
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
662
  if( libcthreads_read_write_lock_release_for_read(
663
       internal_source_array->read_write_lock,
664
       error ) != 1 )
665
  {
666
    libcerror_error_set(
667
     error,
668
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
669
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
670
     "%s: unable to release read/write lock for reading.",
671
     function );
672
673
    libcdata_array_free(
674
     (libcdata_array_t **) &internal_destination_array,
675
     entry_free_function,
676
     NULL );
677
678
    return( -1 );
679
  }
680
#endif
681
0
  *destination_array = (libcdata_array_t *) internal_destination_array;
682
683
0
  return( 1 );
684
685
0
on_error:
686
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
687
  libcthreads_read_write_lock_release_for_read(
688
   internal_source_array->read_write_lock,
689
   NULL );
690
#endif
691
0
  if( internal_destination_array != NULL )
692
0
  {
693
0
    libcdata_array_free(
694
0
     (libcdata_array_t **) &internal_destination_array,
695
0
     entry_free_function,
696
0
     NULL );
697
0
  }
698
0
  return( -1 );
699
0
}
700
701
/* Resizes an array
702
 * This function is not multi-thread safe acquire write lock before call
703
 * Returns 1 if successful or -1 on error
704
 */
705
int libcdata_internal_array_resize(
706
     libcdata_internal_array_t *internal_array,
707
     int number_of_entries,
708
     int (*entry_free_function)(
709
            intptr_t **entry,
710
            libcerror_error_t **error ),
711
     libcerror_error_t **error )
712
6.19k
{
713
6.19k
  static char *function           = "libcdata_internal_array_resize";
714
6.19k
  void *reallocation              = NULL;
715
6.19k
  size_t entries_size             = 0;
716
6.19k
  int entry_iterator              = 0;
717
6.19k
  int number_of_allocated_entries = 0;
718
6.19k
  int result                      = 1;
719
720
6.19k
  if( internal_array == NULL )
721
0
  {
722
0
    libcerror_error_set(
723
0
     error,
724
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
725
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
726
0
     "%s: invalid array.",
727
0
     function );
728
729
0
    return( -1 );
730
0
  }
731
6.19k
  if( internal_array->entries == NULL )
732
0
  {
733
0
    libcerror_error_set(
734
0
     error,
735
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
737
0
     "%s: invalid array - missing entries.",
738
0
     function );
739
740
0
    return( -1 );
741
0
  }
742
6.19k
  if( number_of_entries < 0 )
743
0
  {
744
0
    libcerror_error_set(
745
0
     error,
746
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
747
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
748
0
     "%s: invalid number of entries value less than zero.",
749
0
     function );
750
751
0
    return( -1 );
752
0
  }
753
6.19k
  if( number_of_entries > internal_array->number_of_allocated_entries )
754
0
  {
755
    /* Pre-allocate in blocks of 16 entries
756
     */
757
0
    if( number_of_entries >= (int) ( INT_MAX - 16 ) )
758
0
    {
759
0
      number_of_allocated_entries = INT_MAX;
760
0
    }
761
0
    else
762
0
    {
763
0
      number_of_allocated_entries = ( number_of_entries & ~( 15 ) ) + 16;
764
0
    }
765
0
#if SIZEOF_INT <= SIZEOF_SIZE_T
766
0
    if( (size_t) number_of_allocated_entries > (size_t) ( SSIZE_MAX / sizeof( intptr_t * ) ) )
767
#else
768
    if( number_of_allocated_entries > (int) ( SSIZE_MAX / sizeof( intptr_t * ) ) )
769
#endif
770
0
    {
771
0
      libcerror_error_set(
772
0
       error,
773
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
774
0
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
775
0
       "%s: invalid number of allocated entries value exceeds maximum.",
776
0
       function );
777
778
0
      return( -1 );
779
0
    }
780
0
    entries_size = sizeof( intptr_t * ) * number_of_allocated_entries;
781
782
0
    if( entries_size > (size_t) LIBCDATA_ARRAY_ENTRIES_MEMORY_LIMIT )
783
0
    {
784
0
      libcerror_error_set(
785
0
       error,
786
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
787
0
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
788
0
       "%s: invalid entries size value exceeds maximum.",
789
0
       function );
790
791
0
      return( -1 );
792
0
    }
793
0
    reallocation = memory_reallocate(
794
0
                    internal_array->entries,
795
0
                    entries_size );
796
797
0
    if( reallocation == NULL )
798
0
    {
799
0
      libcerror_error_set(
800
0
       error,
801
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
802
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
803
0
       "%s: unable to resize array entries.",
804
0
       function );
805
806
0
      return( -1 );
807
0
    }
808
0
    internal_array->entries = (intptr_t **) reallocation;
809
810
    /* Cannot use memset reliably here. The loop below will be removed
811
     * when memset is used and the code is optimized. Therefore the loop
812
     * is not executed when memset fails.
813
     */
814
0
    for( entry_iterator = internal_array->number_of_allocated_entries;
815
0
         entry_iterator < number_of_allocated_entries;
816
0
         entry_iterator++ )
817
0
    {
818
0
      internal_array->entries[ entry_iterator ] = NULL;
819
0
    }
820
0
    internal_array->number_of_allocated_entries = number_of_allocated_entries;
821
0
    internal_array->number_of_entries           = number_of_entries;
822
0
  }
823
6.19k
  else if( number_of_entries > internal_array->number_of_entries )
824
6.19k
  {
825
6.19k
    internal_array->number_of_entries = number_of_entries;
826
6.19k
  }
827
0
  else if( internal_array->entries != NULL )
828
0
  {
829
0
    for( entry_iterator = number_of_entries;
830
0
         entry_iterator < internal_array->number_of_entries;
831
0
         entry_iterator++ )
832
0
    {
833
0
      if( internal_array->entries[ entry_iterator ] != NULL )
834
0
      {
835
0
        if( entry_free_function == NULL )
836
0
        {
837
0
          libcerror_error_set(
838
0
           error,
839
0
           LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
840
0
           LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
841
0
           "%s: invalid entry free function.",
842
0
           function );
843
844
0
          return( -1 );
845
0
        }
846
0
        if( entry_free_function(
847
0
             &( internal_array->entries[ entry_iterator ] ),
848
0
             error ) != 1 )
849
0
        {
850
0
          libcerror_error_set(
851
0
           error,
852
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
853
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
854
0
           "%s: unable to free array entry: %d.",
855
0
           function,
856
0
           entry_iterator );
857
858
0
          result = -1;
859
0
        }
860
0
        internal_array->entries[ entry_iterator ] = NULL;
861
0
      }
862
0
    }
863
0
    internal_array->number_of_entries = number_of_entries;
864
0
  }
865
6.19k
  return( result );
866
6.19k
}
867
868
/* Resizes an array
869
 * Returns 1 if successful or -1 on error
870
 */
871
int libcdata_array_resize(
872
     libcdata_array_t *array,
873
     int number_of_entries,
874
     int (*entry_free_function)(
875
            intptr_t **entry,
876
            libcerror_error_t **error ),
877
     libcerror_error_t **error )
878
0
{
879
0
  libcdata_internal_array_t *internal_array = NULL;
880
0
  static char *function                     = "libcdata_array_resize";
881
0
  int result                                = 1;
882
883
0
  if( array == NULL )
884
0
  {
885
0
    libcerror_error_set(
886
0
     error,
887
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
888
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
889
0
     "%s: invalid array.",
890
0
     function );
891
892
0
    return( -1 );
893
0
  }
894
0
  internal_array = (libcdata_internal_array_t *) array;
895
896
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
897
  if( libcthreads_read_write_lock_grab_for_write(
898
       internal_array->read_write_lock,
899
       error ) != 1 )
900
  {
901
    libcerror_error_set(
902
     error,
903
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
904
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
905
     "%s: unable to grab read/write lock for writing.",
906
     function );
907
908
    return( -1 );
909
  }
910
#endif
911
0
  if( libcdata_internal_array_resize(
912
0
       internal_array,
913
0
       number_of_entries,
914
0
       entry_free_function,
915
0
       error ) != 1 )
916
0
  {
917
0
    libcerror_error_set(
918
0
     error,
919
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
920
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
921
0
     "%s: unable to resize array.",
922
0
     function );
923
924
0
    result = -1;
925
0
  }
926
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
927
  if( libcthreads_read_write_lock_release_for_write(
928
       internal_array->read_write_lock,
929
       error ) != 1 )
930
  {
931
    libcerror_error_set(
932
     error,
933
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
934
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
935
     "%s: unable to release read/write lock for writing.",
936
     function );
937
938
    return( -1 );
939
  }
940
#endif
941
0
  return( result );
942
0
}
943
944
/* Reverses the order of the entries in the array
945
 * Returns 1 if successful or -1 on error
946
 */
947
int libcdata_array_reverse(
948
     libcdata_array_t *array,
949
     libcerror_error_t **error )
950
0
{
951
0
  libcdata_internal_array_t *internal_array = NULL;
952
0
  intptr_t *entry                           = NULL;
953
0
  static char *function                     = "libcdata_array_reverse";
954
0
  int entry_iterator                        = 0;
955
0
  int reverse_entry_iterator                = 0;
956
957
0
  if( array == NULL )
958
0
  {
959
0
    libcerror_error_set(
960
0
     error,
961
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
962
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
963
0
     "%s: invalid array.",
964
0
     function );
965
966
0
    return( -1 );
967
0
  }
968
0
  internal_array = (libcdata_internal_array_t *) array;
969
970
0
  if( internal_array->entries == NULL )
971
0
  {
972
0
    libcerror_error_set(
973
0
     error,
974
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
975
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
976
0
     "%s: invalid array - missing entries.",
977
0
     function );
978
979
0
    return( -1 );
980
0
  }
981
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
982
  if( libcthreads_read_write_lock_grab_for_write(
983
       internal_array->read_write_lock,
984
       error ) != 1 )
985
  {
986
    libcerror_error_set(
987
     error,
988
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
989
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
990
     "%s: unable to grab read/write lock for writing.",
991
     function );
992
993
    return( -1 );
994
  }
995
#endif
996
0
  if( internal_array->number_of_entries > 1 )
997
0
  {
998
0
    reverse_entry_iterator = internal_array->number_of_entries - 1;
999
1000
0
    while( entry_iterator < reverse_entry_iterator )
1001
0
    {
1002
0
      entry = internal_array->entries[ reverse_entry_iterator ];
1003
0
      internal_array->entries[ reverse_entry_iterator ] = internal_array->entries[ entry_iterator ];
1004
0
      internal_array->entries[ entry_iterator ] = entry;
1005
1006
0
      entry_iterator++;
1007
0
      reverse_entry_iterator--;
1008
0
    }
1009
0
  }
1010
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1011
  if( libcthreads_read_write_lock_release_for_write(
1012
       internal_array->read_write_lock,
1013
       error ) != 1 )
1014
  {
1015
    libcerror_error_set(
1016
     error,
1017
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1019
     "%s: unable to release read/write lock for writing.",
1020
     function );
1021
1022
    return( -1 );
1023
  }
1024
#endif
1025
0
  return( 1 );
1026
0
}
1027
1028
/* Retrieves the number of entries in the array
1029
 * Returns 1 if successful or -1 on error
1030
 */
1031
int libcdata_array_get_number_of_entries(
1032
     libcdata_array_t *array,
1033
     int *number_of_entries,
1034
     libcerror_error_t **error )
1035
0
{
1036
0
  libcdata_internal_array_t *internal_array = NULL;
1037
0
  static char *function                     = "libcdata_array_get_number_of_entries";
1038
1039
0
  if( array == NULL )
1040
0
  {
1041
0
    libcerror_error_set(
1042
0
     error,
1043
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1044
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1045
0
     "%s: invalid array.",
1046
0
     function );
1047
1048
0
    return( -1 );
1049
0
  }
1050
0
  internal_array = (libcdata_internal_array_t *) array;
1051
1052
0
  if( number_of_entries == NULL )
1053
0
  {
1054
0
    libcerror_error_set(
1055
0
     error,
1056
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1057
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1058
0
     "%s: invalid number of entries.",
1059
0
     function );
1060
1061
0
    return( -1 );
1062
0
  }
1063
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1064
  if( libcthreads_read_write_lock_grab_for_read(
1065
       internal_array->read_write_lock,
1066
       error ) != 1 )
1067
  {
1068
    libcerror_error_set(
1069
     error,
1070
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1071
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1072
     "%s: unable to grab read/write lock for reading.",
1073
     function );
1074
1075
    return( -1 );
1076
  }
1077
#endif
1078
0
  *number_of_entries = internal_array->number_of_entries;
1079
1080
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1081
  if( libcthreads_read_write_lock_release_for_read(
1082
       internal_array->read_write_lock,
1083
       error ) != 1 )
1084
  {
1085
    libcerror_error_set(
1086
     error,
1087
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1088
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1089
     "%s: unable to release read/write lock for reading.",
1090
     function );
1091
1092
    return( -1 );
1093
  }
1094
#endif
1095
0
  return( 1 );
1096
0
}
1097
1098
/* Retrieves a specific entry from the array
1099
 * Returns 1 if successful or -1 on error
1100
 */
1101
int libcdata_array_get_entry_by_index(
1102
     libcdata_array_t *array,
1103
     int entry_index,
1104
     intptr_t **entry,
1105
     libcerror_error_t **error )
1106
0
{
1107
0
  libcdata_internal_array_t *internal_array = NULL;
1108
0
  static char *function                     = "libcdata_array_get_entry_by_index";
1109
1110
0
  if( array == NULL )
1111
0
  {
1112
0
    libcerror_error_set(
1113
0
     error,
1114
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1116
0
     "%s: invalid array.",
1117
0
     function );
1118
1119
0
    return( -1 );
1120
0
  }
1121
0
  internal_array = (libcdata_internal_array_t *) array;
1122
1123
0
  if( internal_array->entries == NULL )
1124
0
  {
1125
0
    libcerror_error_set(
1126
0
     error,
1127
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1129
0
     "%s: invalid array - missing entries.",
1130
0
     function );
1131
1132
0
    return( -1 );
1133
0
  }
1134
0
  if( ( entry_index < 0 )
1135
0
   || ( entry_index >= internal_array->number_of_entries ) )
1136
0
  {
1137
0
    libcerror_error_set(
1138
0
     error,
1139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1140
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1141
0
     "%s: invalid entry index value out of bounds.",
1142
0
     function );
1143
1144
0
    return( -1 );
1145
0
  }
1146
0
  if( entry == NULL )
1147
0
  {
1148
0
    libcerror_error_set(
1149
0
     error,
1150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1152
0
     "%s: invalid entry.",
1153
0
     function );
1154
1155
0
    return( -1 );
1156
0
  }
1157
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1158
  if( libcthreads_read_write_lock_grab_for_read(
1159
       internal_array->read_write_lock,
1160
       error ) != 1 )
1161
  {
1162
    libcerror_error_set(
1163
     error,
1164
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1165
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1166
     "%s: unable to grab read/write lock for reading.",
1167
     function );
1168
1169
    return( -1 );
1170
  }
1171
#endif
1172
0
  *entry = internal_array->entries[ entry_index ];
1173
1174
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1175
  if( libcthreads_read_write_lock_release_for_read(
1176
       internal_array->read_write_lock,
1177
       error ) != 1 )
1178
  {
1179
    libcerror_error_set(
1180
     error,
1181
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1182
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1183
     "%s: unable to release read/write lock for reading.",
1184
     function );
1185
1186
    return( -1 );
1187
  }
1188
#endif
1189
0
  return( 1 );
1190
0
}
1191
1192
/* Retrieves a specific entry from the array
1193
 *
1194
 * Uses the entry_compare_function to determine the similarity of the entries
1195
 * The entry_compare_function should return LIBCDATA_COMPARE_LESS,
1196
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
1197
 *
1198
 * Returns 1 if successful, 0 if no such value or -1 on error
1199
 */
1200
int libcdata_array_get_entry_by_value(
1201
     libcdata_array_t *array,
1202
     intptr_t *entry,
1203
     int (*entry_compare_function)(
1204
            intptr_t *first_entry,
1205
            intptr_t *second_entry,
1206
            libcerror_error_t **error ),
1207
     intptr_t **existing_entry,
1208
     libcerror_error_t **error )
1209
0
{
1210
0
  libcdata_internal_array_t *internal_array = NULL;
1211
0
  static char *function                     = "libcdata_array_get_entry_by_value";
1212
0
  int compare_result                        = 0;
1213
0
  int entry_index                           = 0;
1214
0
  int result                                = 0;
1215
1216
0
  if( array == NULL )
1217
0
  {
1218
0
    libcerror_error_set(
1219
0
     error,
1220
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1221
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1222
0
     "%s: invalid array.",
1223
0
     function );
1224
1225
0
    return( -1 );
1226
0
  }
1227
0
  internal_array = (libcdata_internal_array_t *) array;
1228
1229
0
  if( internal_array->entries == NULL )
1230
0
  {
1231
0
    libcerror_error_set(
1232
0
     error,
1233
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1234
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1235
0
     "%s: invalid array - missing entries.",
1236
0
     function );
1237
1238
0
    return( -1 );
1239
0
  }
1240
0
  if( entry_compare_function == 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 entry compare function.",
1247
0
     function );
1248
1249
0
    return( -1 );
1250
0
  }
1251
0
  if( existing_entry == NULL )
1252
0
  {
1253
0
    libcerror_error_set(
1254
0
     error,
1255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1256
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1257
0
     "%s: invalid existing entry.",
1258
0
     function );
1259
1260
0
    return( -1 );
1261
0
  }
1262
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1263
  if( libcthreads_read_write_lock_grab_for_read(
1264
       internal_array->read_write_lock,
1265
       error ) != 1 )
1266
  {
1267
    libcerror_error_set(
1268
     error,
1269
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1270
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1271
     "%s: unable to grab read/write lock for reading.",
1272
     function );
1273
1274
    return( -1 );
1275
  }
1276
#endif
1277
0
  for( entry_index = 0;
1278
0
       entry_index < internal_array->number_of_entries;
1279
0
       entry_index++ )
1280
0
  {
1281
0
    compare_result = entry_compare_function(
1282
0
                      entry,
1283
0
                      internal_array->entries[ entry_index ],
1284
0
                      error );
1285
1286
0
    if( compare_result == -1 )
1287
0
    {
1288
0
      libcerror_error_set(
1289
0
       error,
1290
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292
0
       "%s: unable to compare entry: %d.",
1293
0
       function,
1294
0
       entry_index );
1295
1296
0
      result = -1;
1297
1298
0
      break;
1299
0
    }
1300
0
    else if( compare_result == LIBCDATA_COMPARE_EQUAL )
1301
0
    {
1302
0
      *existing_entry = internal_array->entries[ entry_index ];
1303
1304
0
      result = 1;
1305
1306
0
      break;
1307
0
    }
1308
0
  }
1309
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1310
  if( libcthreads_read_write_lock_release_for_read(
1311
       internal_array->read_write_lock,
1312
       error ) != 1 )
1313
  {
1314
    libcerror_error_set(
1315
     error,
1316
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1317
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1318
     "%s: unable to release read/write lock for reading.",
1319
     function );
1320
1321
    return( -1 );
1322
  }
1323
#endif
1324
0
  return( result );
1325
0
}
1326
1327
/* Sets a specific entry in the array
1328
 * Returns 1 if successful or -1 on error
1329
 */
1330
int libcdata_array_set_entry_by_index(
1331
     libcdata_array_t *array,
1332
     int entry_index,
1333
     intptr_t *entry,
1334
     libcerror_error_t **error )
1335
0
{
1336
0
  libcdata_internal_array_t *internal_array = NULL;
1337
0
  static char *function                     = "libcdata_array_set_entry_by_index";
1338
1339
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1340
  intptr_t *backup_entry                    = NULL;
1341
#endif
1342
1343
0
  if( array == NULL )
1344
0
  {
1345
0
    libcerror_error_set(
1346
0
     error,
1347
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1348
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1349
0
     "%s: invalid array.",
1350
0
     function );
1351
1352
0
    return( -1 );
1353
0
  }
1354
0
  internal_array = (libcdata_internal_array_t *) array;
1355
1356
0
  if( internal_array->entries == NULL )
1357
0
  {
1358
0
    libcerror_error_set(
1359
0
     error,
1360
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1361
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1362
0
     "%s: invalid array - missing entries.",
1363
0
     function );
1364
1365
0
    return( -1 );
1366
0
  }
1367
0
  if( ( entry_index < 0 )
1368
0
   || ( entry_index >= internal_array->number_of_entries ) )
1369
0
  {
1370
0
    libcerror_error_set(
1371
0
     error,
1372
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1373
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1374
0
     "%s: invalid entry index value out of bounds.",
1375
0
     function );
1376
1377
0
    return( -1 );
1378
0
  }
1379
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1380
  if( libcthreads_read_write_lock_grab_for_write(
1381
       internal_array->read_write_lock,
1382
       error ) != 1 )
1383
  {
1384
    libcerror_error_set(
1385
     error,
1386
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1387
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1388
     "%s: unable to grab read/write lock for writing.",
1389
     function );
1390
1391
    return( -1 );
1392
  }
1393
  backup_entry = internal_array->entries[ entry_index ];
1394
#endif
1395
0
  internal_array->entries[ entry_index ] = entry;
1396
1397
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1398
  if( libcthreads_read_write_lock_release_for_write(
1399
       internal_array->read_write_lock,
1400
       error ) != 1 )
1401
  {
1402
    libcerror_error_set(
1403
     error,
1404
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1405
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1406
     "%s: unable to release read/write lock for writing.",
1407
     function );
1408
1409
    goto on_error;
1410
  }
1411
#endif
1412
0
  return( 1 );
1413
1414
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1415
on_error:
1416
  internal_array->entries[ entry_index ] = backup_entry;
1417
1418
  return( -1 );
1419
#endif
1420
0
}
1421
1422
/* Prepends an entry
1423
 * Returns 1 if successful or -1 on error
1424
 */
1425
int libcdata_array_prepend_entry(
1426
     libcdata_array_t *array,
1427
     intptr_t *entry,
1428
     libcerror_error_t **error )
1429
0
{
1430
0
  libcdata_internal_array_t *internal_array = NULL;
1431
0
  static char *function                     = "libcdata_array_prepend_entry";
1432
0
  int entry_iterator                        = 0;
1433
0
  int result                                = 0;
1434
1435
0
  if( array == NULL )
1436
0
  {
1437
0
    libcerror_error_set(
1438
0
     error,
1439
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1440
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1441
0
     "%s: invalid array.",
1442
0
     function );
1443
1444
0
    return( -1 );
1445
0
  }
1446
0
  internal_array = (libcdata_internal_array_t *) array;
1447
1448
0
  if( internal_array->entries == NULL )
1449
0
  {
1450
0
    libcerror_error_set(
1451
0
     error,
1452
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1453
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1454
0
     "%s: invalid array - missing entries.",
1455
0
     function );
1456
1457
0
    return( -1 );
1458
0
  }
1459
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1460
  if( libcthreads_read_write_lock_grab_for_write(
1461
       internal_array->read_write_lock,
1462
       error ) != 1 )
1463
  {
1464
    libcerror_error_set(
1465
     error,
1466
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1467
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1468
     "%s: unable to grab read/write lock for writing.",
1469
     function );
1470
1471
    return( -1 );
1472
  }
1473
#endif
1474
0
  result = libcdata_internal_array_resize(
1475
0
            internal_array,
1476
0
            internal_array->number_of_entries + 1,
1477
0
            NULL,
1478
0
            error );
1479
1480
0
  if( result != 1 )
1481
0
  {
1482
0
    libcerror_error_set(
1483
0
     error,
1484
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1485
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1486
0
     "%s: unable to resize array.",
1487
0
     function );
1488
1489
0
    result = -1;
1490
0
  }
1491
0
  else
1492
0
  {
1493
0
    for( entry_iterator = internal_array->number_of_entries - 1;
1494
0
         entry_iterator > 0;
1495
0
         entry_iterator-- )
1496
0
    {
1497
0
      internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
1498
0
    }
1499
0
    internal_array->entries[ entry_iterator ] = entry;
1500
0
  }
1501
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1502
  if( libcthreads_read_write_lock_release_for_write(
1503
       internal_array->read_write_lock,
1504
       error ) != 1 )
1505
  {
1506
    libcerror_error_set(
1507
     error,
1508
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1509
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1510
     "%s: unable to release read/write lock for writing.",
1511
     function );
1512
1513
    goto on_error;
1514
  }
1515
#endif
1516
0
  return( result );
1517
1518
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1519
on_error:
1520
  if( result == 1 )
1521
  {
1522
    for( entry_iterator = 0;
1523
         entry_iterator < ( internal_array->number_of_entries - 1 );
1524
         entry_iterator++ )
1525
    {
1526
      internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator + 1 ];
1527
    }
1528
    internal_array->entries[ entry_iterator ] = NULL;
1529
1530
    internal_array->number_of_entries -= 1;
1531
  }
1532
  return( -1 );
1533
#endif
1534
0
}
1535
1536
/* Appends an entry
1537
 * Sets the entry index to the newly appended entry
1538
 * Returns 1 if successful or -1 on error
1539
 */
1540
int libcdata_array_append_entry(
1541
     libcdata_array_t *array,
1542
     int *entry_index,
1543
     intptr_t *entry,
1544
     libcerror_error_t **error )
1545
6.19k
{
1546
6.19k
  libcdata_internal_array_t *internal_array = NULL;
1547
6.19k
  static char *function                     = "libcdata_array_append_entry";
1548
6.19k
  int result                                = 0;
1549
6.19k
  int safe_entry_index                      = 0;
1550
1551
6.19k
  if( array == NULL )
1552
0
  {
1553
0
    libcerror_error_set(
1554
0
     error,
1555
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1556
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1557
0
     "%s: invalid array.",
1558
0
     function );
1559
1560
0
    return( -1 );
1561
0
  }
1562
6.19k
  internal_array = (libcdata_internal_array_t *) array;
1563
1564
6.19k
  if( internal_array->entries == NULL )
1565
0
  {
1566
0
    libcerror_error_set(
1567
0
     error,
1568
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1569
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1570
0
     "%s: invalid array - missing entries.",
1571
0
     function );
1572
1573
0
    return( -1 );
1574
0
  }
1575
6.19k
  if( entry_index == NULL )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1580
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1581
0
     "%s: invalid entry index.",
1582
0
     function );
1583
1584
0
    return( -1 );
1585
0
  }
1586
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1587
  if( libcthreads_read_write_lock_grab_for_write(
1588
       internal_array->read_write_lock,
1589
       error ) != 1 )
1590
  {
1591
    libcerror_error_set(
1592
     error,
1593
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1595
     "%s: unable to grab read/write lock for writing.",
1596
     function );
1597
1598
    return( -1 );
1599
  }
1600
#endif
1601
6.19k
  safe_entry_index = internal_array->number_of_entries;
1602
1603
6.19k
  result = libcdata_internal_array_resize(
1604
6.19k
            internal_array,
1605
6.19k
            internal_array->number_of_entries + 1,
1606
6.19k
            NULL,
1607
6.19k
            error );
1608
1609
6.19k
  if( result != 1 )
1610
0
  {
1611
0
    libcerror_error_set(
1612
0
     error,
1613
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1614
0
     LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1615
0
     "%s: unable to resize array.",
1616
0
     function );
1617
1618
0
    result = -1;
1619
0
  }
1620
6.19k
  else
1621
6.19k
  {
1622
6.19k
    internal_array->entries[ safe_entry_index ] = entry;
1623
6.19k
  }
1624
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1625
  if( libcthreads_read_write_lock_release_for_write(
1626
       internal_array->read_write_lock,
1627
       error ) != 1 )
1628
  {
1629
    libcerror_error_set(
1630
     error,
1631
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1632
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1633
     "%s: unable to release read/write lock for writing.",
1634
     function );
1635
1636
    goto on_error;
1637
  }
1638
#endif
1639
6.19k
  if( result == 1 )
1640
6.19k
  {
1641
6.19k
    *entry_index = safe_entry_index;
1642
6.19k
  }
1643
6.19k
  return( result );
1644
1645
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1646
on_error:
1647
  if( result == 1 )
1648
  {
1649
    internal_array->entries[ safe_entry_index ] = NULL;
1650
1651
    internal_array->number_of_entries -= 1;
1652
  }
1653
  return( -1 );
1654
#endif
1655
6.19k
}
1656
1657
/* Inserts an entry in the array
1658
 *
1659
 * Uses the entry_compare_function to determine the order of the entries
1660
 * The entry_compare_function should return LIBCDATA_COMPARE_LESS,
1661
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
1662
 *
1663
 * Duplicate entries are allowed by default and inserted after the last duplicate entry.
1664
 * Only allowing unique entries can be enforced by setting the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
1665
 *
1666
 * entry_index is set to the index of the entry when the entry was successfully inserted
1667
 * or to the index of the existing entry when the flag LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES
1668
 * is set and an existing entry was found.
1669
 *
1670
 * Returns 1 if successful, 0 if the entry already exists or -1 on error
1671
 */
1672
int libcdata_array_insert_entry(
1673
     libcdata_array_t *array,
1674
     int *entry_index,
1675
     intptr_t *entry,
1676
     int (*entry_compare_function)(
1677
            intptr_t *first_entry,
1678
            intptr_t *second_entry,
1679
            libcerror_error_t **error ),
1680
     uint8_t insert_flags,
1681
     libcerror_error_t **error )
1682
0
{
1683
0
  libcdata_internal_array_t *internal_array = NULL;
1684
0
  static char *function                     = "libcdata_array_insert_entry";
1685
0
  int compare_result                        = 0;
1686
0
  int entry_iterator                        = 0;
1687
0
  int result                                = 0;
1688
0
  int safe_entry_index                      = 0;
1689
1690
0
  if( array == NULL )
1691
0
  {
1692
0
    libcerror_error_set(
1693
0
     error,
1694
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1695
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1696
0
     "%s: invalid array.",
1697
0
     function );
1698
1699
0
    return( -1 );
1700
0
  }
1701
0
  internal_array = (libcdata_internal_array_t *) array;
1702
1703
0
  if( internal_array->entries == NULL )
1704
0
  {
1705
0
    libcerror_error_set(
1706
0
     error,
1707
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1708
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1709
0
     "%s: invalid array - missing entries.",
1710
0
     function );
1711
1712
0
    return( -1 );
1713
0
  }
1714
0
  if( entry_index == NULL )
1715
0
  {
1716
0
    libcerror_error_set(
1717
0
     error,
1718
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1719
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1720
0
     "%s: invalid entry index.",
1721
0
     function );
1722
1723
0
    return( -1 );
1724
0
  }
1725
0
  if( entry_compare_function == NULL )
1726
0
  {
1727
0
    libcerror_error_set(
1728
0
     error,
1729
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1730
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1731
0
     "%s: invalid entry compare function.",
1732
0
     function );
1733
1734
0
    return( -1 );
1735
0
  }
1736
0
  if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
1737
0
  {
1738
0
    libcerror_error_set(
1739
0
     error,
1740
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1741
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1742
0
     "%s: unsupported insert flags: 0x%02" PRIx8 ".",
1743
0
     function,
1744
0
     insert_flags );
1745
1746
0
    return( -1 );
1747
0
  }
1748
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1749
  if( libcthreads_read_write_lock_grab_for_write(
1750
       internal_array->read_write_lock,
1751
       error ) != 1 )
1752
  {
1753
    libcerror_error_set(
1754
     error,
1755
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1756
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1757
     "%s: unable to grab read/write lock for writing.",
1758
     function );
1759
1760
    return( -1 );
1761
  }
1762
#endif
1763
0
  compare_result = LIBCDATA_COMPARE_GREATER;
1764
0
  result         = 1;
1765
1766
0
  for( entry_iterator = 0;
1767
0
       entry_iterator < internal_array->number_of_entries;
1768
0
       entry_iterator++ )
1769
0
  {
1770
0
    compare_result = entry_compare_function(
1771
0
                      entry,
1772
0
                      internal_array->entries[ entry_iterator ],
1773
0
                      error );
1774
1775
0
    if( compare_result == -1 )
1776
0
    {
1777
0
      libcerror_error_set(
1778
0
       error,
1779
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1780
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1781
0
       "%s: unable to compare entry: %d.",
1782
0
       function,
1783
0
       entry_iterator );
1784
1785
0
      result = -1;
1786
0
    }
1787
0
    else if( compare_result == LIBCDATA_COMPARE_EQUAL )
1788
0
    {
1789
0
      if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 )
1790
0
      {
1791
0
        result = 0;
1792
0
      }
1793
0
    }
1794
0
    else if( compare_result == LIBCDATA_COMPARE_LESS )
1795
0
    {
1796
0
      result = 1;
1797
1798
0
      break;
1799
0
    }
1800
0
    else if( compare_result != LIBCDATA_COMPARE_GREATER )
1801
0
    {
1802
0
      libcerror_error_set(
1803
0
       error,
1804
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1805
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1806
0
       "%s: unsupported entry compare function return value: %d.",
1807
0
       function,
1808
0
       compare_result );
1809
1810
0
      result = -1;
1811
0
    }
1812
0
    if( result != 1 )
1813
0
    {
1814
0
      break;
1815
0
    }
1816
0
  }
1817
0
  if( result == 1 )
1818
0
  {
1819
0
    result = libcdata_internal_array_resize(
1820
0
              internal_array,
1821
0
              internal_array->number_of_entries + 1,
1822
0
              NULL,
1823
0
              error );
1824
1825
0
    if( result != 1 )
1826
0
    {
1827
0
      libcerror_error_set(
1828
0
       error,
1829
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1830
0
       LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1831
0
       "%s: unable to resize array.",
1832
0
       function );
1833
1834
0
      result = -1;
1835
0
    }
1836
0
    else
1837
0
    {
1838
0
      safe_entry_index = entry_iterator;
1839
1840
0
      if( compare_result == LIBCDATA_COMPARE_LESS )
1841
0
      {
1842
0
        for( entry_iterator = internal_array->number_of_entries - 1;
1843
0
             entry_iterator > safe_entry_index;
1844
0
             entry_iterator-- )
1845
0
        {
1846
0
          internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
1847
0
        }
1848
0
      }
1849
0
      internal_array->entries[ safe_entry_index ] = entry;
1850
0
    }
1851
0
  }
1852
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1853
  if( libcthreads_read_write_lock_release_for_write(
1854
       internal_array->read_write_lock,
1855
       error ) != 1 )
1856
  {
1857
    libcerror_error_set(
1858
     error,
1859
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1860
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1861
     "%s: unable to release read/write lock for writing.",
1862
     function );
1863
1864
    goto on_error;
1865
  }
1866
#endif
1867
0
  if( result != -1 )
1868
0
  {
1869
0
    *entry_index = safe_entry_index;
1870
0
  }
1871
0
  return( result );
1872
1873
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1874
on_error:
1875
  if( result == 1 )
1876
  {
1877
    for( entry_iterator = safe_entry_index;
1878
         entry_iterator < ( internal_array->number_of_entries - 1 );
1879
         entry_iterator++ )
1880
    {
1881
      internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator + 1 ];
1882
    }
1883
    internal_array->entries[ entry_iterator ] = NULL;
1884
1885
    internal_array->number_of_entries -= 1;
1886
  }
1887
  return( -1 );
1888
#endif
1889
0
}
1890
1891
/* Removes an entry
1892
 * Returns 1 if successful or -1 on error
1893
 */
1894
int libcdata_array_remove_entry(
1895
     libcdata_array_t *array,
1896
     int entry_index,
1897
     intptr_t **entry,
1898
     libcerror_error_t **error )
1899
0
{
1900
0
  libcdata_internal_array_t *internal_array = NULL;
1901
0
  intptr_t *safe_entry                      = NULL;
1902
0
  static char *function                     = "libcdata_array_remove_entry";
1903
0
  int entry_iterator                        = 0;
1904
1905
0
  if( array == NULL )
1906
0
  {
1907
0
    libcerror_error_set(
1908
0
     error,
1909
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1910
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1911
0
     "%s: invalid array.",
1912
0
     function );
1913
1914
0
    return( -1 );
1915
0
  }
1916
0
  internal_array = (libcdata_internal_array_t *) array;
1917
1918
0
  if( internal_array->entries == NULL )
1919
0
  {
1920
0
    libcerror_error_set(
1921
0
     error,
1922
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1923
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1924
0
     "%s: invalid array - missing entries.",
1925
0
     function );
1926
1927
0
    return( -1 );
1928
0
  }
1929
0
  if( ( entry_index < 0 )
1930
0
   || ( entry_index >= internal_array->number_of_entries ) )
1931
0
  {
1932
0
    libcerror_error_set(
1933
0
     error,
1934
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1935
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1936
0
     "%s: invalid entry index value out of bounds.",
1937
0
     function );
1938
1939
0
    return( -1 );
1940
0
  }
1941
0
  if( entry == NULL )
1942
0
  {
1943
0
    libcerror_error_set(
1944
0
     error,
1945
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1946
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1947
0
     "%s: invalid entry.",
1948
0
     function );
1949
1950
0
    return( -1 );
1951
0
  }
1952
0
  *entry = NULL;
1953
1954
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1955
  if( libcthreads_read_write_lock_grab_for_write(
1956
       internal_array->read_write_lock,
1957
       error ) != 1 )
1958
  {
1959
    libcerror_error_set(
1960
     error,
1961
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1962
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1963
     "%s: unable to grab read/write lock for writing.",
1964
     function );
1965
1966
    return( -1 );
1967
  }
1968
#endif
1969
0
  safe_entry = internal_array->entries[ entry_index ];
1970
1971
0
  for( entry_iterator = entry_index;
1972
0
       entry_iterator < ( internal_array->number_of_entries - 1 );
1973
0
       entry_iterator++ )
1974
0
  {
1975
0
    internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator + 1 ];
1976
0
  }
1977
0
  internal_array->entries[ entry_iterator ] = NULL;
1978
1979
0
  internal_array->number_of_entries -= 1;
1980
1981
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1982
  if( libcthreads_read_write_lock_release_for_write(
1983
       internal_array->read_write_lock,
1984
       error ) != 1 )
1985
  {
1986
    libcerror_error_set(
1987
     error,
1988
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1989
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1990
     "%s: unable to release read/write lock for writing.",
1991
     function );
1992
1993
    goto on_error;
1994
  }
1995
#endif
1996
0
  *entry = safe_entry;
1997
1998
0
  return( 1 );
1999
2000
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
2001
on_error:
2002
  internal_array->number_of_entries += 1;
2003
2004
  for( entry_iterator = ( internal_array->number_of_entries - 1 );
2005
       entry_iterator > entry_index;
2006
       entry_iterator-- )
2007
  {
2008
    internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
2009
  }
2010
  internal_array->entries[ entry_index ] = safe_entry;
2011
2012
  return( -1 );
2013
#endif
2014
0
}
2015