1 /*
2 * Copyright (c) 2023 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_helper.h"
16
17 #include <unistd.h>
18
19 #include "file_operations_cloud.h"
20 #include "file_operations_local.h"
21 #include "securec.h"
22 #include "utils_log.h"
23
24 namespace OHOS {
25 namespace FileManagement {
26 namespace CloudDisk {
27 using namespace std;
28 namespace {
29 static const string LOCAL_PATH_DATA_SERVICE_EL2 = "/data/service/el2/";
30 static const string LOCAL_PATH_HMDFS_CLOUD_DATA = "/hmdfs/cloud/data/";
31 static const string LOCAL_PATH_HMDFS_CLOUD = "/hmdfs/cloud/";
32 }
33
GetCloudDiskRootPath(int32_t userId)34 string FileOperationsHelper::GetCloudDiskRootPath(int32_t userId)
35 {
36 return LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) + LOCAL_PATH_HMDFS_CLOUD;
37 }
38
GetCloudDiskLocalPath(int32_t userId,string fileName)39 string FileOperationsHelper::GetCloudDiskLocalPath(int32_t userId, string fileName)
40 {
41 if (fileName == "data") {
42 return LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) +
43 LOCAL_PATH_HMDFS_CLOUD_DATA;
44 } else if (fileName == "/") {
45 return GetCloudDiskRootPath(userId);
46 } else {
47 return LOCAL_PATH_DATA_SERVICE_EL2 + to_string(userId) +
48 LOCAL_PATH_HMDFS_CLOUD_DATA + fileName;
49 }
50 }
51
GetInodeAttr(shared_ptr<CloudDiskInode> ino,struct stat * statBuf)52 void FileOperationsHelper::GetInodeAttr(shared_ptr<CloudDiskInode> ino, struct stat *statBuf)
53 {
54 statBuf->st_ino = reinterpret_cast<fuse_ino_t>(ino.get());
55 statBuf->st_uid = ino->stat.st_uid;
56 statBuf->st_gid = ino->stat.st_gid;
57 statBuf->st_mtime = ino->stat.st_mtime;
58 statBuf->st_ctime = ino->stat.st_ctime;
59 statBuf->st_atime = ino->stat.st_atime;
60 statBuf->st_mode = ino->stat.st_mode;
61 statBuf->st_nlink = ino->stat.st_nlink;
62 if (statBuf->st_mode & S_IFREG) {
63 statBuf->st_size = ino->stat.st_size;
64 }
65 }
66
GetNextLayer(fuse_ino_t ino)67 int32_t FileOperationsHelper::GetNextLayer(fuse_ino_t ino)
68 {
69 if (ino == FUSE_ROOT_ID) {
70 return CLOUD_DISK_INODE_ZERO_LAYER;
71 }
72 struct CloudDiskInode *inoPtr = reinterpret_cast<struct CloudDiskInode *>(ino);
73 if (inoPtr->layer >= CLOUD_DISK_INODE_OTHER_LAYER) {
74 return CLOUD_DISK_INODE_OTHER_LAYER;
75 } else {
76 return inoPtr->layer + 1;
77 }
78 }
79
FindCloudDiskInode(struct CloudDiskFuseData * data,const string & key)80 shared_ptr<CloudDiskInode> FileOperationsHelper::FindCloudDiskInode(struct CloudDiskFuseData *data,
81 const string &key)
82 {
83 shared_ptr<CloudDiskInode> ret;
84 shared_lock<shared_mutex> rLock(data->cacheLock, std::defer_lock);
85 rLock.lock();
86 if (data->inodeCache.find(key) != data->inodeCache.end()) {
87 ret = data->inodeCache[key];
88 } else {
89 ret = nullptr;
90 }
91 rLock.unlock();
92 return ret;
93 }
94
FindCloudDiskFile(struct CloudDiskFuseData * data,const string & key)95 shared_ptr<CloudDiskFile> FileOperationsHelper::FindCloudDiskFile(struct CloudDiskFuseData *data,
96 const string &key)
97 {
98 shared_ptr<CloudDiskFile> ret;
99 shared_lock<shared_mutex> rLock(data->fileLock, std::defer_lock);
100 rLock.lock();
101 if (data->fileCache.find(key) != data->fileCache.end()) {
102 ret = data->fileCache[key];
103 } else {
104 ret = nullptr;
105 }
106 rLock.unlock();
107 return ret;
108 }
109
AddDirEntry(fuse_req_t req,std::string & buf,size_t & size,const char * name,std::shared_ptr<CloudDiskInode> ino)110 void FileOperationsHelper::AddDirEntry(fuse_req_t req, std::string &buf, size_t &size, const char *name,
111 std::shared_ptr<CloudDiskInode> ino)
112 {
113 size_t oldSize = size;
114 size += fuse_add_direntry(req, NULL, 0, name, NULL, 0);
115 buf.resize(size);
116 fuse_add_direntry(req, &buf[oldSize], size - oldSize, name, &ino->stat, size);
117 }
118
FuseReplyLimited(fuse_req_t req,const char * buf,size_t bufSize,off_t off,size_t maxSize)119 void FileOperationsHelper::FuseReplyLimited(fuse_req_t req, const char *buf, size_t bufSize,
120 off_t off, size_t maxSize)
121 {
122 if (off < bufSize) {
123 size_t size = (bufSize - off) < maxSize ? (bufSize - off) : maxSize;
124 fuse_reply_buf(req, buf + off, size);
125 } else {
126 fuse_reply_buf(req, NULL, 0);
127 }
128 }
129
GenerateCloudDiskInode(struct CloudDiskFuseData * data,struct CloudDiskInode * parent,const string & fileName,const string & path)130 shared_ptr<CloudDiskInode> FileOperationsHelper::GenerateCloudDiskInode(struct CloudDiskFuseData *data,
131 struct CloudDiskInode *parent,
132 const string &fileName,
133 const string &path)
134 {
135 std::unique_lock<std::shared_mutex> wLock(data->cacheLock, std::defer_lock);
136 shared_ptr<CloudDiskInode> child = make_shared<CloudDiskInode>();
137 int32_t err = stat(path.c_str(), &child->stat);
138 if (err != 0) {
139 LOGE("GenerateCloudDiskInode %{public}s error, err: %{public}d", path.c_str(), errno);
140 return nullptr;
141 }
142
143 child->refCount++;
144 child->parent = reinterpret_cast<fuse_ino_t>(parent);
145 child->path = path;
146 child->layer = GetNextLayer(child->parent);
147 child->stat.st_ino = reinterpret_cast<fuse_ino_t>(child.get());
148 child->ops = make_shared<FileOperationsLocal>();
149 wLock.lock();
150 data->inodeCache[path] = child;
151 wLock.unlock();
152 if (child->layer == CLOUD_DISK_INODE_FIRST_LAYER) {
153 child->bundleName = fileName;
154 child->ops = make_shared<FileOperationsCloud>();
155 }
156 return child;
157 }
158
PutCloudDiskInode(struct CloudDiskFuseData * data,shared_ptr<CloudDiskInode> inoPtr,uint64_t num,const string & key)159 void FileOperationsHelper::PutCloudDiskInode(struct CloudDiskFuseData *data,
160 shared_ptr<CloudDiskInode> inoPtr, uint64_t num, const string &key)
161 {
162 std::unique_lock<std::shared_mutex> wLock(data->cacheLock, std::defer_lock);
163 if (inoPtr == nullptr) {
164 LOGD("Get an invalid inode!");
165 return;
166 }
167 inoPtr->refCount -= num;
168 if (inoPtr->refCount == 0) {
169 LOGD("node released: %{public}s", key.c_str());
170 wLock.lock();
171 data->inodeCache.erase(key);
172 wLock.unlock();
173 }
174 }
175
PutCloudDiskFile(struct CloudDiskFuseData * data,shared_ptr<CloudDiskFile> filePtr,const string & key)176 void FileOperationsHelper::PutCloudDiskFile(struct CloudDiskFuseData *data,
177 shared_ptr<CloudDiskFile> filePtr, const string &key)
178 {
179 std::unique_lock<std::shared_mutex> wLock(data->fileLock, std::defer_lock);
180 if (filePtr == nullptr) {
181 LOGD("Get an invalid file!");
182 return;
183 }
184 if (filePtr->refCount == 0) {
185 LOGD("file released: %{public}s", key.c_str());
186 wLock.lock();
187 data->fileCache.erase(key);
188 wLock.unlock();
189 }
190 }
191 } // namespace CloudDisk
192 } // namespace FileManagement
193 } // namespace OHOS
194