1 2 /* 3 * Copyright (C) 2023 - 2024 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _FILE_INFO_SHARED_MEMORY_H_ 18 #define _FILE_INFO_SHARED_MEMORY_H_ 19 20 #include <inttypes.h> 21 #include <stdint.h> 22 #include <string> 23 #include <sys/mman.h> 24 #include <unistd.h> 25 #include <utility> 26 #include <vector> 27 28 #include "ashmem.h" 29 #include "file_access_extension_info.h" 30 #include "file_access_framework_errno.h" 31 #include "hilog_wrapper.h" 32 #include "ipc_file_descriptor.h" 33 #include "parcel.h" 34 #include "securec.h" 35 36 namespace OHOS { 37 namespace FileAccessFwk { 38 namespace { 39 const uint32_t DEFAULT_CAPACITY_200KB = 200 * 1024; 40 const uint32_t MAX_CAPACITY_2MB = 2 * 1024 * 1024; 41 } // namespace 42 43 class SharedMemoryInfo : public OHOS::Parcelable { 44 public: 45 const char *memName {nullptr}; 46 int memFd {-1}; 47 uint8_t *memHead {nullptr}; 48 uint8_t *memTail {nullptr}; 49 uint64_t memSize {0}; 50 51 uint8_t *dataPtr {nullptr}; 52 uint64_t dataSize {0}; 53 uint32_t dataCounts = 0; 54 55 bool isOver {false}; 56 uint32_t totalDataCounts = 0; 57 uint32_t leftDataCounts = 0; 58 59 SharedMemoryInfo() = default; 60 SharedMemoryInfo(const SharedMemoryInfo &) = delete; 61 SharedMemoryInfo &operator=(SharedMemoryInfo &) = delete; 62 Marshalling(Parcel & parcel)63 bool Marshalling(Parcel &parcel) const override 64 { 65 if (!WriteFileDescriptor(parcel, memFd)) { 66 HILOG_ERROR("WriteFileDescriptor fail"); 67 return false; 68 } 69 if (!parcel.WriteUint64(memSize)) { 70 return false; 71 } 72 return true; 73 } 74 Unmarshalling(Parcel & parcel)75 static SharedMemoryInfo *Unmarshalling(Parcel &parcel) 76 { 77 auto *obj = new (std::nothrow) SharedMemoryInfo(); 78 if (obj != nullptr && !obj->ReadFromParcel(parcel)) { 79 delete obj; 80 obj = nullptr; 81 } 82 return obj; 83 } 84 ReadFromParcel(Parcel & parcel)85 bool ReadFromParcel(Parcel &parcel) 86 { 87 if (!ReadFileDescriptor(parcel)) { 88 return false; 89 } 90 91 memSize = parcel.ReadUint64(); 92 return true; 93 } 94 Empty()95 bool Empty() const 96 { 97 return dataCounts == 0; 98 } 99 Size()100 uint32_t Size() const 101 { 102 return dataCounts; 103 } 104 Clear()105 void Clear() 106 { 107 dataPtr = memHead; 108 dataSize = 0; 109 dataCounts = 0; 110 isOver = false; 111 totalDataCounts = 0; 112 leftDataCounts = 0; 113 } 114 115 private: WriteFileDescriptor(Parcel & parcel,int fd)116 bool WriteFileDescriptor(Parcel &parcel, int fd) const 117 { 118 if (fd < 0) { 119 return false; 120 } 121 int dupFd = dup(fd); 122 if (dupFd < 0) { 123 return false; 124 } 125 sptr<IPCFileDescriptor> descriptor = new (std::nothrow)IPCFileDescriptor(dupFd); 126 if (descriptor == nullptr) { 127 HILOG_ERROR("create IPCFileDescriptor object failed"); 128 return false; 129 } 130 return parcel.WriteObject<IPCFileDescriptor>(descriptor); 131 } 132 ReadFileDescriptor(Parcel & parcel)133 bool ReadFileDescriptor(Parcel &parcel) 134 { 135 sptr<IPCFileDescriptor> descriptor = parcel.ReadObject<IPCFileDescriptor>(); 136 if (descriptor == nullptr) { 137 return false; 138 } 139 int fd = descriptor->GetFd(); 140 if (fd < 0) { 141 return false; 142 } 143 memFd = dup(fd); 144 return true; 145 } 146 }; 147 148 class SharedMemoryOperation { 149 public: CreateSharedMemory(const char * memName,uint64_t memSize,SharedMemoryInfo & memInfo)150 static int CreateSharedMemory(const char *memName, uint64_t memSize, SharedMemoryInfo &memInfo) 151 { 152 memInfo.memName = memName; 153 memInfo.memSize = memSize; 154 memInfo.memFd = AshmemCreate(memInfo.memName, memInfo.memSize); 155 if (memInfo.memFd < 0) { 156 HILOG_ERROR("Create shared memory error, shared memory name is %{public}s code: %{public}d", 157 memInfo.memName, memInfo.memFd); 158 return memInfo.memFd; 159 } 160 161 int ret = AshmemSetProt(memInfo.memFd, PROT_READ | PROT_WRITE); 162 if (ret < 0) { 163 HILOG_ERROR("Set shared memory protection mask error, code: %{public}d", ret); 164 ::close(memInfo.memFd); 165 return ret; 166 } 167 168 return MapSharedMemory(memInfo); 169 } 170 ExpandSharedMemory(SharedMemoryInfo & memInfo)171 static int ExpandSharedMemory(SharedMemoryInfo &memInfo) 172 { 173 uint64_t memSize = 0; 174 auto alloc = CalculateMemSize(memSize, memInfo); 175 if (alloc) { 176 DestroySharedMemory(memInfo); 177 int ret = CreateSharedMemory(memInfo.memName, memSize, memInfo); 178 if (ret != ERR_OK) { 179 HILOG_ERROR("Recreate shared memory error, code: %{public}d", ret); 180 return ret; 181 } 182 HILOG_INFO("Recreate shared memory success, memory size: %{public}" PRIu64, memSize); 183 } 184 return ERR_OK; 185 } 186 DestroySharedMemory(SharedMemoryInfo & memInfo)187 static void DestroySharedMemory(SharedMemoryInfo &memInfo) 188 { 189 if (memInfo.memHead != nullptr) { 190 ::munmap(memInfo.memHead, memInfo.memSize); 191 ::close(memInfo.memFd); 192 memInfo.memHead = nullptr; 193 } 194 } 195 MapSharedMemory(SharedMemoryInfo & memInfo)196 static int MapSharedMemory(SharedMemoryInfo &memInfo) 197 { 198 memInfo.memHead = reinterpret_cast<uint8_t *>( 199 ::mmap(nullptr, memInfo.memSize, PROT_READ | PROT_WRITE, MAP_SHARED, memInfo.memFd, 0)); 200 if (memInfo.memHead == MAP_FAILED) { 201 int ret = errno; 202 ::close(memInfo.memFd); 203 HILOG_ERROR("Shared memory map error, code: %{public}d", ret); 204 return ret; 205 } 206 memInfo.memTail = memInfo.memHead + memInfo.memSize; 207 memInfo.dataPtr = memInfo.memHead; 208 memInfo.Clear(); 209 return ERR_OK; 210 } 211 CalculateMemSize(uint64_t & memSize,SharedMemoryInfo & memInfo)212 static bool CalculateMemSize(uint64_t &memSize, SharedMemoryInfo &memInfo) 213 { 214 uint64_t allocSize = ((memInfo.leftDataCounts + memInfo.totalDataCounts - 1) / memInfo.totalDataCounts + 1) 215 * DEFAULT_CAPACITY_200KB; 216 217 if (allocSize >= MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB) { 218 memSize = MAX_CAPACITY_2MB; 219 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 220 return true; 221 } 222 223 if (allocSize < MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB && memInfo.memSize < allocSize) { 224 memSize = allocSize; 225 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 226 return true; 227 } 228 return false; 229 } 230 WriteFileInfos(std::vector<FileInfo> & fileInfoVec,SharedMemoryInfo & memInfo)231 static uint32_t WriteFileInfos(std::vector<FileInfo> &fileInfoVec, SharedMemoryInfo &memInfo) 232 { 233 uint32_t count = 0; 234 for (auto &info : fileInfoVec) { 235 int ret = WriteFileInfo(info, memInfo); 236 if (!ret) { 237 return count; 238 } 239 count++; 240 } 241 return count; 242 } 243 WriteFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)244 static bool WriteFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 245 { 246 uint64_t fileInfoSize = GetFileInfoSize(info); 247 uint64_t leftSize = memInfo.memSize - memInfo.dataSize; 248 if (leftSize < fileInfoSize) { 249 HILOG_INFO("Shared memory cannot hold current data"); 250 return false; 251 } 252 253 uint8_t *dataPtr = memInfo.dataPtr; 254 uint64_t dataSize = memInfo.dataSize; 255 bool ret = WriteString(info.uri, memInfo); 256 ret = ret && WriteString(info.relativePath, memInfo); 257 ret = ret && WriteString(info.fileName, memInfo); 258 ret = ret && WriteInt32(info.mode, memInfo); 259 ret = ret && WriteInt64(info.size, memInfo); 260 ret = ret && WriteInt64(info.mtime, memInfo); 261 ret = ret && WriteString(info.mimeType, memInfo); 262 if (!ret) { 263 memInfo.dataPtr = dataPtr; 264 memInfo.dataSize = dataSize; 265 HILOG_ERROR("Write FileInfo into shared memmory failed"); 266 return false; 267 } 268 memInfo.dataCounts++; 269 return true; 270 } 271 ReadFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)272 static bool ReadFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 273 { 274 if (memInfo.dataCounts == 0) { 275 HILOG_INFO("No data in shared memory"); 276 return false; 277 } 278 uint8_t *dataPtr = memInfo.dataPtr; 279 uint64_t dataSize = memInfo.dataSize; 280 bool ret = ReadString(info.uri, memInfo); 281 ret = ret && ReadString(info.relativePath, memInfo); 282 ret = ret && ReadString(info.fileName, memInfo); 283 ret = ret && ReadInt32(info.mode, memInfo); 284 ret = ret && ReadInt64(info.size, memInfo); 285 ret = ret && ReadInt64(info.mtime, memInfo); 286 ret = ret && ReadString(info.mimeType, memInfo); 287 if (!ret) { 288 memInfo.dataPtr = dataPtr; 289 memInfo.dataSize = dataSize; 290 return false; 291 } 292 memInfo.dataCounts--; 293 return true; 294 } 295 296 private: 297 template <typename T> WriteInteger(T & integer,SharedMemoryInfo & memInfo)298 static bool WriteInteger(T &integer, SharedMemoryInfo &memInfo) 299 { 300 uint8_t *src = reinterpret_cast<uint8_t *>(&integer); 301 uint8_t *dest = memInfo.dataPtr; 302 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 303 HILOG_ERROR("WriteInteger failed:%{public}s", std::strerror(errno)); 304 return false; 305 } 306 memInfo.dataPtr += sizeof(T); 307 memInfo.dataSize += sizeof(T); 308 return true; 309 } 310 311 template <typename T> ReadInteger(T & integer,SharedMemoryInfo & memInfo)312 static bool ReadInteger(T &integer, SharedMemoryInfo &memInfo) 313 { 314 uint8_t *src = memInfo.dataPtr; 315 uint8_t *dest = reinterpret_cast<uint8_t *>(&integer); 316 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 317 HILOG_ERROR("ReadInteger failed:%{public}s", std::strerror(errno)); 318 return false; 319 } 320 memInfo.dataPtr += sizeof(T); 321 memInfo.dataSize -= sizeof(T); 322 return true; 323 } 324 WriteInt32(int32_t & value,SharedMemoryInfo & memInfo)325 static bool WriteInt32(int32_t &value, SharedMemoryInfo &memInfo) 326 { 327 return WriteInteger<int32_t>(value, memInfo); 328 } 329 WriteInt64(int64_t & value,SharedMemoryInfo & memInfo)330 static bool WriteInt64(int64_t &value, SharedMemoryInfo &memInfo) 331 { 332 return WriteInteger<int64_t>(value, memInfo); 333 } 334 ReadInt32(int32_t & value,SharedMemoryInfo & memInfo)335 static bool ReadInt32(int32_t &value, SharedMemoryInfo &memInfo) 336 { 337 return ReadInteger<int32_t>(value, memInfo); 338 } 339 ReadInt64(int64_t & value,SharedMemoryInfo & memInfo)340 static bool ReadInt64(int64_t &value, SharedMemoryInfo &memInfo) 341 { 342 return ReadInteger<int64_t>(value, memInfo); 343 } 344 WriteString(std::string & inVal,SharedMemoryInfo & memInfo)345 static bool WriteString(std::string &inVal, SharedMemoryInfo &memInfo) 346 { 347 std::string::size_type len = inVal.size(); 348 bool ret = WriteInteger<std::string::size_type>(len, memInfo); 349 if (!ret) { 350 return false; 351 } 352 if (len == 0) { 353 return true; 354 } 355 356 const uint8_t *src = reinterpret_cast<const uint8_t *>(inVal.c_str()); 357 uint8_t *dest = memInfo.dataPtr; 358 if (memcpy_s(dest, len, src, len) != ERR_OK) { 359 HILOG_ERROR("WriteString failed:%{public}s", std::strerror(errno)); 360 return false; 361 } 362 memInfo.dataPtr += len; 363 memInfo.dataSize += len; 364 return true; 365 } 366 ReadString(std::string & outVal,SharedMemoryInfo & memInfo)367 static bool ReadString(std::string &outVal, SharedMemoryInfo &memInfo) 368 { 369 std::string::size_type len = 0; 370 int ret = ReadInteger<std::string::size_type>(len, memInfo); 371 if (!ret) { 372 return false; 373 } 374 if (len == 0) { 375 outVal = ""; 376 return true; 377 } 378 379 uint8_t *src = memInfo.dataPtr; 380 uint8_t dest[len + 1]; 381 if (memcpy_s(dest, len, src, len) != ERR_OK) { 382 HILOG_ERROR("ReadString failed:%{public}s", std::strerror(errno)); 383 return false; 384 } 385 dest[len] = 0; 386 outVal = reinterpret_cast<char *>(dest); 387 memInfo.dataPtr += len; 388 memInfo.dataSize -= len; 389 return true; 390 } 391 GetFileInfoSize(FileInfo & info)392 static uint64_t GetFileInfoSize(FileInfo &info) 393 { 394 return sizeof(std::string::size_type) + info.uri.size() + sizeof(std::string::size_type) + 395 info.relativePath.size() + sizeof(std::string::size_type) + info.fileName.size() + sizeof(info.mode) + 396 sizeof(info.size) + sizeof(info.mtime) + sizeof(std::string::size_type) + info.mimeType.size(); 397 } 398 }; 399 } // namespace FileAccessFwk 400 } // namespace OHOS 401 #endif // _FILE_INFO_SHARED_MEMORY_H_ 402