• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "file_entry.h"
17 #include <cstring>
18 #include <fstream>
19 #include <iostream>
20 #include "dirent.h"
21 #include "sys/stat.h"
22 #include "unistd.h"
23 #ifdef _WIN32
24 #include "shlwapi.h"
25 #include "windows.h"
26 #endif
27 #include "resource_data.h"
28 #include "restool_errors.h"
29 
30 namespace OHOS {
31 namespace Global {
32 namespace Restool {
33 #ifdef _WIN32
34 const std::string FileEntry::SEPARATE = "\\";
35 #else
36 const std::string FileEntry::SEPARATE = "/";
37 #endif
38 
39 using namespace std;
FileEntry(const string & path)40 FileEntry::FileEntry(const string &path)
41     : filePath_(path), isFile_(false)
42 {
43 }
44 
~FileEntry()45 FileEntry::~FileEntry()
46 {
47 }
48 
Init()49 bool FileEntry::Init()
50 {
51     string filePath = filePath_.GetPath();
52     if (!Exist(filePath)) {
53         cout << "Warning: file not exist: " << filePath << endl;
54         return false;
55     }
56 
57     isFile_ = !IsDirectory(filePath);
58     return true;
59 }
60 
GetChilds() const61 const vector<unique_ptr<FileEntry>> FileEntry::GetChilds() const
62 {
63     vector<unique_ptr<FileEntry>> children;
64     string filePath = filePath_.GetPath();
65 #ifdef _WIN32
66     WIN32_FIND_DATA findData;
67     string temp(filePath + "\\*.*");
68     HANDLE handle = FindFirstFile(AdaptLongPath(temp).c_str(), &findData);
69     if (handle == INVALID_HANDLE_VALUE) {
70         return children;
71     }
72 
73     do {
74         string filename(findData.cFileName);
75         if (IsIgnore(filename)) {
76             continue;
77         }
78 
79         filePath = filePath_.GetPath() + SEPARATE + filename;
80         unique_ptr<FileEntry> f = make_unique<FileEntry>(filePath);
81         f->Init();
82         children.push_back(move(f));
83     } while (FindNextFile(handle, &findData));
84     FindClose(handle);
85 #else
86     DIR *handle = opendir(filePath.c_str());
87     struct dirent *entry;
88     while ((entry = readdir(handle)) != nullptr) {
89         string filename(entry->d_name);
90         if (IsIgnore(filename)) {
91             continue;
92         }
93 
94         filePath = filePath_.GetPath() + SEPARATE + filename;
95         unique_ptr<FileEntry> f = make_unique<FileEntry>(filePath);
96         f->Init();
97         children.push_back(move(f));
98     }
99     closedir(handle);
100 #endif
101     return children;
102 }
103 
IsFile() const104 bool FileEntry::IsFile() const
105 {
106     return isFile_;
107 }
108 
GetFilePath() const109 const FileEntry::FilePath &FileEntry::GetFilePath() const
110 {
111     return filePath_;
112 }
113 
Exist(const string & path)114 bool FileEntry::Exist(const string &path)
115 {
116 #ifdef _WIN32
117     return PathFileExists(AdaptLongPath(path).c_str());
118 #else
119     struct stat s;
120     if (stat(path.c_str(), &s) != 0) {
121         return false;
122     }
123 #endif
124     return true;
125 }
126 
RemoveAllDir(const string & path)127 bool FileEntry::RemoveAllDir(const string &path)
128 {
129     FileEntry f(path);
130     if (!f.Init()) {
131         return false;
132     }
133 
134     if (f.IsFile()) {
135         PrintError(GetError(ERR_CODE_REMOVE_FILE_ERROR).FormatCause(path.c_str(), "not directory"));
136         return false;
137     }
138     return RemoveAllDirInner(f);
139 }
140 
RemoveFile(const string & path)141 bool FileEntry::RemoveFile(const string &path)
142 {
143     FileEntry f(path);
144     if (!f.Init()) {
145         return false;
146     }
147     return RemoveAllDirInner(f);
148 }
149 
CreateDirs(const string & path)150 bool FileEntry::CreateDirs(const string &path)
151 {
152     return CreateDirsInner(path, 0);
153 }
154 
CopyFileInner(const string & src,const string & dst)155 bool FileEntry::CopyFileInner(const string &src, const string &dst)
156 {
157 #ifdef _WIN32
158     if (!CopyFile(AdaptLongPath(src).c_str(), AdaptLongPath(dst).c_str(), false)) {
159         PrintError(GetError(ERR_CODE_COPY_FILE_ERROR).FormatCause(src.c_str(), dst.c_str(), strerror(errno)));
160         return false;
161     }
162 #else
163     ifstream in(src, ios::binary);
164     ofstream out(dst, ios::binary);
165     if (!in || !out) {
166         PrintError(GetError(ERR_CODE_COPY_FILE_ERROR).FormatCause(src.c_str(), dst.c_str(), strerror(errno)));
167         return false;
168     }
169     out << in.rdbuf();
170 #endif
171     return true;
172 }
173 
IsDirectory(const string & path)174 bool FileEntry::IsDirectory(const string &path)
175 {
176 #ifdef _WIN32
177     if (!PathIsDirectory(AdaptLongPath(path).c_str())) {
178         return false;
179     }
180     return true;
181 #else
182     struct stat s;
183     stat(path.c_str(), &s);
184     return S_ISDIR(s.st_mode);
185 #endif
186 }
187 
RealPath(const string & path)188 string FileEntry::RealPath(const string &path)
189 {
190 #ifdef _WIN32
191     char buffer[MAX_PATH];
192     if (!PathCanonicalize(buffer, path.c_str())) {
193         return "";
194     }
195 
196     if (PathIsRelative(buffer)) {
197         char current[MAX_PATH];
198         if (!GetCurrentDirectory(MAX_PATH, current)) {
199             return "";
200         }
201 
202         char temp[MAX_PATH];
203         if (!PathCombine(temp, current, buffer)) {
204             return "";
205         }
206         if (!Exist(string(temp))) {
207             return "";
208         }
209         return string(temp);
210     }
211 #else
212     char buffer[PATH_MAX];
213     if (!realpath(path.c_str(), buffer)) {
214         return "";
215     }
216 #endif
217     if (!Exist(string(buffer))) {
218         return "";
219     }
220     return string(buffer);
221 }
222 
FilePath(const string & path)223 FileEntry::FilePath::FilePath(const string &path) : filePath_(path)
224 {
225     Format();
226     Init();
227 }
228 
~FilePath()229 FileEntry::FilePath::~FilePath()
230 {
231 }
232 
Append(const string & path)233 FileEntry::FilePath FileEntry::FilePath::Append(const string &path)
234 {
235     Format();
236     string filePath = filePath_ + SEPARATE + path;
237     return FilePath(filePath);
238 }
239 
ReplaceExtension(const string & extension)240 FileEntry::FilePath FileEntry::FilePath::ReplaceExtension(const string &extension)
241 {
242     string filePath;
243     if (!parent_.empty()) {
244         filePath += parent_ + SEPARATE;
245     }
246 
247     filePath += filename_.substr(0, filename_.length() - extension_.length()) + extension;
248     return FilePath(filePath);
249 }
250 
GetParent()251 FileEntry::FilePath FileEntry::FilePath::GetParent()
252 {
253     return FilePath(parent_);
254 }
255 
GetPath() const256 const string &FileEntry::FilePath::GetPath() const
257 {
258     return filePath_;
259 }
260 
GetFilename() const261 const string &FileEntry::FilePath::GetFilename() const
262 {
263     return filename_;
264 }
265 
GetExtension() const266 const string &FileEntry::FilePath::GetExtension() const
267 {
268     return extension_;
269 }
270 
GetSegments() const271 const vector<string> FileEntry::FilePath::GetSegments() const
272 {
273     vector<string> segments;
274     string::size_type offset = 0;
275     string::size_type pos = filePath_.find_first_of(SEPARATE.front(), offset);
276     while (pos != string::npos) {
277         segments.push_back(filePath_.substr(offset, pos - offset));
278         offset = pos + 1;
279         pos = filePath_.find_first_of(SEPARATE.front(), offset);
280     }
281 
282     if (offset < filePath_.length()) {
283         segments.push_back(filePath_.substr(offset));
284     }
285     return segments;
286 }
287 
288 // below private
IsIgnore(const string & filename) const289 bool FileEntry::IsIgnore(const string &filename) const
290 {
291     if (filename == "." || filename == "..") {
292         return true;
293     }
294     return false;
295 }
296 
RemoveAllDirInner(const FileEntry & entry)297 bool FileEntry::RemoveAllDirInner(const FileEntry &entry)
298 {
299     string path = entry.GetFilePath().GetPath();
300     if (entry.IsFile()) {
301 #ifdef _WIN32
302         bool result = remove(AdaptLongPath(path).c_str()) == 0;
303 #else
304         bool result = remove(path.c_str()) == 0;
305 #endif
306         if (!result) {
307             PrintError(GetError(ERR_CODE_REMOVE_FILE_ERROR).FormatCause(path.c_str(), strerror(errno)));
308             return false;
309         }
310         return true;
311     }
312 
313     for (const auto &iter : entry.GetChilds()) {
314         if (!RemoveAllDirInner(*iter)) {
315             return false;
316         }
317     }
318 #ifdef _WIN32
319     bool result = rmdir(AdaptLongPath(path).c_str()) == 0;
320 #else
321     bool result = rmdir(path.c_str()) == 0;
322 #endif
323     if (!result) {
324         PrintError(GetError(ERR_CODE_REMOVE_FILE_ERROR).FormatCause(path.c_str(), strerror(errno)));
325         return false;
326     }
327     return true;
328 }
329 
CreateDirsInner(const string & path,string::size_type offset)330 bool FileEntry::CreateDirsInner(const string &path, string::size_type offset)
331 {
332     string::size_type pos = path.find_first_of(SEPARATE.front(), offset);
333     if (pos == string::npos) {
334 #ifdef _WIN32
335         return CreateDirectory(AdaptLongPath(path).c_str(), nullptr) != 0;
336 #else
337         return mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0;
338 #endif
339     }
340 
341     string subPath = path.substr(0, pos + 1);
342     if (!Exist(subPath)) {
343 #ifdef _WIN32
344         if (!CreateDirectory(AdaptLongPath(subPath).c_str(), nullptr)) {
345 #else
346         if (mkdir(subPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
347 #endif
348             return false;
349         }
350     }
351     return CreateDirsInner(path, pos + 1);
352 }
353 
354 void FileEntry::FilePath::Format()
355 {
356     if (filePath_.back() != SEPARATE.front()) {
357         return;
358     }
359     filePath_.pop_back();
360 }
361 
362 void FileEntry::FilePath::Init()
363 {
364     filename_ = filePath_;
365     string::size_type pos = filePath_.find_last_of(SEPARATE.front());
366     if (pos != string::npos) {
367         parent_ = filePath_.substr(0, pos);
368         if (pos + 1 < filePath_.length()) {
369             filename_ = filePath_.substr(pos + 1);
370         }
371     }
372 
373     pos = filename_.find_last_of('.');
374     if (pos != string::npos && pos + 1 < filename_.length()) {
375         extension_ = filename_.substr(pos);
376     }
377 }
378 
379 string FileEntry::AdaptLongPath(const string &path)
380 {
381 #ifdef _WIN32
382     if (path.size() >= MAX_PATH -12) { //the max file path can not exceed 260 - 12
383         return LONG_PATH_HEAD + path;
384     }
385 #endif
386     return path;
387 }
388 }
389 }
390 }
391