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<fstream>
18 #include<iostream>
19 #include "dirent.h"
20 #include "sys/stat.h"
21 #include "unistd.h"
22
23 namespace OHOS {
24 namespace Global {
25 namespace Restool {
26 #ifdef _WIN32
27 const std::string FileEntry::SEPARATE = "\\";
28 #else
29 const std::string FileEntry::SEPARATE = "/";
30 #endif
31
32 using namespace std;
FileEntry(const string & path)33 FileEntry::FileEntry(const string &path)
34 : filePath_(path), isFile_(false)
35 {
36 }
37
~FileEntry()38 FileEntry::~FileEntry()
39 {
40 }
41
Init()42 bool FileEntry::Init()
43 {
44 string filePath = filePath_.GetPath();
45 if (!Exist(filePath)) {
46 cerr << "Error: '" << filePath << "' not exists." << endl;
47 return false;
48 }
49
50 isFile_ = !IsDirectory(filePath);
51 return true;
52 }
53
GetChilds() const54 const vector<unique_ptr<FileEntry>> FileEntry::GetChilds() const
55 {
56 vector<unique_ptr<FileEntry>> children;
57 struct dirent *entry;
58 string filePath = filePath_.GetPath();
59 DIR *handle = opendir(filePath.c_str());
60 while ((entry = readdir(handle)) != nullptr) {
61 string filename(entry->d_name);
62 if (IsIgnore(filename)) {
63 continue;
64 }
65
66 filePath = filePath_.GetPath() + SEPARATE + filename;
67 unique_ptr<FileEntry> f = make_unique<FileEntry>(filePath);
68 f->Init();
69 children.push_back(move(f));
70 }
71 closedir(handle);
72 return children;
73 }
74
IsFile() const75 bool FileEntry::IsFile() const
76 {
77 return isFile_;
78 }
79
GetFilePath() const80 const FileEntry::FilePath &FileEntry::GetFilePath() const
81 {
82 return filePath_;
83 }
84
Exist(const string & path)85 bool FileEntry::Exist(const string &path)
86 {
87 struct stat s;
88 if (stat(path.c_str(), &s) != 0) {
89 return false;
90 }
91 return true;
92 }
93
RemoveAllDir(const string & path)94 bool FileEntry::RemoveAllDir(const string &path)
95 {
96 FileEntry f(path);
97 if (!f.Init()) {
98 return false;
99 }
100
101 if (f.IsFile()) {
102 cerr << "Error: RemoveAllDir '" << path << "' not directory." << endl;
103 return false;
104 }
105 return RemoveAllDirInner(f);
106 }
107
CreateDirs(const string & path)108 bool FileEntry::CreateDirs(const string &path)
109 {
110 return CreateDirsInner(path, 0);
111 }
112
CopyFile(const string & src,const string & dst)113 bool FileEntry::CopyFile(const string &src, const string &dst)
114 {
115 ifstream in(src, ios::binary);
116 ofstream out(dst, ios::binary);
117 if (!in || !out) {
118 cerr << "Error: CopyFile '" << src << "' or '" << dst << "' open fail." << endl;
119 return false;
120 }
121 out << in.rdbuf();
122 return true;
123 }
124
IsDirectory(const string & path)125 bool FileEntry::IsDirectory(const string &path)
126 {
127 struct stat s;
128 stat(path.c_str(), &s);
129 return S_ISDIR(s.st_mode);
130 }
131
FilePath(const string & path)132 FileEntry::FilePath::FilePath(const string &path) : filePath_(path)
133 {
134 Format();
135 Init();
136 }
137
~FilePath()138 FileEntry::FilePath::~FilePath()
139 {
140 }
141
Append(const string & path)142 FileEntry::FilePath FileEntry::FilePath::Append(const string &path)
143 {
144 Format();
145 string filePath = filePath_ + SEPARATE + path;
146 return FilePath(filePath);
147 }
148
ReplaceExtension(const string & extension)149 FileEntry::FilePath FileEntry::FilePath::ReplaceExtension(const string &extension)
150 {
151 string filePath;
152 if (!parent_.empty()) {
153 filePath += parent_ + SEPARATE;
154 }
155
156 filePath += filename_.substr(0, filename_.length() - extension_.length()) + extension;
157 return FilePath(filePath);
158 }
159
GetParent()160 FileEntry::FilePath FileEntry::FilePath::GetParent()
161 {
162 return FilePath(parent_);
163 }
164
GetPath() const165 const string &FileEntry::FilePath::GetPath() const
166 {
167 return filePath_;
168 }
169
GetFilename() const170 const string &FileEntry::FilePath::GetFilename() const
171 {
172 return filename_;
173 }
174
GetExtension() const175 const string &FileEntry::FilePath::GetExtension() const
176 {
177 return extension_;
178 }
179
GetSegments() const180 const vector<string> FileEntry::FilePath::GetSegments() const
181 {
182 vector<string> segments;
183 string::size_type offset = 0;
184 string::size_type pos = filePath_.find_first_of(SEPARATE.front(), offset);
185 while (pos != string::npos) {
186 segments.push_back(filePath_.substr(offset, pos - offset));
187 offset = pos + 1;
188 pos = filePath_.find_first_of(SEPARATE.front(), offset);
189 }
190
191 if (offset < filePath_.length()) {
192 segments.push_back(filePath_.substr(offset));
193 }
194 return segments;
195 }
196
197 // below private
IsIgnore(const string & filename) const198 bool FileEntry::IsIgnore(const string &filename) const
199 {
200 if (filename == "." || filename == "..") {
201 return true;
202 }
203 return false;
204 }
205
RemoveAllDirInner(const FileEntry & entry)206 bool FileEntry::RemoveAllDirInner(const FileEntry &entry)
207 {
208 if (entry.IsFile()) {
209 return remove(entry.GetFilePath().GetPath().c_str()) == 0;
210 }
211
212 for (const auto &iter : entry.GetChilds()) {
213 if (!RemoveAllDirInner(*iter)) {
214 return false;
215 }
216 }
217 return rmdir(entry.GetFilePath().GetPath().c_str()) == 0;
218 }
219
CreateDirsInner(const string & path,string::size_type offset)220 bool FileEntry::CreateDirsInner(const string &path, string::size_type offset)
221 {
222 string::size_type pos = path.find_first_of(SEPARATE.front(), offset);
223 if (pos == string::npos) {
224 #if _WIN32
225 return mkdir(path.c_str()) == 0;
226 #else
227 return mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0;
228 #endif
229 }
230
231 string subPath = path.substr(0, pos + 1);
232 if (!Exist(subPath)) {
233 #if _WIN32
234 if (mkdir(subPath.c_str()) != 0) {
235 #else
236 if (mkdir(subPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
237 #endif
238 return false;
239 }
240 }
241 return CreateDirsInner(path, pos + 1);
242 }
243
244 void FileEntry::FilePath::Format()
245 {
246 if (filePath_.back() != SEPARATE.front()) {
247 return;
248 }
249 filePath_.pop_back();
250 }
251
252 void FileEntry::FilePath::Init()
253 {
254 filename_ = filePath_;
255 string::size_type pos = filePath_.find_last_of(SEPARATE.front());
256 if (pos != string::npos) {
257 parent_ = filePath_.substr(0, pos);
258 if (pos + 1 < filePath_.length()) {
259 filename_ = filePath_.substr(pos + 1);
260 }
261 }
262
263 pos = filename_.find_last_of('.');
264 if (pos != string::npos && pos + 1 < filename_.length()) {
265 extension_ = filename_.substr(pos);
266 }
267 }
268 }
269 }
270 }
271