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 #include "file_operations_local.h"
16
17 #include <cerrno>
18 #include <dirent.h>
19
20 #include "file_operations_cloud.h"
21 #include "file_operations_helper.h"
22 #include "utils_log.h"
23
24 namespace OHOS {
25 namespace FileManagement {
26 namespace CloudDisk {
27 using namespace std;
28 static const int32_t BUNDLE_NAME_OFFSET = 1000000000;
29 static const int32_t STAT_MODE_DIR = 0771;
30 static const float LOOKUP_TIMEOUT = 60.0;
31
DoLocalLookup(fuse_req_t req,fuse_ino_t parent,const char * name,struct fuse_entry_param * e)32 static int32_t DoLocalLookup(fuse_req_t req, fuse_ino_t parent, const char *name,
33 struct fuse_entry_param *e)
34 {
35 int32_t err = 0;
36 bool createFlag = false;
37 struct CloudDiskFuseData *data = reinterpret_cast<struct CloudDiskFuseData *>(fuse_req_userdata(req));
38 string path = FileOperationsHelper::GetCloudDiskLocalPath(data->userId, name);
39 std::unique_lock<std::shared_mutex> cWLock(data->cacheLock, std::defer_lock);
40 string key = std::to_string(parent) + name;
41 int64_t localId = FileOperationsHelper::FindLocalId(data, key);
42 auto child = FileOperationsHelper::FindCloudDiskInode(data, localId);
43 if (child == nullptr) {
44 child = make_shared<CloudDiskInode>();
45 createFlag = true;
46 LOGD("new child %{public}s", name);
47 }
48 std::unique_lock<std::shared_mutex> lWLock(data->localIdLock, std::defer_lock);
49 child->refCount++;
50 if (createFlag) {
51 err = stat(path.c_str(), &child->stat);
52 if (err != 0) {
53 LOGE("lookup %{public}s error, err: %{public}d", path.c_str(), errno);
54 return errno;
55 }
56 child->stat.st_mode |= STAT_MODE_DIR;
57 child->parent = parent;
58 child->path = path;
59 auto parentInode = FileOperationsHelper::FindCloudDiskInode(data, static_cast<int64_t>(parent));
60 child->layer = FileOperationsHelper::GetNextLayer(parentInode, parent);
61 localId = FileOperationsHelper::GetFixedLayerRootId(child->layer);
62 if (child->layer >= CLOUD_DISK_INODE_FIRST_LAYER) {
63 std::lock_guard<std::shared_mutex> bWLock(data->bundleNameIdLock);
64 data->bundleNameId++;
65 localId = data->bundleNameId + BUNDLE_NAME_OFFSET;
66 }
67 child->stat.st_ino = static_cast<uint64_t>(localId);
68 child->ops = make_shared<FileOperationsLocal>();
69 cWLock.lock();
70 data->inodeCache[localId] = child;
71 cWLock.unlock();
72 lWLock.lock();
73 data->localIdCache[key] = localId;
74 lWLock.unlock();
75 }
76 if (child->layer >= CLOUD_DISK_INODE_FIRST_LAYER) {
77 child->bundleName = name;
78 child->ops = make_shared<FileOperationsCloud>();
79 }
80 e->ino = static_cast<fuse_ino_t>(localId);
81 FileOperationsHelper::GetInodeAttr(child, &e->attr);
82 return 0;
83 }
84
Lookup(fuse_req_t req,fuse_ino_t parent,const char * name)85 void FileOperationsLocal::Lookup(fuse_req_t req, fuse_ino_t parent, const char *name) {}
86
GetAttr(fuse_req_t req,fuse_ino_t ino,struct fuse_file_info * fi)87 void FileOperationsLocal::GetAttr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
88 {
89 struct CloudDiskFuseData *data = reinterpret_cast<struct CloudDiskFuseData *>(fuse_req_userdata(req));
90 if (ino == FUSE_ROOT_ID) {
91 string path = FileOperationsHelper::GetCloudDiskRootPath(data->userId);
92
93 struct stat statBuf;
94 int err = stat(path.c_str(), &statBuf);
95 if (err != 0) {
96 LOGE("lookup %{public}s error, err: %{public}d", path.c_str(), err);
97 fuse_reply_err(req, err);
98 return;
99 }
100 fuse_reply_attr(req, &statBuf, 0);
101 return;
102 }
103 auto inoPtr = FileOperationsHelper::FindCloudDiskInode(data, static_cast<int64_t>(ino));
104 if (inoPtr == nullptr) {
105 fuse_reply_err(req, EINVAL);
106 LOGE("inode not found");
107 return;
108 }
109 fuse_reply_attr(req, &inoPtr->stat, 0);
110 }
111
ReadDir(fuse_req_t req,fuse_ino_t ino,size_t size,off_t off,struct fuse_file_info * fi)112 void FileOperationsLocal::ReadDir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
113 struct fuse_file_info *fi)
114 {
115 (void) fi;
116 string path;
117 struct CloudDiskFuseData *data =
118 reinterpret_cast<struct CloudDiskFuseData *>(fuse_req_userdata(req));
119 if (ino == FUSE_ROOT_ID) {
120 path = FileOperationsHelper::GetCloudDiskRootPath(data->userId);
121 } else {
122 auto inoPtr = FileOperationsHelper::FindCloudDiskInode(data, static_cast<int64_t>(ino));
123 if (inoPtr == nullptr) {
124 fuse_reply_err(req, EINVAL);
125 LOGE("inode not found");
126 return;
127 }
128 path = inoPtr->path;
129 }
130 DIR* dir = opendir(path.c_str());
131 if (dir == NULL) {
132 LOGE("opendir error %{public}d, path:%{public}s", errno, path.c_str());
133 return;
134 }
135
136 struct dirent *entry;
137 string entryData;
138 size_t len = 0;
139 while ((entry = readdir(dir)) != NULL) {
140 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
141 continue;
142 }
143
144 string childPath = FileOperationsHelper::GetCloudDiskLocalPath(data->userId,
145 entry->d_name);
146 int64_t key = FileOperationsHelper::FindLocalId(data, std::to_string(ino) +
147 entry->d_name);
148 auto childPtr = FileOperationsHelper::FindCloudDiskInode(data, key);
149 if (childPtr == nullptr) {
150 childPtr = FileOperationsHelper::GenerateCloudDiskInode(data, ino,
151 entry->d_name, childPath.c_str());
152 }
153 if (childPtr == nullptr) {
154 continue;
155 }
156 FileOperationsHelper::AddDirEntry(req, entryData, len, entry->d_name, childPtr);
157 }
158 FileOperationsHelper::FuseReplyLimited(req, entryData.c_str(), len, off, size);
159 closedir(dir);
160 return;
161 }
162 } // namespace CloudDisk
163 } // namespace FileManagement
164 } // namespace OHOS
165