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 "clouddisk_notify_utils.h"
17 #include "clouddisk_rdb_utils.h"
18 #include "file_column.h"
19 #include "cloud_pref_impl.h"
20 #include "dfs_error.h"
21 #include "utils_log.h"
22
23 namespace OHOS::FileManagement::CloudDisk {
24 const uint32_t MAX_QUERY_TIMES = 1024;
25 const string BUNDLENAME_FLAG = "<BundleName>";
26 const string CLOUDDISK_URI_PREFIX = "file://<BundleName>/data/storage/el2/cloud";
27 const string BACKFLASH = "/";
28 const int32_t CloudDiskNotifyUtils::maxCacheCnt_;
29 list<pair<string, CacheNode>> CloudDiskNotifyUtils::cacheList_;
30 unordered_map<string, list<pair<string, CacheNode>>::iterator> CloudDiskNotifyUtils::cacheMap_;
31 mutex CloudDiskNotifyUtils::cacheMutex_;
32
isRoot(const fuse_ino_t & ino)33 static bool isRoot(const fuse_ino_t &ino)
34 {
35 return ino == FUSE_ROOT_ID;
36 }
37
GetUriRecursively(CloudDiskFuseData * data,FindCloudDiskInodeFunc func,shared_ptr<CloudDiskInode> inoPtr,string & uri)38 static int32_t GetUriRecursively(CloudDiskFuseData* data, FindCloudDiskInodeFunc func,
39 shared_ptr<CloudDiskInode> inoPtr, string &uri)
40 {
41 string bundleName = inoPtr->bundleName;
42 string realPrefix = CLOUDDISK_URI_PREFIX;
43 realPrefix.replace(realPrefix.find(BUNDLENAME_FLAG), BUNDLENAME_FLAG.length(), bundleName);
44 uint32_t queryTimes = 0;
45 while (!isRoot(inoPtr->parent)) {
46 inoPtr = func(data, inoPtr->parent);
47 if (!inoPtr || inoPtr->fileName.empty()) {
48 break;
49 }
50 uri = inoPtr->fileName + BACKFLASH + uri;
51 queryTimes++;
52 if (uri.length() > PATH_MAX || queryTimes > MAX_QUERY_TIMES) {
53 return E_INVAL_ARG;
54 }
55 }
56 uri = realPrefix + BACKFLASH + uri;
57 LOGD("GetUriRecursively uri: %{public}s", GetAnonyString(uri).c_str());
58 return E_OK;
59 }
60
GetNotifyData(CloudDiskFuseData * data,FindCloudDiskInodeFunc func,const fuse_ino_t & ino,NotifyData & notifyData)61 int32_t CloudDiskNotifyUtils::GetNotifyData(CloudDiskFuseData* data, FindCloudDiskInodeFunc func,
62 const fuse_ino_t &ino, NotifyData ¬ifyData)
63 {
64 if (isRoot(ino)) {
65 return E_INVAL_ARG;
66 }
67 auto inoPtr = func(data, ino);
68 if (inoPtr == nullptr) {
69 LOGE("inode not found");
70 return E_INVAL_ARG;
71 }
72 notifyData.uri = inoPtr->fileName;
73 notifyData.isDir = inoPtr->stat.st_mode & S_IFDIR;
74 return GetUriRecursively(data, func, inoPtr, notifyData.uri);
75 }
76
GetNotifyData(CloudDiskFuseData * data,FindCloudDiskInodeFunc func,const fuse_ino_t & parent,const string & name,NotifyData & notifyData)77 int32_t CloudDiskNotifyUtils::GetNotifyData(CloudDiskFuseData* data, FindCloudDiskInodeFunc func,
78 const fuse_ino_t &parent, const string &name, NotifyData ¬ifyData)
79 {
80 auto inoPtr = func(data, parent);
81 if (inoPtr == nullptr) {
82 LOGE("inode not found");
83 return E_INVAL_ARG;
84 }
85 notifyData.uri = name;
86 if (!inoPtr->fileName.empty()) {
87 notifyData.uri = inoPtr->fileName + BACKFLASH + notifyData.uri;
88 }
89 return GetUriRecursively(data, func, inoPtr, notifyData.uri);
90 }
91
GetNotifyData(CloudDiskFuseData * data,FindCloudDiskInodeFunc func,shared_ptr<CloudDiskInode> inoPtr,NotifyData & notifyData)92 int32_t CloudDiskNotifyUtils::GetNotifyData(CloudDiskFuseData* data, FindCloudDiskInodeFunc func,
93 shared_ptr<CloudDiskInode> inoPtr, NotifyData ¬ifyData)
94 {
95 if (inoPtr == nullptr) {
96 LOGE("inode not found");
97 return E_INVAL_ARG;
98 }
99 notifyData.uri = inoPtr->fileName;
100 notifyData.isDir = inoPtr->stat.st_mode & S_IFDIR;
101 return GetUriRecursively(data, func, inoPtr, notifyData.uri);
102 }
103
GetNotifyData(CloudDiskFuseData * data,FindCloudDiskInodeFunc func,shared_ptr<CloudDiskInode> pInoPtr,const string & name,NotifyData & notifyData)104 int32_t CloudDiskNotifyUtils::GetNotifyData(CloudDiskFuseData* data, FindCloudDiskInodeFunc func,
105 shared_ptr<CloudDiskInode> pInoPtr, const string &name, NotifyData ¬ifyData)
106 {
107 if (pInoPtr == nullptr) {
108 LOGE("inode not found");
109 return E_INVAL_ARG;
110 }
111 notifyData.uri = name;
112 if (!pInoPtr->fileName.empty()) {
113 notifyData.uri = pInoPtr->fileName + BACKFLASH + notifyData.uri;
114 }
115 return GetUriRecursively(data, func, pInoPtr, notifyData.uri);
116 }
117
GetCacheNode(const string & cloudId,CacheNode & cacheNode)118 int32_t CloudDiskNotifyUtils::GetCacheNode(const string &cloudId, CacheNode &cacheNode)
119 {
120 lock_guard<mutex> lock(cacheMutex_);
121 auto it = cacheMap_.find(cloudId);
122 if (it == cacheMap_.end()) {
123 LOGI("Not fount in cache, id: %{public}s", cloudId.c_str());
124 return E_INVAL_ARG;
125 }
126 cacheList_.splice(cacheList_.begin(), cacheList_, it->second);
127 cacheNode = it->second->second;
128 return E_OK;
129 }
130
PutCacheNode(const string & cloudId,const CacheNode & cacheNode)131 void CloudDiskNotifyUtils::PutCacheNode(const string &cloudId, const CacheNode &cacheNode)
132 {
133 if (cacheNode.isDir != TYPE_DIR_STR) {
134 return;
135 }
136 lock_guard<mutex> lock(cacheMutex_);
137 auto it = cacheMap_.find(cloudId);
138 if (it != cacheMap_.end()) {
139 LOGD("update cache name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
140 it->second->second = cacheNode;
141 cacheList_.splice(cacheList_.begin(), cacheList_, it->second);
142 return;
143 }
144 if (cacheMap_.size() == maxCacheCnt_) {
145 LOGI("upto max, delete last one");
146 string deleteCloudId = cacheList_.back().first;
147 cacheList_.pop_back();
148 cacheMap_.erase(deleteCloudId);
149 }
150 LOGD("insert to cache name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
151 cacheList_.emplace_front(cloudId, cacheNode);
152 cacheMap_[cloudId] = cacheList_.begin();
153 }
154
GetUriFromCache(const string & bundleName,const string & rootId,const CacheNode & cacheNode,string & uri)155 int32_t CloudDiskNotifyUtils::GetUriFromCache(const string &bundleName,
156 const string &rootId,
157 const CacheNode &cacheNode,
158 string &uri)
159 {
160 CacheNode tmpCacheNode;
161 PutCacheNode(cacheNode.cloudId, cacheNode);
162 uri = cacheNode.fileName;
163 tmpCacheNode = cacheNode;
164 int32_t ret;
165 while (tmpCacheNode.parentCloudId != rootId) {
166 ret = GetCacheNode(tmpCacheNode.parentCloudId, tmpCacheNode);
167 if (ret != E_OK) {
168 return ret;
169 }
170 uri = tmpCacheNode.fileName + BACKFLASH + uri;
171 }
172 string realPrefix = CLOUDDISK_URI_PREFIX;
173 realPrefix.replace(realPrefix.find(BUNDLENAME_FLAG), BUNDLENAME_FLAG.length(), bundleName);
174 uri = realPrefix + BACKFLASH + uri;
175 return E_OK;
176 }
177 } // namespace OHOS::FileManagement::CloudDisk