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