Coverage Report

Created: 2026-07-10 07:32

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