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