-
Notifications
You must be signed in to change notification settings - Fork 81
Expand file tree
/
Copy patho_fopen.c
More file actions
131 lines (117 loc) · 4.36 KB
/
o_fopen.c
File metadata and controls
131 lines (117 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
# if defined(__linux) || defined(__sun) || defined(__hpux)
/*
* Following definition aliases fopen to fopen64 on above mentioned
* platforms. This makes it possible to open and sequentially access files
* larger than 2GB from 32-bit application. It does not allow one to traverse
* them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit
* platform permits that, not with fseek/ftell. Not to mention that breaking
* 2GB limit for seeking would require surgery to *our* API. But sequential
* access suffices for practical cases when you can run into large files,
* such as fingerprinting, so we can let API alone. For reference, the list
* of 32-bit platforms which allow for sequential access of large files
* without extra "magic" comprise *BSD, Darwin, IRIX...
*/
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# endif
#include "e_os.h"
#include "internal/cryptlib.h"
#if !defined(OPENSSL_NO_STDIO)
# include <stdio.h>
# ifdef __DJGPP__
# include <unistd.h>
# endif
FILE *openssl_fopen(const char *filename, const char *mode)
{
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, OSSL_NELEM(wmode)) &&
(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);
}
# elif defined(__DJGPP__)
{
char *newname = NULL;
if (pathconf(filename, _PC_NAME_MAX) <= 12) { /* 8.3 file system? */
char *iterator;
char lastchar;
if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (iterator = newname, lastchar = '\0';
*filename; filename++, iterator++) {
if (lastchar == '/' && filename[0] == '.'
&& filename[1] != '.' && filename[1] != '/') {
/* Leading dots are not permitted in plain DOS. */
*iterator = '_';
} else {
*iterator = *filename;
}
lastchar = *filename;
}
*iterator = '\0';
filename = newname;
}
file = fopen(filename, mode);
OPENSSL_free(newname);
}
# else
file = fopen(filename, mode);
# endif
return file;
}
#else
void *openssl_fopen(const char *filename, const char *mode)
{
#ifdef SGXSSL_FIPS
unsigned long* ret = sgxssl_fopen(filename, mode);
return ret;
#else
return NULL;
#endif
}
#endif