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