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