1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
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 */
15
16 #include "ecmascript/platform/file.h"
17
18 #include <windef.h>
19 #include <winbase.h>
20 #include <winnt.h>
21 #include <climits>
22 #include <fileapi.h>
23
24 #ifdef ERROR
25 #undef ERROR
26 #endif
27
28 #ifdef VOID
29 #undef VOID
30 #endif
31
32 #ifdef CONST
33 #undef CONST
34 #endif
35
36 #include "ecmascript/ecma_macros.h"
37 #include "ecmascript/ecma_string.h"
38 #include "ecmascript/js_tagged_value-inl.h"
39 #include "ecmascript/log_wrapper.h"
40 #include "ecmascript/platform/map.h"
41
42 namespace panda::ecmascript {
GetFileDelimiter()43 std::string GetFileDelimiter()
44 {
45 return ";";
46 }
47
GetPathSeparator()48 std::string GetPathSeparator()
49 {
50 return "\\";
51 }
52
RealPath(const std::string & path,std::string & realPath,bool readOnly)53 bool RealPath(const std::string &path, std::string &realPath, [[maybe_unused]] bool readOnly)
54 {
55 realPath = "";
56 if (path.empty() || path.size() > PATH_MAX) {
57 LOG_ECMA(WARN) << "File path is illeage";
58 return false;
59 }
60 char buffer[PATH_MAX] = { '\0' };
61 if (!_fullpath(buffer, path.c_str(), sizeof(buffer) - 1)) {
62 LOG_ECMA(WARN) << "File path:" << path << " full path failure";
63 return false;
64 }
65 realPath = std::string(buffer);
66 return true;
67 }
68
DPrintf(fd_t fd,const std::string & buffer)69 void DPrintf(fd_t fd, const std::string &buffer)
70 {
71 LOG_ECMA(DEBUG) << "Unsupport dprintf fd(" << fd << ") in windows, buffer:" << buffer;
72 }
73
FSync(fd_t fd)74 void FSync(fd_t fd)
75 {
76 LOG_ECMA(DEBUG) << "Unsupport fsync fd(" << fd << ") in windows";
77 }
78
Close(fd_t fd)79 void Close(fd_t fd)
80 {
81 CloseHandle(fd);
82 }
83
FileMap(const char * fileName,int flag,int prot,int64_t offset)84 MemMap FileMap(const char *fileName, int flag, int prot, int64_t offset)
85 {
86 if (prot == PAGE_PROT_READWRITE) {
87 flag |= FILE_RDONLY | FILE_WRONLY;
88 }
89 fd_t fd = CreateFile(fileName, flag, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
90 if (fd == INVALID_FD) {
91 LOG_ECMA(ERROR) << fileName << " file open failed";
92 return MemMap();
93 }
94
95 LARGE_INTEGER fileSize;
96 if (!GetFileSizeEx(fd, &fileSize)) {
97 CloseHandle(fd);
98 LOG_ECMA(ERROR) << "GetFileSize failed with error code:" << GetLastError();
99 return MemMap();
100 }
101 auto size = fileSize.QuadPart;
102 if (size <= 0) {
103 CloseHandle(fd);
104 LOG_HOST_TOOL_ERROR << fileName << " file is empty";
105 return MemMap();
106 }
107
108 // 32: high 32 bits
109 fd_t extra = CreateFileMapping(fd, NULL, prot, size >> 32, size & 0xffffffff, nullptr);
110 if (extra == nullptr) {
111 CloseHandle(fd);
112 LOG_ECMA(ERROR) << "CreateFileMapping failed with error code:" << GetLastError();
113 return MemMap();
114 }
115 int accessor = (prot == PAGE_PROT_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;
116 void *addr = MapViewOfFile(extra, accessor, offset >> 32, offset & 0xffffffff, size);
117 CloseHandle(extra);
118 CloseHandle(fd);
119 if (addr == nullptr) {
120 LOG_ECMA(ERROR) << "MapViewOfFile failed with error code:" << GetLastError();
121 }
122 return MemMap(addr, size);
123 }
124
FileMapForAlignAddress(const char * fileName,int flag,int prot,int64_t offset,uint32_t offStart)125 MemMap FileMapForAlignAddress(const char *fileName, int flag, int prot,
126 int64_t offset, uint32_t offStart)
127 {
128 // AOT not used, previewer used
129 LOG_ECMA(INFO) << "Don't used fileName:" << fileName << " flag:" << flag
130 << " prot:" << prot << " offset:" << offset << " offStart:" << offStart;
131 return MemMap();
132 }
133
FileUnMap(MemMap addr)134 int FileUnMap(MemMap addr)
135 {
136 if (UnmapViewOfFile(addr.GetOriginAddr()) == 0) {
137 return FILE_FAILED;
138 }
139 return FILE_SUCCESS;
140 }
141
ResolveFilenameFromNative(JSThread * thread,JSTaggedValue dirname,JSTaggedValue request)142 JSHandle<EcmaString> ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname,
143 JSTaggedValue request)
144 {
145 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
146 CString fullname;
147 CString resolvedFilename;
148 CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject()));
149 CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject()));
150 int suffixEnd = static_cast<int>(requestStr.find_last_of('.'));
151 if (suffixEnd == -1) {
152 RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
153 }
154 if (requestStr[1] == ':') { // absoluteFilePath
155 fullname = requestStr.substr(0, suffixEnd) + ".abc";
156 } else {
157 int pos = static_cast<int>(dirnameStr.find_last_of('\\'));
158 if (pos == -1) {
159 RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
160 }
161 fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc";
162 }
163
164 std::string relativePath = ConvertToStdString(fullname);
165 std::string absPath = "";
166 if (RealPath(relativePath, absPath)) {
167 resolvedFilename = ConvertToString(absPath);
168 return factory->NewFromUtf8(resolvedFilename);
169 }
170 CString msg = "resolve absolute path fail";
171 THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, EcmaString, msg.c_str());
172 }
173
FileExist(const char * filename)174 bool FileExist(const char *filename)
175 {
176 return (_access(filename, 0) != -1);
177 }
178
Unlink(const char * filename)179 int Unlink(const char *filename)
180 {
181 return _unlink(filename);
182 }
183
TryToRemoveSO(JSThread * thread,JSHandle<SourceTextModule> module)184 bool TryToRemoveSO([[maybe_unused]] JSThread *thread, [[maybe_unused]] JSHandle<SourceTextModule> module)
185 {
186 return false;
187 }
188
LoadLib(const std::string & liname)189 void *LoadLib([[maybe_unused]] const std::string &liname)
190 {
191 LOG_ECMA(INFO) << "Unsupport LoadLib";
192 return nullptr;
193 }
194
FindSymbol(void * handle,const char * symbol)195 void *FindSymbol([[maybe_unused]] void *handle, [[maybe_unused]] const char *symbol)
196 {
197 LOG_ECMA(INFO) << "Unsupport FindSymbol";
198 return nullptr;
199 }
200
CloseLib(void * handle)201 int CloseLib([[maybe_unused]] void *handle)
202 {
203 LOG_ECMA(INFO) << "Unsupport CloseLib";
204 return 0;
205 }
206 } // namespace panda::ecmascript
207