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