diff options
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/bio/bss_file.c')
| -rw-r--r-- | Cryptlib/OpenSSL/crypto/bio/bss_file.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/Cryptlib/OpenSSL/crypto/bio/bss_file.c b/Cryptlib/OpenSSL/crypto/bio/bss_file.c index 81e5b940..153b6fa2 100644 --- a/Cryptlib/OpenSSL/crypto/bio/bss_file.c +++ b/Cryptlib/OpenSSL/crypto/bio/bss_file.c @@ -118,9 +118,53 @@ static BIO_METHOD methods_filep = { BIO *BIO_new_file(const char *filename, const char *mode) { BIO *ret; - FILE *file; - - if ((file = fopen(filename, mode)) == NULL) { + FILE *file = NULL; + +# if defined(_WIN32) && defined(CP_UTF8) + int sz, len_0 = (int)strlen(filename) + 1; + DWORD flags; + + /* + * Basically there are three cases to cover: a) filename is + * pure ASCII string; b) actual UTF-8 encoded string and + * c) locale-ized string, i.e. one containing 8-bit + * characters that are meaningful in current system locale. + * If filename is pure ASCII or real UTF-8 encoded string, + * MultiByteToWideChar succeeds and _wfopen works. If + * filename is locale-ized string, chances are that + * MultiByteToWideChar fails reporting + * ERROR_NO_UNICODE_TRANSLATION, in which case we fall + * back to fopen... + */ + if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS), + filename, len_0, NULL, 0)) > 0 || + (GetLastError() == ERROR_INVALID_FLAGS && + (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), + filename, len_0, NULL, 0)) > 0) + ) { + WCHAR wmode[8]; + WCHAR *wfilename = _alloca(sz * sizeof(WCHAR)); + + if (MultiByteToWideChar(CP_UTF8, flags, + filename, len_0, wfilename, sz) && + MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, + wmode, sizeof(wmode) / sizeof(wmode[0])) && + (file = _wfopen(wfilename, wmode)) == NULL && + (errno == ENOENT || errno == EBADF) + ) { + /* + * UTF-8 decode succeeded, but no file, filename + * could still have been locale-ized... + */ + file = fopen(filename, mode); + } + } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { + file = fopen(filename, mode); + } +# else + file = fopen(filename, mode); +# endif + if (file == NULL) { SYSerr(SYS_F_FOPEN, get_last_sys_error()); ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); if (errno == ENOENT) @@ -129,7 +173,7 @@ BIO *BIO_new_file(const char *filename, const char *mode) BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); return (NULL); } - if ((ret = BIO_new(BIO_s_file_internal())) == NULL) { + if ((ret = BIO_new(BIO_s_file())) == NULL) { fclose(file); return (NULL); } @@ -284,9 +328,7 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) _setmode(fd, _O_BINARY); # elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) int fd = fileno((FILE *)ptr); - /* - * Under CLib there are differences in file modes - */ + /* Under CLib there are differences in file modes */ if (num & BIO_FP_TEXT) setmode(fd, O_TEXT); else @@ -304,7 +346,7 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr) } else _setmode(fd, _O_BINARY); } -# elif defined(OPENSSL_SYS_OS2) +# elif defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_WIN32_CYGWIN) int fd = fileno((FILE *)ptr); if (num & BIO_FP_TEXT) setmode(fd, O_TEXT); @@ -418,7 +460,7 @@ static int MS_CALLBACK file_puts(BIO *bp, const char *str) return (ret); } -#else +# else BIO_METHOD *BIO_s_file(void) { |
