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 #ifndef ECMASCRIPT_PLATFORM_FILE_H 17 #define ECMASCRIPT_PLATFORM_FILE_H 18 19 #ifdef PANDA_TARGET_WINDOWS 20 #include <windef.h> 21 #include <winbase.h> 22 #include <winnt.h> 23 #else 24 #include <fcntl.h> 25 #include <dlfcn.h> 26 #endif 27 28 #include <string> 29 30 #include "ecmascript/platform/map.h" 31 32 namespace panda::ecmascript { 33 class JSThread; 34 #ifdef PANDA_TARGET_WINDOWS 35 using fd_t = HANDLE; 36 #define INVALID_FD INVALID_HANDLE_VALUE 37 38 #define FILE_RDONLY GENERIC_READ 39 #define FILE_WRONLY GENERIC_WRITE 40 #define FILE_RDWR (GENERIC_READ | GENERIC_WRITE) 41 #define FILE_CREAT CREATE_ALWAYS 42 #define FILE_TRUNC TRUNCATE_EXISTING 43 44 #ifdef ERROR 45 #undef ERROR 46 #endif 47 48 #ifdef VOID 49 #undef VOID 50 #endif 51 52 #ifdef CONST 53 #undef CONST 54 #endif 55 #else 56 using fd_t = int; 57 #define INVALID_FD (-1) 58 59 #define FILE_RDONLY O_RDONLY 60 #define FILE_WRONLY O_WRONLY 61 #define FILE_RDWR O_RDWR 62 #define FILE_CREAT O_CREAT 63 #define FILE_TRUNC O_TRUNC 64 #endif 65 66 #define FILE_SUCCESS 1 67 #define FILE_FAILED 0 68 69 #define FILE_MS_SYNC 4 // Synchronous memory sync 70 71 std::string PUBLIC_API GetFileDelimiter(); 72 std::string PUBLIC_API GetPathSeparator(); 73 bool PUBLIC_API RealPath(const std::string &path, std::string &realPath, bool readOnly = true); 74 bool PUBLIC_API RealPathByChar(const char *path, char *realPath, int rowLength, bool readOnly); 75 void DPrintf(fd_t fd, const std::string &buffer); 76 void PUBLIC_API FdsanExchangeOwnerTag(fd_t fd); 77 void PUBLIC_API Close(fd_t fd); 78 void FSync(fd_t fd); 79 MemMap PUBLIC_API FileMap(const char *fileName, int flag, int prot, int64_t offset = 0); 80 MemMap PUBLIC_API CreateFileMap([[maybe_unused]] const char *fileName, [[maybe_unused]] int fileSize, 81 [[maybe_unused]] int flag, [[maybe_unused]] int prot); 82 MemMap PUBLIC_API FileMapForAlignAddressByFd(const fd_t fd, int prot, int64_t offset, uint32_t offStart); 83 int PUBLIC_API FileUnMap(MemMap addr); 84 int PUBLIC_API FileSync(MemMap addr, int flag); 85 CString ResolveFilenameFromNative(JSThread *thread, const CString &dirname, CString request); 86 bool PUBLIC_API FileExist(const char *filename); 87 int PUBLIC_API Unlink(const char *filename); 88 void *LoadLib(const std::string &libname); 89 void *FindSymbol(void *handle, const char *symbol); 90 int CloseLib(void *handle); 91 char *LoadLibError(); 92 void PUBLIC_API DeleteFilesWithSuffix(const std::string &dirPath, const std::string &suffix); 93 94 class MemMapScope { 95 public: MemMapScope(MemMap memMap)96 MemMapScope(MemMap memMap) : memMap_(memMap) {} ~MemMapScope()97 ~MemMapScope() 98 { 99 FileUnMap(memMap_); 100 } 101 102 private: 103 MemMap memMap_ {}; 104 }; 105 106 class FileMemMapReader { 107 public: 108 using ReadFailedCallback = std::function<void()>; FileMemMapReader(const MemMap & memMap,ReadFailedCallback readFailedCallback,CString logTag)109 FileMemMapReader(const MemMap &memMap, ReadFailedCallback readFailedCallback, CString logTag) : memMap_(memMap), 110 readFailedCallback_(std::move(readFailedCallback)), readPtr_(static_cast<uint8_t *>(memMap.GetOriginAddr())), 111 remainingSize_(memMap.GetSize()), fileSize_(memMap.GetSize()), logTag_(std::move(logTag)) {} 112 113 template<typename T> ReadSingleData(T * readDst,const size_t readSize,const CString & message)114 bool ReadSingleData(T *readDst, const size_t readSize, const CString &message) 115 { 116 if (remainingSize_ < readSize) { 117 LOG_ECMA(ERROR) << logTag_ << " read " << message << " remainingSize not sufficient"; 118 readFailedCallback_(); 119 return false; 120 } 121 if (memcpy_s(readDst, readSize, readPtr_, readSize) != EOK) { 122 LOG_ECMA(ERROR) << logTag_ << " memcpy_s read " << message << " failed"; 123 readFailedCallback_(); 124 return false; 125 } 126 Step(readSize); 127 return true; 128 } 129 ReadString(CString & readDst,const size_t readSize,const CString & message)130 bool ReadString(CString &readDst, const size_t readSize, const CString &message) 131 { 132 readDst.reserve(readSize); 133 if (remainingSize_ < readSize) { 134 LOG_ECMA(ERROR) << logTag_ << " read " << message << " remainingSize not sufficient"; 135 readFailedCallback_(); 136 return false; 137 } 138 readDst.assign(reinterpret_cast<const char*>(readPtr_), readSize); 139 Step(readSize); 140 return true; 141 } 142 143 template<typename T> ReadFromOffset(T * readDst,const size_t readSize,const size_t offset,const CString & message)144 bool ReadFromOffset(T *readDst, const size_t readSize, const size_t offset, const CString &message) 145 { 146 if (fileSize_ < offset + readSize) { 147 LOG_ECMA(ERROR) << logTag_ << " read " << message << " fileSize_ not sufficient"; 148 readFailedCallback_(); 149 return false; 150 } 151 uint8_t *readPtr = static_cast<uint8_t *>(memMap_.GetOriginAddr()); 152 if (memcpy_s(readDst, readSize, readPtr + offset, readSize) != EOK) { 153 LOG_ECMA(ERROR) << logTag_ << " memcpy_s read " << message << " failed"; 154 readFailedCallback_(); 155 return false; 156 } 157 return true; 158 } 159 Step(const size_t stepSize)160 void Step(const size_t stepSize) 161 { 162 readPtr_ += stepSize; 163 remainingSize_ -= stepSize; 164 } 165 GetReadPtr()166 uint8_t *GetReadPtr() const 167 { 168 return readPtr_; 169 } 170 171 private: 172 MemMap memMap_ {}; 173 ReadFailedCallback readFailedCallback_ {}; 174 uint8_t *readPtr_ { nullptr }; 175 size_t remainingSize_ { 0 }; 176 size_t fileSize_ { 0 }; 177 CString logTag_ {}; 178 }; 179 180 class FileMemMapWriter { 181 public: FileMemMapWriter(const MemMap & memMap,CString logTag)182 FileMemMapWriter(const MemMap &memMap, CString logTag) : memMap_(memMap), 183 writePtr_(static_cast<uint8_t *>(memMap.GetOriginAddr())), 184 fileSize_(memMap.GetSize()), logTag_(std::move(logTag)) {} 185 186 template<typename T> WriteSingleData(T * writeSrc,const size_t writeSize,const CString & message)187 bool WriteSingleData(T *writeSrc, const size_t writeSize, const CString &message) 188 { 189 if (memcpy_s(writePtr_, writeSize, writeSrc, writeSize) != EOK) { 190 LOG_ECMA(ERROR) << logTag_ << " memcpy_s write " << message << " failed"; 191 return false; 192 } 193 writePtr_ += writeSize; 194 return true; 195 } 196 GetWritePtr()197 uint8_t *GetWritePtr() const 198 { 199 return writePtr_; 200 } 201 WriteAlignUpPadding(const size_t paddingSize)202 bool WriteAlignUpPadding(const size_t paddingSize) 203 { 204 if (paddingSize <= 0) { 205 return true; 206 } 207 if (memset_s(writePtr_, paddingSize, 0, paddingSize) != EOK) { 208 LOG_ECMA(ERROR) << logTag_ << " memset_s WriteAlignUpPadding " << paddingSize << " failed"; 209 return false; 210 } 211 writePtr_ += paddingSize; 212 return true; 213 } 214 215 private: 216 MemMap memMap_ {}; 217 uint8_t *writePtr_ { nullptr }; 218 size_t fileSize_ { 0 }; 219 CString logTag_ {}; 220 }; 221 } // namespace panda::ecmascript 222 #endif // ECMASCRIPT_PLATFORM_FILE_H 223