• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "aemu/base/testing/file_io.h"
15 #include "aemu/base/system/Win32UnicodeString.h"
16 
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #ifndef _MSC_VER
24 #include <unistd.h>
25 #endif
26 
27 #ifdef _WIN32
28 #include <direct.h>
29 #include <windows.h>
30 #include <share.h>
31 #include "aemu/base/files/PathUtils.h"
32 using android::base::PathUtils;
33 using android::base::Win32UnicodeString;
34 // using android::base::ScopedCPtr;
35 #endif
36 
37 // Provide different macros for different number of string arguments where each
38 // string argument requires conversion
39 #ifdef _WIN32
40 #define WIDEN_CALL_1(func, str1, ...) \
41       _w ## func(Win32UnicodeString(str1).c_str() , ##__VA_ARGS__)
42 #define WIDEN_CALL_2(func, str1, str2, ...) \
43       _w ## func(Win32UnicodeString(str1).c_str(), \
44                  Win32UnicodeString(str2).c_str() , ##__VA_ARGS__)
45 #else
46 #define WIDEN_CALL_1(func, str1, ...) func(str1 , ##__VA_ARGS__)
47 #define WIDEN_CALL_2(func, str1, str2, ...) func(str1, str2 , ##__VA_ARGS__)
48 #endif
49 
android_fopen(const char * path,const char * mode)50 FILE* android_fopen(const char* path, const char* mode) {
51 #if _MSC_VER
52     Win32UnicodeString wmode(mode);
53     auto normalized = PathUtils::recompose(PathUtils::decompose(path));
54     Win32UnicodeString wpath(normalized);
55 
56     const wchar_t* wide_path = wpath.c_str();
57     const wchar_t* wide_mode = wmode.c_str();
58 
59     FILE* res = NULL;
60     int err = _wfopen_s(&res, wide_path, wide_mode);
61     if (err != 0) {
62         printf("Failed to open %s, err: %d\n", path, err);
63     }
64     return res;
65 #else
66     return WIDEN_CALL_2(fopen, path, mode);
67 #endif
68 }
69 
android_popen(const char * path,const char * mode)70 FILE* android_popen(const char* path, const char* mode) {
71     return WIDEN_CALL_2(popen, path, mode);
72 }
73 
fdSetCloexec(int fd)74 void fdSetCloexec(int fd) {
75 #ifndef _WIN32
76     int f = ::fcntl(fd, F_GETFD);
77     ::fcntl(fd, F_SETFD, f | FD_CLOEXEC);
78 #endif  // !_WIN32
79 }
80 
android_open_without_mode(const char * path,int flags)81 int android_open_without_mode(const char* path, int flags) {
82     int res = WIDEN_CALL_1(open, path, flags | O_CLOEXEC);
83     fdSetCloexec(res);
84     return res;
85 }
86 
android_open_with_mode(const char * path,int flags,mode_t mode)87 int android_open_with_mode(const char* path, int flags, mode_t mode) {
88     int res = WIDEN_CALL_1(open, path, flags | O_CLOEXEC, mode);
89     fdSetCloexec(res);
90     return res;
91 }
92 
93 #ifdef _WIN32
android_stat(const char * path,struct _stati64 * buf)94 int android_stat(const char* path, struct _stati64* buf) {
95   return _wstati64(Win32UnicodeString(path).c_str(),buf);
96 }
97 #else
android_stat(const char * path,struct stat * buf)98 int android_stat(const char* path, struct stat* buf) {
99     return stat(path, buf);
100 }
101 #endif
102 
103 #ifndef _WIN32
android_lstat(const char * path,struct stat * buf)104 int android_lstat(const char* path, struct stat* buf) {
105     return lstat(path, buf);
106 }
107 #endif
108 
android_access(const char * path,int mode)109 int android_access(const char* path, int mode) {
110     return WIDEN_CALL_1(access, path, mode);
111 }
112 
113 #ifdef _WIN32
114 // The Windows version does not have a mode parameter so just drop that name to
115 // avoid compiler warnings about unused parameters
android_mkdir(const char * path,mode_t)116 int android_mkdir(const char* path, mode_t) {
117     return _wmkdir(Win32UnicodeString(path).c_str());
118 }
119 #else
android_mkdir(const char * path,mode_t mode)120 int android_mkdir(const char* path, mode_t mode) {
121     return mkdir(path, mode);
122 }
123 #endif
124 
android_creat(const char * path,mode_t mode)125 int android_creat(const char* path, mode_t mode) {
126 #ifndef _WIN32
127     return android_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
128 #else
129     int fd = -1;
130     Win32UnicodeString unipath(path);
131     // Be careful here! The security model in windows is very different.
132     _wsopen_s(&fd, unipath.c_str(), _O_CREAT | _O_BINARY | _O_TRUNC | _O_WRONLY, _SH_DENYNO, _S_IWRITE);
133     return fd;
134 #endif
135 }
136 
android_unlink(const char * path)137 int android_unlink(const char* path) {
138     return WIDEN_CALL_1(unlink, path);
139 }
140 
android_chmod(const char * path,mode_t mode)141 int android_chmod(const char* path, mode_t mode) {
142     return WIDEN_CALL_1(chmod, path, mode);
143 }
144 
android_rmdir(const char * path)145 int android_rmdir(const char* path) {
146 #ifdef _MSC_VER
147    // Callers expect 0 on success, win api returns true on success.
148    return !RemoveDirectoryW(Win32UnicodeString(path).c_str());
149 #else
150     return WIDEN_CALL_1(rmdir, path);
151 #endif
152 }
153 // The code below uses the fact that GCC supports something called weak linking.
154 // Several functions in glibc are weakly linked which means that if the same
155 // function name is found in the application binary that function will be used
156 // instead. On Windows we use this to change these calls to call the wchar_t
157 // equivalent function with the parameter converted from UTF-8 to UTF-16.
158 //
159 // Unfortunately stat is not weakly linked which is why it is not listed here
160 // and any code that calls stat should use android_stat instead.
161 // TODO(joshuaduong): Looks like we can't use weak linking with MSVC. Either
162 // need to find another way to do this or rename all of these calls to
163 // android_*.
164 #if defined(_WIN32) && !defined(_MSC_VER)
165 
166 // getcwd cannot use the same macro as the other calls because it places data
167 // in one of its parameters and it returns a char pointer, not a result code
getcwd(char * buffer,int maxlen)168 char* __cdecl getcwd(char* buffer, int maxlen) {
169     ScopedCPtr<wchar_t> wideCwd(_wgetcwd(nullptr, 0));
170     if (wideCwd.get() == nullptr) {
171         return nullptr;
172     }
173     if (buffer == nullptr) {
174         // This is a valid use case and we need to allocate memory and return it
175         auto narrowCwd = Win32UnicodeString::convertToUtf8(wideCwd.get());
176         return strdup(narrowCwd.c_str());
177     }
178 
179     int written = Win32UnicodeString::convertToUtf8(buffer,
180                                                     maxlen,
181                                                     wideCwd.get());
182     if (written < 0 || written >= maxlen) {
183         return nullptr;
184     }
185     return buffer;
186 }
187 
remove(const char * path)188 int __cdecl remove(const char* path) {
189     return WIDEN_CALL_1(remove, path);
190 }
191 
rmdir(const char * dirname)192 int __cdecl rmdir(const char* dirname) {
193     return WIDEN_CALL_1(rmdir, dirname);
194 }
195 
chmod(const char * filename,int pmode)196 int __cdecl chmod(const char* filename, int pmode) {
197     return WIDEN_CALL_1(chmod, filename, pmode);
198 }
199 
unlink(const char * filename)200 int __cdecl unlink(const char* filename) {
201     return WIDEN_CALL_1(unlink, filename);
202 }
203 
mkdir(const char * dirname)204 int __cdecl mkdir(const char* dirname) {
205     return WIDEN_CALL_1(mkdir, dirname);
206 }
207 
creat(const char * path,int mode)208 int __cdecl creat(const char* path, int mode) {
209     return WIDEN_CALL_1(creat, path, mode);
210 }
211 
access(const char * path,int mode)212 int __cdecl access(const char* path, int mode) {
213     return WIDEN_CALL_1(access, path, mode);
214 }
215 
open(const char * pathname,int flags,...)216 int __cdecl open(const char* pathname, int flags, ...) {
217     va_list ap;
218 
219     // Since open comes in two versions and C does not support function
220     // overloading we use varargs for the mode parameters instead.
221     va_start(ap, flags);
222     int result = WIDEN_CALL_1(open, pathname, flags, va_arg(ap, int));
223     va_end(ap);
224     return result;
225 }
226 
fopen(const char * path,const char * mode)227 FILE* __cdecl fopen(const char* path, const char* mode) {
228     return WIDEN_CALL_2(fopen, path, mode);
229 }
230 
231 #endif  // _WIN32 && !_MSC_VER
232