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 ¤t_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 ¤t_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 ¤t_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 ¤t_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 ¤t_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 ¤t_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