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 ¬ifyData)
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 }