1 /*
2  * The segments array 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_libcdata.h"
27 #include "libfdata_libcerror.h"
28 #include "libfdata_libcnotify.h"
29 #include "libfdata_mapped_range.h"
30 #include "libfdata_range.h"
31 #include "libfdata_segments_array.h"
32 
33 /* Retrieves a specific segment
34  * Returns 1 if successful or -1 on error
35  */
libfdata_segments_array_get_segment_by_index(libcdata_array_t * segments_array,int segment_index,int * segment_file_index,off64_t * segment_offset,size64_t * segment_size,uint32_t * segment_flags,libcerror_error_t ** error)36 int libfdata_segments_array_get_segment_by_index(
37      libcdata_array_t *segments_array,
38      int segment_index,
39      int *segment_file_index,
40      off64_t *segment_offset,
41      size64_t *segment_size,
42      uint32_t *segment_flags,
43      libcerror_error_t **error )
44 {
45 	libfdata_range_t *segment_data_range = NULL;
46 	static char *function                = "libfdata_segments_array_get_segment_by_index";
47 
48 	if( libcdata_array_get_entry_by_index(
49 	     segments_array,
50 	     segment_index,
51 	     (intptr_t **) &segment_data_range,
52 	     error ) != 1 )
53 	{
54 		libcerror_error_set(
55 		 error,
56 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
57 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
58 		 "%s: unable to retrieve entry: %d from segments array.",
59 		 function,
60 		 segment_index );
61 
62 		return( -1 );
63 	}
64 	if( libfdata_range_get(
65 	     segment_data_range,
66 	     segment_file_index,
67 	     segment_offset,
68 	     segment_size,
69 	     segment_flags,
70 	     error ) != 1 )
71 	{
72 		libcerror_error_set(
73 		 error,
74 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
75 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
76 		 "%s: unable to retrieve segment: %d data range values.",
77 		 function,
78 		 segment_index );
79 
80 		return( -1 );
81 	}
82 	return( 1 );
83 }
84 
85 /* Sets the offset and size of a specific segment
86  * Returns 1 if successful or -1 on error
87  */
libfdata_segments_array_set_segment_by_index(libcdata_array_t * segments_array,libcdata_array_t * mapped_ranges_array,size64_t * data_size,int segment_index,int segment_file_index,off64_t segment_offset,size64_t segment_size,uint32_t segment_flags,libcerror_error_t ** error)88 int libfdata_segments_array_set_segment_by_index(
89      libcdata_array_t *segments_array,
90      libcdata_array_t *mapped_ranges_array,
91      size64_t *data_size,
92      int segment_index,
93      int segment_file_index,
94      off64_t segment_offset,
95      size64_t segment_size,
96      uint32_t segment_flags,
97      libcerror_error_t **error )
98 {
99 	libfdata_mapped_range_t *mapped_range = NULL;
100 	libfdata_range_t *segment_data_range  = NULL;
101 	static char *function                 = "libfdata_segments_array_set_segment_by_index";
102 	off64_t previous_segment_offset       = 0;
103 	size64_t previous_segment_size        = 0;
104 	uint32_t previous_segment_flags       = 0;
105 	int previous_segment_file_index       = 0;
106 
107 	if( data_size == NULL )
108 	{
109 		libcerror_error_set(
110 		 error,
111 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
112 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
113 		 "%s: invalid data size.",
114 		 function );
115 
116 		return( -1 );
117 	}
118 	if( segment_file_index < 0 )
119 	{
120 		libcerror_error_set(
121 		 error,
122 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
124 		 "%s: invalid segment file index value out of bounds.",
125 		 function );
126 
127 		return( -1 );
128 	}
129 	if( segment_offset < 0 )
130 	{
131 		libcerror_error_set(
132 		 error,
133 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
134 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
135 		 "%s: invalid segment offset value out of bounds.",
136 		 function );
137 
138 		return( -1 );
139 	}
140 	if( libcdata_array_get_entry_by_index(
141 	     segments_array,
142 	     segment_index,
143 	     (intptr_t **) &segment_data_range,
144 	     error ) != 1 )
145 	{
146 		libcerror_error_set(
147 		 error,
148 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
149 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
150 		 "%s: unable to retrieve entry: %d from segments array.",
151 		 function,
152 		 segment_index );
153 
154 		return( -1 );
155 	}
156 	if( segment_data_range == NULL )
157 	{
158 		if( libfdata_range_initialize(
159 		     &segment_data_range,
160 		     error ) != 1 )
161 		{
162 			libcerror_error_set(
163 			 error,
164 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
165 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
166 			 "%s: unable to create segment data range.",
167 			 function );
168 
169 			return( -1 );
170 		}
171 		if( libcdata_array_set_entry_by_index(
172 		     segments_array,
173 		     segment_index,
174 		     (intptr_t *) segment_data_range,
175 		     error ) != 1 )
176 		{
177 			libcerror_error_set(
178 			 error,
179 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
180 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
181 			 "%s: unable to set entry: %d to segments array.",
182 			 function,
183 			 segment_index );
184 
185 			libfdata_range_free(
186 			 &segment_data_range,
187 			 NULL );
188 
189 			return( -1 );
190 		}
191 	}
192 	else
193 	{
194 		if( libfdata_range_get(
195 		     segment_data_range,
196 		     &previous_segment_file_index,
197 		     &previous_segment_offset,
198 		     &previous_segment_size,
199 		     &previous_segment_flags,
200 		     error ) != 1 )
201 		{
202 			libcerror_error_set(
203 			 error,
204 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
205 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
206 			 "%s: unable to retrieve segment: %d data range values.",
207 			 function,
208 			 segment_index );
209 
210 			return( -1 );
211 		}
212 		*data_size -= previous_segment_size;
213 	}
214 	if( libfdata_range_set(
215 	     segment_data_range,
216 	     segment_file_index,
217 	     segment_offset,
218 	     segment_size,
219 	     segment_flags,
220 	     error ) != 1 )
221 	{
222 		libcerror_error_set(
223 		 error,
224 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
225 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
226 		 "%s: unable to set segment data range values.",
227 		 function );
228 
229 		return( -1 );
230 	}
231 	/* Make sure there is a mapped range entry for every segment
232 	 */
233 	if( libcdata_array_get_entry_by_index(
234 	     mapped_ranges_array,
235 	     segment_index,
236 	     (intptr_t **) &mapped_range,
237 	     error ) != 1 )
238 	{
239 		libcerror_error_set(
240 		 error,
241 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
242 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
243 		 "%s: unable to retrieve entry: %d from mapped ranges array.",
244 		 function,
245 		 segment_index );
246 
247 		return( -1 );
248 	}
249 	if( mapped_range == NULL )
250 	{
251 		if( libfdata_mapped_range_initialize(
252 		     &mapped_range,
253 		     error ) != 1 )
254 		{
255 			libcerror_error_set(
256 			 error,
257 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
258 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
259 			 "%s: unable to create mapped range.",
260 			 function );
261 
262 			return( -1 );
263 		}
264 		if( libcdata_array_set_entry_by_index(
265 		     mapped_ranges_array,
266 		     segment_index,
267 		     (intptr_t *) mapped_range,
268 		     error ) != 1 )
269 		{
270 			libcerror_error_set(
271 			 error,
272 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
273 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
274 			 "%s: unable to set entry: %d in mapped ranges array.",
275 			 function,
276 			 segment_index );
277 
278 			libfdata_mapped_range_free(
279 			 &mapped_range,
280 			 NULL );
281 
282 			return( -1 );
283 		}
284 	}
285 	*data_size += segment_size;
286 
287 	return( 1 );
288 }
289 
290 /* Prepends a segment
291  * Returns 1 if successful or -1 on error
292  */
libfdata_segments_array_prepend_segment(libcdata_array_t * segments_array,libcdata_array_t * mapped_ranges_array,size64_t * data_size,int segment_file_index,off64_t segment_offset,size64_t segment_size,uint32_t segment_flags,libcerror_error_t ** error)293 int libfdata_segments_array_prepend_segment(
294      libcdata_array_t *segments_array,
295      libcdata_array_t *mapped_ranges_array,
296      size64_t *data_size,
297      int segment_file_index,
298      off64_t segment_offset,
299      size64_t segment_size,
300      uint32_t segment_flags,
301      libcerror_error_t **error )
302 {
303 	libfdata_mapped_range_t *mapped_range = NULL;
304 	libfdata_range_t *segment_data_range  = NULL;
305 	static char *function                 = "libfdata_segments_array_prepend_segment";
306 	int mapped_range_index                = -1;
307 
308 	if( data_size == NULL )
309 	{
310 		libcerror_error_set(
311 		 error,
312 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
313 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
314 		 "%s: invalid data size.",
315 		 function );
316 
317 		return( -1 );
318 	}
319 	if( segment_file_index < 0 )
320 	{
321 		libcerror_error_set(
322 		 error,
323 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
324 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
325 		 "%s: invalid segment file index value out of bounds.",
326 		 function );
327 
328 		return( -1 );
329 	}
330 	if( segment_offset < 0 )
331 	{
332 		libcerror_error_set(
333 		 error,
334 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
335 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
336 		 "%s: invalid segment offset value out of bounds.",
337 		 function );
338 
339 		return( -1 );
340 	}
341 	if( segment_size > (size64_t) INT64_MAX )
342 	{
343 		libcerror_error_set(
344 		 error,
345 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
346 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
347 		 "%s: invalid segment size value out of bounds.",
348 		 function );
349 
350 		return( -1 );
351 	}
352 	if( libfdata_mapped_range_initialize(
353 	     &mapped_range,
354 	     error ) != 1 )
355 	{
356 		libcerror_error_set(
357 		 error,
358 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
359 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
360 		 "%s: unable to create mapped range.",
361 		 function );
362 
363 		goto on_error;
364 	}
365 	if( libfdata_mapped_range_set(
366 	     mapped_range,
367 	     (off64_t) *data_size,
368 	     segment_size,
369 	     error ) != 1 )
370 	{
371 		libcerror_error_set(
372 		 error,
373 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
374 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
375 		 "%s: unable to set mapped range values.",
376 		 function );
377 
378 		goto on_error;
379 	}
380 	if( libcdata_array_append_entry(
381 	     mapped_ranges_array,
382 	     &mapped_range_index,
383 	     (intptr_t *) mapped_range,
384 	     error ) != 1 )
385 	{
386 		libcerror_error_set(
387 		 error,
388 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
389 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
390 		 "%s: unable to append mapped range to array.",
391 		 function );
392 
393 		goto on_error;
394 	}
395 	if( libfdata_range_initialize(
396 	     &segment_data_range,
397 	     error ) != 1 )
398 	{
399 		libcerror_error_set(
400 		 error,
401 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
402 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
403 		 "%s: unable to create segment data range.",
404 		 function );
405 
406 		goto on_error;
407 	}
408 	if( libfdata_range_set(
409 	     segment_data_range,
410 	     segment_file_index,
411 	     segment_offset,
412 	     segment_size,
413 	     segment_flags,
414 	     error ) != 1 )
415 	{
416 		libcerror_error_set(
417 		 error,
418 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
419 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
420 		 "%s: unable to set segment data range values.",
421 		 function );
422 
423 		goto on_error;
424 	}
425 	if( libcdata_array_prepend_entry(
426 	     segments_array,
427 	     (intptr_t *) segment_data_range,
428 	     error ) != 1 )
429 	{
430 		libcerror_error_set(
431 		 error,
432 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
433 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
434 		 "%s: unable to prepend data range to segments array.",
435 		 function );
436 
437 		goto on_error;
438 	}
439 	*data_size += segment_size;
440 
441 	return( 1 );
442 
443 on_error:
444 	if( segment_data_range != NULL )
445 	{
446 		libfdata_range_free(
447 		 &segment_data_range,
448 		 NULL );
449 	}
450 	if( mapped_range_index != -1 )
451 	{
452 		libcdata_array_set_entry_by_index(
453 		 mapped_ranges_array,
454 		 mapped_range_index,
455 		 NULL,
456 		 NULL );
457 	}
458 	if( mapped_range != NULL )
459 	{
460 		libfdata_mapped_range_free(
461 		 &mapped_range,
462 		 NULL );
463 	}
464 	return( -1 );
465 }
466 
467 /* Appends a segment
468  * Returns 1 if successful or -1 on error
469  */
libfdata_segments_array_append_segment(libcdata_array_t * segments_array,libcdata_array_t * mapped_ranges_array,size64_t * data_size,int * segment_index,int segment_file_index,off64_t segment_offset,size64_t segment_size,uint32_t segment_flags,libcerror_error_t ** error)470 int libfdata_segments_array_append_segment(
471      libcdata_array_t *segments_array,
472      libcdata_array_t *mapped_ranges_array,
473      size64_t *data_size,
474      int *segment_index,
475      int segment_file_index,
476      off64_t segment_offset,
477      size64_t segment_size,
478      uint32_t segment_flags,
479      libcerror_error_t **error )
480 {
481 	libfdata_mapped_range_t *mapped_range = NULL;
482 	libfdata_range_t *segment_data_range  = NULL;
483 	static char *function                 = "libfdata_segments_array_append_segment";
484 	int mapped_range_index                = -1;
485 
486 	if( data_size == NULL )
487 	{
488 		libcerror_error_set(
489 		 error,
490 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
491 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
492 		 "%s: invalid data size.",
493 		 function );
494 
495 		return( -1 );
496 	}
497 	if( segment_file_index < 0 )
498 	{
499 		libcerror_error_set(
500 		 error,
501 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
502 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
503 		 "%s: invalid segment file index value out of bounds.",
504 		 function );
505 
506 		return( -1 );
507 	}
508 	if( segment_offset < 0 )
509 	{
510 		libcerror_error_set(
511 		 error,
512 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
513 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
514 		 "%s: invalid segment offset value out of bounds.",
515 		 function );
516 
517 		return( -1 );
518 	}
519 	if( libfdata_mapped_range_initialize(
520 	     &mapped_range,
521 	     error ) != 1 )
522 	{
523 		libcerror_error_set(
524 		 error,
525 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
526 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
527 		 "%s: unable to create mapped range.",
528 		 function );
529 
530 		goto on_error;
531 	}
532 	if( libfdata_mapped_range_set(
533 	     mapped_range,
534 	     (off64_t) *data_size,
535 	     segment_size,
536 	     error ) != 1 )
537 	{
538 		libcerror_error_set(
539 		 error,
540 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
541 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
542 		 "%s: unable to set mapped range values.",
543 		 function );
544 
545 		goto on_error;
546 	}
547 	if( libcdata_array_append_entry(
548 	     mapped_ranges_array,
549 	     &mapped_range_index,
550 	     (intptr_t *) mapped_range,
551 	     error ) != 1 )
552 	{
553 		libcerror_error_set(
554 		 error,
555 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
556 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
557 		 "%s: unable to append mapped range to array.",
558 		 function );
559 
560 		goto on_error;
561 	}
562 	if( libfdata_range_initialize(
563 	     &segment_data_range,
564 	     error ) != 1 )
565 	{
566 		libcerror_error_set(
567 		 error,
568 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
569 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
570 		 "%s: unable to create segment data range.",
571 		 function );
572 
573 		goto on_error;
574 	}
575 	if( libfdata_range_set(
576 	     segment_data_range,
577 	     segment_file_index,
578 	     segment_offset,
579 	     segment_size,
580 	     segment_flags,
581 	     error ) != 1 )
582 	{
583 		libcerror_error_set(
584 		 error,
585 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
586 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
587 		 "%s: unable to set segment data range values.",
588 		 function );
589 
590 		goto on_error;
591 	}
592 	if( libcdata_array_append_entry(
593 	     segments_array,
594 	     segment_index,
595 	     (intptr_t *) segment_data_range,
596 	     error ) != 1 )
597 	{
598 		libcerror_error_set(
599 		 error,
600 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
601 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
602 		 "%s: unable to append data range to segments array.",
603 		 function );
604 
605 		goto on_error;
606 	}
607 #if defined( HAVE_DEBUG_OUTPUT )
608 	if( libcnotify_verbose != 0 )
609 	{
610 		libcnotify_printf(
611 		 "%s: segment: %03d\tfile index: %03d offset: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
612 		 function,
613 		 *segment_index,
614 		 segment_file_index,
615 		 segment_offset,
616 		 segment_offset + segment_size,
617 		 segment_size );
618 
619 		libcnotify_printf(
620 		 "%s: segment: %03d\tmapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
621 		 function,
622 		 *segment_index,
623 		 *data_size,
624 		 *data_size + segment_size,
625 		 segment_size );
626 
627 		libcnotify_printf(
628 		 "\n" );
629 	}
630 #endif
631 	*data_size += segment_size;
632 
633 	return( 1 );
634 
635 on_error:
636 	if( segment_data_range != NULL )
637 	{
638 		libfdata_range_free(
639 		 &segment_data_range,
640 		 NULL );
641 	}
642 	if( mapped_range_index != -1 )
643 	{
644 		libcdata_array_set_entry_by_index(
645 		 mapped_ranges_array,
646 		 mapped_range_index,
647 		 NULL,
648 		 NULL );
649 	}
650 	if( mapped_range != NULL )
651 	{
652 		libfdata_mapped_range_free(
653 		 &mapped_range,
654 		 NULL );
655 	}
656 	return( -1 );
657 }
658 
659 /* Calculates the mapped ranges from the segments
660  * Returns 1 if successful or -1 on error
661  */
libfdata_segments_array_calculate_mapped_ranges(libcdata_array_t * segments_array,libcdata_array_t * mapped_ranges_array,libcerror_error_t ** error)662 int libfdata_segments_array_calculate_mapped_ranges(
663      libcdata_array_t *segments_array,
664      libcdata_array_t *mapped_ranges_array,
665      libcerror_error_t **error )
666 {
667 	libfdata_mapped_range_t *mapped_range = NULL;
668 	libfdata_range_t *segment_data_range  = NULL;
669 	static char *function                 = "libfdata_segments_array_calculate_mapped_ranges";
670 	off64_t mapped_offset                 = 0;
671 	off64_t segment_offset                = 0;
672 	size64_t segment_size                 = 0;
673 	uint32_t segment_flags                = 0;
674 	int number_of_segments                = 0;
675 	int segment_file_index                = 0;
676 	int segment_index                     = 0;
677 
678 	if( libcdata_array_get_number_of_entries(
679 	     segments_array,
680 	     &number_of_segments,
681 	     error ) != 1 )
682 	{
683 		libcerror_error_set(
684 		 error,
685 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
686 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
687 		 "%s: unable to retrieve number of entries from segments array.",
688 		 function );
689 
690 		return( -1 );
691 	}
692 	for( segment_index = 0;
693 	     segment_index < number_of_segments;
694 	     segment_index++ )
695 	{
696 		if( libcdata_array_get_entry_by_index(
697 		     segments_array,
698 		     segment_index,
699 		     (intptr_t **) &segment_data_range,
700 		     error ) != 1 )
701 		{
702 			libcerror_error_set(
703 			 error,
704 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
705 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
706 			 "%s: unable to retrieve entry: %d from segments array.",
707 			 function,
708 			 segment_index );
709 
710 			return( -1 );
711 		}
712 		if( libcdata_array_get_entry_by_index(
713 		     mapped_ranges_array,
714 		     segment_index,
715 		     (intptr_t **) &mapped_range,
716 		     error ) != 1 )
717 		{
718 			libcerror_error_set(
719 			 error,
720 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
721 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
722 			 "%s: unable to retrieve entry: %d from mapped ranges array.",
723 			 function,
724 			 segment_index );
725 
726 			return( -1 );
727 		}
728 		if( libfdata_range_get(
729 		     segment_data_range,
730 		     &segment_file_index,
731 		     &segment_offset,
732 		     &segment_size,
733 		     &segment_flags,
734 		     error ) != 1 )
735 		{
736 			libcerror_error_set(
737 			 error,
738 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
739 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
740 			 "%s: unable to retrieve segment: %d data range values.",
741 			 function,
742 			 segment_index );
743 
744 			return( -1 );
745 		}
746 #if defined( HAVE_DEBUG_OUTPUT )
747 		if( libcnotify_verbose != 0 )
748 		{
749 			libcnotify_printf(
750 			 "%s: segment: %03d\tfile index: %03d offset: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
751 			 function,
752 			 segment_index,
753 			 segment_file_index,
754 			 segment_offset,
755 			 segment_offset + segment_size,
756 			 segment_size );
757 
758 			libcnotify_printf(
759 			 "%s: segment: %03d\tmapped range: 0x%08" PRIx64 " - 0x%08" PRIx64 " (size: %" PRIu64 ")\n",
760 			 function,
761 			 segment_index,
762 			 mapped_offset,
763 			 mapped_offset + segment_size,
764 			 segment_size );
765 		}
766 #endif
767 		if( libfdata_mapped_range_set(
768 		     mapped_range,
769 		     mapped_offset,
770 		     segment_size,
771 		     error ) != 1 )
772 		{
773 			libcerror_error_set(
774 			 error,
775 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
777 			 "%s: unable to set mapped range: %d values.",
778 			 function,
779 			 segment_index );
780 
781 			return( -1 );
782 		}
783 		mapped_offset += (off64_t) segment_size;
784 	}
785 #if defined( HAVE_DEBUG_OUTPUT )
786 	if( libcnotify_verbose != 0 )
787 	{
788 		libcnotify_printf(
789 		 "\n" );
790 	}
791 #endif
792 	return( 1 );
793 }
794 
795 /* Retrieves the segment data range for a specific offset
796  * Returns 1 if successful or -1 on error
797  */
libfdata_segments_array_get_data_range_at_offset(libcdata_array_t * segments_array,off64_t value_offset,off64_t * segment_data_offset,libfdata_range_t ** segment_data_range,libcerror_error_t ** error)798 int libfdata_segments_array_get_data_range_at_offset(
799      libcdata_array_t *segments_array,
800      off64_t value_offset,
801      off64_t *segment_data_offset,
802      libfdata_range_t **segment_data_range,
803      libcerror_error_t **error )
804 {
805 	static char *function  = "libfdata_segments_array_get_data_range_at_offset";
806 	size64_t segment_size  = 0;
807 	int number_of_segments = 0;
808 	int segment_index      = 0;
809 
810 	if( segment_data_offset == NULL )
811 	{
812 		libcerror_error_set(
813 		 error,
814 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
815 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
816 		 "%s: invalid segment data offset.",
817 		 function );
818 
819 		return( -1 );
820 	}
821 	if( segment_data_range == NULL )
822 	{
823 		libcerror_error_set(
824 		 error,
825 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
826 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
827 		 "%s: invalid segment data range.",
828 		 function );
829 
830 		return( -1 );
831 	}
832 	if( libcdata_array_get_number_of_entries(
833 	     segments_array,
834 	     &number_of_segments,
835 	     error ) != 1 )
836 	{
837 		libcerror_error_set(
838 		 error,
839 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
840 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
841 		 "%s: unable to retrieve number of segments.",
842 		 function );
843 
844 		return( -1 );
845 	}
846 	if( number_of_segments <= 0 )
847 	{
848 		libcerror_error_set(
849 		 error,
850 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
851 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
852 		 "%s: invalid number of segments value out of bounds.",
853 		 function );
854 
855 		return( -1 );
856 	}
857 	for( segment_index = 0;
858 	     segment_index < number_of_segments;
859 	     segment_index++ )
860 	{
861 		if( libcdata_array_get_entry_by_index(
862 		     segments_array,
863 		     segment_index,
864 		     (intptr_t **) segment_data_range,
865 		     error ) != 1 )
866 		{
867 			libcerror_error_set(
868 			 error,
869 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
870 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
871 			 "%s: unable to retrieve segment data range: %d from array.",
872 			 function,
873 			 segment_index );
874 
875 			return( -1 );
876 		}
877 		if( libfdata_range_get_size(
878 		     *segment_data_range,
879 		     &segment_size,
880 		     error ) != 1 )
881 		{
882 			libcerror_error_set(
883 			 error,
884 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
885 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
886 			 "%s: unable to retrieve size from segment data range: %d.",
887 			 function,
888 			 segment_index );
889 
890 			return( -1 );
891 		}
892 /* TODO what about compressed data ranges */
893 		if( (size64_t) value_offset < segment_size )
894 		{
895 			*segment_data_offset = value_offset;
896 
897 			break;
898 		}
899 		value_offset -= segment_size;
900 	}
901 	if( segment_index >= number_of_segments )
902 	{
903 		libcerror_error_set(
904 		 error,
905 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
906 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
907 		 "%s: invalid segment index value out of bounds.",
908 		 function );
909 
910 		return( -1 );
911 	}
912 	return( 1 );
913 }
914 
915