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