1 /*
2 * Copyright (C) 2022 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 #include "medialibrary_db_const.h"
16 #define MLOG_TAG "ObjectUtils"
17
18 #include "medialibrary_object_utils.h"
19
20 #include <algorithm>
21 #include <cerrno>
22 #include <sys/sendfile.h>
23 #include "album_asset.h"
24 #include "datashare_predicates.h"
25 #ifdef DISTRIBUTED
26 #include "device_manager.h"
27 #endif
28 #include "directory_ex.h"
29 #include "fetch_result.h"
30 #include "file_asset.h"
31 #include "ipc_skeleton.h"
32 #include "media_file_utils.h"
33 #include "media_column.h"
34 #include "media_log.h"
35 #include "media_scanner_manager.h"
36 #include "medialibrary_bundle_manager.h"
37 #include "medialibrary_data_manager.h"
38 #include "medialibrary_data_manager_utils.h"
39 #include "medialibrary_dir_operations.h"
40 #include "medialibrary_notify.h"
41 #include "medialibrary_smartalbum_map_operations.h"
42 #include "medialibrary_errno.h"
43 #include "medialibrary_inotify.h"
44 #include "medialibrary_smartalbum_map_operations.h"
45 #include "media_privacy_manager.h"
46 #include "mimetype_utils.h"
47 #include "permission_utils.h"
48 #include "photo_album_column.h"
49 #include "result_set_utils.h"
50 #include "string_ex.h"
51 #include "thumbnail_service.h"
52 #include "value_object.h"
53 #include "medialibrary_tracer.h"
54
55 using namespace std;
56 using namespace OHOS::NativeRdb;
57
58 namespace OHOS {
59 namespace Media {
60 static const string ASSET_RECYCLE_SUFFIX = "-copy";
61 static const string NO_MEDIA_TAG = ".nomedia";
CreateDirWithPath(const string & dirPath)62 int32_t MediaLibraryObjectUtils::CreateDirWithPath(const string &dirPath)
63 {
64 if (dirPath.empty()) {
65 return E_INVALID_PATH;
66 }
67
68 int64_t rowId = -1;
69 ValuesBucket values;
70 values.PutString(MEDIA_DATA_DB_FILE_PATH, dirPath);
71 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ALBUM, OperationType::CREATE, values);
72 int32_t ret = CreateDirObj(cmd, rowId);
73 if (ret == E_FILE_EXIST || ret == E_SUCCESS) {
74 return rowId;
75 }
76 return ret;
77 }
78
GetDirAsset(const string & path)79 NativeAlbumAsset MediaLibraryObjectUtils::GetDirAsset(const string &path)
80 {
81 NativeAlbumAsset dirAsset;
82 if (path.empty()) {
83 MEDIA_ERR_LOG("Path is empty, create failed!");
84 dirAsset.SetAlbumId(E_INVALID_PATH);
85 return dirAsset;
86 }
87
88 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
89 if (uniStore == nullptr) {
90 MEDIA_ERR_LOG("uniStore is nullptr!");
91 dirAsset.SetAlbumId(E_HAS_DB_ERROR);
92 return dirAsset;
93 }
94
95 int32_t dirId = CreateDirWithPath(path);
96 MEDIA_DEBUG_LOG("After CreateDirWithPath, get dirId = %{private}d!", dirId);
97 dirAsset.SetAlbumId(dirId);
98 if (dirId < 0) {
99 return dirAsset;
100 }
101
102 string nameVal = GetStringColumnByIdFromDb(to_string(dirId), MEDIA_DATA_DB_NAME);
103 if (nameVal.empty()) {
104 MEDIA_ERR_LOG("Get dir name failed!");
105 return dirAsset;
106 }
107 dirAsset.SetAlbumName(nameVal);
108 MEDIA_DEBUG_LOG("bucketId = %{private}d bucketName = %{private}s", dirId, nameVal.c_str());
109 return dirAsset;
110 }
111
DeleteInvalidRowInDb(const string & path)112 int32_t MediaLibraryObjectUtils::DeleteInvalidRowInDb(const string &path)
113 {
114 if (GetIdByPathFromDb(path) < 0) {
115 // path is not in database, no need to delete
116 return E_SUCCESS;
117 }
118
119 if (MediaFileUtils::IsFileExists(path)) {
120 // File aready exist, not need to create again
121 return E_SUCCESS;
122 }
123
124 MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
125 if (DeleteInfoByPathInDb(deleteCmd, path) != E_SUCCESS) {
126 // Delete the record in database if file is not in filesystem any more
127 MEDIA_ERR_LOG("CreateFileAsset: delete info in db failed");
128 return E_DELETE_DIR_FAIL;
129 }
130 return E_SUCCESS;
131 }
132
InsertFileInDb(MediaLibraryCommand & cmd,const FileAsset & fileAsset,const NativeAlbumAsset & dirAsset)133 int32_t MediaLibraryObjectUtils::InsertFileInDb(MediaLibraryCommand &cmd,
134 const FileAsset &fileAsset, const NativeAlbumAsset &dirAsset)
135 {
136 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
137 if (uniStore == nullptr) {
138 MEDIA_ERR_LOG("uniStore is nullptr!");
139 return E_HAS_DB_ERROR;
140 }
141
142 // Fill basic file information into DB
143 string displayName = fileAsset.GetDisplayName();
144 ValuesBucket assetInfo;
145 assetInfo.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, fileAsset.GetMediaType());
146 assetInfo.PutString(MEDIA_DATA_DB_URI, MediaFileUtils::GetMediaTypeUri(fileAsset.GetMediaType()));
147 string extension = ScannerUtils::GetFileExtension(displayName);
148 assetInfo.PutString(MEDIA_DATA_DB_MIME_TYPE, MimeTypeUtils::GetMimeTypeFromExtension(extension));
149 assetInfo.PutString(MEDIA_DATA_DB_RELATIVE_PATH, fileAsset.GetRelativePath());
150 assetInfo.PutString(MEDIA_DATA_DB_NAME, displayName);
151 assetInfo.PutString(MEDIA_DATA_DB_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
152 struct stat statInfo {};
153 if (stat(fileAsset.GetPath().c_str(), &statInfo) == 0) {
154 assetInfo.PutLong(MEDIA_DATA_DB_SIZE, statInfo.st_size);
155 assetInfo.PutLong(MEDIA_DATA_DB_DATE_ADDED, MediaFileUtils::UTCTimeSeconds());
156 assetInfo.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, statInfo.st_mtime);
157 }
158 assetInfo.PutString(MEDIA_DATA_DB_FILE_PATH, fileAsset.GetPath());
159 assetInfo.PutInt(MEDIA_DATA_DB_BUCKET_ID, dirAsset.GetAlbumId());
160 assetInfo.PutInt(MEDIA_DATA_DB_PARENT_ID, dirAsset.GetAlbumId());
161 assetInfo.PutString(MEDIA_DATA_DB_BUCKET_NAME, dirAsset.GetAlbumName());
162 assetInfo.PutString(MEDIA_DATA_DB_OWNER_PACKAGE, cmd.GetBundleName());
163 if (!cmd.GetBundleName().empty()) {
164 assetInfo.PutString(MEDIA_DATA_DB_PACKAGE_NAME,
165 PermissionUtils::GetPackageNameByBundleName(cmd.GetBundleName()));
166 }
167
168 assetInfo.PutString(MEDIA_DATA_DB_DEVICE_NAME, cmd.GetDeviceName());
169 assetInfo.PutLong(MEDIA_DATA_DB_TIME_PENDING, fileAsset.GetTimePending());
170 cmd.SetValueBucket(assetInfo);
171 int64_t outRowId = -1;
172 int32_t errCode = uniStore->Insert(cmd, outRowId);
173 return (errCode == NativeRdb::E_OK) ? outRowId : errCode;
174 }
175
GetRelativePathFromValues(ValuesBucket & values,string & relativePath,int32_t mediaType)176 void GetRelativePathFromValues(ValuesBucket &values, string &relativePath, int32_t mediaType)
177 {
178 ValueObject valueObject;
179 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
180 valueObject.GetString(relativePath);
181 return;
182 }
183 if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
184 string albumUri;
185 valueObject.GetString(albumUri);
186 auto albumAsset = MediaLibraryObjectUtils::GetFileAssetFromUri(albumUri);
187 if (albumAsset != nullptr) {
188 relativePath = albumAsset->GetRelativePath() + albumAsset->GetDisplayName() + SLASH_CHAR;
189 }
190 } else {
191 MediaLibraryObjectUtils::GetDefaultRelativePath(mediaType, relativePath);
192 }
193 }
194
195 // create
CreateFileObj(MediaLibraryCommand & cmd)196 int32_t MediaLibraryObjectUtils::CreateFileObj(MediaLibraryCommand &cmd)
197 {
198 string relativePath;
199 string path;
200 string displayName;
201 int32_t mediaType = static_cast<int32_t>(MEDIA_TYPE_FILE);
202 FileAsset fileAsset;
203 ValueObject valueObject;
204 ValuesBucket &values = cmd.GetValueBucket();
205 if (!values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
206 return E_HAS_DB_ERROR;
207 }
208 valueObject.GetString(displayName);
209 fileAsset.SetDisplayName(displayName);
210 if (!values.GetObject(MEDIA_DATA_DB_MEDIA_TYPE, valueObject)) {
211 return E_HAS_DB_ERROR;
212 }
213 valueObject.GetInt(mediaType);
214 fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
215 GetRelativePathFromValues(values, relativePath, mediaType);
216 if (!relativePath.empty()) {
217 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
218 path = ROOT_MEDIA_DIR + relativePath + displayName;
219 fileAsset.SetRelativePath(relativePath);
220 fileAsset.SetPath(path);
221 }
222
223 // check dir and extension
224 int32_t errCode = CheckDirExtension(relativePath, displayName);
225 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS, errCode, "CreateFileAsset: check file asset failed");
226 NativeAlbumAsset dirAsset = GetDirAsset(ROOT_MEDIA_DIR + relativePath);
227 if (dirAsset.GetAlbumId() < 0) {
228 return dirAsset.GetAlbumId();
229 }
230 fileAsset.SetTimePending(0);
231
232 // delete rows in database but not in real filesystem
233 errCode = DeleteInvalidRowInDb(path);
234 if (errCode != E_SUCCESS) {
235 MEDIA_ERR_LOG("Delete invalid row in database failed");
236 return errCode;
237 }
238
239 errCode = MediaFileUtils::CreateAsset(path);
240 if (errCode != E_SUCCESS) {
241 MEDIA_ERR_LOG("CreateFileAsset: create file asset failed");
242 return errCode;
243 }
244
245 if (mediaType == MEDIA_TYPE_NOFILE) {
246 UpdateDateModified(MediaFileUtils::GetParentPath(MediaFileUtils::GetParentPath(fileAsset.GetPath())));
247 return dirAsset.GetAlbumId();
248 }
249 auto ret = InsertFileInDb(cmd, fileAsset, dirAsset);
250 if (ret > 0) {
251 UpdateDateModified(MediaFileUtils::GetParentPath(fileAsset.GetPath()));
252 }
253 return ret;
254 }
255
GetLastDirExistInDb(const string & dirPath)256 NativeAlbumAsset MediaLibraryObjectUtils::GetLastDirExistInDb(const string &dirPath)
257 {
258 NativeAlbumAsset dirAsset;
259 string lastPath = dirPath;
260 if (lastPath.back() == '/') {
261 lastPath.pop_back();
262 }
263 int32_t dirId = 0;
264 int32_t lastPathId = -1;
265 do {
266 size_t slashIndex = lastPath.rfind(SLASH_CHAR);
267 if (slashIndex == string::npos || lastPath.length() <= ROOT_MEDIA_DIR.length()) {
268 break;
269 }
270 lastPath = lastPath.substr(0, slashIndex);
271 lastPathId = GetIdByPathFromDb(lastPath);
272 if (lastPathId >= 0) {
273 dirId = lastPathId;
274 }
275 } while (lastPathId < 0);
276 MEDIA_INFO_LOG("GetLastAlbumExistInDb lastPath = %{private}s", lastPath.c_str());
277 dirAsset.SetAlbumId(dirId);
278 dirAsset.SetAlbumPath(lastPath);
279 return dirAsset;
280 }
281
DeleteRows(const vector<int64_t> & rowIds)282 int32_t MediaLibraryObjectUtils::DeleteRows(const vector<int64_t> &rowIds)
283 {
284 int32_t errCode = 0;
285
286 for (auto id : rowIds) {
287 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
288 errCode = DeleteInfoByIdInDb(cmd, to_string(id));
289 }
290 return errCode;
291 }
292
SetDirValuesByPath(ValuesBucket & values,const string & path,int32_t parentId)293 int32_t SetDirValuesByPath(ValuesBucket &values, const string &path, int32_t parentId)
294 {
295 string title = MediaFileUtils::GetFileName(path);
296 if (MediaFileUtils::CheckDentryName(title) < 0) {
297 MEDIA_ERR_LOG("Check display name failed!");
298 return E_INVALID_DISPLAY_NAME;
299 }
300
301 string relativePath;
302 string parentPath = MediaFileUtils::GetParentPath(path);
303 if (parentPath.length() > ROOT_MEDIA_DIR.length()) {
304 relativePath = parentPath.substr(ROOT_MEDIA_DIR.length()) + "/";
305 }
306
307 values.PutString(MEDIA_DATA_DB_FILE_PATH, path);
308 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
309 values.PutString(MEDIA_DATA_DB_TITLE, title);
310 values.PutString(MEDIA_DATA_DB_NAME, title);
311 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, MediaType::MEDIA_TYPE_ALBUM);
312 values.PutInt(MEDIA_DATA_DB_PARENT_ID, parentId);
313 values.PutLong(MEDIA_DATA_DB_DATE_ADDED, MediaFileUtils::UTCTimeSeconds());
314
315 struct stat statInfo {};
316 if (stat(path.c_str(), &statInfo) == 0) {
317 values.PutLong(MEDIA_DATA_DB_SIZE, statInfo.st_size);
318 #ifdef MEDIALIBRARY_COMPATIBILITY
319 if (statInfo.st_mtime == 0) {
320 values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::UTCTimeSeconds());
321 } else {
322 values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, statInfo.st_mtime);
323 }
324 #else
325 values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, statInfo.st_mtime);
326 #endif
327 }
328 return E_SUCCESS;
329 }
330
InsertDirToDbRecursively(const string & dirPath,int64_t & rowId)331 int32_t MediaLibraryObjectUtils::InsertDirToDbRecursively(const string &dirPath, int64_t &rowId)
332 {
333 CHECK_AND_RETURN_RET_LOG(!dirPath.empty(), E_VIOLATION_PARAMETERS, "Input parameter dirPath is empty!");
334
335 NativeAlbumAsset dirAsset = GetLastDirExistInDb(dirPath);
336 string parentPath = dirAsset.GetAlbumPath();
337 int32_t parentId = dirAsset.GetAlbumId();
338 if ((parentId == 0) && ((parentPath + "/") != ROOT_MEDIA_DIR)) {
339 return E_INVALID_PATH;
340 }
341 vector<int64_t> outIds;
342 rowId = parentId;
343 string path = dirPath;
344 if (path.back() != '/') {
345 path.append("/");
346 }
347 while (parentPath.length() < (path.length() - 1)) {
348 size_t index = path.find("/", parentPath.length() + 1);
349 string currentPath = path.substr(0, index);
350 ValuesBucket values;
351 auto ret = SetDirValuesByPath(values, currentPath, parentId);
352 if (ret == E_INVALID_DISPLAY_NAME) {
353 DeleteRows(outIds);
354 }
355 if (ret != E_SUCCESS) {
356 return ret;
357 }
358
359 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ALBUM, OperationType::CREATE, values);
360 rowId = InsertInDb(cmd);
361 if (rowId <= 0) {
362 rowId = parentId;
363 return E_HAS_DB_ERROR;
364 }
365 parentId = rowId;
366 parentPath = currentPath;
367 outIds.push_back(rowId);
368 }
369 return E_SUCCESS;
370 }
371
CreateDirObj(MediaLibraryCommand & cmd,int64_t & rowId)372 int32_t MediaLibraryObjectUtils::CreateDirObj(MediaLibraryCommand &cmd, int64_t &rowId)
373 {
374 string dirPath;
375 ValueObject valueObject;
376 const ValuesBucket &values = cmd.GetValueBucket();
377 if (values.GetObject(MEDIA_DATA_DB_FILE_PATH, valueObject)) {
378 valueObject.GetString(dirPath);
379 }
380 if (dirPath.empty()) {
381 MEDIA_ERR_LOG("Dir path is empty!");
382 return E_INVALID_PATH;
383 }
384
385 rowId = GetIdByPathFromDb(dirPath);
386 MEDIA_DEBUG_LOG("dirPath %{private}s id in database is %{private}d", dirPath.c_str(), static_cast<int>(rowId));
387 if ((rowId < 0) || (!MediaFileUtils::IsDirectory(dirPath))) {
388 if ((!MediaFileUtils::CreateDirectory(dirPath)) && (errno != EEXIST)) {
389 return E_FAIL;
390 }
391 return InsertDirToDbRecursively(dirPath, rowId);
392 }
393
394 return E_FILE_EXIST;
395 }
396
DeleteEmptyDirsRecursively(int32_t dirId)397 int32_t MediaLibraryObjectUtils::DeleteEmptyDirsRecursively(int32_t dirId)
398 {
399 if (dirId <= 0) {
400 return E_INVALID_FILEID;
401 }
402 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
403 if (uniStore == nullptr) {
404 MEDIA_ERR_LOG("uniStore is nullptr!");
405 return E_HAS_DB_ERROR;
406 }
407
408 int err = E_ERR;
409 const int32_t MAX_DIR_DEPTH = 15;
410 int depth = 0;
411 while ((depth++ < MAX_DIR_DEPTH) && (dirId > 0)) {
412 if (IsColumnValueExist(to_string(dirId), MEDIA_DATA_DB_PARENT_ID)) {
413 return E_SUCCESS;
414 }
415
416 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
417 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(dirId));
418 auto queryParentResultSet = uniStore->Query(cmd, {});
419 if (queryParentResultSet->GoToNextRow() != NativeRdb::E_OK) {
420 return E_SUCCESS;
421 }
422 int32_t colIndex = 0;
423 int32_t parentIdVal = 0;
424 string dirVal;
425 queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_PARENT_ID, colIndex);
426 queryParentResultSet->GetInt(colIndex, parentIdVal);
427 queryParentResultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, colIndex);
428 queryParentResultSet->GetString(colIndex, dirVal);
429 queryParentResultSet.reset();
430 if (parentIdVal == 0) {
431 return E_SUCCESS;
432 }
433 MEDIA_DEBUG_LOG("dirVal = %{private}s, parentIdVal = %{public}d", dirVal.c_str(), parentIdVal);
434
435 // Do not delete user created dir
436 if (MediaFileUtils::IsFileExists(dirVal + "/" + ".nofile")) {
437 return E_SUCCESS;
438 }
439 if (!MediaFileUtils::IsDirEmpty(dirVal)) {
440 return E_SUCCESS;
441 }
442
443 if (!MediaFileUtils::DeleteDir(dirVal)) {
444 MEDIA_ERR_LOG("Delete dir in filesystem failed, errno = %{public}d", errno);
445 err = E_HAS_FS_ERROR;
446 break;
447 }
448 MediaLibraryCommand deleteDirCmd(OperationObject::FILESYSTEM_DIR, OperationType::DELETE);
449 int32_t deletedRows = DeleteInfoByIdInDb(deleteDirCmd, to_string(dirId));
450 if (deletedRows < 0) {
451 MEDIA_ERR_LOG("Delete dir info failed, err: %{public}d", deletedRows);
452 err = deletedRows;
453 break;
454 } else if (deletedRows == 0) {
455 MEDIA_ERR_LOG("Failed to delete dir in db!");
456 return E_HAS_DB_ERROR;
457 }
458 dirId = parentIdVal;
459 }
460 return err;
461 }
462
InvalidateThumbnail(const string & id,const string & tableName,const string & path)463 void MediaLibraryObjectUtils::InvalidateThumbnail(const string &id, const string &tableName, const string &path)
464 {
465 ThumbnailService::GetInstance()->InvalidateThumbnail(id, tableName, path);
466 }
467
DeleteMisc(const int32_t fileId,const string & filePath,const int32_t parentId)468 int32_t MediaLibraryObjectUtils::DeleteMisc(const int32_t fileId, const string &filePath, const int32_t parentId)
469 {
470 // 1) update parent's modify time
471 string parentPath = MediaFileUtils::GetParentPath(filePath);
472 auto updatedRows = UpdateDateModified(parentPath);
473 if (updatedRows <= 0) {
474 MEDIA_ERR_LOG("Update album date_modified failed, path: %{private}s", parentPath.c_str());
475 }
476 // 2) recursively delete empty parent dirs
477 if (DeleteEmptyDirsRecursively(parentId) != E_SUCCESS) {
478 return E_DELETE_DIR_FAIL;
479 }
480 // 3) delete relative records in smart album
481 MediaLibraryCommand deleteSmartMapCmd(OperationObject::SMART_ALBUM_MAP, OperationType::DELETE);
482 deleteSmartMapCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUMMAP_DB_CHILD_ASSET_ID, to_string(fileId));
483 return DeleteInfoByIdInDb(deleteSmartMapCmd);
484 }
485
486 // Restriction: input param cmd MUST have file id in either uri or valuebucket
DeleteFileObj(const shared_ptr<FileAsset> & fileAsset)487 int32_t MediaLibraryObjectUtils::DeleteFileObj(const shared_ptr<FileAsset> &fileAsset)
488 {
489 // delete file in filesystem
490 string filePath = fileAsset->GetPath();
491 if (!MediaFileUtils::DeleteFile(filePath)) {
492 MEDIA_ERR_LOG("Delete file asset failed, errno: %{public}d", errno);
493 return E_HAS_FS_ERROR;
494 }
495
496 // delete thumbnail
497 int32_t fileId = fileAsset->GetId();
498 InvalidateThumbnail(to_string(fileId));
499
500 // delete file in db
501 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
502 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(fileId));
503 int32_t deleteRows = DeleteInfoByIdInDb(cmd);
504 if (deleteRows <= 0) {
505 MEDIA_ERR_LOG("Delete file info in database failed!");
506 return deleteRows;
507 }
508
509 return DeleteMisc(fileId, filePath, fileAsset->GetParent());
510 }
511
DeleteInfoRecursively(const shared_ptr<FileAsset> & fileAsset)512 int32_t MediaLibraryObjectUtils::DeleteInfoRecursively(const shared_ptr<FileAsset> &fileAsset)
513 {
514 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
515 CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "UniStore is nullptr");
516
517 string fileId = to_string(fileAsset->GetId());
518 if (fileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
519 MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
520 queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, fileId);
521 if (fileAsset->GetIsTrash() == NOT_TRASHED) {
522 queryCmd.GetAbsRdbPredicates()->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
523 } else {
524 queryCmd.GetAbsRdbPredicates()->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(TRASHED_DIR_CHILD));
525 }
526 vector<string> columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_IS_TRASH };
527 auto result = uniStore->Query(queryCmd, columns);
528 CHECK_AND_RETURN_RET_LOG(result != nullptr, E_DB_FAIL, "Get child assets failed.");
529
530 while (result->GoToNextRow() == NativeRdb::E_OK) {
531 auto childAsset = make_shared<FileAsset>();
532 childAsset->SetId(GetInt32Val(MEDIA_DATA_DB_ID, result));
533 childAsset->SetMediaType(static_cast<MediaType>(GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, result)));
534 childAsset->SetIsTrash(GetInt32Val(MEDIA_DATA_DB_IS_TRASH, result));
535 auto ret = DeleteInfoRecursively(childAsset);
536 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret,
537 "Delete file info in database failed, file_id: %{public}d, ret: %{public}d", childAsset->GetId(), ret);
538 }
539 }
540
541 InvalidateThumbnail(fileId);
542 MediaLibraryCommand deleteCmd(Uri(MEDIALIBRARY_DATA_URI), OperationType::DELETE);
543 int32_t deleteRows = MediaLibraryObjectUtils::DeleteInfoByIdInDb(deleteCmd, fileId);
544 if (deleteRows <= 0) {
545 MEDIA_ERR_LOG("Delete file info in database failed, file_id: %{public}s", fileId.c_str());
546 return E_DB_FAIL;
547 }
548 return E_SUCCESS;
549 }
550
DeleteDirObj(const shared_ptr<FileAsset> & dirAsset)551 int32_t MediaLibraryObjectUtils::DeleteDirObj(const shared_ptr<FileAsset> &dirAsset)
552 {
553 // delete dir in filesystem
554 string dirPath = dirAsset->GetPath();
555 if (!MediaFileUtils::DeleteDir(dirPath)) {
556 MEDIA_ERR_LOG("Delete album asset failed, errno: %{public}d", errno);
557 return E_HAS_FS_ERROR;
558 }
559
560 // delete dir and children in db
561 auto ret = DeleteInfoRecursively(dirAsset);
562 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret,
563 "Delete file info in database failed, file_id: %{public}d, ret: %{public}d", dirAsset->GetId(), ret);
564
565 return DeleteMisc(dirAsset->GetId(), dirPath, dirAsset->GetParent());
566 }
567
568 // Restriction: input param cmd MUST have id in uri
RenameFileObj(MediaLibraryCommand & cmd,const string & srcFilePath,const string & dstFilePath)569 int32_t MediaLibraryObjectUtils::RenameFileObj(MediaLibraryCommand &cmd,
570 const string &srcFilePath, const string &dstFilePath)
571 {
572 if (srcFilePath.empty() || dstFilePath.empty()) {
573 MEDIA_ERR_LOG("srcFilePath or dstFilePath is empty, rename failed!");
574 return E_INVALID_PATH;
575 }
576 if (srcFilePath.compare(dstFilePath) == 0) {
577 MEDIA_DEBUG_LOG("Skip modify the file, the path of new file is the same as old");
578 return E_SUCCESS;
579 }
580 auto errCode = CheckDirExtension(dstFilePath);
581 CHECK_AND_RETURN_RET_LOG(errCode == E_SUCCESS, errCode, "CreateFileAsset: check file asset failed");
582 if (errCode != E_SUCCESS) {
583 return errCode;
584 }
585
586 string dstAlbumPath = MediaFileUtils::GetParentPath(dstFilePath);
587 NativeAlbumAsset dirAsset = GetDirAsset(dstAlbumPath);
588 if (dirAsset.GetAlbumId() <= 0) {
589 MEDIA_ERR_LOG("Failed to get or create directory");
590 return dirAsset.GetAlbumId();
591 }
592
593 errCode = MediaFileUtils::ModifyAsset(srcFilePath, dstFilePath);
594 if (errCode != E_SUCCESS) {
595 if (errCode != E_FILE_EXIST) {
596 MEDIA_ERR_LOG("Failed to modify the file in the device, errCode = %{public}d", errCode);
597 }
598 return errCode;
599 }
600 InvalidateThumbnail(cmd.GetOprnFileId());
601 string dstFileName = MediaFileUtils::GetFileName(dstFilePath);
602 if ((ProcessNoMediaFile(dstFileName, dstAlbumPath) == E_SUCCESS) ||
603 (ProcessHiddenFile(dstFileName, srcFilePath) == E_SUCCESS)) {
604 MEDIA_ERR_LOG("New file is a .nomedia file or hidden file.");
605 // why: return fail insteal of success
606 return E_FAIL;
607 }
608
609 auto ret = UpdateFileInfoInDb(cmd, dstFilePath, dirAsset.GetAlbumId(), dirAsset.GetAlbumName());
610 if (ret > 0) {
611 UpdateDateModified(dstAlbumPath);
612 string srcAlbumPath = MediaFileUtils::GetParentPath(srcFilePath);
613 UpdateDateModified(srcAlbumPath);
614 }
615 return ret;
616 }
617
618 // Restriction: input param cmd MUST have id in uri
RenameDirObj(MediaLibraryCommand & cmd,const string & srcDirPath,const string & dstDirPath)619 int32_t MediaLibraryObjectUtils::RenameDirObj(MediaLibraryCommand &cmd,
620 const string &srcDirPath, const string &dstDirPath)
621 {
622 MEDIA_DEBUG_LOG("enter, srcDirPath = %{private}s, dstDirPath = %{private}s",
623 srcDirPath.c_str(), dstDirPath.c_str());
624 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
625 if (uniStore == nullptr) {
626 MEDIA_ERR_LOG("uniStore is nullptr!");
627 return E_HAS_DB_ERROR;
628 }
629
630 if (srcDirPath.empty() || dstDirPath.empty()) {
631 MEDIA_ERR_LOG("srcDirPath or dstDirPath is empty, rename failed!");
632 return E_INVALID_PATH;
633 }
634 if (!MediaFileUtils::RenameDir(srcDirPath, dstDirPath)) {
635 MEDIA_ERR_LOG("Rename directory failed!");
636 return E_HAS_FS_ERROR;
637 }
638 string dstDirName = MediaFileUtils::GetFileName(dstDirPath);
639 if (ProcessHiddenDir(dstDirName, srcDirPath) == E_SUCCESS) {
640 MEDIA_ERR_LOG("New album is a hidden album.");
641 return E_SUCCESS;
642 }
643
644 ValuesBucket &values = cmd.GetValueBucket();
645 values.PutString(Media::MEDIA_DATA_DB_RELATIVE_PATH, MediaFileUtils::GetParentPath(dstDirPath));
646 values.PutString(Media::MEDIA_DATA_DB_FILE_PATH, dstDirPath);
647 values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, MediaFileUtils::GetAlbumDateModified(dstDirPath));
648 int32_t retVal = ModifyInfoByIdInDb(cmd);
649 if (retVal <= 0) {
650 return retVal;
651 }
652
653 // Update the path, relative path and album Name for internal files
654 const string modifyAlbumInternalsStmt =
655 "UPDATE " + MEDIALIBRARY_TABLE + " SET " + MEDIA_DATA_DB_FILE_PATH + " = replace(" +
656 MEDIA_DATA_DB_FILE_PATH + ", '" + srcDirPath + "/' , '" + dstDirPath + "/'), " +
657 MEDIA_DATA_DB_RELATIVE_PATH + " = replace(" + MEDIA_DATA_DB_RELATIVE_PATH + ", '" + srcDirPath + "', '" +
658 dstDirPath + "'), " + MEDIA_DATA_DB_ALBUM_NAME + " = replace(" + MEDIA_DATA_DB_ALBUM_NAME + ", '" +
659 MediaFileUtils::GetFileName(srcDirPath) + "', '" + dstDirName + "')" + "where " +
660 MEDIA_DATA_DB_FILE_PATH + " LIKE '" + srcDirPath + "/%'";
661 if (uniStore->ExecuteSql(modifyAlbumInternalsStmt) != NativeRdb::E_OK) {
662 MEDIA_ERR_LOG("Album update sql failed");
663 return E_HAS_DB_ERROR;
664 }
665 return E_SUCCESS;
666 }
667
OpenAsset(const string & filePath,const string & mode)668 static int32_t OpenAsset(const string &filePath, const string &mode)
669 {
670 MediaLibraryTracer tracer;
671 tracer.Start("OpenAsset");
672
673 string absFilePath;
674 if (!PathToRealPath(filePath, absFilePath)) {
675 MEDIA_ERR_LOG("Failed to get real path: %{private}s", filePath.c_str());
676 return E_ERR;
677 }
678 MEDIA_DEBUG_LOG("File absFilePath is %{private}s", absFilePath.c_str());
679
680 return MediaPrivacyManager(absFilePath, mode).Open();
681 }
682
CheckIsOwner(const string & bundleName)683 static bool CheckIsOwner(const string &bundleName)
684 {
685 string clientBundle = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
686 if (strcmp(bundleName.c_str(), clientBundle.c_str()) == 0) {
687 return true;
688 }
689 return false;
690 }
691
OpenFile(MediaLibraryCommand & cmd,const string & mode)692 int32_t MediaLibraryObjectUtils::OpenFile(MediaLibraryCommand &cmd, const string &mode)
693 {
694 MediaLibraryTracer tracer;
695 tracer.Start("MediaLibraryObjectUtils::OpenFile");
696
697 string uriString = cmd.GetUri().ToString();
698 if (cmd.GetOprnObject() == OperationObject::THUMBNAIL) {
699 return ThumbnailService::GetInstance()->GetThumbnailFd(uriString);
700 }
701
702 shared_ptr<FileAsset> fileAsset = GetFileAssetFromUri(uriString);
703 if (fileAsset == nullptr) {
704 MEDIA_ERR_LOG("Failed to obtain path from Database");
705 return E_INVALID_URI;
706 }
707
708 if (fileAsset->GetTimePending() != 0) {
709 if (!CheckIsOwner(fileAsset->GetOwnerPackage().c_str())) {
710 MEDIA_ERR_LOG("Failed to open fileId:%{public}d, it is not owner", fileAsset->GetId());
711 return E_IS_PENDING_ERROR;
712 }
713 }
714
715 string path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
716 int32_t fd = OpenAsset(path, mode);
717 if (fd < 0) {
718 MEDIA_ERR_LOG("open file fd %{private}d, errno %{private}d", fd, errno);
719 return E_HAS_FS_ERROR;
720 }
721
722 if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
723 auto watch = MediaLibraryInotify::GetInstance();
724 if (watch != nullptr) {
725 MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
726 watch->AddWatchList(path, fileAsset->GetUri());
727 }
728 }
729 MEDIA_DEBUG_LOG("MediaLibraryDataManager OpenFile: Success");
730 return fd;
731 }
732
ScanFileAsync(const string & path,const string & id,MediaLibraryApi api)733 void MediaLibraryObjectUtils::ScanFileAsync(const string &path, const string &id, MediaLibraryApi api)
734 {
735 string tableName;
736 if (MediaFileUtils::IsFileTablePath(path)) {
737 tableName = MEDIALIBRARY_TABLE;
738 } else if (MediaFileUtils::IsPhotoTablePath(path)) {
739 tableName = PhotoColumn::PHOTOS_TABLE;
740 } else {
741 tableName = AudioColumn::AUDIOS_TABLE;
742 }
743
744 InvalidateThumbnail(id, tableName);
745
746 shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
747 if (scanFileCb == nullptr) {
748 MEDIA_ERR_LOG("Failed to create scan file callback object");
749 return ;
750 }
751 int ret = MediaScannerManager::GetInstance()->ScanFile(path, scanFileCb, api);
752 if (ret != 0) {
753 MEDIA_ERR_LOG("Scan file failed!");
754 }
755 }
756
CloseFile(MediaLibraryCommand & cmd)757 int32_t MediaLibraryObjectUtils::CloseFile(MediaLibraryCommand &cmd)
758 {
759 string strFileId = cmd.GetOprnFileId();
760 if (strFileId.empty()) {
761 MEDIA_ERR_LOG("Get id from uri or valuesBucket failed!");
762 return E_INVALID_FILEID;
763 }
764
765 auto fileAsset = GetFileAssetFromId(strFileId);
766 if (fileAsset == nullptr) {
767 MEDIA_ERR_LOG("Get fileAsset from database fail!");
768 return E_INVALID_FILEID;
769 }
770 string srcPath = fileAsset->GetPath();
771 string fileName = MediaFileUtils::GetFileName(srcPath);
772 if ((fileName.length() != 0) && (fileName.at(0) != '.')) {
773 string dirPath = MediaFileUtils::GetParentPath(srcPath);
774 UpdateDateModified(dirPath);
775 }
776
777 // remove inotify event since there is close cmd
778 auto watch = MediaLibraryInotify::GetInstance();
779 if (watch != nullptr) {
780 watch->RemoveByFileUri(fileAsset->GetUri());
781 }
782 InvalidateThumbnail(strFileId);
783 ScanFile(srcPath);
784 return E_SUCCESS;
785 }
786
ScanFile(const string & path,MediaLibraryApi api)787 void MediaLibraryObjectUtils::ScanFile(const string &path, MediaLibraryApi api)
788 {
789 MEDIA_DEBUG_LOG("enter, path = %{private}s, api = %{public}d", path.c_str(), static_cast<int>(api));
790 shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
791 if (scanFileCb == nullptr) {
792 MEDIA_ERR_LOG("Failed to create scan file callback object");
793 return ;
794 }
795 int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanFileCb, api);
796 if (ret != 0) {
797 MEDIA_ERR_LOG("Scan file failed!");
798 }
799 }
800
ProcessNoMediaFile(const string & dstFileName,const string & dstAlbumPath)801 int32_t MediaLibraryObjectUtils::ProcessNoMediaFile(const string &dstFileName, const string &dstAlbumPath)
802 {
803 MEDIA_DEBUG_LOG("enter, dstFileName = %{private}s, dstAlbumPath = %{private}s",
804 dstFileName.c_str(), dstAlbumPath.c_str());
805 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
806 if (uniStore == nullptr) {
807 MEDIA_ERR_LOG("uniStore is nullptr!");
808 return E_HAS_DB_ERROR;
809 }
810
811 if (dstFileName.empty() || dstAlbumPath.empty() || dstFileName != NO_MEDIA_TAG) {
812 MEDIA_INFO_LOG("Not a .nomedia file, no need to do anything.");
813 return E_INVALID_ARGUMENTS;
814 }
815
816 // the whole folder containing .nomedia file is invisible in database
817 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
818 string dstAlbumPathPrefix = dstAlbumPath.back() != '/' ? (dstAlbumPath + "/") : dstAlbumPath;
819 cmd.GetAbsRdbPredicates()->BeginsWith(MEDIA_DATA_DB_FILE_PATH, dstAlbumPathPrefix);
820 cmd.GetAbsRdbPredicates()->Or()->EqualTo(MEDIA_DATA_DB_FILE_PATH, dstAlbumPath);
821
822 int32_t deletedRows = -1;
823 if (uniStore->Delete(cmd, deletedRows) != NativeRdb::E_OK) {
824 MEDIA_ERR_LOG("Delete rows for the hidden album failed");
825 }
826 return E_SUCCESS;
827 }
828
ProcessHiddenFile(const string & dstFileName,const string & srcPath)829 int32_t MediaLibraryObjectUtils::ProcessHiddenFile(const string &dstFileName, const string &srcPath)
830 {
831 MEDIA_DEBUG_LOG("enter, dstFileName = %{private}s, srcPath = %{private}s",
832 dstFileName.c_str(), srcPath.c_str());
833 if (dstFileName.empty() || srcPath.empty() || dstFileName.at(0) != '.') {
834 MEDIA_INFO_LOG("Not a hidden file (file name begin with \'.\'), no need to do anything.");
835 return E_INVALID_ARGUMENTS;
836 }
837 MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
838 if (DeleteInfoByPathInDb(deleteCmd, srcPath) != E_SUCCESS) {
839 MEDIA_ERR_LOG("Delete rows for the old path failed");
840 }
841 return E_SUCCESS;
842 }
843
ProcessHiddenDir(const string & dstDirName,const string & srcDirPath)844 int32_t MediaLibraryObjectUtils::ProcessHiddenDir(const string &dstDirName, const string &srcDirPath)
845 {
846 if (dstDirName.empty() || srcDirPath.empty() || dstDirName.at(0) != '.') {
847 MEDIA_INFO_LOG("Not a hidden dir(name begin with \'.\'), no need to do anything.");
848 return E_INVALID_PATH;
849 }
850 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
851 if (uniStore == nullptr) {
852 MEDIA_ERR_LOG("uniStore is nullptr!");
853 return E_HAS_DB_ERROR;
854 }
855
856 MediaLibraryCommand deleteCmd(OperationObject::FILESYSTEM_ASSET, OperationType::DELETE);
857 string dstAlbumPathPrefix = srcDirPath.back() != '/' ? (srcDirPath + "/") : srcDirPath;
858 deleteCmd.GetAbsRdbPredicates()->BeginsWith(MEDIA_DATA_DB_FILE_PATH, dstAlbumPathPrefix);
859 deleteCmd.GetAbsRdbPredicates()->Or()->EqualTo(MEDIA_DATA_DB_FILE_PATH, srcDirPath);
860
861 int32_t deletedRows = -1;
862 if (uniStore->Delete(deleteCmd, deletedRows) != NativeRdb::E_OK) {
863 MEDIA_ERR_LOG("Delete src dir in database failed!");
864 return E_HAS_DB_ERROR;
865 }
866 return E_SUCCESS;
867 }
868
UpdateDateModified(const string & dirPath)869 int32_t MediaLibraryObjectUtils::UpdateDateModified(const string &dirPath)
870 {
871 if (dirPath.empty()) {
872 MEDIA_ERR_LOG("Path is empty, update failed!");
873 return E_INVALID_PATH;
874 }
875
876 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE);
877 ValuesBucket valuesBucket;
878 int64_t dateModified = MediaFileUtils::GetAlbumDateModified(dirPath);
879 #ifdef MEDIALIBRARY_COMPATIBILITY
880 if (dateModified == 0) {
881 return 0;
882 }
883 #endif
884 valuesBucket.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, dateModified);
885
886 cmd.SetValueBucket(valuesBucket);
887
888 return ModifyInfoByPathInDb(cmd, dirPath);
889 }
890
GetFileAssetByPredicates(const NativeRdb::AbsRdbPredicates & predicates,const vector<string> & columns)891 unique_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetByPredicates(const NativeRdb::AbsRdbPredicates &predicates,
892 const vector<string> &columns)
893 {
894 auto absResultSet = MediaLibraryRdbStore::Query(predicates, columns);
895 if (absResultSet == nullptr) {
896 return nullptr;
897 }
898 auto resultSetBridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(absResultSet);
899 auto resultSet = make_shared<DataShare::DataShareResultSet>(resultSetBridge);
900 auto fetchResult = make_unique<FetchResult<FileAsset>>(move(resultSet));
901 return fetchResult->GetFirstObject();
902 }
903
GetFileAssetFromId(const string & id,const string & networkId)904 shared_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetFromId(const string &id, const string &networkId)
905 {
906 if ((id.empty()) || (!MediaLibraryDataManagerUtils::IsNumber(id)) || (stoi(id) == -1)) {
907 MEDIA_ERR_LOG("Id for the path is incorrect: %{public}s", id.c_str());
908 return nullptr;
909 }
910
911 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY, networkId);
912 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id);
913
914 auto resultSet = QueryWithCondition(cmd, {});
915 if (resultSet == nullptr) {
916 MEDIA_ERR_LOG("Failed to obtain file asset from database");
917 return nullptr;
918 }
919
920 shared_ptr<FetchResult<FileAsset>> fetchFileResult = make_shared<FetchResult<FileAsset>>();
921 if (fetchFileResult == nullptr) {
922 MEDIA_ERR_LOG("Failed to obtain fetch file result");
923 return nullptr;
924 }
925 fetchFileResult->SetNetworkId(networkId);
926 return fetchFileResult->GetObjectFromRdb(resultSet, 0);
927 }
928
GetFileAssetFromUri(const string & uriStr)929 shared_ptr<FileAsset> MediaLibraryObjectUtils::GetFileAssetFromUri(const string &uriStr)
930 {
931 string id = MediaLibraryDataManagerUtils::GetIdFromUri(uriStr);
932 string networkId = MediaFileUtils::GetNetworkIdFromUri(uriStr);
933
934 return GetFileAssetFromId(id, networkId);
935 }
936
GetDefaultRelativePath(const int32_t mediaType,string & relativePath)937 void MediaLibraryObjectUtils::GetDefaultRelativePath(const int32_t mediaType, string &relativePath)
938 {
939 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_DIR, OperationType::QUERY);
940 cmd.GetAbsRdbPredicates()->EqualTo(DIRECTORY_DB_MEDIA_TYPE, to_string(mediaType));
941
942 auto resultSet = QueryWithCondition(cmd, {});
943 if (resultSet == nullptr) {
944 MEDIA_ERR_LOG("Failed to obtain file asset from database, mediaType: %{public}d", static_cast<int>(mediaType));
945 return;
946 }
947
948 if (resultSet->GoToFirstRow() == NativeRdb::E_OK) {
949 relativePath = get<string>(ResultSetUtils::GetValFromColumn(DIRECTORY_DB_DIRECTORY, resultSet, TYPE_STRING));
950 }
951 }
952
GetRelativePathFromFilePath(const string & path)953 string GetRelativePathFromFilePath(const string &path)
954 {
955 string relativePath;
956 if (path.length() > ROOT_MEDIA_DIR.length()) {
957 relativePath = path.substr(ROOT_MEDIA_DIR.length());
958 }
959 size_t pos = relativePath.rfind('/');
960 if (pos != string::npos) {
961 relativePath = relativePath.substr(0, pos + 1);
962 }
963 return relativePath;
964 }
965
UpdateFileInfoInDb(MediaLibraryCommand & cmd,const string & dstPath,const int32_t & bucketId,const string & bucketName)966 int32_t MediaLibraryObjectUtils::UpdateFileInfoInDb(MediaLibraryCommand &cmd, const string &dstPath,
967 const int32_t &bucketId, const string &bucketName)
968 {
969 MEDIA_DEBUG_LOG("enter, dstPath: %{private}s,", dstPath.c_str());
970 if (dstPath.empty()) {
971 MEDIA_ERR_LOG("Input argument is empty.");
972 return E_INVALID_PATH;
973 }
974
975 // dispName doesn't be used, maybe forget
976 size_t found = dstPath.rfind("/");
977 string dispName;
978 if (found != string::npos) {
979 dispName = dstPath.substr(found + 1);
980 }
981
982 struct stat statInfo;
983 if (stat(dstPath.c_str(), &statInfo) != 0) {
984 MEDIA_ERR_LOG("dstPath %{private}s is invalid. Modify failed!", dstPath.c_str());
985 return E_HAS_FS_ERROR;
986 }
987 string fileId = cmd.GetOprnFileId();
988 string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(ScannerUtils::GetFileExtension(dstPath));
989 MediaType mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
990 string displayName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(dstPath);
991 ValuesBucket values;
992 values.PutString(MEDIA_DATA_DB_NAME, displayName);
993 values.PutString(MEDIA_DATA_DB_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
994 values.PutString(MEDIA_DATA_DB_FILE_PATH, dstPath);
995 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, GetRelativePathFromFilePath(dstPath));
996 values.PutString(MEDIA_DATA_DB_BUCKET_NAME, bucketName);
997 values.PutString(MEDIA_DATA_DB_MIME_TYPE, mimeType);
998 values.PutString(MEDIA_DATA_DB_URI, MediaFileUtils::GetMediaTypeUri(mediaType));
999 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
1000 values.PutInt(MEDIA_DATA_DB_BUCKET_ID, bucketId);
1001 values.PutInt(MEDIA_DATA_DB_PARENT_ID, bucketId);
1002 cmd.SetValueBucket(values);
1003
1004 return ModifyInfoByIdInDb(cmd, fileId);
1005 }
1006
GetPathByIdFromDb(const string & id,const bool isDelete)1007 string MediaLibraryObjectUtils::GetPathByIdFromDb(const string &id, const bool isDelete)
1008 {
1009 return GetStringColumnByIdFromDb(id, MEDIA_DATA_DB_FILE_PATH, isDelete);
1010 }
1011
GetRecyclePathByIdFromDb(const string & id)1012 string MediaLibraryObjectUtils::GetRecyclePathByIdFromDb(const string &id)
1013 {
1014 return GetStringColumnByIdFromDb(id, MEDIA_DATA_DB_RECYCLE_PATH);
1015 }
1016
GetStringColumnByIdFromDb(const string & id,const string & column,const bool isDelete)1017 string MediaLibraryObjectUtils::GetStringColumnByIdFromDb(const string &id, const string &column, const bool isDelete)
1018 {
1019 string value;
1020 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1021 if (uniStore == nullptr) {
1022 MEDIA_ERR_LOG("uniStore is nullptr!");
1023 return value;
1024 }
1025
1026 if ((id.empty()) || (!MediaLibraryDataManagerUtils::IsNumber(id)) || (stoi(id) == -1)) {
1027 MEDIA_ERR_LOG("Id for the path is incorrect or rdbStore is null");
1028 return value;
1029 }
1030
1031 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1032 if (isDelete) {
1033 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id);
1034 } else {
1035 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, id)->And()->
1036 EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1037 }
1038 vector<string> columns;
1039 columns.push_back(column);
1040
1041 auto queryResultSet = uniStore->Query(cmd, columns);
1042 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, value, "Failed to obtain value from database");
1043
1044 auto ret = queryResultSet->GoToFirstRow();
1045 CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to shift at first row");
1046 int32_t columnIndex = 0;
1047 ret = queryResultSet->GetColumnIndex(column, columnIndex);
1048 CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to obtain column index");
1049
1050 ret = queryResultSet->GetString(columnIndex, value);
1051 CHECK_AND_RETURN_RET_LOG(ret == 0, value, "Failed to obtain value");
1052
1053 return value;
1054 }
1055
GetIdByPathFromDb(const string & path)1056 int32_t MediaLibraryObjectUtils::GetIdByPathFromDb(const string &path)
1057 {
1058 MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1059 if (path.empty()) {
1060 return E_INVALID_PATH;
1061 }
1062 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1063 if (uniStore == nullptr) {
1064 MEDIA_ERR_LOG("uniStore is nullptr!");
1065 return E_HAS_DB_ERROR;
1066 }
1067
1068 int32_t columnIndex = 0;
1069 string newPath = path;
1070 if (newPath.back() == '/') {
1071 newPath.pop_back();
1072 }
1073 int32_t fileId = E_INVALID_FILEID;
1074
1075 vector<string> columns;
1076 columns.push_back(MEDIA_DATA_DB_ID);
1077
1078 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1079 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, newPath)->And()->
1080 EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1081 auto queryResultSet = uniStore->Query(cmd, columns);
1082 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, fileId, "Failed to obtain path from database");
1083
1084 auto ret = queryResultSet->GoToFirstRow();
1085 CHECK_AND_RETURN_RET(ret == 0, fileId);
1086
1087 ret = queryResultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
1088 CHECK_AND_RETURN_RET_LOG(ret == 0, fileId, "Failed to obtain column index");
1089
1090 ret = queryResultSet->GetInt(columnIndex, fileId);
1091 CHECK_AND_RETURN_RET_LOG(ret == 0, fileId, "Failed to obtain file id");
1092
1093 return fileId;
1094 }
1095
GetParentIdByIdFromDb(const string & fileId)1096 int32_t MediaLibraryObjectUtils::GetParentIdByIdFromDb(const string &fileId)
1097 {
1098 MEDIA_DEBUG_LOG("enter, fileId = %{private}s", fileId.c_str());
1099 if (fileId.empty() || fileId == "-1") {
1100 return E_INVALID_FILEID;
1101 }
1102 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1103 if (uniStore == nullptr) {
1104 MEDIA_ERR_LOG("uniStore is nullptr!");
1105 return E_HAS_DB_ERROR;
1106 }
1107
1108 int32_t parentIdVal = -1;
1109 int32_t columnIndex = 0;
1110 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1111 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, fileId);
1112 auto queryResultSet = uniStore->Query(cmd, {});
1113 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, parentIdVal, "Failed to obtain path from database");
1114
1115 auto ret = queryResultSet->GoToNextRow();
1116 CHECK_AND_RETURN_RET_LOG(ret == 0, parentIdVal, "Failed to shift at next row");
1117
1118 ret = queryResultSet->GetColumnIndex(MEDIA_DATA_DB_PARENT_ID, columnIndex);
1119 CHECK_AND_RETURN_RET_LOG(ret == 0, parentIdVal, "Failed to obtain column index");
1120
1121 ret = queryResultSet->GetInt(columnIndex, parentIdVal);
1122 CHECK_AND_RETURN_RET_LOG(ret == 0, parentIdVal, "Failed to obtain file id");
1123
1124 return parentIdVal;
1125 }
1126
InsertInDb(MediaLibraryCommand & cmd)1127 int32_t MediaLibraryObjectUtils::InsertInDb(MediaLibraryCommand &cmd)
1128 {
1129 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1130 if (uniStore == nullptr) {
1131 MEDIA_ERR_LOG("uniStore is nullptr!");
1132 return E_HAS_DB_ERROR;
1133 }
1134
1135 int64_t outRowId = E_HAS_DB_ERROR;
1136 int32_t result = uniStore->Insert(cmd, outRowId);
1137 if (result != NativeRdb::E_OK) {
1138 MEDIA_ERR_LOG("Insert operation failed. Result %{public}d. Deleted %{public}d",
1139 result, static_cast<int32_t>(outRowId));
1140 return E_HAS_DB_ERROR;
1141 }
1142 return static_cast<int32_t>(outRowId);
1143 }
1144
DeleteInfoByPathInDb(MediaLibraryCommand & cmd,const string & path)1145 int32_t MediaLibraryObjectUtils::DeleteInfoByPathInDb(MediaLibraryCommand &cmd, const string &path)
1146 {
1147 MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1148 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1149 if (uniStore == nullptr) {
1150 MEDIA_ERR_LOG("uniStore is nullptr!");
1151 return E_HAS_DB_ERROR;
1152 }
1153
1154 int32_t deletedRows = E_HAS_DB_ERROR;
1155 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path);
1156 int32_t result = uniStore->Delete(cmd, deletedRows);
1157 if (result != NativeRdb::E_OK) {
1158 MEDIA_ERR_LOG("Delete operation failed. Result %{public}d. Deleted %{public}d", result, deletedRows);
1159 return E_HAS_DB_ERROR;
1160 }
1161
1162 return E_SUCCESS;
1163 }
1164
DeleteInfoByIdInDb(MediaLibraryCommand & cmd,const string & fileId)1165 int32_t MediaLibraryObjectUtils::DeleteInfoByIdInDb(MediaLibraryCommand &cmd, const string &fileId)
1166 {
1167 MEDIA_DEBUG_LOG("enter, fileId = %{private}s", fileId.c_str());
1168 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1169 if (uniStore == nullptr) {
1170 MEDIA_ERR_LOG("uniStore is nullptr!");
1171 return E_HAS_DB_ERROR;
1172 }
1173
1174 string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1175 if (strDeleteCondition.empty()) {
1176 string strRow = fileId.empty() ? cmd.GetOprnFileId() : fileId;
1177 if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
1178 MEDIA_ERR_LOG("MediaLibraryObjectUtils DeleteFile: Index not digit");
1179 return E_INVALID_FILEID;
1180 }
1181 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, strRow);
1182 }
1183
1184 int32_t deletedRows = E_HAS_DB_ERROR;
1185 int32_t result = uniStore->Delete(cmd, deletedRows);
1186 if (result != NativeRdb::E_OK) {
1187 MEDIA_ERR_LOG("Delete operation failed. Result %{public}d. Deleted %{public}d", result, deletedRows);
1188 }
1189
1190 return deletedRows;
1191 }
1192
ModifyInfoByPathInDb(MediaLibraryCommand & cmd,const string & path)1193 int32_t MediaLibraryObjectUtils::ModifyInfoByPathInDb(MediaLibraryCommand &cmd, const string &path)
1194 {
1195 MEDIA_DEBUG_LOG("enter, path = %{private}s", path.c_str());
1196 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1197 if (uniStore == nullptr) {
1198 MEDIA_ERR_LOG("uniStore is nullptr!");
1199 return E_HAS_DB_ERROR;
1200 }
1201
1202 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path);
1203 int32_t updatedRows = E_HAS_DB_ERROR;
1204 int32_t result = uniStore->Update(cmd, updatedRows);
1205 if (result != NativeRdb::E_OK || updatedRows <= 0) {
1206 MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updatedRows);
1207 }
1208
1209 return updatedRows;
1210 }
1211
ModifyInfoByIdInDb(MediaLibraryCommand & cmd,const string & fileId)1212 int32_t MediaLibraryObjectUtils::ModifyInfoByIdInDb(MediaLibraryCommand &cmd, const string &fileId)
1213 {
1214 MEDIA_DEBUG_LOG("enter, fileId = %{private}s", fileId.c_str());
1215 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1216 if (uniStore == nullptr) {
1217 MEDIA_ERR_LOG("uniStore is nullptr!");
1218 return E_HAS_DB_ERROR;
1219 }
1220
1221 string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1222 if (strDeleteCondition.empty()) {
1223 string strRow = fileId.empty() ? cmd.GetOprnFileId() : fileId;
1224 if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow) || (stoi(strRow) == -1)) {
1225 MEDIA_ERR_LOG("DeleteFile: Index not digit");
1226 return E_INVALID_FILEID;
1227 }
1228 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, strRow);
1229 }
1230
1231 int32_t updatedRows = E_HAS_DB_ERROR;
1232 int32_t result = uniStore->Update(cmd, updatedRows);
1233 if (result != NativeRdb::E_OK || updatedRows <= 0) {
1234 MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updatedRows);
1235 }
1236
1237 return updatedRows;
1238 }
1239
QueryWithCondition(MediaLibraryCommand & cmd,const vector<string> & columns,const string & conditionColumn)1240 shared_ptr<ResultSet> MediaLibraryObjectUtils::QueryWithCondition(MediaLibraryCommand &cmd,
1241 const vector<string> &columns, const string &conditionColumn)
1242 {
1243 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1244 if (uniStore == nullptr) {
1245 MEDIA_ERR_LOG("uniStore is nullptr!");
1246 return nullptr;
1247 }
1248
1249 string strQueryCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1250 if (strQueryCondition.empty()) {
1251 if (conditionColumn.empty()) {
1252 return uniStore->QuerySql("SELECT * FROM " + cmd.GetTableName());
1253 }
1254 string strFileId = cmd.GetOprnFileId();
1255 if (strFileId.empty()) {
1256 MEDIA_ERR_LOG("Get file id from uri or valuebucket failed!");
1257 return nullptr;
1258 }
1259 cmd.GetAbsRdbPredicates()->EqualTo(conditionColumn, strFileId);
1260 }
1261
1262 return uniStore->Query(cmd, columns);
1263 }
1264
IsColumnValueExist(const string & value,const string & column)1265 bool MediaLibraryObjectUtils::IsColumnValueExist(const string &value, const string &column)
1266 {
1267 if (column.empty()) {
1268 MEDIA_ERR_LOG("Empty column param");
1269 return false;
1270 }
1271 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1272 if (uniStore == nullptr) {
1273 MEDIA_ERR_LOG("uniStore is nullptr!");
1274 return false;
1275 }
1276
1277 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1278 cmd.GetAbsRdbPredicates()->EqualTo(column, value);
1279 vector<string> columns;
1280 columns.push_back(column);
1281 auto queryResultSet = uniStore->Query(cmd, columns);
1282 if (queryResultSet != nullptr) {
1283 int32_t count = 0;
1284 queryResultSet->GetRowCount(count);
1285 if (count > 0) {
1286 return true;
1287 }
1288 }
1289 return false;
1290 }
1291
IsAssetExistInDb(const int32_t id,const bool isIncludeTrash)1292 bool MediaLibraryObjectUtils::IsAssetExistInDb(const int32_t id, const bool isIncludeTrash)
1293 {
1294 if (id <= 0) {
1295 MEDIA_ERR_LOG("Invalid id param");
1296 return false;
1297 }
1298 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1299 if (isIncludeTrash) {
1300 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(id));
1301 } else {
1302 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, to_string(id))->And()->
1303 EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1304 }
1305 vector<string> columns;
1306 auto queryResultSet = QueryWithCondition(cmd, columns);
1307 if (queryResultSet != nullptr && queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1308 return true;
1309 }
1310 return false;
1311 }
1312
IsFileExistInDb(const string & path)1313 bool MediaLibraryObjectUtils::IsFileExistInDb(const string &path)
1314 {
1315 if (path.empty()) {
1316 MEDIA_ERR_LOG("path is incorrect");
1317 return false;
1318 }
1319
1320 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1321 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_FILE_PATH, path)
1322 ->And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
1323
1324 vector<string> columns;
1325 columns.push_back(MEDIA_DATA_DB_FILE_PATH);
1326 auto queryResultSet = QueryWithCondition(cmd, columns);
1327 if (queryResultSet != nullptr && queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1328 return true;
1329 }
1330
1331 return false;
1332 }
1333
CheckUriPending(const std::string & uri)1334 bool MediaLibraryObjectUtils::CheckUriPending(const std::string &uri)
1335 {
1336 if (!uri.empty()) {
1337 int positon = uri.find_first_of('?');
1338 string tempUri = uri.substr(0, positon);
1339 auto fileAsset = GetFileAssetFromUri(tempUri);
1340 if ((fileAsset != nullptr) && (fileAsset->GetTimePending() != 0)) {
1341 return true;
1342 }
1343 }
1344 return false;
1345 }
1346
CopyAsset(const shared_ptr<FileAsset> & srcFileAsset,const string & relativePath)1347 int32_t MediaLibraryObjectUtils::CopyAsset(const shared_ptr<FileAsset> &srcFileAsset,
1348 const string &relativePath)
1349 {
1350 if (srcFileAsset == nullptr) {
1351 MEDIA_ERR_LOG("Failed to obtain path from Database");
1352 return E_INVALID_URI;
1353 }
1354 string srcPath = MediaFileUtils::UpdatePath(srcFileAsset->GetPath(), srcFileAsset->GetUri());
1355 int32_t srcFd = OpenAsset(srcPath, MEDIA_FILEMODE_READWRITE);
1356 // dest asset
1357 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::CREATE);
1358 ValuesBucket values;
1359 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath);
1360 string displayName = srcFileAsset->GetDisplayName();
1361 values.PutString(MEDIA_DATA_DB_NAME, displayName);
1362 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, srcFileAsset->GetMediaType());
1363 cmd.SetValueBucket(values);
1364 int32_t outRow = CreateFileObj(cmd);
1365 while (outRow == E_FILE_EXIST) {
1366 displayName = displayName + ASSET_RECYCLE_SUFFIX;
1367 values.PutString(MEDIA_DATA_DB_NAME, displayName);
1368 outRow = CreateFileObj(cmd);
1369 }
1370 if (outRow < 0) {
1371 MEDIA_ERR_LOG("Failed to obtain CreateFileObj");
1372 return outRow;
1373 }
1374 shared_ptr<FileAsset> destFileAsset = GetFileAssetFromId(to_string(outRow));
1375 if (destFileAsset == nullptr) {
1376 MEDIA_ERR_LOG("Failed to obtain path from Database");
1377 return E_INVALID_URI;
1378 }
1379 string destPath = MediaFileUtils::UpdatePath(destFileAsset->GetPath(), destFileAsset->GetUri());
1380 int32_t destFd = OpenAsset(destPath, MEDIA_FILEMODE_READWRITE);
1381 return CopyAssetByFd(srcFd, srcFileAsset->GetId(), destFd, outRow);
1382 }
1383
CopyAssetByFd(int32_t srcFd,int32_t srcId,int32_t destFd,int32_t destId)1384 int32_t MediaLibraryObjectUtils::CopyAssetByFd(int32_t srcFd, int32_t srcId, int32_t destFd, int32_t destId)
1385 {
1386 struct stat statSrc;
1387 if (fstat(srcFd, &statSrc) == -1) {
1388 CloseFileById(srcId);
1389 MEDIA_ERR_LOG("File get stat failed, %{public}d", errno);
1390 return E_FILE_OPER_FAIL;
1391 }
1392
1393 if (sendfile(destFd, srcFd, nullptr, statSrc.st_size) == -1) {
1394 CloseFileById(srcId);
1395 CloseFileById(destId);
1396 MEDIA_ERR_LOG("copy file fail %{public}d ", errno);
1397 return E_FILE_OPER_FAIL;
1398 }
1399 CloseFileById(srcId);
1400 CloseFileById(destId);
1401 return destId;
1402 }
1403
CloseFileById(int32_t fileId)1404 void MediaLibraryObjectUtils::CloseFileById(int32_t fileId)
1405 {
1406 ValuesBucket values;
1407 values.PutInt(MEDIA_DATA_DB_ID, fileId);
1408 MediaLibraryCommand closeCmd(OperationObject::FILESYSTEM_ASSET, OperationType::CLOSE, values);
1409 CloseFile(closeCmd);
1410 }
1411
GetFileResult(shared_ptr<NativeRdb::ResultSet> & resultSet,int count,const string & relativePath,const string & displayName)1412 int32_t MediaLibraryObjectUtils::GetFileResult(shared_ptr<NativeRdb::ResultSet> &resultSet,
1413 int count, const string &relativePath, const string &displayName)
1414 {
1415 shared_ptr<FetchResult<FileAsset>> fetchFileResult = make_shared<FetchResult<FileAsset>>();
1416 int errCode = E_SUCCESS;
1417 for (int32_t row = 0; row < count; row++) {
1418 unique_ptr<FileAsset> fileAsset = fetchFileResult->GetObjectFromRdb(resultSet, row);
1419 if (fileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
1420 errCode = CopyDir(move(fileAsset), relativePath + displayName + "/");
1421 CHECK_AND_RETURN_RET_LOG(errCode > 0, errCode, "failed to copy dir");
1422 } else {
1423 errCode = CopyAsset(move(fileAsset), relativePath + displayName + "/");
1424 CHECK_AND_RETURN_RET_LOG(errCode > 0, errCode, "failed to copy asset");
1425 }
1426 }
1427 return errCode;
1428 }
1429
CopyDir(const shared_ptr<FileAsset> & srcDirAsset,const string & relativePath)1430 int32_t MediaLibraryObjectUtils::CopyDir(const shared_ptr<FileAsset> &srcDirAsset,
1431 const string &relativePath)
1432 {
1433 if (srcDirAsset == nullptr) {
1434 MEDIA_ERR_LOG("Failed to obtain path from Database");
1435 return E_INVALID_URI;
1436 }
1437 ValuesBucket values;
1438 values.PutString(MEDIA_DATA_DB_NAME, ".nofile");
1439 values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_TYPE_NOFILE);
1440 string displayName = srcDirAsset->GetDisplayName();
1441 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath + displayName + "/");
1442 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::CREATE);
1443 cmd.SetValueBucket(values);
1444 int32_t outRow = CreateFileObj(cmd);
1445 while (outRow == E_FILE_EXIST) {
1446 displayName = displayName + ASSET_RECYCLE_SUFFIX;
1447 values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, relativePath + displayName + "/");
1448 outRow = CreateFileObj(cmd);
1449 }
1450 if (outRow < 0) {
1451 MEDIA_ERR_LOG("Failed to obtain CreateFileObj");
1452 return outRow;
1453 }
1454 MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1455 queryCmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_PARENT_ID, to_string(srcDirAsset->GetId()))->And()->
1456 EqualTo(MEDIA_DATA_DB_IS_TRASH, "0")->And()->NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_NOFILE));
1457 auto resultSet = QueryWithCondition(queryCmd, {});
1458 auto count = 0;
1459 auto ret = resultSet->GetRowCount(count);
1460 CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR, "get rdbstore failed");
1461 if (count == 0) {
1462 MEDIA_ERR_LOG("have no copy file");
1463 return E_SUCCESS;
1464 }
1465
1466 int err = GetFileResult(resultSet, count, relativePath, displayName);
1467 resultSet.reset();
1468 if (err <= 0) {
1469 return err;
1470 }
1471 Uri srcUri(MEDIALIBRARY_DATA_URI + "/" + to_string(outRow));
1472 string srcUriString = srcUri.ToString();
1473 shared_ptr<FileAsset> srcAsset = MediaLibraryObjectUtils::GetFileAssetFromUri(srcUriString);
1474 if (srcAsset == nullptr) {
1475 MEDIA_ERR_LOG("Failed to obtain parentAsset from Database");
1476 return E_INVALID_URI;
1477 }
1478 return srcAsset->GetParent();
1479 }
1480
GetRelativePathFromPath(const string & path)1481 static string GetRelativePathFromPath(const string &path)
1482 {
1483 string relativePath;
1484 if (path.find(ROOT_MEDIA_DIR) == 0) {
1485 relativePath = path.substr(ROOT_MEDIA_DIR.length());
1486 }
1487 auto pos = relativePath.rfind('/');
1488 if (pos == string::npos) {
1489 return "";
1490 }
1491 return relativePath.substr(0, pos + 1);
1492 }
1493
CheckDirExtension(const string & destFilePath)1494 int32_t MediaLibraryObjectUtils::CheckDirExtension(const string &destFilePath)
1495 {
1496 string relativePath = GetRelativePathFromPath(destFilePath);
1497 string displayName = MediaLibraryDataManagerUtils::GetDisPlayNameFromPath(destFilePath);
1498 return CheckDirExtension(relativePath, displayName);
1499 }
1500
GetRootDirAssetByRelativePath(const string & relativePath,DirAsset & dirAsset)1501 static int32_t GetRootDirAssetByRelativePath(const string &relativePath, DirAsset &dirAsset)
1502 {
1503 auto pos = relativePath.find('/');
1504 if (pos == string::npos) {
1505 return E_CHECK_EXTENSION_FAIL;
1506 }
1507 string rootDir = relativePath.substr(0, pos + 1);
1508 auto dirMap = MediaLibraryDataManager::GetDirQuerySetMap();
1509 if (dirMap.find(rootDir) == dirMap.end()) {
1510 return E_CHECK_EXTENSION_FAIL;
1511 }
1512 dirAsset = dirMap.at(rootDir);
1513 return E_SUCCESS;
1514 }
1515
CheckDirExtension(const string & relativePath,const string & displayName)1516 int32_t MediaLibraryObjectUtils::CheckDirExtension(const string &relativePath, const string &displayName)
1517 {
1518 if (relativePath.empty() || displayName.empty()) {
1519 return E_INVALID_ARGUMENTS;
1520 }
1521 if (displayName.compare(MEDIA_NO_FILE) == 0) {
1522 return E_SUCCESS;
1523 }
1524 if (MediaFileUtils::CheckFileDisplayName(displayName) < 0) {
1525 MEDIA_ERR_LOG("Check File DisplayName failed, displayName: %{private}s", displayName.c_str());
1526 return E_FILE_NAME_INVALID;
1527 }
1528 DirAsset rootDirAsset;
1529 auto ret = GetRootDirAssetByRelativePath(relativePath, rootDirAsset);
1530 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret, "get root dir from relativePath failed, path: %{private}s",
1531 relativePath.c_str());
1532 string dirMediaTypes = rootDirAsset.GetMediaTypes();
1533 if (dirMediaTypes == DIR_ALL_TYPE_VALUES) {
1534 return E_SUCCESS;
1535 }
1536 string fileExtension = MediaFileUtils::GetExtensionFromPath(displayName);
1537 string fileMimeType = MimeTypeUtils::GetMimeTypeFromExtension(fileExtension);
1538 string fileMediaType = to_string(static_cast<int32_t>(MimeTypeUtils::GetMediaTypeFromMimeType(fileMimeType)));
1539 if (dirMediaTypes.find(fileMediaType) == string::npos) {
1540 MEDIA_ERR_LOG("CheckDirExtension failed, file extension: %{private}s, root dir media_type: %{private}s",
1541 fileExtension.c_str(), dirMediaTypes.c_str());
1542 return E_CHECK_EXTENSION_FAIL;
1543 }
1544 return E_SUCCESS;
1545 }
1546
IsSmartAlbumExistInDb(const int32_t id)1547 bool MediaLibraryObjectUtils::IsSmartAlbumExistInDb(const int32_t id)
1548 {
1549 MediaLibraryCommand querySmartAlbumCmd(OperationObject::SMART_ALBUM, OperationType::QUERY);
1550 querySmartAlbumCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUM_DB_ID, to_string(id));
1551 auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1552 if (queryResultSet != nullptr) {
1553 if (queryResultSet->GoToFirstRow() == NativeRdb::E_OK) {
1554 return true;
1555 }
1556 } else {
1557 MEDIA_ERR_LOG("QuerySmartAlbum failed");
1558 }
1559 return false;
1560 }
1561
IsParentSmartAlbum(const int32_t id,const bool isInclude)1562 bool MediaLibraryObjectUtils::IsParentSmartAlbum(const int32_t id, const bool isInclude)
1563 {
1564 MediaLibraryCommand querySmartAlbumCmd(OperationObject::SMART_ALBUM_MAP, OperationType::QUERY);
1565 querySmartAlbumCmd.GetAbsRdbPredicates()->EqualTo(SMARTALBUMMAP_DB_ALBUM_ID, to_string(id));
1566 if (isInclude) {
1567 auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1568 if (queryResultSet != nullptr) {
1569 if (queryResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1570 return true;
1571 }
1572 queryResultSet.reset();
1573 } else {
1574 MEDIA_ERR_LOG("QuerySmartAlbum failed");
1575 return false;
1576 }
1577 }
1578 querySmartAlbumCmd.GetAbsRdbPredicates()->IsNotNull(SMARTALBUMMAP_DB_CHILD_ALBUM_ID);
1579 auto queryResultSet = QuerySmartAlbum(querySmartAlbumCmd);
1580 if (queryResultSet != nullptr) {
1581 if (queryResultSet->GoToFirstRow() == NativeRdb::E_OK) {
1582 return true;
1583 }
1584 }
1585 return false;
1586 }
1587
QuerySmartAlbum(MediaLibraryCommand & cmd)1588 shared_ptr<ResultSet> MediaLibraryObjectUtils::QuerySmartAlbum(MediaLibraryCommand &cmd)
1589 {
1590 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1591 if (uniStore == nullptr) {
1592 MEDIA_ERR_LOG("UniStore is nullptr");
1593 return nullptr;
1594 }
1595 vector<string> columns;
1596 return uniStore->Query(cmd, columns);
1597 }
1598 } // namespace Media
1599 } // namespace OHOS
1600