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