1 /*
2 * Array functions
3 *
4 * Copyright (C) 2006-2021, 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 */
libcdata_array_initialize(libcdata_array_t ** array,int number_of_entries,libcerror_error_t ** error)36 int libcdata_array_initialize(
37 libcdata_array_t **array,
38 int number_of_entries,
39 libcerror_error_t **error )
40 {
41 libcdata_internal_array_t *internal_array = NULL;
42 static char *function = "libcdata_array_initialize";
43 size_t entries_size = 0;
44 int number_of_allocated_entries = 0;
45
46 if( array == NULL )
47 {
48 libcerror_error_set(
49 error,
50 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52 "%s: invalid array.",
53 function );
54
55 return( -1 );
56 }
57 if( *array != NULL )
58 {
59 libcerror_error_set(
60 error,
61 LIBCERROR_ERROR_DOMAIN_RUNTIME,
62 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63 "%s: invalid array value already set.",
64 function );
65
66 return( -1 );
67 }
68 if( number_of_entries < 0 )
69 {
70 libcerror_error_set(
71 error,
72 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
74 "%s: invalid number of entries value less than zero.",
75 function );
76
77 return( -1 );
78 }
79 internal_array = memory_allocate_structure(
80 libcdata_internal_array_t );
81
82 if( internal_array == NULL )
83 {
84 libcerror_error_set(
85 error,
86 LIBCERROR_ERROR_DOMAIN_MEMORY,
87 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88 "%s: unable to create array.",
89 function );
90
91 goto on_error;
92 }
93 if( memory_set(
94 internal_array,
95 0,
96 sizeof( libcdata_internal_array_t ) ) == NULL )
97 {
98 libcerror_error_set(
99 error,
100 LIBCERROR_ERROR_DOMAIN_MEMORY,
101 LIBCERROR_MEMORY_ERROR_SET_FAILED,
102 "%s: unable to clear array.",
103 function );
104
105 memory_free(
106 internal_array );
107
108 return( -1 );
109 }
110 /* Pre-allocate in blocks of 16 entries
111 */
112 if( number_of_entries >= (int) ( INT_MAX - 16 ) )
113 {
114 number_of_allocated_entries = INT_MAX;
115 }
116 else
117 {
118 number_of_allocated_entries = ( number_of_entries & ~( 15 ) ) + 16;
119 }
120 #if SIZEOF_INT <= SIZEOF_SIZE_T
121 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 {
126 libcerror_error_set(
127 error,
128 LIBCERROR_ERROR_DOMAIN_RUNTIME,
129 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
130 "%s: invalid number of allocated entries value exceeds maximum.",
131 function );
132
133 goto on_error;
134 }
135 entries_size = sizeof( intptr_t * ) * number_of_allocated_entries;
136
137 if( entries_size > (size_t) LIBCDATA_ARRAY_ENTRIES_MEMORY_LIMIT )
138 {
139 libcerror_error_set(
140 error,
141 LIBCERROR_ERROR_DOMAIN_RUNTIME,
142 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
143 "%s: invalid entries size value exceeds maximum.",
144 function );
145
146 goto on_error;
147 }
148 internal_array->entries = (intptr_t **) memory_allocate(
149 entries_size );
150
151 if( internal_array->entries == NULL )
152 {
153 libcerror_error_set(
154 error,
155 LIBCERROR_ERROR_DOMAIN_MEMORY,
156 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
157 "%s: unable to create array entries.",
158 function );
159
160 goto on_error;
161 }
162 if( memory_set(
163 internal_array->entries,
164 0,
165 entries_size ) == NULL )
166 {
167 libcerror_error_set(
168 error,
169 LIBCERROR_ERROR_DOMAIN_MEMORY,
170 LIBCERROR_MEMORY_ERROR_SET_FAILED,
171 "%s: unable to clear array entries.",
172 function );
173
174 goto on_error;
175 }
176 internal_array->number_of_allocated_entries = number_of_allocated_entries;
177 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 *array = (libcdata_array_t *) internal_array;
195
196 return( 1 );
197
198 on_error:
199 if( internal_array != NULL )
200 {
201 if( internal_array->entries != NULL )
202 {
203 memory_free(
204 internal_array->entries );
205 }
206 memory_free(
207 internal_array );
208 }
209 return( -1 );
210 }
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 */
libcdata_array_free(libcdata_array_t ** array,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
223 libcdata_internal_array_t *internal_array = NULL;
224 static char *function = "libcdata_array_free";
225 int result = 1;
226
227 if( array == NULL )
228 {
229 libcerror_error_set(
230 error,
231 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
232 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
233 "%s: invalid array.",
234 function );
235
236 return( -1 );
237 }
238 if( *array != NULL )
239 {
240 internal_array = (libcdata_internal_array_t *) *array;
241 *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 if( internal_array->entries != NULL )
259 {
260 if( libcdata_internal_array_clear(
261 internal_array,
262 entry_free_function,
263 error ) != 1 )
264 {
265 libcerror_error_set(
266 error,
267 LIBCERROR_ERROR_DOMAIN_RUNTIME,
268 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
269 "%s: unable to clear array.",
270 function );
271
272 result = -1;
273 }
274 memory_free(
275 internal_array->entries );
276 }
277 memory_free(
278 internal_array );
279 }
280 return( result );
281 }
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 */
libcdata_array_empty(libcdata_array_t * array,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
296 libcdata_internal_array_t *internal_array = NULL;
297 static char *function = "libcdata_array_empty";
298 int result = 1;
299
300 if( array == NULL )
301 {
302 libcerror_error_set(
303 error,
304 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
305 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
306 "%s: invalid array.",
307 function );
308
309 return( -1 );
310 }
311 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 if( libcdata_internal_array_clear(
329 internal_array,
330 entry_free_function,
331 error ) != 1 )
332 {
333 libcerror_error_set(
334 error,
335 LIBCERROR_ERROR_DOMAIN_RUNTIME,
336 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
337 "%s: unable to clear array.",
338 function );
339
340 result = -1;
341 }
342 else
343 {
344 internal_array->number_of_entries = 0;
345 }
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 return( result );
362 }
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 */
libcdata_internal_array_clear(libcdata_internal_array_t * internal_array,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
378 static char *function = "libcdata_internal_array_clear";
379 int entry_free_result = 0;
380 int entry_iterator = 0;
381 int result = 1;
382
383 if( internal_array == NULL )
384 {
385 libcerror_error_set(
386 error,
387 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
389 "%s: invalid array.",
390 function );
391
392 return( -1 );
393 }
394 if( internal_array->entries == NULL )
395 {
396 libcerror_error_set(
397 error,
398 LIBCERROR_ERROR_DOMAIN_RUNTIME,
399 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
400 "%s: invalid array - missing entries.",
401 function );
402
403 return( -1 );
404 }
405 for( entry_iterator = 0;
406 entry_iterator < internal_array->number_of_entries;
407 entry_iterator++ )
408 {
409 if( internal_array->entries[ entry_iterator ] != NULL )
410 {
411 if( entry_free_function == NULL )
412 {
413 entry_free_result = 1;
414 }
415 else
416 {
417 entry_free_result = entry_free_function(
418 &( internal_array->entries[ entry_iterator ] ),
419 error );
420 }
421 if( entry_free_result != 1 )
422 {
423 libcerror_error_set(
424 error,
425 LIBCERROR_ERROR_DOMAIN_RUNTIME,
426 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
427 "%s: unable to free array entry: %d.",
428 function,
429 entry_iterator );
430
431 result = -1;
432 }
433 else
434 {
435 internal_array->entries[ entry_iterator ] = NULL;
436 }
437 }
438 }
439 return( result );
440 }
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 */
libcdata_array_clear(libcdata_array_t * array,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
455 libcdata_internal_array_t *internal_array = NULL;
456 static char *function = "libcdata_array_clear";
457 int result = 1;
458
459 if( array == NULL )
460 {
461 libcerror_error_set(
462 error,
463 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
464 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
465 "%s: invalid array.",
466 function );
467
468 return( -1 );
469 }
470 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 if( libcdata_internal_array_clear(
488 internal_array,
489 entry_free_function,
490 error ) != 1 )
491 {
492 libcerror_error_set(
493 error,
494 LIBCERROR_ERROR_DOMAIN_RUNTIME,
495 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
496 "%s: unable to clear array.",
497 function );
498
499 result = -1;
500 }
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 return( result );
517 }
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 */
libcdata_array_clone(libcdata_array_t ** destination_array,libcdata_array_t * source_array,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),int (* entry_clone_function)(intptr_t ** destination_entry,intptr_t * source_entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
538 libcdata_internal_array_t *internal_destination_array = NULL;
539 libcdata_internal_array_t *internal_source_array = NULL;
540 static char *function = "libcdata_array_clone";
541 int entry_iterator = 0;
542
543 if( destination_array == NULL )
544 {
545 libcerror_error_set(
546 error,
547 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
548 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
549 "%s: invalid destination array.",
550 function );
551
552 return( -1 );
553 }
554 if( *destination_array != NULL )
555 {
556 libcerror_error_set(
557 error,
558 LIBCERROR_ERROR_DOMAIN_RUNTIME,
559 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
560 "%s: invalid destination array already set.",
561 function );
562
563 return( -1 );
564 }
565 if( entry_free_function == NULL )
566 {
567 libcerror_error_set(
568 error,
569 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
571 "%s: invalid entry free function.",
572 function );
573
574 return( -1 );
575 }
576 if( entry_clone_function == NULL )
577 {
578 libcerror_error_set(
579 error,
580 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
581 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
582 "%s: invalid entry clone function.",
583 function );
584
585 return( -1 );
586 }
587 if( source_array == NULL )
588 {
589 *destination_array = NULL;
590
591 return( 1 );
592 }
593 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 if( libcdata_array_initialize(
611 (libcdata_array_t **) &internal_destination_array,
612 internal_source_array->number_of_entries,
613 error ) != 1 )
614 {
615 libcerror_error_set(
616 error,
617 LIBCERROR_ERROR_DOMAIN_RUNTIME,
618 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
619 "%s: unable to create destination array.",
620 function );
621
622 goto on_error;
623 }
624 if( internal_destination_array == NULL )
625 {
626 libcerror_error_set(
627 error,
628 LIBCERROR_ERROR_DOMAIN_RUNTIME,
629 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
630 "%s: missing destination array.",
631 function );
632
633 goto on_error;
634 }
635 if( internal_source_array->entries != NULL )
636 {
637 for( entry_iterator = 0;
638 entry_iterator < internal_source_array->number_of_entries;
639 entry_iterator++ )
640 {
641 if( internal_source_array->entries[ entry_iterator ] != NULL )
642 {
643 if( entry_clone_function(
644 &( internal_destination_array->entries[ entry_iterator ] ),
645 internal_source_array->entries[ entry_iterator ],
646 error ) != 1 )
647 {
648 libcerror_error_set(
649 error,
650 LIBCERROR_ERROR_DOMAIN_RUNTIME,
651 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
652 "%s: unable to create destination array entry: %d.",
653 function,
654 entry_iterator );
655
656 goto on_error;
657 }
658 }
659 }
660 }
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 *destination_array = (libcdata_array_t *) internal_destination_array;
682
683 return( 1 );
684
685 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 if( internal_destination_array != NULL )
692 {
693 libcdata_array_free(
694 (libcdata_array_t **) &internal_destination_array,
695 entry_free_function,
696 NULL );
697 }
698 return( -1 );
699 }
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 */
libcdata_internal_array_resize(libcdata_internal_array_t * internal_array,int number_of_entries,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
713 static char *function = "libcdata_internal_array_resize";
714 void *reallocation = NULL;
715 size_t entries_size = 0;
716 int entry_iterator = 0;
717 int number_of_allocated_entries = 0;
718 int result = 1;
719
720 if( internal_array == NULL )
721 {
722 libcerror_error_set(
723 error,
724 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
725 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
726 "%s: invalid array.",
727 function );
728
729 return( -1 );
730 }
731 if( internal_array->entries == NULL )
732 {
733 libcerror_error_set(
734 error,
735 LIBCERROR_ERROR_DOMAIN_RUNTIME,
736 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
737 "%s: invalid array - missing entries.",
738 function );
739
740 return( -1 );
741 }
742 if( number_of_entries < 0 )
743 {
744 libcerror_error_set(
745 error,
746 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
747 LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
748 "%s: invalid number of entries value less than zero.",
749 function );
750
751 return( -1 );
752 }
753 if( number_of_entries > internal_array->number_of_allocated_entries )
754 {
755 /* Pre-allocate in blocks of 16 entries
756 */
757 if( number_of_entries >= (int) ( INT_MAX - 16 ) )
758 {
759 number_of_allocated_entries = INT_MAX;
760 }
761 else
762 {
763 number_of_allocated_entries = ( number_of_entries & ~( 15 ) ) + 16;
764 }
765 #if SIZEOF_INT <= SIZEOF_SIZE_T
766 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 {
771 libcerror_error_set(
772 error,
773 LIBCERROR_ERROR_DOMAIN_RUNTIME,
774 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
775 "%s: invalid number of allocated entries value exceeds maximum.",
776 function );
777
778 return( -1 );
779 }
780 entries_size = sizeof( intptr_t * ) * number_of_allocated_entries;
781
782 if( entries_size > (size_t) LIBCDATA_ARRAY_ENTRIES_MEMORY_LIMIT )
783 {
784 libcerror_error_set(
785 error,
786 LIBCERROR_ERROR_DOMAIN_RUNTIME,
787 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
788 "%s: invalid entries size value exceeds maximum.",
789 function );
790
791 return( -1 );
792 }
793 reallocation = memory_reallocate(
794 internal_array->entries,
795 entries_size );
796
797 if( reallocation == NULL )
798 {
799 libcerror_error_set(
800 error,
801 LIBCERROR_ERROR_DOMAIN_MEMORY,
802 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
803 "%s: unable to resize array entries.",
804 function );
805
806 return( -1 );
807 }
808 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 for( entry_iterator = internal_array->number_of_allocated_entries;
815 entry_iterator < number_of_allocated_entries;
816 entry_iterator++ )
817 {
818 internal_array->entries[ entry_iterator ] = NULL;
819 }
820 internal_array->number_of_allocated_entries = number_of_allocated_entries;
821 internal_array->number_of_entries = number_of_entries;
822 }
823 else if( number_of_entries > internal_array->number_of_entries )
824 {
825 internal_array->number_of_entries = number_of_entries;
826 }
827 else if( internal_array->entries != NULL )
828 {
829 for( entry_iterator = number_of_entries;
830 entry_iterator < internal_array->number_of_entries;
831 entry_iterator++ )
832 {
833 if( internal_array->entries[ entry_iterator ] != NULL )
834 {
835 if( entry_free_function == NULL )
836 {
837 libcerror_error_set(
838 error,
839 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
840 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
841 "%s: invalid entry free function.",
842 function );
843
844 return( -1 );
845 }
846 if( entry_free_function(
847 &( internal_array->entries[ entry_iterator ] ),
848 error ) != 1 )
849 {
850 libcerror_error_set(
851 error,
852 LIBCERROR_ERROR_DOMAIN_RUNTIME,
853 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
854 "%s: unable to free array entry: %d.",
855 function,
856 entry_iterator );
857
858 result = -1;
859 }
860 internal_array->entries[ entry_iterator ] = NULL;
861 }
862 }
863 internal_array->number_of_entries = number_of_entries;
864 }
865 return( result );
866 }
867
868 /* Resizes an array
869 * Returns 1 if successful or -1 on error
870 */
libcdata_array_resize(libcdata_array_t * array,int number_of_entries,int (* entry_free_function)(intptr_t ** entry,libcerror_error_t ** error),libcerror_error_t ** error)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 {
879 libcdata_internal_array_t *internal_array = NULL;
880 static char *function = "libcdata_array_resize";
881 int result = 1;
882
883 if( array == NULL )
884 {
885 libcerror_error_set(
886 error,
887 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
888 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
889 "%s: invalid array.",
890 function );
891
892 return( -1 );
893 }
894 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 if( libcdata_internal_array_resize(
912 internal_array,
913 number_of_entries,
914 entry_free_function,
915 error ) != 1 )
916 {
917 libcerror_error_set(
918 error,
919 LIBCERROR_ERROR_DOMAIN_RUNTIME,
920 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
921 "%s: unable to resize array.",
922 function );
923
924 result = -1;
925 }
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 return( result );
942 }
943
944 /* Reverses the order of the entries in the array
945 * Returns 1 if successful or -1 on error
946 */
libcdata_array_reverse(libcdata_array_t * array,libcerror_error_t ** error)947 int libcdata_array_reverse(
948 libcdata_array_t *array,
949 libcerror_error_t **error )
950 {
951 libcdata_internal_array_t *internal_array = NULL;
952 intptr_t *entry = NULL;
953 static char *function = "libcdata_array_reverse";
954 int entry_iterator = 0;
955 int reverse_entry_iterator = 0;
956
957 if( array == NULL )
958 {
959 libcerror_error_set(
960 error,
961 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
962 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
963 "%s: invalid array.",
964 function );
965
966 return( -1 );
967 }
968 internal_array = (libcdata_internal_array_t *) array;
969
970 if( internal_array->entries == NULL )
971 {
972 libcerror_error_set(
973 error,
974 LIBCERROR_ERROR_DOMAIN_RUNTIME,
975 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
976 "%s: invalid array - missing entries.",
977 function );
978
979 return( -1 );
980 }
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 if( internal_array->number_of_entries > 1 )
997 {
998 reverse_entry_iterator = internal_array->number_of_entries - 1;
999
1000 while( entry_iterator < reverse_entry_iterator )
1001 {
1002 entry = internal_array->entries[ reverse_entry_iterator ];
1003 internal_array->entries[ reverse_entry_iterator ] = internal_array->entries[ entry_iterator ];
1004 internal_array->entries[ entry_iterator ] = entry;
1005
1006 entry_iterator++;
1007 reverse_entry_iterator--;
1008 }
1009 }
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 return( 1 );
1026 }
1027
1028 /* Retrieves the number of entries in the array
1029 * Returns 1 if successful or -1 on error
1030 */
libcdata_array_get_number_of_entries(libcdata_array_t * array,int * number_of_entries,libcerror_error_t ** error)1031 int libcdata_array_get_number_of_entries(
1032 libcdata_array_t *array,
1033 int *number_of_entries,
1034 libcerror_error_t **error )
1035 {
1036 libcdata_internal_array_t *internal_array = NULL;
1037 static char *function = "libcdata_array_get_number_of_entries";
1038
1039 if( array == NULL )
1040 {
1041 libcerror_error_set(
1042 error,
1043 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1044 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1045 "%s: invalid array.",
1046 function );
1047
1048 return( -1 );
1049 }
1050 internal_array = (libcdata_internal_array_t *) array;
1051
1052 if( number_of_entries == NULL )
1053 {
1054 libcerror_error_set(
1055 error,
1056 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1057 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1058 "%s: invalid number of entries.",
1059 function );
1060
1061 return( -1 );
1062 }
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 *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 return( 1 );
1096 }
1097
1098 /* Retrieves a specific entry from the array
1099 * Returns 1 if successful or -1 on error
1100 */
libcdata_array_get_entry_by_index(libcdata_array_t * array,int entry_index,intptr_t ** entry,libcerror_error_t ** error)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 {
1107 libcdata_internal_array_t *internal_array = NULL;
1108 static char *function = "libcdata_array_get_entry_by_index";
1109
1110 if( array == NULL )
1111 {
1112 libcerror_error_set(
1113 error,
1114 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1116 "%s: invalid array.",
1117 function );
1118
1119 return( -1 );
1120 }
1121 internal_array = (libcdata_internal_array_t *) array;
1122
1123 if( internal_array->entries == NULL )
1124 {
1125 libcerror_error_set(
1126 error,
1127 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1128 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1129 "%s: invalid array - missing entries.",
1130 function );
1131
1132 return( -1 );
1133 }
1134 if( ( entry_index < 0 )
1135 || ( entry_index >= internal_array->number_of_entries ) )
1136 {
1137 libcerror_error_set(
1138 error,
1139 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1140 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1141 "%s: invalid entry index value out of bounds.",
1142 function );
1143
1144 return( -1 );
1145 }
1146 if( entry == NULL )
1147 {
1148 libcerror_error_set(
1149 error,
1150 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1151 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1152 "%s: invalid entry.",
1153 function );
1154
1155 return( -1 );
1156 }
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 *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 return( 1 );
1190 }
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 */
libcdata_array_get_entry_by_value(libcdata_array_t * array,intptr_t * entry,int (* entry_compare_function)(intptr_t * first_entry,intptr_t * second_entry,libcerror_error_t ** error),intptr_t ** existing_entry,libcerror_error_t ** error)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 {
1210 libcdata_internal_array_t *internal_array = NULL;
1211 static char *function = "libcdata_array_get_entry_by_value";
1212 int compare_result = 0;
1213 int entry_index = 0;
1214 int result = 0;
1215
1216 if( array == NULL )
1217 {
1218 libcerror_error_set(
1219 error,
1220 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1221 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1222 "%s: invalid array.",
1223 function );
1224
1225 return( -1 );
1226 }
1227 internal_array = (libcdata_internal_array_t *) array;
1228
1229 if( internal_array->entries == NULL )
1230 {
1231 libcerror_error_set(
1232 error,
1233 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1234 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1235 "%s: invalid array - missing entries.",
1236 function );
1237
1238 return( -1 );
1239 }
1240 if( entry_compare_function == NULL )
1241 {
1242 libcerror_error_set(
1243 error,
1244 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1245 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1246 "%s: invalid entry compare function.",
1247 function );
1248
1249 return( -1 );
1250 }
1251 if( existing_entry == NULL )
1252 {
1253 libcerror_error_set(
1254 error,
1255 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1256 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1257 "%s: invalid existing entry.",
1258 function );
1259
1260 return( -1 );
1261 }
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 for( entry_index = 0;
1278 entry_index < internal_array->number_of_entries;
1279 entry_index++ )
1280 {
1281 compare_result = entry_compare_function(
1282 entry,
1283 internal_array->entries[ entry_index ],
1284 error );
1285
1286 if( compare_result == -1 )
1287 {
1288 libcerror_error_set(
1289 error,
1290 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1292 "%s: unable to compare entry: %d.",
1293 function,
1294 entry_index );
1295
1296 result = -1;
1297
1298 break;
1299 }
1300 else if( compare_result == LIBCDATA_COMPARE_EQUAL )
1301 {
1302 *existing_entry = internal_array->entries[ entry_index ];
1303
1304 result = 1;
1305
1306 break;
1307 }
1308 }
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 return( result );
1325 }
1326
1327 /* Sets a specific entry in the array
1328 * Returns 1 if successful or -1 on error
1329 */
libcdata_array_set_entry_by_index(libcdata_array_t * array,int entry_index,intptr_t * entry,libcerror_error_t ** error)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 {
1336 libcdata_internal_array_t *internal_array = NULL;
1337 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 if( array == NULL )
1344 {
1345 libcerror_error_set(
1346 error,
1347 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1348 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1349 "%s: invalid array.",
1350 function );
1351
1352 return( -1 );
1353 }
1354 internal_array = (libcdata_internal_array_t *) array;
1355
1356 if( internal_array->entries == NULL )
1357 {
1358 libcerror_error_set(
1359 error,
1360 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1361 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1362 "%s: invalid array - missing entries.",
1363 function );
1364
1365 return( -1 );
1366 }
1367 if( ( entry_index < 0 )
1368 || ( entry_index >= internal_array->number_of_entries ) )
1369 {
1370 libcerror_error_set(
1371 error,
1372 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1373 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1374 "%s: invalid entry index value out of bounds.",
1375 function );
1376
1377 return( -1 );
1378 }
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 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 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 }
1421
1422 /* Prepends an entry
1423 * Returns 1 if successful or -1 on error
1424 */
libcdata_array_prepend_entry(libcdata_array_t * array,intptr_t * entry,libcerror_error_t ** error)1425 int libcdata_array_prepend_entry(
1426 libcdata_array_t *array,
1427 intptr_t *entry,
1428 libcerror_error_t **error )
1429 {
1430 libcdata_internal_array_t *internal_array = NULL;
1431 static char *function = "libcdata_array_prepend_entry";
1432 int entry_iterator = 0;
1433 int result = 0;
1434
1435 if( array == NULL )
1436 {
1437 libcerror_error_set(
1438 error,
1439 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1440 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1441 "%s: invalid array.",
1442 function );
1443
1444 return( -1 );
1445 }
1446 internal_array = (libcdata_internal_array_t *) array;
1447
1448 if( internal_array->entries == NULL )
1449 {
1450 libcerror_error_set(
1451 error,
1452 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1453 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1454 "%s: invalid array - missing entries.",
1455 function );
1456
1457 return( -1 );
1458 }
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 result = libcdata_internal_array_resize(
1475 internal_array,
1476 internal_array->number_of_entries + 1,
1477 NULL,
1478 error );
1479
1480 if( result != 1 )
1481 {
1482 libcerror_error_set(
1483 error,
1484 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1485 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1486 "%s: unable to resize array.",
1487 function );
1488
1489 result = -1;
1490 }
1491 else
1492 {
1493 for( entry_iterator = internal_array->number_of_entries - 1;
1494 entry_iterator > 0;
1495 entry_iterator-- )
1496 {
1497 internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
1498 }
1499 internal_array->entries[ entry_iterator ] = entry;
1500 }
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 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 }
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 */
libcdata_array_append_entry(libcdata_array_t * array,int * entry_index,intptr_t * entry,libcerror_error_t ** error)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 {
1546 libcdata_internal_array_t *internal_array = NULL;
1547 static char *function = "libcdata_array_append_entry";
1548 int result = 0;
1549 int safe_entry_index = 0;
1550
1551 if( array == NULL )
1552 {
1553 libcerror_error_set(
1554 error,
1555 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1556 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1557 "%s: invalid array.",
1558 function );
1559
1560 return( -1 );
1561 }
1562 internal_array = (libcdata_internal_array_t *) array;
1563
1564 if( internal_array->entries == NULL )
1565 {
1566 libcerror_error_set(
1567 error,
1568 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1569 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1570 "%s: invalid array - missing entries.",
1571 function );
1572
1573 return( -1 );
1574 }
1575 if( entry_index == NULL )
1576 {
1577 libcerror_error_set(
1578 error,
1579 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1580 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1581 "%s: invalid entry index.",
1582 function );
1583
1584 return( -1 );
1585 }
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 safe_entry_index = internal_array->number_of_entries;
1602
1603 result = libcdata_internal_array_resize(
1604 internal_array,
1605 internal_array->number_of_entries + 1,
1606 NULL,
1607 error );
1608
1609 if( result != 1 )
1610 {
1611 libcerror_error_set(
1612 error,
1613 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1614 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1615 "%s: unable to resize array.",
1616 function );
1617
1618 result = -1;
1619 }
1620 else
1621 {
1622 internal_array->entries[ safe_entry_index ] = entry;
1623 }
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 if( result == 1 )
1640 {
1641 *entry_index = safe_entry_index;
1642 }
1643 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 }
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 when the entry was successfully inserted
1667 *
1668 * Returns 1 if successful, 0 if the entry already exists or -1 on error
1669 */
libcdata_array_insert_entry(libcdata_array_t * array,int * entry_index,intptr_t * entry,int (* entry_compare_function)(intptr_t * first_entry,intptr_t * second_entry,libcerror_error_t ** error),uint8_t insert_flags,libcerror_error_t ** error)1670 int libcdata_array_insert_entry(
1671 libcdata_array_t *array,
1672 int *entry_index,
1673 intptr_t *entry,
1674 int (*entry_compare_function)(
1675 intptr_t *first_entry,
1676 intptr_t *second_entry,
1677 libcerror_error_t **error ),
1678 uint8_t insert_flags,
1679 libcerror_error_t **error )
1680 {
1681 libcdata_internal_array_t *internal_array = NULL;
1682 static char *function = "libcdata_array_insert_entry";
1683 int compare_result = 0;
1684 int entry_iterator = 0;
1685 int result = 0;
1686 int safe_entry_index = 0;
1687
1688 if( array == NULL )
1689 {
1690 libcerror_error_set(
1691 error,
1692 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1693 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1694 "%s: invalid array.",
1695 function );
1696
1697 return( -1 );
1698 }
1699 internal_array = (libcdata_internal_array_t *) array;
1700
1701 if( internal_array->entries == NULL )
1702 {
1703 libcerror_error_set(
1704 error,
1705 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1706 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1707 "%s: invalid array - missing entries.",
1708 function );
1709
1710 return( -1 );
1711 }
1712 if( entry_index == NULL )
1713 {
1714 libcerror_error_set(
1715 error,
1716 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1717 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1718 "%s: invalid entry index.",
1719 function );
1720
1721 return( -1 );
1722 }
1723 if( entry_compare_function == NULL )
1724 {
1725 libcerror_error_set(
1726 error,
1727 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1728 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1729 "%s: invalid entry compare function.",
1730 function );
1731
1732 return( -1 );
1733 }
1734 if( ( insert_flags & ~( LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) ) != 0 )
1735 {
1736 libcerror_error_set(
1737 error,
1738 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1739 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1740 "%s: unsupported insert flags: 0x%02" PRIx8 ".",
1741 function,
1742 insert_flags );
1743
1744 return( -1 );
1745 }
1746 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1747 if( libcthreads_read_write_lock_grab_for_write(
1748 internal_array->read_write_lock,
1749 error ) != 1 )
1750 {
1751 libcerror_error_set(
1752 error,
1753 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1754 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1755 "%s: unable to grab read/write lock for writing.",
1756 function );
1757
1758 return( -1 );
1759 }
1760 #endif
1761 compare_result = LIBCDATA_COMPARE_GREATER;
1762 result = 1;
1763
1764 for( entry_iterator = 0;
1765 entry_iterator < internal_array->number_of_entries;
1766 entry_iterator++ )
1767 {
1768 compare_result = entry_compare_function(
1769 entry,
1770 internal_array->entries[ entry_iterator ],
1771 error );
1772
1773 if( compare_result == -1 )
1774 {
1775 libcerror_error_set(
1776 error,
1777 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1778 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1779 "%s: unable to compare entry: %d.",
1780 function,
1781 entry_iterator );
1782
1783 result = -1;
1784 }
1785 else if( compare_result == LIBCDATA_COMPARE_EQUAL )
1786 {
1787 if( ( insert_flags & LIBCDATA_INSERT_FLAG_UNIQUE_ENTRIES ) != 0 )
1788 {
1789 result = 0;
1790 }
1791 }
1792 else if( compare_result == LIBCDATA_COMPARE_LESS )
1793 {
1794 result = 1;
1795
1796 break;
1797 }
1798 else if( compare_result != LIBCDATA_COMPARE_GREATER )
1799 {
1800 libcerror_error_set(
1801 error,
1802 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1803 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1804 "%s: unsupported entry compare function return value: %d.",
1805 function,
1806 compare_result );
1807
1808 result = -1;
1809 }
1810 if( result != 1 )
1811 {
1812 break;
1813 }
1814 }
1815 if( result == 1 )
1816 {
1817 result = libcdata_internal_array_resize(
1818 internal_array,
1819 internal_array->number_of_entries + 1,
1820 NULL,
1821 error );
1822
1823 if( result != 1 )
1824 {
1825 libcerror_error_set(
1826 error,
1827 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1828 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
1829 "%s: unable to resize array.",
1830 function );
1831
1832 result = -1;
1833 }
1834 else
1835 {
1836 safe_entry_index = entry_iterator;
1837
1838 if( compare_result == LIBCDATA_COMPARE_LESS )
1839 {
1840 for( entry_iterator = internal_array->number_of_entries - 1;
1841 entry_iterator > safe_entry_index;
1842 entry_iterator-- )
1843 {
1844 internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
1845 }
1846 }
1847 internal_array->entries[ safe_entry_index ] = entry;
1848 }
1849 }
1850 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1851 if( libcthreads_read_write_lock_release_for_write(
1852 internal_array->read_write_lock,
1853 error ) != 1 )
1854 {
1855 libcerror_error_set(
1856 error,
1857 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1858 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1859 "%s: unable to release read/write lock for writing.",
1860 function );
1861
1862 goto on_error;
1863 }
1864 #endif
1865 if( result == 1 )
1866 {
1867 *entry_index = safe_entry_index;
1868 }
1869 return( result );
1870
1871 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1872 on_error:
1873 if( result == 1 )
1874 {
1875 for( entry_iterator = safe_entry_index;
1876 entry_iterator < ( internal_array->number_of_entries - 1 );
1877 entry_iterator++ )
1878 {
1879 internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator + 1 ];
1880 }
1881 internal_array->entries[ entry_iterator ] = NULL;
1882
1883 internal_array->number_of_entries -= 1;
1884 }
1885 return( -1 );
1886 #endif
1887 }
1888
1889 /* Removes an entry
1890 * Returns 1 if successful or -1 on error
1891 */
libcdata_array_remove_entry(libcdata_array_t * array,int entry_index,intptr_t ** entry,libcerror_error_t ** error)1892 int libcdata_array_remove_entry(
1893 libcdata_array_t *array,
1894 int entry_index,
1895 intptr_t **entry,
1896 libcerror_error_t **error )
1897 {
1898 libcdata_internal_array_t *internal_array = NULL;
1899 intptr_t *safe_entry = NULL;
1900 static char *function = "libcdata_array_remove_entry";
1901 int entry_iterator = 0;
1902
1903 if( array == NULL )
1904 {
1905 libcerror_error_set(
1906 error,
1907 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1908 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1909 "%s: invalid array.",
1910 function );
1911
1912 return( -1 );
1913 }
1914 internal_array = (libcdata_internal_array_t *) array;
1915
1916 if( internal_array->entries == NULL )
1917 {
1918 libcerror_error_set(
1919 error,
1920 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1921 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1922 "%s: invalid array - missing entries.",
1923 function );
1924
1925 return( -1 );
1926 }
1927 if( ( entry_index < 0 )
1928 || ( entry_index >= internal_array->number_of_entries ) )
1929 {
1930 libcerror_error_set(
1931 error,
1932 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1933 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1934 "%s: invalid entry index value out of bounds.",
1935 function );
1936
1937 return( -1 );
1938 }
1939 if( entry == NULL )
1940 {
1941 libcerror_error_set(
1942 error,
1943 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1944 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1945 "%s: invalid entry.",
1946 function );
1947
1948 return( -1 );
1949 }
1950 *entry = NULL;
1951
1952 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1953 if( libcthreads_read_write_lock_grab_for_write(
1954 internal_array->read_write_lock,
1955 error ) != 1 )
1956 {
1957 libcerror_error_set(
1958 error,
1959 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1960 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1961 "%s: unable to grab read/write lock for writing.",
1962 function );
1963
1964 return( -1 );
1965 }
1966 #endif
1967 safe_entry = internal_array->entries[ entry_index ];
1968
1969 for( entry_iterator = entry_index;
1970 entry_iterator < ( internal_array->number_of_entries - 1 );
1971 entry_iterator++ )
1972 {
1973 internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator + 1 ];
1974 }
1975 internal_array->entries[ entry_iterator ] = NULL;
1976
1977 internal_array->number_of_entries -= 1;
1978
1979 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1980 if( libcthreads_read_write_lock_release_for_write(
1981 internal_array->read_write_lock,
1982 error ) != 1 )
1983 {
1984 libcerror_error_set(
1985 error,
1986 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1987 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1988 "%s: unable to release read/write lock for writing.",
1989 function );
1990
1991 goto on_error;
1992 }
1993 #endif
1994 *entry = safe_entry;
1995
1996 return( 1 );
1997
1998 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
1999 on_error:
2000 internal_array->number_of_entries += 1;
2001
2002 for( entry_iterator = ( internal_array->number_of_entries - 1 );
2003 entry_iterator > entry_index;
2004 entry_iterator-- )
2005 {
2006 internal_array->entries[ entry_iterator ] = internal_array->entries[ entry_iterator - 1 ];
2007 }
2008 internal_array->entries[ entry_index ] = safe_entry;
2009
2010 return( -1 );
2011 #endif
2012 }
2013
2014