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