• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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