From ac616cbbea0e0fee02f2788bbc6a45e93a1cabcd Mon Sep 17 00:00:00 2001 From: zhangkaixiang Date: Sun, 19 May 2024 21:54:31 +0800 Subject: [PATCH] add read dir for recycle Signed-off-by: zhangkaixiang Change-Id: I69fa147dd6a9c4df27c2f5fad24f6391df87eb5c --- .../src/cloud_disk/file_operations_cloud.cpp | 88 +++++++++++++++++++ utils/dentry/include/meta_file.h | 1 + 2 files changed, 89 insertions(+) diff --git a/services/cloudfiledaemon/src/cloud_disk/file_operations_cloud.cpp b/services/cloudfiledaemon/src/cloud_disk/file_operations_cloud.cpp index cfb7b8ef6..927c03a70 100644 --- a/services/cloudfiledaemon/src/cloud_disk/file_operations_cloud.cpp +++ b/services/cloudfiledaemon/src/cloud_disk/file_operations_cloud.cpp @@ -598,6 +598,21 @@ static size_t FindNextPos(const vector &childInfos, off_t off return 0; } +static size_t FindNextPos(const vector &childInfos, off_t off) +{ + for (size_t i = 0; i < childInfos.size(); i++) { + /* Find the first valid offset beyond @off */ + if (childInfos[i].nextOff > off) { + return i + 1; + } + } + /* If @off is beyond all valid offset, then return the index after the last info */ + if (!childInfos.empty() && childInfos.back().nextOff < off) { + return childInfos.size(); + } + return 0; +} + static int32_t GetChildInfos(fuse_req_t req, fuse_ino_t ino, vector &childInfos) { auto data = reinterpret_cast(fuse_req_userdata(req)); @@ -640,9 +655,82 @@ static size_t CloudSeekDir(fuse_req_t req, fuse_ino_t ino, off_t off, return 0; } +static size_t CloudSeekDir(fuse_req_t req, fuse_ino_t ino, off_t off, + const std::vector &childInfos) +{ + if (off == 0 || childInfos.empty()) { + return 0; + } + + size_t i = 0; + for (; i < childInfos.size(); i++) { + if (childInfos[i].nextOff == off) { + /* Start position should be the index of next entry */ + return i + 1; + } + } + if (i == childInfos.size()) { + /* The directory may changed recently, find the next valid index for this offset */ + return FindNextPos(childInfos, off); + } + + return 0; +} + +static void ReadDirForRecycle(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi) +{ + int32_t err = -1; + auto data = reinterpret_cast(fuse_req_userdata(req)); + auto inode = FileOperationsHelper::FindCloudDiskInode(data, static_cast(ino)); + if (inode == nullptr) { + LOGE("inode not found"); + fuse_reply_err(req, EINVAL); + return; + } + auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(data->userId, + inode->bundleName, RECYCLE_NAME); + std::vector bases; + err = metaFile->LoadChildren(bases); + if (err != 0) { + LOGE("load children failed, err=%{public}d", err); + fuse_reply_err(req, EINVAL); + return; + } + + size_t startPos = CloudSeekDir(req, ino, off, bases); + string buf; + buf.resize(size); + if (bases.empty() || startPos == bases.size()) { + return (void)fuse_reply_buf(req, buf.c_str(), 0); + } + + size_t nextOff = 0; + size_t remain = size; + static const struct stat STAT_INFO_DIR = { .st_mode = S_IFDIR | STAT_MODE_DIR }; + static const struct stat STAT_INFO_REG = { .st_mode = S_IFREG | STAT_MODE_REG }; + for (size_t i = startPos; i < bases.size(); i++) { + size_t alignSize = CloudDiskRdbUtils::FuseDentryAlignSize(bases[i].name.c_str()); + if (alignSize > remain) { + break; + } + alignSize = fuse_add_direntry(req, &buf[nextOff], alignSize, bases[i].name.c_str(), + bases[i].mode != S_IFREG ? &STAT_INFO_DIR : &STAT_INFO_REG, + off + static_cast(nextOff) + static_cast(alignSize)); + nextOff += alignSize; + remain -= alignSize; + } + (void)fuse_reply_buf(req, buf.c_str(), size - remain); +} + void FileOperationsCloud::ReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { + if (ino == RECYCLE_LOCAL_ID) { + ReadDirForRecycle(req, ino, size, off, fi); + return; + } + vector childInfos; int32_t err = GetChildInfos(req, ino, childInfos); if (err != 0) { diff --git a/utils/dentry/include/meta_file.h b/utils/dentry/include/meta_file.h index c4052ea76..535a73f7f 100644 --- a/utils/dentry/include/meta_file.h +++ b/utils/dentry/include/meta_file.h @@ -157,6 +157,7 @@ struct MetaBase { uint8_t fileType{FILE_TYPE_CONTENT}; std::string name{}; std::string cloudId{}; + off_t nextOff{0}; bool hasDownloaded{false}; }; -- Gitee