• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "Scanner"
16 
17 #include "scanner_utils.h"
18 
19 #include <cerrno>
20 #include <fstream>
21 
22 #include "directory_ex.h"
23 #include "media_column.h"
24 #include "media_log.h"
25 #include "medialibrary_type_const.h"
26 namespace OHOS {
27 namespace Media {
28 using namespace std;
29 
30 // Check if file exists or not
IsExists(const string & path)31 bool ScannerUtils::IsExists(const string &path)
32 {
33     struct stat statInfo {};
34 
35     if (path.empty()) {
36         MEDIA_ERR_LOG("Given path name is empty");
37         return false;
38     }
39 
40     return ((stat(path.c_str(), &statInfo)) == ERR_SUCCESS);
41 }
42 
43 // Get the file name from file URI
GetFileNameFromUri(const string & path)44 string ScannerUtils::GetFileNameFromUri(const string &path)
45 {
46     if (!path.empty()) {
47         size_t lastSlashPosition = path.rfind("/");
48         if (lastSlashPosition != string::npos) {
49             if (path.size() > lastSlashPosition) {
50                 return path.substr(lastSlashPosition + 1);
51             }
52         }
53     }
54 
55     MEDIA_ERR_LOG("Failed to obtain file name because given pathname is empty");
56     return "";
57 }
58 
59 // Get file extension from the given filepath or displayName
GetFileExtension(const string & pathOrDisplayName)60 string ScannerUtils::GetFileExtension(const string &pathOrDisplayName)
61 {
62     if (!pathOrDisplayName.empty()) {
63         size_t dotIndex = pathOrDisplayName.rfind(".");
64         string extension {};
65         if (dotIndex != string::npos) {
66             extension = pathOrDisplayName.substr(dotIndex + 1);
67             CHECK_AND_WARN_LOG(!extension.empty(), "Extension is empty, path/displayName: %{public}s",
68                 pathOrDisplayName.c_str());
69             return extension;
70         }
71     }
72 
73     MEDIA_ERR_LOG("Failed to obtain file extension because given path/displayName is empty");
74     return "";
75 }
76 
77 // Check if the given path is a directory path
IsDirectory(const string & path)78 bool ScannerUtils::IsDirectory(const string &path)
79 {
80     struct stat s;
81 
82     if (!path.empty()) {
83         if (stat(path.c_str(), &s) == 0) {
84             if (s.st_mode & S_IFDIR) {
85                 return true;
86             }
87         }
88     }
89 
90     MEDIA_ERR_LOG("Either path is empty or it is not a directory");
91     return false;
92 }
93 
IsRegularFile(const string & path)94 bool ScannerUtils::IsRegularFile(const string &path)
95 {
96     struct stat s;
97     if (!path.empty()) {
98         if (stat(path.c_str(), &s) == 0) {
99             if (s.st_mode & S_IFREG) {
100                 return true;
101             }
102         }
103     }
104 
105     return false;
106 }
107 
108 // Check if the given file starts with '.' , i.e. if it is hidden
IsFileHidden(const string & path)109 bool ScannerUtils::IsFileHidden(const string &path)
110 {
111     if (!path.empty()) {
112         string fileName = GetFileNameFromUri(path);
113         if (!fileName.empty() && fileName.at(0) == '.') {
114             return true;
115         }
116     }
117 
118     return false;
119 }
120 
121 // Get the parent path
GetParentPath(const string & path)122 string ScannerUtils::GetParentPath(const string &path)
123 {
124     if (!path.empty()) {
125         size_t lastSlashPosition = path.rfind("/");
126         if (lastSlashPosition != string::npos && path.size() > lastSlashPosition) {
127             return path.substr(0, lastSlashPosition);
128         }
129     }
130 
131     MEDIA_ERR_LOG("Failed to obtain the parent path");
132     return "";
133 }
134 
GetRootMediaDir(string & dir)135 void ScannerUtils::GetRootMediaDir(string &dir)
136 {
137     dir = ROOT_MEDIA_DIR;
138 }
139 
GetFileTitle(const string & displayName)140 string ScannerUtils::GetFileTitle(const string &displayName)
141 {
142     string::size_type pos = displayName.find_last_of('.');
143     return (pos == string::npos) ? displayName : displayName.substr(0, pos);
144 }
145 
IsDirHidden(const string & path,bool skipPhoto)146 bool ScannerUtils::IsDirHidden(const string &path, bool skipPhoto)
147 {
148     bool dirHid = false;
149 
150     if (!path.empty()) {
151         string dirName = ScannerUtils::GetFileNameFromUri(path);
152         if (!dirName.empty() && dirName.at(0) == '.') {
153             MEDIA_DEBUG_LOG("hidden Directory, name:%{private}s path:%{private}s", dirName.c_str(), path.c_str());
154             return true;
155         }
156 
157         string curPath = path;
158         string excludePath = curPath.append("/.nomedia");
159         // Check is the folder consist of .nomedia file
160         if (ScannerUtils::IsExists(excludePath)) {
161             return true;
162         }
163 
164         // Check is the dir is part of skiplist
165         if (skipPhoto && CheckSkipScanList(path)) {
166             MEDIA_DEBUG_LOG("skip Directory, path:%{private}s", path.c_str());
167             return true;
168         }
169     }
170 
171     return dirHid;
172 }
173 
IsDirHiddenRecursive(const string & path,bool skipPhoto)174 bool ScannerUtils::IsDirHiddenRecursive(const string &path, bool skipPhoto)
175 {
176     bool dirHid = false;
177     string curPath = path;
178 
179     do {
180         dirHid = IsDirHidden(curPath, skipPhoto);
181         if (dirHid) {
182             break;
183         }
184 
185         curPath = ScannerUtils::GetParentPath(curPath);
186         if (curPath.empty()) {
187             break;
188         }
189     } while (true);
190 
191     return dirHid;
192 }
193 
194 // Check if path is part of Skip scan list
CheckSkipScanList(const string & path)195 bool ScannerUtils::CheckSkipScanList(const string &path)
196 {
197     if (path.length() <= ROOT_MEDIA_DIR.length()) {
198         return false;
199     }
200     static const string AUDIO = "Audios";
201     static const string CAMERA = "Camera";
202     static const string Pictures = "Pictures";
203     static const string Videos = "Videos";
204     static const string Doc = "Documents";
205     static const string Download = "Download";
206     // white list
207     static vector<string> list = {
208         { ROOT_MEDIA_DIR + AUDIO },
209         { ROOT_MEDIA_DIR + CAMERA },
210         { ROOT_MEDIA_DIR + Pictures },
211         { ROOT_MEDIA_DIR + Videos },
212         { ROOT_MEDIA_DIR + Doc },
213         { ROOT_MEDIA_DIR + Download },
214     };
215     for (const auto &pathPrefix : list) {
216         if (path.find(pathPrefix) != string::npos) {
217             return false;
218         }
219     }
220     return true;
221 }
222 } // namespace Media
223 } // namespace OHOS
224