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