• 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_rdbstore.h"
17 
18 #include <cinttypes>
19 #include <ctime>
20 #include <sys/stat.h>
21 #include <sstream>
22 #include <functional>
23 
24 #include "cloud_pref_impl.h"
25 #include "clouddisk_db_const.h"
26 #include "clouddisk_notify.h"
27 #include "clouddisk_notify_utils.h"
28 #include "clouddisk_rdb_transaction.h"
29 #include "clouddisk_rdb_utils.h"
30 #include "clouddisk_sync_helper.h"
31 #include "clouddisk_type_const.h"
32 #include "data_sync_const.h"
33 #include "dfs_error.h"
34 #include "directory_ex.h"
35 #include "file_column.h"
36 #include "ffrt_inner.h"
37 #include "nlohmann/json.hpp"
38 #include "parameter.h"
39 #include "parameters.h"
40 #include "rdb_errno.h"
41 #include "rdb_sql_utils.h"
42 #include "utils_log.h"
43 
44 namespace OHOS::FileManagement::CloudDisk {
45 using namespace std;
46 using namespace OHOS::NativeRdb;
47 using namespace CloudSync;
48 
49 enum XATTR_CODE {
50     ERROR_CODE = -1,
51     CLOUD_LOCATION = 1,
52     CLOUD_RECYCLE,
53     IS_FAVORITE,
54     FILE_SYNC_STATUS,
55     IS_EXT_ATTR,
56     TIME_RECYCLED,
57     HAS_THM
58 };
59 static constexpr int32_t LOOKUP_QUERY_LIMIT = 1;
60 static constexpr int32_t CHECK_QUERY_LIMIT = 2000;
61 static const uint32_t SET_STATE = 1;
62 static const uint32_t CANCEL_STATE = 0;
63 static const uint32_t MAX_FILE_NAME_SIZE = 246;
64 static const uint32_t MAX_QUERY_TIMES = 1024;
65 static const uint32_t STAT_MODE_DIR = 0771;
66 static const uint32_t STAT_MODE_REG = 0660;
67 const string BUNDLENAME_FLAG = "<BundleName>";
68 const string CLOUDDISK_URI_PREFIX = "file://<BundleName>/data/storage/el2/cloud";
69 const string BACKFLASH = "/";
70 static const string RECYCLE_FILE_NAME = ".trash";
71 static const string ROOT_CLOUD_ID = "rootId";
72 static const std::string FILEMANAGER_KEY = "persist.kernel.bundle_name.filemanager";
73 // srcPath only used in restore files
74 static const string SRC_PATH_KEY = "srcPath";
75 static const string LOCAL_PATH_MNT_HMDFS = "/mnt/hmdfs/";
76 static const string LOCAL_PATH_CLOUD_DATA = "/cloud/data/";
77 static const string FILE_SCHEME = "file";
78 
CloudSyncTriggerFunc(const std::vector<std::string> & args)79 static const std::string CloudSyncTriggerFunc(const std::vector<std::string> &args)
80 {
81     size_t size = args.size();
82     if (size != ARGS_SIZE) {
83         LOGE("CloudSyncTriggerFunc args size error, %{public}zu", size);
84         return "";
85     }
86     int32_t userId = std::strtol(args[ARG_USER_ID].c_str(), nullptr, 0);
87     string bundleName = args[ARG_BUNDLE_NAME];
88     LOGD("begin cloud sync trigger, bundleName: %{public}s, userId: %{public}d", bundleName.c_str(), userId);
89     return "";
90 }
91 
CloudDiskRdbStore(const std::string & bundleName,const int32_t & userId)92 CloudDiskRdbStore::CloudDiskRdbStore(const std::string &bundleName, const int32_t &userId)
93     : bundleName_(bundleName), userId_(userId)
94 {
95     RdbInit();
96 }
97 
~CloudDiskRdbStore()98 CloudDiskRdbStore::~CloudDiskRdbStore()
99 {
100     Stop();
101 }
102 
ReBuildDatabase(const string & databasePath)103 int32_t CloudDiskRdbStore::ReBuildDatabase(const string &databasePath)
104 {
105     LOGI("database need to be rebuilded");
106     int32_t errCode = RdbHelper::DeleteRdbStore(databasePath);
107     if (errCode != NativeRdb::E_OK) {
108         LOGE("Delete CloudDisk Database is failed, err = %{public}d", errCode);
109         return errCode;
110     }
111     errCode = 0;
112     CloudDiskDataCallBack rdbDataCallBack;
113     rdbStore_ = RdbHelper::GetRdbStore(config_, CLOUD_DISK_RDB_VERSION, rdbDataCallBack, errCode);
114     if (rdbStore_ == nullptr) {
115         LOGE("ReGetRdbStore is failed, userId_ = %{public}d, bundleName_ = %{public}s, errCode = %{public}d",
116              userId_, bundleName_.c_str(), errCode);
117         return errCode;
118     }
119     DatabaseRestore();
120     return E_OK;
121 }
122 
RdbInit()123 int32_t CloudDiskRdbStore::RdbInit()
124 {
125     if (WaitParameter("persist.kernel.move.finish", "true", MOVE_FILE_TIME_SERVICE) != 0) {
126         LOGE("wait move error");
127         return EBUSY;
128     }
129     LOGI("Init rdb store, userId_ = %{public}d, bundleName_ = %{public}s", userId_, bundleName_.c_str());
130     string baseDir = "/data/service/el2/" + to_string(userId_) + "/hmdfs/cloudfile_manager/";
131     string customDir = baseDir.append(system::GetParameter(FILEMANAGER_KEY, ""));
132     string name = CLOUD_DISK_DATABASE_NAME;
133     int32_t errCode = 0;
134     string databasePath = RdbSqlUtils::GetDefaultDatabasePath(customDir, CLOUD_DISK_DATABASE_NAME, errCode);
135     if (errCode != NativeRdb::E_OK) {
136         LOGE("Create Default Database Path is failed, errCode = %{public}d", errCode);
137         return E_PATH;
138     }
139     config_.SetName(name);
140     config_.SetPath(databasePath);
141     config_.SetReadConSize(CONNECT_SIZE);
142     config_.SetScalarFunction("cloud_sync_func", ARGS_SIZE, CloudSyncTriggerFunc);
143     errCode = 0;
144     CloudDiskDataCallBack rdbDataCallBack;
145     rdbStore_ = RdbHelper::GetRdbStore(config_, CLOUD_DISK_RDB_VERSION, rdbDataCallBack, errCode);
146     if (rdbStore_ == nullptr) {
147         LOGE("GetRdbStore is failed, userId_ = %{public}d, bundleName_ = %{public}s, errCode = %{public}d",
148              userId_, bundleName_.c_str(), errCode);
149         if (errCode == NativeRdb::E_SQLITE_CORRUPT) {
150             if (ReBuildDatabase(databasePath)) {
151                 LOGE("clouddisk db image is malformed, ReBuild failed");
152             }
153         }
154         return errCode;
155     } else if (errCode == NativeRdb::E_SQLITE_CORRUPT) { DatabaseRestore(); }
156     return E_OK;
157 }
158 
Stop()159 void CloudDiskRdbStore::Stop()
160 {
161     if (rdbStore_ == nullptr) {
162         return;
163     }
164     rdbStore_ = nullptr;
165 }
166 
GetRaw()167 shared_ptr<RdbStore> CloudDiskRdbStore::GetRaw()
168 {
169     return rdbStore_;
170 }
171 
DatabaseRestore()172 void CloudDiskRdbStore::DatabaseRestore()
173 {
174     if (rdbStore_ == nullptr) {
175         LOGE("rdbStore_ is nullptr");
176         return;
177     }
178     LOGI("clouddisk db image is malformed, need to restore");
179     auto fileName = "/data/service/el2/" + to_string(userId_) + "/hmdfs/cloudfile_manager/" +
180         system::GetParameter(FILEMANAGER_KEY, "") + "/backup/clouddisk_backup.db";
181     int32_t ret = -1;
182     if (access(fileName.c_str(), F_OK) == 0) {
183         {
184             lock_guard<mutex> lock(backupMutex_);
185             ret = rdbStore_->Restore(fileName);
186         }
187         if (ret != 0) {
188             LOGE("cloudisk restore failed, ret %{public}d", ret);
189         }
190     } else {
191         LOGE("clouddisk backup db is not exist");
192     }
193 }
194 
LookUp(const std::string & parentCloudId,const std::string & fileName,CloudDiskFileInfo & info)195 int32_t CloudDiskRdbStore::LookUp(const std::string &parentCloudId,
196     const std::string &fileName, CloudDiskFileInfo &info)
197 {
198     RDBPTR_IS_NULLPTR(rdbStore_);
199     if (fileName.empty() || parentCloudId.empty()) {
200         LOGE("look up parameters is invalid");
201         return E_INVAL_ARG;
202     }
203     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
204     lookUpPredicates
205         .EqualTo(FileColumn::PARENT_CLOUD_ID, parentCloudId)->And()
206         ->EqualTo(FileColumn::FILE_NAME, fileName)->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
207         ->EqualTo(FileColumn::ROOT_DIRECTORY, bundleName_)->And()
208         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
209     lookUpPredicates.Limit(LOOKUP_QUERY_LIMIT);
210     auto resultSet = rdbStore_->QueryByStep(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
211     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfo(move(resultSet), info);
212     if (ret != E_OK) {
213         LOGE("lookup file info is failed, ret %{public}d", ret);
214         return E_RDB;
215     }
216     return E_OK;
217 }
218 
GetAttr(const std::string & cloudId,CloudDiskFileInfo & info)219 int32_t CloudDiskRdbStore::GetAttr(const std::string &cloudId, CloudDiskFileInfo &info)
220 {
221     RDBPTR_IS_NULLPTR(rdbStore_);
222     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
223         LOGE("getAttr parameter is invalid");
224         return E_INVAL_ARG;
225     }
226     AbsRdbPredicates getAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
227     getAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
228     auto resultSet = rdbStore_->QueryByStep(getAttrPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
229     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfo(move(resultSet), info);
230     if (ret != E_OK) {
231         LOGE("get file attr is failed, ret %{public}d", ret);
232         return E_RDB;
233     }
234     return E_OK;
235 }
236 
SetAttr(const std::string & fileName,const std::string & parentCloudId,const std::string & cloudId,const unsigned long long & size)237 int32_t CloudDiskRdbStore::SetAttr(const std::string &fileName, const std::string &parentCloudId,
238     const std::string &cloudId, const unsigned long long &size)
239 {
240     RDBPTR_IS_NULLPTR(rdbStore_);
241     if (cloudId.empty()) {
242         LOGE("cloudId is empty");
243         return E_INVAL_ARG;
244     }
245     if (cloudId == ROOT_CLOUD_ID) {
246         LOGE("cloudId is rootId");
247         return E_INVAL_ARG;
248     }
249 
250     ValuesBucket setAttr;
251     setAttr.PutLong(FileColumn::FILE_SIZE, static_cast<int64_t>(size));
252     TransactionOperations rdbTransaction(rdbStore_);
253     auto [ret, transaction] = rdbTransaction.Start();
254     if (ret != E_OK) {
255         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
256         return ret;
257     }
258     int32_t changedRows = -1;
259     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
260     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
261     std::tie(ret, changedRows) = transaction->Update(setAttr, predicates);
262     if (ret != E_OK) {
263         LOGE("setAttr size fail, ret: %{public}d, changeRow is %{public}d", ret, changedRows);
264         return E_RDB;
265     }
266 
267     MetaBase metaBase(fileName, cloudId);
268     metaBase.size = size;
269     auto callback = [&metaBase] (MetaBase &m) {
270         m.size = metaBase.size;
271     };
272     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
273     ret = metaFile->DoLookupAndUpdate(fileName, callback);
274     if (ret != E_OK) {
275         LOGE("update new dentry failed, ret = %{public}d", ret);
276         return ret;
277     }
278     rdbTransaction.Finish();
279     return E_OK;
280 }
281 
ReadDir(const std::string & cloudId,vector<CloudDiskFileInfo> & infos)282 int32_t CloudDiskRdbStore::ReadDir(const std::string &cloudId, vector<CloudDiskFileInfo> &infos)
283 {
284     RDBPTR_IS_NULLPTR(rdbStore_);
285     CLOUDID_IS_NULL(cloudId);
286     AbsRdbPredicates readDirPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
287     readDirPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, cloudId)
288         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
289         ->EqualTo(FileColumn::ROOT_DIRECTORY, bundleName_)->And()
290         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
291     auto resultSet = rdbStore_->QueryByStep(readDirPredicates, { FileColumn::FILE_NAME, FileColumn::IS_DIRECTORY });
292     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfos(move(resultSet), infos);
293     if (ret != E_OK) {
294         LOGE("read directory is failed, ret %{public}d", ret);
295         return E_RDB;
296     }
297     return E_OK;
298 }
299 
GetFileExtension(const std::string & fileName,std::string & extension)300 static int32_t GetFileExtension(const std::string &fileName, std::string &extension)
301 {
302     size_t dotIndex = fileName.rfind(".");
303     if (dotIndex != string::npos) {
304         extension = fileName.substr(dotIndex + 1);
305         return E_OK;
306     }
307     LOGE("Failed to obtain file extension");
308     return E_INVAL_ARG;
309 }
310 
FillFileType(const std::string & fileName,ValuesBucket & fileInfo)311 static void FillFileType(const std::string &fileName, ValuesBucket &fileInfo)
312 {
313     string extension;
314     if (!GetFileExtension(fileName, extension)) {
315         fileInfo.PutString(FileColumn::FILE_CATEGORY, extension);
316     }
317 }
318 
UTCTimeMilliSeconds()319 static int64_t UTCTimeMilliSeconds()
320 {
321     struct timespec t;
322     clock_gettime(CLOCK_REALTIME, &t);
323     return t.tv_sec * SECOND_TO_MILLISECOND + t.tv_nsec / MILLISECOND_TO_NANOSECOND;
324 }
325 
CheckNameForSpace(const std::string & fileName,const int32_t isDir)326 static int32_t CheckNameForSpace(const std::string& fileName, const int32_t isDir)
327 {
328     if (fileName.empty()) {
329         return EINVAL;
330     }
331     if (fileName[0] == ' ') {
332         LOGI("Illegal name");
333         return EINVAL;
334     }
335     if (isDir == DIRECTORY) {
336         if ((fileName.length() >= 1 && fileName[fileName.length() - 1] == ' ') || fileName == RECYCLE_FILE_NAME) {
337             LOGI("Illegal name");
338             return EINVAL;
339         }
340     }
341     return E_OK;
342 }
343 
CheckName(const std::string & fileName)344 static int32_t CheckName(const std::string &fileName)
345 {
346     if (fileName.empty() ||
347         fileName == "." ||
348         fileName == ".." ||
349         fileName.length() > MAX_FILE_NAME_SIZE) {
350         return EINVAL;
351     }
352     std::map<char, bool> illegalCharacter = {
353         {'<', true},
354         {'>', true},
355         {'|', true},
356         {':', true},
357         {'?', true},
358         {'/', true},
359         {'\\', true},
360         {'"', true},
361         {'*', true},
362     };
363     for (char c : fileName) {
364         if (illegalCharacter.find(c) != illegalCharacter.end()) {
365             LOGI("Illegal name");
366             return EINVAL;
367         }
368     }
369     return E_OK;
370 }
371 
CreateFile(const std::string & fileName,const std::string & filePath,ValuesBucket & fileInfo,struct stat * statInfo)372 static int32_t CreateFile(const std::string &fileName, const std::string &filePath, ValuesBucket &fileInfo,
373     struct stat *statInfo)
374 {
375     int32_t ret = stat(filePath.c_str(), statInfo);
376     if (ret) {
377         LOGE("filePath %{private}s is invalid", GetAnonyString(filePath).c_str());
378         return E_PATH;
379     }
380     fileInfo.PutInt(FileColumn::IS_DIRECTORY, FILE);
381     fileInfo.PutLong(FileColumn::FILE_SIZE, statInfo->st_size);
382     fileInfo.PutLong(FileColumn::FILE_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
383     fileInfo.PutLong(FileColumn::META_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
384     fileInfo.PutLong(FileColumn::LCD_FLAG, NO_THM_TO_DOWNLOAD);
385     fileInfo.PutLong(FileColumn::THM_FLAG, NO_THM_TO_DOWNLOAD);
386     FillFileType(fileName, fileInfo);
387     return E_OK;
388 }
389 
CreateDentry(MetaBase & metaBase,uint32_t userId,const std::string & bundleName,const std::string & fileName,const std::string & parentCloudId)390 static int32_t CreateDentry(MetaBase &metaBase, uint32_t userId, const std::string &bundleName,
391     const std::string &fileName, const std::string &parentCloudId)
392 {
393     auto callback = [&metaBase] (MetaBase &m) {
394         m.cloudId = metaBase.cloudId;
395         m.atime = metaBase.atime;
396         m.mtime = metaBase.mtime;
397         m.size = metaBase.size;
398         m.mode = metaBase.mode;
399         m.position = metaBase.position;
400         m.fileType = metaBase.fileType;
401         m.noUpload = metaBase.noUpload;
402     };
403     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
404     int32_t ret = metaFile->DoLookupAndUpdate(fileName, callback);
405     if (ret != E_OK) {
406         LOGE("update new dentry failed, ret = %{public}d", ret);
407         return ret;
408     }
409     return E_OK;
410 }
411 
UpdateMetabase(MetaBase & metaBase,int64_t fileTimeAdded,struct stat * statInfo)412 static void UpdateMetabase(MetaBase &metaBase, int64_t fileTimeAdded, struct stat *statInfo)
413 {
414     metaBase.atime = static_cast<uint64_t>(fileTimeAdded);
415     metaBase.mtime = static_cast<uint64_t>(CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
416     metaBase.mode = statInfo->st_mode;
417     metaBase.size = static_cast<uint64_t>(statInfo->st_size);
418     metaBase.position = LOCAL;
419     metaBase.fileType = FILE_TYPE_CONTENT;
420 }
421 
HandleCreateValue(ValuesBucket & fileInfo,const std::string & cloudId,const std::string & parentCloudId,const std::string & fileName,const std::string & bundleName)422 static void HandleCreateValue(ValuesBucket &fileInfo, const std::string &cloudId, const std::string &parentCloudId,
423                               const std::string &fileName, const std::string &bundleName)
424 {
425     fileInfo.PutString(FileColumn::CLOUD_ID, cloudId);
426     fileInfo.PutString(FileColumn::FILE_NAME, fileName);
427     fileInfo.PutString(FileColumn::PARENT_CLOUD_ID, parentCloudId);
428     fileInfo.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_NO_NEED_UPLOAD));
429     fileInfo.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::NEW));
430     fileInfo.PutString(FileColumn::ROOT_DIRECTORY, bundleName);
431 }
432 
Create(const std::string & cloudId,const std::string & parentCloudId,const std::string & fileName,bool noNeedUpload)433 int32_t CloudDiskRdbStore::Create(const std::string &cloudId, const std::string &parentCloudId,
434     const std::string &fileName, bool noNeedUpload)
435 {
436     int32_t ret = CheckName(fileName);
437     if (ret != E_OK) {
438         return ret;
439     }
440     ret = CheckNameForSpace(fileName, FILE);
441     if (ret != E_OK) {
442         return ret;
443     }
444     RDBPTR_IS_NULLPTR(rdbStore_);
445     ValuesBucket fileInfo;
446     if (cloudId.empty() || parentCloudId.empty() || fileName.empty()) {
447         LOGE("create parameter is invalid");
448         return E_INVAL_ARG;
449     }
450 
451     MetaBase metaBase(fileName, cloudId);
452     if (noNeedUpload) {
453         fileInfo.PutInt(FileColumn::NO_NEED_UPLOAD, NO_UPLOAD);
454         metaBase.noUpload = NO_UPLOAD;
455     }
456 
457     int64_t fileTimeAdded = UTCTimeMilliSeconds();
458     fileInfo.PutLong(FileColumn::FILE_TIME_ADDED, fileTimeAdded);
459     HandleCreateValue(fileInfo, cloudId, parentCloudId, fileName, bundleName_);
460     struct stat statInfo {};
461     string filePath = CloudFileUtils::GetLocalFilePath(cloudId, bundleName_, userId_);
462     if (CreateFile(fileName, filePath, fileInfo, &statInfo)) {
463         LOGE("file path is invalid, cannot create file record");
464         return E_PATH;
465     }
466     TransactionOperations rdbTransaction(rdbStore_);
467     auto [rdbRet, transaction] = rdbTransaction.Start();
468     if (rdbRet != E_OK) {
469         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
470         return rdbRet;
471     }
472     int64_t outRowId = 0;
473     std::tie(rdbRet, outRowId) = transaction->Insert(FileColumn::FILES_TABLE, fileInfo);
474     if (rdbRet != E_OK) {
475         LOGE("insert new file record in DB is failed, ret = %{public}d", ret);
476         return rdbRet;
477     }
478 
479     UpdateMetabase(metaBase, fileTimeAdded, &statInfo);
480     ret = CreateDentry(metaBase, userId_, bundleName_, fileName, parentCloudId);
481     if (ret != E_OK) {
482         LOGE("create new dentry failed, ret = %{public}d", ret);
483         return ret;
484     }
485     rdbTransaction.Finish();
486     return E_OK;
487 }
488 
MkDir(const std::string & cloudId,const std::string & parentCloudId,const std::string & directoryName,bool noNeedUpload)489 int32_t CloudDiskRdbStore::MkDir(const std::string &cloudId, const std::string &parentCloudId,
490     const std::string &directoryName, bool noNeedUpload)
491 {
492     int32_t ret = CheckName(directoryName);
493     if (ret != E_OK) {
494         return ret;
495     }
496     ret = CheckNameForSpace(directoryName, DIRECTORY);
497     if (ret != E_OK) {
498         return ret;
499     }
500     RDBPTR_IS_NULLPTR(rdbStore_);
501     ValuesBucket dirInfo;
502     if (cloudId.empty() || parentCloudId.empty() || directoryName.empty()) {
503         LOGE("make directory parameter is invalid");
504         return E_INVAL_ARG;
505     }
506 
507     MetaBase metaBase(directoryName, cloudId);
508     if (noNeedUpload) {
509         dirInfo.PutInt(FileColumn::NO_NEED_UPLOAD, NO_UPLOAD);
510         metaBase.noUpload = NO_UPLOAD;
511     }
512 
513     dirInfo.PutString(FileColumn::CLOUD_ID, cloudId);
514     dirInfo.PutString(FileColumn::FILE_NAME, directoryName);
515     int64_t fileTimeAdded = UTCTimeMilliSeconds();
516     dirInfo.PutLong(FileColumn::FILE_TIME_ADDED, fileTimeAdded);
517     int64_t fileTimeEdited = UTCTimeMilliSeconds();
518     dirInfo.PutLong(FileColumn::FILE_TIME_EDITED, fileTimeEdited);
519     int64_t metaTimeEdited = UTCTimeMilliSeconds();
520     dirInfo.PutLong(FileColumn::META_TIME_EDITED, metaTimeEdited);
521     dirInfo.PutInt(FileColumn::IS_DIRECTORY, DIRECTORY);
522     dirInfo.PutString(FileColumn::PARENT_CLOUD_ID, parentCloudId);
523     dirInfo.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::NEW));
524     dirInfo.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
525     dirInfo.PutString(FileColumn::ROOT_DIRECTORY, bundleName_);
526     TransactionOperations rdbTransaction(rdbStore_);
527     std::shared_ptr<Transaction> transaction;
528     std::tie(ret, transaction) = rdbTransaction.Start();
529     if (ret != E_OK) {
530         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
531         return ret;
532     }
533     int64_t outRowId = 0;
534     std::tie(ret, outRowId) = transaction->Insert(FileColumn::FILES_TABLE, dirInfo);
535     if (ret != E_OK) {
536         LOGE("insert new directory record in DB is failed, ret = %{public}d", ret);
537         return ret;
538     }
539 
540     metaBase.atime = static_cast<uint64_t>(fileTimeAdded);
541     metaBase.mtime = static_cast<uint64_t>(fileTimeEdited);
542     metaBase.mode = S_IFDIR | STAT_MODE_DIR;
543     metaBase.position = LOCAL;
544     metaBase.fileType = FILE_TYPE_CONTENT;
545     ret = CreateDentry(metaBase, userId_, bundleName_, directoryName, parentCloudId);
546     if (ret != E_OK) {
547         LOGE("create new dentry failed, ret = %{public}d", ret);
548         return ret;
549     }
550     rdbTransaction.Finish();
551     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
552     return E_OK;
553 }
554 
HandleWriteValue(ValuesBucket & write,int32_t position,struct stat & statInfo)555 static void HandleWriteValue(ValuesBucket &write, int32_t position, struct stat &statInfo)
556 {
557     write.PutLong(FileColumn::FILE_SIZE, statInfo.st_size);
558     write.PutLong(FileColumn::FILE_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
559     write.PutLong(FileColumn::META_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
560     write.PutLong(FileColumn::FILE_TIME_VISIT, CloudFileUtils::Timespec2Milliseconds(statInfo.st_atim));
561     write.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
562     if (position != LOCAL) {
563         write.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_FDIRTY));
564         write.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::UPDATE));
565     } else {
566         write.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_NEW));
567     }
568 }
569 
WriteUpdateDentry(MetaBase & metaBase,uint32_t userId,const std::string & bundleName,const std::string & fileName,const std::string & parentCloudId)570 static int32_t WriteUpdateDentry(MetaBase &metaBase, uint32_t userId, const std::string &bundleName,
571     const std::string &fileName, const std::string &parentCloudId)
572 {
573     auto callback = [&metaBase] (MetaBase &m) {
574         m.mtime = metaBase.mtime;
575         m.size = metaBase.size;
576     };
577     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
578     LOGD("write update dentry start");
579     int32_t ret = metaFile->DoChildUpdate(fileName, callback);
580     if (ret != E_OK) {
581         LOGE("update new dentry failed, ret = %{public}d", ret);
582         return ret;
583     }
584     return ret;
585 }
586 
Write(const std::string & fileName,const std::string & parentCloudId,const std::string & cloudId)587 int32_t CloudDiskRdbStore::Write(const std::string &fileName, const std::string &parentCloudId,
588     const std::string &cloudId)
589 {
590     RDBPTR_IS_NULLPTR(rdbStore_);
591     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
592         LOGE("write parameter is invalid");
593         return E_INVAL_ARG;
594     }
595     TransactionOperations rdbTransaction(rdbStore_);
596     auto [ret, transaction] = rdbTransaction.Start();
597     if (ret != E_OK) {
598         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
599         return ret;
600     }
601     string filePath = CloudFileUtils::GetLocalFilePath(cloudId, bundleName_, userId_);
602     struct stat statInfo {};
603     ret = stat(filePath.c_str(), &statInfo);
604     if (ret) {
605         LOGE("filePath %{private}s is invalid", GetAnonyString(filePath).c_str());
606         return E_PATH;
607     }
608     CloudDiskFileInfo info;
609     if (GetAttr(cloudId, info)) {
610         LOGE("get write cloudId info in DB fail");
611         return E_RDB;
612     }
613     int32_t position = static_cast<int32_t>(info.location);
614     ValuesBucket write;
615     HandleWriteValue(write, position, statInfo);
616     int32_t changedRows = -1;
617     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
618     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
619     std::tie(ret, changedRows) = transaction->Update(write, predicates);
620     if (ret != E_OK) {
621         LOGE("write file record in DB fail, ret %{public}d", ret);
622         return E_RDB;
623     }
624     MetaBase metaBase(fileName, cloudId);
625     metaBase.mtime = static_cast<uint64_t>(CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
626     metaBase.size = static_cast<uint64_t>(statInfo.st_size);
627     ret = WriteUpdateDentry(metaBase, userId_, bundleName_, fileName, parentCloudId);
628     if (ret != E_OK) {
629         LOGE("write update dentry failed, ret %{public}d", ret);
630         return E_RDB;
631     }
632     rdbTransaction.Finish();
633     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
634     return E_OK;
635 }
636 
LocationSetXattr(const std::string & name,const std::string & parentCloudId,const std::string & cloudId,const std::string & value)637 int32_t CloudDiskRdbStore::LocationSetXattr(const std::string &name, const std::string &parentCloudId,
638     const std::string &cloudId, const std::string &value)
639 {
640     RDBPTR_IS_NULLPTR(rdbStore_);
641     int32_t val = -1;
642     istringstream transfer(value);
643     transfer >> val;
644     if (val != LOCAL && val != CLOUD && val != LOCAL_AND_CLOUD) {
645         LOGE("setxattr unknown value");
646         return E_INVAL_ARG;
647     }
648     ValuesBucket setXAttr;
649     setXAttr.PutInt(FileColumn::POSITION, val);
650     int32_t changedRows = -1;
651     TransactionOperations rdbTransaction(rdbStore_);
652     auto [ret, transaction] = rdbTransaction.Start();
653     if (ret != E_OK) {
654         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
655         return ret;
656     }
657     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
658     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
659     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
660     if (ret != E_OK) {
661         LOGE("set xAttr location fail, ret %{public}d", ret);
662         return E_RDB;
663     }
664     MetaBase metaBase(name, cloudId);
665     auto callback = [&val] (MetaBase &m) {
666         m.position = val;
667     };
668     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
669     ret = metaFile->DoLookupAndUpdate(name, callback);
670     if (ret != E_OK) {
671         LOGE("update new dentry failed, ret = %{public}d", ret);
672         return ret;
673     }
674     rdbTransaction.Finish();
675     return E_OK;
676 }
677 
HasTHMSetXattr(const std::string & name,const std::string & key,const std::string & cloudId,const std::string & value)678 int32_t CloudDiskRdbStore::HasTHMSetXattr(const std::string &name, const std::string &key,
679     const std::string &cloudId, const std::string &value)
680 {
681     RDBPTR_IS_NULLPTR(rdbStore_);
682     if (!all_of(value.begin(), value.end(), ::isdigit)) {
683         return E_INVAL_ARG;
684     }
685     int32_t val = std::stoi(value);
686     if (val != 0 && val != 1) {
687         LOGE("setxattr unknown value");
688         return E_INVAL_ARG;
689     }
690 
691     ValuesBucket setXAttr;
692     if (val == 0) {
693         if (key == CLOUD_HAS_LCD) {
694             setXAttr.PutInt(FileColumn::LCD_FLAG, NO_THM_TO_DOWNLOAD);
695         } else {
696             setXAttr.PutInt(FileColumn::THM_FLAG, NO_THM_TO_DOWNLOAD);
697         }
698     } else {
699         if (key == CLOUD_HAS_LCD) {
700             setXAttr.PutInt(FileColumn::LCD_FLAG, DOWNLOADED_THM);
701         } else {
702             setXAttr.PutInt(FileColumn::THM_FLAG, DOWNLOADED_THM);
703         }
704     }
705     int32_t dirtyType;
706     TransactionOperations rdbTransaction(rdbStore_);
707     auto [ret, transaction] = rdbTransaction.Start();
708     RETURN_ON_ERR(GetDirtyType(cloudId, dirtyType));
709     if (dirtyType == static_cast<int32_t>(DirtyType::TYPE_SYNCED)) {
710         setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
711     }
712     int32_t changedRows = -1;
713     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
714     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
715     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
716     if (ret != E_OK) {
717         LOGE("set xAttr thm_flag fail, ret %{public}d", ret);
718         return E_RDB;
719     }
720     rdbTransaction.Finish();
721     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
722     return E_OK;
723 }
724 
725 
GetRowId(const std::string & cloudId,int64_t & rowId)726 int32_t CloudDiskRdbStore::GetRowId(const std::string &cloudId, int64_t &rowId)
727 {
728     RDBPTR_IS_NULLPTR(rdbStore_);
729     CLOUDID_IS_NULL(cloudId);
730     AbsRdbPredicates getRowIdPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
731     getRowIdPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
732     auto resultSet = rdbStore_->QueryByStep(getRowIdPredicates, {FileColumn::ROW_ID});
733     if (resultSet == nullptr) {
734         LOGE("get nullptr result set");
735         return E_RDB;
736     }
737     if (resultSet->GoToNextRow() != E_OK) {
738         LOGE("getRowId result set go to next row failed");
739         return E_RDB;
740     }
741     CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet);
742     return E_OK;
743 }
744 
RecycleSetValue(TrashOptType val,ValuesBucket & setXAttr,int32_t position)745 static int32_t RecycleSetValue(TrashOptType val, ValuesBucket &setXAttr, int32_t position)
746 {
747     if (position != LOCAL) {
748         setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
749     } else {
750         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::NEW));
751     }
752     if (val == TrashOptType::RESTORE) {
753         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::RESTORE));
754         setXAttr.PutLong(FileColumn::FILE_TIME_RECYCLED, CANCEL_STATE);
755         setXAttr.PutInt(FileColumn::DIRECTLY_RECYCLED, CANCEL_STATE);
756         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
757     } else if (val == TrashOptType::RECYCLE) {
758         int64_t recycledTime = UTCTimeMilliSeconds();
759         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::DELETE));
760         setXAttr.PutLong(FileColumn::FILE_TIME_RECYCLED, recycledTime);
761         setXAttr.PutInt(FileColumn::DIRECTLY_RECYCLED, SET_STATE);
762         setXAttr.PutLong(FileColumn::META_TIME_EDITED, recycledTime);
763     } else {
764         LOGE("invalid value");
765         return E_RDB;
766     }
767     return E_OK;
768 }
769 
GetParentCloudId(const std::string & cloudId,std::string & parentCloudId)770 int32_t CloudDiskRdbStore::GetParentCloudId(const std::string &cloudId, std::string &parentCloudId)
771 {
772     RDBPTR_IS_NULLPTR(rdbStore_);
773     AbsRdbPredicates getParentCloudIdPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
774     getParentCloudIdPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
775     auto resultSet = rdbStore_->QueryByStep(getParentCloudIdPredicates, { FileColumn::PARENT_CLOUD_ID });
776     if (resultSet == nullptr) {
777         LOGE("get nullptr parentCloudId resultSet");
778         return E_RDB;
779     }
780     if (resultSet->GoToNextRow() != E_OK) {
781         LOGE("get parentCloudId go to next row failed");
782         return E_RDB;
783     }
784     int32_t ret = CloudDiskRdbUtils::GetString(FileColumn::PARENT_CLOUD_ID, parentCloudId, resultSet);
785     if (ret != E_OK) {
786         LOGE("get parent cloudId failed");
787         return ret;
788     }
789     return E_OK;
790 }
791 
ConvertUriToSrcPath(const string & uriStr)792 static string ConvertUriToSrcPath(const string &uriStr)
793 {
794     Uri uri(uriStr);
795     string scheme = uri.GetScheme();
796     if (scheme != FILE_SCHEME) {
797         return "/";
798     }
799     const string sandboxPrefix = "/data/storage/el2/cloud";
800     string filePath = uri.GetPath().substr(sandboxPrefix.length());
801     size_t pos = filePath.rfind("/");
802     filePath = pos == 0 ? "/" : filePath.substr(0, pos);
803     return filePath;
804 }
805 
GetSourcePath(const string & attr,const string & parentCloudId,string & sourcePath)806 int32_t CloudDiskRdbStore::GetSourcePath(const string &attr, const string &parentCloudId, string &sourcePath)
807 {
808     nlohmann::json jsonObject = nlohmann::json::parse(attr, nullptr, false);
809     if (jsonObject.is_discarded() || (!jsonObject.is_object())) {
810         LOGD("jsonObject is discarded");
811         jsonObject = nlohmann::json::object();
812     }
813     if (jsonObject.contains(SRC_PATH_KEY) && jsonObject[SRC_PATH_KEY].is_string()) {
814         sourcePath = jsonObject[SRC_PATH_KEY].get<std::string>();
815         return E_OK;
816     }
817 
818     string uri;
819     int32_t ret = GetUriFromDB(parentCloudId, uri);
820     if (ret == E_OK) {
821         sourcePath == ConvertUriToSrcPath(uri);
822     } else {
823         LOGI("file src path fail, restore to root dir");
824     }
825     return E_OK;
826 }
827 
SourcePathSetValue(const string & cloudId,const string & attr,ValuesBucket & setXattr)828 int32_t CloudDiskRdbStore::SourcePathSetValue(const string &cloudId, const string &attr, ValuesBucket &setXattr)
829 {
830     RDBPTR_IS_NULLPTR(rdbStore_);
831     string uri;
832     CacheNode cacheNode = {cloudId};
833     RETURN_ON_ERR(GetCurNode(cloudId, cacheNode));
834     int32_t ret = GetNotifyUri(cacheNode, uri);
835     if (ret != E_OK) {
836         LOGE("failed to get source path, ret=%{public}d", ret);
837         return ret;
838     }
839     string filePath = ConvertUriToSrcPath(uri);
840     nlohmann::json jsonObject = nlohmann::json::parse(attr, nullptr, false);
841     if (jsonObject.is_discarded() || (!jsonObject.is_object())) {
842         LOGD("jsonObject is discarded");
843         jsonObject = nlohmann::json::object();
844     }
845     jsonObject[SRC_PATH_KEY] = filePath;
846     string attrStr = jsonObject.dump();
847     setXattr.PutString(FileColumn::ATTRIBUTE, attrStr);
848     return E_OK;
849 }
850 
UpdateParent(const int32_t userId,const string & bundleName,const string & srcPath,string & parentCloudId)851 static int32_t UpdateParent(const int32_t userId, const string &bundleName, const string &srcPath,
852     string &parentCloudId)
853 {
854     // root dir no need create
855     if (srcPath.empty() || srcPath == "/") {
856         parentCloudId = ROOT_CLOUD_ID;
857         return E_OK;
858     }
859 
860     string parentDir = LOCAL_PATH_MNT_HMDFS + to_string(userId) + LOCAL_PATH_CLOUD_DATA + bundleName + srcPath;
861     if (!ForceCreateDirectory(parentDir)) {
862         LOGE("create parent dir fail, %{public}s", GetAnonyString(parentDir).c_str());
863         return errno;
864     }
865     parentCloudId = CloudFileUtils::GetCloudId(parentDir);
866     return E_OK;
867 }
868 
RecycleSetXattr(const std::string & name,const std::string & parentCloudId,const std::string & cloudId,const std::string & value)869 int32_t CloudDiskRdbStore::RecycleSetXattr(const std::string &name, const std::string &parentCloudId,
870     const std::string &cloudId, const std::string &value)
871 {
872     bool isNum = std::all_of(value.begin(), value.end(), ::isdigit);
873     if (!isNum) {
874         return EINVAL;
875     }
876     int32_t val = std::stoi(value);
877     if (val == static_cast<int32_t>(TrashOptType::RESTORE)) {
878         return HandleRestoreXattr(name, parentCloudId, cloudId);
879     }
880     if (val == static_cast<int32_t>(TrashOptType::RECYCLE)) {
881         return HandleRecycleXattr(name, parentCloudId, cloudId);
882     }
883     return EINVAL;
884 }
885 
HandleRestoreXattr(const string & name,const string & parentCloudId,const string & cloudId)886 int32_t CloudDiskRdbStore::HandleRestoreXattr(const string &name, const string &parentCloudId, const string &cloudId)
887 {
888     RDBPTR_IS_NULLPTR(rdbStore_);
889     int64_t rowId = 0;
890     int32_t position = -1;
891     string attr;
892     TransactionOperations rdbTransaction(rdbStore_);
893     auto [ret, transaction] = rdbTransaction.Start();
894     if (ret != E_OK) {
895         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
896         return ret;
897     }
898     ret = GetRecycleInfo(transaction, cloudId, rowId, position, attr);
899     if (ret != E_OK) {
900         LOGE("get recycle fields fail, ret %{public}d", ret);
901         return E_RDB;
902     }
903     rdbTransaction.Finish();
904 
905     string realParentCloudId = parentCloudId;
906     string srcPath = "/";
907     RETURN_ON_ERR(GetSourcePath(attr, parentCloudId, srcPath));
908     RETURN_ON_ERR(UpdateParent(userId_, bundleName_, srcPath, realParentCloudId));
909 
910     ValuesBucket setXAttr;
911     setXAttr.PutString(FileColumn::PARENT_CLOUD_ID, realParentCloudId);
912     ret = RecycleSetValue(TrashOptType::RESTORE, setXAttr, position);
913     if (ret != E_OK) {
914         return ret;
915     }
916 
917     TransactionOperations rdbTransactionUpdate(rdbStore_);
918     tie(ret, transaction) = rdbTransactionUpdate.Start();
919     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
920     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
921 
922     int32_t changedRows = -1;
923     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
924     if (ret != E_OK) {
925         LOGE("set xAttr location fail, ret %{public}d", ret);
926         return E_RDB;
927     }
928     ret = MetaFileMgr::GetInstance().RemoveFromRecycleDentryfile(userId_, bundleName_, name, realParentCloudId, rowId);
929     if (ret != E_OK) {
930         LOGE("recycle set dentryfile failed, ret = %{public}d", ret);
931         return ret;
932     }
933     rdbTransactionUpdate.Finish();
934     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
935     return E_OK;
936 }
937 
HandleRecycleXattr(const string & name,const string & parentCloudId,const string & cloudId)938 int32_t CloudDiskRdbStore::HandleRecycleXattr(const string &name, const string &parentCloudId, const string &cloudId)
939 {
940     RDBPTR_IS_NULLPTR(rdbStore_);
941     int64_t rowId = 0;
942     int32_t position = -1;
943     string attr;
944     TransactionOperations rdbTransaction(rdbStore_);
945     auto [ret, transaction] = rdbTransaction.Start();
946     if (ret != E_OK) {
947         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
948         return ret;
949     }
950     ret = GetRecycleInfo(transaction, cloudId, rowId, position, attr);
951     if (ret != E_OK) {
952         LOGE("get rowId and position fail, ret %{public}d", ret);
953         return E_RDB;
954     }
955     ValuesBucket setXAttr;
956     SourcePathSetValue(cloudId, attr, setXAttr);
957     ret = RecycleSetValue(TrashOptType::RECYCLE, setXAttr, position);
958     if (ret != E_OK) {
959         return ret;
960     }
961     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
962     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
963     int32_t changedRows = -1;
964     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
965     if (ret != E_OK) {
966         LOGE("set xAttr location fail, ret %{public}d", ret);
967         return E_RDB;
968     }
969     ret = MetaFileMgr::GetInstance().MoveIntoRecycleDentryfile(userId_, bundleName_, name, parentCloudId, rowId);
970     if (ret != E_OK) {
971         LOGE("recycle set dentryfile failed, ret = %{public}d", ret);
972         return ret;
973     }
974     rdbTransaction.Finish();
975     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
976     return E_OK;
977 }
978 
GetRecycleInfo(shared_ptr<Transaction> transaction,const std::string & cloudId,int64_t & rowId,int32_t & position,string & attr)979 int32_t CloudDiskRdbStore::GetRecycleInfo(shared_ptr<Transaction> transaction, const std::string &cloudId,
980     int64_t &rowId, int32_t &position, string &attr)
981 {
982     RDBPTR_IS_NULLPTR(rdbStore_);
983     CLOUDID_IS_NULL(cloudId);
984     AbsRdbPredicates getRowIdAndPositionPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
985     getRowIdAndPositionPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
986     auto resultSet = transaction->QueryByStep(getRowIdAndPositionPredicates,
987                                               {FileColumn::ROW_ID, FileColumn::POSITION, FileColumn::ATTRIBUTE});
988     if (resultSet == nullptr) {
989         LOGE("get nullptr result set");
990         return E_RDB;
991     }
992     if (resultSet->GoToNextRow() != E_OK) {
993         LOGE("getRowIdAndPositionPredicates result set go to next row failed");
994         return E_RDB;
995     }
996     int32_t ret = CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet);
997     if (ret != E_OK) {
998         LOGE("get rowId failed");
999         return ret;
1000     }
1001     ret = CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet);
1002     if (ret != E_OK) {
1003         LOGE("get position failed");
1004         return ret;
1005     }
1006     ret = CloudDiskRdbUtils::GetString(FileColumn::ATTRIBUTE, attr, resultSet);
1007     if (ret != E_OK) {
1008         LOGE("get file attribute failed");
1009         return ret;
1010     }
1011     return E_OK;
1012 }
1013 
FavoriteSetXattr(const std::string & cloudId,const std::string & value)1014 int32_t CloudDiskRdbStore::FavoriteSetXattr(const std::string &cloudId, const std::string &value)
1015 {
1016     LOGD("favoriteSetXattr, value %{public}s", value.c_str());
1017     RDBPTR_IS_NULLPTR(rdbStore_);
1018     bool isNum = std::all_of(value.begin(), value.end(), ::isdigit);
1019     if (!isNum) {
1020         return EINVAL;
1021     }
1022     int32_t val = std::stoi(value);
1023     ValuesBucket setXAttr;
1024     if (val == 0) {
1025         setXAttr.PutInt(FileColumn::IS_FAVORITE, CANCEL_STATE);
1026         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1027     } else if (val == 1) {
1028         setXAttr.PutInt(FileColumn::IS_FAVORITE, SET_STATE);
1029         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1030     } else {
1031         return E_RDB;
1032     }
1033     int32_t changedRows = -1;
1034     vector<ValueObject> bindArgs;
1035     bindArgs.emplace_back(cloudId);
1036     int32_t ret = rdbStore_->Update(changedRows, FileColumn::FILES_TABLE, setXAttr,
1037         FileColumn::CLOUD_ID + " = ?", bindArgs);
1038     if (ret != E_OK) {
1039         LOGE("set xAttr location fail, ret %{public}d", ret);
1040         return E_RDB;
1041     }
1042     return E_OK;
1043 }
1044 
CheckXattr(const std::string & key)1045 int32_t CheckXattr(const std::string &key)
1046 {
1047     if (key == CLOUD_FILE_LOCATION) {
1048         return CLOUD_LOCATION;
1049     } else if (key == CLOUD_CLOUD_RECYCLE_XATTR) {
1050         return CLOUD_RECYCLE;
1051     } else if (key == IS_FAVORITE_XATTR) {
1052         return IS_FAVORITE;
1053     } else if (key == IS_FILE_STATUS_XATTR) {
1054         return FILE_SYNC_STATUS;
1055     } else if (key == CLOUD_EXT_ATTR) {
1056         return IS_EXT_ATTR;
1057     } else if (key == CLOUD_TIME_RECYCLED) {
1058         return TIME_RECYCLED;
1059     } else if (key == CLOUD_HAS_LCD || key == CLOUD_HAS_THM) {
1060         return HAS_THM;
1061     } else {
1062         return ERROR_CODE;
1063     }
1064 }
1065 
LocationGetXattr(const std::string & name,const std::string & key,std::string & value,const std::string & parentCloudId)1066 int32_t CloudDiskRdbStore::LocationGetXattr(const std::string &name, const std::string &key, std::string &value,
1067     const std::string &parentCloudId)
1068 {
1069     if (key != CLOUD_FILE_LOCATION) {
1070         LOGE("getxattr parameter is invalid");
1071         return E_INVAL_ARG;
1072     }
1073     MetaBase metaBase(name);
1074     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
1075     int32_t ret = metaFile->DoLookup(metaBase);
1076     if (ret != E_OK) {
1077         LOGE("lookup dentry failed, ret = %{public}d", ret);
1078         return ENOENT;
1079     }
1080     value = std::to_string(metaBase.position);
1081     return E_OK;
1082 }
1083 
FavoriteGetXattr(const std::string & cloudId,const std::string & key,std::string & value)1084 int32_t CloudDiskRdbStore::FavoriteGetXattr(const std::string &cloudId, const std::string &key, std::string &value)
1085 {
1086     RDBPTR_IS_NULLPTR(rdbStore_);
1087     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != IS_FAVORITE_XATTR) {
1088         LOGE("getxattr parameter is invalid");
1089         return E_INVAL_ARG;
1090     }
1091     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1092     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1093     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::IS_FAVORITE });
1094     if (resultSet == nullptr) {
1095         LOGE("get nullptr getxattr result");
1096         return E_RDB;
1097     }
1098     if (resultSet->GoToNextRow() != E_OK) {
1099         LOGE("getxattr result set go to next row failed");
1100         return E_RDB;
1101     }
1102     int32_t isFavorite;
1103     CloudDiskRdbUtils::GetInt(FileColumn::IS_FAVORITE, isFavorite, resultSet);
1104     value = to_string(isFavorite);
1105     return E_OK;
1106 }
1107 
FileStatusGetXattr(const std::string & cloudId,const std::string & key,std::string & value)1108 int32_t CloudDiskRdbStore::FileStatusGetXattr(const std::string &cloudId, const std::string &key, std::string &value)
1109 {
1110     RDBPTR_IS_NULLPTR(rdbStore_);
1111     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != IS_FILE_STATUS_XATTR) {
1112         LOGE("getxattr parameter is invalid");
1113         return E_INVAL_ARG;
1114     }
1115     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1116     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1117     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::FILE_STATUS });
1118     if (resultSet == nullptr) {
1119         LOGE("get nullptr getxattr result");
1120         return E_RDB;
1121     }
1122     if (resultSet->GoToNextRow() != E_OK) {
1123         LOGE("getxattr result set go to next row failed");
1124         return E_RDB;
1125     }
1126     int32_t fileStatus;
1127     int32_t ret = CloudDiskRdbUtils::GetInt(FileColumn::FILE_STATUS, fileStatus, resultSet);
1128     if (ret != E_OK) {
1129         LOGE("get file status failed");
1130         return ret;
1131     }
1132     value = to_string(fileStatus);
1133     return E_OK;
1134 }
1135 
TimeRecycledGetXattr(const string & cloudId,const string & key,string & value)1136 int32_t CloudDiskRdbStore::TimeRecycledGetXattr(const string &cloudId, const string &key, string &value)
1137 {
1138     RDBPTR_IS_NULLPTR(rdbStore_);
1139     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != CLOUD_TIME_RECYCLED) {
1140         LOGE("getxattr parameter is invalid");
1141         return E_INVAL_ARG;
1142     }
1143     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1144     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1145     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::FILE_TIME_RECYCLED });
1146     if (resultSet == nullptr) {
1147         LOGE("get nullptr getxattr result");
1148         return E_RDB;
1149     }
1150     if (resultSet->GoToNextRow() != E_OK) {
1151         LOGE("getxattr result set go to next row failed");
1152         return E_RDB;
1153     }
1154     int64_t timeRecycled = 0;
1155     CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_RECYCLED, timeRecycled, resultSet);
1156     value = to_string(timeRecycled);
1157     return E_OK;
1158 }
1159 
GetExtAttrValue(const std::string & cloudId,const std::string & key,std::string & value)1160 int32_t CloudDiskRdbStore::GetExtAttrValue(const std::string &cloudId, const std::string &key, std::string &value)
1161 {
1162     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key.empty()) {
1163         LOGE("get ext attr value parameter is invalid");
1164         return E_INVAL_ARG;
1165     }
1166 
1167     std::string res;
1168     int32_t pos = 0;
1169     int32_t ret = GetExtAttr(cloudId, res, pos);
1170     if (ret != E_OK || res.empty()) {
1171         LOGE("get ext attr value res is empty");
1172         return E_RDB;
1173     }
1174 
1175     nlohmann::json jsonObj = nlohmann::json::parse(res, nullptr, false);
1176     if (jsonObj.is_discarded()) {
1177         LOGE("get ext jsonObj parse failed");
1178         return E_RDB;
1179     }
1180 
1181     LOGD("GetExtAttrValue, name %{public}s", key.c_str());
1182     if (!jsonObj.contains(key) || !jsonObj[key].is_string()) {
1183         LOGE("get ext not a string");
1184         return E_RDB;
1185     }
1186 
1187     value = jsonObj[key].get<std::string>();
1188     return E_OK;
1189 }
1190 
GetExtAttr(const std::string & cloudId,std::string & value,int32_t & position)1191 int32_t CloudDiskRdbStore::GetExtAttr(const std::string &cloudId, std::string &value, int32_t &position)
1192 {
1193     RDBPTR_IS_NULLPTR(rdbStore_);
1194     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1195         LOGE("get ext attr parameter is invalid");
1196         return E_INVAL_ARG;
1197     }
1198     AbsRdbPredicates getAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1199     getAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1200     auto resultSet = rdbStore_->QueryByStep(getAttrPredicates, FileColumn::EXT_ATTR_QUERY_COLUMNS);
1201     if (resultSet == nullptr) {
1202         LOGE("get nullptr get ext attr result");
1203         return E_RDB;
1204     }
1205     if (resultSet->GoToNextRow() != E_OK) {
1206         LOGE("get ext attr result set go to next row failed");
1207         return E_RDB;
1208     }
1209 
1210     int32_t ret = CloudDiskRdbUtils::GetString(FileColumn::ATTRIBUTE, value, resultSet);
1211     if (ret != E_OK) {
1212         LOGE("get ext attr value failed");
1213         return ret;
1214     }
1215 
1216     ret = CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet);
1217     if (ret != E_OK) {
1218         LOGE("get location value failed");
1219         return ret;
1220     }
1221 
1222     return E_OK;
1223 }
1224 
GetXAttr(const std::string & cloudId,const std::string & key,std::string & value,const CacheNode & node,const std::string & extAttrKey)1225 int32_t CloudDiskRdbStore::GetXAttr(const std::string &cloudId, const std::string &key, std::string &value,
1226     const CacheNode &node, const std::string &extAttrKey)
1227 {
1228     int32_t num = CheckXattr(key);
1229     switch (num) {
1230         case CLOUD_LOCATION:
1231             return LocationGetXattr(node.fileName, key, value, node.parentCloudId);
1232             break;
1233         case IS_FAVORITE:
1234             return FavoriteGetXattr(cloudId, key, value);
1235             break;
1236         case FILE_SYNC_STATUS:
1237             return FileStatusGetXattr(cloudId, key, value);
1238             break;
1239         case IS_EXT_ATTR:
1240             return GetExtAttrValue(cloudId, extAttrKey, value);
1241         case TIME_RECYCLED:
1242             return TimeRecycledGetXattr(cloudId, key, value);
1243             break;
1244     }
1245 
1246     return E_INVAL_ARG;
1247 }
1248 
ExtAttributeSetValue(const std::string & key,const std::string & value,ValuesBucket & setXAttr,std::string & xattrList,int32_t pos)1249 static int32_t ExtAttributeSetValue(const std::string &key, const std::string &value,
1250     ValuesBucket &setXAttr, std::string &xattrList, int32_t pos)
1251 {
1252     nlohmann::json jsonObj;
1253     if (xattrList.empty()) {
1254         jsonObj = nlohmann::json({{key, value}});
1255     } else {
1256         jsonObj = nlohmann::json::parse(xattrList, nullptr, false);
1257         if (jsonObj.is_discarded()) {
1258             LOGE("ext jsonObj parse failed");
1259             return E_RDB;
1260         }
1261 
1262         jsonObj[key] = value;
1263     }
1264     std::string jsonValue = jsonObj.dump();
1265     setXAttr.PutString(FileColumn::ATTRIBUTE, jsonValue);
1266     if (pos != LOCAL) {
1267         setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1268         setXAttr.PutLong(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::UNKNOWN_TYPE));
1269     }
1270     setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1271     return E_OK;
1272 }
1273 
ExtAttributeSetXattr(const std::string & cloudId,const std::string & value,const std::string & key)1274 int32_t CloudDiskRdbStore::ExtAttributeSetXattr(const std::string &cloudId, const std::string &value,
1275     const std::string &key)
1276 {
1277     RDBPTR_IS_NULLPTR(rdbStore_);
1278     ValuesBucket setAttr;
1279     int32_t changedRows = -1;
1280     TransactionOperations rdbTransaction(rdbStore_);
1281     auto [ret, transaction] = rdbTransaction.Start();
1282     if (ret != E_OK) {
1283         LOGE("Ext rdbstore begin transaction failed, ret = %{public}d", ret);
1284         return ret;
1285     }
1286     std::string xattrList;
1287     int32_t pos = 0;
1288     RETURN_ON_ERR(GetExtAttr(cloudId, xattrList, pos));
1289     RETURN_ON_ERR(ExtAttributeSetValue(key, value, setAttr, xattrList, pos));
1290     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
1291     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1292     std::tie(ret, changedRows) = transaction->Update(setAttr, predicates);
1293     if (ret != E_OK) {
1294         LOGE("ext attr location fail, ret %{public}d", ret);
1295         return E_RDB;
1296     }
1297     rdbTransaction.Finish();
1298     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1299     return E_OK;
1300 }
1301 
SetXAttr(const std::string & cloudId,const std::string & key,const std::string & value,const std::string & name,const std::string & parentCloudId)1302 int32_t CloudDiskRdbStore::SetXAttr(const std::string &cloudId, const std::string &key, const std::string &value,
1303     const std::string &name, const std::string &parentCloudId)
1304 {
1305     int32_t num = CheckXattr(key);
1306     switch (num) {
1307         case CLOUD_LOCATION:
1308             return LocationSetXattr(name, parentCloudId, cloudId, value);
1309             break;
1310         case CLOUD_RECYCLE:
1311             return RecycleSetXattr(name, parentCloudId, cloudId, value);
1312             break;
1313         case IS_FAVORITE:
1314             return FavoriteSetXattr(cloudId, value);
1315             break;
1316         case IS_EXT_ATTR:
1317             return ExtAttributeSetXattr(cloudId, value, name);
1318             break;
1319         case HAS_THM:
1320             return HasTHMSetXattr(name, key, cloudId, value);
1321     }
1322 
1323     return E_INVAL_ARG;
1324 }
1325 
FileRename(ValuesBucket & values,const int32_t & position,const std::string & newFileName)1326 static void FileRename(ValuesBucket &values, const int32_t &position, const std::string &newFileName)
1327 {
1328     values.PutString(FileColumn::FILE_NAME, newFileName);
1329     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1330     FillFileType(newFileName, values);
1331     if (position != LOCAL) {
1332         values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1333         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::RENAME));
1334     }
1335 }
1336 
FileMove(ValuesBucket & values,const int32_t & position,const std::string & newParentCloudId)1337 static void FileMove(ValuesBucket &values, const int32_t &position, const std::string &newParentCloudId)
1338 {
1339     values.PutString(FileColumn::PARENT_CLOUD_ID, newParentCloudId);
1340     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1341     if (position != LOCAL) {
1342         values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1343         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::MOVE));
1344     }
1345 }
1346 
FileMoveAndRename(ValuesBucket & values,const int32_t & position,const std::string & newParentCloudId,const std::string & newFileName)1347 static void FileMoveAndRename(ValuesBucket &values, const int32_t &position, const std::string &newParentCloudId,
1348     const std::string &newFileName)
1349 {
1350     values.PutString(FileColumn::PARENT_CLOUD_ID, newParentCloudId);
1351     values.PutString(FileColumn::FILE_NAME, newFileName);
1352     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1353     FillFileType(newFileName, values);
1354     if (position != LOCAL) {
1355         values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1356         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::MOVE));
1357     }
1358 }
1359 
HandleRenameValue(ValuesBucket & rename,int32_t position,const CacheNode & oldNode,const CacheNode & newNode)1360 static void HandleRenameValue(ValuesBucket &rename, int32_t position, const CacheNode &oldNode,
1361     const CacheNode &newNode)
1362 {
1363     string oldParentCloudId = oldNode.parentCloudId;
1364     string oldFileName = oldNode.fileName;
1365     string newParentCloudId = newNode.parentCloudId;
1366     string newFileName = newNode.fileName;
1367     rename.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1368     if (oldFileName != newFileName && oldParentCloudId == newParentCloudId) {
1369         FileRename(rename, position, newFileName);
1370     }
1371     if (oldFileName == newFileName && oldParentCloudId != newParentCloudId) {
1372         FileMove(rename, position, newParentCloudId);
1373     }
1374     if (oldFileName != newFileName && oldParentCloudId != newParentCloudId) {
1375         FileMoveAndRename(rename, position, newParentCloudId, newFileName);
1376     }
1377 }
1378 
Rename(const std::string & oldParentCloudId,const std::string & oldFileName,const std::string & newParentCloudId,const std::string & newFileName)1379 int32_t CloudDiskRdbStore::Rename(const std::string &oldParentCloudId, const std::string &oldFileName,
1380     const std::string &newParentCloudId, const std::string &newFileName)
1381 {
1382     int32_t ret = CheckName(newFileName);
1383     if (ret != E_OK) {
1384         return ret;
1385     }
1386     RDBPTR_IS_NULLPTR(rdbStore_);
1387     if (oldParentCloudId.empty() || oldFileName.empty() || newParentCloudId.empty() || newFileName.empty()) {
1388         LOGE("rename parameters is invalid");
1389         return E_INVAL_ARG;
1390     }
1391     MetaBase metaBase(oldFileName);
1392     auto oldMetaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, oldParentCloudId);
1393     ret = oldMetaFile->DoLookup(metaBase);
1394     if (ret != E_OK) {
1395         LOGE("lookup dentry failed, ret = %{public}d", ret);
1396         return EINVAL;
1397     }
1398     ret = CheckNameForSpace(newFileName, S_ISDIR(metaBase.mode));
1399     if (ret != E_OK) {
1400         return ret;
1401     }
1402     ValuesBucket rename;
1403     CacheNode newNode = {.parentCloudId = newParentCloudId, .fileName = newFileName};
1404     CacheNode oldNode = {.parentCloudId = oldParentCloudId, .fileName = oldFileName};
1405     HandleRenameValue(rename, metaBase.position, oldNode, newNode);
1406     vector<ValueObject> bindArgs;
1407     bindArgs.emplace_back(metaBase.cloudId);
1408     auto newMetaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, newParentCloudId);
1409     ret = oldMetaFile->DoRename(metaBase, newFileName, newMetaFile);
1410     if (ret != E_OK) {
1411         LOGE("rename dentry failed, ret = %{public}d", ret);
1412         return EINVAL;
1413     }
1414     function<void()> rdbUpdate = [this, rename, bindArgs] {
1415         int32_t changedRows = -1;
1416         int32_t ret = rdbStore_ ->Update(changedRows, FileColumn::FILES_TABLE, rename,
1417                                          FileColumn::CLOUD_ID + " = ?", bindArgs);
1418         if (ret != E_OK) {
1419             LOGE("rename file fail, ret %{public}d", ret);
1420         }
1421         CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1422     };
1423     ffrt::thread(rdbUpdate).detach();
1424     return E_OK;
1425 }
1426 
GetHasChild(const std::string & cloudId,bool & hasChild)1427 int32_t CloudDiskRdbStore::GetHasChild(const std::string &cloudId, bool &hasChild)
1428 {
1429     RDBPTR_IS_NULLPTR(rdbStore_);
1430     CLOUDID_IS_NULL(cloudId);
1431     AbsRdbPredicates readDirPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1432     readDirPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, cloudId)
1433         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
1434         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
1435     auto resultSet = rdbStore_->QueryByStep(readDirPredicates, {FileColumn::FILE_NAME});
1436     if (resultSet == nullptr) {
1437         LOGE("get nullptr result set");
1438         return E_RDB;
1439     }
1440     if (resultSet->GoToNextRow() == E_OK) {
1441         hasChild = true;
1442     } else {
1443         hasChild = false;
1444     }
1445     return E_OK;
1446 }
1447 
UnlinkSynced(const std::string & cloudId)1448 int32_t CloudDiskRdbStore::UnlinkSynced(const std::string &cloudId)
1449 {
1450     RDBPTR_IS_NULLPTR(rdbStore_);
1451     CLOUDID_IS_NULL(cloudId);
1452     int32_t changedRows = -1;
1453     ValuesBucket updateValue;
1454     vector<string> whereArgs = {cloudId};
1455     updateValue.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_DELETED));
1456     int32_t ret = rdbStore_->Update(changedRows, FileColumn::FILES_TABLE, updateValue, FileColumn::CLOUD_ID + " = ?",
1457         whereArgs);
1458     if (ret != E_OK) {
1459         LOGE("unlink synced directory fail, ret %{public}d", ret);
1460         return E_RDB;
1461     }
1462     return E_OK;
1463 }
1464 
UnlinkLocal(const std::string & cloudId)1465 int32_t CloudDiskRdbStore::UnlinkLocal(const std::string &cloudId)
1466 {
1467     RDBPTR_IS_NULLPTR(rdbStore_);
1468     CLOUDID_IS_NULL(cloudId);
1469     int32_t changedRows = -1;
1470     vector<string> whereArgs = {cloudId};
1471     int32_t ret = rdbStore_->Delete(changedRows, FileColumn::FILES_TABLE, FileColumn::CLOUD_ID + " = ?", whereArgs);
1472     if (ret != E_OK) {
1473         LOGE("unlink local directory fail, ret %{public}d", ret);
1474         return E_RDB;
1475     }
1476     return E_OK;
1477 }
1478 
Unlink(const std::string & cloudId,const int32_t & noUpload)1479 int32_t CloudDiskRdbStore::Unlink(const std::string &cloudId, const int32_t &noUpload)
1480 {
1481     RDBPTR_IS_NULLPTR(rdbStore_);
1482     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1483         LOGE("Unlink parameters is invalid");
1484         return E_INVAL_ARG;
1485     }
1486     if (noUpload == NO_UPLOAD) {
1487         RETURN_ON_ERR(UnlinkLocal(cloudId));
1488     } else {
1489         RETURN_ON_ERR(UnlinkSynced(cloudId));
1490     }
1491     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1492     return E_OK;
1493 }
1494 
GetDirtyType(const std::string & cloudId,int32_t & dirtyType)1495 int32_t CloudDiskRdbStore::GetDirtyType(const std::string &cloudId, int32_t &dirtyType)
1496 {
1497     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1498     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1499     auto resultSet = rdbStore_->QueryByStep(predicates, {FileColumn::DIRTY_TYPE});
1500     if (resultSet == nullptr) {
1501         LOGE("get null result");
1502         return E_RDB;
1503     }
1504     if (resultSet->GoToNextRow() != E_OK) {
1505         LOGE("get current node resultSet fail");
1506         return E_RDB;
1507     }
1508 
1509     int32_t ret = CloudDiskRdbUtils::GetInt(FileColumn::DIRTY_TYPE, dirtyType, resultSet);
1510     if (ret != E_OK) {
1511         LOGE("get file status fail");
1512         return ret;
1513     }
1514     return E_OK;
1515 }
1516 
GetCurNode(const std::string & cloudId,CacheNode & curNode)1517 int32_t CloudDiskRdbStore::GetCurNode(const std::string &cloudId, CacheNode &curNode)
1518 {
1519     RDBPTR_IS_NULLPTR(rdbStore_);
1520     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1521         LOGE("parameter invalid");
1522         return E_INVAL_ARG;
1523     }
1524     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1525     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1526     auto resultSet = rdbStore_->QueryByStep(
1527         predicates, {FileColumn::PARENT_CLOUD_ID, FileColumn::IS_DIRECTORY, FileColumn::FILE_NAME});
1528     if (resultSet == nullptr) {
1529         LOGE("get null result");
1530         return E_RDB;
1531     }
1532     if (resultSet->GoToNextRow() != E_OK) {
1533         LOGE("get current node resultSet fail");
1534         return E_RDB;
1535     }
1536     RowEntity rowEntity;
1537     if (resultSet->GetRow(rowEntity) != E_OK) {
1538         LOGE("result set to file info get row failed");
1539         return E_RDB;
1540     }
1541 
1542     int32_t isDirectory;
1543     rowEntity.Get(FileColumn::PARENT_CLOUD_ID).GetString(curNode.parentCloudId);
1544     rowEntity.Get(FileColumn::FILE_NAME).GetString(curNode.fileName);
1545     rowEntity.Get(FileColumn::IS_DIRECTORY).GetInt(isDirectory);
1546     curNode.isDir = isDirectory ? "directory" : "file";
1547 
1548     return E_OK;
1549 }
1550 
GetParentNode(const std::string parentCloudId,std::string & nextCloudId,std::string & fileName)1551 int32_t CloudDiskRdbStore::GetParentNode(const std::string parentCloudId, std::string &nextCloudId,
1552     std::string &fileName)
1553 {
1554     RDBPTR_IS_NULLPTR(rdbStore_);
1555     if (parentCloudId.empty()) {
1556         LOGE("parameter invalid");
1557         return E_INVAL_ARG;
1558     }
1559     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1560     predicates.EqualTo(FileColumn::CLOUD_ID, parentCloudId);
1561     auto resultSet = rdbStore_->QueryByStep(predicates, {FileColumn::PARENT_CLOUD_ID, FileColumn::FILE_NAME});
1562     if (resultSet == nullptr) {
1563         LOGE("get null result");
1564         return E_RDB;
1565     }
1566     if (resultSet->GoToNextRow() != E_OK) {
1567         LOGE("get current node resultSet fail");
1568         return E_RDB;
1569     }
1570     RowEntity rowEntity;
1571     if (resultSet->GetRow(rowEntity) != E_OK) {
1572         LOGE("result set to file info get row failed");
1573         return E_RDB;
1574     }
1575     rowEntity.Get(FileColumn::PARENT_CLOUD_ID).GetString(nextCloudId);
1576     rowEntity.Get(FileColumn::FILE_NAME).GetString(fileName);
1577     return E_OK;
1578 }
1579 
GetUriFromDB(const std::string & parentCloudId,std::string & uri)1580 int32_t CloudDiskRdbStore::GetUriFromDB(const std::string &parentCloudId, std::string &uri)
1581 {
1582     string realPrefix = CLOUDDISK_URI_PREFIX;
1583     realPrefix.replace(realPrefix.find(BUNDLENAME_FLAG), BUNDLENAME_FLAG.length(), bundleName_);
1584     if (parentCloudId.empty() || parentCloudId == rootId_ || parentCloudId == ROOT_CLOUD_ID) {
1585         uri = realPrefix + BACKFLASH + uri;
1586         return E_OK;
1587     }
1588 
1589     string nextCloudId;
1590     string fileName;
1591     int32_t ret = GetParentNode(parentCloudId, nextCloudId, fileName);
1592     if (ret != E_OK) {
1593         LOGI("get parentnode fail, parentCloudId: %{public}s", parentCloudId.c_str());
1594         return ret;
1595     }
1596     uri = fileName + BACKFLASH + uri;
1597     uint32_t queryTimes = 0;
1598     while (nextCloudId != ROOT_CLOUD_ID) {
1599         ret = GetParentNode(nextCloudId, nextCloudId, fileName);
1600         if (ret != E_OK) {
1601             return E_OK;
1602         }
1603         uri = fileName + BACKFLASH + uri;
1604         queryTimes++;
1605         if (uri.length() > PATH_MAX || queryTimes > MAX_QUERY_TIMES) {
1606             return E_INVAL_ARG;
1607         }
1608     }
1609     uri = realPrefix + BACKFLASH + uri;
1610     return E_OK;
1611 }
1612 
GetNotifyUri(const CacheNode & cacheNode,std::string & uri)1613 int32_t CloudDiskRdbStore::GetNotifyUri(const CacheNode &cacheNode, std::string &uri)
1614 {
1615     int32_t ret = CheckRootIdValid();
1616     if (ret != E_OK) {
1617         LOGE("rootId is invalid");
1618         return ret;
1619     }
1620     ret = CloudDiskNotifyUtils::GetUriFromCache(bundleName_, rootId_, cacheNode, uri);
1621     if (ret == E_OK) {
1622         return ret;
1623     }
1624     LOGD("get uri from cache fail, name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
1625     uri = cacheNode.fileName;
1626     ret = GetUriFromDB(cacheNode.parentCloudId, uri);
1627     if (ret == E_OK) {
1628         return ret;
1629     }
1630     LOGI("get uri from db fail, name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
1631     return ret;
1632 }
1633 
GetNotifyData(const CacheNode & cacheNode,NotifyData & notifyData)1634 int32_t CloudDiskRdbStore::GetNotifyData(const CacheNode &cacheNode, NotifyData &notifyData)
1635 {
1636     int32_t ret = GetNotifyUri(cacheNode, notifyData.uri);
1637     if (ret == E_OK) {
1638         notifyData.isDir = cacheNode.isDir == "directory";
1639     }
1640     return ret;
1641 }
1642 
CheckRootIdValid()1643 int32_t CloudDiskRdbStore::CheckRootIdValid()
1644 {
1645     if (!rootId_.empty()) {
1646         return E_OK;
1647     }
1648     CloudPrefImpl cloudPrefImpl(userId_, bundleName_, FileColumn::FILES_TABLE);
1649     cloudPrefImpl.GetString(ROOT_CLOUD_ID, rootId_);
1650     if (rootId_.empty()) {
1651         LOGE("get rootId fail");
1652         return E_INVAL_ARG;
1653     }
1654     LOGI("load rootis succ, rootId: %{public}s", rootId_.c_str());
1655     return E_OK;
1656 }
1657 
GenCloudSyncTriggerFuncParams(RdbStore & store,std::string & userId,std::string & bundleName)1658 static void GenCloudSyncTriggerFuncParams(RdbStore &store, std::string &userId, std::string &bundleName)
1659 {
1660     string databasePath = store.GetPath();
1661     string str = "cloudfile/";
1662     size_t startPos = databasePath.find(str);
1663     size_t endPos = databasePath.find("/rdb");
1664     if (startPos != std::string::npos && endPos != std::string::npos) {
1665         startPos += str.size();
1666         string tempStr = databasePath.substr(startPos, endPos - startPos);
1667         size_t pos = tempStr.find('/');
1668         if (pos != std::string::npos) {
1669             userId = tempStr.substr(0, pos);
1670             bundleName = tempStr.substr(pos + 1);
1671             LOGI("generate CloudSyncTriggerFunc parameters success, userId: %{public}s, bundleName: %{public}s",
1672                 userId.c_str(), bundleName.c_str());
1673             return;
1674         }
1675     }
1676     LOGE("generate CloudSyncTriggerFunc parameters fail");
1677     return;
1678 }
1679 
CreateFolderTriggerSync(RdbStore & store)1680 static const std::string &CreateFolderTriggerSync(RdbStore &store)
1681 {
1682     string userId;
1683     string bundleName;
1684     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1685     static const string CREATE_FOLDERS_NEW_CLOUD_SYNC =
1686         "CREATE TRIGGER folders_new_cloud_sync_trigger AFTER INSERT ON " + FileColumn::FILES_TABLE +
1687         " FOR EACH ROW WHEN new.isDirectory == 1 AND new.dirty_type == " +
1688         std::to_string(static_cast<int32_t>(DirtyType::TYPE_NEW)) +
1689         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1690     return CREATE_FOLDERS_NEW_CLOUD_SYNC;
1691 }
1692 
UpdateFileTriggerSync(RdbStore & store)1693 static const std::string &UpdateFileTriggerSync(RdbStore &store)
1694 {
1695     string userId;
1696     string bundleName;
1697     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1698     static const string CREATE_FILES_UPDATE_CLOUD_SYNC =
1699         "CREATE TRIGGER files_update_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1700         " FOR EACH ROW WHEN OLD.dirty_type IN (0,1,2,3) AND new.dirty_type IN (2,3)" +
1701         " AND OLD.meta_time_edited != new.meta_time_edited" +
1702         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1703     return CREATE_FILES_UPDATE_CLOUD_SYNC;
1704 }
1705 
DeleteFileTriggerSync(RdbStore & store)1706 static const std::string &DeleteFileTriggerSync(RdbStore &store)
1707 {
1708     string userId;
1709     string bundleName;
1710     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1711     static const string CREATE_FILES_DELETE_CLOUD_SYNC =
1712         "CREATE TRIGGER files_delete_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1713         " FOR EACH ROW WHEN OLD.dirty_type IN (0,2,3) AND new.dirty_type == " +
1714         std::to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)) +
1715         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1716     return CREATE_FILES_DELETE_CLOUD_SYNC;
1717 }
1718 
LocalFileTriggerSync(RdbStore & store)1719 static const std::string &LocalFileTriggerSync(RdbStore &store)
1720 {
1721     string userId;
1722     string bundleName;
1723     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1724     static const string CREATE_FILES_LOCAL_CLOUD_SYNC =
1725         "CREATE TRIGGER files_local_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1726         " FOR EACH ROW WHEN OLD.dirty_type IN (1,6) AND new.dirty_type == " +
1727         std::to_string(static_cast<int32_t>(DirtyType::TYPE_NEW)) +
1728         " AND OLD.file_status NOT IN (0,1) AND new.file_status NOT IN (1,2)" +
1729         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1730     return CREATE_FILES_LOCAL_CLOUD_SYNC;
1731 }
1732 
ExecuteSql(RdbStore & store)1733 static int32_t ExecuteSql(RdbStore &store)
1734 {
1735     static const vector<string> onCreateSqlStrs = {
1736         FileColumn::CREATE_FILE_TABLE,
1737         FileColumn::CREATE_PARENT_CLOUD_ID_INDEX,
1738     };
1739     for (const string& sqlStr : onCreateSqlStrs) {
1740         if (store.ExecuteSql(sqlStr) != NativeRdb::E_OK) {
1741             return NativeRdb::E_ERROR;
1742         }
1743     }
1744     return NativeRdb::E_OK;
1745 }
1746 
OnCreate(RdbStore & store)1747 int32_t CloudDiskDataCallBack::OnCreate(RdbStore &store)
1748 {
1749     if (ExecuteSql(store) != NativeRdb::E_OK) {
1750         return NativeRdb::E_ERROR;
1751     }
1752     return NativeRdb::E_OK;
1753 }
1754 
VersionAddParentCloudIdIndex(RdbStore & store)1755 static void VersionAddParentCloudIdIndex(RdbStore &store)
1756 {
1757     const string executeSqlStr = FileColumn::CREATE_PARENT_CLOUD_ID_INDEX;
1758     int32_t ret = store.ExecuteSql(executeSqlStr);
1759     if (ret != NativeRdb::E_OK) {
1760         LOGE("add parent cloud id index fail, err %{public}d", ret);
1761     }
1762 }
1763 
VersionFixFileTrigger(RdbStore & store)1764 static void VersionFixFileTrigger(RdbStore &store)
1765 {
1766     const string dropFilesUpdateTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
1767     if (store.ExecuteSql(dropFilesUpdateTrigger) != NativeRdb::E_OK) {
1768         LOGE("drop files_update_cloud_sync_trigger fail");
1769     }
1770     const string addUpdateFileTrigger = UpdateFileTriggerSync(store);
1771     int32_t ret = store.ExecuteSql(addUpdateFileTrigger);
1772     if (ret != NativeRdb::E_OK) {
1773         LOGE("add update file trigger fail, err %{public}d", ret);
1774     }
1775     const string addDeleteFileTrigger = DeleteFileTriggerSync(store);
1776     ret = store.ExecuteSql(addDeleteFileTrigger);
1777     if (ret != NativeRdb::E_OK) {
1778         LOGE("add delete file trigger fail, err %{public}d", ret);
1779     }
1780     const string addLocalFileTrigger = LocalFileTriggerSync(store);
1781     ret = store.ExecuteSql(addLocalFileTrigger);
1782     if (ret != NativeRdb::E_OK) {
1783         LOGE("add local file trigger fail, err %{public}d", ret);
1784     }
1785 }
1786 
VersionFixCreateAndLocalTrigger(RdbStore & store)1787 static void VersionFixCreateAndLocalTrigger(RdbStore &store)
1788 {
1789     const string dropFilesCreateTrigger = "DROP TRIGGER IF EXISTS files_new_cloud_sync_trigger";
1790     if (store.ExecuteSql(dropFilesCreateTrigger) != NativeRdb::E_OK) {
1791         LOGE("drop files_new_cloud_sync_trigger fail");
1792     }
1793     const string dropFilesLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
1794     if (store.ExecuteSql(dropFilesLocalTrigger) != NativeRdb::E_OK) {
1795         LOGE("drop files_local_cloud_sync_trigger fail");
1796     }
1797     const string addLocalFileTrigger = LocalFileTriggerSync(store);
1798     int32_t ret = store.ExecuteSql(addLocalFileTrigger);
1799     if (ret != NativeRdb::E_OK) {
1800         LOGE("add local file trigger fail, err %{public}d", ret);
1801     }
1802     const string addCreateFolderTrigger = CreateFolderTriggerSync(store);
1803     ret = store.ExecuteSql(addCreateFolderTrigger);
1804     if (ret != NativeRdb::E_OK) {
1805         LOGE("add create folder trigger fail, err %{public}d", ret);
1806     }
1807 }
1808 
VersionAddFileStatusAndErrorCode(RdbStore & store)1809 static void VersionAddFileStatusAndErrorCode(RdbStore &store)
1810 {
1811     const string addIsFavorite = FileColumn::ADD_IS_FAVORITE;
1812     int32_t ret = store.ExecuteSql(addIsFavorite);
1813     if (ret != NativeRdb::E_OK) {
1814         LOGE("add is_favorite fail, err %{public}d", ret);
1815     }
1816 }
1817 
VersionAddFileStatus(RdbStore & store)1818 static void VersionAddFileStatus(RdbStore &store)
1819 {
1820     const string addFileStatus = FileColumn::ADD_FILE_STATUS;
1821     int32_t ret = store.ExecuteSql(addFileStatus);
1822     if (ret != NativeRdb::E_OK) {
1823         LOGE("add file_status fail, err %{public}d", ret);
1824     }
1825 }
1826 
VersionSetFileStatusDefault(RdbStore & store)1827 static void VersionSetFileStatusDefault(RdbStore &store)
1828 {
1829     const string setFileStatus = FileColumn::SET_FILE_STATUS_DEFAULT;
1830     int32_t ret = store.ExecuteSql(setFileStatus);
1831     if (ret != NativeRdb::E_OK) {
1832         LOGE("set file_status fail, err %{public}d", ret);
1833     }
1834 }
1835 
VersionFixSyncMetatimeTrigger(RdbStore & store)1836 static void VersionFixSyncMetatimeTrigger(RdbStore &store)
1837 {
1838     const string dropFilesUpdateTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
1839     if (store.ExecuteSql(dropFilesUpdateTrigger) != NativeRdb::E_OK) {
1840         LOGE("drop files_update_cloud_sync_trigger fail");
1841     }
1842     const string addUpdateFileTrigger = UpdateFileTriggerSync(store);
1843     int32_t ret = store.ExecuteSql(addUpdateFileTrigger);
1844     if (ret != NativeRdb::E_OK) {
1845         LOGE("add update file trigger fail, err %{public}d", ret);
1846     }
1847 }
1848 
VersionFixRetryTrigger(RdbStore & store)1849 static void VersionFixRetryTrigger(RdbStore &store)
1850 {
1851     const string dropFilesLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
1852     if (store.ExecuteSql(dropFilesLocalTrigger) != NativeRdb::E_OK) {
1853         LOGE("drop local file trigger fail");
1854     }
1855     const string addFilesLocalTrigger = LocalFileTriggerSync(store);
1856     int32_t ret = store.ExecuteSql(addFilesLocalTrigger);
1857     if (ret != NativeRdb::E_OK) {
1858         LOGE("add local file trigger fail, err %{public}d", ret);
1859     }
1860 }
1861 
VersionRemoveCloudSyncFuncTrigger(RdbStore & store)1862 static void VersionRemoveCloudSyncFuncTrigger(RdbStore &store)
1863 {
1864     const string dropNewFolderTrigger = "DROP TRIGGER IF EXISTS folders_new_cloud_sync_trigger";
1865     if (store.ExecuteSql(dropNewFolderTrigger) != NativeRdb::E_OK) {
1866         LOGE("drop folders_new_cloud_sync_trigger fail");
1867     }
1868     const string dropUpdateFileTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
1869     if (store.ExecuteSql(dropUpdateFileTrigger) != NativeRdb::E_OK) {
1870         LOGE("drop files_update_cloud_sync_trigger fail");
1871     }
1872     const string dropFileDeleteTrigger = "DROP TRIGGER IF EXISTS files_delete_cloud_sync_trigger";
1873     if (store.ExecuteSql(dropFileDeleteTrigger) != NativeRdb::E_OK) {
1874         LOGE("drop files_delete_cloud_sync_trigger fail");
1875     }
1876     const string dropFileLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
1877     if (store.ExecuteSql(dropFileLocalTrigger) != NativeRdb::E_OK) {
1878         LOGE("drop files_local_cloud_sync_trigger fail");
1879     }
1880 }
1881 
VersionAddThmFlag(RdbStore & store)1882 static void VersionAddThmFlag(RdbStore &store)
1883 {
1884     const string addThmFlag = FileColumn::ADD_THM_FLAG;
1885     int32_t ret = store.ExecuteSql(addThmFlag);
1886     if (ret != NativeRdb::E_OK) {
1887         LOGE("add thm_flag fail, err %{public}d", ret);
1888     }
1889     const string addLcdFlag = FileColumn::ADD_LCD_FLAG;
1890     ret = store.ExecuteSql(addLcdFlag);
1891     if (ret != NativeRdb::E_OK) {
1892         LOGE("add lcd_flag fail, err %{public}d", ret);
1893     }
1894     const string addUploadFlag = FileColumn::ADD_UPLOAD_FLAG;
1895     ret = store.ExecuteSql(addUploadFlag);
1896     if (ret != NativeRdb::E_OK) {
1897         LOGE("add no_need_upload fail, err %{public}d", ret);
1898     }
1899 }
1900 
GetMetaBaseData(CloudDiskFileInfo & info,const shared_ptr<ResultSet> resultSet)1901 static int32_t GetMetaBaseData(CloudDiskFileInfo &info, const shared_ptr<ResultSet> resultSet)
1902 {
1903     RETURN_ON_ERR(CloudDiskRdbUtils::GetString(FileColumn::CLOUD_ID, info.cloudId, resultSet));
1904     RETURN_ON_ERR(CloudDiskRdbUtils::GetString(FileColumn::FILE_NAME, info.name, resultSet));
1905     int32_t isDir = 0;
1906     RETURN_ON_ERR(CloudDiskRdbUtils::GetInt(FileColumn::IS_DIRECTORY, isDir, resultSet));
1907     info.IsDirectory = static_cast<bool>(isDir);
1908     int32_t position = 0;
1909     RETURN_ON_ERR(CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet));
1910     info.location = static_cast<uint32_t>(position);
1911     int64_t atime = 0;
1912     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_ADDED, atime, resultSet));
1913     info.atime = static_cast<uint64_t>(atime);
1914     int64_t mtime = 0;
1915     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_EDITED, mtime, resultSet));
1916     info.mtime = static_cast<uint64_t>(mtime);
1917     int64_t size = 0;
1918     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_SIZE, size, resultSet));
1919     info.size = static_cast<uint64_t>(size);
1920     int64_t rowId = 0;
1921     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet));
1922     info.rowId = static_cast<uint64_t>(rowId);
1923     return E_OK;
1924 }
1925 
GetUserIdAndBundleName(RdbStore & store,uint32_t & userId,string & bundleName)1926 static int32_t GetUserIdAndBundleName(RdbStore &store, uint32_t &userId, string &bundleName)
1927 {
1928     string userIdStr;
1929     GenCloudSyncTriggerFuncParams(store, userIdStr, bundleName);
1930     bool isValid = std::all_of(userIdStr.begin(), userIdStr.end(), ::isdigit);
1931     if (!isValid) {
1932         LOGE("invalid user Id");
1933         return E_INVAL_ARG;
1934     }
1935     userId = static_cast<uint32_t>(std::stoi(userIdStr));
1936     return E_OK;
1937 }
1938 
GenerateDentryRecursively(RdbStore & store,const string & parentCloudId)1939 static int32_t GenerateDentryRecursively(RdbStore &store, const string &parentCloudId)
1940 {
1941     LOGD("Generate dentry recursively parentCloudId:%{public}s", parentCloudId.c_str());
1942     uint32_t userId;
1943     string bundleName;
1944     RETURN_ON_ERR(GetUserIdAndBundleName(store, userId, bundleName));
1945     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1946     lookUpPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, parentCloudId)
1947         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0");
1948     int32_t rowCount = 0;
1949     uint64_t offset = 0;
1950     do {
1951         lookUpPredicates.Limit(offset, CHECK_QUERY_LIMIT);
1952         auto resultSet = store.Query(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
1953         if (resultSet == nullptr) {
1954             LOGE("failed to get result set at offset:%{public}" PRIu64 "", offset);
1955             continue;
1956         }
1957         int32_t ret = resultSet->GetRowCount(rowCount);
1958         if (ret != E_OK || rowCount < 0) {
1959             LOGE("failed to get row count at offset:%{public}" PRIu64 ", ret: %{public}d", offset, ret);
1960             continue;
1961         }
1962         if (rowCount == 0) {
1963             return E_OK;
1964         }
1965         CloudDiskFileInfo info;
1966         while (resultSet->GoToNextRow() == 0) {
1967             RETURN_ON_ERR(GetMetaBaseData(info, resultSet));
1968             MetaBase metaBase(info.name);
1969             auto callback = [info] (MetaBase &m) {
1970                 m.cloudId = info.cloudId;
1971                 m.atime = info.atime;
1972                 m.mtime = info.mtime;
1973                 m.size = info.size;
1974                 m.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
1975                 m.position = info.location;
1976                 m.fileType = FILE_TYPE_CONTENT;
1977             };
1978             auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
1979             ret = metaFile->DoLookupAndUpdate(info.name, callback);
1980             if (ret != E_OK) {
1981                 LOGE("insert new dentry failed, ret = %{public}d", ret);
1982                 return ret;
1983             }
1984             if (info.IsDirectory) {RETURN_ON_ERR(GenerateDentryRecursively(store, info.cloudId));}
1985         }
1986         offset += CHECK_QUERY_LIMIT;
1987     } while (rowCount != 0);
1988     return E_OK;
1989 }
1990 
GenerateRecycleDentryRecursively(RdbStore & store)1991 static int32_t GenerateRecycleDentryRecursively(RdbStore &store)
1992 {
1993     uint32_t userId;
1994     string bundleName;
1995     RETURN_ON_ERR(GetUserIdAndBundleName(store, userId, bundleName));
1996     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1997     lookUpPredicates.NotEqualTo(FileColumn::FILE_TIME_RECYCLED, "0");
1998     int32_t rowCount = 0;
1999     uint64_t offset = 0;
2000     do {
2001         lookUpPredicates.Limit(offset, CHECK_QUERY_LIMIT);
2002         auto resultSet = store.Query(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
2003         if (resultSet == nullptr) {
2004             LOGE("failed to get result set at offset:%{public}" PRIu64 "", offset);
2005             continue;
2006         }
2007         int32_t ret = resultSet->GetRowCount(rowCount);
2008         if (ret != E_OK || rowCount < 0) {
2009             LOGE("failed to get row count at offset:%{public}" PRIu64 ", ret: %{public}d", offset, ret);
2010             continue;
2011         }
2012         if (rowCount == 0) {
2013             return E_OK;
2014         }
2015         CloudDiskFileInfo info;
2016         while (resultSet->GoToNextRow() == 0) {
2017             RETURN_ON_ERR(GetMetaBaseData(info, resultSet));
2018             string uniqueName = info.name + "_" + std::to_string(info.rowId);
2019             MetaBase metaBase(uniqueName);
2020             auto callback = [info] (MetaBase &m) {
2021                 m.cloudId = info.cloudId;
2022                 m.atime = info.atime;
2023                 m.mtime = info.mtime;
2024                 m.size = info.size;
2025                 m.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
2026                 m.position = info.location;
2027                 m.fileType = FILE_TYPE_CONTENT;
2028             };
2029             RETURN_ON_ERR(MetaFileMgr::GetInstance().CreateRecycleDentry(userId, bundleName));
2030             auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, RECYCLE_CLOUD_ID);
2031             ret = metaFile->DoLookupAndUpdate(uniqueName, callback);
2032             if (ret != E_OK) {
2033                 LOGE("insert new dentry failed, ret = %{public}d", ret);
2034                 return ret;
2035             }
2036         }
2037         offset += CHECK_QUERY_LIMIT;
2038     } while (rowCount != 0);
2039     return E_OK;
2040 }
2041 
VersionAddCheckFlag(RdbStore & store)2042 static void VersionAddCheckFlag(RdbStore &store)
2043 {
2044     const string addCheckFlag = FileColumn::ADD_CHECK_FLAG;
2045     int32_t ret = store.ExecuteSql(addCheckFlag);
2046     if (ret != NativeRdb::E_OK) {
2047         LOGE("add check_flag fail, ret = %{public}d", ret);
2048     }
2049     ret = GenerateDentryRecursively(store, ROOT_CLOUD_ID);
2050     if (ret != E_OK) {
2051         LOGE("failed to generate dentry recursively, ret = %{public}d", ret);
2052     }
2053     ret = GenerateRecycleDentryRecursively(store);
2054     if (ret != E_OK) {
2055         LOGE("failed to generate recycle ndentry recursively, ret = %{public}d", ret);
2056     }
2057 }
2058 
VersionAddRootDirectory(RdbStore & store)2059 static void VersionAddRootDirectory(RdbStore &store)
2060 {
2061     const string addRootDirectory = "ALTER Table " + FileColumn::FILES_TABLE +
2062         " ADD COLUMN " + FileColumn::ROOT_DIRECTORY + " TEXT";
2063     int32_t ret = store.ExecuteSql(addRootDirectory);
2064     if (ret != NativeRdb::E_OK) {
2065         LOGE("add root_directory fail, ret = %{public}d", ret);
2066     }
2067     ValuesBucket rootDirectory;
2068     rootDirectory.PutString(FileColumn::ROOT_DIRECTORY, system::GetParameter(FILEMANAGER_KEY, ""));
2069     int32_t changedRows = -1;
2070     vector<ValueObject> bindArgs;
2071     ret = store.Update(changedRows, FileColumn::FILES_TABLE, rootDirectory, "", bindArgs);
2072     if (ret != NativeRdb::E_OK) {
2073         LOGE("set root_directory fail, err %{public}d", ret);
2074     }
2075 }
2076 
VersionAddAttribute(RdbStore & store)2077 static void VersionAddAttribute(RdbStore &store)
2078 {
2079     const string attrbute = FileColumn::ADD_ATTRIBUTE;
2080     int32_t ret = store.ExecuteSql(attrbute);
2081     if (ret != NativeRdb::E_OK) {
2082         LOGE("add attrbute fail, ret = %{public}d", ret);
2083     }
2084 }
2085 
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)2086 int32_t CloudDiskDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
2087 {
2088     LOGD("OnUpgrade old:%d, new:%d", oldVersion, newVersion);
2089     if (oldVersion < VERSION_ADD_PARENT_CLOUD_ID_INDEX) {
2090         VersionAddParentCloudIdIndex(store);
2091     }
2092     if (oldVersion < VERSION_FIX_FILE_TRIGGER) {
2093         VersionFixFileTrigger(store);
2094     }
2095     if (oldVersion < VERSION_FIX_CREATE_AND_LOCAL_TRIGGER) {
2096         VersionFixCreateAndLocalTrigger(store);
2097     }
2098     if (oldVersion < VERSION_ADD_STATUS_ERROR_FAVORITE) {
2099         VersionAddFileStatusAndErrorCode(store);
2100     }
2101     if (oldVersion < VERSION_ADD_FILE_STATUS) {
2102         VersionAddFileStatus(store);
2103     }
2104     if (oldVersion < VERSION_SET_FILE_STATUS_DEFAULT) {
2105         VersionSetFileStatusDefault(store);
2106     }
2107     if (oldVersion < VERSION_ADD_CHECK_FLAG) {
2108         VersionAddCheckFlag(store);
2109     }
2110     if (oldVersion < VERSION_ADD_ROOT_DIRECTORY) {
2111         VersionAddRootDirectory(store);
2112     }
2113     if (oldVersion < VERSION_FIX_SYNC_METATIME_TRIGGER) {
2114         VersionFixSyncMetatimeTrigger(store);
2115     }
2116     if (oldVersion < VERSION_FIX_RETRY_TRIGGER) {
2117         VersionFixRetryTrigger(store);
2118     }
2119 
2120     if (oldVersion < VERSION_REMOVE_CLOUD_SYNC_FUNC_TRIGGER) {
2121         VersionRemoveCloudSyncFuncTrigger(store);
2122     }
2123 
2124     if (oldVersion < VERSION_ADD_ATTRIBUTE) {
2125         VersionAddAttribute(store);
2126     }
2127 
2128     if (oldVersion < VERSION_ADD_THM_FLAG) {
2129         VersionAddThmFlag(store);
2130     }
2131     return NativeRdb::E_OK;
2132 }
2133 }