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