1 /*
2  * The range list functions
3  *
4  * Copyright (C) 2010-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 "libfdata_definitions.h"
27 #include "libfdata_libcdata.h"
28 #include "libfdata_libcerror.h"
29 #include "libfdata_libcnotify.h"
30 #include "libfdata_libfcache.h"
31 #include "libfdata_list.h"
32 #include "libfdata_list_element.h"
33 #include "libfdata_range_list.h"
34 #include "libfdata_types.h"
35 
36 /* Creates a range list
37  * Make sure the value range_list is referencing, is set to NULL
38  *
39  * If the flag LIBFDATA_DATA_HANDLE_FLAG_MANAGED is set the range list
40  * takes over management of the data handle and the data handle is freed when
41  * no longer needed
42  *
43  * Returns 1 if successful or -1 on error
44  */
libfdata_range_list_initialize(libfdata_range_list_t ** range_list,intptr_t * data_handle,int (* free_data_handle)(intptr_t ** data_handle,libcerror_error_t ** error),int (* clone_data_handle)(intptr_t ** destination_data_handle,intptr_t * source_data_handle,libcerror_error_t ** error),int (* read_element_data)(intptr_t * data_handle,intptr_t * file_io_handle,libfdata_list_element_t * list_element,libfdata_cache_t * cache,int element_file_index,off64_t element_offset,size64_t element_size,uint32_t element_flags,uint8_t read_flags,libcerror_error_t ** error),int (* write_element_data)(intptr_t * data_handle,intptr_t * file_io_handle,libfdata_list_element_t * list_element,libfdata_cache_t * cache,int element_file_index,off64_t element_offset,size64_t element_size,uint32_t element_flags,uint8_t write_flags,libcerror_error_t ** error),uint8_t flags,libcerror_error_t ** error)45 int libfdata_range_list_initialize(
46      libfdata_range_list_t **range_list,
47      intptr_t *data_handle,
48      int (*free_data_handle)(
49             intptr_t **data_handle,
50             libcerror_error_t **error ),
51      int (*clone_data_handle)(
52             intptr_t **destination_data_handle,
53             intptr_t *source_data_handle,
54             libcerror_error_t **error ),
55      int (*read_element_data)(
56             intptr_t *data_handle,
57             intptr_t *file_io_handle,
58             libfdata_list_element_t *list_element,
59             libfdata_cache_t *cache,
60             int element_file_index,
61             off64_t element_offset,
62             size64_t element_size,
63             uint32_t element_flags,
64             uint8_t read_flags,
65             libcerror_error_t **error ),
66      int (*write_element_data)(
67             intptr_t *data_handle,
68             intptr_t *file_io_handle,
69             libfdata_list_element_t *list_element,
70             libfdata_cache_t *cache,
71             int element_file_index,
72             off64_t element_offset,
73             size64_t element_size,
74             uint32_t element_flags,
75             uint8_t write_flags,
76             libcerror_error_t **error ),
77      uint8_t flags,
78      libcerror_error_t **error )
79 {
80 	libfdata_internal_range_list_t *internal_range_list = NULL;
81 	static char *function                               = "libfdata_range_list_initialize";
82 
83 	if( range_list == NULL )
84 	{
85 		libcerror_error_set(
86 		 error,
87 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
88 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
89 		 "%s: invalid range list.",
90 		 function );
91 
92 		return( -1 );
93 	}
94 	if( *range_list != NULL )
95 	{
96 		libcerror_error_set(
97 		 error,
98 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
99 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
100 		 "%s: invalid range list value already set.",
101 		 function );
102 
103 		return( -1 );
104 	}
105 	if( ( flags & 0xfe ) != 0 )
106 	{
107 		libcerror_error_set(
108 		 error,
109 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
110 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
111 		 "%s: unsupported flags: 0x%02" PRIx8 ".",
112 		 function );
113 
114 		return( -1 );
115 	}
116 	internal_range_list = memory_allocate_structure(
117 	                       libfdata_internal_range_list_t );
118 
119 	if( internal_range_list == NULL )
120 	{
121 		libcerror_error_set(
122 		 error,
123 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
124 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
125 		 "%s: unable to create range list.",
126 		 function );
127 
128 		goto on_error;
129 	}
130 	if( memory_set(
131 	     internal_range_list,
132 	     0,
133 	     sizeof( libfdata_internal_range_list_t ) ) == NULL )
134 	{
135 		libcerror_error_set(
136 		 error,
137 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
138 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
139 		 "%s: unable to clear range list.",
140 		 function );
141 
142 		memory_free(
143 		 internal_range_list );
144 
145 		return( -1 );
146 	}
147 	if( libcdata_range_list_initialize(
148 	     &( internal_range_list->elements_range_list ),
149 	     error ) != 1 )
150 	{
151 		libcerror_error_set(
152 		 error,
153 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
154 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
155 		 "%s: unable to create elements range list.",
156 		 function );
157 
158 		goto on_error;
159 	}
160 	internal_range_list->flags             |= flags;
161 	internal_range_list->data_handle        = data_handle;
162 	internal_range_list->free_data_handle   = free_data_handle;
163 	internal_range_list->clone_data_handle  = clone_data_handle;
164 	internal_range_list->read_element_data  = read_element_data;
165 	internal_range_list->write_element_data = write_element_data;
166 
167 	*range_list = (libfdata_range_list_t *) internal_range_list;
168 
169 	return( 1 );
170 
171 on_error:
172 	if( internal_range_list != NULL )
173 	{
174 		if( internal_range_list->elements_range_list != NULL )
175 		{
176 			libcdata_range_list_free(
177 			 &( internal_range_list->elements_range_list ),
178 			 NULL,
179 			 NULL );
180 		}
181 		memory_free(
182 		 internal_range_list );
183 	}
184 	return( -1 );
185 }
186 
187 /* Frees a range list
188  * Returns 1 if successful or -1 on error
189  */
libfdata_range_list_free(libfdata_range_list_t ** range_list,libcerror_error_t ** error)190 int libfdata_range_list_free(
191      libfdata_range_list_t **range_list,
192      libcerror_error_t **error )
193 {
194 	libfdata_internal_range_list_t *internal_range_list = NULL;
195 	static char *function                               = "libfdata_range_list_free";
196 	int result                                          = 1;
197 
198 	if( range_list == NULL )
199 	{
200 		libcerror_error_set(
201 		 error,
202 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
203 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
204 		 "%s: invalid list.",
205 		 function );
206 
207 		return( -1 );
208 	}
209 	if( *range_list != NULL )
210 	{
211 		internal_range_list = (libfdata_internal_range_list_t *) *range_list;
212 		*range_list         = NULL;
213 
214 		if( libcdata_range_list_free(
215 		     &( internal_range_list->elements_range_list ),
216 		     (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_list_free,
217 		     error ) != 1 )
218 		{
219 			libcerror_error_set(
220 			 error,
221 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
222 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
223 			 "%s: unable to free the elements range list.",
224 			 function );
225 
226 			result = -1;
227 		}
228 		if( ( internal_range_list->flags & LIBFDATA_DATA_HANDLE_FLAG_MANAGED ) != 0 )
229 		{
230 			if( internal_range_list->data_handle != NULL )
231 			{
232 				if( internal_range_list->free_data_handle == NULL )
233 				{
234 					libcerror_error_set(
235 					 error,
236 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
237 					 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
238 					 "%s: invalid range list - missing free data handle function.",
239 					 function );
240 
241 					result = -1;
242 				}
243 				else if( internal_range_list->free_data_handle(
244 				          &( internal_range_list->data_handle ),
245 				          error ) != 1 )
246 				{
247 					libcerror_error_set(
248 					 error,
249 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
250 					 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
251 					 "%s: unable to free data handle.",
252 					 function );
253 
254 					result = -1;
255 				}
256 			}
257 		}
258 		memory_free(
259 		 internal_range_list );
260 	}
261 	return( result );
262 }
263 
264 /* Clones (duplicates) the range list
265  * Returns 1 if successful or -1 on error
266  */
libfdata_range_list_clone(libfdata_range_list_t ** destination_range_list,libfdata_range_list_t * source_range_list,libcerror_error_t ** error)267 int libfdata_range_list_clone(
268      libfdata_range_list_t **destination_range_list,
269      libfdata_range_list_t *source_range_list,
270      libcerror_error_t **error )
271 {
272 	libfdata_internal_range_list_t *internal_destination_range_list = NULL;
273 	libfdata_internal_range_list_t *internal_source_range_list      = NULL;
274 	static char *function                                           = "libfdata_range_list_clone";
275 
276 	if( destination_range_list == NULL )
277 	{
278 		libcerror_error_set(
279 		 error,
280 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
281 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
282 		 "%s: invalid destination range list.",
283 		 function );
284 
285 		return( -1 );
286 	}
287 	if( *destination_range_list != NULL )
288 	{
289 		libcerror_error_set(
290 		 error,
291 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
292 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
293 		 "%s: invalid destination range list value already set.",
294 		 function );
295 
296 		return( -1 );
297 	}
298 	if( source_range_list == NULL )
299 	{
300 		*destination_range_list = NULL;
301 
302 		return( 1 );
303 	}
304 	internal_source_range_list = (libfdata_internal_range_list_t *) source_range_list;
305 
306 	internal_destination_range_list = memory_allocate_structure(
307 	                                   libfdata_internal_range_list_t );
308 
309 	if( internal_destination_range_list == NULL )
310 	{
311 		libcerror_error_set(
312 		 error,
313 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
314 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
315 		 "%s: unable to create destination range list.",
316 		 function );
317 
318 		goto on_error;
319 	}
320 	if( memory_set(
321 	     internal_destination_range_list,
322 	     0,
323 	     sizeof( libfdata_internal_range_list_t ) ) == NULL )
324 	{
325 		libcerror_error_set(
326 		 error,
327 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
328 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
329 		 "%s: unable to clear destination range list.",
330 		 function );
331 
332 		memory_free(
333 		 internal_destination_range_list );
334 
335 		return( -1 );
336 	}
337 	if( internal_source_range_list->data_handle != NULL )
338 	{
339 		if( internal_source_range_list->free_data_handle == NULL )
340 		{
341 			libcerror_error_set(
342 			 error,
343 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
344 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
345 			 "%s: invalid source range list - missing free data handle function.",
346 			 function );
347 
348 			goto on_error;
349 		}
350 		if( internal_source_range_list->clone_data_handle == NULL )
351 		{
352 			libcerror_error_set(
353 			 error,
354 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
355 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
356 			 "%s: invalid source range list - missing clone data handle function.",
357 			 function );
358 
359 			goto on_error;
360 		}
361 		if( internal_source_range_list->clone_data_handle(
362 		     &( internal_destination_range_list->data_handle ),
363 		     internal_source_range_list->data_handle,
364 		     error ) != 1 )
365 		{
366 			libcerror_error_set(
367 			 error,
368 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
369 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
370 			 "%s: unable to create destination data handle.",
371 			 function );
372 
373 			goto on_error;
374 		}
375 	}
376 	if( libcdata_range_list_clone(
377 	     &( internal_destination_range_list->elements_range_list ),
378 	     internal_source_range_list->elements_range_list,
379 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_list_free,
380 	     (int (*)(intptr_t **, intptr_t *, libcerror_error_t **)) &libfdata_list_clone,
381 	     error ) != 1 )
382 	{
383 		libcerror_error_set(
384 		 error,
385 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
386 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
387 		 "%s: unable to create destination elements range list.",
388 		 function );
389 
390 		goto on_error;
391 	}
392 	internal_destination_range_list->flags              = internal_source_range_list->flags | LIBFDATA_DATA_HANDLE_FLAG_MANAGED;
393 	internal_destination_range_list->free_data_handle   = internal_source_range_list->free_data_handle;
394 	internal_destination_range_list->clone_data_handle  = internal_source_range_list->clone_data_handle;
395 	internal_destination_range_list->read_element_data  = internal_source_range_list->read_element_data;
396 	internal_destination_range_list->write_element_data = internal_source_range_list->write_element_data;
397 
398 	*destination_range_list = (libfdata_range_list_t *) internal_destination_range_list;
399 
400 	return( 1 );
401 
402 on_error:
403 	if( internal_destination_range_list != NULL )
404 	{
405 		if( ( internal_destination_range_list->data_handle != NULL )
406 		 && ( internal_source_range_list->free_data_handle != NULL ) )
407 		{
408 			internal_source_range_list->free_data_handle(
409 			 &( internal_destination_range_list->data_handle ),
410 			 NULL );
411 		}
412 		memory_free(
413 		 internal_destination_range_list );
414 	}
415 	return( -1 );
416 }
417 
418 /* List elements functions
419  */
420 
421 /* Empties the range list
422  * Returns 1 if successful or -1 on error
423  */
libfdata_range_list_empty(libfdata_range_list_t * range_list,libcerror_error_t ** error)424 int libfdata_range_list_empty(
425      libfdata_range_list_t *range_list,
426      libcerror_error_t **error )
427 {
428 	libfdata_internal_range_list_t *internal_range_list = NULL;
429 	static char *function                               = "libfdata_range_list_empty";
430 
431 	if( range_list == NULL )
432 	{
433 		libcerror_error_set(
434 		 error,
435 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
436 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
437 		 "%s: invalid range list.",
438 		 function );
439 
440 		return( -1 );
441 	}
442 	internal_range_list = (libfdata_internal_range_list_t *) range_list;
443 
444 	if( libcdata_range_list_empty(
445 	     internal_range_list->elements_range_list,
446 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_list_free,
447 	     error ) != 1 )
448 	{
449 		libcerror_error_set(
450 		 error,
451 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
452 		 LIBCERROR_RUNTIME_ERROR_RESIZE_FAILED,
453 		 "%s: unable to empty elements range list.",
454 		 function );
455 
456 		return( -1 );
457 	}
458 	return( 1 );
459 }
460 
461 /* Mapped range functions
462  */
463 
464 /* Retrieves the list element for a specific offset
465  * Returns 1 if successful, 0 if not or -1 on error
466  */
libfdata_range_list_get_list_element_at_offset(libfdata_range_list_t * range_list,off64_t offset,off64_t * element_data_offset,libfdata_list_element_t ** element,libcerror_error_t ** error)467 int libfdata_range_list_get_list_element_at_offset(
468      libfdata_range_list_t *range_list,
469      off64_t offset,
470      off64_t *element_data_offset,
471      libfdata_list_element_t **element,
472      libcerror_error_t **error )
473 {
474 	libfdata_internal_range_list_t *internal_range_list = NULL;
475 	libfdata_list_t *list                               = NULL;
476 	static char *function                               = "libfdata_range_list_get_list_element_at_offset";
477 	off64_t mapped_range_offset                         = 0;
478 	size64_t mapped_range_size                          = 0;
479 	int element_index                                   = 0;
480 	int result                                          = 0;
481 
482 	if( range_list == NULL )
483 	{
484 		libcerror_error_set(
485 		 error,
486 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
487 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
488 		 "%s: invalid range list.",
489 		 function );
490 
491 		return( -1 );
492 	}
493 	internal_range_list = (libfdata_internal_range_list_t *) range_list;
494 
495 #if defined( HAVE_DEBUG_OUTPUT )
496 	if( libcnotify_verbose != 0 )
497 	{
498 		libcnotify_printf(
499 		 "%s: requested offset: 0x%08" PRIx64 "\n",
500 		 function,
501 		 offset );
502 	}
503 #endif
504 	result = libcdata_range_list_get_range_at_offset(
505 	          internal_range_list->elements_range_list,
506 	          (uint64_t) offset,
507 	          (uint64_t *) &mapped_range_offset,
508 	          (uint64_t *) &mapped_range_size,
509 	          (intptr_t **) &list,
510 	          error );
511 
512 	if( result == -1 )
513 	{
514 		libcerror_error_set(
515 		 error,
516 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
517 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
518 		 "%s: unable to retrieve range from elements range list for offset: %" PRIi64 ".",
519 		 function,
520 		 offset );
521 
522 		return( -1 );
523 	}
524 	else if( result != 0 )
525 	{
526 #if defined( HAVE_DEBUG_OUTPUT )
527 		if( libcnotify_verbose != 0 )
528 		{
529 			libcnotify_printf(
530 			 "%s: mapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
531 			 function,
532 			 mapped_range_offset,
533 			 mapped_range_offset + mapped_range_size,
534 			 mapped_range_size );
535 		}
536 #endif
537 		result = libfdata_list_get_list_element_at_offset(
538 		          list,
539 		          offset,
540 		          &element_index,
541 		          element_data_offset,
542 		          element,
543 		          error );
544 
545 		if( result == -1 )
546 		{
547 			libcerror_error_set(
548 			 error,
549 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
550 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
551 			 "%s: unable to retrieve element from list for offset: %" PRIi64 ".",
552 			 function,
553 			 offset );
554 
555 			return( -1 );
556 		}
557 		else if( result == 0 )
558 		{
559 			libcerror_error_set(
560 			 error,
561 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
562 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
563 			 "%s: invalid list - element missing for offset: %" PRIi64 ".",
564 			 function,
565 			 offset );
566 
567 			return( -1 );
568 		}
569 	}
570 #if defined( HAVE_DEBUG_OUTPUT )
571 	if( libcnotify_verbose != 0 )
572 	{
573 		libcnotify_printf(
574 		 "\n" );
575 	}
576 #endif
577 	return( result );
578 }
579 
580 /* Retrieves the data range of an element at a specific offset
581  * Returns 1 if successful, 0 if not or -1 on error
582  */
libfdata_range_list_get_element_at_offset(libfdata_range_list_t * range_list,off64_t offset,off64_t * element_data_offset,int * element_file_index,off64_t * element_offset,size64_t * element_size,uint32_t * element_flags,libcerror_error_t ** error)583 int libfdata_range_list_get_element_at_offset(
584      libfdata_range_list_t *range_list,
585      off64_t offset,
586      off64_t *element_data_offset,
587      int *element_file_index,
588      off64_t *element_offset,
589      size64_t *element_size,
590      uint32_t *element_flags,
591      libcerror_error_t **error )
592 {
593 	libfdata_list_element_t *list_element = NULL;
594 	static char *function                 = "libfdata_list_get_element_at_offset";
595 	int result                            = 0;
596 
597 	result = libfdata_range_list_get_list_element_at_offset(
598 	          range_list,
599 	          offset,
600 	          element_data_offset,
601 	          &list_element,
602 	          error );
603 
604 	if( result == -1 )
605 	{
606 		libcerror_error_set(
607 		 error,
608 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
609 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
610 		 "%s: unable to retrieve element at offset: %" PRIi64 ".",
611 		 function,
612 		 offset );
613 
614 		return( -1 );
615 	}
616 	else if( result != 0 )
617 	{
618 		if( libfdata_list_element_get_data_range(
619 		     list_element,
620 		     element_file_index,
621 		     element_offset,
622 		     element_size,
623 		     element_flags,
624 		     error ) != 1 )
625 		{
626 			libcerror_error_set(
627 			 error,
628 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
629 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
630 			 "%s: unable to retrieve data range of list element at offset: %" PRIi64 ".",
631 			 function,
632 			 offset );
633 
634 			return( -1 );
635 		}
636 	}
637 	return( result );
638 }
639 
640 /* Inserts an element data range based on its mapped range
641  * Returns 1 if successful or -1 on error
642  */
libfdata_range_list_insert_element(libfdata_range_list_t * range_list,off64_t offset,size64_t size,int element_file_index,off64_t element_offset,size64_t element_size,uint32_t element_flags,libcerror_error_t ** error)643 int libfdata_range_list_insert_element(
644      libfdata_range_list_t *range_list,
645      off64_t offset,
646      size64_t size,
647      int element_file_index,
648      off64_t element_offset,
649      size64_t element_size,
650      uint32_t element_flags,
651      libcerror_error_t **error )
652 {
653 	libfdata_internal_range_list_t *internal_range_list = NULL;
654 	libfdata_list_t *list                               = NULL;
655 	libfdata_list_element_t *list_element               = NULL;
656 	static char *function                               = "libfdata_range_list_insert_element";
657 	off64_t element_data_offset                         = 0;
658 	off64_t mapped_range_offset                         = 0;
659 	size64_t element_mapped_size                        = 0;
660 	size64_t mapped_range_size                          = 0;
661 	int element_index                                   = 0;
662 	int result                                          = 0;
663 
664 	if( range_list == NULL )
665 	{
666 		libcerror_error_set(
667 		 error,
668 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
669 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
670 		 "%s: invalid range list.",
671 		 function );
672 
673 		return( -1 );
674 	}
675 	internal_range_list = (libfdata_internal_range_list_t *) range_list;
676 
677 	if( offset < 0 )
678 	{
679 		libcerror_error_set(
680 		 error,
681 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
682 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
683 		 "%s: invalid offset value out of bounds.",
684 		 function );
685 
686 		return( -1 );
687 	}
688 	if( size > (size64_t) INT64_MAX )
689 	{
690 		libcerror_error_set(
691 		 error,
692 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
693 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
694 		 "%s: invalid size value exceeds maximum.",
695 		 function );
696 
697 		return( -1 );
698 	}
699 #if defined( HAVE_DEBUG_OUTPUT )
700 	if( libcnotify_verbose != 0 )
701 	{
702 		libcnotify_printf(
703 		 "%s: file index: %03d offset: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
704 		 function,
705 		 element_file_index,
706 		 element_offset,
707 		 element_offset + element_size,
708 		 element_size );
709 
710 		libcnotify_printf(
711 		 "%s: requested range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
712 		 function,
713 		 offset,
714 		 offset + size,
715 		 size );
716 	}
717 #endif
718 	result = libcdata_range_list_get_range_at_offset(
719 	          internal_range_list->elements_range_list,
720 	          (uint64_t) offset,
721 	          (uint64_t *) &mapped_range_offset,
722 	          (uint64_t *) &mapped_range_size,
723 	          (intptr_t **) &list,
724 	          error );
725 
726 	if( result == -1 )
727 	{
728 		libcerror_error_set(
729 		 error,
730 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
731 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
732 		 "%s: unable to retrieve range from elements range list for offset: %" PRIi64 ".",
733 		 function,
734 		 offset );
735 
736 		return( -1 );
737 	}
738 	else if( result != 0 )
739 	{
740 #if defined( HAVE_DEBUG_OUTPUT )
741 		if( libcnotify_verbose != 0 )
742 		{
743 			libcnotify_printf(
744 			 "%s: mapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
745 			 function,
746 			 mapped_range_offset,
747 			 mapped_range_offset + mapped_range_size,
748 			 mapped_range_size );
749 		}
750 #endif
751 		result = libfdata_list_get_list_element_at_offset(
752 		          list,
753 		          offset,
754 		          &element_index,
755 		          &element_data_offset,
756 		          &list_element,
757 		          error );
758 
759 		if( result == -1 )
760 		{
761 			libcerror_error_set(
762 			 error,
763 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
764 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
765 			 "%s: unable to retrieve element from list for offset: %" PRIi64 ".",
766 			 function,
767 			 offset );
768 
769 			return( -1 );
770 		}
771 		else if( result == 0 )
772 		{
773 			libcerror_error_set(
774 			 error,
775 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
777 			 "%s: invalid list - element missing for offset: %" PRIi64 ".",
778 			 function,
779 			 offset );
780 
781 			return( -1 );
782 		}
783 		if( element_data_offset != 0 )
784 		{
785 			libcerror_error_set(
786 			 error,
787 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
788 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
789 			 "%s: invalid offset value out of bounds.",
790 			 function );
791 
792 			return( -1 );
793 		}
794 		if( libfdata_list_element_get_mapped_size(
795 		     list_element,
796 		     &element_mapped_size,
797 		     error ) != 1 )
798 		{
799 			libcerror_error_set(
800 			 error,
801 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
802 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
803 			 "%s: unable to retrieve mapped size from list element at offset: %" PRIi64 ".",
804 			 function,
805 			 offset );
806 
807 			return( -1 );
808 		}
809 		if( size != element_mapped_size )
810 		{
811 			libcerror_error_set(
812 			 error,
813 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
814 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
815 			 "%s: invalid size value out of bounds.",
816 			 function );
817 
818 			return( -1 );
819 		}
820 		if( libfdata_list_element_set_data_range(
821 		     list_element,
822 		     element_file_index,
823 		     element_offset,
824 		     element_size,
825 		     element_flags,
826 		     error ) != 1 )
827 		{
828 			libcerror_error_set(
829 			 error,
830 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
831 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
832 			 "%s: unable to set data range in list element at offset: %" PRIi64 ".",
833 			 function,
834 			 offset );
835 
836 			return( -1 );
837 		}
838 	}
839 	else
840 	{
841 #if defined( HAVE_DEBUG_OUTPUT )
842 		if( libcnotify_verbose != 0 )
843 		{
844 			libcnotify_printf(
845 			 "%s: no mapped range found.\n",
846 			 function );
847 		}
848 #endif
849 		if( libfdata_list_initialize(
850 		     &list,
851 		     internal_range_list->data_handle,
852 		     internal_range_list->free_data_handle,
853 		     internal_range_list->clone_data_handle,
854 		     internal_range_list->read_element_data,
855 		     internal_range_list->write_element_data,
856 		     LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
857 		     error ) != 1 )
858 		{
859 			libcerror_error_set(
860 			 error,
861 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
862 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
863 			 "%s: unable to create list.",
864 			 function );
865 
866 			return( -1 );
867 		}
868 		if( libfdata_list_set_mapped_offset(
869 		     list,
870 		     offset,
871 		     error ) != 1 )
872 		{
873 			libcerror_error_set(
874 			 error,
875 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
876 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
877 			 "%s: unable to set mapped offset in list.",
878 			 function );
879 
880 			libfdata_list_free(
881 			 &list,
882 			 NULL );
883 
884 			return( -1 );
885 		}
886 		if( libfdata_list_append_element_with_mapped_size(
887 		     list,
888 		     &element_index,
889 		     element_file_index,
890 		     element_offset,
891 		     element_size,
892 		     element_flags,
893 		     size,
894 		     error ) != 1 )
895 		{
896 			libcerror_error_set(
897 			 error,
898 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
899 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
900 			 "%s: unable to append element to list.",
901 			 function );
902 
903 			libfdata_list_free(
904 			 &list,
905 			 NULL );
906 
907 			return( -1 );
908 		}
909 		result = libcdata_range_list_insert_range(
910 		          internal_range_list->elements_range_list,
911 		          (uint64_t) offset,
912 		          (uint64_t) size,
913 		          (intptr_t *) list,
914 		          (int (*)(intptr_t **, libcerror_error_t **)) &libfdata_list_free,
915 		          (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfdata_list_append_list,
916 		          error );
917 
918 		if( result == -1 )
919 		{
920 			libcerror_error_set(
921 			 error,
922 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
923 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
924 			 "%s: unable to insert range in elements range list.",
925 			 function );
926 
927 			libfdata_list_free(
928 			 &list,
929 			 NULL );
930 
931 			return( -1 );
932 		}
933 		list = NULL;
934 	}
935 #if defined( HAVE_DEBUG_OUTPUT )
936 	if( libcnotify_verbose != 0 )
937 	{
938 		libcnotify_printf(
939 		 "\n" );
940 	}
941 #endif
942 	return( 1 );
943 }
944 
945 /* List element value functions
946  */
947 
948 /* Retrieves the value an element at a specific offset
949  * Returns 1 if successful, 0 if not or -1 on error
950  */
libfdata_range_list_get_element_value_at_offset(libfdata_range_list_t * range_list,intptr_t * file_io_handle,libfdata_cache_t * cache,off64_t offset,off64_t * element_data_offset,intptr_t ** element_value,uint8_t read_flags,libcerror_error_t ** error)951 int libfdata_range_list_get_element_value_at_offset(
952      libfdata_range_list_t *range_list,
953      intptr_t *file_io_handle,
954      libfdata_cache_t *cache,
955      off64_t offset,
956      off64_t *element_data_offset,
957      intptr_t **element_value,
958      uint8_t read_flags,
959      libcerror_error_t **error )
960 {
961 	libfdata_internal_range_list_t *internal_range_list = NULL;
962 	libfdata_list_t *list                               = NULL;
963 	static char *function                               = "libfdata_range_list_get_element_value_at_offset";
964 	off64_t mapped_range_offset                         = 0;
965 	size64_t mapped_range_size                          = 0;
966 	int element_index                                   = 0;
967 	int result                                          = 0;
968 
969 	if( range_list == NULL )
970 	{
971 		libcerror_error_set(
972 		 error,
973 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
974 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
975 		 "%s: invalid range list.",
976 		 function );
977 
978 		return( -1 );
979 	}
980 	internal_range_list = (libfdata_internal_range_list_t *) range_list;
981 
982 #if defined( HAVE_DEBUG_OUTPUT )
983 	if( libcnotify_verbose != 0 )
984 	{
985 		libcnotify_printf(
986 		 "%s: requested offset: 0x%08" PRIx64 "\n",
987 		 function,
988 		 offset );
989 	}
990 #endif
991 	result = libcdata_range_list_get_range_at_offset(
992 	          internal_range_list->elements_range_list,
993 	          (uint64_t) offset,
994 	          (uint64_t *) &mapped_range_offset,
995 	          (uint64_t *) &mapped_range_size,
996 	          (intptr_t **) &list,
997 	          error );
998 
999 	if( result == -1 )
1000 	{
1001 		libcerror_error_set(
1002 		 error,
1003 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1004 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1005 		 "%s: unable to retrieve range from elements range list for offset: %" PRIi64 ".",
1006 		 function,
1007 		 offset );
1008 
1009 		return( -1 );
1010 	}
1011 	else if( result != 0 )
1012 	{
1013 #if defined( HAVE_DEBUG_OUTPUT )
1014 		if( libcnotify_verbose != 0 )
1015 		{
1016 			libcnotify_printf(
1017 			 "%s: mapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
1018 			 function,
1019 			 mapped_range_offset,
1020 			 mapped_range_offset + mapped_range_size,
1021 			 mapped_range_size );
1022 		}
1023 #endif
1024 		result = libfdata_list_get_element_value_at_offset(
1025 		          list,
1026 		          file_io_handle,
1027 		          cache,
1028 		          offset,
1029 		          &element_index,
1030 		          element_data_offset,
1031 		          element_value,
1032 		          read_flags,
1033 		          error );
1034 
1035 		if( result == -1 )
1036 		{
1037 			libcerror_error_set(
1038 			 error,
1039 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1041 			 "%s: unable to retrieve element value from list for offset: %" PRIi64 ".",
1042 			 function,
1043 			 offset );
1044 
1045 			return( -1 );
1046 		}
1047 		else if( result == 0 )
1048 		{
1049 			libcerror_error_set(
1050 			 error,
1051 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1052 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1053 			 "%s: invalid list - element value missing for offset: %" PRIi64 ".",
1054 			 function,
1055 			 offset );
1056 
1057 			return( -1 );
1058 		}
1059 	}
1060 #if defined( HAVE_DEBUG_OUTPUT )
1061 	if( libcnotify_verbose != 0 )
1062 	{
1063 		libcnotify_printf(
1064 		 "\n" );
1065 	}
1066 #endif
1067 	return( result );
1068 }
1069 
1070 /* Sets the value of an element at a specific offset
1071  *
1072  * If the flag LIBFDATA_RANGE_LIST_VALUE_FLAG_MANAGED is set the list
1073  * takes over management of the value and the value is freed when
1074  * no longer needed.
1075  *
1076  * Returns 1 if successful, 0 if not or -1 on error
1077  */
libfdata_range_list_set_element_value_at_offset(libfdata_range_list_t * range_list,intptr_t * file_io_handle,libfdata_cache_t * cache,off64_t offset,intptr_t * element_value,int (* free_element_value)(intptr_t ** element_value,libcerror_error_t ** error),uint8_t write_flags,libcerror_error_t ** error)1078 int libfdata_range_list_set_element_value_at_offset(
1079      libfdata_range_list_t *range_list,
1080      intptr_t *file_io_handle,
1081      libfdata_cache_t *cache,
1082      off64_t offset,
1083      intptr_t *element_value,
1084      int (*free_element_value)(
1085             intptr_t **element_value,
1086             libcerror_error_t **error ),
1087      uint8_t write_flags,
1088      libcerror_error_t **error )
1089 {
1090 	libfdata_internal_range_list_t *internal_range_list = NULL;
1091 	libfdata_list_t *list                               = NULL;
1092 	static char *function                               = "libfdata_range_list_set_element_value_at_offset";
1093 	off64_t mapped_range_offset                         = 0;
1094 	size64_t mapped_range_size                          = 0;
1095 	int result                                          = 0;
1096 
1097 	if( range_list == NULL )
1098 	{
1099 		libcerror_error_set(
1100 		 error,
1101 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1102 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1103 		 "%s: invalid range list.",
1104 		 function );
1105 
1106 		return( -1 );
1107 	}
1108 	internal_range_list = (libfdata_internal_range_list_t *) range_list;
1109 
1110 #if defined( HAVE_DEBUG_OUTPUT )
1111 	if( libcnotify_verbose != 0 )
1112 	{
1113 		libcnotify_printf(
1114 		 "%s: requested offset: 0x%08" PRIx64 "\n",
1115 		 function,
1116 		 offset );
1117 	}
1118 #endif
1119 	result = libcdata_range_list_get_range_at_offset(
1120 	          internal_range_list->elements_range_list,
1121 	          (uint64_t) offset,
1122 	          (uint64_t *) &mapped_range_offset,
1123 	          (uint64_t *) &mapped_range_size,
1124 	          (intptr_t **) &list,
1125 	          error );
1126 
1127 	if( result == -1 )
1128 	{
1129 		libcerror_error_set(
1130 		 error,
1131 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1132 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1133 		 "%s: unable to retrieve range from elements range list for offset: %" PRIi64 ".",
1134 		 function,
1135 		 offset );
1136 
1137 		return( -1 );
1138 	}
1139 	else if( result != 0 )
1140 	{
1141 #if defined( HAVE_DEBUG_OUTPUT )
1142 		if( libcnotify_verbose != 0 )
1143 		{
1144 			libcnotify_printf(
1145 			 "%s: mapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
1146 			 function,
1147 			 mapped_range_offset,
1148 			 mapped_range_offset + mapped_range_size,
1149 			 mapped_range_size );
1150 		}
1151 #endif
1152 		result = libfdata_list_set_element_value_at_offset(
1153 		          list,
1154 		          file_io_handle,
1155 		          cache,
1156 		          offset,
1157 		          element_value,
1158 		          free_element_value,
1159 		          write_flags,
1160 		          error );
1161 
1162 		if( result == -1 )
1163 		{
1164 			libcerror_error_set(
1165 			 error,
1166 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1167 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1168 			 "%s: unable to set element value in list for offset: %" PRIi64 ".",
1169 			 function,
1170 			 offset );
1171 
1172 			return( -1 );
1173 		}
1174 		else if( result == 0 )
1175 		{
1176 			libcerror_error_set(
1177 			 error,
1178 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1179 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1180 			 "%s: invalid list - element value missing for offset: %" PRIi64 ".",
1181 			 function,
1182 			 offset );
1183 
1184 			return( -1 );
1185 		}
1186 	}
1187 #if defined( HAVE_DEBUG_OUTPUT )
1188 	if( libcnotify_verbose != 0 )
1189 	{
1190 		libcnotify_printf(
1191 		 "\n" );
1192 	}
1193 #endif
1194 	return( result );
1195 }
1196 
1197