Coverage Report

Created: 2024-02-25 07:20

/src/liblnk/libcfile/libcfile_support.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Support 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_UNISTD_H )
38
#include <unistd.h>
39
#endif
40
41
#include "libcfile_definitions.h"
42
#include "libcfile_libcerror.h"
43
#include "libcfile_libclocale.h"
44
#include "libcfile_libuna.h"
45
#include "libcfile_support.h"
46
#include "libcfile_winapi.h"
47
48
#if !defined( HAVE_LOCAL_LIBCFILE )
49
50
/* Returns the library version as a string
51
 */
52
const char *libcfile_get_version(
53
             void )
54
{
55
  return( (const char *) LIBCFILE_VERSION_STRING );
56
}
57
58
/* Retrieves the narrow system string codepage
59
 * A value of 0 represents no codepage, UTF-8 encoding is used instead
60
 * Returns 1 if successful or -1 on error
61
 */
62
int libcfile_get_codepage(
63
     int *codepage,
64
     libcerror_error_t **error )
65
{
66
  static char *function = "libcfile_get_codepage";
67
68
  if( libclocale_codepage_get(
69
       codepage,
70
       error ) != 1 )
71
  {
72
    libcerror_error_set(
73
     error,
74
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
75
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
76
     "%s: unable to retrieve codepage.",
77
     function );
78
79
    return( -1 );
80
  }
81
  return( 1 );
82
}
83
84
/* Sets the narrow system string codepage
85
 * A value of 0 represents no codepage, UTF-8 encoding is used instead
86
 * Returns 1 if successful or -1 on error
87
 */
88
int libcfile_set_codepage(
89
     int codepage,
90
     libcerror_error_t **error )
91
{
92
  static char *function = "libcfile_set_codepage";
93
94
  if( libclocale_codepage_set(
95
       codepage,
96
       error ) != 1 )
97
  {
98
    libcerror_error_set(
99
     error,
100
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
101
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
102
     "%s: unable to set codepage.",
103
     function );
104
105
    return( -1 );
106
  }
107
  return( 1 );
108
}
109
110
#endif /* !defined( HAVE_LOCAL_LIBCFILE ) */
111
112
#if defined( WINAPI )
113
114
/* Determines if a file exists
115
 * This function uses the WINAPI function for Windows XP (0x0501) or later,
116
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
117
 * Returns 1 if the file exists, 0 if not or -1 on error
118
 */
119
int libcfile_file_exists(
120
     const char *filename,
121
     libcerror_error_t **error )
122
{
123
  static char *function  = "libcfile_file_exists";
124
  size_t filename_length = 0;
125
  DWORD error_code       = 0;
126
  DWORD file_attributes  = 0;
127
  HANDLE handle          = INVALID_HANDLE_VALUE;
128
  int is_device_filename = 0;
129
  int result             = 1;
130
131
  if( filename == NULL )
132
  {
133
    libcerror_error_set(
134
     error,
135
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
136
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
137
     "%s: invalid filename.",
138
     function );
139
140
    return( -1 );
141
  }
142
  filename_length = narrow_string_length(
143
                     filename );
144
145
  if( filename_length > 4 )
146
  {
147
    if( ( filename[ 0 ] == '\\' )
148
     && ( filename[ 1 ] == '\\' )
149
     && ( filename[ 2 ] == '.' )
150
     && ( filename[ 3 ] == '\\' ) )
151
    {
152
      /* Ignore \\.\F:\ which is an alternative notation for F:
153
       */
154
      if( ( filename_length < 7 )
155
       || ( filename[ 5 ] != ':' )
156
       || ( filename[ 6 ] != '\\' ) )
157
      {
158
        is_device_filename = 1;
159
      }
160
    }
161
  }
162
  if( is_device_filename != 0 )
163
  {
164
#if ( WINVER <= 0x0500 )
165
    handle = libcfile_CreateFileA(
166
              (LPCSTR) filename,
167
              GENERIC_READ,
168
              FILE_SHARE_READ | FILE_SHARE_WRITE,
169
              NULL,
170
              OPEN_EXISTING,
171
              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
172
              NULL );
173
#else
174
    handle = CreateFileA(
175
              (LPCSTR) filename,
176
              GENERIC_READ,
177
              FILE_SHARE_READ | FILE_SHARE_WRITE,
178
              NULL,
179
              OPEN_EXISTING,
180
              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
181
              NULL );
182
#endif
183
    if( handle == INVALID_HANDLE_VALUE )
184
    {
185
      error_code = (uint32_t) GetLastError();
186
187
      switch( error_code )
188
      {
189
        case ERROR_ACCESS_DENIED:
190
          result = 1;
191
192
          break;
193
194
        case ERROR_FILE_NOT_FOUND:
195
        case ERROR_PATH_NOT_FOUND:
196
          result = 0;
197
198
          break;
199
200
        default:
201
          libcerror_system_set_error(
202
           error,
203
           LIBCERROR_ERROR_DOMAIN_IO,
204
           LIBCERROR_IO_ERROR_OPEN_FAILED,
205
           error_code,
206
           "%s: unable to open file: %s.",
207
           function,
208
           filename );
209
210
          return( -1 );
211
      }
212
    }
213
    else
214
    {
215
#if ( WINVER <= 0x0500 )
216
      result = libcfile_CloseHandle(
217
                handle );
218
#else
219
      result = CloseHandle(
220
                handle );
221
#endif
222
      if( result == 0 )
223
      {
224
        error_code = GetLastError();
225
226
        libcerror_system_set_error(
227
         error,
228
         LIBCERROR_ERROR_DOMAIN_IO,
229
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
230
         error_code,
231
         "%s: unable to close file.",
232
         function );
233
234
        return( -1 );
235
      }
236
      result = 1;
237
    }
238
  }
239
  else
240
  {
241
    /* Note that GetFileAttributesA does not support Windows device file names.
242
     */
243
#if ( WINVER <= 0x0500 )
244
    file_attributes = libcfile_GetFileAttributesA(
245
                       (LPCSTR) filename );
246
#else
247
    file_attributes = GetFileAttributesA(
248
                       (LPCSTR) filename );
249
#endif
250
    if( file_attributes == INVALID_FILE_ATTRIBUTES )
251
    {
252
      error_code = GetLastError();
253
254
      switch( error_code )
255
      {
256
        case ERROR_ACCESS_DENIED:
257
          result = 1;
258
259
          break;
260
261
        case ERROR_FILE_NOT_FOUND:
262
        case ERROR_PATH_NOT_FOUND:
263
          result = 0;
264
265
          break;
266
267
        default:
268
          libcerror_system_set_error(
269
           error,
270
           LIBCERROR_ERROR_DOMAIN_IO,
271
           LIBCERROR_IO_ERROR_GENERIC,
272
           error_code,
273
           "%s: unable to determine attributes of file: %s.",
274
           function,
275
           filename );
276
277
          return( -1 );
278
      }
279
    }
280
  }
281
  return( result );
282
}
283
284
#elif defined( HAVE_STAT )
285
286
/* Determines if a file exists
287
 * This function uses the POSIX stat function or equivalent
288
 * Returns 1 if the file exists, 0 if not or -1 on error
289
 */
290
int libcfile_file_exists(
291
     const char *filename,
292
     libcerror_error_t **error )
293
0
{
294
0
  struct stat file_statistics;
295
296
0
  static char *function = "libcfile_file_exists";
297
0
  int result            = 0;
298
299
0
  if( filename == NULL )
300
0
  {
301
0
    libcerror_error_set(
302
0
     error,
303
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
305
0
     "%s: invalid filename.",
306
0
     function );
307
308
0
    return( -1 );
309
0
  }
310
0
  if( memory_set(
311
0
       &file_statistics,
312
0
       0,
313
0
       sizeof( struct stat ) ) == NULL )
314
0
  {
315
0
    libcerror_error_set(
316
0
     error,
317
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
318
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
319
0
     "%s: unable to clear file statistics.",
320
0
     function );
321
322
0
    return( -1 );
323
0
  }
324
0
  result = stat(
325
0
            filename,
326
0
            &file_statistics );
327
328
0
  if( result != 0 )
329
0
  {
330
0
    switch( errno )
331
0
    {
332
0
      case EACCES:
333
0
        result = 1;
334
335
0
        break;
336
337
0
      case ENOENT:
338
0
        result = 0;
339
340
0
        break;
341
342
0
      default:
343
0
        libcerror_system_set_error(
344
0
         error,
345
0
         LIBCERROR_ERROR_DOMAIN_IO,
346
0
         LIBCERROR_IO_ERROR_GENERIC,
347
0
         errno,
348
0
         "%s: unable to stat file: %" PRIs_SYSTEM ".",
349
0
         function,
350
0
         filename );
351
352
0
        return( -1 );
353
0
    }
354
0
  }
355
0
  else
356
0
  {
357
0
    result = 1;
358
0
  }
359
0
  return( result );
360
0
}
361
362
#else
363
#error Missing file exists function
364
#endif
365
366
#if defined( HAVE_WIDE_CHARACTER_TYPE )
367
368
#if defined( WINAPI )
369
370
/* Determines if a file exists using get file attibutes
371
 * This function uses the WINAPI function for Windows XP (0x0501) or later,
372
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
373
 * Returns 1 if the file exists, 0 if not or -1 on error
374
 */
375
int libcfile_file_exists_wide(
376
     const wchar_t *filename,
377
     libcerror_error_t **error )
378
{
379
  static char *function  = "libcfile_file_exists_wide";
380
  size_t filename_length = 0;
381
  DWORD error_code       = 0;
382
  DWORD file_attributes  = 0;
383
  HANDLE handle          = INVALID_HANDLE_VALUE;
384
  int is_device_filename = 0;
385
  int result             = 1;
386
387
  if( filename == NULL )
388
  {
389
    libcerror_error_set(
390
     error,
391
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
392
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
393
     "%s: invalid filename.",
394
     function );
395
396
    return( -1 );
397
  }
398
  filename_length = wide_string_length(
399
                     filename );
400
401
  if( filename_length > 4 )
402
  {
403
    if( ( filename[ 0 ] == (uint16_t) '\\' )
404
     && ( filename[ 1 ] == (uint16_t) '\\' )
405
     && ( filename[ 2 ] == (uint16_t) '.' )
406
     && ( filename[ 3 ] == (uint16_t) '\\' ) )
407
    {
408
      /* Ignore \\.\F:\ which is an alternative notation for F:
409
       */
410
      if( ( filename_length < 7 )
411
       || ( filename[ 5 ] != (uint16_t) ':' )
412
       || ( filename[ 6 ] != (uint16_t) '\\' ) )
413
      {
414
        is_device_filename = 1;
415
      }
416
    }
417
  }
418
  if( is_device_filename != 0 )
419
  {
420
#if ( WINVER <= 0x0500 )
421
    handle = libcfile_CreateFileW(
422
              (LPCWSTR) filename,
423
              GENERIC_READ,
424
              FILE_SHARE_READ | FILE_SHARE_WRITE,
425
              NULL,
426
              OPEN_EXISTING,
427
              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
428
              NULL );
429
#else
430
    handle = CreateFileW(
431
              (LPCWSTR) filename,
432
              GENERIC_READ,
433
              FILE_SHARE_READ | FILE_SHARE_WRITE,
434
              NULL,
435
              OPEN_EXISTING,
436
              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
437
              NULL );
438
#endif
439
    if( handle == INVALID_HANDLE_VALUE )
440
    {
441
      error_code = (uint32_t) GetLastError();
442
443
      switch( error_code )
444
      {
445
        case ERROR_ACCESS_DENIED:
446
          result = 1;
447
448
          break;
449
450
        case ERROR_FILE_NOT_FOUND:
451
        case ERROR_PATH_NOT_FOUND:
452
          result = 0;
453
454
          break;
455
456
        default:
457
          libcerror_system_set_error(
458
           error,
459
           LIBCERROR_ERROR_DOMAIN_IO,
460
           LIBCERROR_IO_ERROR_OPEN_FAILED,
461
           error_code,
462
           "%s: unable to open file: %ls.",
463
           function,
464
           filename );
465
466
          return( -1 );
467
      }
468
    }
469
    else
470
    {
471
#if ( WINVER <= 0x0500 )
472
      result = libcfile_CloseHandle(
473
                handle );
474
#else
475
      result = CloseHandle(
476
                handle );
477
#endif
478
      if( result == 0 )
479
      {
480
        error_code = GetLastError();
481
482
        libcerror_system_set_error(
483
         error,
484
         LIBCERROR_ERROR_DOMAIN_IO,
485
         LIBCERROR_IO_ERROR_CLOSE_FAILED,
486
         error_code,
487
         "%s: unable to close file.",
488
         function );
489
490
        return( -1 );
491
      }
492
      result = 1;
493
    }
494
  }
495
  else
496
  {
497
    /* Note that GetFileAttributesW does not support Windows device file names.
498
     */
499
#if ( WINVER <= 0x0500 )
500
    file_attributes = libcfile_GetFileAttributesW(
501
                       (LPCWSTR) filename );
502
#else
503
    file_attributes = GetFileAttributesW(
504
                       (LPCWSTR) filename );
505
#endif
506
    if( file_attributes == INVALID_FILE_ATTRIBUTES )
507
    {
508
      error_code = GetLastError();
509
510
      switch( error_code )
511
      {
512
        case ERROR_ACCESS_DENIED:
513
          result = 1;
514
515
          break;
516
517
        case ERROR_FILE_NOT_FOUND:
518
        case ERROR_PATH_NOT_FOUND:
519
          result = 0;
520
521
          break;
522
523
        default:
524
          libcerror_system_set_error(
525
           error,
526
           LIBCERROR_ERROR_DOMAIN_IO,
527
           LIBCERROR_IO_ERROR_GENERIC,
528
           error_code,
529
           "%s: unable to determine attributes of file: %ls.",
530
           function,
531
           filename );
532
533
          return( -1 );
534
      }
535
    }
536
  }
537
  return( result );
538
}
539
540
#elif defined( HAVE_STAT )
541
542
/* Determines if a file exists
543
 * This function uses the POSIX stat function or equivalent
544
 * Returns 1 if the file exists, 0 if not or -1 on error
545
 */
546
int libcfile_file_exists_wide(
547
     const wchar_t *filename,
548
     libcerror_error_t **error )
549
{
550
  struct stat file_statistics;
551
552
  char *narrow_filename       = NULL;
553
  static char *function       = "libcfile_file_exists_wide";
554
  size_t narrow_filename_size = 0;
555
  size_t filename_size        = 0;
556
  int result                  = 0;
557
558
  if( filename == NULL )
559
  {
560
    libcerror_error_set(
561
     error,
562
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
563
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
564
     "%s: invalid filename.",
565
     function );
566
567
    return( -1 );
568
  }
569
  filename_size = 1 + wide_string_length(
570
                       filename );
571
572
  /* Convert the filename to a narrow string
573
   * if the platform has no wide character open function
574
   */
575
  if( libclocale_codepage == 0 )
576
  {
577
#if SIZEOF_WCHAR_T == 4
578
    result = libuna_utf8_string_size_from_utf32(
579
              (libuna_utf32_character_t *) filename,
580
              filename_size,
581
              &narrow_filename_size,
582
              error );
583
#elif SIZEOF_WCHAR_T == 2
584
    result = libuna_utf8_string_size_from_utf16(
585
              (libuna_utf16_character_t *) filename,
586
              filename_size,
587
              &narrow_filename_size,
588
              error );
589
#else
590
#error Unsupported size of wchar_t
591
#endif /* SIZEOF_WCHAR_T */
592
  }
593
  else
594
  {
595
#if SIZEOF_WCHAR_T == 4
596
    result = libuna_byte_stream_size_from_utf32(
597
              (libuna_utf32_character_t *) filename,
598
              filename_size,
599
              libclocale_codepage,
600
              &narrow_filename_size,
601
              error );
602
#elif SIZEOF_WCHAR_T == 2
603
    result = libuna_byte_stream_size_from_utf16(
604
              (libuna_utf16_character_t *) filename,
605
              filename_size,
606
              libclocale_codepage,
607
              &narrow_filename_size,
608
              error );
609
#else
610
#error Unsupported size of wchar_t
611
#endif /* SIZEOF_WCHAR_T */
612
  }
613
  if( result != 1 )
614
  {
615
    libcerror_error_set(
616
     error,
617
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
618
     LIBCERROR_CONVERSION_ERROR_GENERIC,
619
     "%s: unable to determine narrow character filename size.",
620
     function );
621
622
    return( -1 );
623
  }
624
  narrow_filename = narrow_string_allocate(
625
                     narrow_filename_size );
626
627
  if( narrow_filename == NULL )
628
  {
629
    libcerror_error_set(
630
     error,
631
     LIBCERROR_ERROR_DOMAIN_MEMORY,
632
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
633
     "%s: unable to create narrow character filename.",
634
     function );
635
636
    return( -1 );
637
  }
638
  if( libclocale_codepage == 0 )
639
  {
640
#if SIZEOF_WCHAR_T == 4
641
    result = libuna_utf8_string_copy_from_utf32(
642
              (libuna_utf8_character_t *) narrow_filename,
643
              narrow_filename_size,
644
              (libuna_utf32_character_t *) filename,
645
              filename_size,
646
              error );
647
#elif SIZEOF_WCHAR_T == 2
648
    result = libuna_utf8_string_copy_from_utf16(
649
              (libuna_utf8_character_t *) narrow_filename,
650
              narrow_filename_size,
651
              (libuna_utf16_character_t *) filename,
652
              filename_size,
653
              error );
654
#else
655
#error Unsupported size of wchar_t
656
#endif /* SIZEOF_WCHAR_T */
657
  }
658
  else
659
  {
660
#if SIZEOF_WCHAR_T == 4
661
    result = libuna_byte_stream_copy_from_utf32(
662
              (uint8_t *) narrow_filename,
663
              narrow_filename_size,
664
              libclocale_codepage,
665
              (libuna_utf32_character_t *) filename,
666
              filename_size,
667
              error );
668
#elif SIZEOF_WCHAR_T == 2
669
    result = libuna_byte_stream_copy_from_utf16(
670
              (uint8_t *) narrow_filename,
671
              narrow_filename_size,
672
              libclocale_codepage,
673
              (libuna_utf16_character_t *) filename,
674
              filename_size,
675
              error );
676
#else
677
#error Unsupported size of wchar_t
678
#endif /* SIZEOF_WCHAR_T */
679
  }
680
  if( result != 1 )
681
  {
682
    libcerror_error_set(
683
     error,
684
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
685
     LIBCERROR_CONVERSION_ERROR_GENERIC,
686
     "%s: unable to set narrow character filename.",
687
     function );
688
689
    memory_free(
690
     narrow_filename );
691
692
    return( -1 );
693
  }
694
  result = stat(
695
            narrow_filename,
696
            &file_statistics );
697
698
  memory_free(
699
   narrow_filename );
700
701
  if( result != 0 )
702
  {
703
    switch( errno )
704
    {
705
      case EACCES:
706
        result = 1;
707
708
        break;
709
710
      case ENOENT:
711
        result = 0;
712
713
        break;
714
715
      default:
716
        libcerror_system_set_error(
717
         error,
718
         LIBCERROR_ERROR_DOMAIN_IO,
719
         LIBCERROR_IO_ERROR_GENERIC,
720
         errno,
721
         "%s: unable to stat file: %" PRIs_SYSTEM ".",
722
         function,
723
         filename );
724
725
        return( -1 );
726
    }
727
  }
728
  else
729
  {
730
    result = 1;
731
  }
732
  return( result );
733
}
734
735
#else
736
#error Missing file exists wide function
737
#endif
738
739
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
740
741
/* Removes a file
742
 * Returns 1 if successful or -1 on error
743
 */
744
int libcfile_file_remove(
745
     const char *filename,
746
     libcerror_error_t **error )
747
0
{
748
0
  static char *function = "libcfile_file_remove";
749
0
  uint32_t error_code   = 0;
750
751
0
  if( libcfile_file_remove_with_error_code(
752
0
       filename,
753
0
       &error_code,
754
0
       error ) != 1 )
755
0
  {
756
0
    libcerror_error_set(
757
0
     error,
758
0
     LIBCERROR_ERROR_DOMAIN_IO,
759
0
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
760
0
     "%s: unable to remove file.",
761
0
     function );
762
763
0
    return( -1 );
764
0
  }
765
0
  return( 1 );
766
0
}
767
768
#if defined( WINAPI )
769
770
/* Removes a file
771
 * This function uses the WINAPI function for Windows XP (0x0501) or later,
772
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
773
 * Returns 1 if successful or -1 on error
774
 */
775
int libcfile_file_remove_with_error_code(
776
     const char *filename,
777
     uint32_t *error_code,
778
     libcerror_error_t **error )
779
{
780
  static char *function = "libcfile_file_remove_with_error_code";
781
  BOOL result           = FALSE;
782
783
  if( filename == NULL )
784
  {
785
    libcerror_error_set(
786
     error,
787
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
788
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
789
     "%s: invalid filename.",
790
     function );
791
792
    return( -1 );
793
  }
794
  if( error_code == NULL )
795
  {
796
    libcerror_error_set(
797
     error,
798
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
799
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
800
     "%s: invalid error code.",
801
     function );
802
803
    return( -1 );
804
  }
805
#if ( WINVER <= 0x0500 )
806
  result = libcfile_DeleteFileA(
807
            filename );
808
#else
809
  result = DeleteFileA(
810
            filename );
811
#endif
812
  if( result == 0 )
813
  {
814
    *error_code = GetLastError();
815
816
    libcerror_system_set_error(
817
     error,
818
     LIBCERROR_ERROR_DOMAIN_IO,
819
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
820
     *error_code,
821
     "%s: unable to remove file.",
822
     function );
823
824
    return( -1 );
825
  }
826
  return( 1 );
827
}
828
829
#elif defined( HAVE_UNLINK )
830
831
/* Removes a file
832
 * This function uses the POSIX unlink function or equivalent
833
 * Returns 1 if successful or -1 on error
834
 */
835
int libcfile_file_remove_with_error_code(
836
     const char *filename,
837
     uint32_t *error_code,
838
     libcerror_error_t **error )
839
0
{
840
0
  static char *function = "libcfile_file_remove_with_error_code";
841
842
0
  if( filename == NULL )
843
0
  {
844
0
    libcerror_error_set(
845
0
     error,
846
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
847
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
848
0
     "%s: invalid filename.",
849
0
     function );
850
851
0
    return( -1 );
852
0
  }
853
0
  if( error_code == NULL )
854
0
  {
855
0
    libcerror_error_set(
856
0
     error,
857
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
858
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
859
0
     "%s: invalid error code.",
860
0
     function );
861
862
0
    return( -1 );
863
0
  }
864
0
  if( unlink(
865
0
       filename ) != 0 )
866
0
  {
867
0
    *error_code = (uint32_t) errno;
868
869
0
    libcerror_system_set_error(
870
0
     error,
871
0
     LIBCERROR_ERROR_DOMAIN_IO,
872
0
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
873
0
     *error_code,
874
0
     "%s: unable to unlink file.",
875
0
     function );
876
877
0
    return( -1 );
878
0
  }
879
0
  return( 1 );
880
0
}
881
882
#else
883
#error Missing file remove function
884
#endif
885
886
#if defined( HAVE_WIDE_CHARACTER_TYPE )
887
888
/* Removes a file
889
 * Returns 1 if successful or -1 on error
890
 */
891
int libcfile_file_remove_wide(
892
     const wchar_t *filename,
893
     libcerror_error_t **error )
894
{
895
  static char *function = "libcfile_file_remove_wide";
896
  uint32_t error_code   = 0;
897
898
  if( libcfile_file_remove_wide_with_error_code(
899
       filename,
900
       &error_code,
901
       error ) != 1 )
902
  {
903
    libcerror_error_set(
904
     error,
905
     LIBCERROR_ERROR_DOMAIN_IO,
906
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
907
     "%s: unable to remove file.",
908
     function );
909
910
    return( -1 );
911
  }
912
  return( 1 );
913
}
914
915
#if defined( WINAPI )
916
917
/* Removes a file
918
 * This function uses the WINAPI function for Windows XP (0x0501) or later,
919
 * or tries to dynamically call the function for Windows 2000 (0x0500) or earlier
920
 * Returns 1 if successful or -1 on error
921
 */
922
int libcfile_file_remove_wide_with_error_code(
923
     const wchar_t *filename,
924
     uint32_t *error_code,
925
     libcerror_error_t **error )
926
{
927
  static char *function = "libcfile_file_remove_wide_with_error_code";
928
  BOOL result           = FALSE;
929
930
  if( filename == NULL )
931
  {
932
    libcerror_error_set(
933
     error,
934
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
935
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
936
     "%s: invalid filename.",
937
     function );
938
939
    return( -1 );
940
  }
941
  if( error_code == NULL )
942
  {
943
    libcerror_error_set(
944
     error,
945
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
946
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
947
     "%s: invalid error code.",
948
     function );
949
950
    return( -1 );
951
  }
952
#if ( WINVER <= 0x0500 )
953
  result = libcfile_DeleteFileW(
954
            filename );
955
#else
956
  result = DeleteFileW(
957
            filename );
958
#endif
959
  if( result == 0 )
960
  {
961
    *error_code = GetLastError();
962
963
    libcerror_system_set_error(
964
     error,
965
     LIBCERROR_ERROR_DOMAIN_IO,
966
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
967
     *error_code,
968
     "%s: unable to remove file.",
969
     function );
970
971
    return( -1 );
972
  }
973
  return( 1 );
974
}
975
976
#elif defined( HAVE_UNLINK )
977
978
/* Removes a file
979
 * This function uses the POSIX unlink function or equivalent
980
 * Returns 1 if successful or -1 on error
981
 */
982
int libcfile_file_remove_wide_with_error_code(
983
     const wchar_t *filename,
984
     uint32_t *error_code,
985
     libcerror_error_t **error )
986
{
987
  char *narrow_filename       = NULL;
988
  static char *function       = "libcfile_file_remove_wide_with_error_code";
989
  size_t narrow_filename_size = 0;
990
  size_t filename_size        = 0;
991
  int result                  = 0;
992
993
  if( filename == NULL )
994
  {
995
    libcerror_error_set(
996
     error,
997
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
998
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
999
     "%s: invalid filename.",
1000
     function );
1001
1002
    return( -1 );
1003
  }
1004
  if( error_code == NULL )
1005
  {
1006
    libcerror_error_set(
1007
     error,
1008
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1009
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1010
     "%s: invalid error code.",
1011
     function );
1012
1013
    return( -1 );
1014
  }
1015
  filename_size = 1 + wide_string_length(
1016
                       filename );
1017
1018
  /* Convert the filename to a narrow string
1019
   * if the platform has no wide character open function
1020
   */
1021
  if( libclocale_codepage == 0 )
1022
  {
1023
#if SIZEOF_WCHAR_T == 4
1024
    result = libuna_utf8_string_size_from_utf32(
1025
              (libuna_utf32_character_t *) filename,
1026
              filename_size,
1027
              &narrow_filename_size,
1028
              error );
1029
#elif SIZEOF_WCHAR_T == 2
1030
    result = libuna_utf8_string_size_from_utf16(
1031
              (libuna_utf16_character_t *) filename,
1032
              filename_size,
1033
              &narrow_filename_size,
1034
              error );
1035
#else
1036
#error Unsupported size of wchar_t
1037
#endif /* SIZEOF_WCHAR_T */
1038
  }
1039
  else
1040
  {
1041
#if SIZEOF_WCHAR_T == 4
1042
    result = libuna_byte_stream_size_from_utf32(
1043
              (libuna_utf32_character_t *) filename,
1044
              filename_size,
1045
              libclocale_codepage,
1046
              &narrow_filename_size,
1047
              error );
1048
#elif SIZEOF_WCHAR_T == 2
1049
    result = libuna_byte_stream_size_from_utf16(
1050
              (libuna_utf16_character_t *) filename,
1051
              filename_size,
1052
              libclocale_codepage,
1053
              &narrow_filename_size,
1054
              error );
1055
#else
1056
#error Unsupported size of wchar_t
1057
#endif /* SIZEOF_WCHAR_T */
1058
  }
1059
  if( result != 1 )
1060
  {
1061
    libcerror_error_set(
1062
     error,
1063
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
1064
     LIBCERROR_CONVERSION_ERROR_GENERIC,
1065
     "%s: unable to determine narrow character filename size.",
1066
     function );
1067
1068
    goto on_error;
1069
  }
1070
  narrow_filename = narrow_string_allocate(
1071
                     narrow_filename_size );
1072
1073
  if( narrow_filename == NULL )
1074
  {
1075
    libcerror_error_set(
1076
     error,
1077
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1078
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1079
     "%s: unable to create narrow character filename.",
1080
     function );
1081
1082
    goto on_error;
1083
  }
1084
  if( libclocale_codepage == 0 )
1085
  {
1086
#if SIZEOF_WCHAR_T == 4
1087
    result = libuna_utf8_string_copy_from_utf32(
1088
              (libuna_utf8_character_t *) narrow_filename,
1089
              narrow_filename_size,
1090
              (libuna_utf32_character_t *) filename,
1091
              filename_size,
1092
              error );
1093
#elif SIZEOF_WCHAR_T == 2
1094
    result = libuna_utf8_string_copy_from_utf16(
1095
              (libuna_utf8_character_t *) narrow_filename,
1096
              narrow_filename_size,
1097
              (libuna_utf16_character_t *) filename,
1098
              filename_size,
1099
              error );
1100
#else
1101
#error Unsupported size of wchar_t
1102
#endif /* SIZEOF_WCHAR_T */
1103
  }
1104
  else
1105
  {
1106
#if SIZEOF_WCHAR_T == 4
1107
    result = libuna_byte_stream_copy_from_utf32(
1108
              (uint8_t *) narrow_filename,
1109
              narrow_filename_size,
1110
              libclocale_codepage,
1111
              (libuna_utf32_character_t *) filename,
1112
              filename_size,
1113
              error );
1114
#elif SIZEOF_WCHAR_T == 2
1115
    result = libuna_byte_stream_copy_from_utf16(
1116
              (uint8_t *) narrow_filename,
1117
              narrow_filename_size,
1118
              libclocale_codepage,
1119
              (libuna_utf16_character_t *) filename,
1120
              filename_size,
1121
              error );
1122
#else
1123
#error Unsupported size of wchar_t
1124
#endif /* SIZEOF_WCHAR_T */
1125
  }
1126
  if( result != 1 )
1127
  {
1128
    libcerror_error_set(
1129
     error,
1130
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
1131
     LIBCERROR_CONVERSION_ERROR_GENERIC,
1132
     "%s: unable to set narrow character filename.",
1133
     function );
1134
1135
    goto on_error;
1136
  }
1137
  if( unlink(
1138
       narrow_filename ) != 0 )
1139
  {
1140
    *error_code = (uint32_t) errno;
1141
1142
    libcerror_system_set_error(
1143
     error,
1144
     LIBCERROR_ERROR_DOMAIN_IO,
1145
     LIBCERROR_IO_ERROR_UNLINK_FAILED,
1146
     *error_code,
1147
     "%s: unable to unlink file.",
1148
     function );
1149
1150
    goto on_error;
1151
  }
1152
  memory_free(
1153
   narrow_filename );
1154
1155
  return( 1 );
1156
1157
on_error:
1158
  if( narrow_filename != NULL )
1159
  {
1160
    memory_free(
1161
     narrow_filename );
1162
  }
1163
  return( -1 );
1164
}
1165
1166
#else
1167
#error Missing file remove wide function
1168
#endif
1169
1170
#endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
1171