1 /*
2  * Copyright (c) 2023-2024 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 OHOS_FILEMGMT_DENTRY_META_FILE_H
17 #define OHOS_FILEMGMT_DENTRY_META_FILE_H
18 
19 #include <atomic>
20 #include <functional>
21 #include <list>
22 #include <map>
23 #include <memory>
24 #include <mutex>
25 #include <string>
26 #include <sys/stat.h>
27 #include <vector>
28 
29 #include "unique_fd.h"
30 
31 namespace OHOS {
32 namespace FileManagement {
33 
34 const std::string RECYCLE_NAME = ".trash";
35 const std::string RECYCLE_CLOUD_ID = ".trash";
36 const std::string ROOT_CLOUD_ID = "rootId";
37 const unsigned int STAT_MODE_DIR = 0771;
38 constexpr int32_t LOCAL = 1;
39 constexpr uint32_t MAX_META_FILE_NUM = 100;
40 constexpr uint32_t MAX_CLOUDDISK_META_FILE_NUM = 150;
41 
42 struct MetaBase;
43 class MetaFile {
44 public:
45     MetaFile() = delete;
46     ~MetaFile();
47     using CloudDiskMetaFileCallBack = std::function<void(MetaBase &)>;
48     explicit MetaFile(uint32_t userId, const std::string &path);
49     explicit MetaFile(uint32_t userId, const std::string &bundleName, const std::string &parentCloudId);
50     int32_t DoLookupAndUpdate(const std::string &name, CloudDiskMetaFileCallBack updateFunc);
51     int32_t DoLookupAndRemove(MetaBase &metaBase);
52     int32_t DoCreate(const MetaBase &base);
53     int32_t HandleFileByFd(unsigned long &endBlock, uint32_t &level);
54     int32_t DoRemove(const MetaBase &base);
55     int32_t DoUpdate(const MetaBase &base);
56     int32_t DoRename(const MetaBase &oldBase, const std::string &newName);
57     int32_t DoRename(MetaBase &metaBase, const std::string &newName, std::shared_ptr<MetaFile> newMetaFile);
58     int32_t DoLookup(MetaBase &base);
59     int32_t LoadChildren(std::vector<MetaBase> &bases);
60 
61     static std::string GetParentDir(const std::string &path);
62     static std::string GetFileName(const std::string &path);
63 
64 private:
65     std::mutex mtx_{};
66     std::string path_{};
67     std::string cacheFile_{};
68     std::string bundleName_{};
69     std::string cloudId_{};
70     std::string name_{};
71     UniqueFd fd_{};
72     uint32_t userId_{};
73     std::shared_ptr<MetaFile> parentMetaFile_{nullptr};
74 };
75 
76 class CloudDiskMetaFile {
77 public:
78     CloudDiskMetaFile() = delete;
79     ~CloudDiskMetaFile();
80     using CloudDiskMetaFileCallBack = std::function<void(MetaBase &)>;
81     explicit CloudDiskMetaFile(uint32_t userId, const std::string &bundleName, const std::string &cloudId);
82 
83     int32_t DoLookupAndUpdate(const std::string &name, CloudDiskMetaFileCallBack updateFunc);
84     int32_t DoChildUpdate(const std::string &name, CloudDiskMetaFileCallBack updateFunc);
85     int32_t DoLookupAndRemove(MetaBase &metaBase);
86     int32_t DoCreate(const MetaBase &base);
87     int32_t HandleFileByFd(unsigned long &endBlock, uint32_t &level);
88     int32_t DoRemove(const MetaBase &base);
89     int32_t DoUpdate(const MetaBase &base);
90     int32_t DoRename(MetaBase &metaBase, const std::string &newName,
91         std::shared_ptr<CloudDiskMetaFile> newMetaFile);
92     int32_t DoLookup(MetaBase &base);
93     int32_t LoadChildren(std::vector<MetaBase> &bases);
94     std::string GetDentryFilePath();
95 
96 private:
97     std::mutex mtx_{};
98     std::string path_{};
99     std::string cacheFile_{};
100     std::string bundleName_{};
101     std::string cloudId_{};
102     std::string name_{};
103     UniqueFd fd_{};
104     uint32_t userId_{};
105     std::shared_ptr<MetaFile> parentMetaFile_{nullptr};
106 };
107 
108 enum {
109     NEED_UPLOAD = 0,
110     NO_UPLOAD,
111 };
112 
113 enum {
114     FILE_TYPE_CONTENT = 0,
115     FILE_TYPE_THUMBNAIL,
116     FILE_TYPE_LCD,
117 };
118 
119 enum {
120     POSITION_UNKNOWN = 0,
121     POSITION_LOCAL = 0x01,
122     POSITION_CLOUD = 0x02,
123     POSITION_LOCAL_AND_CLOUD = POSITION_LOCAL | POSITION_CLOUD,
124 };
125 
126 typedef std::pair<uint32_t, std::string> MetaFileKey;
127 typedef std::pair<MetaFileKey, std::shared_ptr<CloudDiskMetaFile>> CloudDiskMetaFileListEle;
128 typedef std::pair<MetaFileKey, std::shared_ptr<MetaFile>> MetaFileListEle;
129 
130 class MetaFileMgr {
131 public:
132     static MetaFileMgr& GetInstance();
133     /* recordId is hex string of 256 bits, convert to u8 cloudId[32] to kernel */
134     static std::string RecordIdToCloudId(const std::string hexStr);
135     static std::string CloudIdToRecordId(const std::string cloudId);
136     std::shared_ptr<MetaFile> GetMetaFile(uint32_t userId, const std::string &path);
137     std::shared_ptr<CloudDiskMetaFile> GetCloudDiskMetaFile(uint32_t userId, const std::string &bundleName,
138         const std::string &cloudId);
139     void ClearAll();
140     void CloudDiskClearAll();
141     void Clear(uint32_t userId, const std::string &bundleName, const std::string &cloudId);
142     int32_t CreateRecycleDentry(uint32_t userId, const std::string &bundleName);
143     int32_t MoveIntoRecycleDentryfile(uint32_t userId, const std::string &bundleName,
144         const std::string &name, const std::string &parentCloudId, int64_t rowId);
145     int32_t RemoveFromRecycleDentryfile(uint32_t userId, const std::string &bundleName,
146         const std::string &name, const std::string &parentCloudId, int64_t rowId);
147 private:
148     MetaFileMgr() = default;
149     ~MetaFileMgr() = default;
150     MetaFileMgr(const MetaFileMgr &m) = delete;
151     const MetaFileMgr &operator=(const MetaFileMgr &m) = delete;
152 
153     std::recursive_mutex mtx_{};
154     std::mutex cloudDiskMutex_{};
155     std::list<MetaFileListEle> metaFileList_;
156     std::map<MetaFileKey, std::list<MetaFileListEle>::iterator> metaFiles_;
157     std::list<CloudDiskMetaFileListEle> cloudDiskMetaFileList_;
158     std::map<MetaFileKey, std::list<CloudDiskMetaFileListEle>::iterator> cloudDiskMetaFile_;
159 };
160 
161 struct MetaBase {
MetaBaseMetaBase162     MetaBase(const std::string &name) : name(name) {}
MetaBaseMetaBase163     MetaBase(const std::string &name, const std::string &cloudId) : name(name), cloudId(cloudId) {}
164     MetaBase() = default;
165     inline bool operator!=(const MetaBase &other) const
166     {
167         return !operator==(other);
168     }
169     inline bool operator==(const MetaBase &other) const
170     {
171         return other.cloudId == cloudId && other.name == name && other.size == size;
172     }
173     uint64_t atime{0};
174     uint64_t mtime{0};
175     uint64_t size{0};
176     uint32_t mode{S_IFREG};
177     uint8_t position{POSITION_LOCAL};
178     uint8_t fileType{FILE_TYPE_CONTENT};
179     uint8_t noUpload{NEED_UPLOAD};
180     std::string name{};
181     std::string cloudId{};
182     off_t nextOff{0};
183     bool hasDownloaded{false};
184 };
185 
186 struct BitOps {
187     static const uint8_t BIT_PER_BYTE = 8;
TestBitBitOps188     static int TestBit(uint32_t nr, const uint8_t addr[])
189     {
190         return 1 & (addr[nr / BIT_PER_BYTE] >> (nr & (BIT_PER_BYTE - 1)));
191     }
192 
ClearBitBitOps193     static void ClearBit(uint32_t nr, uint8_t addr[])
194     {
195         addr[nr / BIT_PER_BYTE] &= ~(1UL << ((nr) % BIT_PER_BYTE));
196     }
197 
SetBitBitOps198     static void SetBit(uint32_t nr, uint8_t addr[])
199     {
200         addr[nr / BIT_PER_BYTE] |= (1UL << ((nr) % BIT_PER_BYTE));
201     }
202 
FindNextBitBitOps203     static uint32_t FindNextBit(const uint8_t addr[], uint32_t maxSlots, uint32_t start)
204     {
205         while (start < maxSlots) {
206             if (BitOps::TestBit(start, addr)) {
207                 return start;
208             }
209             start++;
210         }
211         return maxSlots;
212     }
213 
FindNextZeroBitBitOps214     static uint32_t FindNextZeroBit(const uint8_t addr[], uint32_t maxSlots, uint32_t start)
215     {
216         while (start < maxSlots) {
217             if (!BitOps::TestBit(start, addr)) {
218                 return start;
219             }
220             start++;
221         }
222         return maxSlots;
223     }
224 };
225 
226 struct MetaHelper {
227     static void SetFileType(struct HmdfsDentry *de, uint8_t fileType);
228     static void SetPosition(struct HmdfsDentry *de, uint8_t position);
229     static uint8_t GetFileType(const struct HmdfsDentry *de);
230     static uint8_t GetPosition(const struct HmdfsDentry *de);
231 };
232 } // namespace FileManagement
233 } // namespace OHOS
234 
235 #endif // META_FILE_H
236