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