1 /*
2  * Array functions
3  *
4  * Copyright (C) 2006-2020, 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_tree_node_insert_node";
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