• 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 <cerrno>
19 #include <climits>
20 #include <sys/mman.h>
21 #include <unistd.h>
22 
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/ecma_macros.h"
25 #include "ecmascript/log_wrapper.h"
26 #include "ecmascript/platform/map.h"
27 
28 namespace panda::ecmascript {
GetFileDelimiter()29 std::string GetFileDelimiter()
30 {
31     return ":";
32 }
33 
RealPath(const std::string & path,std::string & realPath,bool readOnly)34 bool RealPath(const std::string &path, std::string &realPath, bool readOnly)
35 {
36     if (path.empty() || path.size() > PATH_MAX) {
37         LOG_ECMA(WARN) << "File path is illeage";
38         return false;
39     }
40     char buffer[PATH_MAX] = { '\0' };
41     if (!realpath(path.c_str(), buffer)) {
42         // Maybe file does not exist.
43         if (!readOnly && errno == ENOENT) {
44             realPath = path;
45             return true;
46         }
47         LOG_ECMA(ERROR) << "File path:" << path << " realpath failure";
48         return false;
49     }
50     realPath = std::string(buffer);
51     return true;
52 }
53 
DPrintf(fd_t fd,const std::string & buffer)54 void DPrintf(fd_t fd, const std::string &buffer)
55 {
56     int ret = dprintf(fd, "%s", buffer.c_str());
57     if (ret < 0) {
58         LOG_ECMA(DEBUG) << "dprintf fd(" << fd << ") failed";
59     }
60 }
61 
FSync(fd_t fd)62 void FSync(fd_t fd)
63 {
64     int ret = fsync(fd);
65     if (ret < 0) {
66         LOG_ECMA(DEBUG) << "fsync fd(" << fd << ") failed";
67     }
68 }
69 
Close(fd_t fd)70 void Close(fd_t fd)
71 {
72     close(fd);
73 }
74 
FileMap(const char * fileName,int flag,int prot,int64_t offset)75 MemMap FileMap(const char *fileName, int flag, int prot, int64_t offset)
76 {
77     fd_t fd = open(fileName, flag);
78     if (fd == INVALID_FD) {
79         LOG_ECMA(ERROR) << fileName << " file open failed";
80         return MemMap();
81     }
82 
83     size_t size = static_cast<size_t>(lseek(fd, 0, SEEK_END));
84     if (size <= 0) {
85         close(fd);
86         LOG_ECMA(ERROR) << fileName << " file is empty";
87         return MemMap();
88     }
89 
90     void *addr = mmap(nullptr, size, prot, MAP_PRIVATE, fd, offset);
91     close(fd);
92     return MemMap(addr, size);
93 }
94 
FileUnMap(MemMap addr)95 int FileUnMap(MemMap addr)
96 {
97     return munmap(addr.GetOriginAddr(), addr.GetSize());
98 }
99 
ResolveFilenameFromNative(JSThread * thread,JSTaggedValue dirname,JSTaggedValue request)100 JSHandle<EcmaString> ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname,
101                                                JSTaggedValue request)
102 {
103     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
104     CString fullname;
105     CString resolvedFilename;
106     CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject()));
107     CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject()));
108 
109     if (requestStr.find("./") == 0) {
110         requestStr = requestStr.substr(2); // 2 : delete './'
111     }
112     int suffixEnd = static_cast<int>(requestStr.find_last_of('.'));
113     if (suffixEnd == -1) {
114         RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
115     }
116     if (requestStr[0] == '/') { // absolute FilePath
117         fullname = requestStr.substr(0, suffixEnd) + ".abc";
118     } else {
119         int pos = static_cast<int>(dirnameStr.find_last_of('/'));
120         if (pos == -1) {
121             RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
122         }
123         fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc";
124     }
125 
126     std::string relativePath = CstringConvertToStdString(fullname);
127     std::string absPath = "";
128     if (RealPath(relativePath, absPath)) {
129         resolvedFilename = ConvertToString(absPath);
130         return factory->NewFromUtf8(resolvedFilename);
131     }
132     CString msg = "resolve absolute path fail";
133     THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, EcmaString, msg.c_str());
134 }
135 }  // namespace panda::ecmascript
136