]>
Commit | Line | Data |
---|---|---|
09487816 AP |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include "internal/cryptlib.h" | |
11 | ||
12 | #if !defined(OPENSSL_NO_STDIO) | |
13 | ||
14 | # include <stdio.h> | |
15 | ||
16 | FILE *openssl_fopen(const char *filename, const char *mode) | |
17 | { | |
18 | FILE *file = NULL; | |
19 | # if defined(_WIN32) && defined(CP_UTF8) | |
20 | int sz, len_0 = (int)strlen(filename) + 1; | |
21 | DWORD flags; | |
22 | ||
23 | /* | |
24 | * Basically there are three cases to cover: a) filename is | |
25 | * pure ASCII string; b) actual UTF-8 encoded string and | |
26 | * c) locale-ized string, i.e. one containing 8-bit | |
27 | * characters that are meaningful in current system locale. | |
28 | * If filename is pure ASCII or real UTF-8 encoded string, | |
29 | * MultiByteToWideChar succeeds and _wfopen works. If | |
30 | * filename is locale-ized string, chances are that | |
31 | * MultiByteToWideChar fails reporting | |
32 | * ERROR_NO_UNICODE_TRANSLATION, in which case we fall | |
33 | * back to fopen... | |
34 | */ | |
35 | if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS), | |
36 | filename, len_0, NULL, 0)) > 0 || | |
37 | (GetLastError() == ERROR_INVALID_FLAGS && | |
38 | (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), | |
39 | filename, len_0, NULL, 0)) > 0) | |
40 | ) { | |
41 | WCHAR wmode[8]; | |
42 | WCHAR *wfilename = _alloca(sz * sizeof(WCHAR)); | |
43 | ||
44 | if (MultiByteToWideChar(CP_UTF8, flags, | |
45 | filename, len_0, wfilename, sz) && | |
46 | MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, | |
47 | wmode, OSSL_NELEM(wmode)) && | |
48 | (file = _wfopen(wfilename, wmode)) == NULL && | |
49 | (errno == ENOENT || errno == EBADF) | |
50 | ) { | |
51 | /* | |
52 | * UTF-8 decode succeeded, but no file, filename | |
53 | * could still have been locale-ized... | |
54 | */ | |
55 | file = fopen(filename, mode); | |
56 | } | |
57 | } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { | |
58 | file = fopen(filename, mode); | |
59 | } | |
60 | # elif defined(__DJGPP__) | |
61 | { | |
62 | char *newname = NULL; | |
63 | ||
64 | if (!HAS_LFN_SUPPORT(filename)) { | |
65 | char *iterator; | |
66 | char lastchar; | |
67 | ||
68 | newname = OPENSSL_malloc(strlen(filename) + 1); | |
69 | if (newname == NULL) | |
70 | return NULL; | |
71 | ||
e8aa8b6c | 72 | for (iterator = newname, lastchar = '\0'; |
09487816 AP |
73 | *filename; filename++, iterator++) { |
74 | if (lastchar == '/' && filename[0] == '.' | |
75 | && filename[1] != '.' && filename[1] != '/') { | |
76 | /* Leading dots are not permitted in plain DOS. */ | |
77 | *iterator = '_'; | |
78 | } else { | |
79 | *iterator = *filename; | |
80 | } | |
81 | lastchar = *filename; | |
82 | } | |
83 | *iterator = '\0'; | |
84 | filename = newname; | |
85 | } | |
86 | file = fopen(filename, mode); | |
87 | ||
88 | OPENSSL_free(newname); | |
89 | } | |
90 | # else | |
91 | file = fopen(filename, mode); | |
92 | # endif | |
93 | return file; | |
94 | } | |
95 | ||
96 | #else | |
97 | ||
98 | void *openssl_fopen(const char *filename, const char *mode) | |
99 | { | |
100 | return NULL; | |
101 | } | |
102 | ||
103 | #endif |