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