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