• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RealPath(const std::string & path,std::string & realPath,bool readOnly)48 bool RealPath(const std::string &path, std::string &realPath, [[maybe_unused]] bool readOnly)
49 {
50     realPath = "";
51     if (path.empty() || path.size() > PATH_MAX) {
52         LOG_ECMA(WARN) << "File path is illeage";
53         return false;
54     }
55     char buffer[PATH_MAX] = { '\0' };
56     if (!_fullpath(buffer, path.c_str(), sizeof(buffer) - 1)) {
57         LOG_ECMA(WARN) << "File path:" << path << " full path failure";
58         return false;
59     }
60     realPath = std::string(buffer);
61     return true;
62 }
63 
DPrintf(fd_t fd,const std::string & buffer)64 void DPrintf(fd_t fd, const std::string &buffer)
65 {
66     LOG_ECMA(DEBUG) << "Unsupport dprintf fd(" << fd << ") in windows, buffer:" << buffer;
67 }
68 
FSync(fd_t fd)69 void FSync(fd_t fd)
70 {
71     LOG_ECMA(DEBUG) << "Unsupport fsync fd(" << fd << ") in windows";
72 }
73 
Close(fd_t fd)74 void Close(fd_t fd)
75 {
76     CloseHandle(fd);
77 }
78 
FileMap(const char * fileName,int flag,int prot,int64_t offset)79 MemMap FileMap(const char *fileName, int flag, int prot, int64_t offset)
80 {
81     fd_t fd = CreateFile(fileName, flag, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
82     if (fd == INVALID_FD) {
83         LOG_ECMA(ERROR) << fileName << " file open failed";
84         return MemMap();
85     }
86 
87     LARGE_INTEGER fileSize;
88     if (!GetFileSizeEx(fd, &fileSize)) {
89         CloseHandle(fd);
90         LOG_ECMA(ERROR) << "GetFileSize failed with error code:" << GetLastError();
91         return MemMap();
92     }
93     auto size = fileSize.QuadPart;
94     if (size <= 0) {
95         CloseHandle(fd);
96         LOG_HOST_TOOL_ERROR << fileName << " file is empty";
97         return MemMap();
98     }
99 
100     // 32: high 32 bits
101     fd_t extra = CreateFileMapping(fd, NULL, prot, size >> 32, size & 0xffffffff, nullptr);
102     if (extra == nullptr) {
103         CloseHandle(fd);
104         LOG_ECMA(ERROR) << "CreateFileMapping failed with error code:" << GetLastError();
105         return MemMap();
106     }
107     int accessor = (prot == PAGE_PROT_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;
108     void *addr = MapViewOfFile(extra, accessor, offset >> 32, offset & 0xffffffff, size);
109     CloseHandle(extra);
110     CloseHandle(fd);
111     if (addr == nullptr) {
112         LOG_ECMA(ERROR) << "MapViewOfFile failed with error code:" << GetLastError();
113     }
114     return MemMap(addr, size);
115 }
116 
FileUnMap(MemMap addr)117 int FileUnMap(MemMap addr)
118 {
119     if (UnmapViewOfFile(addr.GetOriginAddr()) == 0) {
120         return FILE_FAILED;
121     }
122     return FILE_SUCCESS;
123 }
124 
ResolveFilenameFromNative(JSThread * thread,JSTaggedValue dirname,JSTaggedValue request)125 JSHandle<EcmaString> ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname,
126                                                JSTaggedValue request)
127 {
128     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
129     CString fullname;
130     CString resolvedFilename;
131     CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject()));
132     CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject()));
133     int suffixEnd = static_cast<int>(requestStr.find_last_of('.'));
134     if (suffixEnd == -1) {
135         RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
136     }
137     if (requestStr[1] == ':') { // absoluteFilePath
138         fullname = requestStr.substr(0, suffixEnd) + ".abc";
139     } else {
140         int pos = static_cast<int>(dirnameStr.find_last_of('\\'));
141         if (pos == -1) {
142             RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
143         }
144         fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc";
145     }
146 
147     std::string relativePath = CstringConvertToStdString(fullname);
148     std::string absPath = "";
149     if (RealPath(relativePath, absPath)) {
150         resolvedFilename = ConvertToString(absPath);
151         return factory->NewFromUtf8(resolvedFilename);
152     }
153     CString msg = "resolve absolute path fail";
154     THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, EcmaString, msg.c_str());
155 }
156 }  // namespace panda::ecmascript
157