• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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