Coverage Report

Created: 2024-02-25 07:19

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