1 /*
2 * Support functions
3 *
4 * Copyright (C) 2008-2020, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <memory.h>
24 #include <narrow_string.h>
25 #include <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28
29 #if defined( HAVE_SYS_STAT_H )
30 #include <sys/stat.h>
31 #endif
32
33 #if defined( HAVE_ERRNO_H )
34 #include <errno.h>
35 #endif
36
37 #if defined( HAVE_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 */
libcfile_get_version(void)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 */
libcfile_get_codepage(int * codepage,libcerror_error_t ** error)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 */
libcfile_set_codepage(int codepage,libcerror_error_t ** error)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 */
libcfile_file_exists(const char * filename,libcerror_error_t ** error)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 */
libcfile_file_exists(const char * filename,libcerror_error_t ** error)290 int libcfile_file_exists(
291 const char *filename,
292 libcerror_error_t **error )
293 {
294 struct stat file_statistics;
295
296 static char *function = "libcfile_file_exists";
297 int result = 0;
298
299 if( filename == NULL )
300 {
301 libcerror_error_set(
302 error,
303 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
304 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
305 "%s: invalid filename.",
306 function );
307
308 return( -1 );
309 }
310 if( memory_set(
311 &file_statistics,
312 0,
313 sizeof( struct stat ) ) == NULL )
314 {
315 libcerror_error_set(
316 error,
317 LIBCERROR_ERROR_DOMAIN_MEMORY,
318 LIBCERROR_MEMORY_ERROR_SET_FAILED,
319 "%s: unable to clear file statistics.",
320 function );
321
322 return( -1 );
323 }
324 result = stat(
325 filename,
326 &file_statistics );
327
328 if( result != 0 )
329 {
330 switch( errno )
331 {
332 case EACCES:
333 result = 1;
334
335 break;
336
337 case ENOENT:
338 result = 0;
339
340 break;
341
342 default:
343 libcerror_system_set_error(
344 error,
345 LIBCERROR_ERROR_DOMAIN_IO,
346 LIBCERROR_IO_ERROR_GENERIC,
347 errno,
348 "%s: unable to stat file: %" PRIs_SYSTEM ".",
349 function,
350 filename );
351
352 return( -1 );
353 }
354 }
355 else
356 {
357 result = 1;
358 }
359 return( result );
360 }
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 */
libcfile_file_exists_wide(const wchar_t * filename,libcerror_error_t ** error)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 */
libcfile_file_exists_wide(const wchar_t * filename,libcerror_error_t ** error)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 */
libcfile_file_remove(const char * filename,libcerror_error_t ** error)744 int libcfile_file_remove(
745 const char *filename,
746 libcerror_error_t **error )
747 {
748 static char *function = "libcfile_file_remove";
749 uint32_t error_code = 0;
750
751 if( libcfile_file_remove_with_error_code(
752 filename,
753 &error_code,
754 error ) != 1 )
755 {
756 libcerror_error_set(
757 error,
758 LIBCERROR_ERROR_DOMAIN_IO,
759 LIBCERROR_IO_ERROR_UNLINK_FAILED,
760 "%s: unable to remove file.",
761 function );
762
763 return( -1 );
764 }
765 return( 1 );
766 }
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 */
libcfile_file_remove_with_error_code(const char * filename,uint32_t * error_code,libcerror_error_t ** error)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 */
libcfile_file_remove_with_error_code(const char * filename,uint32_t * error_code,libcerror_error_t ** error)835 int libcfile_file_remove_with_error_code(
836 const char *filename,
837 uint32_t *error_code,
838 libcerror_error_t **error )
839 {
840 static char *function = "libcfile_file_remove_with_error_code";
841
842 if( filename == NULL )
843 {
844 libcerror_error_set(
845 error,
846 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
847 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
848 "%s: invalid filename.",
849 function );
850
851 return( -1 );
852 }
853 if( error_code == NULL )
854 {
855 libcerror_error_set(
856 error,
857 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
858 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
859 "%s: invalid error code.",
860 function );
861
862 return( -1 );
863 }
864 if( unlink(
865 filename ) != 0 )
866 {
867 *error_code = (uint32_t) errno;
868
869 libcerror_system_set_error(
870 error,
871 LIBCERROR_ERROR_DOMAIN_IO,
872 LIBCERROR_IO_ERROR_UNLINK_FAILED,
873 *error_code,
874 "%s: unable to unlink file.",
875 function );
876
877 return( -1 );
878 }
879 return( 1 );
880 }
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 */
libcfile_file_remove_wide(const wchar_t * filename,libcerror_error_t ** error)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 */
libcfile_file_remove_wide_with_error_code(const wchar_t * filename,uint32_t * error_code,libcerror_error_t ** error)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 */
libcfile_file_remove_wide_with_error_code(const wchar_t * filename,uint32_t * error_code,libcerror_error_t ** error)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
1172