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 return ret; 180 } 181 182 return MapSharedMemory(memInfo); 183 } 184 ExpandSharedMemory(SharedMemoryInfo & memInfo)185 static int ExpandSharedMemory(SharedMemoryInfo &memInfo) 186 { 187 uint64_t memSize = 0; 188 auto alloc = CalculateMemSize(memSize, memInfo); 189 if (alloc) { 190 DestroySharedMemory(memInfo); 191 int ret = CreateSharedMemory(memInfo.memName, memSize, memInfo); 192 if (ret != ERR_OK) { 193 HILOG_ERROR("Recreate shared memory error, code: %{public}d", ret); 194 return ret; 195 } 196 HILOG_INFO("Recreate shared memory success, memory size: %{public}" PRIu64, memSize); 197 } 198 return ERR_OK; 199 } 200 DestroySharedMemory(SharedMemoryInfo & memInfo)201 static void DestroySharedMemory(SharedMemoryInfo &memInfo) 202 { 203 if (memInfo.memHead != nullptr) { 204 ::munmap(memInfo.memHead, memInfo.memSize); 205 ::close(memInfo.memFd); 206 memInfo.memHead = nullptr; 207 } 208 } 209 MapSharedMemory(SharedMemoryInfo & memInfo)210 static int MapSharedMemory(SharedMemoryInfo &memInfo) 211 { 212 memInfo.memHead = reinterpret_cast<uint8_t *>( 213 ::mmap(nullptr, memInfo.memSize, PROT_READ | PROT_WRITE, MAP_SHARED, memInfo.memFd, 0)); 214 if (memInfo.memHead == MAP_FAILED) { 215 int ret = errno; 216 ::close(memInfo.memFd); 217 HILOG_ERROR("Shared memory map error, code: %{public}d", ret); 218 return ret; 219 } 220 memInfo.memTail = memInfo.memHead + memInfo.memSize; 221 memInfo.dataPtr = memInfo.memHead; 222 memInfo.Clear(); 223 return ERR_OK; 224 } 225 CalculateMemSize(uint64_t & memSize,SharedMemoryInfo & memInfo)226 static bool CalculateMemSize(uint64_t &memSize, SharedMemoryInfo &memInfo) 227 { 228 uint64_t allocSize = ((memInfo.leftDataCounts + memInfo.totalDataCounts - 1) / memInfo.totalDataCounts + 1) 229 * DEFAULT_CAPACITY_200KB; 230 231 if (allocSize >= MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB) { 232 memSize = MAX_CAPACITY_2MB; 233 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 234 return true; 235 } 236 237 if (allocSize < MAX_CAPACITY_2MB && memInfo.memSize < MAX_CAPACITY_2MB && memInfo.memSize < allocSize) { 238 memSize = allocSize; 239 HILOG_ERROR("memSize: %{public}" PRIu64, memSize); 240 return true; 241 } 242 return false; 243 } 244 WriteFileInfos(std::vector<FileInfo> & fileInfoVec,SharedMemoryInfo & memInfo)245 static uint32_t WriteFileInfos(std::vector<FileInfo> &fileInfoVec, SharedMemoryInfo &memInfo) 246 { 247 uint32_t count = 0; 248 for (auto &info : fileInfoVec) { 249 int ret = WriteFileInfo(info, memInfo); 250 if (!ret) { 251 return count; 252 } 253 count++; 254 } 255 return count; 256 } 257 WriteFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)258 static bool WriteFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 259 { 260 uint64_t fileInfoSize = GetFileInfoSize(info); 261 uint64_t leftSize = memInfo.memSize - memInfo.dataSize; 262 if (leftSize < fileInfoSize) { 263 HILOG_INFO("Shared memory cannot hold current data"); 264 return false; 265 } 266 267 uint8_t *dataPtr = memInfo.dataPtr; 268 uint64_t dataSize = memInfo.dataSize; 269 bool ret = WriteString(info.uri, memInfo); 270 ret = ret && WriteString(info.relativePath, memInfo); 271 ret = ret && WriteString(info.fileName, memInfo); 272 ret = ret && WriteInt32(info.mode, memInfo); 273 ret = ret && WriteInt64(info.size, memInfo); 274 ret = ret && WriteInt64(info.mtime, memInfo); 275 ret = ret && WriteString(info.mimeType, memInfo); 276 if (!ret) { 277 memInfo.dataPtr = dataPtr; 278 memInfo.dataSize = dataSize; 279 HILOG_ERROR("Write FileInfo into shared memmory failed"); 280 return false; 281 } 282 memInfo.dataCounts++; 283 return true; 284 } 285 ReadFileInfo(FileInfo & info,SharedMemoryInfo & memInfo)286 static bool ReadFileInfo(FileInfo &info, SharedMemoryInfo &memInfo) 287 { 288 if (memInfo.dataCounts == 0) { 289 HILOG_INFO("No data in shared memory"); 290 return false; 291 } 292 uint8_t *dataPtr = memInfo.dataPtr; 293 uint64_t dataSize = memInfo.dataSize; 294 bool ret = ReadString(info.uri, memInfo); 295 ret = ret && ReadString(info.relativePath, memInfo); 296 ret = ret && ReadString(info.fileName, memInfo); 297 ret = ret && ReadInt32(info.mode, memInfo); 298 ret = ret && ReadInt64(info.size, memInfo); 299 ret = ret && ReadInt64(info.mtime, memInfo); 300 ret = ret && ReadString(info.mimeType, memInfo); 301 if (!ret) { 302 memInfo.dataPtr = dataPtr; 303 memInfo.dataSize = dataSize; 304 return false; 305 } 306 memInfo.dataCounts--; 307 return true; 308 } 309 310 private: 311 template <typename T> WriteInteger(T & integer,SharedMemoryInfo & memInfo)312 static bool WriteInteger(T &integer, SharedMemoryInfo &memInfo) 313 { 314 uint8_t *src = reinterpret_cast<uint8_t *>(&integer); 315 uint8_t *dest = memInfo.dataPtr; 316 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 317 HILOG_ERROR("WriteInteger 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 325 template <typename T> ReadInteger(T & integer,SharedMemoryInfo & memInfo)326 static bool ReadInteger(T &integer, SharedMemoryInfo &memInfo) 327 { 328 uint8_t *src = memInfo.dataPtr; 329 uint8_t *dest = reinterpret_cast<uint8_t *>(&integer); 330 if (memcpy_s(dest, sizeof(T), src, sizeof(T)) != ERR_OK) { 331 HILOG_ERROR("ReadInteger failed:%{public}s", std::strerror(errno)); 332 return false; 333 } 334 memInfo.dataPtr += sizeof(T); 335 memInfo.dataSize -= sizeof(T); 336 return true; 337 } 338 WriteInt32(int32_t & value,SharedMemoryInfo & memInfo)339 static bool WriteInt32(int32_t &value, SharedMemoryInfo &memInfo) 340 { 341 return WriteInteger<int32_t>(value, memInfo); 342 } 343 WriteInt64(int64_t & value,SharedMemoryInfo & memInfo)344 static bool WriteInt64(int64_t &value, SharedMemoryInfo &memInfo) 345 { 346 return WriteInteger<int64_t>(value, memInfo); 347 } 348 ReadInt32(int32_t & value,SharedMemoryInfo & memInfo)349 static bool ReadInt32(int32_t &value, SharedMemoryInfo &memInfo) 350 { 351 return ReadInteger<int32_t>(value, memInfo); 352 } 353 ReadInt64(int64_t & value,SharedMemoryInfo & memInfo)354 static bool ReadInt64(int64_t &value, SharedMemoryInfo &memInfo) 355 { 356 return ReadInteger<int64_t>(value, memInfo); 357 } 358 WriteString(std::string & inVal,SharedMemoryInfo & memInfo)359 static bool WriteString(std::string &inVal, SharedMemoryInfo &memInfo) 360 { 361 std::string::size_type len = inVal.size(); 362 bool ret = WriteInteger<std::string::size_type>(len, memInfo); 363 if (!ret) { 364 return false; 365 } 366 if (len == 0) { 367 return true; 368 } 369 370 const uint8_t *src = reinterpret_cast<const uint8_t *>(inVal.c_str()); 371 uint8_t *dest = memInfo.dataPtr; 372 if (memcpy_s(dest, len, src, len) != ERR_OK) { 373 HILOG_ERROR("WriteString failed:%{public}s", std::strerror(errno)); 374 return false; 375 } 376 memInfo.dataPtr += len; 377 memInfo.dataSize += len; 378 return true; 379 } 380 ReadString(std::string & outVal,SharedMemoryInfo & memInfo)381 static bool ReadString(std::string &outVal, SharedMemoryInfo &memInfo) 382 { 383 std::string::size_type len = 0; 384 int ret = ReadInteger<std::string::size_type>(len, memInfo); 385 if (!ret) { 386 return false; 387 } 388 if (len == 0) { 389 outVal = ""; 390 return true; 391 } 392 393 uint8_t *src = memInfo.dataPtr; 394 uint8_t dest[len + 1]; 395 if (memcpy_s(dest, len, src, len) != ERR_OK) { 396 HILOG_ERROR("ReadString failed:%{public}s", std::strerror(errno)); 397 return false; 398 } 399 dest[len] = 0; 400 outVal = reinterpret_cast<char *>(dest); 401 memInfo.dataPtr += len; 402 memInfo.dataSize -= len; 403 return true; 404 } 405 GetFileInfoSize(FileInfo & info)406 static uint64_t GetFileInfoSize(FileInfo &info) 407 { 408 return sizeof(std::string::size_type) + info.uri.size() + sizeof(std::string::size_type) + 409 info.relativePath.size() + sizeof(std::string::size_type) + info.fileName.size() + sizeof(info.mode) + 410 sizeof(info.size) + sizeof(info.mtime) + sizeof(std::string::size_type) + info.mimeType.size(); 411 } 412 }; 413 } // namespace FileAccessFwk 414 } // namespace OHOS 415 #endif // _FILE_INFO_SHARED_MEMORY_H_ 416