Coverage Report

Created: 2026-05-24 07:09

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