1 2 /* 3 * Copyright (C) 2023 - 2025 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 Marshalling(Parcel & parcel)61 bool Marshalling(Parcel &parcel) const override 62 { 63 if (!WriteFileDescriptor(parcel, memFd)) { 64 HILOG_ERROR("WriteFileDescriptor fail"); 65 return false; 66 } 67 if (!parcel.WriteUint64(memSize)) { 68 return false; 69 } 70 if (!parcel.WriteUint32(dataCounts)) { 71 return false; 72 } 73 if (!parcel.WriteUint64(dataSize)) { 74 return false; 75 } 76 if (!parcel.WriteUint32(leftDataCounts)) { 77 return false; 78 } 79 if (!parcel.WriteBool(isOver)) { 80 return false; 81 } 82 return true; 83 } 84 Unmarshalling(Parcel & parcel)85 static SharedMemoryInfo *Unmarshalling(Parcel &parcel) 86 { 87 auto *obj = new (std::nothrow) SharedMemoryInfo(); 88 if (obj != nullptr && !obj->ReadFromParcel(parcel)) { 89 delete obj; 90 obj = nullptr; 91 } 92 return obj; 93 } 94 ReadFromParcel(Parcel & parcel)95 bool ReadFromParcel(Parcel &parcel) 96 { 97 if (!ReadFileDescriptor(parcel)) { 98 return false; 99 } 100 101 memSize = parcel.ReadUint64(); 102 dataCounts = parcel.ReadUint32(); 103 dataSize = parcel.ReadUint64(); 104 leftDataCounts = parcel.ReadUint32(); 105 isOver = parcel.ReadBool(); 106 return true; 107 } 108 Empty()109 bool Empty() const 110 { 111 return dataCounts == 0; 112 } 113 Size()114 uint32_t Size() const 115 { 116 return dataCounts; 117 } 118 Clear()119 void Clear() 120 { 121 dataPtr = memHead; 122 dataSize = 0; 123 dataCounts = 0; 124 isOver = false; 125 totalDataCounts = 0; 126 leftDataCounts = 0; 127 } 128 129 private: WriteFileDescriptor(Parcel & parcel,int fd)130 bool WriteFileDescriptor(Parcel &parcel, int fd) const 131 { 132 if (fd < 0) { 133 return false; 134 } 135 int dupFd = dup(fd); 136 if (dupFd < 0) { 137 return false; 138 } 139 sptr<IPCFileDescriptor> descriptor = new (std::nothrow)IPCFileDescriptor(dupFd); 140 if (descriptor == nullptr) { 141 HILOG_ERROR("create IPCFileDescriptor object failed"); 142 return false; 143 } 144 return parcel.WriteObject<IPCFileDescriptor>(descriptor); 145 } 146 ReadFileDescriptor(Parcel & parcel)147 bool ReadFileDescriptor(Parcel &parcel) 148 { 149 sptr<IPCFileDescriptor> descriptor = parcel.ReadObject<IPCFileDescriptor>(); 150 if (descriptor == nullptr) { 151 return false; 152 } 153 int fd = descriptor->GetFd(); 154 if (fd < 0) { 155 return false; 156 } 157 memFd = dup(fd); 158 return true; 159 } 160 }; 161 162 class SharedMemoryOperation { 163 public: CreateSharedMemory(const char * memName,uint64_t memSize,SharedMemoryInfo & memInfo)164 static int CreateSharedMemory(const char *memName, uint64_t memSize, SharedMemoryInfo &memInfo) 165 { 166 memInfo.memName = memName; 167 memInfo.memSize = memSize; 168 memInfo.memFd = AshmemCreate(memInfo.memName, memInfo.memSize); 169 if (memInfo.memFd < 0) { 170 HILOG_ERROR("Create shared memory error, shared memory name is %{public}s code: %{public}d", 171 memInfo.memName, memInfo.memFd); 172 return memInfo.memFd; 173 } 174 175 int ret = AshmemSetProt(memInfo.memFd, PROT_READ | PROT_WRITE); 176 if (ret < 0) { 177 HILOG_ERROR("Set shared memory protection mask error, code: %{public}d", ret); 178 ::close(memInfo.memFd); 179 memInfo.memFd = -1; 180 return ret; 181 } 182 183 return MapSharedMemory(memInfo); 184 } 185 ExpandSharedMemory(SharedMemoryInfo & memInfo)186 static int ExpandSharedMemory(SharedMemoryInfo &memInfo) 187 { 188 uint64_t memSize = 0; 189 auto alloc = CalculateMemSize(memSize, memInfo); 190 if (alloc) { 191 DestroySharedMemory(memInfo); 192 int ret = CreateSharedMemory(memInfo.memName, memSize, memInfo); 193 if (ret != ERR_OK) { 194 HILOG_ERROR("Recreate shared memory error, code: %{public}d", ret); 195 return ret; 196 } 197 HILOG_INFO("Recreate shared memory success, memory size: %{public}" PRIu64, memSize); 198 } 199 return ERR_OK; 200 } 201 DestroySharedMemory(SharedMemoryInfo & memInfo)202 static void DestroySharedMemory(SharedMemoryInfo &memInfo) 203 { 204 if (memInfo.memHead != nullptr) { 205 ::munmap(memInfo.memHead, memInfo.memSize); 206 ::close(memInfo.memFd); 207 memInfo.memFd = -1; 208 memInfo.memHead = nullptr; 209 } 210 } 211 MapSharedMemory(SharedMemoryInfo & memInfo)212 static int MapSharedMemory(SharedMemoryInfo &memInfo) 213 { 214 memInfo.memHead = reinterpret_cast<uint8_t *>( 215 ::mmap(nullptr, memInfo.memSize, PROT_READ | PROT_WRITE, MAP_SHARED, memInfo.memFd, 0)); 216 if (memInfo.memHead == MAP_FAILED) { 217 int ret = errno; 218 ::close(memInfo.memFd); 219 memInfo.memFd = -1; 220 HILOG_ERROR("Shared memory map error, code: %{public}d", ret); 221 return ret; 222 } 223 memInfo.memTail = memInfo.memHead + memInfo.memSize; 224 memInfo.dataPtr = memInfo.memHead; 225 memInfo.Clear(); 226 return ERR_OK; 227 } 228 CalculateMemSize(uint64_t & memSize,SharedMemoryInfo & memInfo)229 static bool CalculateMemSize(uint64_t &memSize, SharedMemoryInfo &memInfo) 230 { 231 uint64_t allocSize = ((memInfo.leftDataCounts + memInfo.totalDataCounts - 1) / memInfo.totalDataCounts + 1) 232 * DEFAULT_CAPACITY_200KB; 233 234 if (allocSize >= MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB) { 235 memSize = MAX_CAPACITY_2MB; 236 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 237 return true; 238 } 239 240 if (allocSize < MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB && memInfo.memSize < allocSize) { 241 memSize = allocSize; 242 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 243 return true; 244 } 245 return false; 246 } 247 WriteFileInfos(std::vector<FileInfo> & fileInfoVec,SharedMemoryInfo & memInfo)248 static uint32_t WriteFileInfos(std::vector<FileInfo> &fileInfoVec, SharedMemoryInfo &memInfo) 249 { 250 uint32_t count = 0; 251 for (auto &info : fileInfoVec) { 252 int ret = WriteFileInfo(info, memInfo); 253 if (!ret) { 254 return count; 255 } 256 count++; 257 } 258 return count; 259 } 260 WriteFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)261 static bool WriteFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 262 { 263 uint64_t fileInfoSize = GetFileInfoSize(info); 264 uint64_t leftSize = memInfo.memSize - memInfo.dataSize; 265 if (leftSize < fileInfoSize) { 266 HILOG_INFO("Shared memory cannot hold current data"); 267 return false; 268 } 269 270 uint8_t *dataPtr = memInfo.dataPtr; 271 uint64_t dataSize = memInfo.dataSize; 272 bool ret = WriteString(info.uri, memInfo); 273 ret = ret && WriteString(info.relativePath, memInfo); 274 ret = ret && WriteString(info.fileName, memInfo); 275 ret = ret && WriteInt32(info.mode, memInfo); 276 ret = ret && WriteInt64(info.size, memInfo); 277 ret = ret && WriteInt64(info.mtime, memInfo); 278 ret = ret && WriteString(info.mimeType, memInfo); 279 if (!ret) { 280 memInfo.dataPtr = dataPtr; 281 memInfo.dataSize = dataSize; 282 HILOG_ERROR("Write FileInfo into shared memmory failed"); 283 return false; 284 } 285 memInfo.dataCounts++; 286 return true; 287 } 288 ReadFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)289 static bool ReadFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 290 { 291 if (memInfo.dataCounts == 0) { 292 HILOG_INFO("No data in shared memory"); 293 return false; 294 } 295 uint8_t *dataPtr = memInfo.dataPtr; 296 uint64_t dataSize = memInfo.dataSize; 297 bool ret = ReadString(info.uri, memInfo); 298 ret = ret && ReadString(info.relativePath, memInfo); 299 ret = ret && ReadString(info.fileName, memInfo); 300 ret = ret && ReadInt32(info.mode, memInfo); 301 ret = ret && ReadInt64(info.size, memInfo); 302 ret = ret && ReadInt64(info.mtime, memInfo); 303 ret = ret && ReadString(info.mimeType, memInfo); 304 if (!ret) { 305 memInfo.dataPtr = dataPtr; 306 memInfo.dataSize = dataSize; 307 return false; 308 } 309 memInfo.dataCounts--; 310 return true; 311 } 312 313 private: 314 template <typename T> WriteInteger(T & integer,SharedMemoryInfo & memInfo)315 static bool WriteInteger(T &integer, SharedMemoryInfo &memInfo) 316 { 317 uint8_t *src = reinterpret_cast<uint8_t *>(&integer); 318 uint8_t *dest = memInfo.dataPtr; 319 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 320 HILOG_ERROR("WriteInteger failed:%{public}s", std::strerror(errno)); 321 return false; 322 } 323 memInfo.dataPtr += sizeof(T); 324 memInfo.dataSize += sizeof(T); 325 return true; 326 } 327 328 template <typename T> ReadInteger(T & integer,SharedMemoryInfo & memInfo)329 static bool ReadInteger(T &integer, SharedMemoryInfo &memInfo) 330 { 331 uint8_t *src = memInfo.dataPtr; 332 uint8_t *dest = reinterpret_cast<uint8_t *>(&integer); 333 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 334 HILOG_ERROR("ReadInteger failed:%{public}s", std::strerror(errno)); 335 return false; 336 } 337 memInfo.dataPtr += sizeof(T); 338 memInfo.dataSize -= sizeof(T); 339 return true; 340 } 341 WriteInt32(int32_t & value,SharedMemoryInfo & memInfo)342 static bool WriteInt32(int32_t &value, SharedMemoryInfo &memInfo) 343 { 344 return WriteInteger<int32_t>(value, memInfo); 345 } 346 WriteInt64(int64_t & value,SharedMemoryInfo & memInfo)347 static bool WriteInt64(int64_t &value, SharedMemoryInfo &memInfo) 348 { 349 return WriteInteger<int64_t>(value, memInfo); 350 } 351 ReadInt32(int32_t & value,SharedMemoryInfo & memInfo)352 static bool ReadInt32(int32_t &value, SharedMemoryInfo &memInfo) 353 { 354 return ReadInteger<int32_t>(value, memInfo); 355 } 356 ReadInt64(int64_t & value,SharedMemoryInfo & memInfo)357 static bool ReadInt64(int64_t &value, SharedMemoryInfo &memInfo) 358 { 359 return ReadInteger<int64_t>(value, memInfo); 360 } 361 WriteString(std::string & inVal,SharedMemoryInfo & memInfo)362 static bool WriteString(std::string &inVal, SharedMemoryInfo &memInfo) 363 { 364 std::string::size_type len = inVal.size(); 365 bool ret = WriteInteger<std::string::size_type>(len, memInfo); 366 if (!ret) { 367 return false; 368 } 369 if (len == 0) { 370 return true; 371 } 372 373 const uint8_t *src = reinterpret_cast<const uint8_t *>(inVal.c_str()); 374 uint8_t *dest = memInfo.dataPtr; 375 if (memcpy_s(dest, len, src, len) != ERR_OK) { 376 HILOG_ERROR("WriteString failed:%{public}s", std::strerror(errno)); 377 return false; 378 } 379 memInfo.dataPtr += len; 380 memInfo.dataSize += len; 381 return true; 382 } 383 ReadString(std::string & outVal,SharedMemoryInfo & memInfo)384 static bool ReadString(std::string &outVal, SharedMemoryInfo &memInfo) 385 { 386 std::string::size_type len = 0; 387 int ret = ReadInteger<std::string::size_type>(len, memInfo); 388 if (!ret) { 389 return false; 390 } 391 if (len == 0) { 392 outVal = ""; 393 return true; 394 } 395 396 uint8_t *src = memInfo.dataPtr; 397 uint8_t dest[len + 1]; 398 if (memcpy_s(dest, len, src, len) != ERR_OK) { 399 HILOG_ERROR("ReadString failed:%{public}s", std::strerror(errno)); 400 return false; 401 } 402 dest[len] = 0; 403 outVal = reinterpret_cast<char *>(dest); 404 memInfo.dataPtr += len; 405 memInfo.dataSize -= len; 406 return true; 407 } 408 GetFileInfoSize(FileInfo & info)409 static uint64_t GetFileInfoSize(FileInfo &info) 410 { 411 return sizeof(std::string::size_type) + info.uri.size() + sizeof(std::string::size_type) + 412 info.relativePath.size() + sizeof(std::string::size_type) + info.fileName.size() + sizeof(info.mode) + 413 sizeof(info.size) + sizeof(info.mtime) + sizeof(std::string::size_type) + info.mimeType.size(); 414 } 415 }; 416 } // namespace FileAccessFwk 417 } // namespace OHOS 418 #endif // _FILE_INFO_SHARED_MEMORY_H_ 419