/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 | | |