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 ¤t_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