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