1 /*
2  * File functions
3  *
4  * Copyright (C) 2008-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 <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28 
29 #if defined( HAVE_SYS_STAT_H )
30 #include <sys/stat.h>
31 #endif
32 
33 #if defined( HAVE_ERRNO_H )
34 #include <errno.h>
35 #endif
36 
37 #if defined( HAVE_FCNTL_H )
38 #include <fcntl.h>
39 #endif
40 
41 #if defined( WINAPI )
42 #include <io.h>
43 #endif
44 
45 #if defined( WINAPI ) && !defined( __CYGWIN__ )
46 #include <share.h>
47 #endif
48 
49 #if defined( HAVE_SYS_IOCTL_H )
50 #include <sys/ioctl.h>
51 #endif
52 
53 #if defined( WINAPI )
54 #include <winioctl.h>
55 
56 #elif defined( HAVE_CYGWIN_FS_H )
57 #include <cygwin/fs.h>
58 
59 #elif defined( HAVE_LINUX_FS_H )
60 /* Required for Linux platforms that use a sizeof( u64 )
61  * in linux/fs.h but have no typedef of it
62  */
63 #if !defined( HAVE_U64 )
64 typedef size_t u64;
65 #endif
66 
67 #include <linux/fs.h>
68 
69 #else
70 
71 #if defined( HAVE_SYS_DISK_H )
72 #include <sys/disk.h>
73 #endif
74 
75 #if defined( HAVE_SYS_DISKLABEL_H )
76 #include <sys/disklabel.h>
77 #endif
78 
79 #endif
80 
81 #if defined( HAVE_UNISTD_H )
82 #include <unistd.h>
83 #endif
84 
85 #if defined( HAVE_GLIB_H )
86 #include <glib.h>
87 #include <glib/gstdio.h>
88 #endif
89 
90 #include "libcfile_definitions.h"
91 #include "libcfile_file.h"
92 #include "libcfile_libcerror.h"
93 #include "libcfile_libcnotify.h"
94 #include "libcfile_system_string.h"
95 #include "libcfile_types.h"
96 #include "libcfile_winapi.h"
97 
98 /* Creates a file
99  * Make sure the value file is referencing, is set to NULL
100  * Returns 1 if successful or -1 on error
101  */
libcfile_file_initialize(libcfile_file_t ** file,libcerror_error_t ** error)102 int libcfile_file_initialize(
103      libcfile_file_t **file,
104      libcerror_error_t **error )
105 {
106 	libcfile_internal_file_t *internal_file = NULL;
107 	static char *function                   = "libcfile_file_initialize";
108 
109 	if( file == NULL )
110 	{
111 		libcerror_error_set(
112 		 error,
113 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
114 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
115 		 "%s: invalid file.",
116 		 function );
117 
118 		return( -1 );
119 	}
120 	if( *file != NULL )
121 	{
122 		libcerror_error_set(
123 		 error,
124 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
125 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
126 		 "%s: invalid file value already set.",
127 		 function );
128 
129 		return( -1 );
130 	}
131 	internal_file = memory_allocate_structure(
132 		         libcfile_internal_file_t );
133 
134 	if( internal_file == NULL )
135 	{
136 		libcerror_error_set(
137 		 error,
138 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
139 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
140 		 "%s: unable to create file.",
141 		 function );
142 
143 		goto on_error;
144 	}
145 	if( memory_set(
146 	     internal_file,
147 	     0,
148 	     sizeof( libcfile_internal_file_t ) ) == NULL )
149 	{
150 		libcerror_error_set(
151 		 error,
152 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
153 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
154 		 "%s: unable to clear file.",
155 		 function );
156 
157 		goto on_error;
158 	}
159 #if defined( WINAPI )
160 	internal_file->handle = INVALID_HANDLE_VALUE;
161 #else
162 	internal_file->descriptor = -1;
163 #endif
164 	*file = (libcfile_file_t *) internal_file;
165 
166 	return( 1 );
167 
168 on_error:
169 	if( internal_file != NULL )
170 	{
171 		memory_free(
172 		 internal_file );
173 	}
174 	return( -1 );
175 }
176 
177 /* Frees a file
178  * Returns 1 if successful or -1 on error
179  */
libcfile_file_free(libcfile_file_t ** file,libcerror_error_t ** error)180 int libcfile_file_free(
181      libcfile_file_t **file,
182      libcerror_error_t **error )
183 {
184 	libcfile_internal_file_t *internal_file = NULL;
185 	static char *function                   = "libcfile_file_free";
186 	int result                              = 1;
187 
188 	if( file == NULL )
189 	{
190 		libcerror_error_set(
191 		 error,
192 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
193 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
194 		 "%s: invalid file.",
195 		 function );
196 
197 		return( -1 );
198 	}
199 	if( *file != NULL )
200 	{
201 		internal_file = (libcfile_internal_file_t *) *file;
202 
203 #if defined( WINAPI )
204 		if( internal_file->handle != INVALID_HANDLE_VALUE )
205 #else
206 		if( internal_file->descriptor != -1 )
207 #endif
208 		{
209 			if( libcfile_file_close(
210 			     *file,
211 			     error ) != 0 )
212 			{
213 				libcerror_error_set(
214 				 error,
215 				 LIBCERROR_ERROR_DOMAIN_IO,
216 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
217 				 "%s: unable to close file.",
218 				 function );
219 
220 				result = -1;
221 			}
222 		}
223 		*file = NULL;
224 
225 		memory_free(
226 		 internal_file );
227 	}
228 	return( result );
229 }
230 
231 /* Opens a file
232  * Returns 1 if successful or -1 on error
233  */
libcfile_file_open(libcfile_file_t * file,const char * filename,int access_flags,libcerror_error_t ** error)234 int libcfile_file_open(
235      libcfile_file_t *file,
236      const char *filename,
237      int access_flags,
238      libcerror_error_t **error )
239 {
240 	static char *function = "libcfile_file_open";
241 	uint32_t error_code   = 0;
242 
243 	if( libcfile_file_open_with_error_code(
244 	     file,
245 	     filename,
246 	     access_flags,
247 	     &error_code,
248 	     error ) != 1 )
249 	{
250 		libcerror_error_set(
251 		 error,
252 		 LIBCERROR_ERROR_DOMAIN_IO,
253 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
254 		 "%s: unable to open file.",
255 		 function );
256 
257 		return( -1 );
258 	}
259 	return( 1 );
260 }
261 
262 #if defined( WINAPI )
263 
264 #if ( WINVER >= 0x0600 ) && ( WINVER < 0x0602 )
265 
266 #define FileAlignmentInfo 0x11
267 
268 typedef struct _FILE_ALIGNMENT_INFO FILE_ALIGNMENT_INFO;
269 
270 struct _FILE_ALIGNMENT_INFO {
271 	ULONG AlignmentRequirement;
272 };
273 
274 #endif
275 
276 /* Opens a file
277  * This function uses the WINAPI function for Windows XP (0x0501) or later,
278  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
279  * Returns 1 if successful or -1 on error
280  */
libcfile_file_open_with_error_code(libcfile_file_t * file,const char * filename,int access_flags,uint32_t * error_code,libcerror_error_t ** error)281 int libcfile_file_open_with_error_code(
282      libcfile_file_t *file,
283      const char *filename,
284      int access_flags,
285      uint32_t *error_code,
286      libcerror_error_t **error )
287 {
288 #if ( WINVER >= 0x0600 )
289 	FILE_ALIGNMENT_INFO file_alignment_information;
290 
291 	BOOL result                             = 0;
292 #endif
293 
294 	libcfile_internal_file_t *internal_file = NULL;
295 	static char *function                   = "libcfile_file_open_with_error_code";
296 	DWORD file_io_access_flags              = 0;
297 	DWORD file_io_creation_flags            = 0;
298 	DWORD file_io_shared_flags              = 0;
299 	DWORD flags_and_attributes              = 0;
300 	size_t filename_length                  = 0;
301 	ssize_t read_count                      = 0;
302 
303 	if( file == NULL )
304 	{
305 		libcerror_error_set(
306 		 error,
307 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
308 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
309 		 "%s: invalid file.",
310 		 function );
311 
312 		return( -1 );
313 	}
314 	internal_file = (libcfile_internal_file_t *) file;
315 
316 	if( internal_file->handle != INVALID_HANDLE_VALUE )
317 	{
318 		libcerror_error_set(
319 		 error,
320 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
321 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
322 		 "%s: invalid file - handle value already set.",
323 		 function );
324 
325 		return( -1 );
326 	}
327 	if( filename == NULL )
328 	{
329 		libcerror_error_set(
330 		 error,
331 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
332 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
333 		 "%s: invalid filename.",
334 		 function );
335 
336 		return( -1 );
337 	}
338 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
339 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 ) )
340 	{
341 		file_io_access_flags   = GENERIC_WRITE | GENERIC_READ;
342 		file_io_creation_flags = OPEN_ALWAYS;
343 		file_io_shared_flags   = FILE_SHARE_READ;
344 	}
345 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
346 	{
347 		file_io_access_flags   = GENERIC_READ;
348 		file_io_creation_flags = OPEN_EXISTING;
349 
350 		/* FILE_SHARE_WRITE is set to allow reading files that are
351 		 * currently being written FILE_SHARE_READ alone does not suffice
352 		 */
353 		file_io_shared_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
354 	}
355 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
356 	{
357 		file_io_access_flags   = GENERIC_WRITE;
358 		file_io_creation_flags = OPEN_ALWAYS;
359 		file_io_shared_flags   = FILE_SHARE_READ;
360 	}
361 	else
362 	{
363 		libcerror_error_set(
364 		 error,
365 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
367 		 "%s: unsupported access flags: 0x%02x.",
368 		 function,
369 		 access_flags );
370 
371 		return( -1 );
372 	}
373 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
374 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_TRUNCATE ) != 0 ) )
375 	{
376 		file_io_creation_flags = CREATE_ALWAYS;
377 	}
378 	if( error_code == NULL )
379 	{
380 		libcerror_error_set(
381 		 error,
382 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
383 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
384 		 "%s: invalid error code.",
385 		 function );
386 
387 		return( -1 );
388 	}
389 	filename_length = narrow_string_length(
390 	                   filename );
391 
392 	if( filename_length > 4 )
393 	{
394 		if( ( filename[ 0 ] == '\\' )
395 		 && ( filename[ 1 ] == '\\' )
396 		 && ( filename[ 2 ] == '.' )
397 		 && ( filename[ 3 ] == '\\' ) )
398 		{
399 			/* Ignore \\.\F:\ which is an alternative notation for F:
400 			 */
401 			if( ( filename_length < 7 )
402 			 || ( filename[ 5 ] != ':' )
403 			 || ( filename[ 6 ] != '\\' ) )
404 			{
405 				internal_file->is_device_filename  = 1;
406 				internal_file->use_asynchronous_io = 1;
407 			}
408 		}
409 	}
410 	flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
411 
412 	if( internal_file->use_asynchronous_io != 0 )
413 	{
414 		flags_and_attributes |= FILE_FLAG_OVERLAPPED;
415 	}
416 #if ( WINVER <= 0x0500 )
417 	internal_file->handle = libcfile_CreateFileA(
418 	                         (LPCSTR) filename,
419 	                         file_io_access_flags,
420 	                         file_io_shared_flags,
421 	                         NULL,
422 	                         file_io_creation_flags,
423 	                         flags_and_attributes,
424 	                         NULL );
425 #else
426 	internal_file->handle = CreateFileA(
427 	                         (LPCSTR) filename,
428 	                         file_io_access_flags,
429 	                         file_io_shared_flags,
430 	                         NULL,
431 	                         file_io_creation_flags,
432 	                         flags_and_attributes,
433 	                         NULL );
434 #endif
435 	if( internal_file->handle == INVALID_HANDLE_VALUE )
436 	{
437 		*error_code = (uint32_t) GetLastError();
438 
439 		switch( *error_code )
440 		{
441 			case ERROR_ACCESS_DENIED:
442 				libcerror_error_set(
443 				 error,
444 				 LIBCERROR_ERROR_DOMAIN_IO,
445 				 LIBCERROR_IO_ERROR_ACCESS_DENIED,
446 				 "%s: access denied to file: %" PRIs_SYSTEM ".",
447 				 function,
448 				 filename );
449 
450 				break;
451 
452 			case ERROR_FILE_NOT_FOUND:
453 			case ERROR_PATH_NOT_FOUND:
454 				libcerror_error_set(
455 				 error,
456 				 LIBCERROR_ERROR_DOMAIN_IO,
457 				 LIBCERROR_IO_ERROR_INVALID_RESOURCE,
458 				 "%s: no such file: %" PRIs_SYSTEM ".",
459 				 function,
460 				 filename );
461 
462 				break;
463 
464 			default:
465 				libcerror_system_set_error(
466 				 error,
467 				 LIBCERROR_ERROR_DOMAIN_IO,
468 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
469 				 *error_code,
470 				 "%s: unable to open file: %" PRIs_SYSTEM ".",
471 				 function,
472 				 filename );
473 
474 				break;
475 		}
476 		return( -1 );
477 	}
478 	if( internal_file->is_device_filename != 0 )
479 	{
480 		read_count = libcfile_internal_file_io_control_read_with_error_code(
481 		              internal_file,
482 		              FSCTL_ALLOW_EXTENDED_DASD_IO,
483 		              NULL,
484 		              0,
485 		              NULL,
486 		              0,
487 		              error_code,
488 		              error );
489 
490 		if( read_count == -1 )
491 		{
492 			libcerror_error_set(
493 			 error,
494 			 LIBCERROR_ERROR_DOMAIN_IO,
495 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
496 			 "%s: unable to query device for: FSCTL_ALLOW_EXTENDED_DASD_IO.",
497 			 function );
498 
499 #if defined( HAVE_DEBUG_OUTPUT )
500 			if( libcnotify_verbose != 0 )
501 			{
502 				if( ( error != NULL )
503 				 && ( *error != NULL ) )
504 				{
505 					libcnotify_print_error_backtrace(
506 					 *error );
507 				}
508 			}
509 #endif
510 			libcerror_error_free(
511 			 error );
512 		}
513 #if ( WINVER >= 0x0600 )
514 		result = GetFileInformationByHandleEx(
515 		          internal_file->handle,
516 		          FileAlignmentInfo,
517 		          (void *) &file_alignment_information,
518 		          (DWORD) sizeof( FILE_ALIGNMENT_INFO ) );
519 
520 		if( result == FALSE )
521 		{
522 			*error_code = (uint32_t) GetLastError();
523 
524 			libcerror_system_set_error(
525 			 error,
526 			 LIBCERROR_ERROR_DOMAIN_IO,
527 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
528 			 *error_code,
529 			 "%s: unable to retrieve file alignment information.",
530 			 function );
531 
532 #if defined( HAVE_DEBUG_OUTPUT )
533 			if( libcnotify_verbose != 0 )
534 			{
535 				if( ( error != NULL )
536 				 && ( *error != NULL ) )
537 				{
538 					libcnotify_print_error_backtrace(
539 					 *error );
540 				}
541 			}
542 #endif
543 			libcerror_error_free(
544 			 error );
545 		}
546 		else if( file_alignment_information.AlignmentRequirement != 0 )
547 		{
548 			if( libcfile_internal_file_set_block_size(
549 			     internal_file,
550 			     (size_t) 512,
551 			     error ) != 1 )
552 			{
553 				libcerror_error_set(
554 				 error,
555 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
556 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
557 				 "%s: unable to set block size.",
558 				 function );
559 
560 				return( -1 );
561 			}
562 		}
563 #endif /* ( WINVER >= 0x0600 ) */
564 	}
565 	if( libcfile_internal_file_get_size(
566 	     internal_file,
567 	     &( internal_file->size ),
568 	     error ) != 1 )
569 	{
570 		libcerror_error_set(
571 		 error,
572 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
573 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
574 		 "%s: unable to retrieve size.",
575 		 function );
576 
577 		return( -1 );
578 	}
579 	internal_file->access_flags   = access_flags;
580 	internal_file->current_offset = 0;
581 
582 	return( 1 );
583 }
584 
585 #elif defined( HAVE_OPEN )
586 
587 /* Opens a file
588  * This function uses the POSIX open function or equivalent
589  * Returns 1 if successful or -1 on error
590  */
libcfile_file_open_with_error_code(libcfile_file_t * file,const char * filename,int access_flags,uint32_t * error_code,libcerror_error_t ** error)591 int libcfile_file_open_with_error_code(
592      libcfile_file_t *file,
593      const char *filename,
594      int access_flags,
595      uint32_t *error_code,
596      libcerror_error_t **error )
597 {
598 	libcfile_internal_file_t *internal_file = NULL;
599 	static char *function                   = "libcfile_file_open_with_error_code";
600 	int file_io_flags                       = 0;
601 
602 	if( file == NULL )
603 	{
604 		libcerror_error_set(
605 		 error,
606 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
607 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
608 		 "%s: invalid file.",
609 		 function );
610 
611 		return( -1 );
612 	}
613 	internal_file = (libcfile_internal_file_t *) file;
614 
615 	if( internal_file->descriptor != -1 )
616 	{
617 		libcerror_error_set(
618 		 error,
619 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
620 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
621 		 "%s: invalid file - descriptor value already set.",
622 		 function );
623 
624 		return( -1 );
625 	}
626 	if( filename == NULL )
627 	{
628 		libcerror_error_set(
629 		 error,
630 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
631 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
632 		 "%s: invalid filename.",
633 		 function );
634 
635 		return( -1 );
636 	}
637 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
638 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 ) )
639 	{
640 		file_io_flags = O_RDWR | O_CREAT;
641 	}
642 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
643 	{
644 		file_io_flags = O_RDONLY;
645 	}
646 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
647 	{
648 		file_io_flags = O_WRONLY | O_CREAT;
649 	}
650 	else
651 	{
652 		libcerror_error_set(
653 		 error,
654 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
655 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
656 		 "%s: unsupported access flags: 0x%02x.",
657 		 function,
658 		 access_flags );
659 
660 		return( -1 );
661 	}
662 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
663 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_TRUNCATE ) != 0 ) )
664 	{
665 		file_io_flags |= O_TRUNC;
666 	}
667 	if( error_code == NULL )
668 	{
669 		libcerror_error_set(
670 		 error,
671 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
672 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
673 		 "%s: invalid error code.",
674 		 function );
675 
676 		return( -1 );
677 	}
678 #if defined( O_CLOEXEC )
679 	/* Prevent the file descriptor to remain open across an execve
680 	 */
681 	file_io_flags |= O_CLOEXEC;
682 #endif
683 #if defined( HAVE_GLIB_H )
684 	internal_file->descriptor = g_open(
685 	                             filename,
686 	                             file_io_flags,
687 	                             0644 );
688 #else
689 	internal_file->descriptor = open(
690 	                             filename,
691 	                             file_io_flags,
692 	                             0644 );
693 #endif
694 	if( internal_file->descriptor == -1 )
695 	{
696 		*error_code = (uint32_t) errno;
697 
698 		switch( *error_code )
699 		{
700 			case EACCES:
701 				libcerror_error_set(
702 				 error,
703 				 LIBCERROR_ERROR_DOMAIN_IO,
704 				 LIBCERROR_IO_ERROR_ACCESS_DENIED,
705 				 "%s: access denied to file: %" PRIs_SYSTEM ".",
706 				 function,
707 				 filename );
708 
709 				break;
710 
711 			case ENOENT:
712 				libcerror_error_set(
713 				 error,
714 				 LIBCERROR_ERROR_DOMAIN_IO,
715 				 LIBCERROR_IO_ERROR_INVALID_RESOURCE,
716 				 "%s: no such file: %" PRIs_SYSTEM ".",
717 				 function,
718 				 filename );
719 
720 				break;
721 
722 			default:
723 				libcerror_system_set_error(
724 				 error,
725 				 LIBCERROR_ERROR_DOMAIN_IO,
726 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
727 				 *error_code,
728 				 "%s: unable to open file: %" PRIs_SYSTEM ".",
729 				 function,
730 				 filename );
731 
732 				break;
733 		}
734 		return( -1 );
735 	}
736 	if( libcfile_internal_file_get_size(
737 	     internal_file,
738 	     &( internal_file->size ),
739 	     error ) != 1 )
740 	{
741 		libcerror_error_set(
742 		 error,
743 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
744 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
745 		 "%s: unable to retrieve size.",
746 		 function );
747 
748 		return( -1 );
749 	}
750 	internal_file->access_flags   = access_flags;
751 	internal_file->current_offset = 0;
752 
753 	return( 1 );
754 }
755 
756 #else
757 #error Missing file open function
758 #endif
759 
760 #if defined( HAVE_WIDE_CHARACTER_TYPE )
761 
762 /* Opens a file
763  * Returns 1 if successful or -1 on error
764  */
libcfile_file_open_wide(libcfile_file_t * file,const wchar_t * filename,int access_flags,libcerror_error_t ** error)765 int libcfile_file_open_wide(
766      libcfile_file_t *file,
767      const wchar_t *filename,
768      int access_flags,
769      libcerror_error_t **error )
770 {
771 	static char *function = "libcfile_file_open_wide";
772 	uint32_t error_code   = 0;
773 
774 	if( libcfile_file_open_wide_with_error_code(
775 	     file,
776 	     filename,
777 	     access_flags,
778 	     &error_code,
779 	     error ) != 1 )
780 	{
781 		libcerror_error_set(
782 		 error,
783 		 LIBCERROR_ERROR_DOMAIN_IO,
784 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
785 		 "%s: unable to open file.",
786 		 function );
787 
788 		return( -1 );
789 	}
790 	return( 1 );
791 }
792 
793 #if defined( WINAPI )
794 
795 /* Opens a file
796  * This function uses the WINAPI function for Windows XP (0x0501) or later
797  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
798  * Returns 1 if successful or -1 on error
799  */
libcfile_file_open_wide_with_error_code(libcfile_file_t * file,const wchar_t * filename,int access_flags,uint32_t * error_code,libcerror_error_t ** error)800 int libcfile_file_open_wide_with_error_code(
801      libcfile_file_t *file,
802      const wchar_t *filename,
803      int access_flags,
804      uint32_t *error_code,
805      libcerror_error_t **error )
806 {
807 #if ( WINVER >= 0x0600 )
808 	FILE_ALIGNMENT_INFO file_alignment_information;
809 
810 	BOOL result                             = 0;
811 #endif
812 
813 	libcfile_internal_file_t *internal_file = NULL;
814 	static char *function                   = "libcfile_file_open_wide_with_error_code";
815 	DWORD file_io_access_flags              = 0;
816 	DWORD file_io_creation_flags            = 0;
817 	DWORD file_io_shared_flags              = 0;
818 	DWORD flags_and_attributes              = 0;
819 	size_t filename_length                  = 0;
820 	ssize_t read_count                      = 0;
821 
822 	if( file == NULL )
823 	{
824 		libcerror_error_set(
825 		 error,
826 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
827 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
828 		 "%s: invalid file.",
829 		 function );
830 
831 		return( -1 );
832 	}
833 	internal_file = (libcfile_internal_file_t *) file;
834 
835 	if( internal_file->handle != INVALID_HANDLE_VALUE )
836 	{
837 		libcerror_error_set(
838 		 error,
839 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
840 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
841 		 "%s: invalid file - handle value already set.",
842 		 function );
843 
844 		return( -1 );
845 	}
846 	if( filename == NULL )
847 	{
848 		libcerror_error_set(
849 		 error,
850 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
851 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
852 		 "%s: invalid filename.",
853 		 function );
854 
855 		return( -1 );
856 	}
857 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
858 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 ) )
859 	{
860 		file_io_access_flags   = GENERIC_WRITE | GENERIC_READ;
861 		file_io_creation_flags = OPEN_ALWAYS;
862 		file_io_shared_flags   = FILE_SHARE_READ;
863 	}
864 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
865 	{
866 		file_io_access_flags   = GENERIC_READ;
867 		file_io_creation_flags = OPEN_EXISTING;
868 
869 		/* FILE_SHARE_WRITE is set to allow reading files that are
870 		 * currently being written FILE_SHARE_READ alone does not suffice
871 		 */
872 		file_io_shared_flags = FILE_SHARE_READ | FILE_SHARE_WRITE;
873 	}
874 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
875 	{
876 		file_io_access_flags   = GENERIC_WRITE;
877 		file_io_creation_flags = OPEN_ALWAYS;
878 		file_io_shared_flags   = FILE_SHARE_READ;
879 	}
880 	else
881 	{
882 		libcerror_error_set(
883 		 error,
884 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
885 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
886 		 "%s: unsupported access flags: 0x%02x.",
887 		 function,
888 		 access_flags );
889 
890 		return( -1 );
891 	}
892 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
893 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_TRUNCATE ) != 0 ) )
894 	{
895 		file_io_creation_flags = CREATE_ALWAYS;
896 	}
897 	if( error_code == NULL )
898 	{
899 		libcerror_error_set(
900 		 error,
901 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
902 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
903 		 "%s: invalid error code.",
904 		 function );
905 
906 		return( -1 );
907 	}
908 	filename_length = wide_string_length(
909 	                   filename );
910 
911 	if( filename_length > 4 )
912 	{
913 		if( ( filename[ 0 ] == (wchar_t) '\\' )
914 		 && ( filename[ 1 ] == (wchar_t) '\\' )
915 		 && ( filename[ 2 ] == (wchar_t) '.' )
916 		 && ( filename[ 3 ] == (wchar_t) '\\' ) )
917 		{
918 			/* Ignore \\.\F:\ which is an alternative notation for F:
919 			 */
920 			if( ( filename_length < 7 )
921 			 || ( filename[ 5 ] != (wchar_t) ':' )
922 			 || ( filename[ 6 ] != (wchar_t) '\\' ) )
923 			{
924 				internal_file->is_device_filename  = 1;
925 				internal_file->use_asynchronous_io = 1;
926 			}
927 		}
928 	}
929 	flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
930 
931 	if( internal_file->use_asynchronous_io != 0 )
932 	{
933 		flags_and_attributes |= FILE_FLAG_OVERLAPPED;
934 	}
935 #if ( WINVER <= 0x0500 )
936 	internal_file->handle = libcfile_CreateFileW(
937 	                         (LPCWSTR) filename,
938 	                         file_io_access_flags,
939 	                         file_io_shared_flags,
940 	                         NULL,
941 	                         file_io_creation_flags,
942 	                         flags_and_attributes,
943 	                         NULL );
944 #else
945 	internal_file->handle = CreateFileW(
946 	                         (LPCWSTR) filename,
947 	                         file_io_access_flags,
948 	                         file_io_shared_flags,
949 	                         NULL,
950 	                         file_io_creation_flags,
951 	                         flags_and_attributes,
952 	                         NULL );
953 #endif
954 	if( internal_file->handle == INVALID_HANDLE_VALUE )
955 	{
956 		*error_code = (uint32_t) GetLastError();
957 
958 		switch( *error_code )
959 		{
960 			case ERROR_ACCESS_DENIED:
961 				libcerror_error_set(
962 				 error,
963 				 LIBCERROR_ERROR_DOMAIN_IO,
964 				 LIBCERROR_IO_ERROR_ACCESS_DENIED,
965 				 "%s: access denied to file: %" PRIs_SYSTEM ".",
966 				 function,
967 				 filename );
968 
969 				break;
970 
971 			case ERROR_FILE_NOT_FOUND:
972 			case ERROR_PATH_NOT_FOUND:
973 				libcerror_error_set(
974 				 error,
975 				 LIBCERROR_ERROR_DOMAIN_IO,
976 				 LIBCERROR_IO_ERROR_INVALID_RESOURCE,
977 				 "%s: no such file: %" PRIs_SYSTEM ".",
978 				 function,
979 				 filename );
980 
981 				break;
982 
983 			default:
984 				libcerror_system_set_error(
985 				 error,
986 				 LIBCERROR_ERROR_DOMAIN_IO,
987 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
988 				 *error_code,
989 				 "%s: unable to open file: %" PRIs_SYSTEM ".",
990 				 function,
991 				 filename );
992 
993 				break;
994 		}
995 		return( -1 );
996 	}
997 	if( internal_file->is_device_filename != 0 )
998 	{
999 		read_count = libcfile_internal_file_io_control_read_with_error_code(
1000 		              internal_file,
1001 		              FSCTL_ALLOW_EXTENDED_DASD_IO,
1002 		              NULL,
1003 		              0,
1004 		              NULL,
1005 		              0,
1006 		              error_code,
1007 		              error );
1008 
1009 		if( read_count == -1 )
1010 		{
1011 			libcerror_error_set(
1012 			 error,
1013 			 LIBCERROR_ERROR_DOMAIN_IO,
1014 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
1015 			 "%s: unable to query device for: FSCTL_ALLOW_EXTENDED_DASD_IO.",
1016 			 function );
1017 
1018 #if defined( HAVE_DEBUG_OUTPUT )
1019 			if( libcnotify_verbose != 0 )
1020 			{
1021 				if( ( error != NULL )
1022 				 && ( *error != NULL ) )
1023 				{
1024 					libcnotify_print_error_backtrace(
1025 					 *error );
1026 				}
1027 			}
1028 #endif
1029 			libcerror_error_free(
1030 			 error );
1031 		}
1032 #if ( WINVER >= 0x0600 )
1033 		result = GetFileInformationByHandleEx(
1034 		          internal_file->handle,
1035 		          FileAlignmentInfo,
1036 		          (void *) &file_alignment_information,
1037 		          (DWORD) sizeof( FILE_ALIGNMENT_INFO ) );
1038 
1039 		if( result == FALSE )
1040 		{
1041 			*error_code = (uint32_t) GetLastError();
1042 
1043 			libcerror_system_set_error(
1044 			 error,
1045 			 LIBCERROR_ERROR_DOMAIN_IO,
1046 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
1047 			 *error_code,
1048 			 "%s: unable to retrieve file alignment information.",
1049 			 function );
1050 
1051 #if defined( HAVE_DEBUG_OUTPUT )
1052 			if( libcnotify_verbose != 0 )
1053 			{
1054 				if( ( error != NULL )
1055 				 && ( *error != NULL ) )
1056 				{
1057 					libcnotify_print_error_backtrace(
1058 					 *error );
1059 				}
1060 			}
1061 #endif
1062 			libcerror_error_free(
1063 			 error );
1064 		}
1065 		else if( file_alignment_information.AlignmentRequirement != 0 )
1066 		{
1067 			if( libcfile_internal_file_set_block_size(
1068 			     internal_file,
1069 			     (size_t) 512,
1070 			     error ) != 1 )
1071 			{
1072 				libcerror_error_set(
1073 				 error,
1074 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1075 				 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1076 				 "%s: unable to set block size.",
1077 				 function );
1078 
1079 				return( -1 );
1080 			}
1081 		}
1082 #endif /* ( WINVER >= 0x0600 ) */
1083 	}
1084 	if( libcfile_internal_file_get_size(
1085 	     internal_file,
1086 	     &( internal_file->size ),
1087 	     error ) != 1 )
1088 	{
1089 		libcerror_error_set(
1090 		 error,
1091 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1092 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1093 		 "%s: unable to retrieve size.",
1094 		 function );
1095 
1096 		return( -1 );
1097 	}
1098 	internal_file->access_flags   = access_flags;
1099 	internal_file->current_offset = 0;
1100 
1101 	return( 1 );
1102 }
1103 
1104 #elif defined( HAVE_OPEN )
1105 
1106 /* Opens a file
1107  * This function uses the POSIX open function or equivalent
1108  * Returns 1 if successful or -1 on error
1109  */
libcfile_file_open_wide_with_error_code(libcfile_file_t * file,const wchar_t * filename,int access_flags,uint32_t * error_code,libcerror_error_t ** error)1110 int libcfile_file_open_wide_with_error_code(
1111      libcfile_file_t *file,
1112      const wchar_t *filename,
1113      int access_flags,
1114      uint32_t *error_code,
1115      libcerror_error_t **error )
1116 {
1117 	libcfile_internal_file_t *internal_file = NULL;
1118 	static char *function                   = "libcfile_file_open_wide_with_error_code";
1119 	char *narrow_filename                   = NULL;
1120 	size_t filename_size                    = 0;
1121 	size_t narrow_filename_size             = 0;
1122 	int file_io_flags                       = 0;
1123 
1124 	if( file == NULL )
1125 	{
1126 		libcerror_error_set(
1127 		 error,
1128 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1129 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1130 		 "%s: invalid file.",
1131 		 function );
1132 
1133 		return( -1 );
1134 	}
1135 	internal_file = (libcfile_internal_file_t *) file;
1136 
1137 	if( internal_file->descriptor != -1 )
1138 	{
1139 		libcerror_error_set(
1140 		 error,
1141 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1142 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1143 		 "%s: invalid file - descriptor value already set.",
1144 		 function );
1145 
1146 		return( -1 );
1147 	}
1148 	if( filename == NULL )
1149 	{
1150 		libcerror_error_set(
1151 		 error,
1152 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1153 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1154 		 "%s: invalid filename.",
1155 		 function );
1156 
1157 		return( -1 );
1158 	}
1159 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
1160 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 ) )
1161 	{
1162 		file_io_flags = O_RDWR | O_CREAT;
1163 	}
1164 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_READ ) != 0 )
1165 	{
1166 		file_io_flags = O_RDONLY;
1167 	}
1168 	else if( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
1169 	{
1170 		file_io_flags = O_WRONLY | O_CREAT;
1171 	}
1172 	else
1173 	{
1174 		libcerror_error_set(
1175 		 error,
1176 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1177 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1178 		 "%s: unsupported access flags: 0x%02x.",
1179 		 function,
1180 		 access_flags );
1181 
1182 		return( -1 );
1183 	}
1184 	if( ( ( access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
1185 	 && ( ( access_flags & LIBCFILE_ACCESS_FLAG_TRUNCATE ) != 0 ) )
1186 	{
1187 		file_io_flags |= O_TRUNC;
1188 	}
1189 	if( error_code == NULL )
1190 	{
1191 		libcerror_error_set(
1192 		 error,
1193 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1194 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1195 		 "%s: invalid error code.",
1196 		 function );
1197 
1198 		return( -1 );
1199 	}
1200 	filename_size = 1 + wide_string_length(
1201 	                     filename );
1202 
1203 	if( libcfile_system_string_size_from_wide_string(
1204 	     filename,
1205 	     filename_size,
1206 	     &narrow_filename_size,
1207 	     error ) != 1 )
1208 	{
1209 		libcerror_error_set(
1210 		 error,
1211 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1212 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
1213 		 "%s: unable to determine narrow character filename size.",
1214 		 function );
1215 
1216 		goto on_error;
1217 	}
1218 	narrow_filename = narrow_string_allocate(
1219 	                   narrow_filename_size );
1220 
1221 	if( narrow_filename == NULL )
1222 	{
1223 		libcerror_error_set(
1224 		 error,
1225 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1226 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1227 		 "%s: unable to create narrow character filename.",
1228 		 function );
1229 
1230 		goto on_error;
1231 	}
1232 	if( libcfile_system_string_copy_from_wide_string(
1233 	     narrow_filename,
1234 	     narrow_filename_size,
1235 	     filename,
1236 	     filename_size,
1237 	     error ) != 1 )
1238 	{
1239 		libcerror_error_set(
1240 		 error,
1241 		 LIBCERROR_ERROR_DOMAIN_CONVERSION,
1242 		 LIBCERROR_CONVERSION_ERROR_GENERIC,
1243 		 "%s: unable to set narrow character filename.",
1244 		 function );
1245 
1246 		goto on_error;
1247 	}
1248 #if defined( O_CLOEXEC )
1249 	/* Prevent the file descriptor to remain open across an execve
1250 	 */
1251 	file_io_flags |= O_CLOEXEC;
1252 #endif
1253 #if defined( HAVE_GLIB_H )
1254 	internal_file->descriptor = g_open(
1255 	                             narrow_filename,
1256 	                             file_io_flags,
1257 	                             0644 );
1258 #else
1259 	internal_file->descriptor = open(
1260 	                             narrow_filename,
1261 	                             file_io_flags,
1262 	                             0644 );
1263 #endif
1264 
1265 	memory_free(
1266 	 narrow_filename );
1267 
1268 	narrow_filename = NULL;
1269 
1270 	if( internal_file->descriptor == -1 )
1271 	{
1272 		*error_code = (uint32_t) errno;
1273 
1274 		switch( *error_code )
1275 		{
1276 			case EACCES:
1277 				libcerror_error_set(
1278 				 error,
1279 				 LIBCERROR_ERROR_DOMAIN_IO,
1280 				 LIBCERROR_IO_ERROR_ACCESS_DENIED,
1281 				 "%s: access denied to file: %" PRIs_SYSTEM ".",
1282 				 function,
1283 				 filename );
1284 
1285 				break;
1286 
1287 			case ENOENT:
1288 				libcerror_error_set(
1289 				 error,
1290 				 LIBCERROR_ERROR_DOMAIN_IO,
1291 				 LIBCERROR_IO_ERROR_INVALID_RESOURCE,
1292 				 "%s: no such file: %" PRIs_SYSTEM ".",
1293 				 function,
1294 				 filename );
1295 
1296 				break;
1297 
1298 			default:
1299 				libcerror_system_set_error(
1300 				 error,
1301 				 LIBCERROR_ERROR_DOMAIN_IO,
1302 				 LIBCERROR_IO_ERROR_OPEN_FAILED,
1303 				 *error_code,
1304 				 "%s: unable to open file: %" PRIs_SYSTEM ".",
1305 				 function,
1306 				 filename );
1307 
1308 				break;
1309 		}
1310 		goto on_error;
1311 	}
1312 	if( libcfile_internal_file_get_size(
1313 	     internal_file,
1314 	     &( internal_file->size ),
1315 	     error ) != 1 )
1316 	{
1317 		libcerror_error_set(
1318 		 error,
1319 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1320 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1321 		 "%s: unable to retrieve size.",
1322 		 function );
1323 
1324 		goto on_error;
1325 	}
1326 	return( 1 );
1327 
1328 on_error:
1329 	if( narrow_filename != NULL )
1330 	{
1331 		memory_free(
1332 		 narrow_filename );
1333 	}
1334 	return( -1 );
1335 }
1336 
1337 #else
1338 #error Missing file open wide function
1339 #endif
1340 
1341 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1342 
1343 #if defined( WINAPI )
1344 
1345 /* Closes the file
1346  * This function uses the WINAPI function for Windows 2000 (0x0500) or later
1347  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
1348  * Returns 0 if successful or -1 on error
1349  */
libcfile_file_close(libcfile_file_t * file,libcerror_error_t ** error)1350 int libcfile_file_close(
1351      libcfile_file_t *file,
1352      libcerror_error_t **error )
1353 {
1354 	libcfile_internal_file_t *internal_file = NULL;
1355 	static char *function                   = "libcfile_file_close";
1356 	DWORD error_code                        = 0;
1357 	BOOL result                             = FALSE;
1358 
1359 	if( file == NULL )
1360 	{
1361 		libcerror_error_set(
1362 		 error,
1363 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1364 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1365 		 "%s: invalid file.",
1366 		 function );
1367 
1368 		return( -1 );
1369 	}
1370 	internal_file = (libcfile_internal_file_t *) file;
1371 
1372 	if( internal_file->handle != INVALID_HANDLE_VALUE )
1373 	{
1374 #if ( WINVER <= 0x0500 )
1375 		result = libcfile_CloseHandle(
1376 		          internal_file->handle );
1377 #else
1378 		result = CloseHandle(
1379 		          internal_file->handle );
1380 #endif
1381 		if( result == 0 )
1382 		{
1383 			error_code = GetLastError();
1384 
1385 			libcerror_system_set_error(
1386 			 error,
1387 			 LIBCERROR_ERROR_DOMAIN_IO,
1388 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
1389 			 error_code,
1390 			 "%s: unable to close file.",
1391 			 function );
1392 
1393 			return( -1 );
1394 		}
1395 		internal_file->handle              = INVALID_HANDLE_VALUE;
1396 		internal_file->is_device_filename  = 0;
1397 		internal_file->use_asynchronous_io = 0;
1398 		internal_file->access_flags        = 0;
1399 		internal_file->size                = 0;
1400 		internal_file->current_offset      = 0;
1401 	}
1402 	if( internal_file->block_data != NULL )
1403 	{
1404 		if( memory_set(
1405 		     internal_file->block_data,
1406 		     0,
1407 		     internal_file->block_size ) == NULL )
1408 		{
1409 			libcerror_error_set(
1410 			 error,
1411 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1412 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1413 			 "%s: unable to clear block data.",
1414 			 function );
1415 
1416 			return( -1 );
1417 		}
1418 	}
1419 	return( 0 );
1420 }
1421 
1422 #elif defined( HAVE_CLOSE )
1423 
1424 /* Closes the file
1425  * This function uses the POSIX close function or equivalent
1426  * Returns 0 if successful or -1 on error
1427  */
libcfile_file_close(libcfile_file_t * file,libcerror_error_t ** error)1428 int libcfile_file_close(
1429      libcfile_file_t *file,
1430      libcerror_error_t **error )
1431 {
1432 	libcfile_internal_file_t *internal_file = NULL;
1433 	static char *function                   = "libcfile_file_close";
1434 
1435 	if( file == NULL )
1436 	{
1437 		libcerror_error_set(
1438 		 error,
1439 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1440 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1441 		 "%s: invalid file.",
1442 		 function );
1443 
1444 		return( -1 );
1445 	}
1446 	internal_file = (libcfile_internal_file_t *) file;
1447 
1448 	if( internal_file->descriptor != -1 )
1449 	{
1450 		if( close(
1451 		     internal_file->descriptor ) != 0 )
1452 		{
1453 			libcerror_system_set_error(
1454 			 error,
1455 			 LIBCERROR_ERROR_DOMAIN_IO,
1456 			 LIBCERROR_IO_ERROR_CLOSE_FAILED,
1457 			 errno,
1458 			 "%s: unable to close file.",
1459 			 function );
1460 
1461 			return( -1 );
1462 		}
1463 		internal_file->descriptor     = -1;
1464 		internal_file->access_flags   = 0;
1465 		internal_file->size           = 0;
1466 		internal_file->current_offset = 0;
1467 	}
1468 	if( internal_file->block_data != NULL )
1469 	{
1470 		if( memory_set(
1471 		     internal_file->block_data,
1472 		     0,
1473 		     internal_file->block_size ) == NULL )
1474 		{
1475 			libcerror_error_set(
1476 			 error,
1477 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1478 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1479 			 "%s: unable to clear block data.",
1480 			 function );
1481 
1482 			return( -1 );
1483 		}
1484 	}
1485 	return( 0 );
1486 }
1487 
1488 #else
1489 #error Missing file close function
1490 #endif
1491 
1492 /* Reads a buffer from the file
1493  * Returns the number of bytes read if successful, or -1 on error
1494  */
libcfile_file_read_buffer(libcfile_file_t * file,uint8_t * buffer,size_t size,libcerror_error_t ** error)1495 ssize_t libcfile_file_read_buffer(
1496          libcfile_file_t *file,
1497          uint8_t *buffer,
1498          size_t size,
1499          libcerror_error_t **error )
1500 {
1501 	static char *function = "libcfile_file_read_buffer";
1502 	ssize_t read_count    = 0;
1503 	uint32_t error_code   = 0;
1504 
1505 	read_count = libcfile_file_read_buffer_with_error_code(
1506 	              file,
1507 	              buffer,
1508 	              size,
1509 	              &error_code,
1510 	              error );
1511 
1512 	if( read_count == -1 )
1513 	{
1514 		libcerror_error_set(
1515 		 error,
1516 		 LIBCERROR_ERROR_DOMAIN_IO,
1517 		 LIBCERROR_IO_ERROR_READ_FAILED,
1518 		 "%s: unable to read from file.",
1519 		 function );
1520 
1521 		return( -1 );
1522 	}
1523 	return( read_count );
1524 }
1525 
1526 #if defined( WINAPI )
1527 
1528 /* Reads a buffer from the file
1529  * This is an internal function to wrap ReadFile in synchronous and asynchronous mode
1530  * the current_offset is only used in asynchronous mode.
1531  * Returns the number of bytes read if successful, or -1 on error
1532  */
libcfile_internal_file_read_buffer_at_offset_with_error_code(libcfile_internal_file_t * internal_file,off64_t current_offset,uint8_t * buffer,size_t size,uint32_t * error_code,libcerror_error_t ** error)1533 ssize_t libcfile_internal_file_read_buffer_at_offset_with_error_code(
1534          libcfile_internal_file_t *internal_file,
1535          off64_t current_offset,
1536          uint8_t *buffer,
1537          size_t size,
1538          uint32_t *error_code,
1539          libcerror_error_t **error )
1540 {
1541 	OVERLAPPED overlapped_data;
1542 
1543 	static char *function  = "libcfile_internal_file_read_buffer_at_offset_with_error_code";
1544 	OVERLAPPED *overlapped = NULL;
1545 	DWORD read_count       = 0;
1546 	BOOL io_pending        = FALSE;
1547 	BOOL result            = FALSE;
1548 
1549 	if( internal_file == NULL )
1550 	{
1551 		libcerror_error_set(
1552 		 error,
1553 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1554 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1555 		 "%s: invalid file.",
1556 		 function );
1557 
1558 		return( -1 );
1559 	}
1560 	if( current_offset < 0 )
1561 	{
1562 		libcerror_error_set(
1563 		 error,
1564 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1565 		 LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1566 		 "%s: invalid current offset value out of bounds.",
1567 		 function );
1568 
1569 		return( -1 );
1570 	}
1571 	if( buffer == NULL )
1572 	{
1573 		libcerror_error_set(
1574 		 error,
1575 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1576 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1577 		 "%s: invalid buffer.",
1578 		 function );
1579 
1580 		return( -1 );
1581 	}
1582 #if ( UINT32_MAX < SSIZE_MAX )
1583 	if( size > (size_t) UINT32_MAX )
1584 #else
1585 	if( size > (size_t) SSIZE_MAX )
1586 #endif
1587 	{
1588 		libcerror_error_set(
1589 		 error,
1590 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1591 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1592 		 "%s: invalid size value exceeds maximum.",
1593 		 function );
1594 
1595 		return( -1 );
1596 	}
1597 	if( error_code == NULL )
1598 	{
1599 		libcerror_error_set(
1600 		 error,
1601 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1602 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1603 		 "%s: invalid error code.",
1604 		 function );
1605 
1606 		return( -1 );
1607 	}
1608 	/* For Windows devices we need to use asynchronous IO here
1609 	 * otherwise the ReadFile function can return ERROR_INVALID_PARAMETER
1610 	 * if the device is read concurrently and the the block is too large
1611 	 * to fill. Using smaller block sizes decreases the likelyhood but
1612 	 * also impacts the performance.
1613 	 */
1614 	if( internal_file->use_asynchronous_io != 0 )
1615 	{
1616 		if( memory_set(
1617 		     &overlapped_data,
1618 		     0,
1619 		     sizeof( OVERLAPPED ) ) == NULL )
1620 		{
1621 			libcerror_error_set(
1622 			 error,
1623 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1624 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1625 			 "%s: unable to clear overlapped data.",
1626 			 function );
1627 
1628 			return( -1 );
1629 		}
1630 		overlapped = &overlapped_data;
1631 
1632 		overlapped->Offset     = (DWORD) ( 0x0ffffffffUL & current_offset );
1633 		overlapped->OffsetHigh = (DWORD) ( current_offset >> 32 );
1634 	}
1635 #if ( WINVER <= 0x0500 )
1636 	result = libcfile_ReadFile(
1637 		  internal_file->handle,
1638 		  buffer,
1639 		  (DWORD) size,
1640 		  &read_count,
1641 		  overlapped );
1642 #else
1643 	result = ReadFile(
1644 		  internal_file->handle,
1645 		  (VOID *) buffer,
1646 		  (DWORD) size,
1647 		  &read_count,
1648 		  overlapped );
1649 #endif
1650 	if( result == 0 )
1651 	{
1652 		*error_code = (uint32_t) GetLastError();
1653 
1654 		switch( *error_code )
1655 		{
1656 			case ERROR_HANDLE_EOF:
1657 				break;
1658 
1659 			case ERROR_IO_PENDING:
1660 				io_pending = TRUE;
1661 				break;
1662 
1663 			default:
1664 				libcerror_system_set_error(
1665 				 error,
1666 				 LIBCERROR_ERROR_DOMAIN_IO,
1667 				 LIBCERROR_IO_ERROR_READ_FAILED,
1668 				 *error_code,
1669 				 "%s: unable to read from file.",
1670 				 function );
1671 
1672 				return( -1 );
1673 		}
1674 	}
1675 	if( io_pending == TRUE )
1676 	{
1677 #if ( WINVER <= 0x0500 )
1678 		result = libcfile_GetOverlappedResult(
1679 			  internal_file->handle,
1680 			  overlapped,
1681 			  &read_count,
1682 			  TRUE );
1683 #else
1684 		result = GetOverlappedResult(
1685 			  internal_file->handle,
1686 			  overlapped,
1687 			  &read_count,
1688 			  TRUE );
1689 #endif
1690 		if( result == 0 )
1691 		{
1692 			*error_code = (uint32_t) GetLastError();
1693 
1694 			switch( *error_code )
1695 			{
1696 				case ERROR_HANDLE_EOF:
1697 					break;
1698 
1699 				default:
1700 					libcerror_system_set_error(
1701 					 error,
1702 					 LIBCERROR_ERROR_DOMAIN_IO,
1703 					 LIBCERROR_IO_ERROR_READ_FAILED,
1704 					 *error_code,
1705 					 "%s: unable to read from file - overlapped result.",
1706 					 function );
1707 
1708 					return( -1 );
1709 			}
1710 		}
1711 	}
1712 	return( (ssize_t) read_count );
1713 }
1714 
1715 /* Reads a buffer from the file
1716  * This function uses the WINAPI function for Windows XP (0x0501) or later
1717  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
1718  * Returns the number of bytes read if successful, or -1 on error
1719  */
libcfile_file_read_buffer_with_error_code(libcfile_file_t * file,uint8_t * buffer,size_t size,uint32_t * error_code,libcerror_error_t ** error)1720 ssize_t libcfile_file_read_buffer_with_error_code(
1721          libcfile_file_t *file,
1722          uint8_t *buffer,
1723          size_t size,
1724          uint32_t *error_code,
1725          libcerror_error_t **error )
1726 {
1727 	libcfile_internal_file_t *internal_file = NULL;
1728 	static char *function                   = "libcfile_file_read_buffer_with_error_code";
1729 	size_t buffer_offset                    = 0;
1730 	size_t read_size                        = 0;
1731 	size_t read_size_remainder              = 0;
1732 	ssize_t read_count                      = 0;
1733 	BOOL result                             = FALSE;
1734 
1735 	if( file == NULL )
1736 	{
1737 		libcerror_error_set(
1738 		 error,
1739 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1740 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1741 		 "%s: invalid file.",
1742 		 function );
1743 
1744 		return( -1 );
1745 	}
1746 	internal_file = (libcfile_internal_file_t *) file;
1747 
1748 	if( internal_file->handle == INVALID_HANDLE_VALUE )
1749 	{
1750 		libcerror_error_set(
1751 		 error,
1752 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1753 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1754 		 "%s: invalid file - missing handle.",
1755 		 function );
1756 
1757 		return( -1 );
1758 	}
1759 	if( buffer == NULL )
1760 	{
1761 		libcerror_error_set(
1762 		 error,
1763 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1764 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1765 		 "%s: invalid buffer.",
1766 		 function );
1767 
1768 		return( -1 );
1769 	}
1770 #if ( UINT32_MAX < SSIZE_MAX )
1771 	if( size > (size_t) UINT32_MAX )
1772 #else
1773 	if( size > (size_t) SSIZE_MAX )
1774 #endif
1775 	{
1776 		libcerror_error_set(
1777 		 error,
1778 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1779 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1780 		 "%s: invalid size value exceeds maximum.",
1781 		 function );
1782 
1783 		return( -1 );
1784 	}
1785 	if( error_code == NULL )
1786 	{
1787 		libcerror_error_set(
1788 		 error,
1789 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1790 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1791 		 "%s: invalid error code.",
1792 		 function );
1793 
1794 		return( -1 );
1795 	}
1796 	if( internal_file->block_size != 0 )
1797 	{
1798 		if( internal_file->block_data == NULL )
1799 		{
1800 			libcerror_error_set(
1801 			 error,
1802 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1803 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1804 			 "%s: invalid file - missing block data.",
1805 			 function );
1806 
1807 			return( -1 );
1808 		}
1809 	}
1810 	if( internal_file->current_offset < 0 )
1811 	{
1812 		libcerror_error_set(
1813 		 error,
1814 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1816 		 "%s: invalid file - current offset value out of bounds.",
1817 		 function );
1818 
1819 		return( -1 );
1820 	}
1821 	if( ( size == 0 )
1822 	 || ( (size64_t) internal_file->current_offset > internal_file->size ) )
1823 	{
1824 		return( 0 );
1825 	}
1826 	if( ( (size64_t) internal_file->current_offset + size ) > internal_file->size )
1827 	{
1828 		size = (size_t) ( internal_file->size - internal_file->current_offset );
1829 	}
1830 	if( internal_file->block_size != 0 )
1831 	{
1832 		/* Read a block of data to align with the next block
1833 		 */
1834 		if( ( internal_file->block_data_offset > 0 )
1835 		 && ( internal_file->block_data_size == 0 ) )
1836 		{
1837 			if( memory_set(
1838 			     internal_file->block_data,
1839 			     0,
1840 			     internal_file->block_size ) == NULL )
1841 			{
1842 				libcerror_error_set(
1843 				 error,
1844 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
1845 				 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1846 				 "%s: unable to clear block data.",
1847 				 function );
1848 
1849 				return( -1 );
1850 			}
1851 			read_count = libcfile_internal_file_read_buffer_at_offset_with_error_code(
1852 			              internal_file,
1853 			              internal_file->current_offset - internal_file->block_data_offset,
1854 			              internal_file->block_data,
1855 			              internal_file->block_size,
1856 			              error_code,
1857 			              error );
1858 
1859 			if( read_count != (ssize_t) internal_file->block_size )
1860 			{
1861 				libcerror_error_set(
1862 				 error,
1863 				 LIBCERROR_ERROR_DOMAIN_IO,
1864 				 LIBCERROR_IO_ERROR_READ_FAILED,
1865 				 "%s: invalid read count: %" PRIzd " returned.",
1866 				 function,
1867 				 read_count );
1868 
1869 				return( -1 );
1870 			}
1871 			internal_file->block_data_size = (size_t) read_count;
1872 		}
1873 		if( ( internal_file->block_data_offset > 0 )
1874 		 && ( internal_file->block_data_offset < internal_file->block_data_size ) )
1875 		{
1876 			read_size = internal_file->block_data_size - internal_file->block_data_offset;
1877 
1878 			if( read_size > size )
1879 			{
1880 				read_size = size;
1881 			}
1882 			if( memory_copy(
1883 			     buffer,
1884 			     &( internal_file->block_data[ internal_file->block_data_offset ] ),
1885 			     read_size ) == NULL )
1886 			{
1887 				libcerror_error_set(
1888 				 error,
1889 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
1890 				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1891 				 "%s: unable to copy block data.",
1892 				 function );
1893 
1894 				return( -1 );
1895 			}
1896 			buffer_offset                    += read_size;
1897 			size                             -= read_size;
1898 			internal_file->current_offset    += read_size;
1899 			internal_file->block_data_offset += read_size;
1900 		}
1901 		if( size == 0 )
1902 		{
1903 			return( (ssize_t) buffer_offset );
1904 		}
1905 	}
1906 	read_size = size;
1907 
1908 	if( internal_file->block_size != 0 )
1909 	{
1910 		/* Read block aligned
1911 		 */
1912 		read_size_remainder = read_size % internal_file->block_size;
1913 		read_size          -= read_size_remainder;
1914 	}
1915 	if( read_size > 0 )
1916 	{
1917 		read_count = libcfile_internal_file_read_buffer_at_offset_with_error_code(
1918 		              internal_file,
1919 		              internal_file->current_offset,
1920 		              &( buffer[ buffer_offset ] ),
1921 		              read_size,
1922 		              error_code,
1923 		              error );
1924 
1925 		if( ( internal_file->block_size == 0 )
1926 		 && ( read_count < 0 ) )
1927 		{
1928 			result = 0;
1929 		}
1930 		else if( ( internal_file->block_size != 0 )
1931 		      && ( read_count != (ssize_t) read_size ) )
1932 		{
1933 			result = 0;
1934 		}
1935 		else
1936 		{
1937 			result = 1;
1938 		}
1939 		if( result == 0 )
1940 		{
1941 			libcerror_system_set_error(
1942 			 error,
1943 			 LIBCERROR_ERROR_DOMAIN_IO,
1944 			 LIBCERROR_IO_ERROR_READ_FAILED,
1945 			 *error_code,
1946 			 "%s: unable to read from file.",
1947 			 function );
1948 
1949 			return( -1 );
1950 		}
1951 		buffer_offset                 += (size_t) read_count;
1952 		internal_file->current_offset += read_count;
1953 	}
1954 	/* Read the non-aligned remainder
1955 	 */
1956 	if( read_size_remainder > 0 )
1957 	{
1958 		if( memory_set(
1959 		     internal_file->block_data,
1960 		     0,
1961 		     internal_file->block_size ) == NULL )
1962 		{
1963 			libcerror_error_set(
1964 			 error,
1965 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1966 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1967 			 "%s: unable to clear block data.",
1968 			 function );
1969 
1970 			return( -1 );
1971 		}
1972 		read_count = libcfile_internal_file_read_buffer_at_offset_with_error_code(
1973 		              internal_file,
1974 		              internal_file->current_offset,
1975 		              internal_file->block_data,
1976 		              internal_file->block_size,
1977 		              error_code,
1978 		              error );
1979 
1980 		if( read_count != (ssize_t) internal_file->block_size )
1981 		{
1982 			libcerror_error_set(
1983 			 error,
1984 			 LIBCERROR_ERROR_DOMAIN_IO,
1985 			 LIBCERROR_IO_ERROR_READ_FAILED,
1986 			 "%s: invalid read count: %" PRIzd " returned.",
1987 			 function,
1988 			 read_count );
1989 
1990 			return( -1 );
1991 		}
1992 		internal_file->block_data_offset = 0;
1993 		internal_file->block_data_size   = (size_t) read_count;
1994 
1995 		if( memory_copy(
1996 		     &( buffer[ buffer_offset ] ),
1997 		     internal_file->block_data,
1998 		     read_size_remainder ) == NULL )
1999 		{
2000 			libcerror_error_set(
2001 			 error,
2002 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2003 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2004 			 "%s: unable to copy block data.",
2005 			 function );
2006 
2007 			return( -1 );
2008 		}
2009 		buffer_offset                    += read_size_remainder;
2010 		internal_file->current_offset    += read_size_remainder;
2011 		internal_file->block_data_offset += read_size_remainder;
2012 	}
2013 	return( (ssize_t) buffer_offset );
2014 }
2015 
2016 #elif defined( HAVE_READ )
2017 
2018 /* Reads a buffer from the file
2019  * This function uses the POSIX read function or equivalent
2020  * Returns the number of bytes read if successful, or -1 on error
2021  */
libcfile_file_read_buffer_with_error_code(libcfile_file_t * file,uint8_t * buffer,size_t size,uint32_t * error_code,libcerror_error_t ** error)2022 ssize_t libcfile_file_read_buffer_with_error_code(
2023          libcfile_file_t *file,
2024          uint8_t *buffer,
2025          size_t size,
2026          uint32_t *error_code,
2027          libcerror_error_t **error )
2028 {
2029 	libcfile_internal_file_t *internal_file = NULL;
2030 	static char *function                   = "libcfile_file_read_buffer_with_error_code";
2031 	size_t buffer_offset                    = 0;
2032 	size_t read_size                        = 0;
2033 	size_t read_size_remainder              = 0;
2034 	ssize_t read_count                      = 0;
2035 	int result                              = 0;
2036 
2037 	if( file == NULL )
2038 	{
2039 		libcerror_error_set(
2040 		 error,
2041 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2042 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2043 		 "%s: invalid file.",
2044 		 function );
2045 
2046 		return( -1 );
2047 	}
2048 	internal_file = (libcfile_internal_file_t *) file;
2049 
2050 	if( internal_file->descriptor == -1 )
2051 	{
2052 		libcerror_error_set(
2053 		 error,
2054 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2055 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2056 		 "%s: invalid file - missing descriptor.",
2057 		 function );
2058 
2059 		return( -1 );
2060 	}
2061 	if( buffer == NULL )
2062 	{
2063 		libcerror_error_set(
2064 		 error,
2065 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2066 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2067 		 "%s: invalid buffer.",
2068 		 function );
2069 
2070 		return( -1 );
2071 	}
2072 	if( size > (size_t) SSIZE_MAX )
2073 	{
2074 		libcerror_error_set(
2075 		 error,
2076 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2077 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2078 		 "%s: invalid size value exceeds maximum.",
2079 		 function );
2080 
2081 		return( -1 );
2082 	}
2083 	if( error_code == NULL )
2084 	{
2085 		libcerror_error_set(
2086 		 error,
2087 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2088 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2089 		 "%s: invalid error code.",
2090 		 function );
2091 
2092 		return( -1 );
2093 	}
2094 	if( internal_file->block_size != 0 )
2095 	{
2096 		if( internal_file->block_data == NULL )
2097 		{
2098 			libcerror_error_set(
2099 			 error,
2100 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2101 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2102 			 "%s: invalid file - missing block data.",
2103 			 function );
2104 
2105 			return( -1 );
2106 		}
2107 	}
2108 	if( internal_file->current_offset < 0 )
2109 	{
2110 		libcerror_error_set(
2111 		 error,
2112 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2113 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2114 		 "%s: invalid file - current offset value out of bounds.",
2115 		 function );
2116 
2117 		return( -1 );
2118 	}
2119 	if( ( size == 0 )
2120 	 || ( (size64_t) internal_file->current_offset > internal_file->size ) )
2121 	{
2122 		return( 0 );
2123 	}
2124 	if( ( (size64_t) internal_file->current_offset + size ) > internal_file->size )
2125 	{
2126 		size = (size_t) ( internal_file->size - internal_file->current_offset );
2127 	}
2128 	if( internal_file->block_size != 0 )
2129 	{
2130 		/* Read a block of data to align with the next block
2131 		 */
2132 		if( ( internal_file->block_data_offset > 0 )
2133 		 && ( internal_file->block_data_size == 0 ) )
2134 		{
2135 			if( memory_set(
2136 			     internal_file->block_data,
2137 			     0,
2138 			     internal_file->block_size ) == NULL )
2139 			{
2140 				libcerror_error_set(
2141 				 error,
2142 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
2143 				 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2144 				 "%s: unable to clear block data.",
2145 				 function );
2146 
2147 				return( -1 );
2148 			}
2149 			read_count = read(
2150 			              internal_file->descriptor,
2151 			              internal_file->block_data,
2152 			              internal_file->block_size );
2153 
2154 			if( read_count != (ssize_t) internal_file->block_size )
2155 			{
2156 				*error_code = (uint32_t) errno;
2157 
2158 				libcerror_system_set_error(
2159 				 error,
2160 				 LIBCERROR_ERROR_DOMAIN_IO,
2161 				 LIBCERROR_IO_ERROR_READ_FAILED,
2162 				 *error_code,
2163 				 "%s: unable to read from file.",
2164 				 function );
2165 
2166 				return( -1 );
2167 			}
2168 			internal_file->block_data_size = (size_t) read_count;
2169 		}
2170 		if( ( internal_file->block_data_offset > 0 )
2171 		 && ( internal_file->block_data_offset < internal_file->block_data_size ) )
2172 		{
2173 			read_size = internal_file->block_data_size - internal_file->block_data_offset;
2174 
2175 			if( read_size > size )
2176 			{
2177 				read_size = size;
2178 			}
2179 			if( memory_copy(
2180 			     buffer,
2181 			     &( internal_file->block_data[ internal_file->block_data_offset ] ),
2182 			     read_size ) == NULL )
2183 			{
2184 				libcerror_error_set(
2185 				 error,
2186 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
2187 				 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2188 				 "%s: unable to copy block data.",
2189 				 function );
2190 
2191 				return( -1 );
2192 			}
2193 			buffer_offset                    += read_size;
2194 			size                             -= read_size;
2195 			internal_file->block_data_offset += read_size;
2196 			internal_file->current_offset    += read_size;
2197 		}
2198 		if( size == 0 )
2199 		{
2200 			return( (ssize_t) buffer_offset );
2201 		}
2202 	}
2203 	read_size = size;
2204 
2205 	if( internal_file->block_size != 0 )
2206 	{
2207 		/* Read block aligned
2208 		 */
2209 		read_size_remainder = read_size % internal_file->block_size;
2210 		read_size          -= read_size_remainder;
2211 	}
2212 	if( read_size > 0 )
2213 	{
2214 		read_count = read(
2215 		              internal_file->descriptor,
2216 		              (void *) &( buffer[ buffer_offset ] ),
2217 		              read_size );
2218 
2219 		if( ( internal_file->block_size == 0 )
2220 		 && ( read_count < 0 ) )
2221 		{
2222 			result = 0;
2223 		}
2224 		else if( ( internal_file->block_size != 0 )
2225 		      && ( read_count != (ssize_t) read_size ) )
2226 		{
2227 			result = 0;
2228 		}
2229 		else
2230 		{
2231 			result = 1;
2232 		}
2233 		if( result == 0 )
2234 		{
2235 			*error_code = (uint32_t) errno;
2236 
2237 			libcerror_system_set_error(
2238 			 error,
2239 			 LIBCERROR_ERROR_DOMAIN_IO,
2240 			 LIBCERROR_IO_ERROR_READ_FAILED,
2241 			 *error_code,
2242 			 "%s: unable to read from file.",
2243 			 function );
2244 
2245 			return( -1 );
2246 		}
2247 		buffer_offset                 += (size_t) read_count;
2248 		internal_file->current_offset += read_count;
2249 	}
2250 	/* Read the non-aligned remainder
2251 	 */
2252 	if( read_size_remainder > 0 )
2253 	{
2254 		if( memory_set(
2255 		     internal_file->block_data,
2256 		     0,
2257 		     internal_file->block_size ) == NULL )
2258 		{
2259 			libcerror_error_set(
2260 			 error,
2261 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2262 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2263 			 "%s: unable to clear block data.",
2264 			 function );
2265 
2266 			return( -1 );
2267 		}
2268 		read_count = read(
2269 		              internal_file->descriptor,
2270 		              internal_file->block_data,
2271 		              internal_file->block_size );
2272 
2273 		if( read_count != (ssize_t) internal_file->block_size )
2274 		{
2275 			*error_code = (uint32_t) errno;
2276 
2277 			libcerror_system_set_error(
2278 			 error,
2279 			 LIBCERROR_ERROR_DOMAIN_IO,
2280 			 LIBCERROR_IO_ERROR_READ_FAILED,
2281 			 *error_code,
2282 			 "%s: unable to read from file.",
2283 			 function );
2284 
2285 			return( -1 );
2286 		}
2287 		internal_file->block_data_offset = 0;
2288 		internal_file->block_data_size   = (size_t) read_count;
2289 
2290 		if( memory_copy(
2291 		     &( buffer[ buffer_offset ] ),
2292 		     internal_file->block_data,
2293 		     read_size_remainder ) == NULL )
2294 		{
2295 			libcerror_error_set(
2296 			 error,
2297 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2298 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2299 			 "%s: unable to copy block data.",
2300 			 function );
2301 
2302 			return( -1 );
2303 		}
2304 		buffer_offset                    += read_size_remainder;
2305 		internal_file->block_data_offset += read_size_remainder;
2306 		internal_file->current_offset    += read_size_remainder;
2307 	}
2308 	return( (ssize_t) buffer_offset );
2309 }
2310 
2311 #else
2312 #error Missing file read function
2313 #endif
2314 
2315 /* Writes a buffer to the file
2316  * Returns the number of bytes written if successful, or -1 on error
2317  */
libcfile_file_write_buffer(libcfile_file_t * file,const uint8_t * buffer,size_t size,libcerror_error_t ** error)2318 ssize_t libcfile_file_write_buffer(
2319          libcfile_file_t *file,
2320          const uint8_t *buffer,
2321          size_t size,
2322          libcerror_error_t **error )
2323 {
2324 	static char *function = "libcfile_file_write_buffer";
2325 	ssize_t write_count   = 0;
2326 	uint32_t error_code   = 0;
2327 
2328 	write_count = libcfile_file_write_buffer_with_error_code(
2329 	               file,
2330 	               buffer,
2331 	               size,
2332 	               &error_code,
2333 	               error );
2334 
2335 	if( write_count == -1 )
2336 	{
2337 		libcerror_error_set(
2338 		 error,
2339 		 LIBCERROR_ERROR_DOMAIN_IO,
2340 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2341 		 "%s: unable to write to file.",
2342 		 function );
2343 
2344 		return( -1 );
2345 	}
2346 	return( write_count );
2347 }
2348 
2349 #if defined( WINAPI )
2350 
2351 /* Writes a buffer to the file
2352  * This function uses the WINAPI function for Windows XP (0x0501) or later
2353  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
2354  * Returns the number of bytes written if successful, or -1 on error
2355  */
libcfile_file_write_buffer_with_error_code(libcfile_file_t * file,const uint8_t * buffer,size_t size,uint32_t * error_code,libcerror_error_t ** error)2356 ssize_t libcfile_file_write_buffer_with_error_code(
2357          libcfile_file_t *file,
2358          const uint8_t *buffer,
2359          size_t size,
2360          uint32_t *error_code,
2361          libcerror_error_t **error )
2362 {
2363 	libcfile_internal_file_t *internal_file = NULL;
2364 	static char *function                   = "libcfile_file_write_buffer_with_error_code";
2365 	ssize_t write_count                     = 0;
2366 	BOOL result                             = FALSE;
2367 
2368 	if( file == NULL )
2369 	{
2370 		libcerror_error_set(
2371 		 error,
2372 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2373 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2374 		 "%s: invalid file.",
2375 		 function );
2376 
2377 		return( -1 );
2378 	}
2379 	internal_file = (libcfile_internal_file_t *) file;
2380 
2381 	if( internal_file->handle == INVALID_HANDLE_VALUE )
2382 	{
2383 		libcerror_error_set(
2384 		 error,
2385 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2386 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2387 		 "%s: invalid file - missing handle.",
2388 		 function );
2389 
2390 		return( -1 );
2391 	}
2392 	if( buffer == NULL )
2393 	{
2394 		libcerror_error_set(
2395 		 error,
2396 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2397 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2398 		 "%s: invalid buffer.",
2399 		 function );
2400 
2401 		return( -1 );
2402 	}
2403 #if ( UINT32_MAX < SSIZE_MAX )
2404 	if( size > (size_t) UINT32_MAX )
2405 #else
2406 	if( size > (size_t) SSIZE_MAX )
2407 #endif
2408 	{
2409 		libcerror_error_set(
2410 		 error,
2411 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2412 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2413 		 "%s: invalid size value exceeds maximum.",
2414 		 function );
2415 
2416 		return( -1 );
2417 	}
2418 	if( error_code == NULL )
2419 	{
2420 		libcerror_error_set(
2421 		 error,
2422 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2423 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2424 		 "%s: invalid error code.",
2425 		 function );
2426 
2427 		return( -1 );
2428 	}
2429 #if ( WINVER <= 0x0500 )
2430 	result = libcfile_WriteFile(
2431 	          internal_file->handle,
2432 	          (VOID *) buffer,
2433 	          (DWORD) size,
2434 	          (DWORD *) &write_count,
2435 	          NULL );
2436 #else
2437 	result = WriteFile(
2438 	          internal_file->handle,
2439 	          (VOID *) buffer,
2440 	          (DWORD) size,
2441 	          (DWORD *) &write_count,
2442 	          NULL );
2443 #endif
2444 	if( result == 0 )
2445 	{
2446 		*error_code = (uint32_t) GetLastError();
2447 
2448 		libcerror_system_set_error(
2449 		 error,
2450 		 LIBCERROR_ERROR_DOMAIN_IO,
2451 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2452 		 *error_code,
2453 		 "%s: unable to write to file.",
2454 		 function );
2455 
2456 		return( -1 );
2457 	}
2458 	if( write_count < 0 )
2459 	{
2460 		libcerror_error_set(
2461 		 error,
2462 		 LIBCERROR_ERROR_DOMAIN_IO,
2463 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2464 		 "%s: invalid write count: %" PRIzd " returned.",
2465 		 function,
2466 		 write_count );
2467 
2468 		return( -1 );
2469 	}
2470 	internal_file->current_offset += write_count;
2471 
2472 	if( (size64_t) internal_file->current_offset > internal_file->size )
2473 	{
2474 		internal_file->size = (size64_t) internal_file->current_offset;
2475 	}
2476 	return( write_count );
2477 }
2478 
2479 #elif defined( HAVE_WRITE )
2480 
2481 /* Writes a buffer to the file
2482  * This function uses the POSIX write function or equivalent
2483  * Returns the number of bytes written if successful, or -1 on error
2484  */
libcfile_file_write_buffer_with_error_code(libcfile_file_t * file,const uint8_t * buffer,size_t size,uint32_t * error_code,libcerror_error_t ** error)2485 ssize_t libcfile_file_write_buffer_with_error_code(
2486          libcfile_file_t *file,
2487          const uint8_t *buffer,
2488          size_t size,
2489          uint32_t *error_code,
2490          libcerror_error_t **error )
2491 {
2492 	libcfile_internal_file_t *internal_file = NULL;
2493 	static char *function                   = "libcfile_file_write_buffer_with_error_code";
2494 	ssize_t write_count                     = 0;
2495 
2496 	if( file == NULL )
2497 	{
2498 		libcerror_error_set(
2499 		 error,
2500 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2501 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2502 		 "%s: invalid file.",
2503 		 function );
2504 
2505 		return( -1 );
2506 	}
2507 	internal_file = (libcfile_internal_file_t *) file;
2508 
2509 	if( internal_file->descriptor == -1 )
2510 	{
2511 		libcerror_error_set(
2512 		 error,
2513 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2514 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2515 		 "%s: invalid file - missing descriptor.",
2516 		 function );
2517 
2518 		return( -1 );
2519 	}
2520 	if( buffer == NULL )
2521 	{
2522 		libcerror_error_set(
2523 		 error,
2524 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2525 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2526 		 "%s: invalid buffer.",
2527 		 function );
2528 
2529 		return( -1 );
2530 	}
2531 	if( size > (size_t) SSIZE_MAX )
2532 	{
2533 		libcerror_error_set(
2534 		 error,
2535 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2536 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2537 		 "%s: invalid size value exceeds maximum.",
2538 		 function );
2539 
2540 		return( -1 );
2541 	}
2542 	if( error_code == NULL )
2543 	{
2544 		libcerror_error_set(
2545 		 error,
2546 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2547 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2548 		 "%s: invalid error code.",
2549 		 function );
2550 
2551 		return( -1 );
2552 	}
2553 	write_count = write(
2554 	               internal_file->descriptor,
2555 	               (void *) buffer,
2556 	               size );
2557 
2558 	if( write_count < 0 )
2559 	{
2560 		*error_code = (uint32_t) errno;
2561 
2562 		libcerror_system_set_error(
2563 		 error,
2564 		 LIBCERROR_ERROR_DOMAIN_IO,
2565 		 LIBCERROR_IO_ERROR_WRITE_FAILED,
2566 		 *error_code,
2567 		 "%s: unable to write to file.",
2568 		 function );
2569 
2570 		return( -1 );
2571 	}
2572 	internal_file->current_offset += write_count;
2573 
2574 	if( (size64_t) internal_file->current_offset > internal_file->size )
2575 	{
2576 		internal_file->size = (size64_t) internal_file->current_offset;
2577 	}
2578 	return( write_count );
2579 }
2580 
2581 #else
2582 #error Missing file write function
2583 #endif
2584 
2585 #if defined( WINAPI )
2586 
2587 /* Seeks a certain offset within the file
2588  * This function uses the WINAPI function for Windows XP (0x0501) or later
2589  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
2590  * Returns the offset if the seek is successful or -1 on error
2591  */
libcfile_file_seek_offset(libcfile_file_t * file,off64_t offset,int whence,libcerror_error_t ** error)2592 off64_t libcfile_file_seek_offset(
2593          libcfile_file_t *file,
2594          off64_t offset,
2595          int whence,
2596          libcerror_error_t **error )
2597 {
2598 	libcfile_internal_file_t *internal_file = NULL;
2599 	static char *function                   = "libcfile_file_seek_offset";
2600 	off64_t offset_remainder                = 0;
2601 	LARGE_INTEGER large_integer_offset      = LIBCFILE_LARGE_INTEGER_ZERO;
2602 	DWORD error_code                        = 0;
2603 	DWORD move_method                       = 0;
2604 
2605 	if( file == NULL )
2606 	{
2607 		libcerror_error_set(
2608 		 error,
2609 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2610 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2611 		 "%s: invalid file.",
2612 		 function );
2613 
2614 		return( -1 );
2615 	}
2616 	internal_file = (libcfile_internal_file_t *) file;
2617 
2618 	if( internal_file->handle == INVALID_HANDLE_VALUE )
2619 	{
2620 		libcerror_error_set(
2621 		 error,
2622 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2623 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2624 		 "%s: invalid file - missing handle.",
2625 		 function );
2626 
2627 		return( -1 );
2628 	}
2629 	if( offset > (off64_t) INT64_MAX )
2630 	{
2631 		libcerror_error_set(
2632 		 error,
2633 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2634 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2635 		 "%s: invalid offset value exceeds maximum.",
2636 		 function );
2637 
2638 		return( -1 );
2639 	}
2640 	if( ( whence != SEEK_CUR )
2641 	 && ( whence != SEEK_END )
2642 	 && ( whence != SEEK_SET ) )
2643 	{
2644 		libcerror_error_set(
2645 		 error,
2646 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2647 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2648 		 "%s: unsupported whence.",
2649 		 function );
2650 
2651 		return( -1 );
2652 	}
2653 	if( internal_file->block_size != 0 )
2654 	{
2655 		if( whence == SEEK_CUR )
2656 		{
2657 			offset += internal_file->current_offset;
2658 		}
2659 		else if( whence == SEEK_END )
2660 		{
2661 			offset += internal_file->size;
2662 		}
2663 		whence           = SEEK_SET;
2664 		offset_remainder = offset % internal_file->block_size;
2665 		offset          -= offset_remainder;
2666 	}
2667 	if( whence == SEEK_SET )
2668 	{
2669 		move_method = FILE_BEGIN;
2670 	}
2671 	else if( whence == SEEK_CUR )
2672 	{
2673 		move_method = FILE_CURRENT;
2674 	}
2675 	else if( whence == SEEK_END )
2676 	{
2677 		move_method = FILE_END;
2678 	}
2679 	/* SetFilePointerEx cannot be used in combination with FILE_FLAG_OVERLAPPED.
2680 	 */
2681 	if( internal_file->use_asynchronous_io == 0 )
2682 	{
2683 #if defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520
2684 		large_integer_offset.QuadPart = (LONGLONG) offset;
2685 #else
2686 		large_integer_offset.LowPart  = (DWORD) ( 0x0ffffffffUL & offset );
2687 		large_integer_offset.HighPart = (LONG) ( offset >> 32 );
2688 #endif
2689 
2690 #if ( WINVER <= 0x0500 )
2691 		if( libcfile_SetFilePointerEx(
2692 		     internal_file->handle,
2693 		     large_integer_offset,
2694 		     &large_integer_offset,
2695 		     move_method ) == 0 )
2696 #else
2697 		if( SetFilePointerEx(
2698 		     internal_file->handle,
2699 		     large_integer_offset,
2700 		     &large_integer_offset,
2701 		     move_method ) == 0 )
2702 #endif
2703 		{
2704 			error_code = GetLastError();
2705 
2706 			libcerror_system_set_error(
2707 			 error,
2708 			 LIBCERROR_ERROR_DOMAIN_IO,
2709 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
2710 			 error_code,
2711 			 "%s: unable to seek offset in file.",
2712 			 function );
2713 
2714 			return( -1 );
2715 		}
2716 #if defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520
2717 		offset = (off64_t) large_integer_offset.QuadPart;
2718 #else
2719 		offset = ( (off64_t) large_integer_offset.HighPart << 32 ) + large_integer_offset.LowPart;
2720 #endif
2721 
2722 		if( offset < 0 )
2723 		{
2724 			libcerror_error_set(
2725 			 error,
2726 			 LIBCERROR_ERROR_DOMAIN_IO,
2727 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
2728 			 "%s: invalid offset: %" PRIi64 " returned.",
2729 			 function,
2730 			 offset );
2731 
2732 			return( -1 );
2733 		}
2734 	}
2735 	internal_file->current_offset = offset;
2736 
2737 	if( internal_file->block_size != 0 )
2738 	{
2739 		internal_file->current_offset   += offset_remainder;
2740 		internal_file->block_data_offset = (size_t) offset_remainder;
2741 		internal_file->block_data_size   = 0;
2742 	}
2743 	return( internal_file->current_offset );
2744 }
2745 
2746 #elif defined( HAVE_LSEEK )
2747 
2748 /* Seeks a certain offset within the file
2749  * This function uses the POSIX lseek function or equivalent
2750  * Returns the offset if the seek is successful or -1 on error
2751  */
libcfile_file_seek_offset(libcfile_file_t * file,off64_t offset,int whence,libcerror_error_t ** error)2752 off64_t libcfile_file_seek_offset(
2753          libcfile_file_t *file,
2754          off64_t offset,
2755          int whence,
2756          libcerror_error_t **error )
2757 {
2758 	libcfile_internal_file_t *internal_file = NULL;
2759 	static char *function                   = "libcfile_file_seek_offset";
2760 	off64_t offset_remainder                = 0;
2761 
2762 	if( file == NULL )
2763 	{
2764 		libcerror_error_set(
2765 		 error,
2766 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2767 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2768 		 "%s: invalid file.",
2769 		 function );
2770 
2771 		return( -1 );
2772 	}
2773 	internal_file = (libcfile_internal_file_t *) file;
2774 
2775 	if( internal_file->descriptor == -1 )
2776 	{
2777 		libcerror_error_set(
2778 		 error,
2779 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2780 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2781 		 "%s: invalid file - missing descriptor.",
2782 		 function );
2783 
2784 		return( -1 );
2785 	}
2786 	if( offset > (off64_t) INT64_MAX )
2787 	{
2788 		libcerror_error_set(
2789 		 error,
2790 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2791 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2792 		 "%s: invalid offset value exceeds maximum.",
2793 		 function );
2794 
2795 		return( -1 );
2796 	}
2797 	if( ( whence != SEEK_CUR )
2798 	 && ( whence != SEEK_END )
2799 	 && ( whence != SEEK_SET ) )
2800 	{
2801 		libcerror_error_set(
2802 		 error,
2803 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2804 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
2805 		 "%s: unsupported whence.",
2806 		 function );
2807 
2808 		return( -1 );
2809 	}
2810 	if( internal_file->block_size != 0 )
2811 	{
2812 		if( whence == SEEK_CUR )
2813 		{
2814 			offset += internal_file->current_offset;
2815 		}
2816 		else if( whence == SEEK_END )
2817 		{
2818 			offset += internal_file->size;
2819 		}
2820 		whence           = SEEK_SET;
2821 		offset_remainder = offset % internal_file->block_size;
2822 		offset          -= offset_remainder;
2823 	}
2824 	offset = lseek(
2825 	          internal_file->descriptor,
2826 	          (off_t) offset,
2827 	          whence );
2828 
2829 	if( offset < 0 )
2830 	{
2831 		libcerror_system_set_error(
2832 		 error,
2833 		 LIBCERROR_ERROR_DOMAIN_IO,
2834 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2835 		 errno,
2836 		 "%s: unable to seek offset in file.",
2837 		 function );
2838 
2839 		return( -1 );
2840 	}
2841 	internal_file->current_offset = offset;
2842 
2843 	if( internal_file->block_size != 0 )
2844 	{
2845 		internal_file->current_offset   += offset_remainder;
2846 		internal_file->block_data_offset = (size_t) offset_remainder;
2847 		internal_file->block_data_size   = 0;
2848 	}
2849 	return( internal_file->current_offset );
2850 }
2851 
2852 #else
2853 #error Missing file lseek function
2854 #endif
2855 
2856 #if defined( WINAPI )
2857 
2858 /* Resizes the file
2859  * This function uses the WINAPI function for Windows XP (0x0501) or later
2860  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
2861  * Returns 1 if successful or -1 on error
2862  */
libcfile_file_resize(libcfile_file_t * file,size64_t size,libcerror_error_t ** error)2863 int libcfile_file_resize(
2864      libcfile_file_t *file,
2865      size64_t size,
2866      libcerror_error_t **error )
2867 {
2868 	libcfile_internal_file_t *internal_file = NULL;
2869 	static char *function                   = "libcfile_file_resize";
2870 	off64_t offset                          = 0;
2871 	LARGE_INTEGER large_integer_offset      = LIBCFILE_LARGE_INTEGER_ZERO;
2872 	DWORD error_code                        = 0;
2873 
2874 	if( file == NULL )
2875 	{
2876 		libcerror_error_set(
2877 		 error,
2878 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2879 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2880 		 "%s: invalid file.",
2881 		 function );
2882 
2883 		return( -1 );
2884 	}
2885 	internal_file = (libcfile_internal_file_t *) file;
2886 
2887 	if( internal_file->handle == INVALID_HANDLE_VALUE )
2888 	{
2889 		libcerror_error_set(
2890 		 error,
2891 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2892 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2893 		 "%s: invalid file - missing handle.",
2894 		 function );
2895 
2896 		return( -1 );
2897 	}
2898 	if( size > (size64_t) INT64_MAX )
2899 	{
2900 		libcerror_error_set(
2901 		 error,
2902 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2903 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2904 		 "%s: invalid size value exceeds maximum.",
2905 		 function );
2906 
2907 		return( -1 );
2908 	}
2909 #if defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520
2910 	large_integer_offset.QuadPart = (LONGLONG) size;
2911 #else
2912 	large_integer_offset.LowPart  = (DWORD) ( 0x0ffffffffUL & size );
2913 	large_integer_offset.HighPart = (LONG) ( size >> 32 );
2914 #endif
2915 
2916 #if ( WINVER <= 0x0500 )
2917 	if( libcfile_SetFilePointerEx(
2918 	     internal_file->handle,
2919 	     large_integer_offset,
2920 	     &large_integer_offset,
2921 	     FILE_BEGIN ) == 0 )
2922 #else
2923 	if( SetFilePointerEx(
2924 	     internal_file->handle,
2925 	     large_integer_offset,
2926 	     &large_integer_offset,
2927 	     FILE_BEGIN ) == 0 )
2928 #endif
2929 	{
2930 		error_code = GetLastError();
2931 
2932 		libcerror_system_set_error(
2933 		 error,
2934 		 LIBCERROR_ERROR_DOMAIN_IO,
2935 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2936 		 error_code,
2937 		 "%s: unable to seek offset in file.",
2938 		 function );
2939 
2940 		return( -1 );
2941 	}
2942 #if defined( __BORLANDC__ ) && __BORLANDC__ <= 0x0520
2943 	offset = (off64_t) large_integer_offset.QuadPart;
2944 #else
2945 	offset = ( (off64_t) large_integer_offset.HighPart << 32 ) + large_integer_offset.LowPart;
2946 #endif
2947 
2948 	if( offset < 0 )
2949 	{
2950 		libcerror_error_set(
2951 		 error,
2952 		 LIBCERROR_ERROR_DOMAIN_IO,
2953 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2954 		 "%s: invalid offset: %" PRIi64 " returned.",
2955 		 function,
2956 		 offset );
2957 
2958 		return( -1 );
2959 	}
2960 	internal_file->current_offset = offset;
2961 
2962 #if ( WINVER <= 0x0500 )
2963 	if( libcfile_SetEndOfFile(
2964 	     internal_file->handle ) == 0 )
2965 #else
2966 	if( SetEndOfFile(
2967 	     internal_file->handle ) == 0 )
2968 #endif
2969 	{
2970 		error_code = GetLastError();
2971 
2972 		libcerror_system_set_error(
2973 		 error,
2974 		 LIBCERROR_ERROR_DOMAIN_IO,
2975 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
2976 		 error_code,
2977 		 "%s: unable to resize file.",
2978 		 function );
2979 
2980 		return( -1 );
2981 	}
2982 	return( 1 );
2983 }
2984 
2985 #elif defined( HAVE_FTRUNCATE )
2986 
2987 /* Resizes the file
2988  * This function uses the POSIX truncate function or equivalent
2989  * Returns 1 if successful or -1 on error
2990  */
libcfile_file_resize(libcfile_file_t * file,size64_t size,libcerror_error_t ** error)2991 int libcfile_file_resize(
2992      libcfile_file_t *file,
2993      size64_t size,
2994      libcerror_error_t **error )
2995 {
2996 	libcfile_internal_file_t *internal_file = NULL;
2997 	static char *function                   = "libcfile_file_resize";
2998 	off_t offset                            = 0;
2999 
3000 	if( file == NULL )
3001 	{
3002 		libcerror_error_set(
3003 		 error,
3004 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3005 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3006 		 "%s: invalid file.",
3007 		 function );
3008 
3009 		return( -1 );
3010 	}
3011 	internal_file = (libcfile_internal_file_t *) file;
3012 
3013 	if( internal_file->descriptor == -1 )
3014 	{
3015 		libcerror_error_set(
3016 		 error,
3017 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3018 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3019 		 "%s: invalid file - missing descriptor.",
3020 		 function );
3021 
3022 		return( -1 );
3023 	}
3024 #if SIZEOF_OFF_T >= 8
3025 	if( size > (size64_t) INT64_MAX )
3026 #else
3027 	if( size > (size64_t) INT32_MAX )
3028 #endif
3029 	{
3030 		libcerror_error_set(
3031 		 error,
3032 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3033 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
3034 		 "%s: invalid size value exceeds maximum.",
3035 		 function );
3036 
3037 		return( -1 );
3038 	}
3039 	if( ftruncate(
3040 	     internal_file->descriptor,
3041 	     (off_t) size ) != 0 )
3042 	{
3043 		libcerror_system_set_error(
3044 		 error,
3045 		 LIBCERROR_ERROR_DOMAIN_IO,
3046 		 LIBCERROR_IO_ERROR_GENERIC,
3047 		 errno,
3048 		 "%s: unable to resize file.",
3049 		 function );
3050 
3051 		return( -1 );
3052 	}
3053 	offset = lseek(
3054 	          internal_file->descriptor,
3055 	          0,
3056 	          SEEK_CUR );
3057 
3058 	if( offset < 0 )
3059 	{
3060 		libcerror_system_set_error(
3061 		 error,
3062 		 LIBCERROR_ERROR_DOMAIN_IO,
3063 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
3064 		 errno,
3065 		 "%s: unable to seek offset in file.",
3066 		 function );
3067 
3068 		return( -1 );
3069 	}
3070 	internal_file->current_offset = (off64_t) offset;
3071 
3072 	return( 1 );
3073 }
3074 
3075 #else
3076 #error Missing file truncate function
3077 #endif
3078 
3079 /* Checks if the file is open
3080  * Returns 1 if open, 0 if not or -1 on error
3081  */
libcfile_file_is_open(libcfile_file_t * file,libcerror_error_t ** error)3082 int libcfile_file_is_open(
3083      libcfile_file_t *file,
3084      libcerror_error_t **error )
3085 {
3086 	libcfile_internal_file_t *internal_file = NULL;
3087 	static char *function                   = "libcfile_file_is_open";
3088 
3089 	if( file == NULL )
3090 	{
3091 		libcerror_error_set(
3092 		 error,
3093 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3094 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3095 		 "%s: invalid file.",
3096 		 function );
3097 
3098 		return( -1 );
3099 	}
3100 	internal_file = (libcfile_internal_file_t *) file;
3101 
3102 #if defined( WINAPI )
3103 	if( internal_file->handle == INVALID_HANDLE_VALUE )
3104 #else
3105 	if( internal_file->descriptor == -1 )
3106 #endif
3107 	{
3108 		return( 0 );
3109 	}
3110 	return( 1 );
3111 }
3112 
3113 /* Retrieves the current offset in the file
3114  * Returns 1 if successful or -1 on error
3115  */
libcfile_file_get_offset(libcfile_file_t * file,off64_t * offset,libcerror_error_t ** error)3116 int libcfile_file_get_offset(
3117      libcfile_file_t *file,
3118      off64_t *offset,
3119      libcerror_error_t **error )
3120 {
3121 	libcfile_internal_file_t *internal_file = NULL;
3122 	static char *function                   = "libcfile_file_get_offset";
3123 
3124 	if( file == NULL )
3125 	{
3126 		libcerror_error_set(
3127 		 error,
3128 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3129 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3130 		 "%s: invalid file.",
3131 		 function );
3132 
3133 		return( -1 );
3134 	}
3135 	internal_file = (libcfile_internal_file_t *) file;
3136 
3137 #if defined( WINAPI )
3138 	if( internal_file->handle == INVALID_HANDLE_VALUE )
3139 	{
3140 		libcerror_error_set(
3141 		 error,
3142 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3143 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3144 		 "%s: invalid file - missing handle.",
3145 		 function );
3146 
3147 		return( -1 );
3148 	}
3149 #else
3150 	if( internal_file->descriptor == -1 )
3151 	{
3152 		libcerror_error_set(
3153 		 error,
3154 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3155 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3156 		 "%s: invalid file - missing descriptor.",
3157 		 function );
3158 
3159 		return( -1 );
3160 	}
3161 #endif
3162 	if( offset == NULL )
3163 	{
3164 		libcerror_error_set(
3165 		 error,
3166 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3167 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3168 		 "%s: invalid offset.",
3169 		 function );
3170 
3171 		return( -1 );
3172 	}
3173 	*offset = internal_file->current_offset;
3174 
3175 	return( 1 );
3176 }
3177 
3178 #if defined( WINAPI )
3179 
3180 #if !defined( IOCTL_DISK_GET_LENGTH_INFO )
3181 #define IOCTL_DISK_GET_LENGTH_INFO \
3182 	CTL_CODE( IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS )
3183 
3184 typedef struct
3185 {
3186 	LARGE_INTEGER Length;
3187 }
3188 GET_LENGTH_INFORMATION;
3189 
3190 #endif /* !defined( IOCTL_DISK_GET_LENGTH_INFO ) */
3191 
3192 /* Retrieves the size of the file
3193  * This function uses the WINAPI function for Windows XP (0x0501) or later
3194  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
3195  * Returns 1 if successful or -1 on error
3196  */
libcfile_internal_file_get_size(libcfile_internal_file_t * internal_file,size64_t * size,libcerror_error_t ** error)3197 int libcfile_internal_file_get_size(
3198      libcfile_internal_file_t *internal_file,
3199      size64_t *size,
3200      libcerror_error_t **error )
3201 {
3202 	DISK_GEOMETRY disk_geometry;
3203 	GET_LENGTH_INFORMATION length_information;
3204 
3205 	static char *function            = "libcfile_internal_file_get_size";
3206 	LARGE_INTEGER large_integer_size = LIBCFILE_LARGE_INTEGER_ZERO;
3207 	size_t read_count                = 0;
3208 	uint32_t error_code              = 0;
3209 	int result                       = 0;
3210 
3211 	if( internal_file == NULL )
3212 	{
3213 		libcerror_error_set(
3214 		 error,
3215 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3216 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3217 		 "%s: invalid file.",
3218 		 function );
3219 
3220 		return( -1 );
3221 	}
3222 	if( internal_file->handle == INVALID_HANDLE_VALUE )
3223 	{
3224 		libcerror_error_set(
3225 		 error,
3226 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3227 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3228 		 "%s: invalid file - missing handle.",
3229 		 function );
3230 
3231 		return( -1 );
3232 	}
3233 	if( size == NULL )
3234 	{
3235 		libcerror_error_set(
3236 		 error,
3237 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3238 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3239 		 "%s: invalid size.",
3240 		 function );
3241 
3242 		return( -1 );
3243 	}
3244 	result = libcfile_file_is_device(
3245 	          (libcfile_file_t *) internal_file,
3246 	          error );
3247 
3248 	if( result == -1 )
3249 	{
3250 		libcerror_error_set(
3251 		 error,
3252 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3253 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3254 		 "%s: unable to determine if file is a device.",
3255 		 function );
3256 
3257 		return( -1 );
3258 	}
3259 	else if( result != 0 )
3260 	{
3261 		read_count = libcfile_internal_file_io_control_read_with_error_code(
3262 		              internal_file,
3263 		              IOCTL_DISK_GET_LENGTH_INFO,
3264 		              NULL,
3265 		              0,
3266 		              (uint8_t *) &length_information,
3267 		              sizeof( GET_LENGTH_INFORMATION ),
3268 		              &error_code,
3269 		              error );
3270 
3271 		if( read_count == -1 )
3272 		{
3273 			libcerror_error_set(
3274 			 error,
3275 			 LIBCERROR_ERROR_DOMAIN_IO,
3276 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3277 			 "%s: unable to query device for: IOCTL_DISK_GET_LENGTH_INFO.",
3278 			 function );
3279 
3280 #if defined( HAVE_DEBUG_OUTPUT )
3281 			if( libcnotify_verbose != 0 )
3282 			{
3283 				if( ( error != NULL )
3284 				 && ( *error != NULL ) )
3285 				{
3286 					libcnotify_print_error_backtrace(
3287 					 *error );
3288 				}
3289 			}
3290 #endif
3291 			libcerror_error_free(
3292 			 error );
3293 
3294 			if( error_code == ERROR_NOT_SUPPORTED )
3295 			{
3296 				/* A floppy device does not support IOCTL_DISK_GET_LENGTH_INFO
3297 				 */
3298 				read_count = libcfile_internal_file_io_control_read_with_error_code(
3299 				              internal_file,
3300 				              IOCTL_DISK_GET_DRIVE_GEOMETRY,
3301 				              NULL,
3302 				              0,
3303 				              (uint8_t *) &disk_geometry,
3304 				              sizeof( DISK_GEOMETRY ),
3305 				              &error_code,
3306 				              error );
3307 
3308 				if( read_count == -1 )
3309 				{
3310 					libcerror_error_set(
3311 					 error,
3312 					 LIBCERROR_ERROR_DOMAIN_IO,
3313 					 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3314 					 "%s: unable to query device for: IOCTL_DISK_GET_DRIVE_GEOMETRY.",
3315 					 function );
3316 
3317 #if defined( HAVE_DEBUG_OUTPUT )
3318 					if( libcnotify_verbose != 0 )
3319 					{
3320 						if( ( error != NULL )
3321 						 && ( *error != NULL ) )
3322 						{
3323 							libcnotify_print_error_backtrace(
3324 							 *error );
3325 						}
3326 					}
3327 #endif
3328 					libcerror_error_free(
3329 					 error );
3330 				}
3331 				else
3332 				{
3333 					*size  = disk_geometry.Cylinders.QuadPart;
3334 					*size *= disk_geometry.TracksPerCylinder;
3335 					*size *= disk_geometry.SectorsPerTrack;
3336 					*size *= disk_geometry.BytesPerSector;
3337 				}
3338 			}
3339 		}
3340 		else
3341 		{
3342 			*size  = (size64_t) length_information.Length.HighPart << 32;
3343 			*size += (uint32_t) length_information.Length.LowPart;
3344 		}
3345 	}
3346 	else
3347 	{
3348 #if ( WINVER <= 0x0500 )
3349 		if( libcfile_GetFileSizeEx(
3350 		     internal_file->handle,
3351 		     &large_integer_size ) == 0 )
3352 #else
3353 		if( GetFileSizeEx(
3354 		     internal_file->handle,
3355 		     &large_integer_size ) == 0 )
3356 #endif
3357 		{
3358 			libcerror_error_set(
3359 			 error,
3360 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3361 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3362 			 "%s: unable to retrieve file size.",
3363 			 function );
3364 
3365 			return( -1 );
3366 		}
3367 #if defined( __BORLANDC__ ) && __BORLANDC__ <= 0x520
3368 		*size = (size64_t) large_integer_size.QuadPart;
3369 #else
3370 		*size  = (size64_t) large_integer_size.HighPart << 32;
3371 		*size += (uint32_t) large_integer_size.LowPart;
3372 #endif
3373 	}
3374 	return( 1 );
3375 }
3376 
3377 #elif defined( HAVE_FSTAT )
3378 
3379 /* Retrieves the size of the file
3380  * This function uses the POSIX fstat function or equivalent
3381  * Returns 1 if successful or -1 on error
3382  */
libcfile_internal_file_get_size(libcfile_internal_file_t * internal_file,size64_t * size,libcerror_error_t ** error)3383 int libcfile_internal_file_get_size(
3384      libcfile_internal_file_t *internal_file,
3385      size64_t *size,
3386      libcerror_error_t **error )
3387 {
3388 	struct stat file_statistics;
3389 
3390 	static char *function     = "libcfile_internal_file_get_size";
3391 	size64_t safe_size        = 0;
3392 	ssize_t read_count        = 0;
3393 	off64_t current_offset    = 0;
3394 	off64_t offset            = 0;
3395 
3396 #if defined( BLKGETSIZE64 ) || defined( DIOCGMEDIASIZE ) || defined( DIOCGDINFO ) || ( defined( DKIOCGETBLOCKCOUNT ) && defined( DKIOCGETBLOCKSIZE ) )
3397 	uint32_t error_code       = 0;
3398 #endif
3399 
3400 #if !defined( DIOCGMEDIASIZE ) && defined( DIOCGDINFO )
3401 	struct disklabel disk_label;
3402 #endif
3403 #if defined( DKIOCGETBLOCKCOUNT ) && defined( DKIOCGETBLOCKSIZE )
3404 	uint64_t block_count      = 0;
3405 	uint32_t bytes_per_sector = 0;
3406 #endif
3407 
3408 	if( internal_file == NULL )
3409 	{
3410 		libcerror_error_set(
3411 		 error,
3412 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3413 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3414 		 "%s: invalid file.",
3415 		 function );
3416 
3417 		return( -1 );
3418 	}
3419 	if( internal_file->descriptor == -1 )
3420 	{
3421 		libcerror_error_set(
3422 		 error,
3423 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3424 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3425 		 "%s: invalid file - missing descriptor.",
3426 		 function );
3427 
3428 		return( -1 );
3429 	}
3430 	if( size == NULL )
3431 	{
3432 		libcerror_error_set(
3433 		 error,
3434 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3435 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3436 		 "%s: invalid size.",
3437 		 function );
3438 
3439 		return( -1 );
3440 	}
3441 	if( memory_set(
3442 	     &file_statistics,
3443 	     0,
3444 	     sizeof( struct stat ) ) == NULL )
3445 	{
3446 		libcerror_error_set(
3447 		 error,
3448 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
3449 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
3450 		 "%s: unable to clear file statistics.",
3451 		 function );
3452 
3453 		return( -1 );
3454 	}
3455 	if( fstat(
3456 	     internal_file->descriptor,
3457 	     &file_statistics ) != 0 )
3458 	{
3459 		libcerror_error_set(
3460 		 error,
3461 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3462 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3463 		 "%s: unable to retrieve file statistics.",
3464 		 function );
3465 
3466 		return( -1 );
3467 	}
3468 	if( S_ISBLK( file_statistics.st_mode )
3469 	 || S_ISCHR( file_statistics.st_mode ) )
3470 	{
3471 #if defined( BLKGETSIZE64 )
3472 		read_count = libcfile_internal_file_io_control_read_with_error_code(
3473 		              internal_file,
3474 		              (uint32_t) BLKGETSIZE64,
3475 		              NULL,
3476 		              0,
3477 		              (uint8_t *) &safe_size,
3478 		              8,
3479 		              &error_code,
3480 		              error );
3481 
3482 		if( read_count == -1 )
3483 		{
3484 			libcerror_error_set(
3485 			 error,
3486 			 LIBCERROR_ERROR_DOMAIN_IO,
3487 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3488 			 "%s: unable to query device for: BLKGETSIZE64.",
3489 			 function );
3490 
3491 #if defined( HAVE_DEBUG_OUTPUT )
3492 			if( libcnotify_verbose != 0 )
3493 			{
3494 				if( ( error != NULL )
3495 				 && ( *error != NULL ) )
3496 				{
3497 					libcnotify_print_error_backtrace(
3498 					 *error );
3499 				}
3500 			}
3501 #endif
3502 			libcerror_error_free(
3503 			 error );
3504 		}
3505 #elif defined( DIOCGMEDIASIZE )
3506 		read_count = libcfile_internal_file_io_control_read_with_error_code(
3507 		              internal_file,
3508 		              (uint32_t) DIOCGMEDIASIZE,
3509 		              NULL,
3510 		              0,
3511 		              (uint8_t *) &safe_size,
3512 		              8,
3513 		              &error_code,
3514 		              error );
3515 
3516 		if( read_count == -1 )
3517 		{
3518 			libcerror_error_set(
3519 			 error,
3520 			 LIBCERROR_ERROR_DOMAIN_IO,
3521 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3522 			 "%s: unable to query device for: DIOCGMEDIASIZE.",
3523 			 function );
3524 
3525 #if defined( HAVE_DEBUG_OUTPUT )
3526 			if( libcnotify_verbose != 0 )
3527 			{
3528 				if( ( error != NULL )
3529 				 && ( *error != NULL ) )
3530 				{
3531 					libcnotify_print_error_backtrace(
3532 					 *error );
3533 				}
3534 			}
3535 #endif
3536 			libcerror_error_free(
3537 			 error );
3538 		}
3539 #elif defined( DIOCGDINFO )
3540 		read_count = libcfile_internal_file_io_control_read_with_error_code(
3541 		              internal_file,
3542 		              (uint32_t) DIOCGDINFO,
3543 		              NULL,
3544 		              0,
3545 		              (uint8_t *) &disk_label,
3546 		              sizeof( struct disklabel ),
3547 		              &error_code,
3548 		              error );
3549 
3550 		if( read_count == -1 )
3551 		{
3552 			libcerror_error_set(
3553 			 error,
3554 			 LIBCERROR_ERROR_DOMAIN_IO,
3555 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3556 			 "%s: unable to query device for: DIOCGDINFO.",
3557 			 function );
3558 
3559 #if defined( HAVE_DEBUG_OUTPUT )
3560 			if( libcnotify_verbose != 0 )
3561 			{
3562 				if( ( error != NULL )
3563 				 && ( *error != NULL ) )
3564 				{
3565 					libcnotify_print_error_backtrace(
3566 					 *error );
3567 				}
3568 			}
3569 #endif
3570 			libcerror_error_free(
3571 			 error );
3572 		}
3573 		else
3574 		{
3575 			safe_size = disk_label.d_secperunit * disk_label.d_secsize;
3576 		}
3577 #elif defined( DKIOCGETBLOCKCOUNT ) && defined( DKIOCGETBLOCKSIZE )
3578 		read_count = libcfile_internal_file_io_control_read_with_error_code(
3579 		              internal_file,
3580 		              (uint32_t) DKIOCGETBLOCKSIZE,
3581 		              NULL,
3582 		              0,
3583 		              (uint8_t *) &bytes_per_sector,
3584 		              4,
3585 		              &error_code,
3586 		              error );
3587 
3588 		if( read_count == -1 )
3589 		{
3590 			libcerror_error_set(
3591 			 error,
3592 			 LIBCERROR_ERROR_DOMAIN_IO,
3593 			 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3594 			 "%s: unable to query device for: DKIOCGETBLOCKSIZE.",
3595 			 function );
3596 
3597 #if defined( HAVE_DEBUG_OUTPUT )
3598 			if( libcnotify_verbose != 0 )
3599 			{
3600 				if( ( error != NULL )
3601 				 && ( *error != NULL ) )
3602 				{
3603 					libcnotify_print_error_backtrace(
3604 					 *error );
3605 				}
3606 			}
3607 #endif
3608 			libcerror_error_free(
3609 			 error );
3610 		}
3611 		else
3612 		{
3613 			read_count = libcfile_internal_file_io_control_read_with_error_code(
3614 			              internal_file,
3615 			              (uint32_t) DKIOCGETBLOCKCOUNT,
3616 			              NULL,
3617 			              0,
3618 			              (uint8_t *) &block_count,
3619 			              4,
3620 			              &error_code,
3621 			              error );
3622 
3623 			if( read_count == -1 )
3624 			{
3625 				libcerror_error_set(
3626 				 error,
3627 				 LIBCERROR_ERROR_DOMAIN_IO,
3628 				 LIBCERROR_IO_ERROR_IOCTL_FAILED,
3629 				 "%s: unable to query device for: DKIOCGETBLOCKCOUNT.",
3630 				 function );
3631 
3632 #if defined( HAVE_DEBUG_OUTPUT )
3633 				if( libcnotify_verbose != 0 )
3634 				{
3635 					if( ( error != NULL )
3636 					 && ( *error != NULL ) )
3637 					{
3638 						libcnotify_print_error_backtrace(
3639 						 *error );
3640 					}
3641 				}
3642 #endif
3643 				libcerror_error_free(
3644 				 error );
3645 			}
3646 			else
3647 			{
3648 #if defined( HAVE_DEBUG_OUTPUT )
3649 				if( libcnotify_verbose != 0 )
3650 				{
3651 					libcnotify_printf(
3652 					 "%s: block size: %" PRIu32 " block count: %" PRIu64 " ",
3653 					 function,
3654 					 bytes_per_sector,
3655 					 block_count );
3656 				}
3657 #endif
3658 				safe_size = (size64_t) ( block_count * bytes_per_sector );
3659 			}
3660 		}
3661 #endif /* defined( BLKGETSIZE64 ) || defined( DIOCGMEDIASIZE ) || defined( DIOCGDINFO ) || ( defined( DKIOCGETBLOCKCOUNT ) && defined( DKIOCGETBLOCKSIZE ) ) */
3662 
3663 		if( read_count <= 0 )
3664 		{
3665 			/* Try to seek the end of the file and determine the size based on the offset
3666 			 */
3667 			if( libcfile_file_get_offset(
3668 			     (libcfile_file_t *) internal_file,
3669 			     &current_offset,
3670 			     error ) != 1  )
3671 			{
3672 				libcerror_error_set(
3673 				 error,
3674 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3675 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3676 				 "%s: unable to retrieve current offset.",
3677 				 function );
3678 
3679 				return( -1 );
3680 			}
3681 			offset = libcfile_file_seek_offset(
3682 			          (libcfile_file_t *) internal_file,
3683 				  0,
3684 				  SEEK_END,
3685 				  error );
3686 
3687 			if( offset == -1 )
3688 			{
3689 				libcerror_error_set(
3690 				 error,
3691 				 LIBCERROR_ERROR_DOMAIN_IO,
3692 				 LIBCERROR_IO_ERROR_SEEK_FAILED,
3693 				 "%s: unable to seek end of file.",
3694 				 function );
3695 
3696 				return( -1 );
3697 			}
3698 			safe_size = (size64_t) offset;
3699 
3700 			offset = libcfile_file_seek_offset(
3701 			          (libcfile_file_t *) internal_file,
3702 				  current_offset,
3703 				  SEEK_SET,
3704 				  error );
3705 
3706 			if( offset == -1 )
3707 			{
3708 				libcerror_error_set(
3709 				 error,
3710 				 LIBCERROR_ERROR_DOMAIN_IO,
3711 				 LIBCERROR_IO_ERROR_SEEK_FAILED,
3712 				 "%s: unable to seek offset: %" PRIi64 ".",
3713 				 function,
3714 				 current_offset );
3715 
3716 				return( -1 );
3717 			}
3718 		}
3719 #if defined( HAVE_DEBUG_OUTPUT )
3720 		if( libcnotify_verbose != 0 )
3721 		{
3722 			libcnotify_printf(
3723 			 "%s: device media size: %" PRIu64 "\n",
3724 			 function,
3725 			 safe_size );
3726 		}
3727 #endif
3728 	}
3729 	else
3730 	{
3731 		safe_size = (size64_t) file_statistics.st_size;
3732 	}
3733 	*size = safe_size;
3734 
3735 	return( 1 );
3736 }
3737 
3738 #else
3739 #error Missing file get size function
3740 #endif
3741 
3742 /* Retrieves the size of the file
3743  * Returns 1 if successful or -1 on error
3744  */
libcfile_file_get_size(libcfile_file_t * file,size64_t * size,libcerror_error_t ** error)3745 int libcfile_file_get_size(
3746      libcfile_file_t *file,
3747      size64_t *size,
3748      libcerror_error_t **error )
3749 {
3750 	libcfile_internal_file_t *internal_file = NULL;
3751 	static char *function                   = "libcfile_file_get_size";
3752 
3753 	if( file == NULL )
3754 	{
3755 		libcerror_error_set(
3756 		 error,
3757 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3758 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3759 		 "%s: invalid file.",
3760 		 function );
3761 
3762 		return( -1 );
3763 	}
3764 	internal_file = (libcfile_internal_file_t *) file;
3765 
3766 	if( size == NULL )
3767 	{
3768 		libcerror_error_set(
3769 		 error,
3770 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3771 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3772 		 "%s: invalid size.",
3773 		 function );
3774 
3775 		return( -1 );
3776 	}
3777 	*size = internal_file->size;
3778 
3779 	return( 1 );
3780 }
3781 
3782 #if defined( WINAPI )
3783 
3784 /* Determines if a file is a device
3785  * This function uses the WINAPI function for Windows XP (0x0501) or later
3786  * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
3787  * Returns 1 if true, 0 if not or -1 on error
3788  */
libcfile_file_is_device(libcfile_file_t * file,libcerror_error_t ** error)3789 int libcfile_file_is_device(
3790      libcfile_file_t *file,
3791      libcerror_error_t **error )
3792 {
3793 	libcfile_internal_file_t *internal_file = NULL;
3794 	static char *function                   = "libcfile_file_is_device";
3795 	DWORD file_type                         = 0;
3796 	int result                              = 0;
3797 
3798 	if( file == NULL )
3799 	{
3800 		libcerror_error_set(
3801 		 error,
3802 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3803 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3804 		 "%s: invalid file.",
3805 		 function );
3806 
3807 		return( -1 );
3808 	}
3809 	internal_file = (libcfile_internal_file_t *) file;
3810 
3811 	if( internal_file->handle == INVALID_HANDLE_VALUE )
3812 	{
3813 		libcerror_error_set(
3814 		 error,
3815 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3816 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3817 		 "%s: invalid file - missing handle.",
3818 		 function );
3819 
3820 		return( -1 );
3821 	}
3822 /* TODO what about FILE_ATTRIBUTE_DEVICE using GetFileAttributes() */
3823 
3824 	/* Use the GetFileType function to rule out certain file types
3825 	 * like pipes, sockets, etc.
3826 	 */
3827 #if ( WINVER <= 0x0500 )
3828 	file_type = libcfile_GetFileType(
3829 	             internal_file->handle );
3830 #else
3831 	file_type = GetFileType(
3832 	             internal_file->handle );
3833 #endif
3834 
3835 	if( file_type == FILE_TYPE_UNKNOWN )
3836 	{
3837 		libcerror_error_set(
3838 		 error,
3839 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3840 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3841 		 "%s: unable to determine file type.",
3842 		 function );
3843 
3844 		return( -1 );
3845 	}
3846 	else if( file_type == FILE_TYPE_DISK )
3847 	{
3848 		if( internal_file->is_device_filename )
3849 		{
3850 			result = 1;
3851 		}
3852 	}
3853 	return( result );
3854 }
3855 
3856 #elif defined( HAVE_FSTAT )
3857 
3858 /* Determines if a file is a device
3859  * This function uses the POSIX fstat function or equivalent
3860  * Returns 1 if true, 0 if not or -1 on error
3861  */
libcfile_file_is_device(libcfile_file_t * file,libcerror_error_t ** error)3862 int libcfile_file_is_device(
3863      libcfile_file_t *file,
3864      libcerror_error_t **error )
3865 {
3866 	struct stat file_statistics;
3867 
3868 	libcfile_internal_file_t *internal_file = NULL;
3869 	static char *function                   = "libcfile_file_is_device";
3870 	int result                              = 0;
3871 
3872 	if( file == NULL )
3873 	{
3874 		libcerror_error_set(
3875 		 error,
3876 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3877 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3878 		 "%s: invalid file.",
3879 		 function );
3880 
3881 		return( -1 );
3882 	}
3883 	internal_file = (libcfile_internal_file_t *) file;
3884 
3885 	if( internal_file->descriptor == -1 )
3886 	{
3887 		libcerror_error_set(
3888 		 error,
3889 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3890 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3891 		 "%s: invalid file - missing descriptor.",
3892 		 function );
3893 
3894 		return( -1 );
3895 	}
3896 	if( memory_set(
3897 	     &file_statistics,
3898 	     0,
3899 	     sizeof( struct stat ) ) == NULL )
3900 	{
3901 		libcerror_error_set(
3902 		 error,
3903 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
3904 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
3905 		 "%s: unable to clear file statistics.",
3906 		 function );
3907 
3908 		return( -1 );
3909 	}
3910 	if( fstat(
3911 	     internal_file->descriptor,
3912 	     &file_statistics ) != 0 )
3913 	{
3914 		libcerror_error_set(
3915 		 error,
3916 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3917 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3918 		 "%s: unable to retrieve file statistics.",
3919 		 function );
3920 
3921 		return( -1 );
3922 	}
3923 	if( S_ISBLK( file_statistics.st_mode )
3924 	 || S_ISCHR( file_statistics.st_mode ) )
3925 	{
3926 		result = 1;
3927 	}
3928 	return( result );
3929 }
3930 
3931 #else
3932 #error Missing file is device function
3933 #endif
3934 
3935 #if defined( HAVE_IOCTL ) || defined( WINAPI )
3936 
3937 /* Read data from a device file using IO control
3938  * This function uses the POSIX ioctl function or WINAPI DeviceIoControl
3939  * Returns the number of bytes read if successful or -1 on error
3940  */
libcfile_internal_file_io_control_read_with_error_code(libcfile_internal_file_t * internal_file,uint32_t control_code,uint8_t * control_data,size_t control_data_size,uint8_t * data,size_t data_size,uint32_t * error_code,libcerror_error_t ** error)3941 ssize_t libcfile_internal_file_io_control_read_with_error_code(
3942          libcfile_internal_file_t *internal_file,
3943          uint32_t control_code,
3944          uint8_t *control_data,
3945          size_t control_data_size,
3946          uint8_t *data,
3947          size_t data_size,
3948          uint32_t *error_code,
3949          libcerror_error_t **error )
3950 {
3951 	static char *function = "libcfile_internal_file_io_control_read_with_error_code";
3952 
3953 #if defined( WINAPI )
3954 	DWORD response_count  = 0;
3955 #endif
3956 
3957 	if( internal_file == NULL )
3958 	{
3959 		libcerror_error_set(
3960 		 error,
3961 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3962 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3963 		 "%s: invalid file.",
3964 		 function );
3965 
3966 		return( -1 );
3967 	}
3968 #if defined( WINAPI )
3969 	if( internal_file->handle == INVALID_HANDLE_VALUE )
3970 	{
3971 		libcerror_error_set(
3972 		 error,
3973 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3974 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3975 		 "%s: invalid file - missing handle.",
3976 		 function );
3977 
3978 		return( -1 );
3979 	}
3980 #else
3981 	if( internal_file->descriptor == -1 )
3982 	{
3983 		libcerror_error_set(
3984 		 error,
3985 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3986 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3987 		 "%s: invalid file - missing descriptor.",
3988 		 function );
3989 
3990 		return( -1 );
3991 	}
3992 #endif
3993 	if( control_data == NULL )
3994 	{
3995 		if( control_data_size != 0 )
3996 		{
3997 			libcerror_error_set(
3998 			 error,
3999 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4000 			 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4001 			 "%s: invalid control data size value exceeds maximum.",
4002 			 function );
4003 
4004 			return( -1 );
4005 		}
4006 	}
4007 	else
4008 	{
4009 #if ( UINT32_MAX < SSIZE_MAX )
4010 		if( control_data_size > (size_t) UINT32_MAX )
4011 #else
4012 		if( control_data_size > (size_t) SSIZE_MAX )
4013 #endif
4014 		{
4015 			libcerror_error_set(
4016 			 error,
4017 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4018 			 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4019 			 "%s: invalid control data size value exceeds maximum.",
4020 			 function );
4021 
4022 			return( -1 );
4023 		}
4024 	}
4025 	if( data == NULL )
4026 	{
4027 		if( data_size != 0 )
4028 		{
4029 			libcerror_error_set(
4030 			 error,
4031 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4032 			 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4033 			 "%s: invalid data size value exceeds maximum.",
4034 			 function );
4035 
4036 			return( -1 );
4037 		}
4038 	}
4039 	else
4040 	{
4041 #if ( UINT32_MAX < SSIZE_MAX )
4042 		if( data_size > (size_t) UINT32_MAX )
4043 #else
4044 		if( data_size > (size_t) SSIZE_MAX )
4045 #endif
4046 		{
4047 			libcerror_error_set(
4048 			 error,
4049 			 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4050 			 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4051 			 "%s: invalid data size value exceeds maximum.",
4052 			 function );
4053 
4054 			return( -1 );
4055 		}
4056 	}
4057 	if( error_code == NULL )
4058 	{
4059 		libcerror_error_set(
4060 		 error,
4061 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4062 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4063 		 "%s: invalid error code.",
4064 		 function );
4065 
4066 		return( -1 );
4067 	}
4068 #if defined( WINAPI )
4069 	if( DeviceIoControl(
4070 	     internal_file->handle,
4071 	     (DWORD) control_code,
4072 	     control_data,
4073 	     (DWORD) control_data_size,
4074 	     data,
4075 	     (DWORD) data_size,
4076 	     &response_count,
4077 	     NULL ) == 0 )
4078 	{
4079 		*error_code = (uint32_t) GetLastError();
4080 
4081 		libcerror_system_set_error(
4082 		 error,
4083 		 LIBCERROR_ERROR_DOMAIN_IO,
4084 		 LIBCERROR_IO_ERROR_IOCTL_FAILED,
4085 		 *error_code,
4086 		 "%s: unable to IO control device.",
4087 		 function );
4088 
4089 		return( -1 );
4090 	}
4091 #if ( SSIZE_MAX < UINT32_MAX )
4092 	if( response_count > (size_t) SSIZE_MAX )
4093 	{
4094 		libcerror_error_set(
4095 		 error,
4096 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4097 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4098 		 "%s: invalid response count value out of bounds.",
4099 		 function );
4100 
4101 		return( -1 );
4102 	}
4103 #endif
4104 	return( (ssize_t) response_count );
4105 
4106 #elif defined( HAVE_IOCTL )
4107 	if( control_data != NULL )
4108 	{
4109 		libcerror_error_set(
4110 		 error,
4111 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4112 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4113 		 "%s: unsupported control data.",
4114 		 function );
4115 
4116 		return( -1 );
4117 	}
4118 	if( ioctl(
4119 	     internal_file->descriptor,
4120 	     (int) control_code,
4121 	     data ) == -1 )
4122 	{
4123 		*error_code = (uint32_t) errno;
4124 
4125 		libcerror_system_set_error(
4126 		 error,
4127 		 LIBCERROR_ERROR_DOMAIN_IO,
4128 		 LIBCERROR_IO_ERROR_IOCTL_FAILED,
4129 		 *error_code,
4130 		 "%s: unable to IO control device.",
4131 		 function );
4132 
4133 		return( -1 );
4134 	}
4135 	return( (size_t) data_size );
4136 #endif
4137 }
4138 
4139 #else
4140 #error Missing file IO control with data function
4141 #endif
4142 
4143 /* Read data from a device file using IO control
4144  * Returns the number of bytes read if successful or -1 on error
4145  */
libcfile_file_io_control_read(libcfile_file_t * file,uint32_t control_code,uint8_t * control_data,size_t control_data_size,uint8_t * data,size_t data_size,libcerror_error_t ** error)4146 ssize_t libcfile_file_io_control_read(
4147          libcfile_file_t *file,
4148          uint32_t control_code,
4149          uint8_t *control_data,
4150          size_t control_data_size,
4151          uint8_t *data,
4152          size_t data_size,
4153          libcerror_error_t **error )
4154 {
4155 	libcfile_internal_file_t *internal_file = NULL;
4156 	static char *function                   = "libcfile_file_io_control_read";
4157 	ssize_t read_count                      = 0;
4158 	uint32_t error_code                     = 0;
4159 
4160 	if( file == NULL )
4161 	{
4162 		libcerror_error_set(
4163 		 error,
4164 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4165 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4166 		 "%s: invalid file.",
4167 		 function );
4168 
4169 		return( -1 );
4170 	}
4171 	internal_file = (libcfile_internal_file_t *) file;
4172 
4173 	read_count = libcfile_internal_file_io_control_read_with_error_code(
4174 	              internal_file,
4175 	              control_code,
4176 	              control_data,
4177 	              control_data_size,
4178 	              data,
4179 	              data_size,
4180 	              &error_code,
4181 	              error );
4182 
4183 	if( read_count == -1 )
4184 	{
4185 		libcerror_error_set(
4186 		 error,
4187 		 LIBCERROR_ERROR_DOMAIN_IO,
4188 		 LIBCERROR_IO_ERROR_IOCTL_FAILED,
4189 		 "%s: unable to to IO control device.",
4190 		 function );
4191 
4192 		return( -1 );
4193 	}
4194 	return( read_count );
4195 }
4196 
4197 /* Read data from a device file using IO control
4198  * Returns the number of bytes read if successful or -1 on error
4199  */
libcfile_file_io_control_read_with_error_code(libcfile_file_t * file,uint32_t control_code,uint8_t * control_data,size_t control_data_size,uint8_t * data,size_t data_size,uint32_t * error_code,libcerror_error_t ** error)4200 ssize_t libcfile_file_io_control_read_with_error_code(
4201          libcfile_file_t *file,
4202          uint32_t control_code,
4203          uint8_t *control_data,
4204          size_t control_data_size,
4205          uint8_t *data,
4206          size_t data_size,
4207          uint32_t *error_code,
4208          libcerror_error_t **error )
4209 {
4210 	libcfile_internal_file_t *internal_file = NULL;
4211 	static char *function                   = "libcfile_file_io_control_read_with_error_code";
4212 	ssize_t read_count                      = 0;
4213 
4214 	if( file == NULL )
4215 	{
4216 		libcerror_error_set(
4217 		 error,
4218 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4219 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4220 		 "%s: invalid file.",
4221 		 function );
4222 
4223 		return( -1 );
4224 	}
4225 	internal_file = (libcfile_internal_file_t *) file;
4226 
4227 	read_count = libcfile_internal_file_io_control_read_with_error_code(
4228 	              internal_file,
4229 	              control_code,
4230 	              control_data,
4231 	              control_data_size,
4232 	              data,
4233 	              data_size,
4234 	              error_code,
4235 	              error );
4236 
4237 	if( read_count == -1 )
4238 	{
4239 		libcerror_error_set(
4240 		 error,
4241 		 LIBCERROR_ERROR_DOMAIN_IO,
4242 		 LIBCERROR_IO_ERROR_IOCTL_FAILED,
4243 		 "%s: unable to to IO control device.",
4244 		 function );
4245 
4246 		return( -1 );
4247 	}
4248 	return( read_count );
4249 }
4250 
4251 /* On some versions of Linux the FADVISE definions seem to be missing from fcntl.h
4252  */
4253 #if defined( HAVE_POSIX_FADVISE ) && !defined( WINAPI )
4254 
4255 #if !defined( POSIX_FADV_NORMAL )
4256 #define POSIX_FADV_NORMAL		0
4257 #endif
4258 
4259 #if !defined( POSIX_FADV_RANDOM )
4260 #define POSIX_FADV_RANDOM		1
4261 #endif
4262 
4263 #if !defined( POSIX_FADV_SEQUENTIAL )
4264 #define POSIX_FADV_SEQUENTIAL		2
4265 #endif
4266 
4267 #endif /* #if defined( HAVE_POSIX_FADVISE ) && !defined( WINAPI ) */
4268 
4269 /* Sets the expected access behavior so the system can optimize the access
4270  * Returns 1 if successful or -1 on error
4271  */
libcfile_file_set_access_behavior(libcfile_file_t * file,int access_behavior,libcerror_error_t ** error)4272 int libcfile_file_set_access_behavior(
4273      libcfile_file_t *file,
4274      int access_behavior,
4275      libcerror_error_t **error )
4276 {
4277 	libcfile_internal_file_t *internal_file = NULL;
4278 	static char *function                   = "libcfile_file_set_access_behavior";
4279 
4280 #if defined( HAVE_POSIX_FADVISE ) && !defined( WINAPI )
4281 	int advice                              = POSIX_FADV_NORMAL;
4282 	int result                              = 0;
4283 #endif
4284 
4285 	if( file == NULL )
4286 	{
4287 		libcerror_error_set(
4288 		 error,
4289 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4290 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4291 		 "%s: invalid file.",
4292 		 function );
4293 
4294 		return( -1 );
4295 	}
4296 	internal_file = (libcfile_internal_file_t *) file;
4297 
4298 #if defined( WINAPI )
4299 	if( internal_file->handle == INVALID_HANDLE_VALUE )
4300 	{
4301 		libcerror_error_set(
4302 		 error,
4303 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4304 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4305 		 "%s: invalid file - missing handle.",
4306 		 function );
4307 
4308 		return( -1 );
4309 	}
4310 #else
4311 	if( internal_file->descriptor == -1 )
4312 	{
4313 		libcerror_error_set(
4314 		 error,
4315 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4316 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4317 		 "%s: invalid file - missing descriptor.",
4318 		 function );
4319 
4320 		return( -1 );
4321 	}
4322 #endif
4323 	if( ( access_behavior != LIBCFILE_ACCESS_BEHAVIOR_NORMAL )
4324 	 && ( access_behavior != LIBCFILE_ACCESS_BEHAVIOR_RANDOM )
4325 	 && ( access_behavior != LIBCFILE_ACCESS_BEHAVIOR_SEQUENTIAL ) )
4326 	{
4327 		libcerror_error_set(
4328 		 error,
4329 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4330 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4331 		 "%s: unsupported access behavior: %d.",
4332 		 function,
4333 		 access_behavior );
4334 
4335 		return( -1 );
4336 	}
4337 #if defined( HAVE_POSIX_FADVISE ) && !defined( WINAPI )
4338 	if( access_behavior == LIBCFILE_ACCESS_BEHAVIOR_NORMAL )
4339 	{
4340 		advice = POSIX_FADV_NORMAL;
4341 	}
4342 	else if( access_behavior == LIBCFILE_ACCESS_BEHAVIOR_RANDOM )
4343 	{
4344 		advice = POSIX_FADV_RANDOM;
4345 	}
4346 	else if( access_behavior == LIBCFILE_ACCESS_BEHAVIOR_SEQUENTIAL )
4347 	{
4348 		advice = POSIX_FADV_SEQUENTIAL;
4349 	}
4350 	result = posix_fadvise(
4351 	          internal_file->descriptor,
4352 	          0,
4353 	          0,
4354 	          advice );
4355 
4356 	/* Safely ignore if the device does not support fadvise.
4357 	 * Note that FreeBSD 10.0 had a bug and was returning -1
4358 	 * and setting errno.
4359 	 */
4360 	if( ( result != 0 )
4361 	 && ( result != ENODEV ) )
4362 	{
4363 		libcerror_system_set_error(
4364 		 error,
4365 		 LIBCERROR_ERROR_DOMAIN_IO,
4366 		 LIBCERROR_IO_ERROR_GENERIC,
4367 		 errno,
4368 		 "%s: unable to advice file descriptor on access behavior.",
4369 		 function );
4370 
4371 		return( -1 );
4372 	}
4373 #endif /* defined( HAVE_POSIX_FADVISE ) && !defined( WINAPI ) */
4374 
4375 	return( 1 );
4376 }
4377 
4378 /* Sets the block size for the read and seek operations
4379  * A block size of 0 represents no block-based operations
4380  * The total size must be a multitude of block size
4381  * Returns 1 if successful or -1 on error
4382  */
libcfile_internal_file_set_block_size(libcfile_internal_file_t * internal_file,size_t block_size,libcerror_error_t ** error)4383 int libcfile_internal_file_set_block_size(
4384      libcfile_internal_file_t *internal_file,
4385      size_t block_size,
4386      libcerror_error_t **error )
4387 {
4388 	static char *function = "libcfile_internal_file_set_block_size";
4389 
4390 	if( internal_file == NULL )
4391 	{
4392 		libcerror_error_set(
4393 		 error,
4394 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4395 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4396 		 "%s: invalid file.",
4397 		 function );
4398 
4399 		return( -1 );
4400 	}
4401 #if defined( WINAPI ) && ( UINT32_MAX < SSIZE_MAX )
4402 	if( block_size > (size_t) UINT32_MAX )
4403 #else
4404 	if( block_size > (size_t) SSIZE_MAX )
4405 #endif
4406 	{
4407 		libcerror_error_set(
4408 		 error,
4409 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4410 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4411 		 "%s: invalid block size value exceeds maximum.",
4412 		 function );
4413 
4414 		return( -1 );
4415 	}
4416 	if( internal_file->block_data != NULL )
4417 	{
4418 		if( block_size != internal_file->block_size )
4419 		{
4420 			memory_free(
4421 			 internal_file->block_data );
4422 
4423 			internal_file->block_data      = NULL;
4424 			internal_file->block_data_size = 0;
4425 		}
4426 	}
4427 	if( internal_file->block_data == NULL )
4428 	{
4429 		if( block_size > 0 )
4430 		{
4431 			internal_file->block_data = (uint8_t *) memory_allocate(
4432 			                                         sizeof( uint8_t ) * block_size );
4433 
4434 			if( internal_file->block_data == NULL )
4435 			{
4436 				libcerror_error_set(
4437 				 error,
4438 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
4439 				 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
4440 				 "%s: unable to create block data.",
4441 				 function );
4442 
4443 				return( -1 );
4444 			}
4445 			if( memory_set(
4446 			     internal_file->block_data,
4447 			     0,
4448 			     block_size ) == NULL )
4449 			{
4450 				libcerror_error_set(
4451 				 error,
4452 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
4453 				 LIBCERROR_MEMORY_ERROR_SET_FAILED,
4454 				 "%s: unable to clear block data.",
4455 				 function );
4456 
4457 				return( -1 );
4458 			}
4459 		}
4460 		internal_file->block_size = block_size;
4461 	}
4462 	return( 1 );
4463 }
4464 
4465 /* Sets the block size for the read and seek operations
4466  * A block size of 0 represents no block-based operations
4467  * The total size must be a multitude of block size
4468  * Returns 1 if successful or -1 on error
4469  */
libcfile_file_set_block_size(libcfile_file_t * file,size_t block_size,libcerror_error_t ** error)4470 int libcfile_file_set_block_size(
4471      libcfile_file_t *file,
4472      size_t block_size,
4473      libcerror_error_t **error )
4474 {
4475 	libcfile_internal_file_t *internal_file = NULL;
4476 	static char *function                   = "libcfile_file_set_block_size";
4477 
4478 	if( file == NULL )
4479 	{
4480 		libcerror_error_set(
4481 		 error,
4482 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4483 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4484 		 "%s: invalid file.",
4485 		 function );
4486 
4487 		return( -1 );
4488 	}
4489 	internal_file = (libcfile_internal_file_t *) file;
4490 
4491 	if( ( internal_file->access_flags & LIBCFILE_ACCESS_FLAG_WRITE ) != 0 )
4492 	{
4493 		libcerror_error_set(
4494 		 error,
4495 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4496 		 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
4497 		 "%s: setting block size not supported with write access.",
4498 		 function );
4499 
4500 		return( -1 );
4501 	}
4502 #if defined( WINAPI )
4503 	if( internal_file->handle == INVALID_HANDLE_VALUE )
4504 	{
4505 		libcerror_error_set(
4506 		 error,
4507 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4508 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4509 		 "%s: invalid file - missing handle.",
4510 		 function );
4511 
4512 		return( -1 );
4513 	}
4514 #else
4515 	if( internal_file->descriptor == -1 )
4516 	{
4517 		libcerror_error_set(
4518 		 error,
4519 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4520 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4521 		 "%s: invalid file - missing descriptor.",
4522 		 function );
4523 
4524 		return( -1 );
4525 	}
4526 #endif
4527 #if defined( WINAPI ) && ( UINT32_MAX < SSIZE_MAX )
4528 	if( block_size > (size_t) UINT32_MAX )
4529 #else
4530 	if( block_size > (size_t) SSIZE_MAX )
4531 #endif
4532 	{
4533 		libcerror_error_set(
4534 		 error,
4535 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4536 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
4537 		 "%s: invalid block size value exceeds maximum.",
4538 		 function );
4539 
4540 		return( -1 );
4541 	}
4542 	if( ( block_size != 0 )
4543 	 && ( ( internal_file->size % block_size ) != 0 ) )
4544 	{
4545 		libcerror_error_set(
4546 		 error,
4547 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4548 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
4549 		 "%s: invalid block size value out of bounds.",
4550 		 function );
4551 
4552 		return( -1 );
4553 	}
4554 	if( libcfile_internal_file_set_block_size(
4555 	     internal_file,
4556 	     block_size,
4557 	     error ) != 1 )
4558 	{
4559 		libcerror_error_set(
4560 		 error,
4561 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4562 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4563 		 "%s: unable to set block size.",
4564 		 function );
4565 
4566 		return( -1 );
4567 	}
4568 	return( 1 );
4569 }
4570 
4571