1 /*
2  * Copyright (c) 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 #include "meta_file.h"
17 
18 #include <ctime>
19 #include <fcntl.h>
20 #include <iomanip>
21 #include <sstream>
22 #include <sys/stat.h>
23 
24 #include "cloud_file_utils.h"
25 #include "dfs_error.h"
26 #include "file_utils.h"
27 #include "securec.h"
28 #include "string_ex.h"
29 #include "sys/xattr.h"
30 #include "utils_directory.h"
31 #include "utils_log.h"
32 
33 namespace OHOS {
34 namespace FileManagement {
35 constexpr uint32_t DENTRYGROUP_SIZE = 4096;
36 constexpr uint32_t DENTRY_NAME_LEN = 8;
37 constexpr uint32_t DENTRY_RESERVED_LENGTH = 4;
38 constexpr uint32_t DENTRY_PER_GROUP = 52;
39 constexpr uint32_t DENTRY_BITMAP_LENGTH = 7;
40 constexpr uint32_t DENTRY_GROUP_RESERVED = 32;
41 constexpr uint32_t CLOUD_RECORD_ID_LEN = 33;
42 constexpr uint32_t DENTRYGROUP_HEADER = 4096;
43 constexpr uint32_t MAX_BUCKET_LEVEL = 63;
44 constexpr uint32_t BUCKET_BLOCKS = 2;
45 constexpr uint32_t BITS_PER_BYTE = 8;
46 constexpr uint32_t HMDFS_SLOT_LEN_BITS = 3;
47 constexpr uint64_t DELTA = 0x9E3779B9; /* Hashing code copied from f2fs */
48 constexpr uint64_t HMDFS_HASH_COL_BIT = (0x1ULL) << 63;
49 constexpr uint32_t FILE_TYPE_OFFSET = 2;
50 
51 #pragma pack(push, 1)
52 struct HmdfsDentry {
53     uint32_t hash{0};
54     uint16_t mode{0};
55     uint16_t namelen{0};
56     uint64_t size{0};
57     uint64_t mtime{0};
58     uint64_t atime{0};
59     uint8_t recordId[CLOUD_RECORD_ID_LEN]{0};
60     uint8_t flags{0};
61     /* reserved bytes for long term extend, total 60 bytes */
62     uint8_t reserved[DENTRY_RESERVED_LENGTH];
63 };
64 
65 struct HmdfsDentryGroup {
66     uint8_t dentryVersion;
67     uint8_t bitmap[DENTRY_BITMAP_LENGTH];
68     struct HmdfsDentry nsl[DENTRY_PER_GROUP];
69     uint8_t fileName[DENTRY_PER_GROUP][DENTRY_NAME_LEN];
70     uint8_t reserved[DENTRY_GROUP_RESERVED];
71 };
72 static_assert(sizeof(HmdfsDentryGroup) == DENTRYGROUP_SIZE);
73 
74 struct HmdfsDcacheHeader {
75     uint64_t dcacheCrtime{0};
76     uint64_t dcacheCrtimeNsec{0};
77 
78     uint64_t dentryCtime{0};
79     uint64_t dentryCtimeNsec{0};
80 
81     uint64_t dentryCount{0};
82 };
83 #pragma pack(pop)
84 
SetFileType(struct HmdfsDentry * de,uint8_t fileType)85 void MetaHelper::SetFileType(struct HmdfsDentry *de, uint8_t fileType)
86 {
87     de->flags &= 0x3;
88     de->flags |= (fileType << FILE_TYPE_OFFSET);
89 }
90 
SetPosition(struct HmdfsDentry * de,uint8_t position)91 void MetaHelper::SetPosition(struct HmdfsDentry *de, uint8_t position)
92 {
93     de->flags &= 0xFC;
94     de->flags |= position;
95 }
96 
GetFileType(const struct HmdfsDentry * de)97 uint8_t MetaHelper::GetFileType(const struct HmdfsDentry *de)
98 {
99     return (de->flags & 0xFC) >> FILE_TYPE_OFFSET;
100 }
101 
GetPosition(const struct HmdfsDentry * de)102 uint8_t MetaHelper::GetPosition(const struct HmdfsDentry *de)
103 {
104     return de->flags & 0x3;
105 }
106 
GetCloudDiskDentryFileByPath(uint32_t userId,const std::string & bundleName,const std::string & cloudId)107 static std::string GetCloudDiskDentryFileByPath(uint32_t userId, const std::string &bundleName,
108     const std::string &cloudId)
109 {
110     std::string cacheDir =
111         "/data/service/el2/" + std::to_string(userId) +
112         "/hmdfs/cloud/data/" + bundleName + "/" +
113         std::to_string(CloudDisk::CloudFileUtils::GetBucketId(cloudId)) + "/";
114     std::string dentryFileName = MetaFileMgr::GetInstance().CloudIdToRecordId(cloudId);
115     Storage::DistributedFile::Utils::ForceCreateDirectory(cacheDir, STAT_MODE_DIR);
116     return cacheDir + dentryFileName;
117 }
118 
CloudDiskMetaFile(uint32_t userId,const std::string & bundleName,const std::string & cloudId)119 CloudDiskMetaFile::CloudDiskMetaFile(uint32_t userId, const std::string &bundleName, const std::string &cloudId)
120 {
121     userId_ = userId;
122     bundleName_ = bundleName;
123     cloudId_ = cloudId;
124     cacheFile_ = GetCloudDiskDentryFileByPath(userId_, bundleName_, cloudId_);
125     fd_ = UniqueFd{open(cacheFile_.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)};
126     LOGD("CloudDiskMetaFile cloudId=%{public}s, path=%{public}s", cloudId_.c_str(), GetAnonyString(cacheFile_).c_str());
127     LOGD("CloudDiskMetaFile fd=%{public}d, errno :%{public}d", fd_.Get(), errno);
128 
129     HmdfsDcacheHeader header{};
130     (void)FileUtils::ReadFile(fd_, 0, sizeof(header), &header);
131 }
132 
GetDentryFilePath()133 std::string CloudDiskMetaFile::GetDentryFilePath()
134 {
135     return cacheFile_;
136 }
137 
DoLookupAndUpdate(const std::string & name,CloudDiskMetaFileCallBack callback)138 int32_t CloudDiskMetaFile::DoLookupAndUpdate(const std::string &name, CloudDiskMetaFileCallBack callback)
139 {
140     if (name == "mock") {
141         return E_RDB;
142     }
143     return E_OK;
144 }
145 
DoChildUpdate(const std::string & name,CloudDiskMetaFileCallBack callback)146 int32_t CloudDiskMetaFile::DoChildUpdate(const std::string &name, CloudDiskMetaFileCallBack callback)
147 {
148     return E_OK;
149 }
150 
DoLookupAndRemove(MetaBase & metaBase)151 int32_t CloudDiskMetaFile::DoLookupAndRemove(MetaBase &metaBase)
152 {
153     /* lookup and remove in parent */
154     int32_t ret = DoLookup(metaBase);
155     if (ret == E_OK) {
156         ret = DoRemove(metaBase);
157         if (ret != E_OK) {
158             LOGE("remove dentry file failed, ret %{public}d", ret);
159             return ret;
160         }
161         return E_OK;
162     }
163     return E_OK;
164 }
165 
~CloudDiskMetaFile()166 CloudDiskMetaFile::~CloudDiskMetaFile()
167 {
168 }
169 
IsDotDotdot(const std::string & name)170 static bool IsDotDotdot(const std::string &name)
171 {
172     return name == "." || name == "..";
173 }
174 
Str2HashBuf(const char * msg,size_t len,uint32_t * buf,int num)175 static void Str2HashBuf(const char *msg, size_t len, uint32_t *buf, int num)
176 {
177     uint32_t pad = static_cast<uint32_t>(len) | (static_cast<uint32_t>(len) << 8);
178     pad |= pad << 16; /* hash pad length 16 */
179 
180     uint32_t val = pad;
181     len = std::min(len, static_cast<size_t>(num * sizeof(int)));
182     for (uint32_t i = 0; i < len; i++) {
183         if ((i % sizeof(int)) == 0) {
184             val = pad;
185         }
186         uint8_t c = static_cast<uint8_t>(tolower(msg[i]));
187         val = c + (val << 8); /* hash shift size 8 */
188         if ((i % 4) == 3) {   /* msg size 4, shift when 3 */
189             *buf++ = val;
190             val = pad;
191             num--;
192         }
193     }
194     if (--num >= 0) {
195         *buf++ = val;
196     }
197     while (--num >= 0) {
198         *buf++ = pad;
199     }
200 }
201 
TeaTransform(uint32_t buf[4],uint32_t const in[])202 static void TeaTransform(uint32_t buf[4], uint32_t const in[]) __attribute__((no_sanitize("unsigned-integer-overflow")))
203 {
204     int n = 16;           /* transform total rounds 16 */
205     uint32_t a = in[0];   /* transform input pos 0 */
206     uint32_t b = in[1];   /* transform input pos 1 */
207     uint32_t c = in[2];   /* transform input pos 2 */
208     uint32_t d = in[3];   /* transform input pos 3 */
209     uint32_t b0 = buf[0]; /* buf pos 0 */
210     uint32_t b1 = buf[1]; /* buf pos 1 */
211     uint32_t sum = 0;
212 
213     do {
214         sum += DELTA;
215         b0 += ((b1 << 4) + a) ^ (b1 + sum) ^ ((b1 >> 5) + b); /* tea transform width 4 and 5 */
216         b1 += ((b0 << 4) + c) ^ (b0 + sum) ^ ((b0 >> 5) + d); /* tea transform width 4 and 5 */
217     } while (--n);
218 
219     buf[0] += b0;
220     buf[1] += b1;
221 }
222 
DentryHash(const std::string & name)223 static uint32_t DentryHash(const std::string &name)
224 {
225     if (IsDotDotdot(name)) {
226         return 0;
227     }
228 
229     constexpr int inLen = 8;      /* hash input buf size 8 */
230     constexpr int bufLen = 4;     /* hash output buf size 4 */
231     uint32_t in[inLen];
232     uint32_t buf[bufLen];
233     auto len = name.length();
234     constexpr decltype(len) hashWidth = 16; /* hash operation width 4 */
235     const char *p = name.c_str();
236 
237     buf[0] = 0x67452301; /* hash magic 1 */
238     buf[1] = 0xefcdab89; /* hash magic 2 */
239     buf[2] = 0x98badcfe; /* hash magic 3 */
240     buf[3] = 0x10325476; /* hash magic 4 */
241 
242     bool loopFlag = true;
243     while (loopFlag) {
244         Str2HashBuf(p, len, in, bufLen);
245         TeaTransform(buf, in);
246 
247         if (len <= hashWidth) {
248             break;
249         }
250 
251         p += hashWidth;
252         len -= hashWidth;
253     };
254     uint32_t hash = buf[0];
255     uint32_t hmdfsHash = hash & ~HMDFS_HASH_COL_BIT;
256 
257     return hmdfsHash;
258 }
259 
GetDentrySlots(size_t nameLen)260 static inline uint32_t GetDentrySlots(size_t nameLen)
261 {
262     return static_cast<uint32_t>((nameLen + BITS_PER_BYTE - 1) >> HMDFS_SLOT_LEN_BITS);
263 }
264 
GetDentryGroupPos(size_t bidx)265 static inline off_t GetDentryGroupPos(size_t bidx)
266 {
267     return bidx * DENTRYGROUP_SIZE + DENTRYGROUP_HEADER;
268 }
269 
GetDentryGroupCnt(uint64_t size)270 static inline uint64_t GetDentryGroupCnt(uint64_t size)
271 {
272     return (size >= DENTRYGROUP_HEADER) ? ((size - DENTRYGROUP_HEADER) / DENTRYGROUP_SIZE) : 0;
273 }
274 
GetOverallBucket(uint32_t level)275 static uint32_t GetOverallBucket(uint32_t level)
276 {
277     if (level >= MAX_BUCKET_LEVEL) {
278         LOGD("level = %{public}d overflow", level);
279         return 0;
280     }
281     uint64_t buckets = (1ULL << (level + 1)) - 1;
282     return static_cast<uint32_t>(buckets);
283 }
284 
GetDcacheFileSize(uint32_t level)285 static size_t GetDcacheFileSize(uint32_t level)
286 {
287     size_t buckets = GetOverallBucket(level);
288     return buckets * DENTRYGROUP_SIZE * BUCKET_BLOCKS + DENTRYGROUP_HEADER;
289 }
290 
GetBucketaddr(uint32_t level,uint32_t buckoffset)291 static uint32_t GetBucketaddr(uint32_t level, uint32_t buckoffset)
292 {
293     if (level >= MAX_BUCKET_LEVEL) {
294         return 0;
295     }
296 
297     uint64_t curLevelMaxBucks = (1ULL << level);
298     if (buckoffset >= curLevelMaxBucks) {
299         return 0;
300     }
301 
302     return static_cast<uint32_t>(curLevelMaxBucks) + buckoffset - 1;
303 }
304 
GetBucketByLevel(uint32_t level)305 static uint32_t GetBucketByLevel(uint32_t level)
306 {
307     if (level >= MAX_BUCKET_LEVEL) {
308         LOGD("level = %{public}d overflow", level);
309         return 0;
310     }
311 
312     uint64_t buckets = (1ULL << level);
313     return static_cast<uint32_t>(buckets);
314 }
315 
RoomForFilename(const uint8_t bitmap[],size_t slots,uint32_t maxSlots)316 static uint32_t RoomForFilename(const uint8_t bitmap[], size_t slots, uint32_t maxSlots)
317 {
318     uint32_t bitStart = 0;
319     bool loopFlag = true;
320     while (loopFlag) {
321         uint32_t zeroStart = BitOps::FindNextZeroBit(bitmap, maxSlots, bitStart);
322         if (zeroStart >= maxSlots) {
323             return maxSlots;
324         }
325 
326         uint32_t zeroEnd = BitOps::FindNextBit(bitmap, maxSlots, zeroStart);
327         if (zeroEnd - zeroStart >= slots) {
328             return zeroStart;
329         }
330 
331         bitStart = zeroEnd + 1;
332         if (zeroEnd + 1 >= maxSlots) {
333             return maxSlots;
334         }
335     }
336     return 0;
337 }
338 
UpdateDentry(HmdfsDentryGroup & d,const MetaBase & base,uint32_t nameHash,uint32_t bitPos)339 static void UpdateDentry(HmdfsDentryGroup &d, const MetaBase &base, uint32_t nameHash, uint32_t bitPos)
340 {
341     HmdfsDentry *de;
342     const std::string name = base.name;
343     uint32_t slots = GetDentrySlots(name.length());
344 
345     de = &d.nsl[bitPos];
346     de->hash = nameHash;
347     de->namelen = name.length();
348     auto ret = memcpy_s(d.fileName[bitPos], slots * DENTRY_NAME_LEN, name.c_str(), name.length());
349     if (ret != 0) {
350         LOGE("memcpy_s failed, dstLen = %{public}d, srcLen = %{public}zu", slots * DENTRY_NAME_LEN, name.length());
351     }
352     de->atime = base.atime;
353     de->mtime = base.mtime;
354     de->size = base.size;
355     de->mode = base.mode;
356     MetaHelper::SetPosition(de, base.position);
357     MetaHelper::SetFileType(de, base.fileType);
358     (void) memset_s(de->recordId, CLOUD_RECORD_ID_LEN, 0, CLOUD_RECORD_ID_LEN);
359     ret = memcpy_s(de->recordId, CLOUD_RECORD_ID_LEN, base.cloudId.c_str(), base.cloudId.length());
360     if (ret != 0) {
361         LOGE("memcpy_s failed, dstLen = %{public}d, srcLen = %{public}zu", CLOUD_RECORD_ID_LEN, base.cloudId.length());
362     }
363 
364     for (uint32_t i = 0; i < slots; i++) {
365         BitOps::SetBit(bitPos + i, d.bitmap);
366         if (i) {
367             (de + i)->namelen = 0;
368         }
369     }
370 }
371 
HandleFileByFd(unsigned long & endBlock,uint32_t & level)372 int32_t CloudDiskMetaFile::HandleFileByFd(unsigned long &endBlock, uint32_t &level)
373 {
374     return E_OK;
375 }
376 
GetBidxFromLevel(uint32_t level,uint32_t namehash)377 static unsigned long GetBidxFromLevel(uint32_t level, uint32_t namehash)
378 {
379     uint32_t bucket = GetBucketByLevel(level);
380     if (bucket == 0) {
381         return 0;
382     }
383     return BUCKET_BLOCKS * GetBucketaddr(level, namehash % bucket);
384 }
385 
DoCreate(const MetaBase & base)386 int32_t CloudDiskMetaFile::DoCreate(const MetaBase &base)
387 {
388     return E_OK;
389 }
390 
391 struct DcacheLookupCtx {
392     int fd{-1};
393     std::string name{};
394     uint32_t hash{0};
395     uint32_t bidx{0};
396     std::unique_ptr<HmdfsDentryGroup> page{nullptr};
397 };
398 
InitDcacheLookupCtx(DcacheLookupCtx * ctx,const MetaBase & base,int fd)399 static void InitDcacheLookupCtx(DcacheLookupCtx *ctx, const MetaBase &base, int fd)
400 {
401     ctx->fd = fd;
402     ctx->name = base.name;
403     ctx->bidx = 0;
404     ctx->page = nullptr;
405     ctx->hash = DentryHash(ctx->name);
406 }
407 
FindDentryPage(uint64_t index,DcacheLookupCtx * ctx)408 static std::unique_ptr<HmdfsDentryGroup> FindDentryPage(uint64_t index, DcacheLookupCtx *ctx)
409 {
410     auto dentryBlk = std::make_unique<HmdfsDentryGroup>();
411 
412     off_t pos = GetDentryGroupPos(index);
413     ssize_t size = FileUtils::ReadFile(ctx->fd, pos, DENTRYGROUP_SIZE, dentryBlk.get());
414     if (size != DENTRYGROUP_SIZE) {
415         return nullptr;
416     }
417     return dentryBlk;
418 }
419 
FindInBlock(HmdfsDentryGroup & dentryBlk,uint32_t namehash,const std::string & name)420 static HmdfsDentry *FindInBlock(HmdfsDentryGroup &dentryBlk, uint32_t namehash, const std::string &name)
421 {
422     int maxLen = 0;
423     uint32_t bitPos = 0;
424     HmdfsDentry *de = nullptr;
425 
426     while (bitPos < DENTRY_PER_GROUP) {
427         if (!BitOps::TestBit(bitPos, dentryBlk.bitmap)) {
428             bitPos++;
429             maxLen++;
430             continue;
431         }
432         de = &dentryBlk.nsl[bitPos];
433         if (!de->namelen) {
434             bitPos++;
435             continue;
436         }
437 
438         if (de->hash == namehash && de->namelen == name.length() &&
439             !memcmp(name.c_str(), dentryBlk.fileName[bitPos], de->namelen)) {
440             return de;
441         }
442         maxLen = 0;
443         bitPos += GetDentrySlots(de->namelen);
444     }
445 
446     return nullptr;
447 }
448 
InLevel(uint32_t level,DcacheLookupCtx * ctx)449 static HmdfsDentry *InLevel(uint32_t level, DcacheLookupCtx *ctx)
450     __attribute__((no_sanitize("unsigned-integer-overflow")))
451 {
452     HmdfsDentry *de = nullptr;
453 
454     uint32_t nbucket = GetBucketByLevel(level);
455     if (nbucket == 0) {
456         return de;
457     }
458 
459     uint32_t bidx = GetBucketaddr(level, ctx->hash % nbucket) * BUCKET_BLOCKS;
460     uint32_t endBlock = bidx + BUCKET_BLOCKS;
461 
462     for (; bidx < endBlock; bidx++) {
463         auto dentryBlk = FindDentryPage(bidx, ctx);
464         if (dentryBlk == nullptr) {
465             break;
466         }
467 
468         de = FindInBlock(*dentryBlk, ctx->hash, ctx->name);
469         if (de != nullptr) {
470             ctx->page = std::move(dentryBlk);
471             break;
472         }
473     }
474     ctx->bidx = bidx;
475     return de;
476 }
477 
FindDentry(DcacheLookupCtx * ctx)478 static HmdfsDentry *FindDentry(DcacheLookupCtx *ctx)
479 {
480     for (uint32_t level = 0; level < MAX_BUCKET_LEVEL; level++) {
481         HmdfsDentry *de = InLevel(level, ctx);
482         if (de != nullptr) {
483             return de;
484         }
485     }
486     return nullptr;
487 }
488 
DoRemove(const MetaBase & base)489 int32_t CloudDiskMetaFile::DoRemove(const MetaBase &base)
490 {
491     return E_OK;
492 }
493 
DoLookup(MetaBase & base)494 int32_t CloudDiskMetaFile::DoLookup(MetaBase &base)
495 {
496     if (base.name == "mock") {
497         return EINVAL;
498     }
499     return E_OK;
500 }
501 
DoUpdate(const MetaBase & base)502 int32_t CloudDiskMetaFile::DoUpdate(const MetaBase &base)
503 {
504     return E_OK;
505 }
506 
DoRename(MetaBase & metaBase,const std::string & newName,std::shared_ptr<CloudDiskMetaFile> newMetaFile)507 int32_t CloudDiskMetaFile::DoRename(MetaBase &metaBase, const std::string &newName,
508     std::shared_ptr<CloudDiskMetaFile> newMetaFile)
509 {
510     return E_OK;
511 }
512 
DecodeDentrys(const HmdfsDentryGroup & dentryGroup,std::vector<MetaBase> & bases)513 static int32_t DecodeDentrys(const HmdfsDentryGroup &dentryGroup, std::vector<MetaBase> &bases)
514 {
515     return 0;
516 }
517 
LoadChildren(std::vector<MetaBase> & bases)518 int32_t CloudDiskMetaFile::LoadChildren(std::vector<MetaBase> &bases)
519 {
520     return E_OK;
521 }
522 
Clear(uint32_t userId,const std::string & bundleName,const std::string & cloudId)523 void MetaFileMgr::Clear(uint32_t userId, const std::string &bundleName,
524     const std::string &cloudId)
525 {
526     std::lock_guard<std::mutex> lock(cloudDiskMutex_);
527     MetaFileKey key(userId, cloudId + bundleName);
528     cloudDiskMetaFile_.erase(key);
529     cloudDiskMetaFileList_.remove_if([key](CloudDiskMetaFileListEle &item) { return item.first == key; });
530 }
531 
CloudDiskClearAll()532 void MetaFileMgr::CloudDiskClearAll()
533 {
534     std::lock_guard<std::mutex> lock(cloudDiskMutex_);
535     cloudDiskMetaFile_.clear();
536     cloudDiskMetaFileList_.clear();
537 }
538 
GetCloudDiskMetaFile(uint32_t userId,const std::string & bundleName,const std::string & cloudId)539 std::shared_ptr<CloudDiskMetaFile> MetaFileMgr::GetCloudDiskMetaFile(uint32_t userId, const std::string &bundleName,
540     const std::string &cloudId)
541 {
542     std::shared_ptr<CloudDiskMetaFile> mFile = nullptr;
543     std::lock_guard<std::mutex> lock(cloudDiskMutex_);
544     MetaFileKey key(userId, cloudId + bundleName);
545     auto it = cloudDiskMetaFile_.find(key);
546     if (it != cloudDiskMetaFile_.end()) {
547         cloudDiskMetaFileList_.splice(cloudDiskMetaFileList_.begin(), cloudDiskMetaFileList_, it->second);
548         mFile = it->second->second;
549     } else {
550         if (cloudDiskMetaFile_.size() == MAX_META_FILE_NUM) {
551             auto deleteKey = cloudDiskMetaFileList_.back().first;
552             cloudDiskMetaFile_.erase(deleteKey);
553             cloudDiskMetaFileList_.pop_back();
554         }
555         mFile = std::make_shared<CloudDiskMetaFile>(userId, bundleName, cloudId);
556         cloudDiskMetaFileList_.emplace_front(key, mFile);
557         cloudDiskMetaFile_[key] = cloudDiskMetaFileList_.begin();
558     }
559     return mFile;
560 }
561 
CreateRecycleDentry(uint32_t userId,const std::string & bundleName)562 int32_t MetaFileMgr::CreateRecycleDentry(uint32_t userId, const std::string &bundleName)
563 {
564     if (bundleName != "com.ohos.photos") {
565         return EINVAL;
566     }
567     return E_OK;
568 }
569 
MoveIntoRecycleDentryfile(uint32_t userId,const std::string & bundleName,const std::string & name,const std::string & parentCloudId,int64_t rowId)570 int32_t MetaFileMgr::MoveIntoRecycleDentryfile(uint32_t userId, const std::string &bundleName, const std::string &name,
571     const std::string &parentCloudId, int64_t rowId)
572 {
573     return E_OK;
574 }
575 
RemoveFromRecycleDentryfile(uint32_t userId,const std::string & bundleName,const std::string & name,const std::string & parentCloudId,int64_t rowId)576 int32_t MetaFileMgr::RemoveFromRecycleDentryfile(uint32_t userId, const std::string &bundleName,
577     const std::string &name, const std::string &parentCloudId, int64_t rowId)
578 {
579     return E_OK;
580 }
581 } // namespace FileManagement
582 } // namespace OHOS